chore: initial commit (extracted from Launchers monorepo)

Plugin: ns7zip v2.0.0
Architectures: x86-ansi, x86-unicode, amd64-unicode
License: LGPL-2.1-or-later
This commit is contained in:
Simone
2026-04-29 14:07:51 +02:00
commit d074cc7c07
3848 changed files with 1076682 additions and 0 deletions
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.7zFM" type="win32"/>
<description>7-Zip File Manager.</description>
<dependency>
<dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly>
</dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application>
<!-- Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Win 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Win 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Win 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Win 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application></compatibility>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

@@ -0,0 +1,63 @@
// AboutDialog.cpp
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "../../MyVersion.h"
#include "AboutDialog.h"
#include "PropertyNameRes.h"
#include "HelpUtils.h"
#include "LangUtils.h"
static const UInt32 kLangIDs[] =
{
IDT_ABOUT_INFO
};
#define kHomePageURL TEXT("http://www.7-zip.org/")
#define kHelpTopic "start.htm"
#define LLL_(quote) L##quote
#define LLL(quote) LLL_(quote)
bool CAboutDialog::OnInit()
{
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
SetItemText(IDT_ABOUT_VERSION, UString("7-Zip " MY_VERSION_CPU));
SetItemText(IDT_ABOUT_DATE, LLL(MY_DATE));
LangSetWindowText(*this, IDD_ABOUT);
NormalizePosition();
return CModalDialog::OnInit();
}
void CAboutDialog::OnHelp()
{
ShowHelpWindow(kHelpTopic);
}
bool CAboutDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
{
LPCTSTR url;
switch (buttonID)
{
case IDB_ABOUT_HOMEPAGE: url = kHomePageURL; break;
default:
return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
}
#ifdef UNDER_CE
SHELLEXECUTEINFO s;
memset(&s, 0, sizeof(s));
s.cbSize = sizeof(s);
s.lpFile = url;
::ShellExecuteEx(&s);
#else
::ShellExecute(NULL, NULL, url, NULL, NULL, SW_SHOWNORMAL);
#endif
return true;
}
@@ -0,0 +1,19 @@
// AboutDialog.h
#ifndef __ABOUT_DIALOG_H
#define __ABOUT_DIALOG_H
#include "../../../Windows/Control/Dialog.h"
#include "AboutDialogRes.h"
class CAboutDialog: public NWindows::NControl::CModalDialog
{
public:
virtual bool OnInit();
virtual void OnHelp();
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_ABOUT, wndParent); }
};
#endif
@@ -0,0 +1,26 @@
#include "AboutDialogRes.h"
#include "../../GuiCommon.rc"
#include "../../MyVersion.h"
#define xc 144
#define yc 144
#define y 93
IDI_LOGO ICON "../../UI/FileManager/7zipLogo.ico"
#ifndef SS_REALSIZEIMAGE
#define SS_REALSIZEIMAGE 0x800
#endif
IDD_ABOUT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
CAPTION "About 7-Zip"
{
DEFPUSHBUTTON "OK", IDOK, bx1, by, bxs, bys
PUSHBUTTON "www.7-zip.org", IDB_ABOUT_HOMEPAGE, bx2, by, bxs, bys
ICON IDI_LOGO, -1, m, m, 32, 32, SS_REALSIZEIMAGE,
LTEXT "", IDT_ABOUT_VERSION, m, 54, xc, 8
LTEXT "", IDT_ABOUT_DATE, m, 67, xc, 8
LTEXT MY_COPYRIGHT, -1, m, 80, xc, 8
LTEXT "7-Zip is free software", IDT_ABOUT_INFO, m, y, xc, (by - y - 1)
}
@@ -0,0 +1,8 @@
#define IDD_ABOUT 2900
#define IDT_ABOUT_INFO 2901
#define IDI_LOGO 100
#define IDT_ABOUT_VERSION 101
#define IDT_ABOUT_DATE 102
#define IDB_ABOUT_HOMEPAGE 110
Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

@@ -0,0 +1,839 @@
// AltStreamsFolder.cpp
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileIO.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/PropVariant.h"
#include "../Common/ExtractingFilePath.h"
#include "../Agent/IFolderArchive.h"
#include "AltStreamsFolder.h"
#include "FSDrives.h"
#include "FSFolder.h"
#include "SysIconUtils.h"
using namespace NWindows;
using namespace NFile;
using namespace NFind;
using namespace NDir;
using namespace NName;
#ifndef USE_UNICODE_FSTRING
int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2);
#endif
#ifndef UNDER_CE
namespace NFsFolder
{
bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size);
}
#endif
namespace NAltStreamsFolder {
static const Byte kProps[] =
{
kpidName,
kpidSize,
kpidPackSize
};
static unsigned GetFsParentPrefixSize(const FString &path)
{
if (IsNetworkShareRootPath(path))
return 0;
unsigned prefixSize = GetRootPrefixSize(path);
if (prefixSize == 0 || prefixSize >= path.Len())
return 0;
FString parentPath = path;
int pos = parentPath.ReverseFind_PathSepar();
if (pos < 0)
return 0;
if (pos == (int)parentPath.Len() - 1)
{
parentPath.DeleteBack();
pos = parentPath.ReverseFind_PathSepar();
if (pos < 0)
return 0;
}
if ((unsigned)pos + 1 < prefixSize)
return 0;
return pos + 1;
}
HRESULT CAltStreamsFolder::Init(const FString &path /* , IFolderFolder *parentFolder */)
{
// _parentFolder = parentFolder;
if (path.Back() != ':')
return E_FAIL;
_pathPrefix = path;
_pathBaseFile = path;
_pathBaseFile.DeleteBack();
{
CFileInfo fi;
if (!fi.Find(_pathBaseFile))
return GetLastError();
}
unsigned prefixSize = GetFsParentPrefixSize(_pathBaseFile);
if (prefixSize == 0)
return S_OK;
FString parentPath = _pathBaseFile;
parentPath.DeleteFrom(prefixSize);
_findChangeNotification.FindFirst(parentPath, false,
FILE_NOTIFY_CHANGE_FILE_NAME
| FILE_NOTIFY_CHANGE_DIR_NAME
| FILE_NOTIFY_CHANGE_ATTRIBUTES
| FILE_NOTIFY_CHANGE_SIZE
| FILE_NOTIFY_CHANGE_LAST_WRITE
/*
| FILE_NOTIFY_CHANGE_LAST_ACCESS
| FILE_NOTIFY_CHANGE_CREATION
| FILE_NOTIFY_CHANGE_SECURITY
*/
);
/*
if (_findChangeNotification.IsHandleAllocated())
return S_OK;
return GetLastError();
*/
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::LoadItems()
{
Int32 dummy;
WasChanged(&dummy);
Clear();
CStreamEnumerator enumerator(_pathBaseFile);
CStreamInfo si;
for (;;)
{
bool found;
if (!enumerator.Next(si, found))
{
// if (GetLastError() == ERROR_ACCESS_DENIED)
// break;
// return E_FAIL;
break;
}
if (!found)
break;
if (si.IsMainStream())
continue;
CAltStream ss;
ss.Name = si.GetReducedName();
if (!ss.Name.IsEmpty() && ss.Name[0] == ':')
ss.Name.Delete(0);
ss.Size = si.Size;
ss.PackSize_Defined = false;
ss.PackSize = si.Size;
Streams.Add(ss);
}
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::GetNumberOfItems(UInt32 *numItems)
{
*numItems = Streams.Size();
return S_OK;
}
#ifdef USE_UNICODE_FSTRING
STDMETHODIMP CAltStreamsFolder::GetItemPrefix(UInt32 /* index */, const wchar_t **name, unsigned *len)
{
*name = 0;
*len = 0;
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len)
{
*name = 0;
*len = 0;
{
const CAltStream &ss = Streams[index];
*name = ss.Name;
*len = ss.Name.Len();
}
return S_OK;
}
STDMETHODIMP_(UInt64) CAltStreamsFolder::GetItemSize(UInt32 index)
{
return Streams[index].Size;
}
#endif
STDMETHODIMP CAltStreamsFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
{
CAltStream &ss = Streams[index];
switch (propID)
{
case kpidIsDir: prop = false; break;
case kpidIsAltStream: prop = true; break;
case kpidName: prop = ss.Name; break;
case kpidSize: prop = ss.Size; break;
case kpidPackSize:
#ifdef UNDER_CE
prop = ss.Size;
#else
if (!ss.PackSize_Defined)
{
ss.PackSize_Defined = true;
if (!NFsFolder::MyGetCompressedFileSizeW(_pathPrefix + us2fs(ss.Name), ss.PackSize))
ss.PackSize = ss.Size;
}
prop = ss.PackSize;
#endif
break;
}
}
prop.Detach(value);
return S_OK;
}
// returns Position of extension including '.'
static inline const wchar_t *GetExtensionPtr(const UString &name)
{
int dotPos = name.ReverseFind_Dot();
return name.Ptr((dotPos < 0) ? name.Len() : dotPos);
}
STDMETHODIMP_(Int32) CAltStreamsFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 /* propIsRaw */)
{
const CAltStream &ss1 = Streams[index1];
const CAltStream &ss2 = Streams[index2];
switch (propID)
{
case kpidName:
{
return CompareFileNames_ForFolderList(ss1.Name, ss2.Name);
// return MyStringCompareNoCase(ss1.Name, ss2.Name);
}
case kpidSize:
return MyCompare(ss1.Size, ss2.Size);
case kpidPackSize:
{
#ifdef UNDER_CE
return MyCompare(ss1.Size, ss2.Size);
#else
// PackSize can be undefined here
return MyCompare(
ss1.PackSize,
ss2.PackSize);
#endif
}
case kpidExtension:
return CompareFileNames_ForFolderList(
GetExtensionPtr(ss1.Name),
GetExtensionPtr(ss2.Name));
}
return 0;
}
STDMETHODIMP CAltStreamsFolder::BindToFolder(UInt32 /* index */, IFolderFolder **resultFolder)
{
*resultFolder = 0;
return E_INVALIDARG;
}
STDMETHODIMP CAltStreamsFolder::BindToFolder(const wchar_t * /* name */, IFolderFolder **resultFolder)
{
*resultFolder = 0;
return E_INVALIDARG;
}
// static CFSTR const kSuperPrefix = FTEXT("\\\\?\\");
STDMETHODIMP CAltStreamsFolder::BindToParentFolder(IFolderFolder **resultFolder)
{
*resultFolder = 0;
/*
if (_parentFolder)
{
CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
*resultFolder = parentFolder.Detach();
return S_OK;
}
*/
if (IsDriveRootPath_SuperAllowed(_pathBaseFile))
{
CFSDrives *drivesFolderSpec = new CFSDrives;
CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;
drivesFolderSpec->Init();
*resultFolder = drivesFolder.Detach();
return S_OK;
}
/*
parentPath.DeleteFrom(pos + 1);
if (parentPath == kSuperPrefix)
{
#ifdef UNDER_CE
*resultFolder = 0;
#else
CFSDrives *drivesFolderSpec = new CFSDrives;
CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;
drivesFolderSpec->Init(false, true);
*resultFolder = drivesFolder.Detach();
#endif
return S_OK;
}
FString parentPathReduced = parentPath.Left(pos);
#ifndef UNDER_CE
pos = parentPathReduced.ReverseFind_PathSepar();
if (pos == 1)
{
if (!IS_PATH_SEPAR_CHAR(parentPath[0]))
return E_FAIL;
CNetFolder *netFolderSpec = new CNetFolder;
CMyComPtr<IFolderFolder> netFolder = netFolderSpec;
netFolderSpec->Init(fs2us(parentPath));
*resultFolder = netFolder.Detach();
return S_OK;
}
#endif
CFSFolder *parentFolderSpec = new CFSFolder;
CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec;
RINOK(parentFolderSpec->Init(parentPath, 0));
*resultFolder = parentFolder.Detach();
*/
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::GetNumberOfProperties(UInt32 *numProperties)
{
*numProperties = ARRAY_SIZE(kProps);
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)
STDMETHODIMP CAltStreamsFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
switch (propID)
{
case kpidType: prop = "AltStreamsFolder"; break;
case kpidPath: prop = fs2us(_pathPrefix); break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CAltStreamsFolder::WasChanged(Int32 *wasChanged)
{
bool wasChangedMain = false;
for (;;)
{
if (!_findChangeNotification.IsHandleAllocated())
{
*wasChanged = BoolToInt(false);
return S_OK;
}
DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
if (wasChangedLoc)
{
_findChangeNotification.FindNext();
wasChangedMain = true;
}
else
break;
}
*wasChanged = BoolToInt(wasChangedMain);
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::Clone(IFolderFolder **resultFolder)
{
CAltStreamsFolder *folderSpec = new CAltStreamsFolder;
CMyComPtr<IFolderFolder> folderNew = folderSpec;
folderSpec->Init(_pathPrefix);
*resultFolder = folderNew.Detach();
return S_OK;
}
void CAltStreamsFolder::GetAbsPath(const wchar_t *name, FString &absPath)
{
absPath.Empty();
if (!IsAbsolutePath(name))
absPath += _pathPrefix;
absPath += us2fs(name);
}
static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
const wchar_t *message, const FString &fileName)
{
UString s = message;
s += " : ";
s += fs2us(fileName);
return callback->ShowMessage(s);
}
static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback,
const wchar_t *message, const FString &fileName)
{
UString s = message;
s += " : ";
s += fs2us(fileName);
return callback->UpdateErrorMessage(s);
}
static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
const char *message, const FString &fileName)
{
return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
}
/*
static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback,
const char *message, const FString &fileName)
{
return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
}
*/
STDMETHODIMP CAltStreamsFolder::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
STDMETHODIMP CAltStreamsFolder::CreateFile(const wchar_t *name, IProgress * /* progress */)
{
FString absPath;
GetAbsPath(name, absPath);
NIO::COutFile outFile;
if (!outFile.Create(absPath, false))
return ::GetLastError();
return S_OK;
}
static DWORD Return_LastError_or_FAIL()
{
DWORD errorCode = GetLastError();
if (errorCode == 0)
errorCode = (DWORD)E_FAIL;
return errorCode;
}
static UString GetLastErrorMessage()
{
return NError::MyFormatMessage(Return_LastError_or_FAIL());
}
static HRESULT UpdateFile(NFsFolder::CCopyStateIO &state, CFSTR inPath, CFSTR outPath, IFolderArchiveUpdateCallback *callback)
{
if (NFind::DoesFileOrDirExist(outPath))
{
RINOK(SendMessageError(callback, NError::MyFormatMessage(ERROR_ALREADY_EXISTS), FString(outPath)));
CFileInfo fi;
if (fi.Find(inPath))
{
if (state.TotalSize >= fi.Size)
state.TotalSize -= fi.Size;
}
return S_OK;
}
{
if (callback)
RINOK(callback->CompressOperation(fs2us(inPath)));
RINOK(state.MyCopyFile(inPath, outPath));
if (state.ErrorFileIndex >= 0)
{
if (state.ErrorMessage.IsEmpty())
state.ErrorMessage = GetLastErrorMessage();
FString errorName;
if (state.ErrorFileIndex == 0)
errorName = inPath;
else
errorName = outPath;
if (callback)
RINOK(SendMessageError(callback, state.ErrorMessage, errorName));
}
if (callback)
RINOK(callback->OperationResult(0));
}
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress)
{
CMyComPtr<IFolderArchiveUpdateCallback> callback;
if (progress)
{
RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&callback));
}
FString destPath = _pathPrefix + us2fs(newName);
const CAltStream &ss = Streams[index];
if (callback)
{
RINOK(callback->SetNumFiles(1));
RINOK(callback->SetTotal(ss.Size));
}
NFsFolder::CCopyStateIO state;
state.Progress = progress;
state.TotalSize = 0;
state.DeleteSrcFile = true;
return UpdateFile(state, _pathPrefix + us2fs(ss.Name), destPath, callback);
}
STDMETHODIMP CAltStreamsFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress *progress)
{
RINOK(progress->SetTotal(numItems));
for (UInt32 i = 0; i < numItems; i++)
{
const CAltStream &ss = Streams[indices[i]];
const FString fullPath = _pathPrefix + us2fs(ss.Name);
bool result = DeleteFileAlways(fullPath);
if (!result)
return Return_LastError_or_FAIL();
UInt64 completed = i;
RINOK(progress->SetCompleted(&completed));
}
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::SetProperty(UInt32 /* index */, PROPID /* propID */,
const PROPVARIANT * /* value */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
STDMETHODIMP CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
{
const CAltStream &ss = Streams[index];
*iconIndex = 0;
int iconIndexTemp;
if (GetRealIconIndex(_pathPrefix + us2fs(ss.Name),
0 // fi.Attrib
, iconIndexTemp) != 0)
{
*iconIndex = iconIndexTemp;
return S_OK;
}
return Return_LastError_or_FAIL();
}
/*
class CGetProp:
public IGetProp,
public CMyUnknownImp
{
public:
// const CArc *Arc;
// UInt32 IndexInArc;
UString Name; // relative path
UInt64 Size;
MY_UNKNOWN_IMP1(IGetProp)
INTERFACE_IGetProp(;)
};
STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value)
{
if (propID == kpidName)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop = Name;
prop.Detach(value);
return S_OK;
COM_TRY_END
}
if (propID == kpidSize)
{
NCOM::CPropVariant prop = Size;
prop.Detach(value);
return S_OK;
}
NCOM::CPropVariant prop;
prop.Detach(value);
return S_OK;
}
*/
static HRESULT CopyStream(
NFsFolder::CCopyStateIO &state,
const FString &srcPath,
const CFileInfo &srcFileInfo,
const CAltStream &srcAltStream,
const FString &destPathSpec,
IFolderOperationsExtractCallback *callback)
{
FString destPath = destPathSpec;
if (CompareFileNames(destPath, srcPath) == 0)
{
RINOK(SendMessageError(callback, "can not copy file onto itself", destPath));
return E_ABORT;
}
Int32 writeAskResult;
CMyComBSTR destPathResult;
RINOK(callback->AskWrite(
fs2us(srcPath),
BoolToInt(false),
&srcFileInfo.MTime, &srcAltStream.Size,
fs2us(destPath),
&destPathResult,
&writeAskResult));
if (IntToBool(writeAskResult))
{
RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
FString destPathNew (us2fs((LPCOLESTR)destPathResult));
RINOK(state.MyCopyFile(srcPath, destPathNew));
if (state.ErrorFileIndex >= 0)
{
if (state.ErrorMessage.IsEmpty())
state.ErrorMessage = GetLastErrorMessage();
FString errorName;
if (state.ErrorFileIndex == 0)
errorName = srcPath;
else
errorName = destPathNew;
RINOK(SendMessageError(callback, state.ErrorMessage, errorName));
return E_ABORT;
}
state.StartPos += state.CurrentSize;
}
else
{
if (state.TotalSize >= srcAltStream.Size)
{
state.TotalSize -= srcAltStream.Size;
RINOK(state.Progress->SetTotal(state.TotalSize));
}
}
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
const wchar_t *path, IFolderOperationsExtractCallback *callback)
{
if (numItems == 0)
return S_OK;
/*
CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
RINOK(callback->QueryInterface(IID_IFolderExtractToStreamCallback, (void **)&ExtractToStreamCallback));
if (ExtractToStreamCallback)
{
Int32 useStreams = 0;
if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK)
useStreams = 0;
if (useStreams == 0)
ExtractToStreamCallback.Release();
}
*/
UInt64 totalSize = 0;
{
UInt32 i;
for (i = 0; i < numItems; i++)
{
totalSize += Streams[indices[i]].Size;
}
RINOK(callback->SetTotal(totalSize));
RINOK(callback->SetNumFiles(numItems));
}
/*
if (ExtractToStreamCallback)
{
CGetProp *GetProp_Spec = new CGetProp;
CMyComPtr<IGetProp> GetProp= GetProp_Spec;
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 index = indices[i];
const CAltStream &ss = Streams[index];
GetProp_Spec->Name = ss.Name;
GetProp_Spec->Size = ss.Size;
CMyComPtr<ISequentialOutStream> outStream;
RINOK(ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, BoolToInt(false), &outStream,
NArchive::NExtract::NAskMode::kExtract, GetProp)); // isDir
FString srcPath;
GetFullPath(ss, srcPath);
RINOK(ExtractToStreamCallback->PrepareOperation7(NArchive::NExtract::NAskMode::kExtract));
RINOK(ExtractToStreamCallback->SetOperationResult7(NArchive::NExtract::NOperationResult::kOK, BoolToInt(false))); // _encrypted
// RINOK(CopyStream(state, srcPath, fi, ss, destPath2, callback, completedSize));
}
return S_OK;
}
*/
FString destPath (us2fs(path));
if (destPath.IsEmpty() /* && !ExtractToStreamCallback */)
return E_INVALIDARG;
bool isAltDest = NName::IsAltPathPrefix(destPath);;
bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
if (isDirectPath)
{
if (numItems > 1)
return E_INVALIDARG;
}
CFileInfo fi;
if (!fi.Find(_pathBaseFile))
return GetLastError();
NFsFolder::CCopyStateIO state;
state.Progress = callback;
state.DeleteSrcFile = IntToBool(moveMode);
state.TotalSize = totalSize;
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 index = indices[i];
const CAltStream &ss = Streams[index];
FString destPath2 = destPath;
if (!isDirectPath)
destPath2 += us2fs(Get_Correct_FsFile_Name(ss.Name));
FString srcPath;
GetFullPath(ss, srcPath);
RINOK(CopyStream(state, srcPath, fi, ss, destPath2, callback));
}
return S_OK;
}
STDMETHODIMP CAltStreamsFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
{
/*
if (numItems == 0)
return S_OK;
CMyComPtr<IFolderArchiveUpdateCallback> callback;
if (progress)
{
RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&callback));
}
if (CompareFileNames(fromFolderPath, fs2us(_pathPrefix)) == 0)
{
RINOK(SendMessageError(callback, "can not copy file onto itself", _pathPrefix));
return E_ABORT;
}
if (callback)
RINOK(callback->SetNumFiles(numItems));
UInt64 totalSize = 0;
UInt32 i;
FString path;
for (i = 0; i < numItems; i++)
{
path = us2fs(fromFolderPath);
path += us2fs(itemsPaths[i]);
CFileInfo fi;
if (!fi.Find(path))
return ::GetLastError();
if (fi.IsDir())
return E_NOTIMPL;
totalSize += fi.Size;
}
RINOK(progress->SetTotal(totalSize));
// UInt64 completedSize = 0;
NFsFolder::CCopyStateIO state;
state.Progress = progress;
state.DeleteSrcFile = IntToBool(moveMode);
state.TotalSize = totalSize;
// we need to clear READ-ONLY of parent before creating alt stream
{
DWORD attrib = GetFileAttrib(_pathBaseFile);
if (attrib != INVALID_FILE_ATTRIBUTES
&& (attrib & FILE_ATTRIBUTE_READONLY) != 0)
{
if (!SetFileAttrib(_pathBaseFile, attrib & ~FILE_ATTRIBUTE_READONLY))
{
if (callback)
{
RINOK(SendMessageError(callback, GetLastErrorMessage(), _pathBaseFile));
return S_OK;
}
return Return_LastError_or_FAIL();
}
}
}
for (i = 0; i < numItems; i++)
{
path = us2fs(fromFolderPath);
path += us2fs(itemsPaths[i]);
FString destPath = _pathPrefix + us2fs(itemsPaths[i]);
RINOK(UpdateFile(state, path, destPath, callback));
}
return S_OK;
*/
return E_NOTIMPL;
}
STDMETHODIMP CAltStreamsFolder::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
}
@@ -0,0 +1,100 @@
// AltStreamsFolder.h
#ifndef __ALT_STREAMS_FOLDER_H
#define __ALT_STREAMS_FOLDER_H
#include "../../../Common/MyCom.h"
#include "../../../Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "IFolder.h"
namespace NAltStreamsFolder {
class CAltStreamsFolder;
struct CAltStream
{
UInt64 Size;
UInt64 PackSize;
bool PackSize_Defined;
UString Name;
};
class CAltStreamsFolder:
public IFolderFolder,
public IFolderCompare,
#ifdef USE_UNICODE_FSTRING
public IFolderGetItemName,
#endif
public IFolderWasChanged,
public IFolderOperations,
// public IFolderOperationsDeleteToRecycleBin,
public IFolderClone,
public IFolderGetSystemIconIndex,
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
MY_QUERYINTERFACE_ENTRY(IFolderCompare)
#ifdef USE_UNICODE_FSTRING
MY_QUERYINTERFACE_ENTRY(IFolderGetItemName)
#endif
MY_QUERYINTERFACE_ENTRY(IFolderWasChanged)
// MY_QUERYINTERFACE_ENTRY(IFolderOperationsDeleteToRecycleBin)
MY_QUERYINTERFACE_ENTRY(IFolderOperations)
MY_QUERYINTERFACE_ENTRY(IFolderClone)
MY_QUERYINTERFACE_ENTRY(IFolderGetSystemIconIndex)
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_FolderFolder(;)
INTERFACE_FolderOperations(;)
STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
#ifdef USE_UNICODE_FSTRING
INTERFACE_IFolderGetItemName(;)
#endif
STDMETHOD(WasChanged)(Int32 *wasChanged);
STDMETHOD(Clone)(IFolderFolder **resultFolder);
STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
private:
FString _pathBaseFile; // folder
FString _pathPrefix; // folder:
CObjectVector<CAltStream> Streams;
// CMyComPtr<IFolderFolder> _parentFolder;
NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;
HRESULT GetItemFullSize(unsigned index, UInt64 &size, IProgress *progress);
void GetAbsPath(const wchar_t *name, FString &absPath);
public:
// path must be with ':' at tail
HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */);
CAltStreamsFolder() {}
void GetFullPath(const CAltStream &item, FString &path) const
{
path = _pathPrefix;
path += us2fs(item.Name);
}
void Clear()
{
Streams.Clear();
}
};
}
#endif
@@ -0,0 +1,997 @@
// App.cpp
#include "StdAfx.h"
#include "resource.h"
#include "OverwriteDialogRes.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/PropVariantConv.h"
/*
#include "Windows/COM.h"
#include "Windows/Error.h"
#include "Windows/FileDir.h"
#include "Windows/PropVariant.h"
#include "Windows/Thread.h"
*/
#include "App.h"
#include "CopyDialog.h"
#include "ExtractCallback.h"
#include "FormatUtils.h"
#include "IFolder.h"
#include "LangUtils.h"
#include "MyLoadMenu.h"
#include "RegistryUtils.h"
#include "ViewSettings.h"
#include "PropertyNameRes.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
using namespace NFind;
using namespace NName;
extern DWORD g_ComCtl32Version;
extern HINSTANCE g_hInstance;
#define kTempDirPrefix FTEXT("7zE")
void CPanelCallbackImp::OnTab()
{
if (g_App.NumPanels != 1)
_app->Panels[1 - _index].SetFocusToList();
_app->RefreshTitle();
}
void CPanelCallbackImp::SetFocusToPath(unsigned index)
{
int newPanelIndex = index;
if (g_App.NumPanels == 1)
newPanelIndex = g_App.LastFocusedPanel;
_app->RefreshTitle();
_app->Panels[newPanelIndex]._headerComboBox.SetFocus();
_app->Panels[newPanelIndex]._headerComboBox.ShowDropDown();
}
void CPanelCallbackImp::OnCopy(bool move, bool copyToSame) { _app->OnCopy(move, copyToSame, _index); }
void CPanelCallbackImp::OnSetSameFolder() { _app->OnSetSameFolder(_index); }
void CPanelCallbackImp::OnSetSubFolder() { _app->OnSetSubFolder(_index); }
void CPanelCallbackImp::PanelWasFocused() { _app->SetFocusedPanel(_index); _app->RefreshTitlePanel(_index); }
void CPanelCallbackImp::DragBegin() { _app->DragBegin(_index); }
void CPanelCallbackImp::DragEnd() { _app->DragEnd(); }
void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitlePanel(_index, always); }
void CApp::ReloadLang()
{
LangString(IDS_N_SELECTED_ITEMS, LangString_N_SELECTED_ITEMS);
}
void CApp::SetListSettings()
{
CFmSettings st;
st.Load();
ShowSystemMenu = st.ShowSystemMenu;
DWORD extendedStyle = LVS_EX_HEADERDRAGDROP;
if (st.FullRow)
extendedStyle |= LVS_EX_FULLROWSELECT;
if (st.ShowGrid)
extendedStyle |= LVS_EX_GRIDLINES;
if (st.SingleClick)
{
extendedStyle |= LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT;
/*
if (ReadUnderline())
extendedStyle |= LVS_EX_UNDERLINEHOT;
*/
}
for (unsigned i = 0; i < kNumPanelsMax; i++)
{
CPanel &panel = Panels[i];
panel._mySelectMode = st.AlternativeSelection;
panel._showDots = st.ShowDots;
panel._showRealFileIcons = st.ShowRealFileIcons;
panel._exStyle = extendedStyle;
DWORD style = (DWORD)panel._listView.GetStyle();
if (st.AlternativeSelection)
style |= LVS_SINGLESEL;
else
style &= ~LVS_SINGLESEL;
panel._listView.SetStyle(style);
panel.SetExtendedStyle();
}
}
#ifndef ILC_COLOR32
#define ILC_COLOR32 0x0020
#endif
HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat,
bool needOpenArc,
bool &archiveIsOpened, bool &encrypted)
{
if (Panels[panelIndex].PanelCreated)
return S_OK;
m_PanelCallbackImp[panelIndex].Init(this, panelIndex);
UString path;
if (mainPath.IsEmpty())
{
if (!::ReadPanelPath(panelIndex, path))
path.Empty();
}
else
path = mainPath;
int id = 1000 + 100 * panelIndex;
return Panels[panelIndex].Create(_window, _window,
id, path, arcFormat, &m_PanelCallbackImp[panelIndex], &AppState,
needOpenArc,
archiveIsOpened, encrypted);
}
static void CreateToolbar(HWND parent,
NControl::CImageList &imageList,
NControl::CToolBar &toolBar,
bool largeButtons)
{
toolBar.Attach(::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, 0
| WS_CHILD
| WS_VISIBLE
| TBSTYLE_FLAT
| TBSTYLE_TOOLTIPS
| TBSTYLE_WRAPABLE
// | TBSTYLE_AUTOSIZE
// | CCS_NORESIZE
#ifdef UNDER_CE
| CCS_NODIVIDER
| CCS_NOPARENTALIGN
#endif
,0,0,0,0, parent, NULL, g_hInstance, NULL));
// TB_BUTTONSTRUCTSIZE message, which is required for
// backward compatibility.
toolBar.ButtonStructSize();
imageList.Create(
largeButtons ? 48: 24,
largeButtons ? 36: 24,
ILC_MASK | ILC_COLOR32, 0, 0);
toolBar.SetImageList(0, imageList);
}
struct CButtonInfo
{
int CommandID;
UINT BitmapResID;
UINT Bitmap2ResID;
UINT StringResID;
UString GetText() const { return LangString(StringResID); }
};
static const CButtonInfo g_StandardButtons[] =
{
{ IDM_COPY_TO, IDB_COPY, IDB_COPY2, IDS_BUTTON_COPY },
{ IDM_MOVE_TO, IDB_MOVE, IDB_MOVE2, IDS_BUTTON_MOVE },
{ IDM_DELETE, IDB_DELETE, IDB_DELETE2, IDS_BUTTON_DELETE } ,
{ IDM_PROPERTIES, IDB_INFO, IDB_INFO2, IDS_BUTTON_INFO }
};
static const CButtonInfo g_ArchiveButtons[] =
{
{ kMenuCmdID_Toolbar_Add, IDB_ADD, IDB_ADD2, IDS_ADD },
{ kMenuCmdID_Toolbar_Extract, IDB_EXTRACT, IDB_EXTRACT2, IDS_EXTRACT },
{ kMenuCmdID_Toolbar_Test, IDB_TEST, IDB_TEST2, IDS_TEST }
};
static bool SetButtonText(int commandID, const CButtonInfo *buttons, unsigned numButtons, UString &s)
{
for (unsigned i = 0; i < numButtons; i++)
{
const CButtonInfo &b = buttons[i];
if (b.CommandID == commandID)
{
s = b.GetText();
return true;
}
}
return false;
}
static void SetButtonText(int commandID, UString &s)
{
if (SetButtonText(commandID, g_StandardButtons, ARRAY_SIZE(g_StandardButtons), s))
return;
SetButtonText(commandID, g_ArchiveButtons, ARRAY_SIZE(g_ArchiveButtons), s);
}
static void AddButton(
NControl::CImageList &imageList,
NControl::CToolBar &toolBar,
const CButtonInfo &butInfo, bool showText, bool large)
{
TBBUTTON but;
but.iBitmap = 0;
but.idCommand = butInfo.CommandID;
but.fsState = TBSTATE_ENABLED;
but.fsStyle = TBSTYLE_BUTTON;
but.dwData = 0;
UString s = butInfo.GetText();
but.iString = 0;
if (showText)
but.iString = (INT_PTR)(LPCWSTR)s;
but.iBitmap = imageList.GetImageCount();
HBITMAP b = ::LoadBitmap(g_hInstance,
large ?
MAKEINTRESOURCE(butInfo.BitmapResID):
MAKEINTRESOURCE(butInfo.Bitmap2ResID));
if (b != 0)
{
imageList.AddMasked(b, RGB(255, 0, 255));
::DeleteObject(b);
}
#ifdef _UNICODE
toolBar.AddButton(1, &but);
#else
toolBar.AddButtonW(1, &but);
#endif
}
void CApp::ReloadToolbars()
{
_buttonsImageList.Destroy();
_toolBar.Destroy();
if (ShowArchiveToolbar || ShowStandardToolbar)
{
CreateToolbar(_window, _buttonsImageList, _toolBar, LargeButtons);
unsigned i;
if (ShowArchiveToolbar)
for (i = 0; i < ARRAY_SIZE(g_ArchiveButtons); i++)
AddButton(_buttonsImageList, _toolBar, g_ArchiveButtons[i], ShowButtonsLables, LargeButtons);
if (ShowStandardToolbar)
for (i = 0; i < ARRAY_SIZE(g_StandardButtons); i++)
AddButton(_buttonsImageList, _toolBar, g_StandardButtons[i], ShowButtonsLables, LargeButtons);
_toolBar.AutoSize();
}
}
void CApp::SaveToolbarChanges()
{
SaveToolbar();
ReloadToolbars();
MoveSubWindows();
}
HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, bool &archiveIsOpened, bool &encrypted)
{
_window.Attach(hwnd);
#ifdef UNDER_CE
_commandBar.Create(g_hInstance, hwnd, 1);
#endif
MyLoadMenu();
#ifdef UNDER_CE
_commandBar.AutoSize();
#endif
ReadToolbar();
ReloadToolbars();
unsigned i;
for (i = 0; i < kNumPanelsMax; i++)
Panels[i].PanelCreated = false;
AppState.Read();
SetListSettings();
if (LastFocusedPanel >= kNumPanelsMax)
LastFocusedPanel = 0;
// ShowDeletedFiles = Read_ShowDeleted();
CListMode listMode;
listMode.Read();
for (i = 0; i < kNumPanelsMax; i++)
{
CPanel &panel = Panels[i];
panel._ListViewMode = listMode.Panels[i];
panel._xSize = xSizes[i];
panel._flatModeForArc = ReadFlatView(i);
}
for (i = 0; i < kNumPanelsMax; i++)
{
unsigned panelIndex = i;
if (needOpenArc && LastFocusedPanel == 1)
panelIndex = 1 - i;
bool isMainPanel = (panelIndex == LastFocusedPanel);
if (NumPanels > 1 || isMainPanel)
{
if (NumPanels == 1)
Panels[panelIndex]._xSize = xSizes[0] + xSizes[1];
bool archiveIsOpened2 = false;
bool encrypted2 = false;
UString path;
if (isMainPanel)
path = mainPath;
RINOK(CreateOnePanel(panelIndex, path, arcFormat,
isMainPanel && needOpenArc,
archiveIsOpened2, encrypted2));
if (isMainPanel)
{
archiveIsOpened = archiveIsOpened2;
encrypted = encrypted2;
if (needOpenArc && !archiveIsOpened2)
return S_OK;
}
}
}
SetFocusedPanel(LastFocusedPanel);
Panels[LastFocusedPanel].SetFocusToList();
return S_OK;
}
HRESULT CApp::SwitchOnOffOnePanel()
{
if (NumPanels == 1)
{
NumPanels++;
bool archiveIsOpened, encrypted;
RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), UString(),
false, // needOpenArc
archiveIsOpened, encrypted));
Panels[1 - LastFocusedPanel].Enable(true);
Panels[1 - LastFocusedPanel].Show(SW_SHOWNORMAL);
}
else
{
NumPanels--;
Panels[1 - LastFocusedPanel].Enable(false);
Panels[1 - LastFocusedPanel].Show(SW_HIDE);
}
MoveSubWindows();
return S_OK;
}
void CApp::Save()
{
AppState.Save();
CListMode listMode;
for (unsigned i = 0; i < kNumPanelsMax; i++)
{
const CPanel &panel = Panels[i];
UString path;
if (panel._parentFolders.IsEmpty())
path = panel._currentFolderPrefix;
else
path = panel._parentFolders[0].ParentFolderPath;
// GetFolderPath(panel._parentFolders[0].ParentFolder);
SavePanelPath(i, path);
listMode.Panels[i] = panel.GetListViewMode();
SaveFlatView(i, panel._flatModeForArc);
}
listMode.Save();
// Save_ShowDeleted(ShowDeletedFiles);
}
void CApp::Release()
{
// It's for unloading COM dll's: don't change it.
for (unsigned i = 0; i < kNumPanelsMax; i++)
Panels[i].Release();
}
// reduces path to part that exists on disk (or root prefix of path)
// output path is normalized (with WCHAR_PATH_SEPARATOR)
static void ReducePathToRealFileSystemPath(UString &path)
{
unsigned prefixSize = GetRootPrefixSize(path);
while (!path.IsEmpty())
{
if (NFind::DoesDirExist(us2fs(path)))
{
NName::NormalizeDirPathPrefix(path);
break;
}
int pos = path.ReverseFind_PathSepar();
if (pos < 0)
{
path.Empty();
break;
}
path.DeleteFrom(pos + 1);
if ((unsigned)pos + 1 == prefixSize)
break;
path.DeleteFrom(pos);
}
}
// returns: true, if such dir exists or is root
/*
static bool CheckFolderPath(const UString &path)
{
UString pathReduced = path;
ReducePathToRealFileSystemPath(pathReduced);
return (pathReduced == path);
}
*/
extern UString ConvertSizeToString(UInt64 value);
static void AddSizeValue(UString &s, UInt64 size)
{
s += MyFormatNew(IDS_FILE_SIZE, ConvertSizeToString(size));
}
static void AddValuePair1(UString &s, UINT resourceID, UInt64 size)
{
AddLangString(s, resourceID);
s += ": ";
AddSizeValue(s, size);
s.Add_LF();
}
void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size)
{
if (num == 0)
return;
AddLangString(s, resourceID);
s += ": ";
s += ConvertSizeToString(num);
if (size != (UInt64)(Int64)-1)
{
s += " ( ";
AddSizeValue(s, size);
s += " )";
}
s.Add_LF();
}
static void AddPropValueToSum(IFolderFolder *folder, int index, PROPID propID, UInt64 &sum)
{
if (sum == (UInt64)(Int64)-1)
return;
NCOM::CPropVariant prop;
folder->GetProperty(index, propID, &prop);
UInt64 val = 0;
if (ConvertPropVariantToUInt64(prop, val))
sum += val;
else
sum = (UInt64)(Int64)-1;
}
UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices)
{
UString info;
UInt64 numDirs, numFiles, filesSize, foldersSize;
numDirs = numFiles = filesSize = foldersSize = 0;
unsigned i;
for (i = 0; i < indices.Size(); i++)
{
int index = indices[i];
if (IsItem_Folder(index))
{
AddPropValueToSum(_folder, index, kpidSize, foldersSize);
numDirs++;
}
else
{
AddPropValueToSum(_folder, index, kpidSize, filesSize);
numFiles++;
}
}
AddValuePair2(info, IDS_PROP_FOLDERS, numDirs, foldersSize);
AddValuePair2(info, IDS_PROP_FILES, numFiles, filesSize);
int numDefined = ((foldersSize != (UInt64)(Int64)-1) && foldersSize != 0) ? 1: 0;
numDefined += ((filesSize != (UInt64)(Int64)-1) && filesSize != 0) ? 1: 0;
if (numDefined == 2)
AddValuePair1(info, IDS_PROP_SIZE, filesSize + foldersSize);
info.Add_LF();
info += _currentFolderPrefix;
for (i = 0; i < indices.Size() && (int)i < (int)kCopyDialog_NumInfoLines - 6; i++)
{
info.Add_LF();
info += " ";
int index = indices[i];
info += GetItemRelPath(index);
if (IsItem_Folder(index))
info.Add_PathSepar();
}
if (i != indices.Size())
{
info.Add_LF();
info += " ...";
}
return info;
}
bool IsCorrectFsName(const UString &name);
/* Returns true, if path is path that can be used as path for File System functions
*/
/*
static bool IsFsPath(const FString &path)
{
if (!IsAbsolutePath(path))
return false;
unsigned prefixSize = GetRootPrefixSize(path);
}
*/
void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
{
unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &srcPanel = Panels[srcPanelIndex];
CPanel &destPanel = Panels[destPanelIndex];
CPanel::CDisableTimerProcessing disableTimerProcessing1(destPanel);
CPanel::CDisableTimerProcessing disableTimerProcessing2(srcPanel);
if (move)
{
if (!srcPanel.CheckBeforeUpdate(IDS_MOVE))
return;
}
else if (!srcPanel.DoesItSupportOperations())
{
srcPanel.MessageBox_Error_UnsupportOperation();
return;
}
CRecordVector<UInt32> indices;
UString destPath;
bool useDestPanel = false;
{
if (copyToSame)
{
int focusedItem = srcPanel._listView.GetFocusedItem();
if (focusedItem < 0)
return;
int realIndex = srcPanel.GetRealItemIndex(focusedItem);
if (realIndex == kParentIndex)
return;
indices.Add(realIndex);
destPath = srcPanel.GetItemName(realIndex);
}
else
{
srcPanel.GetOperatedIndicesSmart(indices);
if (indices.Size() == 0)
return;
destPath = destPanel.GetFsPath();
if (NumPanels == 1)
ReducePathToRealFileSystemPath(destPath);
}
}
UStringVector copyFolders;
ReadCopyHistory(copyFolders);
bool useFullItemPaths = srcPanel.Is_IO_FS_Folder(); // maybe we need flat also here ??
{
CCopyDialog copyDialog;
copyDialog.Strings = copyFolders;
copyDialog.Value = destPath;
LangString(move ? IDS_MOVE : IDS_COPY, copyDialog.Title);
LangString(move ? IDS_MOVE_TO : IDS_COPY_TO, copyDialog.Static);
copyDialog.Info = srcPanel.GetItemsInfoString(indices);
if (copyDialog.Create(srcPanel.GetParent()) != IDOK)
return;
destPath = copyDialog.Value;
}
{
if (destPath.IsEmpty())
{
srcPanel.MessageBox_Error_UnsupportOperation();
return;
}
UString correctName;
if (!srcPanel.CorrectFsPath(destPath, correctName))
{
srcPanel.MessageBox_Error_HRESULT(E_INVALIDARG);
return;
}
if (IsAbsolutePath(destPath))
destPath.Empty();
else
destPath = srcPanel.GetFsPath();
destPath += correctName;
#if defined(_WIN32) && !defined(UNDER_CE)
if (destPath.Len() > 0 && destPath[0] == '\\')
if (destPath.Len() == 1 || destPath[1] != '\\')
{
srcPanel.MessageBox_Error_UnsupportOperation();
return;
}
#endif
bool possibleToUseDestPanel = false;
if (CompareFileNames(destPath, destPanel.GetFsPath()) == 0)
{
if (NumPanels == 1 || CompareFileNames(destPath, srcPanel.GetFsPath()) == 0)
{
srcPanel.MessageBox_Error(L"Can not copy files onto itself");
return;
}
if (destPanel.DoesItSupportOperations())
possibleToUseDestPanel = true;
}
bool destIsFsPath = false;
if (possibleToUseDestPanel)
{
if (destPanel.IsFSFolder() || destPanel.IsAltStreamsFolder())
destIsFsPath = true;
else if (destPanel.IsFSDrivesFolder() || destPanel.IsRootFolder())
{
srcPanel.MessageBox_Error_UnsupportOperation();
return;
}
}
else
{
if (IsAltPathPrefix(us2fs(destPath)))
{
// we allow alt streams dest only to alt stream folder in second panel
srcPanel.MessageBox_Error_UnsupportOperation();
return;
/*
FString basePath = us2fs(destPath);
basePath.DeleteBack();
if (!DoesFileOrDirExist(basePath))
{
srcPanel.MessageBoxError2Lines(basePath, ERROR_FILE_NOT_FOUND); // GetLastError()
return;
}
destIsFsPath = true;
*/
}
else
{
if (indices.Size() == 1 &&
!destPath.IsEmpty() && !IS_PATH_SEPAR(destPath.Back()))
{
int pos = destPath.ReverseFind_PathSepar();
if (pos < 0)
{
srcPanel.MessageBox_Error_UnsupportOperation();
return;
}
{
/*
#ifdef _WIN32
UString name = destPath.Ptr(pos + 1);
if (name.Find(L':') >= 0)
{
srcPanel.MessageBox_Error_UnsupportOperation();
return;
}
#endif
*/
UString prefix = destPath.Left(pos + 1);
if (!CreateComplexDir(us2fs(prefix)))
{
DWORD lastError = ::GetLastError();
srcPanel.MessageBox_Error_2Lines_Message_HRESULT(prefix, lastError);
return;
}
}
// bool isFolder = srcPanael.IsItem_Folder(indices[0]);
}
else
{
NName::NormalizeDirPathPrefix(destPath);
if (!CreateComplexDir(us2fs(destPath)))
{
DWORD lastError = ::GetLastError();
srcPanel.MessageBox_Error_2Lines_Message_HRESULT(destPath, lastError);
return;
}
}
destIsFsPath = true;
}
}
if (!destIsFsPath)
useDestPanel = true;
AddUniqueStringToHeadOfList(copyFolders, destPath);
while (copyFolders.Size() > 20)
copyFolders.DeleteBack();
SaveCopyHistory(copyFolders);
}
bool useSrcPanel = !useDestPanel || !srcPanel.Is_IO_FS_Folder();
bool useTemp = useSrcPanel && useDestPanel;
if (useTemp && NumPanels == 1)
{
srcPanel.MessageBox_Error_UnsupportOperation();
return;
}
CTempDir tempDirectory;
FString tempDirPrefix;
if (useTemp)
{
tempDirectory.Create(kTempDirPrefix);
tempDirPrefix = tempDirectory.GetPath();
NFile::NName::NormalizeDirPathPrefix(tempDirPrefix);
}
CSelectedState srcSelState;
CSelectedState destSelState;
srcPanel.SaveSelectedState(srcSelState);
destPanel.SaveSelectedState(destSelState);
CPanel::CDisableNotify disableNotify1(destPanel);
CPanel::CDisableNotify disableNotify2(srcPanel);
HRESULT result = S_OK;
if (useSrcPanel)
{
CCopyToOptions options;
options.folder = useTemp ? fs2us(tempDirPrefix) : destPath;
options.moveMode = move;
options.includeAltStreams = true;
options.replaceAltStreamChars = false;
options.showErrorMessages = true;
result = srcPanel.CopyTo(options, indices, NULL);
}
if (result == S_OK && useDestPanel)
{
UStringVector filePaths;
UString folderPrefix;
if (useTemp)
folderPrefix = fs2us(tempDirPrefix);
else
folderPrefix = srcPanel.GetFsPath();
filePaths.ClearAndReserve(indices.Size());
FOR_VECTOR (i, indices)
{
UInt32 index = indices[i];
UString s;
if (useFullItemPaths)
s = srcPanel.GetItemRelPath2(index);
else
s = srcPanel.GetItemName_for_Copy(index);
filePaths.AddInReserved(s);
}
result = destPanel.CopyFrom(move, folderPrefix, filePaths, true, 0);
}
if (result != S_OK)
{
// disableNotify1.Restore();
// disableNotify2.Restore();
// For Password:
// srcPanel.SetFocusToList();
// srcPanel.InvalidateList(NULL, true);
if (result != E_ABORT)
srcPanel.MessageBox_Error_HRESULT(result);
// return;
}
RefreshTitleAlways();
if (copyToSame || move)
{
srcPanel.RefreshListCtrl(srcSelState);
}
if (!copyToSame)
{
destPanel.RefreshListCtrl(destSelState);
srcPanel.KillSelection();
}
disableNotify1.Restore();
disableNotify2.Restore();
srcPanel.SetFocusToList();
}
void CApp::OnSetSameFolder(int srcPanelIndex)
{
if (NumPanels <= 1)
return;
const CPanel &srcPanel = Panels[srcPanelIndex];
CPanel &destPanel = Panels[1 - srcPanelIndex];
destPanel.BindToPathAndRefresh(srcPanel._currentFolderPrefix);
}
void CApp::OnSetSubFolder(int srcPanelIndex)
{
if (NumPanels <= 1)
return;
const CPanel &srcPanel = Panels[srcPanelIndex];
CPanel &destPanel = Panels[1 - srcPanelIndex];
int focusedItem = srcPanel._listView.GetFocusedItem();
if (focusedItem < 0)
return;
int realIndex = srcPanel.GetRealItemIndex(focusedItem);
if (!srcPanel.IsItem_Folder(realIndex))
return;
// destPanel.BindToFolder(srcPanel._currentFolderPrefix + srcPanel.GetItemName(realIndex) + WCHAR_PATH_SEPARATOR);
CMyComPtr<IFolderFolder> newFolder;
if (realIndex == kParentIndex)
{
if (srcPanel._folder->BindToParentFolder(&newFolder) != S_OK)
return;
if (!newFolder)
{
const UString parentPrefix = srcPanel.GetParentDirPrefix();
bool archiveIsOpened, encrypted;
destPanel.BindToPath(parentPrefix, UString(), archiveIsOpened, encrypted);
destPanel.RefreshListCtrl();
return;
}
}
else
{
if (srcPanel._folder->BindToFolder(realIndex, &newFolder) != S_OK)
return;
}
if (!newFolder)
return;
destPanel.CloseOpenFolders();
destPanel.SetNewFolder(newFolder);
destPanel.RefreshListCtrl();
}
/*
int CApp::GetFocusedPanelIndex() const
{
return LastFocusedPanel;
HWND hwnd = ::GetFocus();
for (;;)
{
if (hwnd == 0)
return 0;
for (unsigned i = 0; i < kNumPanelsMax; i++)
{
if (PanelsCreated[i] &&
((HWND)Panels[i] == hwnd || Panels[i]._listView == hwnd))
return i;
}
hwnd = GetParent(hwnd);
}
}
*/
static UString g_ToolTipBuffer;
static CSysString g_ToolTipBufferSys;
void CApp::OnNotify(int /* ctrlID */, LPNMHDR pnmh)
{
{
if (pnmh->code == TTN_GETDISPINFO)
{
LPNMTTDISPINFO info = (LPNMTTDISPINFO)pnmh;
info->hinst = 0;
g_ToolTipBuffer.Empty();
SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer);
g_ToolTipBufferSys = GetSystemString(g_ToolTipBuffer);
info->lpszText = (LPTSTR)(LPCTSTR)g_ToolTipBufferSys;
return;
}
#ifndef _UNICODE
if (pnmh->code == TTN_GETDISPINFOW)
{
LPNMTTDISPINFOW info = (LPNMTTDISPINFOW)pnmh;
info->hinst = 0;
g_ToolTipBuffer.Empty();
SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer);
info->lpszText = (LPWSTR)(LPCWSTR)g_ToolTipBuffer;
return;
}
#endif
}
}
void CApp::RefreshTitle(bool always)
{
UString path = GetFocusedPanel()._currentFolderPrefix;
if (path.IsEmpty())
path = "7-Zip"; // LangString(IDS_APP_TITLE);
if (!always && path == PrevTitle)
return;
PrevTitle = path;
NWindows::MySetWindowText(_window, path);
}
void CApp::RefreshTitlePanel(unsigned panelIndex, bool always)
{
if (panelIndex != GetFocusedPanelIndex())
return;
RefreshTitle(always);
}
void AddUniqueStringToHead(UStringVector &list, const UString &s)
{
for (unsigned i = 0; i < list.Size();)
if (s.IsEqualTo_NoCase(list[i]))
list.Delete(i);
else
i++;
list.Insert(0, s);
}
void CFolderHistory::Normalize()
{
const unsigned kMaxSize = 100;
if (Strings.Size() > kMaxSize)
Strings.DeleteFrom(kMaxSize);
}
void CFolderHistory::AddString(const UString &s)
{
NSynchronization::CCriticalSectionLock lock(_criticalSection);
AddUniqueStringToHead(Strings, s);
Normalize();
}
@@ -0,0 +1,370 @@
// App.h
#ifndef __APP_H
#define __APP_H
#include "../../../Windows/Control/CommandBar.h"
#include "../../../Windows/Control/ImageList.h"
#include "AppState.h"
#include "Panel.h"
class CApp;
extern CApp g_App;
extern HWND g_HWND;
const unsigned kNumPanelsMax = 2;
extern bool g_IsSmallScreen;
const int kMenuCmdID_Plugin_Start = 1000; // must be large them context menu IDs
const int kMenuCmdID_Toolbar_Start = 1500;
enum
{
kMenuCmdID_Toolbar_Add = kMenuCmdID_Toolbar_Start,
kMenuCmdID_Toolbar_Extract,
kMenuCmdID_Toolbar_Test,
kMenuCmdID_Toolbar_End
};
class CPanelCallbackImp: public CPanelCallback
{
CApp *_app;
unsigned _index;
public:
void Init(CApp *app, unsigned index)
{
_app = app;
_index = index;
}
virtual void OnTab();
virtual void SetFocusToPath(unsigned index);
virtual void OnCopy(bool move, bool copyToSame);
virtual void OnSetSameFolder();
virtual void OnSetSubFolder();
virtual void PanelWasFocused();
virtual void DragBegin();
virtual void DragEnd();
virtual void RefreshTitle(bool always);
};
class CApp;
class CDropTarget:
public IDropTarget,
public CMyUnknownImp
{
CMyComPtr<IDataObject> m_DataObject;
UStringVector m_SourcePaths;
int m_SelectionIndex;
bool m_DropIsAllowed; // = true, if data contain fillist
bool m_PanelDropIsAllowed; // = false, if current target_panel is source_panel.
// check it only if m_DropIsAllowed == true
int m_SubFolderIndex;
UString m_SubFolderName;
CPanel *m_Panel;
bool m_IsAppTarget; // true, if we want to drop to app window (not to panel).
bool m_SetPathIsOK;
bool IsItSameDrive() const;
void QueryGetData(IDataObject *dataObject);
bool IsFsFolderPath() const;
DWORD GetEffect(DWORD keyState, POINTL pt, DWORD allowedEffect);
void RemoveSelection();
void PositionCursor(POINTL ptl);
UString GetTargetPath() const;
bool SetPath(bool enablePath) const;
bool SetPath();
public:
MY_UNKNOWN_IMP1_MT(IDropTarget)
STDMETHOD(DragEnter)(IDataObject * dataObject, DWORD keyState, POINTL pt, DWORD *effect);
STDMETHOD(DragOver)(DWORD keyState, POINTL pt, DWORD * effect);
STDMETHOD(DragLeave)();
STDMETHOD(Drop)(IDataObject * dataObject, DWORD keyState, POINTL pt, DWORD *effect);
CDropTarget():
TargetPanelIndex(-1),
SrcPanelIndex(-1),
m_IsAppTarget(false),
m_Panel(0),
App(0),
m_PanelDropIsAllowed(false),
m_DropIsAllowed(false),
m_SelectionIndex(-1),
m_SubFolderIndex(-1),
m_SetPathIsOK(false) {}
CApp *App;
int SrcPanelIndex; // index of D&D source_panel
int TargetPanelIndex; // what panel to use as target_panel of Application
};
class CApp
{
public:
NWindows::CWindow _window;
bool ShowSystemMenu;
// bool ShowDeletedFiles;
unsigned NumPanels;
unsigned LastFocusedPanel;
bool ShowStandardToolbar;
bool ShowArchiveToolbar;
bool ShowButtonsLables;
bool LargeButtons;
CAppState AppState;
CPanelCallbackImp m_PanelCallbackImp[kNumPanelsMax];
CPanel Panels[kNumPanelsMax];
NWindows::NControl::CImageList _buttonsImageList;
#ifdef UNDER_CE
NWindows::NControl::CCommandBar _commandBar;
#endif
NWindows::NControl::CToolBar _toolBar;
CDropTarget *_dropTargetSpec;
CMyComPtr<IDropTarget> _dropTarget;
UString LangString_N_SELECTED_ITEMS;
void ReloadLang();
CApp(): _window(0), NumPanels(2), LastFocusedPanel(0),
AutoRefresh_Mode(true)
{
SetPanels_AutoRefresh_Mode();
}
void CreateDragTarget()
{
_dropTargetSpec = new CDropTarget();
_dropTarget = _dropTargetSpec;
_dropTargetSpec->App = (this);
}
void SetFocusedPanel(unsigned index)
{
LastFocusedPanel = index;
_dropTargetSpec->TargetPanelIndex = LastFocusedPanel;
}
void DragBegin(unsigned panelIndex)
{
_dropTargetSpec->TargetPanelIndex = (NumPanels > 1) ? 1 - panelIndex : panelIndex;
_dropTargetSpec->SrcPanelIndex = panelIndex;
}
void DragEnd()
{
_dropTargetSpec->TargetPanelIndex = LastFocusedPanel;
_dropTargetSpec->SrcPanelIndex = -1;
}
void OnCopy(bool move, bool copyToSame, int srcPanelIndex);
void OnSetSameFolder(int srcPanelIndex);
void OnSetSubFolder(int srcPanelIndex);
HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool needOpenArc, bool &archiveIsOpened, bool &encrypted);
HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, bool &archiveIsOpened, bool &encrypted);
void Read();
void Save();
void Release();
// void SetFocus(int panelIndex) { Panels[panelIndex].SetFocusToList(); }
void SetFocusToLastItem() { Panels[LastFocusedPanel].SetFocusToLastRememberedItem(); }
unsigned GetFocusedPanelIndex() const { return LastFocusedPanel; }
bool IsPanelVisible(unsigned index) const { return (NumPanels > 1 || index == LastFocusedPanel); }
CPanel &GetFocusedPanel() { return Panels[GetFocusedPanelIndex()]; }
// File Menu
void OpenItem() { GetFocusedPanel().OpenSelectedItems(true); }
void OpenItemInside(const wchar_t *type) { GetFocusedPanel().OpenFocusedItemAsInternal(type); }
void OpenItemOutside() { GetFocusedPanel().OpenSelectedItems(false); }
void EditItem(bool useEditor) { GetFocusedPanel().EditItem(useEditor); }
void Rename() { GetFocusedPanel().RenameFile(); }
void CopyTo() { OnCopy(false, false, GetFocusedPanelIndex()); }
void MoveTo() { OnCopy(true, false, GetFocusedPanelIndex()); }
void Delete(bool toRecycleBin) { GetFocusedPanel().DeleteItems(toRecycleBin); }
HRESULT CalculateCrc2(const UString &methodName);
void CalculateCrc(const char *methodName);
void DiffFiles();
void Split();
void Combine();
void Properties() { GetFocusedPanel().Properties(); }
void Comment() { GetFocusedPanel().ChangeComment(); }
#ifndef UNDER_CE
void Link();
void OpenAltStreams() { GetFocusedPanel().OpenAltStreams(); }
#endif
void CreateFolder() { GetFocusedPanel().CreateFolder(); }
void CreateFile() { GetFocusedPanel().CreateFile(); }
// Edit
void EditCut() { GetFocusedPanel().EditCut(); }
void EditCopy() { GetFocusedPanel().EditCopy(); }
void EditPaste() { GetFocusedPanel().EditPaste(); }
void SelectAll(bool selectMode) { GetFocusedPanel().SelectAll(selectMode); }
void InvertSelection() { GetFocusedPanel().InvertSelection(); }
void SelectSpec(bool selectMode) { GetFocusedPanel().SelectSpec(selectMode); }
void SelectByType(bool selectMode) { GetFocusedPanel().SelectByType(selectMode); }
void Refresh_StatusBar() { GetFocusedPanel().Refresh_StatusBar(); }
void SetListViewMode(UInt32 index) { GetFocusedPanel().SetListViewMode(index); }
UInt32 GetListViewMode() { return GetFocusedPanel().GetListViewMode(); }
PROPID GetSortID() { return GetFocusedPanel().GetSortID(); }
void SortItemsWithPropID(PROPID propID) { GetFocusedPanel().SortItemsWithPropID(propID); }
void OpenRootFolder() { GetFocusedPanel().OpenDrivesFolder(); }
void OpenParentFolder() { GetFocusedPanel().OpenParentFolder(); }
void FoldersHistory() { GetFocusedPanel().FoldersHistory(); }
void RefreshView() { GetFocusedPanel().OnReload(); }
void RefreshAllPanels()
{
for (unsigned i = 0; i < NumPanels; i++)
{
unsigned index = i;
if (NumPanels == 1)
index = LastFocusedPanel;
Panels[index].OnReload();
}
}
/*
void SysIconsWereChanged()
{
for (unsigned i = 0; i < NumPanels; i++)
{
unsigned index = i;
if (NumPanels == 1)
index = LastFocusedPanel;
Panels[index].SysIconsWereChanged();
}
}
*/
void SetListSettings();
HRESULT SwitchOnOffOnePanel();
CIntVector _timestampLevels;
bool GetFlatMode() { return Panels[LastFocusedPanel].GetFlatMode(); }
int GetTimestampLevel() const { return Panels[LastFocusedPanel]._timestampLevel; }
void SetTimestampLevel(int level)
{
unsigned i;
for (i = 0; i < kNumPanelsMax; i++)
{
CPanel &panel = Panels[i];
panel._timestampLevel = level;
if (panel.PanelCreated)
panel.RedrawListItems();
}
}
// bool Get_ShowNtfsStrems_Mode() { return Panels[LastFocusedPanel].Get_ShowNtfsStrems_Mode(); }
void ChangeFlatMode() { Panels[LastFocusedPanel].ChangeFlatMode(); }
// void Change_ShowNtfsStrems_Mode() { Panels[LastFocusedPanel].Change_ShowNtfsStrems_Mode(); }
// void Change_ShowDeleted() { ShowDeletedFiles = !ShowDeletedFiles; }
bool AutoRefresh_Mode;
bool Get_AutoRefresh_Mode()
{
// return Panels[LastFocusedPanel].Get_ShowNtfsStrems_Mode();
return AutoRefresh_Mode;
}
void Change_AutoRefresh_Mode()
{
AutoRefresh_Mode = !AutoRefresh_Mode;
SetPanels_AutoRefresh_Mode();
}
void SetPanels_AutoRefresh_Mode()
{
for (unsigned i = 0; i < kNumPanelsMax; i++)
Panels[i].Set_AutoRefresh_Mode(AutoRefresh_Mode);
}
void OpenBookmark(int index) { GetFocusedPanel().OpenBookmark(index); }
void SetBookmark(int index) { GetFocusedPanel().SetBookmark(index); }
void ReloadToolbars();
void ReadToolbar()
{
UInt32 mask = ReadToolbarsMask();
if (mask & ((UInt32)1 << 31))
{
ShowButtonsLables = !g_IsSmallScreen;
LargeButtons = false;
ShowStandardToolbar = ShowArchiveToolbar = true;
}
else
{
ShowButtonsLables = ((mask & 1) != 0);
LargeButtons = ((mask & 2) != 0);
ShowStandardToolbar = ((mask & 4) != 0);
ShowArchiveToolbar = ((mask & 8) != 0);
}
}
void SaveToolbar()
{
UInt32 mask = 0;
if (ShowButtonsLables) mask |= 1;
if (LargeButtons) mask |= 2;
if (ShowStandardToolbar) mask |= 4;
if (ShowArchiveToolbar) mask |= 8;
SaveToolbarsMask(mask);
}
void SaveToolbarChanges();
void SwitchStandardToolbar()
{
ShowStandardToolbar = !ShowStandardToolbar;
SaveToolbarChanges();
}
void SwitchArchiveToolbar()
{
ShowArchiveToolbar = !ShowArchiveToolbar;
SaveToolbarChanges();
}
void SwitchButtonsLables()
{
ShowButtonsLables = !ShowButtonsLables;
SaveToolbarChanges();
}
void SwitchLargeButtons()
{
LargeButtons = !LargeButtons;
SaveToolbarChanges();
}
void AddToArchive() { GetFocusedPanel().AddToArchive(); }
void ExtractArchives() { GetFocusedPanel().ExtractArchives(); }
void TestArchives() { GetFocusedPanel().TestArchives(); }
void OnNotify(int ctrlID, LPNMHDR pnmh);
UString PrevTitle;
void RefreshTitle(bool always = false);
void RefreshTitleAlways() { RefreshTitle(true); }
void RefreshTitlePanel(unsigned panelIndex, bool always = false);
void MoveSubWindows();
};
#endif
@@ -0,0 +1,95 @@
// AppState.h
#ifndef __APP_STATE_H
#define __APP_STATE_H
#include "../../../Windows/Synchronization.h"
#include "ViewSettings.h"
class CFastFolders
{
NWindows::NSynchronization::CCriticalSection _criticalSection;
public:
UStringVector Strings;
void SetString(unsigned index, const UString &s)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
while (Strings.Size() <= index)
Strings.AddNew();
Strings[index] = s;
}
UString GetString(unsigned index)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
if (index >= Strings.Size())
return UString();
return Strings[index];
}
void Save()
{
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
SaveFastFolders(Strings);
}
void Read()
{
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
ReadFastFolders(Strings);
}
};
class CFolderHistory
{
NWindows::NSynchronization::CCriticalSection _criticalSection;
UStringVector Strings;
void Normalize();
public:
void GetList(UStringVector &foldersHistory)
{
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
foldersHistory = Strings;
}
void AddString(const UString &s);
void RemoveAll()
{
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
Strings.Clear();
}
void Save()
{
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
SaveFolderHistory(Strings);
}
void Read()
{
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
ReadFolderHistory(Strings);
Normalize();
}
};
struct CAppState
{
CFastFolders FastFolders;
CFolderHistory FolderHistory;
void Save()
{
FastFolders.Save();
FolderHistory.Save();
}
void Read()
{
FastFolders.Read();
FolderHistory.Read();
}
};
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,21 @@
// BrowseDialog.h
#ifndef __BROWSE_DIALOG_H
#define __BROWSE_DIALOG_H
#include "../../../Common/MyString.h"
bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath);
bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath);
/* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file)
But it doesn't change "bad" name in any of the following cases:
- path is Super Path (with \\?\ prefix)
- path is relative and relBase is Super Path
- there is file or dir in filesystem with specified "bad" name */
bool CorrectFsPath(const UString &relBase, const UString &path, UString &result);
bool Dlg_CreateFolder(HWND wnd, UString &destName);
#endif
@@ -0,0 +1,25 @@
#include "BrowseDialogRes.h"
#include "../../GuiCommon.rc"
#define xc 256
#define yc 320
#define k_BROWSE_y_CtrlSize 14
#define k_BROWSE_y_List 24
IDD_BROWSE DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
CAPTION "7-Zip: Browse"
{
EDITTEXT IDE_BROWSE_PATH, m, by - m - k_BROWSE_y_CtrlSize - k_BROWSE_y_CtrlSize - m, xc, k_BROWSE_y_CtrlSize, ES_AUTOHSCROLL
COMBOBOX IDC_BROWSE_FILTER, m, by - m - k_BROWSE_y_CtrlSize, xc, 30, MY_COMBO
PUSHBUTTON "OK", IDOK, bx2, by, bxs, bys
PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
PUSHBUTTON "<--", IDB_BROWSE_PARENT, m, m, 24, bys
PUSHBUTTON "+", IDB_BROWSE_CREATE_DIR, m + 32, m, 24, bys
LTEXT "", IDT_BROWSE_FOLDER, m + 64, m + 3, xc - 20, 8
CONTROL "List1", IDL_BROWSE, "SysListView32",
LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,
m, m + k_BROWSE_y_List, xc, yc - bys - m - k_BROWSE_y_List - k_BROWSE_y_CtrlSize - m - k_BROWSE_y_CtrlSize - m
}
@@ -0,0 +1,9 @@
#define IDD_BROWSE 95
#define IDL_BROWSE 100
#define IDT_BROWSE_FOLDER 101
#define IDE_BROWSE_PATH 102
#define IDC_BROWSE_FILTER 103
#define IDB_BROWSE_PARENT 110
#define IDB_BROWSE_CREATE_DIR 112
@@ -0,0 +1,11 @@
// ClassDefs.cpp
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include "../../../Common/MyInitGuid.h"
#include "../Agent/Agent.h"
#include "MyWindowsNew.h"
@@ -0,0 +1,64 @@
// ComboDialog.cpp
#include "StdAfx.h"
#include "ComboDialog.h"
#include "../../../Windows/Control/Static.h"
#ifdef LANG
#include "LangUtils.h"
#endif
using namespace NWindows;
bool CComboDialog::OnInit()
{
#ifdef LANG
LangSetDlgItems(*this, NULL, 0);
#endif
_comboBox.Attach(GetItem(IDC_COMBO));
/*
// why it doesn't work ?
DWORD style = _comboBox.GetStyle();
if (Sorted)
style |= CBS_SORT;
else
style &= ~CBS_SORT;
_comboBox.SetStyle(style);
*/
SetText(Title);
NControl::CStatic staticContol;
staticContol.Attach(GetItem(IDT_COMBO));
staticContol.SetText(Static);
_comboBox.SetText(Value);
FOR_VECTOR (i, Strings)
_comboBox.AddString(Strings[i]);
NormalizeSize();
return CModalDialog::OnInit();
}
bool CComboDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
{
int mx, my;
GetMargins(8, mx, my);
int bx1, bx2, by;
GetItemSizes(IDCANCEL, bx1, by);
GetItemSizes(IDOK, bx2, by);
int y = ySize - my - by;
int x = xSize - mx - bx1;
InvalidateRect(NULL);
MoveItem(IDCANCEL, x, y, bx1, by);
MoveItem(IDOK, x - mx - bx2, y, bx2, by);
ChangeSubWindowSizeX(_comboBox, xSize - mx * 2);
return false;
}
void CComboDialog::OnOK()
{
_comboBox.GetText(Value);
CModalDialog::OnOK();
}
@@ -0,0 +1,28 @@
// ComboDialog.h
#ifndef __COMBO_DIALOG_H
#define __COMBO_DIALOG_H
#include "../../../Windows/Control/ComboBox.h"
#include "../../../Windows/Control/Dialog.h"
#include "ComboDialogRes.h"
class CComboDialog: public NWindows::NControl::CModalDialog
{
NWindows::NControl::CComboBox _comboBox;
virtual void OnOK();
virtual bool OnInit();
virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
public:
// bool Sorted;
UString Title;
UString Static;
UString Value;
UStringVector Strings;
// CComboDialog(): Sorted(false) {};
INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_COMBO, parentWindow); }
};
#endif
@@ -0,0 +1,16 @@
#include "ComboDialogRes.h"
#include "../../GuiCommon.rc"
#define xc 240
#define yc 64
IDD_COMBO DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
CAPTION "Combo"
{
LTEXT "", IDT_COMBO, m, m, xc, 8
COMBOBOX IDC_COMBO, m, 20, xc, 65, MY_COMBO_WITH_EDIT
OK_CANCEL
}
#undef xc
#undef yc
@@ -0,0 +1,4 @@
#define IDD_COMBO 98
#define IDT_COMBO 100
#define IDC_COMBO 101
Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

@@ -0,0 +1,106 @@
// CopyDialog.cpp
#include "StdAfx.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/Control/Static.h"
#include "BrowseDialog.h"
#include "CopyDialog.h"
#ifdef LANG
#include "LangUtils.h"
#endif
using namespace NWindows;
bool CCopyDialog::OnInit()
{
#ifdef LANG
LangSetDlgItems(*this, NULL, 0);
#endif
_path.Attach(GetItem(IDC_COPY));
SetText(Title);
NControl::CStatic staticContol;
staticContol.Attach(GetItem(IDT_COPY));
staticContol.SetText(Static);
#ifdef UNDER_CE
// we do it, since WinCE selects Value\something instead of Value !!!!
_path.AddString(Value);
#endif
FOR_VECTOR (i, Strings)
_path.AddString(Strings[i]);
_path.SetText(Value);
SetItemText(IDT_COPY_INFO, Info);
NormalizeSize(true);
return CModalDialog::OnInit();
}
bool CCopyDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
{
int mx, my;
GetMargins(8, mx, my);
int bx1, bx2, by;
GetItemSizes(IDCANCEL, bx1, by);
GetItemSizes(IDOK, bx2, by);
int y = ySize - my - by;
int x = xSize - mx - bx1;
InvalidateRect(NULL);
{
RECT r;
GetClientRectOfItem(IDB_COPY_SET_PATH, r);
int bx = RECT_SIZE_X(r);
MoveItem(IDB_COPY_SET_PATH, xSize - mx - bx, r.top, bx, RECT_SIZE_Y(r));
ChangeSubWindowSizeX(_path, xSize - mx - mx - bx - mx);
}
{
RECT r;
GetClientRectOfItem(IDT_COPY_INFO, r);
NControl::CStatic staticContol;
staticContol.Attach(GetItem(IDT_COPY_INFO));
int yPos = r.top;
staticContol.Move(mx, yPos, xSize - mx * 2, y - 2 - yPos);
}
MoveItem(IDCANCEL, x, y, bx1, by);
MoveItem(IDOK, x - mx - bx2, y, bx2, by);
return false;
}
bool CCopyDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
{
switch (buttonID)
{
case IDB_COPY_SET_PATH:
OnButtonSetPath();
return true;
}
return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
}
void CCopyDialog::OnButtonSetPath()
{
UString currentPath;
_path.GetText(currentPath);
const UString title = LangString(IDS_SET_FOLDER);
UString resultPath;
if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
return;
NFile::NName::NormalizeDirPathPrefix(resultPath);
_path.SetCurSel(-1);
_path.SetText(resultPath);
}
void CCopyDialog::OnOK()
{
_path.GetText(Value);
CModalDialog::OnOK();
}
@@ -0,0 +1,31 @@
// CopyDialog.h
#ifndef __COPY_DIALOG_H
#define __COPY_DIALOG_H
#include "../../../Windows/Control/ComboBox.h"
#include "../../../Windows/Control/Dialog.h"
#include "CopyDialogRes.h"
const int kCopyDialog_NumInfoLines = 11;
class CCopyDialog: public NWindows::NControl::CModalDialog
{
NWindows::NControl::CComboBox _path;
virtual void OnOK();
virtual bool OnInit();
virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
void OnButtonSetPath();
bool OnButtonClicked(int buttonID, HWND buttonHWND);
public:
UString Title;
UString Static;
UString Value;
UString Info;
UStringVector Strings;
INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_COPY, parentWindow); }
};
#endif
@@ -0,0 +1,20 @@
#include "CopyDialogRes.h"
#include "../../GuiCommon.rc"
#define xc 320
#define yc 144
#define y 40
IDD_COPY DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
CAPTION "Copy"
{
LTEXT "", IDT_COPY, m, m, xc, 8
COMBOBOX IDC_COPY, m, 20, xc - bxsDots - m, 65, MY_COMBO_WITH_EDIT
PUSHBUTTON "...", IDB_COPY_SET_PATH, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP
LTEXT "", IDT_COPY_INFO, m, y, xc, by - y - 1, SS_NOPREFIX | SS_LEFTNOWORDWRAP
OK_CANCEL
}
#undef xc
#undef yc
@@ -0,0 +1,8 @@
#define IDD_COPY 96
#define IDT_COPY 100
#define IDC_COPY 101
#define IDB_COPY_SET_PATH 102
#define IDT_COPY_INFO 103
#define IDS_SET_FOLDER 6007
Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

@@ -0,0 +1,16 @@
// DialogSize.h
#ifndef __DIALOG_SIZE_H
#define __DIALOG_SIZE_H
#include "../../../Windows/Control/Dialog.h"
#ifdef UNDER_CE
#define BIG_DIALOG_SIZE(x, y) bool isBig = NWindows::NControl::IsDialogSizeOK(x, y);
#define SIZED_DIALOG(big) (isBig ? big : big ## _2)
#else
#define BIG_DIALOG_SIZE(x, y)
#define SIZED_DIALOG(big) big
#endif
#endif
@@ -0,0 +1,57 @@
// EditDialog.cpp
#include "StdAfx.h"
#include "EditDialog.h"
#ifdef LANG
#include "LangUtils.h"
#endif
bool CEditDialog::OnInit()
{
#ifdef LANG
LangSetDlgItems(*this, NULL, 0);
#endif
_edit.Attach(GetItem(IDE_EDIT));
SetText(Title);
_edit.SetText(Text);
NormalizeSize();
return CModalDialog::OnInit();
}
// #define MY_CLOSE_BUTTON__ID IDCANCEL
#define MY_CLOSE_BUTTON__ID IDCLOSE
bool CEditDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
{
int mx, my;
GetMargins(8, mx, my);
int bx1, by;
GetItemSizes(MY_CLOSE_BUTTON__ID, bx1, by);
// int bx2;
// GetItemSizes(IDOK, bx2, by);
int y = ySize - my - by;
int x = xSize - mx - bx1;
/*
RECT rect;
GetClientRect(&rect);
rect.top = y - my;
InvalidateRect(&rect);
*/
InvalidateRect(NULL);
MoveItem(MY_CLOSE_BUTTON__ID, x, y, bx1, by);
// MoveItem(IDOK, x - mx - bx2, y, bx2, by);
/*
if (wParam == SIZE_MAXSHOW || wParam == SIZE_MAXIMIZED || wParam == SIZE_MAXHIDE)
mx = 0;
*/
_edit.Move(mx, my, xSize - mx * 2, y - my * 2);
return false;
}
@@ -0,0 +1,25 @@
// EditDialog.h
#ifndef __EDIT_DIALOG_H
#define __EDIT_DIALOG_H
#include "../../../Windows/Control/Dialog.h"
#include "../../../Windows/Control/Edit.h"
#include "EditDialogRes.h"
class CEditDialog: public NWindows::NControl::CModalDialog
{
NWindows::NControl::CEdit _edit;
virtual bool OnInit();
virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
public:
UString Title;
UString Text;
INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_EDIT_DLG, wndParent); }
CEditDialog() {}
};
#endif
@@ -0,0 +1,15 @@
#include "EditDialogRes.h"
#include "../../GuiCommon.rc"
#define xc 320
#define yc 240
IDD_EDIT_DLG DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
CAPTION "Edit"
{
// OK_CANCEL
MY_BUTTON__CLOSE
EDITTEXT IDE_EDIT, m, m, xc, yc - bys - m,
ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_HSCROLL | ES_WANTRETURN
}
@@ -0,0 +1,2 @@
#define IDD_EDIT_DLG 94
#define IDE_EDIT 100
@@ -0,0 +1,147 @@
// EditPage.cpp
#include "StdAfx.h"
#include "EditPage.h"
#include "EditPageRes.h"
#include "BrowseDialog.h"
#include "HelpUtils.h"
#include "LangUtils.h"
#include "RegistryUtils.h"
using namespace NWindows;
static const UInt32 kLangIDs[] =
{
IDT_EDIT_EDITOR,
IDT_EDIT_DIFF
};
static const UInt32 kLangIDs_Colon[] =
{
IDT_EDIT_VIEWER
};
#define kEditTopic "FM/options.htm#editor"
bool CEditPage::OnInit()
{
_initMode = true;
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon));
_ctrls[0].Ctrl = IDE_EDIT_VIEWER; _ctrls[0].Button = IDB_EDIT_VIEWER;
_ctrls[1].Ctrl = IDE_EDIT_EDITOR; _ctrls[1].Button = IDB_EDIT_EDITOR;
_ctrls[2].Ctrl = IDE_EDIT_DIFF; _ctrls[2].Button = IDB_EDIT_DIFF;
for (unsigned i = 0; i < 3; i++)
{
CEditPageCtrl &c = _ctrls[i];
c.WasChanged = false;
c.Edit.Attach(GetItem(c.Ctrl));
UString path;
if (i < 2)
ReadRegEditor(i > 0, path);
else
ReadRegDiff(path);
c.Edit.SetText(path);
}
_initMode = false;
return CPropertyPage::OnInit();
}
LONG CEditPage::OnApply()
{
for (unsigned i = 0; i < 3; i++)
{
CEditPageCtrl &c = _ctrls[i];
if (c.WasChanged)
{
UString path;
c.Edit.GetText(path);
if (i < 2)
SaveRegEditor(i > 0, path);
else
SaveRegDiff(path);
c.WasChanged = false;
}
}
return PSNRET_NOERROR;
}
void CEditPage::OnNotifyHelp()
{
ShowHelpWindow(kEditTopic);
}
void SplitCmdLineSmart(const UString &cmd, UString &prg, UString &params);
static void Edit_BrowseForFile(NWindows::NControl::CEdit &edit, HWND hwnd)
{
UString cmd;
edit.GetText(cmd);
UString param;
UString prg;
SplitCmdLineSmart(cmd, prg, param);
UString resPath;
if (MyBrowseForFile(hwnd, 0, prg, NULL, L"*.exe", resPath))
{
resPath.Trim();
cmd = resPath;
/*
if (!param.IsEmpty() && !resPath.IsEmpty())
{
cmd.InsertAtFront(L'\"');
cmd += L'\"';
cmd.Add_Space();
cmd += param;
}
*/
edit.SetText(cmd);
// Changed();
}
}
bool CEditPage::OnButtonClicked(int buttonID, HWND buttonHWND)
{
for (unsigned i = 0; i < 3; i++)
{
CEditPageCtrl &c = _ctrls[i];
if (buttonID == c.Button)
{
Edit_BrowseForFile(c.Edit, *this);
return true;
}
}
return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
}
bool CEditPage::OnCommand(int code, int itemID, LPARAM param)
{
if (!_initMode && code == EN_CHANGE)
{
for (unsigned i = 0; i < 3; i++)
{
CEditPageCtrl &c = _ctrls[i];
if (itemID == c.Ctrl)
{
c.WasChanged = true;
Changed();
return true;
}
}
}
return CPropertyPage::OnCommand(code, itemID, param);
}
@@ -0,0 +1,30 @@
// EditPage.h
#ifndef __EDIT_PAGE_H
#define __EDIT_PAGE_H
#include "../../../Windows/Control/PropertyPage.h"
#include "../../../Windows/Control/Edit.h"
struct CEditPageCtrl
{
NWindows::NControl::CEdit Edit;
bool WasChanged;
int Ctrl;
int Button;
};
class CEditPage: public NWindows::NControl::CPropertyPage
{
CEditPageCtrl _ctrls[3];
bool _initMode;
public:
virtual bool OnInit();
virtual void OnNotifyHelp();
virtual bool OnCommand(int code, int itemID, LPARAM param);
virtual LONG OnApply();
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
};
#endif
@@ -0,0 +1,19 @@
#include "EditPageRes.h"
#include "../../GuiCommon.rc"
#define xc 240
#define yc 80
IDD_EDIT MY_PAGE
#include "EditPage2.rc"
#ifdef UNDER_CE
#undef xc
#define xc SMALL_PAGE_SIZE_X
IDD_EDIT_2 MY_PAGE
#include "EditPage2.rc"
#endif
@@ -0,0 +1,14 @@
CAPTION "Editor"
{
LTEXT "&View:", IDT_EDIT_VIEWER, m, m, xc, 8
EDITTEXT IDE_EDIT_VIEWER, m, m + 12, xc - m - bxsDots, 14, ES_AUTOHSCROLL
PUSHBUTTON "...", IDB_EDIT_VIEWER, xs - m - bxsDots, m + 11, bxsDots, bys
LTEXT "&Editor:", IDT_EDIT_EDITOR, m, m + 32, xc, 8
EDITTEXT IDE_EDIT_EDITOR, m, m + 44, xc - m - bxsDots, 14, ES_AUTOHSCROLL
PUSHBUTTON "...", IDB_EDIT_EDITOR, xs - m - bxsDots, m + 43, bxsDots, bys
LTEXT "&Diff:", IDT_EDIT_DIFF, m, m + 64, xc, 8
EDITTEXT IDE_EDIT_DIFF, m, m + 76, xc - m - bxsDots, 14, ES_AUTOHSCROLL
PUSHBUTTON "...", IDB_EDIT_DIFF, xs - m - bxsDots, m + 75, bxsDots, bys
}
@@ -0,0 +1,15 @@
#define IDD_EDIT 2103
#define IDD_EDIT_2 12103
#define IDT_EDIT_VIEWER 543
#define IDT_EDIT_EDITOR 2104
#define IDT_EDIT_DIFF 2105
#define IDE_EDIT_VIEWER 100
#define IDB_EDIT_VIEWER 101
#define IDE_EDIT_EDITOR 102
#define IDB_EDIT_EDITOR 103
#define IDE_EDIT_DIFF 104
#define IDB_EDIT_DIFF 105
@@ -0,0 +1,108 @@
// EnumFormatEtc.cpp
#include "StdAfx.h"
#include "EnumFormatEtc.h"
#include "MyCom2.h"
class CEnumFormatEtc :
public IEnumFORMATETC,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1_MT(IEnumFORMATETC)
STDMETHOD(Next)(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
STDMETHOD(Skip)(ULONG celt);
STDMETHOD(Reset)(void);
STDMETHOD(Clone)(IEnumFORMATETC **ppEnumFormatEtc);
CEnumFormatEtc(const FORMATETC *pFormatEtc, ULONG numFormats);
~CEnumFormatEtc();
private:
LONG m_RefCount;
ULONG m_NumFormats;
FORMATETC *m_Formats;
ULONG m_Index;
};
static void DeepCopyFormatEtc(FORMATETC *dest, const FORMATETC *src)
{
*dest = *src;
if (src->ptd)
{
dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
*(dest->ptd) = *(src->ptd);
}
}
CEnumFormatEtc::CEnumFormatEtc(const FORMATETC *pFormatEtc, ULONG numFormats)
{
m_RefCount = 1;
m_Index = 0;
m_NumFormats = 0;
m_Formats = new FORMATETC[numFormats];
// if (m_Formats)
{
m_NumFormats = numFormats;
for (ULONG i = 0; i < numFormats; i++)
DeepCopyFormatEtc(&m_Formats[i], &pFormatEtc[i]);
}
}
CEnumFormatEtc::~CEnumFormatEtc()
{
if (m_Formats)
{
for (ULONG i = 0; i < m_NumFormats; i++)
if (m_Formats[i].ptd)
CoTaskMemFree(m_Formats[i].ptd);
delete[]m_Formats;
}
}
STDMETHODIMP CEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG *pceltFetched)
{
ULONG copied = 0;
if (celt == 0 || pFormatEtc == 0)
return E_INVALIDARG;
while (m_Index < m_NumFormats && copied < celt)
{
DeepCopyFormatEtc(&pFormatEtc[copied], &m_Formats[m_Index]);
copied++;
m_Index++;
}
if (pceltFetched != 0)
*pceltFetched = copied;
return (copied == celt) ? S_OK : S_FALSE;
}
STDMETHODIMP CEnumFormatEtc::Skip(ULONG celt)
{
m_Index += celt;
return (m_Index <= m_NumFormats) ? S_OK : S_FALSE;
}
STDMETHODIMP CEnumFormatEtc::Reset(void)
{
m_Index = 0;
return S_OK;
}
STDMETHODIMP CEnumFormatEtc::Clone(IEnumFORMATETC ** ppEnumFormatEtc)
{
HRESULT hResult = CreateEnumFormatEtc(m_NumFormats, m_Formats, ppEnumFormatEtc);
if (hResult == S_OK)
((CEnumFormatEtc *)*ppEnumFormatEtc)->m_Index = m_Index;
return hResult;
}
// replacement for SHCreateStdEnumFmtEtc
HRESULT CreateEnumFormatEtc(UINT numFormats, const FORMATETC *formats, IEnumFORMATETC **enumFormat)
{
if (numFormats == 0 || formats == 0 || enumFormat == 0)
return E_INVALIDARG;
*enumFormat = new CEnumFormatEtc(formats, numFormats);
return (*enumFormat) ? S_OK : E_OUTOFMEMORY;
}
@@ -0,0 +1,10 @@
// EnumFormatEtc.h
#ifndef __ENUMFORMATETC_H
#define __ENUMFORMATETC_H
#include <windows.h>
HRESULT CreateEnumFormatEtc(UINT numFormats, const FORMATETC *formats, IEnumFORMATETC **enumFormat);
#endif
Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

File diff suppressed because it is too large Load Diff
@@ -0,0 +1,328 @@
// ExtractCallback.h
#ifndef __EXTRACT_CALLBACK_H
#define __EXTRACT_CALLBACK_H
#include "../../../../C/Alloc.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/StringConvert.h"
#ifndef _SFX
#include "../Agent/IFolderArchive.h"
#endif
#include "../Common/ArchiveExtractCallback.h"
#include "../Common/ArchiveOpenCallback.h"
#ifndef _NO_CRYPTO
#include "../../IPassword.h"
#endif
#ifndef _SFX
#include "IFolder.h"
#endif
#include "ProgressDialog2.h"
#ifdef LANG
#include "LangUtils.h"
#endif
#ifndef _SFX
class CGrowBuf
{
Byte *_items;
size_t _size;
CLASS_NO_COPY(CGrowBuf);
public:
bool ReAlloc_KeepData(size_t newSize, size_t keepSize)
{
void *buf = MyAlloc(newSize);
if (!buf)
return false;
if (keepSize != 0)
memcpy(buf, _items, keepSize);
MyFree(_items);
_items = (Byte *)buf;
_size = newSize;
return true;
}
CGrowBuf(): _items(0), _size(0) {}
~CGrowBuf() { MyFree(_items); }
operator Byte *() { return _items; }
operator const Byte *() const { return _items; }
size_t Size() const { return _size; }
};
struct CVirtFile
{
CGrowBuf Data;
UInt64 Size; // real size
UInt64 ExpectedSize; // the size from props request. 0 if unknown
UString Name;
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
bool AttribDefined;
bool IsDir;
bool IsAltStream;
DWORD Attrib;
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
CVirtFile():
CTimeDefined(false),
ATimeDefined(false),
MTimeDefined(false),
AttribDefined(false),
IsDir(false),
IsAltStream(false) {}
};
class CVirtFileSystem:
public ISequentialOutStream,
public CMyUnknownImp
{
UInt64 _totalAllocSize;
size_t _pos;
unsigned _numFlushed;
bool _fileIsOpen;
bool _fileMode;
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
public:
CObjectVector<CVirtFile> Files;
UInt64 MaxTotalAllocSize;
FString DirPrefix;
CVirtFile &AddNewFile()
{
if (!Files.IsEmpty())
{
MaxTotalAllocSize -= Files.Back().Data.Size();
}
return Files.AddNew();
}
HRESULT CloseMemFile()
{
if (_fileMode)
{
return FlushToDisk(true);
}
CVirtFile &file = Files.Back();
if (file.Data.Size() != file.Size)
{
file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size);
}
return S_OK;
}
bool IsStreamInMem() const
{
if (_fileMode)
return false;
if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir)
return false;
return true;
}
size_t GetMemStreamWrittenSize() const { return _pos; }
CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {}
void Init()
{
_totalAllocSize = 0;
_fileMode = false;
_pos = 0;
_numFlushed = 0;
_fileIsOpen = false;
}
HRESULT CloseFile(const FString &path);
HRESULT FlushToDisk(bool closeLast);
size_t GetPos() const { return _pos; }
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
#endif
class CExtractCallbackImp:
public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback
public IOpenCallbackUI,
public IFolderArchiveExtractCallback2,
#ifndef _SFX
public IFolderOperationsExtractCallback,
public IFolderExtractToStreamCallback,
public ICompressProgressInfo,
#endif
#ifndef _NO_CRYPTO
public ICryptoGetTextPassword,
#endif
public CMyUnknownImp
{
HRESULT MessageError(const char *message, const FString &path);
void Add_ArchiveName_Error();
public:
MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)
#ifndef _SFX
MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback)
MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback)
MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)
#endif
#ifndef _NO_CRYPTO
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
#endif
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IProgress(;)
INTERFACE_IOpenCallbackUI(;)
INTERFACE_IFolderArchiveExtractCallback(;)
INTERFACE_IFolderArchiveExtractCallback2(;)
// STDMETHOD(SetTotalFiles)(UInt64 total);
// STDMETHOD(SetCompletedFiles)(const UInt64 *value);
INTERFACE_IExtractCallbackUI(;)
#ifndef _SFX
// IFolderOperationsExtractCallback
STDMETHOD(AskWrite)(
const wchar_t *srcPath,
Int32 srcIsFolder,
const FILETIME *srcTime,
const UInt64 *srcSize,
const wchar_t *destPathRequest,
BSTR *destPathResult,
Int32 *writeAnswer);
STDMETHOD(ShowMessage)(const wchar_t *message);
STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath);
STDMETHOD(SetNumFiles)(UInt64 numFiles);
INTERFACE_IFolderExtractToStreamCallback(;)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
#endif
// ICryptoGetTextPassword
#ifndef _NO_CRYPTO
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
#endif
private:
UString _currentArchivePath;
bool _needWriteArchivePath;
UString _currentFilePath;
bool _isFolder;
bool _isAltStream;
UInt64 _curSize;
bool _curSizeDefined;
UString _filePath;
// bool _extractMode;
// bool _testMode;
bool _newVirtFileWasAdded;
bool _needUpdateStat;
HRESULT SetCurrentFilePath2(const wchar_t *filePath);
void AddError_Message(LPCWSTR message);
#ifndef _SFX
bool _hashStreamWasUsed;
COutStreamWithHash *_hashStreamSpec;
CMyComPtr<ISequentialOutStream> _hashStream;
IHashCalc *_hashCalc; // it's for stat in Test operation
#endif
public:
#ifndef _SFX
CVirtFileSystem *VirtFileSystemSpec;
CMyComPtr<ISequentialOutStream> VirtFileSystem;
#endif
bool ProcessAltStreams;
bool StreamMode;
CProgressDialog *ProgressDialog;
#ifndef _SFX
UInt64 NumFolders;
UInt64 NumFiles;
bool NeedAddFile;
#endif
UInt32 NumArchiveErrors;
bool ThereAreMessageErrors;
NExtract::NOverwriteMode::EEnum OverwriteMode;
#ifndef _NO_CRYPTO
bool PasswordIsDefined;
bool PasswordWasAsked;
UString Password;
#endif
UString _lang_Extracting;
UString _lang_Testing;
UString _lang_Skipping;
UString _lang_Empty;
bool _totalFilesDefined;
bool _totalBytesDefined;
bool MultiArcMode;
CExtractCallbackImp():
#ifndef _NO_CRYPTO
PasswordIsDefined(false),
PasswordWasAsked(false),
#endif
OverwriteMode(NExtract::NOverwriteMode::kAsk),
StreamMode(false),
ProcessAltStreams(true),
_totalFilesDefined(false),
_totalBytesDefined(false),
MultiArcMode(false)
#ifndef _SFX
, _hashCalc(NULL)
#endif
{}
~CExtractCallbackImp();
void Init();
#ifndef _SFX
void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }
void SetHashMethods(IHashCalc *hash)
{
if (!hash)
return;
_hashStreamSpec = new COutStreamWithHash;
_hashStream = _hashStreamSpec;
_hashStreamSpec->_hash = hash;
}
#endif
bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }
};
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "FM"=.\FM.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

@@ -0,0 +1,99 @@
CFLAGS = $(CFLAGS) \
-DLANG \
-DNEW_FOLDER_INTERFACE \
!IFDEF UNDER_CE
LIBS = $(LIBS) ceshell.lib Commctrl.lib
!ELSE
LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib
CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -DSUPPORT_DEVICE_FILE
LFLAGS = $(LFLAGS) /DELAYLOAD:mpr.dll
LIBS = $(LIBS) delayimp.lib
!ENDIF
FM_OBJS = \
$O\App.obj \
$O\BrowseDialog.obj \
$O\ClassDefs.obj \
$O\EnumFormatEtc.obj \
$O\ExtractCallback.obj \
$O\FileFolderPluginOpen.obj \
$O\FilePlugins.obj \
$O\FM.obj \
$O\FoldersPage.obj \
$O\FormatUtils.obj \
$O\FSFolder.obj \
$O\FSFolderCopy.obj \
$O\HelpUtils.obj \
$O\LangUtils.obj \
$O\MenuPage.obj \
$O\MyLoadMenu.obj \
$O\OpenCallback.obj \
$O\OptionsDialog.obj \
$O\Panel.obj \
$O\PanelCopy.obj \
$O\PanelCrc.obj \
$O\PanelDrag.obj \
$O\PanelFolderChange.obj \
$O\PanelItemOpen.obj \
$O\PanelItems.obj \
$O\PanelKey.obj \
$O\PanelListNotify.obj \
$O\PanelMenu.obj \
$O\PanelOperations.obj \
$O\PanelSelect.obj \
$O\PanelSort.obj \
$O\PanelSplitFile.obj \
$O\ProgramLocation.obj \
$O\PropertyName.obj \
$O\RegistryAssociations.obj \
$O\RegistryPlugins.obj \
$O\RegistryUtils.obj \
$O\RootFolder.obj \
$O\SplitUtils.obj \
$O\StringUtils.obj \
$O\SysIconUtils.obj \
$O\TextPairs.obj \
$O\UpdateCallback100.obj \
$O\ViewSettings.obj \
$O\AboutDialog.obj \
$O\ComboDialog.obj \
$O\CopyDialog.obj \
$O\EditDialog.obj \
$O\EditPage.obj \
$O\LangPage.obj \
$O\ListViewDialog.obj \
$O\MessagesDialog.obj \
$O\OverwriteDialog.obj \
$O\PasswordDialog.obj \
$O\ProgressDialog2.obj \
$O\SettingsPage.obj \
$O\SplitDialog.obj \
$O\SystemPage.obj \
!IFNDEF UNDER_CE
FM_OBJS = $(FM_OBJS) \
$O\AltStreamsFolder.obj \
$O\FSDrives.obj \
$O\LinkDialog.obj \
$O\NetFolder.obj \
WIN_OBJS = $(WIN_OBJS) \
$O\FileSystem.obj \
$O\Net.obj \
$O\SecurityUtils.obj \
!ENDIF
C_OBJS = $(C_OBJS) \
$O\DllSecur.obj \
AGENT_OBJS = \
$O\Agent.obj \
$O\AgentOut.obj \
$O\AgentProxy.obj \
$O\ArchiveFolder.obj \
$O\ArchiveFolderOpen.obj \
$O\ArchiveFolderOut.obj \
$O\UpdateCallbackAgent.obj \
@@ -0,0 +1,494 @@
// FSDrives.cpp
#include "StdAfx.h"
#include "../../../../C/Alloc.h"
#include "../../../Common/ComTry.h"
#include "../../../Common/Defs.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileIO.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/FileSystem.h"
#include "../../../Windows/PropVariant.h"
#include "../../PropID.h"
#include "FSDrives.h"
#include "FSFolder.h"
#include "LangUtils.h"
#include "SysIconUtils.h"
#include "resource.h"
using namespace NWindows;
using namespace NFile;
using namespace NFind;
static const char * const kVolPrefix = "\\\\.\\";
static const char * const kSuperPrefix = "\\\\?\\";
FString CDriveInfo::GetDeviceFileIoName() const
{
FString f (kVolPrefix);
f += Name;
return f;
}
struct CPhysTempBuffer
{
void *buffer;
CPhysTempBuffer(): buffer(0) {}
~CPhysTempBuffer() { MidFree(buffer); }
};
static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt64 fileSize,
UInt32 bufferSize, UInt64 progressStart, IProgress *progress)
{
NIO::CInFile inFile;
if (!inFile.Open(fromPath))
return GetLastError();
if (fileSize == (UInt64)(Int64)-1)
{
if (!inFile.GetLength(fileSize))
::GetLastError();
}
NIO::COutFile outFile;
if (writeToDisk)
{
if (!outFile.Open(toPath, FILE_SHARE_WRITE, OPEN_EXISTING, 0))
return GetLastError();
}
else
if (!outFile.Create(toPath, true))
return GetLastError();
CPhysTempBuffer tempBuffer;
tempBuffer.buffer = MidAlloc(bufferSize);
if (!tempBuffer.buffer)
return E_OUTOFMEMORY;
for (UInt64 pos = 0; pos < fileSize;)
{
UInt64 progressCur = progressStart + pos;
RINOK(progress->SetCompleted(&progressCur));
UInt64 rem = fileSize - pos;
UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize);
UInt32 processedSize;
if (!inFile.Read(tempBuffer.buffer, curSize, processedSize))
return GetLastError();
if (processedSize == 0)
break;
curSize = processedSize;
if (writeToDisk)
{
const UInt32 kMask = 0x1FF;
curSize = (curSize + kMask) & ~kMask;
if (curSize > bufferSize)
return E_FAIL;
}
if (!outFile.Write(tempBuffer.buffer, curSize, processedSize))
return GetLastError();
if (curSize != processedSize)
return E_FAIL;
pos += curSize;
}
return S_OK;
}
static const Byte kProps[] =
{
kpidName,
// kpidOutName,
kpidTotalSize,
kpidFreeSpace,
kpidType,
kpidVolumeName,
kpidFileSystem,
kpidClusterSize
};
static const char * const kDriveTypes[] =
{
"Unknown"
, "No Root Dir"
, "Removable"
, "Fixed"
, "Remote"
, "CD-ROM"
, "RAM disk"
};
STDMETHODIMP CFSDrives::LoadItems()
{
_drives.Clear();
FStringVector driveStrings;
MyGetLogicalDriveStrings(driveStrings);
FOR_VECTOR (i, driveStrings)
{
CDriveInfo di;
const FString &driveName = driveStrings[i];
di.FullSystemName = driveName;
if (!driveName.IsEmpty())
di.Name.SetFrom(driveName, driveName.Len() - 1);
di.ClusterSize = 0;
di.DriveSize = 0;
di.FreeSpace = 0;
di.DriveType = NSystem::MyGetDriveType(driveName);
bool needRead = true;
if (di.DriveType == DRIVE_CDROM || di.DriveType == DRIVE_REMOVABLE)
{
/*
DWORD dwSerialNumber;`
if (!::GetVolumeInformation(di.FullSystemName,
NULL, 0, &dwSerialNumber, NULL, NULL, NULL, 0))
*/
{
needRead = false;
}
}
if (needRead)
{
DWORD volumeSerialNumber, maximumComponentLength, fileSystemFlags;
NSystem::MyGetVolumeInformation(driveName,
di.VolumeName,
&volumeSerialNumber, &maximumComponentLength, &fileSystemFlags,
di.FileSystemName);
NSystem::MyGetDiskFreeSpace(driveName,
di.ClusterSize, di.DriveSize, di.FreeSpace);
di.KnownSizes = true;
di.KnownSize = true;
}
_drives.Add(di);
}
if (_volumeMode)
{
// we must use IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
for (unsigned n = 0; n < 16; n++) // why 16 ?
{
FString name ("PhysicalDrive");
name.Add_UInt32(n);
FString fullPath (kVolPrefix);
fullPath += name;
CFileInfo fi;
if (!fi.Find(fullPath))
continue;
CDriveInfo di;
di.Name = name;
di.FullSystemName = fullPath;
di.ClusterSize = 0;
di.DriveSize = fi.Size;
di.FreeSpace = 0;
di.DriveType = 0;
di.IsPhysicalDrive = true;
di.KnownSize = true;
_drives.Add(di);
}
}
return S_OK;
}
STDMETHODIMP CFSDrives::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _drives.Size();
return S_OK;
}
STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)
{
if (itemIndex >= (UInt32)_drives.Size())
return E_INVALIDARG;
NCOM::CPropVariant prop;
const CDriveInfo &di = _drives[itemIndex];
switch (propID)
{
case kpidIsDir: prop = !_volumeMode; break;
case kpidName: prop = di.Name; break;
case kpidOutName:
if (!di.Name.IsEmpty() && di.Name.Back() == ':')
{
FString s = di.Name;
s.DeleteBack();
AddExt(s, itemIndex);
prop = s;
}
break;
case kpidTotalSize: if (di.KnownSize) prop = di.DriveSize; break;
case kpidFreeSpace: if (di.KnownSizes) prop = di.FreeSpace; break;
case kpidClusterSize: if (di.KnownSizes) prop = di.ClusterSize; break;
case kpidType:
if (di.DriveType < ARRAY_SIZE(kDriveTypes))
prop = kDriveTypes[di.DriveType];
break;
case kpidVolumeName: prop = di.VolumeName; break;
case kpidFileSystem: prop = di.FileSystemName; break;
}
prop.Detach(value);
return S_OK;
}
HRESULT CFSDrives::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder)
{
*resultFolder = 0;
if (_volumeMode)
return S_OK;
NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;
FString path;
if (_superMode)
path = kSuperPrefix;
path += name;
RINOK(fsFolderSpec->Init(path));
*resultFolder = subFolder.Detach();
return S_OK;
}
STDMETHODIMP CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
{
*resultFolder = 0;
if (index >= (UInt32)_drives.Size())
return E_INVALIDARG;
const CDriveInfo &di = _drives[index];
/*
if (_volumeMode)
{
*resultFolder = 0;
CPhysDriveFolder *folderSpec = new CPhysDriveFolder;
CMyComPtr<IFolderFolder> subFolder = folderSpec;
RINOK(folderSpec->Init(di.Name));
*resultFolder = subFolder.Detach();
return S_OK;
}
*/
return BindToFolderSpec(di.FullSystemName, resultFolder);
}
STDMETHODIMP CFSDrives::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
{
return BindToFolderSpec(us2fs(name), resultFolder);
}
STDMETHODIMP CFSDrives::BindToParentFolder(IFolderFolder **resultFolder)
{
*resultFolder = 0;
return S_OK;
}
IMP_IFolderFolder_Props(CFSDrives)
STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
switch (propID)
{
case kpidType: prop = "FSDrives"; break;
case kpidPath:
if (_volumeMode)
prop = kVolPrefix;
else if (_superMode)
prop = kSuperPrefix;
else
prop = (UString)LangString(IDS_COMPUTER) + WCHAR_PATH_SEPARATOR;
break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
{
*iconIndex = 0;
const CDriveInfo &di = _drives[index];
if (di.IsPhysicalDrive)
return S_OK;
int iconIndexTemp;
if (GetRealIconIndex(di.FullSystemName, 0, iconIndexTemp) != 0)
{
*iconIndex = iconIndexTemp;
return S_OK;
}
return GetLastError();
}
void CFSDrives::AddExt(FString &s, unsigned index) const
{
s += '.';
const CDriveInfo &di = _drives[index];
const char *ext;
if (di.DriveType == DRIVE_CDROM)
ext = "iso";
else if (di.FileSystemName.IsPrefixedBy_Ascii_NoCase("NTFS"))
ext = "ntfs";
else if (di.FileSystemName.IsPrefixedBy_Ascii_NoCase("FAT"))
ext = "fat";
else
ext = "img";
s += ext;
}
HRESULT CFSDrives::GetFileSize(unsigned index, UInt64 &fileSize) const
{
NIO::CInFile inFile;
if (!inFile.Open(_drives[index].GetDeviceFileIoName()))
return GetLastError();
if (!inFile.SizeDefined)
return E_FAIL;
fileSize = inFile.Size;
return S_OK;
}
STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
const wchar_t *path, IFolderOperationsExtractCallback *callback)
{
if (numItems == 0)
return S_OK;
if (moveMode)
return E_NOTIMPL;
if (!_volumeMode)
return E_NOTIMPL;
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
{
const CDriveInfo &di = _drives[indices[i]];
if (di.KnownSize)
totalSize += di.DriveSize;
}
RINOK(callback->SetTotal(totalSize));
RINOK(callback->SetNumFiles(numItems));
FString destPath = us2fs(path);
if (destPath.IsEmpty())
return E_INVALIDARG;
bool isAltDest = NName::IsAltPathPrefix(destPath);
bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
if (isDirectPath)
{
if (numItems > 1)
return E_INVALIDARG;
}
UInt64 completedSize = 0;
RINOK(callback->SetCompleted(&completedSize));
for (i = 0; i < numItems; i++)
{
unsigned index = indices[i];
const CDriveInfo &di = _drives[index];
FString destPath2 = destPath;
if (!isDirectPath)
{
FString destName = di.Name;
if (!destName.IsEmpty() && destName.Back() == ':')
{
destName.DeleteBack();
AddExt(destName, index);
}
destPath2 += destName;
}
FString srcPath = di.GetDeviceFileIoName();
UInt64 fileSize = 0;
if (GetFileSize(index, fileSize) != S_OK)
{
return E_FAIL;
}
if (!di.KnownSize)
{
totalSize += fileSize;
RINOK(callback->SetTotal(totalSize));
}
Int32 writeAskResult;
CMyComBSTR destPathResult;
RINOK(callback->AskWrite(fs2us(srcPath), BoolToInt(false), NULL, &fileSize,
fs2us(destPath2), &destPathResult, &writeAskResult));
if (!IntToBool(writeAskResult))
{
if (totalSize >= fileSize)
totalSize -= fileSize;
RINOK(callback->SetTotal(totalSize));
continue;
}
RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
static const UInt32 kBufferSize = (4 << 20);
UInt32 bufferSize = (di.DriveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize;
RINOK(CopyFileSpec(srcPath, us2fs(destPathResult), false, fileSize, bufferSize, completedSize, callback));
completedSize += fileSize;
}
return S_OK;
}
STDMETHODIMP CFSDrives::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
STDMETHODIMP CFSDrives::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
STDMETHODIMP CFSDrives::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
STDMETHODIMP CFSDrives::CreateFile(const wchar_t * /* name */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
STDMETHODIMP CFSDrives::Rename(UInt32 /* index */, const wchar_t * /* newName */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
STDMETHODIMP CFSDrives::Delete(const UInt32 * /* indices */, UInt32 /* numItems */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
STDMETHODIMP CFSDrives::SetProperty(UInt32 /* index */, PROPID /* propID */,
const PROPVARIANT * /* value */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
@@ -0,0 +1,59 @@
// FSDrives.h
#ifndef __FS_DRIVES_H
#define __FS_DRIVES_H
#include "../../../Common/MyCom.h"
#include "../../../Common/MyString.h"
#include "IFolder.h"
struct CDriveInfo
{
FString Name;
FString FullSystemName;
UInt64 DriveSize;
UInt64 FreeSpace;
UInt64 ClusterSize;
// UString Type;
UString VolumeName;
UString FileSystemName;
UINT DriveType;
bool KnownSize;
bool KnownSizes;
bool IsPhysicalDrive;
FString GetDeviceFileIoName() const;
CDriveInfo(): KnownSize(false), KnownSizes(false), IsPhysicalDrive(false) {}
};
class CFSDrives:
public IFolderFolder,
public IFolderOperations,
public IFolderGetSystemIconIndex,
public CMyUnknownImp
{
CObjectVector<CDriveInfo> _drives;
bool _volumeMode;
bool _superMode;
HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder);
void AddExt(FString &s, unsigned index) const;
HRESULT GetFileSize(unsigned index, UInt64 &fileSize) const;
public:
MY_UNKNOWN_IMP2(IFolderGetSystemIconIndex, IFolderOperations)
INTERFACE_FolderFolder(;)
INTERFACE_FolderOperations(;)
STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
void Init(bool volMode = false, bool superMode = false)
{
_volumeMode = volMode;
_superMode = superMode;
}
};
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,215 @@
// FSFolder.h
#ifndef __FS_FOLDER_H
#define __FS_FOLDER_H
#include "../../../Common/MyCom.h"
#include "../../../Common/MyBuffer.h"
#include "../../../Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "IFolder.h"
#include "TextPairs.h"
namespace NFsFolder {
class CFSFolder;
#define FS_SHOW_LINKS_INFO
struct CDirItem: public NWindows::NFile::NFind::CFileInfo
{
#ifndef UNDER_CE
UInt64 PackSize;
#endif
#ifdef FS_SHOW_LINKS_INFO
UInt64 FileIndex;
UInt32 NumLinks;
bool FileInfo_Defined;
bool FileInfo_WasRequested;
#endif
#ifndef UNDER_CE
bool PackSize_Defined;
#endif
bool FolderStat_Defined;
#ifndef UNDER_CE
CByteBuffer Reparse;
#endif
UInt64 NumFolders;
UInt64 NumFiles;
int Parent;
};
/*
struct CAltStream
{
UInt64 Size;
UInt64 PackSize;
bool PackSize_Defined;
int Parent;
UString Name;
};
*/
struct CFsFolderStat
{
UInt64 NumFolders;
UInt64 NumFiles;
UInt64 Size;
IProgress *Progress;
FString Path;
CFsFolderStat(): NumFolders(0), NumFiles(0), Size(0), Progress(NULL) {}
CFsFolderStat(const FString &path, IProgress *progress = NULL):
NumFolders(0), NumFiles(0), Size(0), Progress(progress), Path(path) {}
HRESULT Enumerate();
};
class CFSFolder:
public IFolderFolder,
public IArchiveGetRawProps,
public IFolderCompare,
#ifdef USE_UNICODE_FSTRING
public IFolderGetItemName,
#endif
public IFolderWasChanged,
public IFolderOperations,
// public IFolderOperationsDeleteToRecycleBin,
public IFolderCalcItemFullSize,
public IFolderClone,
public IFolderGetSystemIconIndex,
public IFolderSetFlatMode,
// public IFolderSetShowNtfsStreamsMode,
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
MY_QUERYINTERFACE_ENTRY(IFolderCompare)
#ifdef USE_UNICODE_FSTRING
MY_QUERYINTERFACE_ENTRY(IFolderGetItemName)
#endif
MY_QUERYINTERFACE_ENTRY(IFolderWasChanged)
// MY_QUERYINTERFACE_ENTRY(IFolderOperationsDeleteToRecycleBin)
MY_QUERYINTERFACE_ENTRY(IFolderOperations)
MY_QUERYINTERFACE_ENTRY(IFolderCalcItemFullSize)
MY_QUERYINTERFACE_ENTRY(IFolderClone)
MY_QUERYINTERFACE_ENTRY(IFolderGetSystemIconIndex)
MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode)
// MY_QUERYINTERFACE_ENTRY(IFolderSetShowNtfsStreamsMode)
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_FolderFolder(;)
INTERFACE_IArchiveGetRawProps(;)
INTERFACE_FolderOperations(;)
STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
#ifdef USE_UNICODE_FSTRING
INTERFACE_IFolderGetItemName(;)
#endif
STDMETHOD(WasChanged)(Int32 *wasChanged);
STDMETHOD(Clone)(IFolderFolder **resultFolder);
STDMETHOD(CalcItemFullSize)(UInt32 index, IProgress *progress);
STDMETHOD(SetFlatMode)(Int32 flatMode);
// STDMETHOD(SetShowNtfsStreamsMode)(Int32 showStreamsMode);
STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
private:
FString _path;
CObjectVector<CDirItem> Files;
FStringVector Folders;
// CObjectVector<CAltStream> Streams;
// CMyComPtr<IFolderFolder> _parentFolder;
bool _commentsAreLoaded;
CPairsStorage _comments;
// bool _scanAltStreams;
bool _flatMode;
#ifdef _WIN32
NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;
#endif
HRESULT GetItemsFullSize(const UInt32 *indices, UInt32 numItems, CFsFolderStat &stat);
HRESULT GetItemFullSize(unsigned index, UInt64 &size, IProgress *progress);
void GetAbsPath(const wchar_t *name, FString &absPath);
HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder);
bool LoadComments();
bool SaveComments();
HRESULT LoadSubItems(int dirItem, const FString &path);
#ifdef FS_SHOW_LINKS_INFO
bool ReadFileInfo(CDirItem &di);
#endif
public:
HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */);
#if !defined(_WIN32) || defined(UNDER_CE)
HRESULT InitToRoot() { return Init((FString) FSTRING_PATH_SEPARATOR /* , NULL */); }
#endif
CFSFolder() : _flatMode(false)
// , _scanAltStreams(false)
{}
void GetFullPath(const CDirItem &item, FString &path) const
{
// FString prefix;
// GetPrefix(item, prefix);
path = _path;
if (item.Parent >= 0)
path += Folders[item.Parent];
path += item.Name;
}
// void GetPrefix(const CDirItem &item, FString &prefix) const;
FString GetRelPath(const CDirItem &item) const;
void Clear()
{
Files.Clear();
Folders.Clear();
// Streams.Clear();
}
};
struct CCopyStateIO
{
IProgress *Progress;
UInt64 TotalSize;
UInt64 StartPos;
UInt64 CurrentSize;
bool DeleteSrcFile;
int ErrorFileIndex;
UString ErrorMessage;
CCopyStateIO(): DeleteSrcFile(false), TotalSize(0), StartPos(0) {}
HRESULT MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib = INVALID_FILE_ATTRIBUTES);
};
HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName);
}
#endif
@@ -0,0 +1,670 @@
// FSFolderCopy.cpp
#include "StdAfx.h"
#include "../../../Common/MyWindows.h"
#include <Winbase.h>
#include "../../../Common/Defs.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/DLL.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "../../Common/FilePathAutoRename.h"
#include "FSFolder.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
using namespace NName;
using namespace NFind;
#ifndef _UNICODE
extern bool g_IsNT;
#endif
namespace NFsFolder {
HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib)
{
ErrorFileIndex = -1;
ErrorMessage.Empty();
CurrentSize = 0;
{
const size_t kBufSize = 1 << 16;
CByteArr buf(kBufSize);
NIO::CInFile inFile;
NIO::COutFile outFile;
if (!inFile.Open(inPath))
{
ErrorFileIndex = 0;
return S_OK;
}
if (!outFile.Create(outPath, true))
{
ErrorFileIndex = 1;
return S_OK;
}
for (;;)
{
UInt32 num;
if (!inFile.Read(buf, kBufSize, num))
{
ErrorFileIndex = 0;
return S_OK;
}
if (num == 0)
break;
UInt32 written = 0;
if (!outFile.Write(buf, num, written))
{
ErrorFileIndex = 1;
return S_OK;
}
if (written != num)
{
ErrorMessage = "Write error";
return S_OK;
}
CurrentSize += num;
if (Progress)
{
UInt64 completed = StartPos + CurrentSize;
RINOK(Progress->SetCompleted(&completed));
}
}
}
if (attrib != INVALID_FILE_ATTRIBUTES)
SetFileAttrib(outPath, attrib);
if (DeleteSrcFile)
{
if (!DeleteFileAlways(inPath))
{
ErrorFileIndex = 0;
return S_OK;
}
}
return S_OK;
}
/*
static bool IsItWindows2000orHigher()
{
OSVERSIONINFO versionInfo;
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
if (!::GetVersionEx(&versionInfo))
return false;
return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(versionInfo.dwMajorVersion >= 5);
}
*/
struct CProgressInfo
{
UInt64 TotalSize;
UInt64 StartPos;
UInt64 FileSize;
IProgress *Progress;
HRESULT ProgressResult;
void Init() { ProgressResult = S_OK; }
};
#ifndef PROGRESS_CONTINUE
#define PROGRESS_CONTINUE 0
#define PROGRESS_CANCEL 1
#define COPY_FILE_FAIL_IF_EXISTS 0x00000001
typedef
DWORD
(WINAPI* LPPROGRESS_ROUTINE)(
LARGE_INTEGER TotalFileSize,
LARGE_INTEGER TotalBytesTransferred,
LARGE_INTEGER StreamSize,
LARGE_INTEGER StreamBytesTransferred,
DWORD dwStreamNumber,
DWORD dwCallbackReason,
HANDLE hSourceFile,
HANDLE hDestinationFile,
LPVOID lpData
);
#endif
static DWORD CALLBACK CopyProgressRoutine(
LARGE_INTEGER TotalFileSize, // file size
LARGE_INTEGER TotalBytesTransferred, // bytes transferred
LARGE_INTEGER /* StreamSize */, // bytes in stream
LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream
DWORD /* dwStreamNumber */, // current stream
DWORD /* dwCallbackReason */, // callback reason
HANDLE /* hSourceFile */, // handle to source file
HANDLE /* hDestinationFile */, // handle to destination file
LPVOID lpData // from CopyFileEx
)
{
// StreamSize = StreamSize;
// StreamBytesTransferred = StreamBytesTransferred;
// dwStreamNumber = dwStreamNumber;
// dwCallbackReason = dwCallbackReason;
CProgressInfo &pi = *(CProgressInfo *)lpData;
if ((UInt64)TotalFileSize.QuadPart > pi.FileSize)
{
pi.TotalSize += (UInt64)TotalFileSize.QuadPart - pi.FileSize;
pi.FileSize = (UInt64)TotalFileSize.QuadPart;
pi.ProgressResult = pi.Progress->SetTotal(pi.TotalSize);
}
UInt64 completed = pi.StartPos + TotalBytesTransferred.QuadPart;
pi.ProgressResult = pi.Progress->SetCompleted(&completed);
return (pi.ProgressResult == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL);
}
typedef BOOL (WINAPI * Func_CopyFileExA)(
IN LPCSTR lpExistingFileName,
IN LPCSTR lpNewFileName,
IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
IN LPVOID lpData OPTIONAL,
IN LPBOOL pbCancel OPTIONAL,
IN DWORD dwCopyFlags
);
typedef BOOL (WINAPI * Func_CopyFileExW)(
IN LPCWSTR lpExistingFileName,
IN LPCWSTR lpNewFileName,
IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
IN LPVOID lpData OPTIONAL,
IN LPBOOL pbCancel OPTIONAL,
IN DWORD dwCopyFlags
);
typedef BOOL (WINAPI * Func_MoveFileWithProgressW)(
IN LPCWSTR lpExistingFileName,
IN LPCWSTR lpNewFileName,
IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
IN LPVOID lpData OPTIONAL,
IN DWORD dwFlags
);
struct CCopyState
{
CProgressInfo ProgressInfo;
IFolderOperationsExtractCallback *Callback;
bool MoveMode;
bool UseReadWriteMode;
Func_CopyFileExW my_CopyFileExW;
#ifndef UNDER_CE
Func_MoveFileWithProgressW my_MoveFileWithProgressW;
#endif
#ifndef _UNICODE
Func_CopyFileExA my_CopyFileExA;
#endif
void Prepare();
bool CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile);
bool CopyFile_Sys(CFSTR oldFile, CFSTR newFile);
bool MoveFile_Sys(CFSTR oldFile, CFSTR newFile);
HRESULT CallProgress();
bool IsCallbackProgressError() { return ProgressInfo.ProgressResult != S_OK; }
};
HRESULT CCopyState::CallProgress()
{
return ProgressInfo.Progress->SetCompleted(&ProgressInfo.StartPos);
}
void CCopyState::Prepare()
{
my_CopyFileExW = NULL;
#ifndef UNDER_CE
my_MoveFileWithProgressW = NULL;
#endif
#ifndef _UNICODE
my_CopyFileExA = NULL;
if (!g_IsNT)
{
my_CopyFileExA = (Func_CopyFileExA)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "CopyFileExA");
}
else
#endif
{
HMODULE module = ::GetModuleHandleW(
#ifdef UNDER_CE
L"coredll.dll"
#else
L"kernel32.dll"
#endif
);
my_CopyFileExW = (Func_CopyFileExW)My_GetProcAddress(module, "CopyFileExW");
#ifndef UNDER_CE
my_MoveFileWithProgressW = (Func_MoveFileWithProgressW)My_GetProcAddress(module, "MoveFileWithProgressW");
#endif
}
}
/* WinXP-64:
CopyFileW(fromFile, toFile:altStream)
OK - there are NO alt streams in fromFile
ERROR_INVALID_PARAMETER - there are alt streams in fromFile
*/
bool CCopyState::CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile)
{
BOOL cancelFlag = FALSE;
if (my_CopyFileExW)
return BOOLToBool(my_CopyFileExW(oldFile, newFile, CopyProgressRoutine,
&ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS));
return BOOLToBool(::CopyFileW(oldFile, newFile, TRUE));
}
bool CCopyState::CopyFile_Sys(CFSTR oldFile, CFSTR newFile)
{
#ifndef _UNICODE
if (!g_IsNT)
{
if (my_CopyFileExA)
{
BOOL cancelFlag = FALSE;
if (my_CopyFileExA(fs2fas(oldFile), fs2fas(newFile),
CopyProgressRoutine, &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS))
return true;
if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
return false;
}
return BOOLToBool(::CopyFile(fs2fas(oldFile), fs2fas(newFile), TRUE));
}
else
#endif
{
IF_USE_MAIN_PATH_2(oldFile, newFile)
{
if (CopyFile_NT(fs2us(oldFile), fs2us(newFile)))
return true;
}
#ifdef WIN_LONG_PATH
if (USE_SUPER_PATH_2)
{
if (IsCallbackProgressError())
return false;
UString superPathOld, superPathNew;
if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
return false;
if (CopyFile_NT(superPathOld, superPathNew))
return true;
}
#endif
return false;
}
}
bool CCopyState::MoveFile_Sys(CFSTR oldFile, CFSTR newFile)
{
#ifndef UNDER_CE
// if (IsItWindows2000orHigher())
// {
if (my_MoveFileWithProgressW)
{
IF_USE_MAIN_PATH_2(oldFile, newFile)
{
if (my_MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine,
&ProgressInfo, MOVEFILE_COPY_ALLOWED))
return true;
}
#ifdef WIN_LONG_PATH
if ((!(USE_MAIN_PATH_2) || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) && USE_SUPER_PATH_2)
{
if (IsCallbackProgressError())
return false;
UString superPathOld, superPathNew;
if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
return false;
if (my_MoveFileWithProgressW(superPathOld, superPathNew, CopyProgressRoutine,
&ProgressInfo, MOVEFILE_COPY_ALLOWED))
return true;
}
#endif
if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
return false;
}
// }
// else
#endif
return MyMoveFile(oldFile, newFile);
}
static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
const wchar_t *message, const FString &fileName)
{
UString s = message;
s += " : ";
s += fs2us(fileName);
return callback->ShowMessage(s);
}
static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
const char *message, const FString &fileName)
{
return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
}
static DWORD Return_LastError_or_FAIL()
{
DWORD errorCode = GetLastError();
if (errorCode == 0)
errorCode = (DWORD)E_FAIL;
return errorCode;
}
static UString GetLastErrorMessage()
{
return NError::MyFormatMessage(Return_LastError_or_FAIL());
}
HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName)
{
return SendMessageError(callback, GetLastErrorMessage(), fileName);
}
static HRESULT CopyFile_Ask(
CCopyState &state,
const FString &srcPath,
const CFileInfo &srcFileInfo,
const FString &destPath)
{
if (CompareFileNames(destPath, srcPath) == 0)
{
RINOK(SendMessageError(state.Callback,
state.MoveMode ?
"can not move file onto itself" :
"can not copy file onto itself"
, destPath));
return E_ABORT;
}
Int32 writeAskResult;
CMyComBSTR destPathResult;
RINOK(state.Callback->AskWrite(
fs2us(srcPath),
BoolToInt(false),
&srcFileInfo.MTime, &srcFileInfo.Size,
fs2us(destPath),
&destPathResult,
&writeAskResult));
if (IntToBool(writeAskResult))
{
FString destPathNew = us2fs((LPCOLESTR)destPathResult);
RINOK(state.Callback->SetCurrentFilePath(fs2us(srcPath)));
if (state.UseReadWriteMode)
{
NFsFolder::CCopyStateIO state2;
state2.Progress = state.Callback;
state2.DeleteSrcFile = state.MoveMode;
state2.TotalSize = state.ProgressInfo.TotalSize;
state2.StartPos = state.ProgressInfo.StartPos;
RINOK(state2.MyCopyFile(srcPath, destPathNew, srcFileInfo.Attrib));
if (state2.ErrorFileIndex >= 0)
{
if (state2.ErrorMessage.IsEmpty())
state2.ErrorMessage = GetLastErrorMessage();
FString errorName;
if (state2.ErrorFileIndex == 0)
errorName = srcPath;
else
errorName = destPathNew;
RINOK(SendMessageError(state.Callback, state2.ErrorMessage, errorName));
return E_ABORT;
}
state.ProgressInfo.StartPos += state2.CurrentSize;
}
else
{
state.ProgressInfo.FileSize = srcFileInfo.Size;
bool res;
if (state.MoveMode)
res = state.MoveFile_Sys(srcPath, destPathNew);
else
res = state.CopyFile_Sys(srcPath, destPathNew);
RINOK(state.ProgressInfo.ProgressResult);
if (!res)
{
// GetLastError() is ERROR_REQUEST_ABORTED in case of PROGRESS_CANCEL.
RINOK(SendMessageError(state.Callback, GetLastErrorMessage(), destPathNew));
return E_ABORT;
}
state.ProgressInfo.StartPos += state.ProgressInfo.FileSize;
}
}
else
{
if (state.ProgressInfo.TotalSize >= srcFileInfo.Size)
{
state.ProgressInfo.TotalSize -= srcFileInfo.Size;
RINOK(state.ProgressInfo.Progress->SetTotal(state.ProgressInfo.TotalSize));
}
}
return state.CallProgress();
}
static FString CombinePath(const FString &folderPath, const FString &fileName)
{
return folderPath + FCHAR_PATH_SEPARATOR + fileName;
}
static bool IsDestChild(const FString &src, const FString &dest)
{
unsigned len = src.Len();
if (dest.Len() < len)
return false;
if (dest.Len() != len && dest[len] != FCHAR_PATH_SEPARATOR)
return false;
return CompareFileNames(dest.Left(len), src) == 0;
}
static HRESULT CopyFolder(
CCopyState &state,
const FString &srcPath, // without TAIL separator
const FString &destPath) // without TAIL separator
{
RINOK(state.CallProgress());
if (IsDestChild(srcPath, destPath))
{
RINOK(SendMessageError(state.Callback,
state.MoveMode ?
"can not copy folder onto itself" :
"can not move folder onto itself"
, destPath));
return E_ABORT;
}
if (state.MoveMode)
{
if (state.MoveFile_Sys(srcPath, destPath))
return S_OK;
// MSDN: MoveFile() fails for dirs on different volumes.
}
if (!CreateComplexDir(destPath))
{
RINOK(SendMessageError(state.Callback, "can not create folder", destPath));
return E_ABORT;
}
CEnumerator enumerator;
enumerator.SetDirPrefix(CombinePath(srcPath, FString()));
for (;;)
{
NFind::CFileInfo fi;
bool found;
if (!enumerator.Next(fi, found))
{
SendLastErrorMessage(state.Callback, srcPath);
return S_OK;
}
if (!found)
break;
const FString srcPath2 = CombinePath(srcPath, fi.Name);
const FString destPath2 = CombinePath(destPath, fi.Name);
if (fi.IsDir())
{
RINOK(CopyFolder(state, srcPath2, destPath2))
}
else
{
RINOK(CopyFile_Ask(state, srcPath2, fi, destPath2));
}
}
if (state.MoveMode)
{
if (!RemoveDir(srcPath))
{
RINOK(SendMessageError(state.Callback, "can not remove folder", srcPath));
return E_ABORT;
}
}
return S_OK;
}
STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
const wchar_t *path, IFolderOperationsExtractCallback *callback)
{
if (numItems == 0)
return S_OK;
FString destPath = us2fs(path);
if (destPath.IsEmpty())
return E_INVALIDARG;
bool isAltDest = NName::IsAltPathPrefix(destPath);;
bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
if (isDirectPath)
{
if (numItems > 1)
return E_INVALIDARG;
}
CFsFolderStat stat;
stat.Progress = callback;
RINOK(GetItemsFullSize(indices, numItems, stat));
if (stat.NumFolders != 0 && isAltDest)
return E_NOTIMPL;
RINOK(callback->SetTotal(stat.Size));
RINOK(callback->SetNumFiles(stat.NumFiles));
UInt64 completedSize = 0;
RINOK(callback->SetCompleted(&completedSize));
CCopyState state;
state.ProgressInfo.TotalSize = stat.Size;
state.ProgressInfo.StartPos = 0;
state.ProgressInfo.Progress = callback;
state.ProgressInfo.Init();
state.Callback = callback;
state.MoveMode = IntToBool(moveMode);
state.UseReadWriteMode = isAltDest;
state.Prepare();
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 index = indices[i];
if (index >= (UInt32)Files.Size())
continue;
const CDirItem &fi = Files[index];
FString destPath2 = destPath;
if (!isDirectPath)
destPath2 += fi.Name;
FString srcPath;
GetFullPath(fi, srcPath);
if (fi.IsDir())
{
RINOK(CopyFolder(state, srcPath, destPath2));
}
else
{
RINOK(CopyFile_Ask(state, srcPath, fi, destPath2));
}
}
return S_OK;
}
STDMETHODIMP CFSFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
{
/*
UInt64 numFolders, numFiles, totalSize;
numFiles = numFolders = totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
{
UString path = (UString)fromFolderPath + itemsPaths[i];
CFileInfo fi;
if (!FindFile(path, fi))
return ::GetLastError();
if (fi.IsDir())
{
UInt64 subFolders, subFiles, subSize;
RINOK(GetFolderSize(CombinePath(path, fi.Name), subFolders, subFiles, subSize, progress));
numFolders += subFolders;
numFolders++;
numFiles += subFiles;
totalSize += subSize;
}
else
{
numFiles++;
totalSize += fi.Size;
}
}
RINOK(progress->SetTotal(totalSize));
RINOK(callback->SetNumFiles(numFiles));
for (i = 0; i < numItems; i++)
{
UString path = (UString)fromFolderPath + itemsPaths[i];
}
return S_OK;
*/
return E_NOTIMPL;
}
STDMETHODIMP CFSFolder::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */)
{
return E_NOTIMPL;
}
}
@@ -0,0 +1,183 @@
// FileFolderPluginOpen.cpp
#include "StdAfx.h"
#include "resource.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/Thread.h"
#include "../Agent/Agent.h"
#include "LangUtils.h"
#include "OpenCallback.h"
#include "PluginLoader.h"
#include "RegistryPlugins.h"
using namespace NWindows;
struct CThreadArchiveOpen
{
UString Path;
UString ArcFormat;
CMyComPtr<IInStream> InStream;
CMyComPtr<IFolderManager> FolderManager;
CMyComPtr<IProgress> OpenCallback;
COpenArchiveCallback *OpenCallbackSpec;
CMyComPtr<IFolderFolder> Folder;
HRESULT Result;
void Process()
{
try
{
CProgressCloser closer(OpenCallbackSpec->ProgressDialog);
Result = FolderManager->OpenFolderFile(InStream, Path, ArcFormat, &Folder, OpenCallback);
}
catch(...) { Result = E_FAIL; }
}
static THREAD_FUNC_DECL MyThreadFunction(void *param)
{
((CThreadArchiveOpen *)param)->Process();
return 0;
}
};
/*
static int FindPlugin(const CObjectVector<CPluginInfo> &plugins, const UString &pluginName)
{
for (int i = 0; i < plugins.Size(); i++)
if (plugins[i].Name.CompareNoCase(pluginName) == 0)
return i;
return -1;
}
*/
static void SplitNameToPureNameAndExtension(const FString &fullName,
FString &pureName, FString &extensionDelimiter, FString &extension)
{
int index = fullName.ReverseFind_Dot();
if (index < 0)
{
pureName = fullName;
extensionDelimiter.Empty();
extension.Empty();
}
else
{
pureName.SetFrom(fullName, index);
extensionDelimiter = '.';
extension = fullName.Ptr(index + 1);
}
}
HRESULT OpenFileFolderPlugin(
IInStream *inStream,
const FString &path,
const UString &arcFormat,
HMODULE *module,
IFolderFolder **resultFolder,
HWND parentWindow,
bool &encrypted, UString &password)
{
CObjectVector<CPluginInfo> plugins;
ReadFileFolderPluginInfoList(plugins);
FString extension, name, pureName, dot;
int slashPos = path.ReverseFind_PathSepar();
FString dirPrefix;
FString fileName;
if (slashPos >= 0)
{
dirPrefix.SetFrom(path, slashPos + 1);
fileName = path.Ptr(slashPos + 1);
}
else
fileName = path;
SplitNameToPureNameAndExtension(fileName, pureName, dot, extension);
/*
if (!extension.IsEmpty())
{
CExtInfo extInfo;
if (ReadInternalAssociation(extension, extInfo))
{
for (int i = extInfo.Plugins.Size() - 1; i >= 0; i--)
{
int pluginIndex = FindPlugin(plugins, extInfo.Plugins[i]);
if (pluginIndex >= 0)
{
const CPluginInfo plugin = plugins[pluginIndex];
plugins.Delete(pluginIndex);
plugins.Insert(0, plugin);
}
}
}
}
*/
FOR_VECTOR (i, plugins)
{
const CPluginInfo &plugin = plugins[i];
if (!plugin.ClassIDDefined)
continue;
CPluginLibrary library;
CThreadArchiveOpen t;
if (plugin.FilePath.IsEmpty())
t.FolderManager = new CArchiveFolderManager;
else if (library.LoadAndCreateManager(plugin.FilePath, plugin.ClassID, &t.FolderManager) != S_OK)
continue;
t.OpenCallbackSpec = new COpenArchiveCallback;
t.OpenCallback = t.OpenCallbackSpec;
t.OpenCallbackSpec->PasswordIsDefined = encrypted;
t.OpenCallbackSpec->Password = password;
t.OpenCallbackSpec->ParentWindow = parentWindow;
if (inStream)
t.OpenCallbackSpec->SetSubArchiveName(fs2us(fileName));
else
t.OpenCallbackSpec->LoadFileInfo(dirPrefix, fileName);
t.InStream = inStream;
t.Path = fs2us(path);
t.ArcFormat = arcFormat;
UString progressTitle = LangString(IDS_OPENNING);
t.OpenCallbackSpec->ProgressDialog.MainWindow = parentWindow;
t.OpenCallbackSpec->ProgressDialog.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE);
t.OpenCallbackSpec->ProgressDialog.MainAddTitle = progressTitle + L' ';
t.OpenCallbackSpec->ProgressDialog.WaitMode = true;
{
NWindows::CThread thread;
RINOK(thread.Create(CThreadArchiveOpen::MyThreadFunction, &t));
t.OpenCallbackSpec->StartProgressDialog(progressTitle, thread);
}
if (t.Result == E_ABORT)
return t.Result;
encrypted = t.OpenCallbackSpec->PasswordIsDefined;
if (t.Result == S_OK)
{
// if (openCallbackSpec->PasswordWasAsked)
{
password = t.OpenCallbackSpec->Password;
}
*module = library.Detach();
*resultFolder = t.Folder.Detach();
return S_OK;
}
if (t.Result != S_FALSE)
return t.Result;
}
return S_FALSE;
}
@@ -0,0 +1,9 @@
// FileFolderPluginOpen.h
#ifndef __FILE_FOLDER_PLUGIN_OPEN_H
#define __FILE_FOLDER_PLUGIN_OPEN_H
HRESULT OpenFileFolderPlugin(IInStream *inStream, const FString &path, const UString &arcFormat,
HMODULE *module, IFolderFolder **resultFolder, HWND parentWindow, bool &encrypted, UString &password);
#endif
@@ -0,0 +1,69 @@
// FilePlugins.cpp
#include "StdAfx.h"
#include "../Agent/Agent.h"
#include "FilePlugins.h"
#include "PluginLoader.h"
#include "StringUtils.h"
int CExtDatabase::FindExt(const UString &ext)
{
FOR_VECTOR (i, Exts)
if (Exts[i].Ext.IsEqualTo_NoCase(ext))
return i;
return -1;
}
void CExtDatabase::Read()
{
ReadFileFolderPluginInfoList(Plugins);
FOR_VECTOR (pluginIndex, Plugins)
{
const CPluginInfo &plugin = Plugins[pluginIndex];
CPluginLibrary pluginLib;
CMyComPtr<IFolderManager> folderManager;
if (plugin.FilePath.IsEmpty())
folderManager = new CArchiveFolderManager;
else if (pluginLib.LoadAndCreateManager(plugin.FilePath, plugin.ClassID, &folderManager) != S_OK)
continue;
CMyComBSTR extBSTR;
if (folderManager->GetExtensions(&extBSTR) != S_OK)
return;
UStringVector exts;
SplitString((const wchar_t *)extBSTR, exts);
FOR_VECTOR (i, exts)
{
const UString &ext = exts[i];
#ifdef UNDER_CE
if (ext == L"cab")
continue;
#endif
Int32 iconIndex;
CMyComBSTR iconPath;
CPluginToIcon plugPair;
plugPair.PluginIndex = pluginIndex;
if (folderManager->GetIconPath(ext, &iconPath, &iconIndex) == S_OK)
if (iconPath != 0)
{
plugPair.IconPath = (const wchar_t *)iconPath;
plugPair.IconIndex = iconIndex;
}
int index = FindExt(ext);
if (index >= 0)
Exts[index].Plugins.Add(plugPair);
else
{
CExtPlugins extInfo;
extInfo.Plugins.Add(plugPair);
extInfo.Ext = ext;
Exts.Add(extInfo);
}
}
}
}
@@ -0,0 +1,33 @@
// FilePlugins.h
#ifndef __FILE_PLUGINS_H
#define __FILE_PLUGINS_H
#include "RegistryPlugins.h"
struct CPluginToIcon
{
int PluginIndex;
UString IconPath;
int IconIndex;
CPluginToIcon(): IconIndex(-1) {}
};
struct CExtPlugins
{
UString Ext;
CObjectVector<CPluginToIcon> Plugins;
};
class CExtDatabase
{
int FindExt(const UString &ext);
public:
CObjectVector<CExtPlugins> Exts;
CObjectVector<CPluginInfo> Plugins;
void Read();
};
#endif
@@ -0,0 +1,166 @@
// FoldersPage.cpp
#include "StdAfx.h"
#include "FoldersPageRes.h"
#include "FoldersPage.h"
#include "../FileManager/BrowseDialog.h"
#include "../FileManager/HelpUtils.h"
#include "../FileManager/LangUtils.h"
using namespace NWindows;
static const UInt32 kLangIDs[] =
{
IDT_FOLDERS_WORKING_FOLDER,
IDR_FOLDERS_WORK_SYSTEM,
IDR_FOLDERS_WORK_CURRENT,
IDR_FOLDERS_WORK_SPECIFIED,
IDX_FOLDERS_WORK_FOR_REMOVABLE
};
static const int kWorkModeButtons[] =
{
IDR_FOLDERS_WORK_SYSTEM,
IDR_FOLDERS_WORK_CURRENT,
IDR_FOLDERS_WORK_SPECIFIED
};
#define kFoldersTopic "fm/options.htm#folders"
static const unsigned kNumWorkModeButtons = ARRAY_SIZE(kWorkModeButtons);
bool CFoldersPage::OnInit()
{
_initMode = true;
_needSave = false;
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
m_WorkDirInfo.Load();
CheckButton(IDX_FOLDERS_WORK_FOR_REMOVABLE, m_WorkDirInfo.ForRemovableOnly);
CheckRadioButton(kWorkModeButtons[0], kWorkModeButtons[kNumWorkModeButtons - 1],
kWorkModeButtons[m_WorkDirInfo.Mode]);
m_WorkPath.Init(*this, IDE_FOLDERS_WORK_PATH);
m_WorkPath.SetText(fs2us(m_WorkDirInfo.Path));
MyEnableControls();
_initMode = false;
return CPropertyPage::OnInit();
}
int CFoldersPage::GetWorkMode() const
{
for (unsigned i = 0; i < kNumWorkModeButtons; i++)
if (IsButtonCheckedBool(kWorkModeButtons[i]))
return i;
throw 0;
}
void CFoldersPage::MyEnableControls()
{
bool enablePath = (GetWorkMode() == NWorkDir::NMode::kSpecified);
m_WorkPath.Enable(enablePath);
EnableItem(IDB_FOLDERS_WORK_PATH, enablePath);
}
void CFoldersPage::GetWorkDir(NWorkDir::CInfo &workDirInfo)
{
UString s;
m_WorkPath.GetText(s);
workDirInfo.Path = us2fs(s);
workDirInfo.ForRemovableOnly = IsButtonCheckedBool(IDX_FOLDERS_WORK_FOR_REMOVABLE);
workDirInfo.Mode = NWorkDir::NMode::EEnum(GetWorkMode());
}
/*
bool CFoldersPage::WasChanged()
{
NWorkDir::CInfo workDirInfo;
GetWorkDir(workDirInfo);
return (workDirInfo.Mode != m_WorkDirInfo.Mode ||
workDirInfo.ForRemovableOnly != m_WorkDirInfo.ForRemovableOnly ||
workDirInfo.Path.Compare(m_WorkDirInfo.Path) != 0);
}
*/
void CFoldersPage::ModifiedEvent()
{
if (!_initMode)
{
_needSave = true;
Changed();
}
/*
if (WasChanged())
Changed();
else
UnChanged();
*/
}
bool CFoldersPage::OnButtonClicked(int buttonID, HWND buttonHWND)
{
for (unsigned i = 0; i < kNumWorkModeButtons; i++)
if (buttonID == kWorkModeButtons[i])
{
MyEnableControls();
ModifiedEvent();
return true;
}
switch (buttonID)
{
case IDB_FOLDERS_WORK_PATH:
OnFoldersWorkButtonPath();
return true;
case IDX_FOLDERS_WORK_FOR_REMOVABLE:
break;
default:
return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
}
ModifiedEvent();
return true;
}
bool CFoldersPage::OnCommand(int code, int itemID, LPARAM lParam)
{
if (code == EN_CHANGE && itemID == IDE_FOLDERS_WORK_PATH)
{
ModifiedEvent();
return true;
}
return CPropertyPage::OnCommand(code, itemID, lParam);
}
void CFoldersPage::OnFoldersWorkButtonPath()
{
UString currentPath;
m_WorkPath.GetText(currentPath);
UString title = LangString(IDS_FOLDERS_SET_WORK_PATH_TITLE);
UString resultPath;
if (MyBrowseForFolder(*this, title, currentPath, resultPath))
m_WorkPath.SetText(resultPath);
}
LONG CFoldersPage::OnApply()
{
if (_needSave)
{
GetWorkDir(m_WorkDirInfo);
m_WorkDirInfo.Save();
_needSave = false;
}
return PSNRET_NOERROR;
}
void CFoldersPage::OnNotifyHelp()
{
ShowHelpWindow(kFoldersTopic);
}
@@ -0,0 +1,32 @@
// FoldersPage.h
#ifndef __FOLDERS_PAGE_H
#define __FOLDERS_PAGE_H
#include "../../../Windows/Control/PropertyPage.h"
#include "../Common/ZipRegistry.h"
class CFoldersPage : public NWindows::NControl::CPropertyPage
{
NWorkDir::CInfo m_WorkDirInfo;
NWindows::NControl::CDialogChildControl m_WorkPath;
bool _needSave;
bool _initMode;
void MyEnableControls();
void ModifiedEvent();
void OnFoldersWorkButtonPath();
int GetWorkMode() const;
void GetWorkDir(NWorkDir::CInfo &workDirInfo);
// bool WasChanged();
virtual bool OnInit();
virtual bool OnCommand(int code, int itemID, LPARAM lParam);
virtual void OnNotifyHelp();
virtual LONG OnApply();
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
};
#endif
@@ -0,0 +1,23 @@
#include "FoldersPageRes.h"
#include "../../GuiCommon.rc"
#define xc 240
#define yc 100
IDD_FOLDERS MY_PAGE
#include "FoldersPage2.rc"
#ifdef UNDER_CE
#undef xc
#define xc SMALL_PAGE_SIZE_X
IDD_FOLDERS_2 MY_PAGE
#include "FoldersPage2.rc"
#endif
STRINGTABLE
BEGIN
IDS_FOLDERS_SET_WORK_PATH_TITLE "Specify a location for temporary archive files."
END
@@ -0,0 +1,16 @@
CAPTION "Folders"
BEGIN
// GROUPBOX "&Working folder", IDT_FOLDERS_WORKING_FOLDER, m, m, xc, 98
LTEXT "&Working folder", IDT_FOLDERS_WORKING_FOLDER, m, m, xc, 8
CONTROL "&System temp folder", IDR_FOLDERS_WORK_SYSTEM, "Button", BS_AUTORADIOBUTTON | WS_GROUP,
m, 20, xc, 10
CONTROL "&Current", IDR_FOLDERS_WORK_CURRENT, "Button", BS_AUTORADIOBUTTON,
m, 34, xc, 10
CONTROL "Specified:", IDR_FOLDERS_WORK_SPECIFIED, "Button", BS_AUTORADIOBUTTON,
m, 48, xc, 10
EDITTEXT IDE_FOLDERS_WORK_PATH, m + m, 62, xc - m - m - bxsDots, 14, ES_AUTOHSCROLL
PUSHBUTTON "...", IDB_FOLDERS_WORK_PATH, xs - m - bxsDots, 61, bxsDots, bys
CONTROL "Use for removable drives only", IDX_FOLDERS_WORK_FOR_REMOVABLE, MY_CHECKBOX,
m, 86, xc, 10
END
@@ -0,0 +1,12 @@
#define IDD_FOLDERS 2400
#define IDD_FOLDERS_2 12400
#define IDT_FOLDERS_WORKING_FOLDER 2401
#define IDR_FOLDERS_WORK_SYSTEM 2402
#define IDR_FOLDERS_WORK_CURRENT 2403
#define IDR_FOLDERS_WORK_SPECIFIED 2404
#define IDX_FOLDERS_WORK_FOR_REMOVABLE 2405
#define IDS_FOLDERS_SET_WORK_PATH_TITLE 2406
#define IDE_FOLDERS_WORK_PATH 100
#define IDB_FOLDERS_WORK_PATH 101
@@ -0,0 +1,28 @@
// FormatUtils.cpp
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "FormatUtils.h"
#include "LangUtils.h"
UString NumberToString(UInt64 number)
{
wchar_t numberString[32];
ConvertUInt64ToString(number, numberString);
return numberString;
}
UString MyFormatNew(const UString &format, const UString &argument)
{
UString result = format;
result.Replace(L"{0}", argument);
return result;
}
UString MyFormatNew(UINT resourceID, const UString &argument)
{
return MyFormatNew(LangString(resourceID), argument);
}
@@ -0,0 +1,14 @@
// FormatUtils.h
#ifndef __FORMAT_UTILS_H
#define __FORMAT_UTILS_H
#include "../../../Common/MyTypes.h"
#include "../../../Common/MyString.h"
UString NumberToString(UInt64 number);
UString MyFormatNew(const UString &format, const UString &argument);
UString MyFormatNew(UINT resourceID, const UString &argument);
#endif
@@ -0,0 +1,32 @@
// HelpUtils.cpp
#include "StdAfx.h"
#include "HelpUtils.h"
#if defined(UNDER_CE) || !defined(_WIN32)
void ShowHelpWindow(LPCSTR)
{
}
#else
#include <HtmlHelp.h>
#include "../../../Common/StringConvert.h"
#include "../../../Windows/DLL.h"
#define kHelpFileName "7-zip.chm::/"
void ShowHelpWindow(LPCSTR topicFile)
{
FString path = NWindows::NDLL::GetModuleDirPrefix();
path += kHelpFileName;
path += topicFile;
// HWND hwnd = NULL;
HtmlHelp(NULL, GetSystemString(fs2us(path)), HH_DISPLAY_TOPIC, 0);
}
#endif
@@ -0,0 +1,10 @@
// HelpUtils.h
#ifndef __HELP_UTILS_H
#define __HELP_UTILS_H
#include "../../../Common/MyString.h"
void ShowHelpWindow(LPCSTR topicFile);
#endif
@@ -0,0 +1,218 @@
// IFolder.h
#ifndef __IFOLDER_H
#define __IFOLDER_H
#include "../../IProgress.h"
#include "../../IStream.h"
#define FOLDER_INTERFACE_SUB(i, b, x) DECL_INTERFACE_SUB(i, b, 8, x)
#define FOLDER_INTERFACE(i, x) FOLDER_INTERFACE_SUB(i, IUnknown, x)
namespace NPlugin
{
enum
{
kName = 0,
kType,
kClassID,
kOptionsClassID
};
}
#define INTERFACE_FolderFolder(x) \
STDMETHOD(LoadItems)() x; \
STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \
STDMETHOD(GetProperty)(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(BindToFolder)(UInt32 index, IFolderFolder **resultFolder) x; \
STDMETHOD(BindToFolder)(const wchar_t *name, IFolderFolder **resultFolder) x; \
STDMETHOD(BindToParentFolder)(IFolderFolder **resultFolder) x; \
STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
STDMETHOD(GetFolderProperty)(PROPID propID, PROPVARIANT *value) x; \
FOLDER_INTERFACE(IFolderFolder, 0x00)
{
INTERFACE_FolderFolder(PURE)
};
/*
IFolderAltStreams::
BindToAltStreams((UInt32)(Int32)-1, ... ) means alt streams of that folder
*/
#define INTERFACE_FolderAltStreams(x) \
STDMETHOD(BindToAltStreams)(UInt32 index, IFolderFolder **resultFolder) x; \
STDMETHOD(BindToAltStreams)(const wchar_t *name, IFolderFolder **resultFolder) x; \
STDMETHOD(AreAltStreamsSupported)(UInt32 index, Int32 *isSupported) x; \
FOLDER_INTERFACE(IFolderAltStreams, 0x17)
{
INTERFACE_FolderAltStreams(PURE)
};
FOLDER_INTERFACE(IFolderWasChanged, 0x04)
{
STDMETHOD(WasChanged)(Int32 *wasChanged) PURE;
};
FOLDER_INTERFACE_SUB(IFolderOperationsExtractCallback, IProgress, 0x0B)
{
// STDMETHOD(SetTotalFiles)(UInt64 total) PURE;
// STDMETHOD(SetCompletedFiles)(const UInt64 *completedValue) PURE;
STDMETHOD(AskWrite)(
const wchar_t *srcPath,
Int32 srcIsFolder,
const FILETIME *srcTime,
const UInt64 *srcSize,
const wchar_t *destPathRequest,
BSTR *destPathResult,
Int32 *writeAnswer) PURE;
STDMETHOD(ShowMessage)(const wchar_t *message) PURE;
STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath) PURE;
STDMETHOD(SetNumFiles)(UInt64 numFiles) PURE;
};
#define INTERFACE_FolderOperations(x) \
STDMETHOD(CreateFolder)(const wchar_t *name, IProgress *progress) x; \
STDMETHOD(CreateFile)(const wchar_t *name, IProgress *progress) x; \
STDMETHOD(Rename)(UInt32 index, const wchar_t *newName, IProgress *progress) x; \
STDMETHOD(Delete)(const UInt32 *indices, UInt32 numItems, IProgress *progress) x; \
STDMETHOD(CopyTo)(Int32 moveMode, const UInt32 *indices, UInt32 numItems, \
Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, \
const wchar_t *path, IFolderOperationsExtractCallback *callback) x; \
STDMETHOD(CopyFrom)(Int32 moveMode, const wchar_t *fromFolderPath, \
const wchar_t * const *itemsPaths, UInt32 numItems, IProgress *progress) x; \
STDMETHOD(SetProperty)(UInt32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress) x; \
STDMETHOD(CopyFromFile)(UInt32 index, const wchar_t *fullFilePath, IProgress *progress) x; \
FOLDER_INTERFACE(IFolderOperations, 0x13)
{
INTERFACE_FolderOperations(PURE)
};
/*
FOLDER_INTERFACE2(IFolderOperationsDeleteToRecycleBin, 0x06, 0x03)
{
STDMETHOD(DeleteToRecycleBin)(const UInt32 *indices, UInt32 numItems, IProgress *progress) PURE;
};
*/
FOLDER_INTERFACE(IFolderGetSystemIconIndex, 0x07)
{
STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex) PURE;
};
FOLDER_INTERFACE(IFolderGetItemFullSize, 0x08)
{
STDMETHOD(GetItemFullSize)(UInt32 index, PROPVARIANT *value, IProgress *progress) PURE;
};
FOLDER_INTERFACE(IFolderCalcItemFullSize, 0x14)
{
STDMETHOD(CalcItemFullSize)(UInt32 index, IProgress *progress) PURE;
};
FOLDER_INTERFACE(IFolderClone, 0x09)
{
STDMETHOD(Clone)(IFolderFolder **resultFolder) PURE;
};
FOLDER_INTERFACE(IFolderSetFlatMode, 0x0A)
{
STDMETHOD(SetFlatMode)(Int32 flatMode) PURE;
};
/*
FOLDER_INTERFACE(IFolderSetShowNtfsStreamsMode, 0xFA)
{
STDMETHOD(SetShowNtfsStreamsMode)(Int32 showStreamsMode) PURE;
};
*/
#define INTERFACE_FolderProperties(x) \
STDMETHOD(GetNumberOfFolderProperties)(UInt32 *numProperties) x; \
STDMETHOD(GetFolderPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
FOLDER_INTERFACE(IFolderProperties, 0x0E)
{
INTERFACE_FolderProperties(PURE)
};
#define INTERFACE_IFolderArcProps(x) \
STDMETHOD(GetArcNumLevels)(UInt32 *numLevels) x; \
STDMETHOD(GetArcProp)(UInt32 level, PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetArcNumProps)(UInt32 level, UInt32 *numProps) x; \
STDMETHOD(GetArcPropInfo)(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
STDMETHOD(GetArcProp2)(UInt32 level, PROPID propID, PROPVARIANT *value) x; \
STDMETHOD(GetArcNumProps2)(UInt32 level, UInt32 *numProps) x; \
STDMETHOD(GetArcPropInfo2)(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
FOLDER_INTERFACE(IFolderArcProps, 0x10)
{
INTERFACE_IFolderArcProps(PURE)
};
FOLDER_INTERFACE(IGetFolderArcProps, 0x11)
{
STDMETHOD(GetFolderArcProps)(IFolderArcProps **object) PURE;
};
FOLDER_INTERFACE(IFolderCompare, 0x15)
{
STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) PURE;
};
#define INTERFACE_IFolderGetItemName(x) \
STDMETHOD(GetItemName)(UInt32 index, const wchar_t **name, unsigned *len) x; \
STDMETHOD(GetItemPrefix)(UInt32 index, const wchar_t **name, unsigned *len) x; \
STDMETHOD_(UInt64, GetItemSize)(UInt32 index) x; \
FOLDER_INTERFACE(IFolderGetItemName, 0x16)
{
INTERFACE_IFolderGetItemName(PURE)
};
#define FOLDER_MANAGER_INTERFACE(i, x) DECL_INTERFACE(i, 9, x)
#define INTERFACE_IFolderManager(x) \
STDMETHOD(OpenFolderFile)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, IFolderFolder **resultFolder, IProgress *progress) x; \
STDMETHOD(GetExtensions)(BSTR *extensions) x; \
STDMETHOD(GetIconPath)(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex) x; \
// STDMETHOD(GetTypes)(BSTR *types) PURE;
// STDMETHOD(CreateFolderFile)(const wchar_t *type, const wchar_t *filePath, IProgress *progress) PURE;
FOLDER_MANAGER_INTERFACE(IFolderManager, 0x05)
{
INTERFACE_IFolderManager(PURE);
};
/*
#define IMP_IFolderFolder_GetProp(k) \
(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
{ if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \
const CMy_STATPROPSTG_2 &srcItem = k[index]; \
*propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \
#define IMP_IFolderFolder_Props(c) \
STDMETHODIMP c::GetNumberOfProperties(UInt32 *numProperties) \
{ *numProperties = ARRAY_SIZE(kProps); return S_OK; } \
STDMETHODIMP c::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)
*/
#define IMP_IFolderFolder_GetProp(k) \
(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
{ if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \
*propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; return S_OK; } \
#define IMP_IFolderFolder_Props(c) \
STDMETHODIMP c::GetNumberOfProperties(UInt32 *numProperties) \
{ *numProperties = ARRAY_SIZE(kProps); return S_OK; } \
STDMETHODIMP c::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)
int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2);
// int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2);
#endif
Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

@@ -0,0 +1,120 @@
// LangPage.cpp
#include "StdAfx.h"
#include "../../../Common/Lang.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/ResourceString.h"
#include "HelpUtils.h"
#include "LangPage.h"
#include "LangPageRes.h"
#include "LangUtils.h"
#include "RegistryUtils.h"
using namespace NWindows;
static const UInt32 kLangIDs[] =
{
IDT_LANG_LANG
};
#define kLangTopic "fm/options.htm#language"
static void NativeLangString(UString &dest, const wchar_t *s)
{
dest += " (";
dest += s;
dest += ')';
}
bool LangOpen(CLang &lang, CFSTR fileName);
bool CLangPage::OnInit()
{
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
_langCombo.Attach(GetItem(IDC_LANG_LANG));
UString temp = MyLoadString(IDS_LANG_ENGLISH);
NativeLangString(temp, MyLoadString(IDS_LANG_NATIVE));
int index = (int)_langCombo.AddString(temp);
_langCombo.SetItemData(index, _paths.Size());
_paths.Add(L"-");
_langCombo.SetCurSel(0);
const FString dirPrefix = GetLangDirPrefix();
NFile::NFind::CEnumerator enumerator;
enumerator.SetDirPrefix(dirPrefix);
NFile::NFind::CFileInfo fi;
CLang lang;
UString error;
while (enumerator.Next(fi))
{
if (fi.IsDir())
continue;
const unsigned kExtSize = 4;
if (fi.Name.Len() < kExtSize)
continue;
const unsigned pos = fi.Name.Len() - kExtSize;
if (!StringsAreEqualNoCase_Ascii(fi.Name.Ptr(pos), ".txt"))
{
// if (!StringsAreEqualNoCase_Ascii(fi.Name.Ptr(pos), ".ttt"))
continue;
}
if (!LangOpen(lang, dirPrefix + fi.Name))
{
error.Add_Space_if_NotEmpty();
error += fs2us(fi.Name);
continue;
}
const UString shortName = fs2us(fi.Name.Left(pos));
UString s = shortName;
const wchar_t *eng = lang.Get(IDS_LANG_ENGLISH);
if (eng)
s = eng;
const wchar_t *native = lang.Get(IDS_LANG_NATIVE);
if (native)
NativeLangString(s, native);
index = (int)_langCombo.AddString(s);
_langCombo.SetItemData(index, _paths.Size());
_paths.Add(shortName);
if (g_LangID.IsEqualTo_NoCase(shortName))
_langCombo.SetCurSel(index);
}
if (!error.IsEmpty())
MessageBoxW(0, error, L"Error in Lang file", MB_ICONERROR);
return CPropertyPage::OnInit();
}
LONG CLangPage::OnApply()
{
int pathIndex = (int)_langCombo.GetItemData_of_CurSel();
if (_needSave)
SaveRegLang(_paths[pathIndex]);
_needSave = false;
ReloadLang();
LangWasChanged = true;
return PSNRET_NOERROR;
}
void CLangPage::OnNotifyHelp()
{
ShowHelpWindow(kLangTopic);
}
bool CLangPage::OnCommand(int code, int itemID, LPARAM param)
{
if (code == CBN_SELCHANGE && itemID == IDC_LANG_LANG)
{
_needSave = true;
Changed();
return true;
}
return CPropertyPage::OnCommand(code, itemID, param);
}
@@ -0,0 +1,25 @@
// LangPage.h
#ifndef __LANG_PAGE_H
#define __LANG_PAGE_H
#include "../../../Windows/Control/PropertyPage.h"
#include "../../../Windows/Control/ComboBox.h"
class CLangPage: public NWindows::NControl::CPropertyPage
{
NWindows::NControl::CComboBox _langCombo;
UStringVector _paths;
bool _needSave;
public:
bool LangWasChanged;
CLangPage(): _needSave(false), LangWasChanged(false) {}
virtual bool OnInit();
virtual void OnNotifyHelp();
virtual bool OnCommand(int code, int itemID, LPARAM param);
virtual LONG OnApply();
};
#endif
@@ -0,0 +1,37 @@
#include "LangPageRes.h"
#include "../../GuiCommon.rc"
#define xc 160
#define yc 100
IDD_LANG DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT
CAPTION "Language"
{
LTEXT "Language:", IDT_LANG_LANG, m, m, xc, 8
COMBOBOX IDC_LANG_LANG, m, 20, xc, yc - 20, MY_COMBO_SORTED
}
#ifdef UNDER_CE
#undef m
#undef xc
#define m 4
#define xc (SMALL_PAGE_SIZE_X + 8)
IDD_LANG_2 MY_PAGE
CAPTION "Language"
{
LTEXT "Language:", IDT_LANG_LANG, m, m, xc, 8
COMBOBOX IDC_LANG_LANG, m, 20, xc, yc - 20, MY_COMBO_SORTED
}
#endif
STRINGTABLE
BEGIN
IDS_LANG_ENGLISH "English"
IDS_LANG_NATIVE "English"
END
@@ -0,0 +1,8 @@
#define IDD_LANG 2101
#define IDD_LANG_2 12101
#define IDS_LANG_ENGLISH 1
#define IDS_LANG_NATIVE 2
#define IDT_LANG_LANG 2102
#define IDC_LANG_LANG 100
@@ -0,0 +1,292 @@
// LangUtils.cpp
#include "StdAfx.h"
#include "../../../Common/Lang.h"
#include "../../../Windows/DLL.h"
#include "../../../Windows/Synchronization.h"
#include "../../../Windows/Window.h"
#include "LangUtils.h"
#include "RegistryUtils.h"
using namespace NWindows;
#ifndef _UNICODE
extern bool g_IsNT;
#endif
UString g_LangID;
static CLang g_Lang;
static bool g_Loaded = false;
static NSynchronization::CCriticalSection g_CriticalSection;
bool LangOpen(CLang &lang, CFSTR fileName)
{
return lang.Open(fileName, "7-Zip");
}
FString GetLangDirPrefix()
{
return NDLL::GetModuleDirPrefix() + FTEXT("Lang") FSTRING_PATH_SEPARATOR;
}
void LoadLangOneTime()
{
NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
if (g_Loaded)
return;
g_Loaded = true;
ReloadLang();
}
void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID)
{
const wchar_t *s = g_Lang.Get(langID);
if (s)
{
CWindow window(GetDlgItem(dialog, controlID));
window.SetText(s);
}
}
static const CIDLangPair kLangPairs[] =
{
{ IDOK, 401 },
{ IDCANCEL, 402 },
{ IDYES, 406 },
{ IDNO, 407 },
{ IDCLOSE, 408 },
{ IDHELP, 409 }
};
void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems)
{
unsigned i;
for (i = 0; i < ARRAY_SIZE(kLangPairs); i++)
{
const CIDLangPair &pair = kLangPairs[i];
CWindow window(GetDlgItem(dialog, pair.ControlID));
if (window)
{
const wchar_t *s = g_Lang.Get(pair.LangID);
if (s)
window.SetText(s);
}
}
for (i = 0; i < numItems; i++)
{
UInt32 id = ids[i];
LangSetDlgItemText(dialog, id, id);
}
}
void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems)
{
for (unsigned i = 0; i < numItems; i++)
{
UInt32 id = ids[i];
const wchar_t *s = g_Lang.Get(id);
if (s)
{
CWindow window(GetDlgItem(dialog, id));
UString s2 = s;
s2 += ':';
window.SetText(s2);
}
}
}
void LangSetWindowText(HWND window, UInt32 langID)
{
const wchar_t *s = g_Lang.Get(langID);
if (s)
MySetWindowText(window, s);
}
UString LangString(UInt32 langID)
{
const wchar_t *s = g_Lang.Get(langID);
if (s)
return s;
return MyLoadString(langID);
}
void AddLangString(UString &s, UInt32 langID)
{
s += LangString(langID);
}
void LangString(UInt32 langID, UString &dest)
{
const wchar_t *s = g_Lang.Get(langID);
if (s)
{
dest = s;
return;
}
MyLoadString(langID, dest);
}
void LangString_OnlyFromLangFile(UInt32 langID, UString &dest)
{
dest.Empty();
const wchar_t *s = g_Lang.Get(langID);
if (s)
dest = s;
}
static const char * const kLangs =
"ar.bg.ca.zh.-tw.-cn.cs.da.de.el.en.es.fi.fr.he.hu.is."
"it.ja.ko.nl.no.=nb.=nn.pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.sk.sq.sv.th.tr."
"ur.id.uk.be.sl.et.lv.lt.tg.fa.vi.hy.az.eu.hsb.mk."
"st.ts.tn.ve.xh.zu.af.ka.fo.hi.mt.se.ga.yi.ms.kk."
"ky.sw.tk.uz.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa."
"mn.=mn.=mng.bo.cy.kh.lo.my.gl.kok..sd.syr.si..iu.am.tzm."
"ks.ne.fy.ps.tl.dv..ff.ha..yo.qu.st.ba.lb.kl."
"ig.kr.om.ti.gn..la.so.ii..arn..moh..br.."
"ug.mi.oc.co."
// "gsw.sah.qut.rw.wo....prs...."
// ".gd."
;
static void FindShortNames(UInt32 primeLang, AStringVector &names)
{
UInt32 index = 0;
for (const char *p = kLangs; *p != 0;)
{
const char *p2 = p;
for (; *p2 != '.'; p2++);
bool isSub = (p[0] == '-' || p[0] == '=');
if (!isSub)
index++;
if (index >= primeLang)
{
if (index > primeLang)
break;
AString s;
if (isSub)
{
if (p[0] == '-')
s = names[0];
else
p++;
}
while (p != p2)
s += (char)(Byte)*p++;
names.Add(s);
}
p = p2 + 1;
}
}
/*
#include "../../../Common/IntToString.h"
static struct CC1Lang
{
CC1Lang()
{
for (int i = 1; i < 150; i++)
{
UString s;
char ttt[32];
ConvertUInt32ToHex(i, ttt);
s += ttt;
UStringVector names;
FindShortNames(i, names);
FOR_VECTOR (k, names)
{
s.Add_Space();
s += names[k];
}
OutputDebugStringW(s);
}
}
} g_cc1;
*/
// typedef LANGID (WINAPI *GetUserDefaultUILanguageP)();
static void OpenDefaultLang()
{
LANGID sysLang = GetSystemDefaultLangID(); // "Language for non-Unicode programs" in XP64
LANGID userLang = GetUserDefaultLangID(); // "Standards and formats" language in XP64
if (sysLang != userLang)
return;
LANGID langID = userLang;
/*
LANGID sysUILang; // english in XP64
LANGID userUILang; // english in XP64
GetUserDefaultUILanguageP fn = (GetUserDefaultUILanguageP)GetProcAddress(
GetModuleHandle("kernel32"), "GetUserDefaultUILanguage");
if (fn)
userUILang = fn();
fn = (GetUserDefaultUILanguageP)GetProcAddress(
GetModuleHandle("kernel32"), "GetSystemDefaultUILanguage");
if (fn)
sysUILang = fn();
*/
WORD primLang = (WORD)(PRIMARYLANGID(langID));
WORD subLang = (WORD)(SUBLANGID(langID));
{
AStringVector names;
FindShortNames(primLang, names);
const FString dirPrefix (GetLangDirPrefix());
for (unsigned i = 0; i < 2; i++)
{
unsigned index = (i == 0 ? subLang : 0);
if (index < names.Size())
{
const AString &name = names[index];
if (!name.IsEmpty())
{
FString path (dirPrefix);
path += name;
path += ".txt";
if (LangOpen(g_Lang, path))
{
g_LangID = name;
return;
}
}
}
}
}
}
void ReloadLang()
{
g_Lang.Clear();
ReadRegLang(g_LangID);
#ifndef _UNICODE
if (g_IsNT)
#endif
{
if (g_LangID.IsEmpty())
{
OpenDefaultLang();
return;
}
}
if (g_LangID.Len() > 1 || g_LangID[0] != L'-')
{
FString s = us2fs(g_LangID);
if (s.Find(FCHAR_PATH_SEPARATOR) < 0)
{
if (s.Find(FTEXT('.')) < 0)
s += ".txt";
s.Insert(0, GetLangDirPrefix());
}
LangOpen(g_Lang, s);
}
}
@@ -0,0 +1,40 @@
// LangUtils.h
#ifndef __LANG_UTILS_H
#define __LANG_UTILS_H
#include "../../../Windows/ResourceString.h"
#ifdef LANG
extern UString g_LangID;
struct CIDLangPair
{
UInt32 ControlID;
UInt32 LangID;
};
void ReloadLang();
void LoadLangOneTime();
FString GetLangDirPrefix();
void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID);
void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems);
void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems);
void LangSetWindowText(HWND window, UInt32 langID);
UString LangString(UInt32 langID);
void AddLangString(UString &s, UInt32 langID);
void LangString(UInt32 langID, UString &dest);
void LangString_OnlyFromLangFile(UInt32 langID, UString &dest);
#else
inline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); }
inline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); }
inline void AddLangString(UString &s, UInt32 langID) { s += NWindows::MyLoadString(langID); }
#endif
#endif
@@ -0,0 +1,354 @@
// LinkDialog.cpp
#include "StdAfx.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/FileIO.h"
#include "../../../Windows/FileName.h"
#ifdef LANG
#include "LangUtils.h"
#endif
#include "BrowseDialog.h"
#include "CopyDialogRes.h"
#include "LinkDialog.h"
#include "resourceGui.h"
#include "App.h"
#include "resource.h"
extern bool g_SymLink_Supported;
using namespace NWindows;
using namespace NFile;
#ifdef LANG
static const UInt32 kLangIDs[] =
{
IDB_LINK_LINK,
IDT_LINK_PATH_FROM,
IDT_LINK_PATH_TO,
IDG_LINK_TYPE,
IDR_LINK_TYPE_HARD,
IDR_LINK_TYPE_SYM_FILE,
IDR_LINK_TYPE_SYM_DIR,
IDR_LINK_TYPE_JUNCTION
};
#endif
static bool GetSymLink(CFSTR path, CReparseAttr &attr)
{
NIO::CInFile file;
if (!file.Open(path,
FILE_SHARE_READ,
OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS))
return false;
const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
CByteArr buf(kBufSize);
DWORD returnedSize;
if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize))
return false;
DWORD errorCode = 0;
if (!attr.Parse(buf, returnedSize, errorCode))
return false;
CByteBuffer data2;
if (!FillLinkData(data2, attr.GetPath(), attr.IsSymLink()))
return false;
if (data2.Size() != returnedSize ||
memcmp(data2, buf, returnedSize) != 0)
return false;
return true;
}
static const int k_LinkType_Buttons[] =
{
IDR_LINK_TYPE_HARD,
IDR_LINK_TYPE_SYM_FILE,
IDR_LINK_TYPE_SYM_DIR,
IDR_LINK_TYPE_JUNCTION
};
void CLinkDialog::Set_LinkType_Radio(int idb)
{
CheckRadioButton(k_LinkType_Buttons[0], k_LinkType_Buttons[ARRAY_SIZE(k_LinkType_Buttons) - 1], idb);
}
bool CLinkDialog::OnInit()
{
#ifdef LANG
LangSetWindowText(*this, IDD_LINK);
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
#endif
_pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM));
_pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO));
if (!FilePath.IsEmpty())
{
NFind::CFileInfo fi;
int linkType = 0;
if (!fi.Find(us2fs(FilePath)))
linkType = IDR_LINK_TYPE_SYM_FILE;
else
{
if (fi.HasReparsePoint())
{
CReparseAttr attr;
bool res = GetSymLink(us2fs(FilePath), attr);
UString s = attr.PrintName;
if (!attr.IsOkNamePair())
{
s += " : ";
s += attr.SubsName;
}
if (!res)
s.Insert(0, L"ERROR: ");
SetItemText(IDT_LINK_PATH_TO_CUR, s);
UString destPath = attr.GetPath();
_pathFromCombo.SetText(FilePath);
_pathToCombo.SetText(destPath);
if (res)
{
if (attr.IsMountPoint())
linkType = IDR_LINK_TYPE_JUNCTION;
if (attr.IsSymLink())
{
linkType =
fi.IsDir() ?
IDR_LINK_TYPE_SYM_DIR :
IDR_LINK_TYPE_SYM_FILE;
// if (attr.IsRelative()) linkType = IDR_LINK_TYPE_SYM_RELATIVE;
}
if (linkType != 0)
Set_LinkType_Radio(linkType);
}
}
else
{
_pathFromCombo.SetText(AnotherPath);
_pathToCombo.SetText(FilePath);
if (fi.IsDir())
linkType = g_SymLink_Supported ?
IDR_LINK_TYPE_SYM_DIR :
IDR_LINK_TYPE_JUNCTION;
else
linkType = IDR_LINK_TYPE_HARD;
}
}
if (linkType != 0)
Set_LinkType_Radio(linkType);
}
NormalizeSize();
return CModalDialog::OnInit();
}
bool CLinkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
{
int mx, my;
GetMargins(8, mx, my);
int bx1, bx2, by;
GetItemSizes(IDCANCEL, bx1, by);
GetItemSizes(IDB_LINK_LINK, bx2, by);
int yPos = ySize - my - by;
int xPos = xSize - mx - bx1;
InvalidateRect(NULL);
{
RECT r, r2;
GetClientRectOfItem(IDB_LINK_PATH_FROM, r);
GetClientRectOfItem(IDB_LINK_PATH_TO, r2);
int bx = RECT_SIZE_X(r);
int newButtonXpos = xSize - mx - bx;
MoveItem(IDB_LINK_PATH_FROM, newButtonXpos, r.top, bx, RECT_SIZE_Y(r));
MoveItem(IDB_LINK_PATH_TO, newButtonXpos, r2.top, bx, RECT_SIZE_Y(r2));
int newComboXsize = newButtonXpos - mx - mx;
ChangeSubWindowSizeX(_pathFromCombo, newComboXsize);
ChangeSubWindowSizeX(_pathToCombo, newComboXsize);
}
MoveItem(IDCANCEL, xPos, yPos, bx1, by);
MoveItem(IDB_LINK_LINK, xPos - mx - bx2, yPos, bx2, by);
return false;
}
bool CLinkDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
{
switch (buttonID)
{
case IDB_LINK_PATH_FROM:
OnButton_SetPath(false);
return true;
case IDB_LINK_PATH_TO:
OnButton_SetPath(true);
return true;
case IDB_LINK_LINK:
OnButton_Link();
return true;
}
return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
}
void CLinkDialog::OnButton_SetPath(bool to)
{
UString currentPath;
NWindows::NControl::CComboBox &combo = to ?
_pathToCombo :
_pathFromCombo;
combo.GetText(currentPath);
// UString title = "Specify a location for output folder";
UString title = LangString(IDS_SET_FOLDER);
UString resultPath;
if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
return;
NName::NormalizeDirPathPrefix(resultPath);
combo.SetCurSel(-1);
combo.SetText(resultPath);
}
void CLinkDialog::ShowError(const wchar_t *s)
{
::MessageBoxW(*this, s, L"7-Zip", MB_ICONERROR);
}
void CLinkDialog::ShowLastErrorMessage()
{
ShowError(NError::MyFormatMessage(GetLastError()));
}
void CLinkDialog::OnButton_Link()
{
UString from, to;
_pathFromCombo.GetText(from);
_pathToCombo.GetText(to);
if (from.IsEmpty())
return;
if (!NName::IsAbsolutePath(from))
from.Insert(0, CurDirPrefix);
int idb = -1;
for (unsigned i = 0;; i++)
{
if (i >= ARRAY_SIZE(k_LinkType_Buttons))
return;
idb = k_LinkType_Buttons[i];
if (IsButtonCheckedBool(idb))
break;
}
NFind::CFileInfo info1, info2;
bool finded1 = info1.Find(us2fs(from));
bool finded2 = info2.Find(us2fs(to));
bool isDirLink = (
idb == IDR_LINK_TYPE_SYM_DIR ||
idb == IDR_LINK_TYPE_JUNCTION);
if (finded1 && info1.IsDir() != isDirLink ||
finded2 && info2.IsDir() != isDirLink)
{
ShowError(L"Incorrect link type");
return;
}
if (idb == IDR_LINK_TYPE_HARD)
{
if (!NDir::MyCreateHardLink(us2fs(from), us2fs(to)))
{
ShowLastErrorMessage();
return;
}
}
else
{
bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION);
CByteBuffer data;
if (!FillLinkData(data, to, isSymLink))
{
ShowError(L"Incorrect link");
return;
}
CReparseAttr attr;
DWORD errorCode = 0;
if (!attr.Parse(data, data.Size(), errorCode))
{
ShowError(L"Internal conversion error");
return;
}
if (!NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size()))
{
ShowLastErrorMessage();
return;
}
}
End(IDOK);
}
void CApp::Link()
{
unsigned srcPanelIndex = GetFocusedPanelIndex();
CPanel &srcPanel = Panels[srcPanelIndex];
if (!srcPanel.IsFSFolder())
{
srcPanel.MessageBox_Error_UnsupportOperation();
return;
}
CRecordVector<UInt32> indices;
srcPanel.GetOperatedItemIndices(indices);
if (indices.IsEmpty())
return;
if (indices.Size() != 1)
{
srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
return;
}
int index = indices[0];
const UString itemName = srcPanel.GetItemName(index);
const UString fsPrefix = srcPanel.GetFsPath();
const UString srcPath = fsPrefix + srcPanel.GetItemPrefix(index);
UString path = srcPath;
{
unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
CPanel &destPanel = Panels[destPanelIndex];
if (NumPanels > 1)
if (destPanel.IsFSFolder())
path = destPanel.GetFsPath();
}
CLinkDialog dlg;
dlg.CurDirPrefix = fsPrefix;
dlg.FilePath = srcPath + itemName;
dlg.AnotherPath = path;
if (dlg.Create(srcPanel.GetParent()) != IDOK)
return;
RefreshTitleAlways();
}
@@ -0,0 +1,34 @@
// LinkDialog.h
#ifndef __LINK_DIALOG_H
#define __LINK_DIALOG_H
#include "../../../Windows/Control/Dialog.h"
#include "../../../Windows/Control/ComboBox.h"
#include "LinkDialogRes.h"
class CLinkDialog: public NWindows::NControl::CModalDialog
{
NWindows::NControl::CComboBox _pathFromCombo;
NWindows::NControl::CComboBox _pathToCombo;
virtual bool OnInit();
virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
void OnButton_SetPath(bool to);
void OnButton_Link();
void ShowLastErrorMessage();
void ShowError(const wchar_t *s);
void Set_LinkType_Radio(int idb);
public:
UString CurDirPrefix;
UString FilePath;
UString AnotherPath;
INT_PTR Create(HWND parentWindow = 0)
{ return CModalDialog::Create(IDD_LINK, parentWindow); }
};
#endif
@@ -0,0 +1,36 @@
#include "LinkDialogRes.h"
#include "../../GuiCommon.rc"
#define xc 288
#define yc 200
#undef xRadioSize
#define xRadioSize xc - m - 2
IDD_LINK DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
CAPTION "Link"
BEGIN
LTEXT "Link from:", IDT_LINK_PATH_FROM, m, m, xc, 8
COMBOBOX IDC_LINK_PATH_FROM, m, 20, xc - bxsDots - m, 64, MY_COMBO_WITH_EDIT
PUSHBUTTON "...", IDB_LINK_PATH_FROM, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP
LTEXT "Link to:", IDT_LINK_PATH_TO, m, 48, xc, 8
COMBOBOX IDC_LINK_PATH_TO, m, 60, xc - bxsDots - m, 64, MY_COMBO_WITH_EDIT
PUSHBUTTON "...", IDB_LINK_PATH_TO, xs - m - bxsDots, 58, bxsDots, bys, WS_GROUP
LTEXT "", IDT_LINK_PATH_TO_CUR, m, 78, xc, 8
GROUPBOX "Link Type", IDG_LINK_TYPE, m, 104, xc, 76
CONTROL "Hard Link", IDR_LINK_TYPE_HARD, "Button", BS_AUTORADIOBUTTON | WS_GROUP,
m + m, 120, xRadioSize, 10
CONTROL "File Symbolic Link", IDR_LINK_TYPE_SYM_FILE, "Button", BS_AUTORADIOBUTTON,
m + m, 134, xRadioSize, 10
CONTROL "Directory Symbolic Link", IDR_LINK_TYPE_SYM_DIR, "Button", BS_AUTORADIOBUTTON,
m + m, 148, xRadioSize, 10
CONTROL "Directory Junction", IDR_LINK_TYPE_JUNCTION, "Button", BS_AUTORADIOBUTTON,
m + m, 162, xRadioSize, 10
DEFPUSHBUTTON "Link", IDB_LINK_LINK, bx2, by, bxs, bys
PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
END
@@ -0,0 +1,21 @@
#define IDD_LINK 7700
#define IDB_LINK_LINK 7701
#define IDT_LINK_PATH_FROM 7702
#define IDT_LINK_PATH_TO 7703
#define IDG_LINK_TYPE 7710
#define IDR_LINK_TYPE_HARD 7711
#define IDR_LINK_TYPE_SYM_FILE 7712
#define IDR_LINK_TYPE_SYM_DIR 7713
#define IDR_LINK_TYPE_JUNCTION 7714
#define IDC_LINK_PATH_FROM 100
#define IDC_LINK_PATH_TO 101
#define IDT_LINK_PATH_TO_CUR 102
#define IDB_LINK_PATH_FROM 103
#define IDB_LINK_PATH_TO 104
@@ -0,0 +1,321 @@
// ListViewDialog.cpp
#include "StdAfx.h"
#include "../../../Windows/Clipboard.h"
#include "EditDialog.h"
#include "ListViewDialog.h"
#include "RegistryUtils.h"
#ifdef LANG
#include "LangUtils.h"
#endif
using namespace NWindows;
static const unsigned kOneStringMaxSize = 1024;
static void ListView_GetSelected(NControl::CListView &listView, CUIntVector &vector)
{
vector.Clear();
int index = -1;
for (;;)
{
index = listView.GetNextSelectedItem(index);
if (index < 0)
break;
vector.Add(index);
}
}
bool CListViewDialog::OnInit()
{
#ifdef LANG
LangSetDlgItems(*this, NULL, 0);
#endif
_listView.Attach(GetItem(IDL_LISTVIEW));
if (NumColumns > 1)
{
LONG_PTR style = _listView.GetStyle();
style &= ~(LONG_PTR)LVS_NOCOLUMNHEADER;
_listView.SetStyle(style);
}
CFmSettings st;
st.Load();
DWORD exStyle = 0;
if (st.SingleClick)
exStyle |= LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT;
exStyle |= LVS_EX_FULLROWSELECT;
if (exStyle != 0)
_listView.SetExtendedListViewStyle(exStyle);
SetText(Title);
const int kWidth = 400;
LVCOLUMN columnInfo;
columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
columnInfo.fmt = LVCFMT_LEFT;
columnInfo.iSubItem = 0;
columnInfo.cx = kWidth;
columnInfo.pszText = NULL; // (TCHAR *)(const TCHAR *)""; // "Property"
if (NumColumns > 1)
{
columnInfo.cx = 100;
/*
// Windows always uses LVCFMT_LEFT for first column.
// if we need LVCFMT_RIGHT, we can create dummy column and then remove it
// columnInfo.mask |= LVCF_TEXT;
_listView.InsertColumn(0, &columnInfo);
columnInfo.iSubItem = 1;
columnInfo.fmt = LVCFMT_RIGHT;
_listView.InsertColumn(1, &columnInfo);
_listView.DeleteColumn(0);
*/
}
// else
_listView.InsertColumn(0, &columnInfo);
if (NumColumns > 1)
{
// columnInfo.fmt = LVCFMT_LEFT;
columnInfo.cx = kWidth - columnInfo.cx;
columnInfo.iSubItem = 1;
// columnInfo.pszText = NULL; // (TCHAR *)(const TCHAR *)""; // "Value"
_listView.InsertColumn(1, &columnInfo);
}
UString s;
FOR_VECTOR (i, Strings)
{
_listView.InsertItem(i, Strings[i]);
if (NumColumns > 1 && i < Values.Size())
{
s = Values[i];
if (s.Len() > kOneStringMaxSize)
{
s.DeleteFrom(kOneStringMaxSize);
s += " ...";
}
s.Replace(L"\r\n", L" ");
s.Replace(L"\n", L" ");
_listView.SetSubItem(i, 1, s);
}
}
if (SelectFirst && Strings.Size() > 0)
_listView.SetItemState_FocusedSelected(0);
_listView.SetColumnWidthAuto(0);
if (NumColumns > 1)
_listView.SetColumnWidthAuto(1);
StringsWereChanged = false;
NormalizeSize();
return CModalDialog::OnInit();
}
bool CListViewDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
{
int mx, my;
GetMargins(8, mx, my);
int bx1, bx2, by;
GetItemSizes(IDCANCEL, bx1, by);
GetItemSizes(IDOK, bx2, by);
int y = ySize - my - by;
int x = xSize - mx - bx1;
/*
RECT rect;
GetClientRect(&rect);
rect.top = y - my;
InvalidateRect(&rect);
*/
InvalidateRect(NULL);
MoveItem(IDCANCEL, x, y, bx1, by);
MoveItem(IDOK, x - mx - bx2, y, bx2, by);
/*
if (wParam == SIZE_MAXSHOW || wParam == SIZE_MAXIMIZED || wParam == SIZE_MAXHIDE)
mx = 0;
*/
_listView.Move(mx, my, xSize - mx * 2, y - my * 2);
return false;
}
extern bool g_LVN_ITEMACTIVATE_Support;
void CListViewDialog::CopyToClipboard()
{
CUIntVector indexes;
ListView_GetSelected(_listView, indexes);
UString s;
FOR_VECTOR (i, indexes)
{
unsigned index = indexes[i];
s += Strings[index];
if (NumColumns > 1 && index < Values.Size())
{
const UString &v = Values[index];
// if (!v.IsEmpty())
{
s += ": ";
s += v;
}
}
// if (indexes.Size() > 1)
{
s +=
#ifdef _WIN32
"\r\n"
#else
"\n"
#endif
;
}
}
ClipboardSetText(*this, s);
}
void CListViewDialog::ShowItemInfo()
{
CUIntVector indexes;
ListView_GetSelected(_listView, indexes);
if (indexes.Size() != 1)
return;
unsigned index = indexes[0];
CEditDialog dlg;
if (NumColumns == 1)
dlg.Text = Strings[index];
else
{
dlg.Title = Strings[index];
if (index < Values.Size())
dlg.Text = Values[index];
}
#ifdef _WIN32
if (dlg.Text.Find(L'\r') < 0)
dlg.Text.Replace(L"\n", L"\r\n");
#endif
dlg.Create(*this);
}
void CListViewDialog::DeleteItems()
{
for (;;)
{
int index = _listView.GetNextSelectedItem(-1);
if (index < 0)
break;
StringsWereChanged = true;
_listView.DeleteItem(index);
if ((unsigned)index < Strings.Size())
Strings.Delete(index);
if ((unsigned)index < Values.Size())
Values.Delete(index);
}
int focusedIndex = _listView.GetFocusedItem();
if (focusedIndex >= 0)
_listView.SetItemState_FocusedSelected(focusedIndex);
_listView.SetColumnWidthAuto(0);
}
void CListViewDialog::OnEnter()
{
if (IsKeyDown(VK_MENU)
|| NumColumns > 1)
{
ShowItemInfo();
return;
}
OnOK();
}
bool CListViewDialog::OnNotify(UINT /* controlID */, LPNMHDR header)
{
if (header->hwndFrom != _listView)
return false;
switch (header->code)
{
case LVN_ITEMACTIVATE:
if (g_LVN_ITEMACTIVATE_Support)
{
OnEnter();
return true;
}
break;
case NM_DBLCLK:
case NM_RETURN: // probabably it's unused
if (!g_LVN_ITEMACTIVATE_Support)
{
OnEnter();
return true;
}
break;
case LVN_KEYDOWN:
{
LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header);
switch (keyDownInfo->wVKey)
{
case VK_DELETE:
{
if (!DeleteIsAllowed)
return false;
DeleteItems();
return true;
}
case 'A':
{
if (IsKeyDown(VK_CONTROL))
{
_listView.SelectAll();
return true;
}
break;
}
case VK_INSERT:
case 'C':
{
if (IsKeyDown(VK_CONTROL))
{
CopyToClipboard();
return true;
}
break;
}
}
}
}
return false;
}
void CListViewDialog::OnOK()
{
FocusedItemIndex = _listView.GetFocusedItem();
CModalDialog::OnOK();
}
@@ -0,0 +1,46 @@
// ListViewDialog.h
#ifndef __LISTVIEW_DIALOG_H
#define __LISTVIEW_DIALOG_H
#include "../../../Windows/Control/Dialog.h"
#include "../../../Windows/Control/ListView.h"
#include "ListViewDialogRes.h"
class CListViewDialog: public NWindows::NControl::CModalDialog
{
NWindows::NControl::CListView _listView;
virtual void OnOK();
virtual bool OnInit();
virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
virtual bool OnNotify(UINT controlID, LPNMHDR header);
void CopyToClipboard();
void DeleteItems();
void ShowItemInfo();
void OnEnter();
public:
UString Title;
bool SelectFirst;
bool DeleteIsAllowed;
bool StringsWereChanged;
UStringVector Strings;
UStringVector Values;
int FocusedItemIndex;
unsigned NumColumns;
INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_LISTVIEW, wndParent); }
CListViewDialog():
SelectFirst(false),
DeleteIsAllowed(false),
StringsWereChanged(false),
FocusedItemIndex(-1),
NumColumns(1)
{}
};
#endif
@@ -0,0 +1,14 @@
#include "ListViewDialogRes.h"
#include "../../GuiCommon.rc"
#define xc 440
#define yc 320
IDD_LISTVIEW DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
CAPTION "ListView"
{
CONTROL "List1", IDL_LISTVIEW, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS |
LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,
m, m, xc, yc - bys - m
OK_CANCEL
}
@@ -0,0 +1,2 @@
#define IDD_LISTVIEW 99
#define IDL_LISTVIEW 100
@@ -0,0 +1,358 @@
// MenuPage.cpp
#include "StdAfx.h"
#include "../Common/ZipRegistry.h"
#include "../../../Windows/DLL.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/FileFind.h"
#include "../Explorer/ContextMenuFlags.h"
#include "../Explorer/RegistryContextMenu.h"
#include "../Explorer/resource.h"
#include "../FileManager/PropertyNameRes.h"
#include "../GUI/ExtractDialogRes.h"
#include "FormatUtils.h"
#include "HelpUtils.h"
#include "LangUtils.h"
#include "MenuPage.h"
#include "MenuPageRes.h"
using namespace NWindows;
using namespace NContextMenuFlags;
static const UInt32 kLangIDs[] =
{
IDX_SYSTEM_INTEGRATE_TO_MENU,
IDX_SYSTEM_CASCADED_MENU,
IDX_SYSTEM_ICON_IN_MENU,
IDX_EXTRACT_ELIM_DUP,
IDT_SYSTEM_CONTEXT_MENU_ITEMS
};
#define kMenuTopic "fm/options.htm#sevenZip"
struct CContextMenuItem
{
int ControlID;
UInt32 Flag;
};
static const CContextMenuItem kMenuItems[] =
{
{ IDS_CONTEXT_OPEN, kOpen },
{ IDS_CONTEXT_OPEN, kOpenAs },
{ IDS_CONTEXT_EXTRACT, kExtract },
{ IDS_CONTEXT_EXTRACT_HERE, kExtractHere },
{ IDS_CONTEXT_EXTRACT_TO, kExtractTo },
{ IDS_CONTEXT_TEST, kTest },
{ IDS_CONTEXT_COMPRESS, kCompress },
{ IDS_CONTEXT_COMPRESS_TO, kCompressTo7z },
{ IDS_CONTEXT_COMPRESS_TO, kCompressToZip },
#ifndef UNDER_CE
{ IDS_CONTEXT_COMPRESS_EMAIL, kCompressEmail },
{ IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressTo7zEmail },
{ IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressToZipEmail },
#endif
{ IDS_PROP_CHECKSUM, kCRC }
};
#if !defined(_WIN64)
extern bool g_Is_Wow64;
#endif
#ifndef KEY_WOW64_64KEY
#define KEY_WOW64_64KEY (0x0100)
#endif
#ifndef KEY_WOW64_32KEY
#define KEY_WOW64_32KEY (0x0200)
#endif
bool CMenuPage::OnInit()
{
_initMode = true;
Clear_MenuChanged();
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
#ifdef UNDER_CE
HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU);
HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU_2);
#else
{
UString s;
{
CWindow window(GetItem(IDX_SYSTEM_INTEGRATE_TO_MENU));
window.GetText(s);
}
UString bit64 = LangString(IDS_PROP_BIT64);
if (bit64.IsEmpty())
bit64 = "64-bit";
#ifdef _WIN64
bit64.Replace(L"64", L"32");
#endif
s.Add_Space();
s += '(';
s += bit64;
s += ')';
SetItemText(IDX_SYSTEM_INTEGRATE_TO_MENU_2, s);
}
const FString prefix = NDLL::GetModuleDirPrefix();
_dlls[0].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU;
_dlls[1].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU_2;
_dlls[0].wow = 0;
_dlls[1].wow =
#ifdef _WIN64
KEY_WOW64_32KEY
#else
KEY_WOW64_64KEY
#endif
;
for (unsigned d = 0; d < 2; d++)
{
CShellDll &dll = _dlls[d];
dll.wasChanged = false;
#ifndef _WIN64
if (d != 0 && !g_Is_Wow64)
{
HideItem(dll.ctrl);
continue;
}
#endif
FString &path = dll.Path;
path = prefix;
path += (d == 0 ? "7-zip.dll" :
#ifdef _WIN64
"7-zip32.dll"
#else
"7-zip64.dll"
#endif
);
if (!NFile::NFind::DoesFileExist(path))
{
path.Empty();
EnableItem(dll.ctrl, false);
}
else
{
dll.prevValue = CheckContextMenuHandler(fs2us(path), dll.wow);
CheckButton(dll.ctrl, dll.prevValue);
}
}
#endif
CContextMenuInfo ci;
ci.Load();
CheckButton(IDX_SYSTEM_CASCADED_MENU, ci.Cascaded.Val);
CheckButton(IDX_SYSTEM_ICON_IN_MENU, ci.MenuIcons.Val);
CheckButton(IDX_EXTRACT_ELIM_DUP, ci.ElimDup.Val);
_listView.Attach(GetItem(IDL_SYSTEM_OPTIONS));
const UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT;
_listView.SetExtendedListViewStyle(newFlags, newFlags);
_listView.InsertColumn(0, L"", 200);
for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++)
{
const CContextMenuItem &menuItem = kMenuItems[i];
UString s = LangString(menuItem.ControlID);
if (menuItem.Flag == kCRC)
s = "CRC SHA";
if (menuItem.Flag == kOpenAs ||
menuItem.Flag == kCRC)
s += " >";
switch (menuItem.ControlID)
{
case IDS_CONTEXT_EXTRACT_TO:
{
s = MyFormatNew(s, LangString(IDS_CONTEXT_FOLDER));
break;
}
case IDS_CONTEXT_COMPRESS_TO:
case IDS_CONTEXT_COMPRESS_TO_EMAIL:
{
UString s2 = LangString(IDS_CONTEXT_ARCHIVE);
switch (menuItem.Flag)
{
case kCompressTo7z:
case kCompressTo7zEmail:
s2 += (".7z");
break;
case kCompressToZip:
case kCompressToZipEmail:
s2 += (".zip");
break;
}
s = MyFormatNew(s, s2);
break;
}
}
int itemIndex = _listView.InsertItem(i, s);
_listView.SetCheckState(itemIndex, ((ci.Flags & menuItem.Flag) != 0));
}
_listView.SetColumnWidthAuto(0);
_initMode = false;
return CPropertyPage::OnInit();
}
#ifndef UNDER_CE
static void ShowMenuErrorMessage(const wchar_t *m, HWND hwnd)
{
MessageBoxW(hwnd, m, L"7-Zip", MB_ICONERROR);
}
#endif
LONG CMenuPage::OnApply()
{
#ifndef UNDER_CE
for (unsigned d = 2; d != 0;)
{
d--;
CShellDll &dll = _dlls[d];
if (dll.wasChanged && !dll.Path.IsEmpty())
{
bool newVal = IsButtonCheckedBool(dll.ctrl);
LONG res = SetContextMenuHandler(newVal, fs2us(dll.Path), dll.wow);
if (res != ERROR_SUCCESS && (dll.prevValue != newVal || newVal))
ShowMenuErrorMessage(NError::MyFormatMessage(res), *this);
dll.prevValue = CheckContextMenuHandler(fs2us(dll.Path), dll.wow);
CheckButton(dll.ctrl, dll.prevValue);
dll.wasChanged = false;
}
}
#endif
if (_cascaded_Changed || _menuIcons_Changed || _elimDup_Changed || _flags_Changed)
{
CContextMenuInfo ci;
ci.Cascaded.Val = IsButtonCheckedBool(IDX_SYSTEM_CASCADED_MENU);
ci.Cascaded.Def = _cascaded_Changed;
ci.MenuIcons.Val = IsButtonCheckedBool(IDX_SYSTEM_ICON_IN_MENU);
ci.MenuIcons.Def = _menuIcons_Changed;
ci.ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP);
ci.ElimDup.Def = _elimDup_Changed;
ci.Flags = 0;
for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++)
if (_listView.GetCheckState(i))
ci.Flags |= kMenuItems[i].Flag;
ci.Flags_Def = _flags_Changed;
ci.Save();
Clear_MenuChanged();
}
// UnChanged();
return PSNRET_NOERROR;
}
void CMenuPage::OnNotifyHelp()
{
ShowHelpWindow(kMenuTopic);
}
bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND)
{
switch (buttonID)
{
#ifndef UNDER_CE
case IDX_SYSTEM_INTEGRATE_TO_MENU:
case IDX_SYSTEM_INTEGRATE_TO_MENU_2:
{
for (unsigned d = 0; d < 2; d++)
{
CShellDll &dll = _dlls[d];
if (buttonID == dll.ctrl && !dll.Path.IsEmpty())
dll.wasChanged = true;
}
break;
}
#endif
case IDX_SYSTEM_CASCADED_MENU: _cascaded_Changed = true; break;
case IDX_SYSTEM_ICON_IN_MENU: _menuIcons_Changed = true; break;
case IDX_EXTRACT_ELIM_DUP: _elimDup_Changed = true; break;
default:
return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
}
Changed();
return true;
}
bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam)
{
if (lParam->hwndFrom == HWND(_listView))
{
switch (lParam->code)
{
case (LVN_ITEMCHANGED):
return OnItemChanged((const NMLISTVIEW *)lParam);
}
}
return CPropertyPage::OnNotify(controlID, lParam);
}
bool CMenuPage::OnItemChanged(const NMLISTVIEW *info)
{
if (_initMode)
return true;
if ((info->uChanged & LVIF_STATE) != 0)
{
UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK;
UINT newState = info->uNewState & LVIS_STATEIMAGEMASK;
if (oldState != newState)
{
_flags_Changed = true;
Changed();
}
}
return true;
}
@@ -0,0 +1,52 @@
// MenuPage.h
#ifndef __MENU_PAGE_H
#define __MENU_PAGE_H
#include "../../../Windows/Control/PropertyPage.h"
#include "../../../Windows/Control/ListView.h"
struct CShellDll
{
FString Path;
bool wasChanged;
bool prevValue;
int ctrl;
UInt32 wow;
CShellDll(): wasChanged (false), prevValue(false), ctrl(0), wow(0) {}
};
class CMenuPage: public NWindows::NControl::CPropertyPage
{
bool _initMode;
bool _cascaded_Changed;
bool _menuIcons_Changed;
bool _elimDup_Changed;
bool _flags_Changed;
void Clear_MenuChanged()
{
_cascaded_Changed = false;
_menuIcons_Changed = false;
_elimDup_Changed = false;
_flags_Changed = false;
}
#ifndef UNDER_CE
CShellDll _dlls[2];
#endif
NWindows::NControl::CListView _listView;
virtual bool OnInit();
virtual void OnNotifyHelp();
virtual bool OnNotify(UINT controlID, LPNMHDR lParam);
virtual bool OnItemChanged(const NMLISTVIEW *info);
virtual LONG OnApply();
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
public:
};
#endif
@@ -0,0 +1,24 @@
#include "MenuPageRes.h"
#include "../../GuiCommon.rc"
#define xc 240
#define yc 224
IDD_MENU MY_PAGE
#include "MenuPage2.rc"
#ifdef UNDER_CE
#undef m
#undef xc
#undef yc
#define m 4
#define xc (SMALL_PAGE_SIZE_X + 8)
#define yc 112
IDD_MENU_2 MY_PAGE
#include "MenuPage2.rc"
#endif
@@ -0,0 +1,17 @@
#include "../GUI/ExtractDialogRes.h"
#define y 82
CAPTION "7-Zip"
BEGIN
CONTROL "Integrate 7-Zip to shell context menu", IDX_SYSTEM_INTEGRATE_TO_MENU, MY_CHECKBOX, m, m, xc, 10
CONTROL "(32-bit)", IDX_SYSTEM_INTEGRATE_TO_MENU_2, MY_CHECKBOX, m, m + 14, xc, 10
CONTROL "Cascaded context menu", IDX_SYSTEM_CASCADED_MENU, MY_CHECKBOX, m, m + 28, xc, 10
CONTROL "Icons in context menu", IDX_SYSTEM_ICON_IN_MENU, MY_CHECKBOX, m, m + 42, xc, 10
CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, m, m + 56, xc, 10
LTEXT "Context menu items:", IDT_SYSTEM_CONTEXT_MENU_ITEMS, m, m + 70, xc, 8
CONTROL "List", IDL_SYSTEM_OPTIONS, "SysListView32",
LVS_REPORT | LVS_SINGLESEL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,
m, m + y, xc, yc - y
END
@@ -0,0 +1,11 @@
#define IDD_MENU 2300
#define IDD_MENU_2 12300
#define IDX_SYSTEM_INTEGRATE_TO_MENU 2301
#define IDX_SYSTEM_CASCADED_MENU 2302
#define IDT_SYSTEM_CONTEXT_MENU_ITEMS 2303
#define IDX_SYSTEM_ICON_IN_MENU 2304
#define IDX_SYSTEM_INTEGRATE_TO_MENU_2 2310
#define IDL_SYSTEM_OPTIONS 100
@@ -0,0 +1,76 @@
// MessagesDialog.cpp
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "../../../Windows/ResourceString.h"
#include "MessagesDialog.h"
#include "LangUtils.h"
#include "ProgressDialog2Res.h"
using namespace NWindows;
void CMessagesDialog::AddMessageDirect(LPCWSTR message)
{
int i = _messageList.GetItemCount();
wchar_t sz[16];
ConvertUInt32ToString((UInt32)i, sz);
_messageList.InsertItem(i, sz);
_messageList.SetSubItem(i, 1, message);
}
void CMessagesDialog::AddMessage(LPCWSTR message)
{
UString s = message;
while (!s.IsEmpty())
{
int pos = s.Find(L'\n');
if (pos < 0)
break;
AddMessageDirect(s.Left(pos));
s.DeleteFrontal(pos + 1);
}
AddMessageDirect(s);
}
bool CMessagesDialog::OnInit()
{
#ifdef LANG
LangSetWindowText(*this, IDD_MESSAGES);
LangSetDlgItems(*this, NULL, 0);
SetItemText(IDOK, LangString(IDS_CLOSE));
#endif
_messageList.Attach(GetItem(IDL_MESSAGE));
_messageList.SetUnicodeFormat();
_messageList.InsertColumn(0, L"", 30);
_messageList.InsertColumn(1, LangString(IDS_MESSAGE), 600);
FOR_VECTOR (i, *Messages)
AddMessage((*Messages)[i]);
_messageList.SetColumnWidthAuto(0);
_messageList.SetColumnWidthAuto(1);
NormalizeSize();
return CModalDialog::OnInit();
}
bool CMessagesDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
{
int mx, my;
GetMargins(8, mx, my);
int bx, by;
GetItemSizes(IDOK, bx, by);
int y = ySize - my - by;
int x = xSize - mx - bx;
InvalidateRect(NULL);
MoveItem(IDOK, x, y, bx, by);
_messageList.Move(mx, my, xSize - mx * 2, y - my * 2);
return false;
}
@@ -0,0 +1,25 @@
// MessagesDialog.h
#ifndef __MESSAGES_DIALOG_H
#define __MESSAGES_DIALOG_H
#include "../../../Windows/Control/Dialog.h"
#include "../../../Windows/Control/ListView.h"
#include "MessagesDialogRes.h"
class CMessagesDialog: public NWindows::NControl::CModalDialog
{
NWindows::NControl::CListView _messageList;
void AddMessageDirect(LPCWSTR message);
void AddMessage(LPCWSTR message);
virtual bool OnInit();
virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
public:
const UStringVector *Messages;
INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_MESSAGES, parent); }
};
#endif
@@ -0,0 +1,14 @@
#include "MessagesDialogRes.h"
#include "../../GuiCommon.rc"
#define xc 440
#define yc 160
IDD_MESSAGES DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
CAPTION "7-Zip: Diagnostic messages"
{
DEFPUSHBUTTON "&Close", IDOK, bx, by, bxs, bys
CONTROL "List1", IDL_MESSAGE, "SysListView32",
LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
m, m, xc, yc - bys - m
}
@@ -0,0 +1,3 @@
#define IDD_MESSAGES 6602
#define IDS_MESSAGE 6603
#define IDL_MESSAGE 100
Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

@@ -0,0 +1,39 @@
// MyCom2.h
#ifndef __MYCOM2_H
#define __MYCOM2_H
#include "../../../Common/MyCom.h"
#define MY_ADDREF_RELEASE_MT \
STDMETHOD_(ULONG, AddRef)() { InterlockedIncrement((LONG *)&__m_RefCount); return __m_RefCount; } \
STDMETHOD_(ULONG, Release)() { InterlockedDecrement((LONG *)&__m_RefCount); if (__m_RefCount != 0) \
return __m_RefCount; delete this; return 0; }
#define MY_UNKNOWN_IMP_SPEC_MT2(i1, i) \
MY_QUERYINTERFACE_BEGIN \
MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
i \
MY_QUERYINTERFACE_END \
MY_ADDREF_RELEASE_MT
#define MY_UNKNOWN_IMP1_MT(i) MY_UNKNOWN_IMP_SPEC_MT2( \
i, \
MY_QUERYINTERFACE_ENTRY(i) \
)
#define MY_UNKNOWN_IMP2_MT(i1, i2) MY_UNKNOWN_IMP_SPEC_MT2( \
i1, \
MY_QUERYINTERFACE_ENTRY(i1) \
MY_QUERYINTERFACE_ENTRY(i2) \
)
#define MY_UNKNOWN_IMP3_MT(i1, i2, i3) MY_UNKNOWN_IMP_SPEC_MT2( \
i1, \
MY_QUERYINTERFACE_ENTRY(i1) \
MY_QUERYINTERFACE_ENTRY(i2) \
MY_QUERYINTERFACE_ENTRY(i3) \
)
#endif
@@ -0,0 +1,749 @@
// MyLoadMenu.cpp
#include "StdAfx.h"
#include "../../../Windows/Menu.h"
#include "../../../Windows/TimeUtils.h"
#include "../../../Windows/Control/Dialog.h"
#include "../../PropID.h"
#include "../Common/CompressCall.h"
#include "AboutDialog.h"
#include "App.h"
#include "HelpUtils.h"
#include "LangUtils.h"
#include "MyLoadMenu.h"
#include "RegistryUtils.h"
#include "resource.h"
using namespace NWindows;
static const UINT kOpenBookmarkMenuID = 830;
static const UINT kSetBookmarkMenuID = 810;
static const UINT kMenuID_Time_Parent = 760;
static const UINT kMenuID_Time = 761;
extern HINSTANCE g_hInstance;
#define kFMHelpTopic "FM/index.htm"
extern void OptionsDialog(HWND hwndOwner, HINSTANCE hInstance);
enum
{
kMenuIndex_File = 0,
kMenuIndex_Edit,
kMenuIndex_View,
kMenuIndex_Bookmarks
};
static const UInt32 kTopMenuLangIDs[] = { 500, 501, 502, 503, 504, 505 };
static const UInt32 kAddToFavoritesLangID = 800;
static const UInt32 kToolbarsLangID = 733;
static const CIDLangPair kIDLangPairs[] =
{
{ IDCLOSE, 557 },
{ IDM_VIEW_ARANGE_BY_NAME, 1004 },
{ IDM_VIEW_ARANGE_BY_TYPE, 1020 },
{ IDM_VIEW_ARANGE_BY_DATE, 1012 },
{ IDM_VIEW_ARANGE_BY_SIZE, 1007 }
};
static int FindLangItem(unsigned controlID)
{
for (unsigned i = 0; i < ARRAY_SIZE(kIDLangPairs); i++)
if (kIDLangPairs[i].ControlID == controlID)
return i;
return -1;
}
static int GetSortControlID(PROPID propID)
{
switch (propID)
{
case kpidName: return IDM_VIEW_ARANGE_BY_NAME;
case kpidExtension: return IDM_VIEW_ARANGE_BY_TYPE;
case kpidMTime: return IDM_VIEW_ARANGE_BY_DATE;
case kpidSize: return IDM_VIEW_ARANGE_BY_SIZE;
case kpidNoProperty: return IDM_VIEW_ARANGE_NO_SORT;
}
return -1;
}
/*
static bool g_IsNew_fMask = true;
class CInit_fMask
{
public:
CInit_fMask()
{
g_IsNew_fMask = false;
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (::GetVersionEx(&vi))
{
g_IsNew_fMask = (vi.dwMajorVersion > 4 ||
(vi.dwMajorVersion == 4 && vi.dwMinorVersion > 0));
}
g_IsNew_fMask = false;
}
} g_Init_fMask;
// it's hack for supporting Windows NT
// constants are from WinUser.h
#if (WINVER < 0x0500)
#define MIIM_STRING 0x00000040
#define MIIM_BITMAP 0x00000080
#define MIIM_FTYPE 0x00000100
#endif
static UINT Get_fMask_for_String()
{
return g_IsNew_fMask ? MIIM_STRING : MIIM_TYPE;
}
static UINT Get_fMask_for_FType_and_String()
{
return g_IsNew_fMask ? (MIIM_STRING | MIIM_FTYPE) : MIIM_TYPE;
}
*/
static inline UINT Get_fMask_for_String() { return MIIM_TYPE; }
static inline UINT Get_fMask_for_FType_and_String() { return MIIM_TYPE; }
static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex)
{
CMenu menu;
menu.Attach(menuLoc);
for (int i = 0;; i++)
{
CMenuItem item;
item.fMask = Get_fMask_for_String() | MIIM_SUBMENU | MIIM_ID;
item.fType = MFT_STRING;
if (!menu.GetItem(i, true, item))
break;
{
UString newString;
if (item.hSubMenu)
{
UInt32 langID = 0;
if (level == 1 && menuIndex == kMenuIndex_Bookmarks)
langID = kAddToFavoritesLangID;
else
{
MyChangeMenu(item.hSubMenu, level + 1, i);
if (level == 1 && menuIndex == kMenuIndex_View)
{
if (item.wID == kMenuID_Time_Parent || item.StringValue.IsPrefixedBy_Ascii_NoCase("20"))
continue;
else
langID = kToolbarsLangID;
}
else if (level == 0 && i < ARRAY_SIZE(kTopMenuLangIDs))
langID = kTopMenuLangIDs[i];
else
continue;
}
LangString_OnlyFromLangFile(langID, newString);
if (newString.IsEmpty())
continue;
}
else
{
if (item.IsSeparator())
continue;
int langPos = FindLangItem(item.wID);
// we don't need lang change for CRC items!!!
UInt32 langID = langPos >= 0 ? kIDLangPairs[langPos].LangID : item.wID;
if (langID == IDM_OPEN_INSIDE_ONE || langID == IDM_OPEN_INSIDE_PARSER)
{
LangString_OnlyFromLangFile(IDM_OPEN_INSIDE, newString);
if (newString.IsEmpty())
continue;
newString.Replace(L"&", L"");
int tabPos = newString.Find(L"\t");
if (tabPos >= 0)
newString.DeleteFrom(tabPos);
newString += (langID == IDM_OPEN_INSIDE_ONE ? " *" : " #");
}
else if (langID == IDM_BENCHMARK2)
{
LangString_OnlyFromLangFile(IDM_BENCHMARK, newString);
if (newString.IsEmpty())
continue;
newString.Replace(L"&", L"");
int tabPos = newString.Find(L"\t");
if (tabPos >= 0)
newString.DeleteFrom(tabPos);
newString += " 2";
}
else
LangString_OnlyFromLangFile(langID, newString);
if (newString.IsEmpty())
continue;
int tabPos = item.StringValue.ReverseFind(L'\t');
if (tabPos >= 0)
newString += item.StringValue.Ptr(tabPos);
}
{
item.StringValue = newString;
item.fMask = Get_fMask_for_String();
item.fType = MFT_STRING;
menu.SetItem(i, true, item);
}
}
}
}
static CMenu g_FileMenu;
struct CFileMenuDestroyer
{
~CFileMenuDestroyer() { if ((HMENU)g_FileMenu != 0) g_FileMenu.Destroy(); }
} g_FileMenuDestroyer;
static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec);
static void CopyPopMenu_IfRequired(CMenuItem &item)
{
if (item.hSubMenu)
{
CMenu popup;
popup.CreatePopup();
CopyMenu(item.hSubMenu, popup);
item.hSubMenu = popup;
}
}
static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec)
{
CMenu srcMenu;
srcMenu.Attach(srcMenuSpec);
CMenu destMenu;
destMenu.Attach(destMenuSpec);
int startPos = 0;
for (int i = 0;; i++)
{
CMenuItem item;
item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String();
item.fType = MFT_STRING;
if (!srcMenu.GetItem(i, true, item))
break;
CopyPopMenu_IfRequired(item);
if (destMenu.InsertItem(startPos, true, item))
startPos++;
}
}
void MyLoadMenu()
{
HMENU baseMenu;
#ifdef UNDER_CE
HMENU oldMenu = g_App._commandBar.GetMenu(0);
if (oldMenu)
::DestroyMenu(oldMenu);
/* BOOL b = */ g_App._commandBar.InsertMenubar(g_hInstance, IDM_MENU, 0);
baseMenu = g_App._commandBar.GetMenu(0);
// if (startInit)
// SetIdsForSubMenes(baseMenu, 0, 0);
if (!g_LangID.IsEmpty())
MyChangeMenu(baseMenu, 0, 0);
g_App._commandBar.DrawMenuBar(0);
#else
HWND hWnd = g_HWND;
HMENU oldMenu = ::GetMenu(hWnd);
::SetMenu(hWnd, ::LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_MENU)));
::DestroyMenu(oldMenu);
baseMenu = ::GetMenu(hWnd);
// if (startInit)
// SetIdsForSubMenes(baseMenu, 0, 0);
if (!g_LangID.IsEmpty())
MyChangeMenu(baseMenu, 0, 0);
::DrawMenuBar(hWnd);
#endif
if ((HMENU)g_FileMenu != 0)
g_FileMenu.Destroy();
g_FileMenu.CreatePopup();
CopyMenu(::GetSubMenu(baseMenu, 0), g_FileMenu);
}
void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)
{
HMENU mainMenu =
#ifdef UNDER_CE
g_App._commandBar.GetMenu(0);
#else
::GetMenu(g_HWND)
#endif
;
if (::GetSubMenu(mainMenu, position) != hMenu)
return;
if (position == kMenuIndex_File)
{
CMenu menu;
menu.Attach(hMenu);
menu.RemoveAllItems();
g_App.GetFocusedPanel().CreateFileMenu(hMenu);
}
else if (position == kMenuIndex_Edit)
{
/*
CMenu menu;
menu.Attach(hMenu);
menu.EnableItem(IDM_EDIT_CUT, MF_ENABLED);
menu.EnableItem(IDM_EDIT_COPY, MF_ENABLED);
menu.EnableItem(IDM_EDIT_PASTE, IsClipboardFormatAvailableHDROP() ? MF_ENABLED : MF_GRAYED);
*/
}
else if (position == kMenuIndex_View)
{
// View;
CMenu menu;
menu.Attach(hMenu);
menu.CheckRadioItem(IDM_VIEW_LARGE_ICONS, IDM_VIEW_DETAILS,
IDM_VIEW_LARGE_ICONS + g_App.GetListViewMode(), MF_BYCOMMAND);
menu.CheckRadioItem(IDM_VIEW_ARANGE_BY_NAME, IDM_VIEW_ARANGE_NO_SORT,
GetSortControlID(g_App.GetSortID()), MF_BYCOMMAND);
menu.CheckItemByID(IDM_VIEW_TWO_PANELS, g_App.NumPanels == 2);
menu.CheckItemByID(IDM_VIEW_FLAT_VIEW, g_App.GetFlatMode());
menu.CheckItemByID(IDM_VIEW_ARCHIVE_TOOLBAR, g_App.ShowArchiveToolbar);
menu.CheckItemByID(IDM_VIEW_STANDARD_TOOLBAR, g_App.ShowStandardToolbar);
menu.CheckItemByID(IDM_VIEW_TOOLBARS_LARGE_BUTTONS, g_App.LargeButtons);
menu.CheckItemByID(IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT, g_App.ShowButtonsLables);
menu.CheckItemByID(IDM_VIEW_AUTO_REFRESH, g_App.Get_AutoRefresh_Mode());
// menu.CheckItemByID(IDM_VIEW_SHOW_STREAMS, g_App.Get_ShowNtfsStrems_Mode());
// menu.CheckItemByID(IDM_VIEW_SHOW_DELETED, g_App.ShowDeletedFiles);
for (int i = 0;; i++)
{
CMenuItem item;
item.fMask = Get_fMask_for_String() | MIIM_SUBMENU | MIIM_ID;
item.fType = MFT_STRING;
if (!menu.GetItem(i, true, item))
break;
if (item.hSubMenu && (item.wID == kMenuID_Time_Parent
|| item.StringValue.IsPrefixedBy_Ascii_NoCase("20")
))
{
FILETIME ft;
NTime::GetCurUtcFileTime(ft);
{
wchar_t s[64];
s[0] = 0;
if (ConvertUtcFileTimeToString(ft, s, kTimestampPrintLevel_DAY))
item.StringValue = s;
}
item.fMask = Get_fMask_for_String() | MIIM_ID;
item.fType = MFT_STRING;
item.wID = kMenuID_Time_Parent;
menu.SetItem(i, true, item);
CMenu subMenu;
subMenu.Attach(menu.GetSubMenu(i));
subMenu.RemoveAllItems();
const int k_TimeLevels[] =
{
kTimestampPrintLevel_DAY,
kTimestampPrintLevel_MIN,
kTimestampPrintLevel_SEC,
// 1,2,3,4,5,6,
kTimestampPrintLevel_NTFS
};
unsigned last = kMenuID_Time;
unsigned selectedCommand = 0;
g_App._timestampLevels.Clear();
unsigned id = kMenuID_Time;
for (unsigned k = 0; k < ARRAY_SIZE(k_TimeLevels); k++)
{
wchar_t s[64];
s[0] = 0;
int timestampLevel = k_TimeLevels[k];
if (ConvertUtcFileTimeToString(ft, s, timestampLevel))
{
if (subMenu.AppendItem(MF_STRING, id, s))
{
last = id;
g_App._timestampLevels.Add(timestampLevel);
if (g_App.GetTimestampLevel() == timestampLevel)
selectedCommand = id;
id++;
}
}
}
if (selectedCommand != 0)
menu.CheckRadioItem(kMenuID_Time, last, selectedCommand, MF_BYCOMMAND);
}
}
}
else if (position == kMenuIndex_Bookmarks)
{
CMenu menu;
menu.Attach(hMenu);
CMenu subMenu;
subMenu.Attach(menu.GetSubMenu(0));
subMenu.RemoveAllItems();
int i;
for (i = 0; i < 10; i++)
{
UString s = LangString(IDS_BOOKMARK);
s.Add_Space();
char c = (char)(L'0' + i);
s += c;
s += "\tAlt+Shift+";
s += c;
subMenu.AppendItem(MF_STRING, kSetBookmarkMenuID + i, s);
}
menu.RemoveAllItemsFrom(2);
for (i = 0; i < 10; i++)
{
UString s = g_App.AppState.FastFolders.GetString(i);
const int kMaxSize = 100;
const int kFirstPartSize = kMaxSize / 2;
if (s.Len() > kMaxSize)
{
s.Delete(kFirstPartSize, s.Len() - kMaxSize);
s.Insert(kFirstPartSize, L" ... ");
}
if (s.IsEmpty())
s = '-';
s += "\tAlt+";
s += (char)('0' + i);
menu.AppendItem(MF_STRING, kOpenBookmarkMenuID + i, s);
}
}
}
/*
It doesn't help
void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id)
{
if (::GetSubMenu(::GetMenu(g_HWND), 0) != hMenu)
return;
}
*/
void CFileMenu::Load(HMENU hMenu, unsigned startPos)
{
CMenu destMenu;
destMenu.Attach(hMenu);
UString diffPath;
ReadRegDiff(diffPath);
unsigned numRealItems = startPos;
for (unsigned i = 0;; i++)
{
CMenuItem item;
item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String();
item.fType = MFT_STRING;
if (!g_FileMenu.GetItem(i, true, item))
break;
{
if (!programMenu && item.wID == IDCLOSE)
continue;
if (item.wID == IDM_DIFF && diffPath.IsEmpty())
continue;
if (item.wID == IDM_OPEN_INSIDE_ONE || item.wID == IDM_OPEN_INSIDE_PARSER)
{
// We use diff as "super mode" marker for additional commands.
/*
if (diffPath.IsEmpty())
continue;
*/
}
if (item.wID == IDM_BENCHMARK2)
{
// We use diff as "super mode" marker for additional commands.
if (diffPath.IsEmpty())
continue;
}
bool isOneFsFile = (isFsFolder && numItems == 1 && allAreFiles);
bool disable = (!isOneFsFile && (item.wID == IDM_SPLIT || item.wID == IDM_COMBINE));
if (readOnly)
{
switch (item.wID)
{
case IDM_RENAME:
case IDM_MOVE_TO:
case IDM_DELETE:
case IDM_COMMENT:
case IDM_CREATE_FOLDER:
case IDM_CREATE_FILE:
disable = true;
}
}
if (item.wID == IDM_LINK && numItems != 1)
disable = true;
if (item.wID == IDM_ALT_STREAMS)
disable = !isAltStreamsSupported;
bool isBigScreen = NControl::IsDialogSizeOK(40, 200);
if (!isBigScreen && (disable || item.IsSeparator()))
continue;
CopyPopMenu_IfRequired(item);
if (destMenu.InsertItem(startPos, true, item))
{
if (disable)
destMenu.EnableItem(startPos, MF_BYPOSITION | MF_GRAYED);
startPos++;
}
if (!item.IsSeparator())
numRealItems = startPos;
}
}
destMenu.RemoveAllItemsFrom(numRealItems);
}
bool ExecuteFileCommand(int id)
{
if (id >= kMenuCmdID_Plugin_Start)
{
g_App.GetFocusedPanel().InvokePluginCommand(id);
g_App.GetFocusedPanel()._sevenZipContextMenu.Release();
g_App.GetFocusedPanel()._systemContextMenu.Release();
return true;
}
switch (id)
{
// File
case IDM_OPEN: g_App.OpenItem(); break;
case IDM_OPEN_INSIDE: g_App.OpenItemInside(NULL); break;
case IDM_OPEN_INSIDE_ONE: g_App.OpenItemInside(L"*"); break;
case IDM_OPEN_INSIDE_PARSER: g_App.OpenItemInside(L"#"); break;
case IDM_OPEN_OUTSIDE: g_App.OpenItemOutside(); break;
case IDM_FILE_VIEW: g_App.EditItem(false); break;
case IDM_FILE_EDIT: g_App.EditItem(true); break;
case IDM_RENAME: g_App.Rename(); break;
case IDM_COPY_TO: g_App.CopyTo(); break;
case IDM_MOVE_TO: g_App.MoveTo(); break;
case IDM_DELETE: g_App.Delete(!IsKeyDown(VK_SHIFT)); break;
case IDM_HASH_ALL: g_App.CalculateCrc("*"); break;
case IDM_CRC32: g_App.CalculateCrc("CRC32"); break;
case IDM_CRC64: g_App.CalculateCrc("CRC64"); break;
case IDM_SHA1: g_App.CalculateCrc("SHA1"); break;
case IDM_SHA256: g_App.CalculateCrc("SHA256"); break;
case IDM_DIFF: g_App.DiffFiles(); break;
case IDM_SPLIT: g_App.Split(); break;
case IDM_COMBINE: g_App.Combine(); break;
case IDM_PROPERTIES: g_App.Properties(); break;
case IDM_COMMENT: g_App.Comment(); break;
case IDM_CREATE_FOLDER: g_App.CreateFolder(); break;
case IDM_CREATE_FILE: g_App.CreateFile(); break;
#ifndef UNDER_CE
case IDM_LINK: g_App.Link(); break;
case IDM_ALT_STREAMS: g_App.OpenAltStreams(); break;
#endif
default: return false;
}
return true;
}
static void MyBenchmark(bool totalMode)
{
CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]);
CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]);
Benchmark(totalMode);
}
bool OnMenuCommand(HWND hWnd, int id)
{
if (ExecuteFileCommand(id))
return true;
switch (id)
{
// File
case IDCLOSE:
SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), (LPARAM)hWnd);
g_ExitEventLauncher.Exit(false);
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
// Edit
/*
case IDM_EDIT_CUT:
g_App.EditCut();
break;
case IDM_EDIT_COPY:
g_App.EditCopy();
break;
case IDM_EDIT_PASTE:
g_App.EditPaste();
break;
*/
case IDM_SELECT_ALL:
g_App.SelectAll(true);
g_App.Refresh_StatusBar();
break;
case IDM_DESELECT_ALL:
g_App.SelectAll(false);
g_App.Refresh_StatusBar();
break;
case IDM_INVERT_SELECTION:
g_App.InvertSelection();
g_App.Refresh_StatusBar();
break;
case IDM_SELECT:
g_App.SelectSpec(true);
g_App.Refresh_StatusBar();
break;
case IDM_DESELECT:
g_App.SelectSpec(false);
g_App.Refresh_StatusBar();
break;
case IDM_SELECT_BY_TYPE:
g_App.SelectByType(true);
g_App.Refresh_StatusBar();
break;
case IDM_DESELECT_BY_TYPE:
g_App.SelectByType(false);
g_App.Refresh_StatusBar();
break;
//View
case IDM_VIEW_LARGE_ICONS:
case IDM_VIEW_SMALL_ICONS:
case IDM_VIEW_LIST:
case IDM_VIEW_DETAILS:
{
UINT index = id - IDM_VIEW_LARGE_ICONS;
if (index < 4)
{
g_App.SetListViewMode(index);
/*
CMenu menu;
menu.Attach(::GetSubMenu(::GetMenu(hWnd), kMenuIndex_View));
menu.CheckRadioItem(IDM_VIEW_LARGE_ICONS, IDM_VIEW_DETAILS,
id, MF_BYCOMMAND);
*/
}
break;
}
case IDM_VIEW_ARANGE_BY_NAME: g_App.SortItemsWithPropID(kpidName); break;
case IDM_VIEW_ARANGE_BY_TYPE: g_App.SortItemsWithPropID(kpidExtension); break;
case IDM_VIEW_ARANGE_BY_DATE: g_App.SortItemsWithPropID(kpidMTime); break;
case IDM_VIEW_ARANGE_BY_SIZE: g_App.SortItemsWithPropID(kpidSize); break;
case IDM_VIEW_ARANGE_NO_SORT: g_App.SortItemsWithPropID(kpidNoProperty); break;
case IDM_OPEN_ROOT_FOLDER: g_App.OpenRootFolder(); break;
case IDM_OPEN_PARENT_FOLDER: g_App.OpenParentFolder(); break;
case IDM_FOLDERS_HISTORY: g_App.FoldersHistory(); break;
case IDM_VIEW_FLAT_VIEW: g_App.ChangeFlatMode(); break;
case IDM_VIEW_REFRESH: g_App.RefreshView(); break;
case IDM_VIEW_AUTO_REFRESH: g_App.Change_AutoRefresh_Mode(); break;
// case IDM_VIEW_SHOW_STREAMS: g_App.Change_ShowNtfsStrems_Mode(); break;
/*
case IDM_VIEW_SHOW_DELETED:
{
g_App.Change_ShowDeleted();
bool isChecked = g_App.ShowDeletedFiles;
Save_ShowDeleted(isChecked);
}
*/
case IDM_VIEW_TWO_PANELS: g_App.SwitchOnOffOnePanel(); break;
case IDM_VIEW_STANDARD_TOOLBAR: g_App.SwitchStandardToolbar(); break;
case IDM_VIEW_ARCHIVE_TOOLBAR: g_App.SwitchArchiveToolbar(); break;
case IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT: g_App.SwitchButtonsLables(); break;
case IDM_VIEW_TOOLBARS_LARGE_BUTTONS: g_App.SwitchLargeButtons(); break;
// Tools
case IDM_OPTIONS: OptionsDialog(hWnd, g_hInstance); break;
case IDM_BENCHMARK: MyBenchmark(false); break;
case IDM_BENCHMARK2: MyBenchmark(true); break;
// Help
case IDM_HELP_CONTENTS:
ShowHelpWindow(kFMHelpTopic);
break;
case IDM_ABOUT:
{
CAboutDialog dialog;
dialog.Create(hWnd);
break;
}
default:
{
if (id >= kOpenBookmarkMenuID && id <= kOpenBookmarkMenuID + 9)
{
g_App.OpenBookmark(id - kOpenBookmarkMenuID);
return true;
}
else if (id >= kSetBookmarkMenuID && id <= kSetBookmarkMenuID + 9)
{
g_App.SetBookmark(id - kSetBookmarkMenuID);
return true;
}
else if (id >= kMenuID_Time && (unsigned)id <= kMenuID_Time + g_App._timestampLevels.Size())
{
unsigned index = id - kMenuID_Time;
g_App.SetTimestampLevel(g_App._timestampLevels[index]);
return true;
}
return false;
}
}
return true;
}
@@ -0,0 +1,36 @@
// MyLoadMenu.h
#ifndef __MY_LOAD_MENU_H
#define __MY_LOAD_MENU_H
void OnMenuActivating(HWND hWnd, HMENU hMenu, int position);
// void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id);
// void OnMenuUnActivating(HWND hWnd);
bool OnMenuCommand(HWND hWnd, int id);
void MyLoadMenu();
struct CFileMenu
{
bool programMenu;
bool readOnly;
bool isFsFolder;
bool allAreFiles;
bool isAltStreamsSupported;
int numItems;
CFileMenu():
programMenu(false),
readOnly(false),
isFsFolder(false),
allAreFiles(false),
isAltStreamsSupported(true),
numItems(0)
{}
void Load(HMENU hMenu, unsigned startPos);
};
bool ExecuteFileCommand(int id);
#endif

Some files were not shown because too many files have changed in this diff Show More