📄 client7z.cpp
字号:
UInt32 Attributes;
FILETIME CreationTime;
FILETIME LastAccessTime;
FILETIME LastWriteTime;
UInt64 Size;
UString Name;
UString FullPath;
bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
};
class CArchiveUpdateCallback:
public IArchiveUpdateCallback2,
public ICryptoGetTextPassword2,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)
// IProgress
STDMETHOD(SetTotal)(UInt64 size);
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
// IUpdateCallback2
STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);
STDMETHOD(GetUpdateItemInfo)(UInt32 index,
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);
STDMETHOD(SetOperationResult)(Int32 operationResult);
STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);
STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
public:
CRecordVector<UInt64> VolumesSizes;
UString VolName;
UString VolExt;
UString DirPrefix;
const CObjectVector<CDirItem> *DirItems;
bool PasswordIsDefined;
UString Password;
bool AskPassword;
bool m_NeedBeClosed;
UStringVector FailedFiles;
CRecordVector<HRESULT> FailedCodes;
CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {};
~CArchiveUpdateCallback() { Finilize(); }
HRESULT Finilize();
void Init(const CObjectVector<CDirItem> *dirItems)
{
DirItems = dirItems;
m_NeedBeClosed = false;
FailedFiles.Clear();
FailedCodes.Clear();
}
};
STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */)
{
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */)
{
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */)
{
return E_NOTIMPL;
}
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */,
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
{
if(newData != NULL)
*newData = BoolToInt(true);
if(newProperties != NULL)
*newProperties = BoolToInt(true);
if(indexInArchive != NULL)
*indexInArchive = UInt32(-1);
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant propVariant;
if (propID == kpidIsAnti)
{
propVariant = false;
propVariant.Detach(value);
return S_OK;
}
{
const CDirItem &dirItem = (*DirItems)[index];
switch(propID)
{
case kpidPath:
propVariant = dirItem.Name;
break;
case kpidIsFolder:
propVariant = dirItem.IsDirectory();
break;
case kpidSize:
propVariant = dirItem.Size;
break;
case kpidAttributes:
propVariant = dirItem.Attributes;
break;
case kpidLastAccessTime:
propVariant = dirItem.LastAccessTime;
break;
case kpidCreationTime:
propVariant = dirItem.CreationTime;
break;
case kpidLastWriteTime:
propVariant = dirItem.LastWriteTime;
break;
}
}
propVariant.Detach(value);
return S_OK;
}
HRESULT CArchiveUpdateCallback::Finilize()
{
if (m_NeedBeClosed)
{
PrintNewLine();
m_NeedBeClosed = false;
}
return S_OK;
}
static void GetStream2(const wchar_t *name)
{
PrintString("Compressing ");
if (name[0] == 0)
name = kEmptyFileAlias;
PrintString(name);
}
STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
{
RINOK(Finilize());
const CDirItem &dirItem = (*DirItems)[index];
GetStream2(dirItem.Name);
if(dirItem.IsDirectory())
return S_OK;
{
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
UString path = DirPrefix + dirItem.FullPath;
if(!inStreamSpec->Open(path))
{
DWORD sysError = ::GetLastError();
FailedCodes.Add(sysError);
FailedFiles.Add(path);
// if (systemError == ERROR_SHARING_VIOLATION)
{
PrintNewLine();
PrintError("WARNING: can't open file");
// PrintString(NError::MyFormatMessageW(systemError));
return S_FALSE;
}
// return sysError;
}
*inStream = inStreamLoc.Detach();
}
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */)
{
m_NeedBeClosed = true;
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
{
if (VolumesSizes.Size() == 0)
return S_FALSE;
if (index >= (UInt32)VolumesSizes.Size())
index = VolumesSizes.Size() - 1;
*size = VolumesSizes[index];
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
{
wchar_t temp[32];
ConvertUInt64ToString(index + 1, temp);
UString res = temp;
while (res.Length() < 2)
res = UString(L'0') + res;
UString fileName = VolName;
fileName += L'.';
fileName += res;
fileName += VolExt;
COutFileStream *streamSpec = new COutFileStream;
CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
if(!streamSpec->Create(fileName, false))
return ::GetLastError();
*volumeStream = streamLoc.Detach();
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
if (!PasswordIsDefined)
{
if (AskPassword)
{
// You can ask real password here from user
// Password = GetPassword(OutStream);
// PasswordIsDefined = true;
PrintError("Password is not defined");
return E_ABORT;
}
}
*passwordIsDefined = BoolToInt(PasswordIsDefined);
CMyComBSTR tempName(Password);
*password = tempName.Detach();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////
// Main function
int
#ifdef _MSC_VER
__cdecl
#endif
main(int argc, char* argv[])
{
#ifdef _WIN32
#ifndef _UNICODE
g_IsNT = IsItWindowsNT();
#endif
#endif
PrintStringLn(kCopyrightString);
if (argc < 3)
{
PrintStringLn(kHelpString);
return 1;
}
NWindows::NDLL::CLibrary library;
if (!library.Load(TEXT(kDllName)))
{
PrintError("Can not load library");
return 1;
}
CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject");
if (createObjectFunc == 0)
{
PrintError("Can not get CreateObject");
return 1;
}
AString command = argv[1];
UString archiveName = GetUnicodeString(argv[2], CP_OEMCP);
if (command.CompareNoCase("a") == 0)
{
// create archive command
if (argc < 4)
{
PrintStringLn(kHelpString);
return 1;
}
CObjectVector<CDirItem> dirItems;
int i;
for (i = 3; i < argc; i++)
{
CDirItem item;
UString name = GetUnicodeString(argv[i], CP_OEMCP);
NFile::NFind::CFileInfoW fileInfo;
if (!NFile::NFind::FindFile(name, fileInfo))
{
PrintString(UString(L"Can't find file") + name);
return 1;
}
item.Attributes = fileInfo.Attributes;
item.Size = fileInfo.Size;
item.CreationTime = fileInfo.CreationTime;
item.LastAccessTime = fileInfo.LastAccessTime;
item.LastWriteTime = fileInfo.LastWriteTime;
item.Name = name;
item.FullPath = name;
dirItems.Add(item);
}
COutFileStream *outFileStreamSpec = new COutFileStream;
CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;
if (!outFileStreamSpec->Create(archiveName, false))
{
PrintError("can't create archive file");
return 1;
}
CMyComPtr<IOutArchive> outArchive;
if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK)
{
PrintError("Can not get class object");
return 1;
}
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);
updateCallbackSpec->Init(&dirItems);
// updateCallbackSpec->PasswordIsDefined = true;
// updateCallbackSpec->Password = L"1";
HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback);
updateCallbackSpec->Finilize();
if (result != S_OK)
{
PrintError("Update Error");
return 1;
}
for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++)
{
PrintNewLine();
PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]);
}
if (updateCallbackSpec->FailedFiles.Size() != 0)
return 1;
}
else
{
if (argc != 3)
{
PrintStringLn(kHelpString);
return 1;
}
bool listCommand;
if (command.CompareNoCase("l") == 0)
listCommand = true;
else if (command.CompareNoCase("x") == 0)
listCommand = false;
else
{
PrintError("incorrect command");
return 1;
}
CMyComPtr<IInArchive> archive;
if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK)
{
PrintError("Can not get class object");
return 1;
}
CInFileStream *fileSpec = new CInFileStream;
CMyComPtr<IInStream> file = fileSpec;
if (!fileSpec->Open(archiveName))
{
PrintError("Can not open archive file");
return 1;
}
{
CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback;
CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);
openCallbackSpec->PasswordIsDefined = false;
// openCallbackSpec->PasswordIsDefined = true;
// openCallbackSpec->Password = L"1";
if (archive->Open(file, 0, openCallback) != S_OK)
{
PrintError("Can not open archive");
return 1;
}
}
if (listCommand)
{
// List command
UInt32 numItems = 0;
archive->GetNumberOfItems(&numItems);
for (UInt32 i = 0; i < numItems; i++)
{
{
// Get uncompressed size of file
NWindows::NCOM::CPropVariant propVariant;
archive->GetProperty(i, kpidSize, &propVariant);
UString s = ConvertPropVariantToString(propVariant);
PrintString(s);
PrintString(" ");
}
{
// Get name of file
NWindows::NCOM::CPropVariant propVariant;
archive->GetProperty(i, kpidPath, &propVariant);
UString s = ConvertPropVariantToString(propVariant);
PrintString(s);
}
PrintString("\n");
}
}
else
{
// Extract command
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
extractCallbackSpec->Init(archive, L""); // second parameter is output folder path
extractCallbackSpec->PasswordIsDefined = false;
// extractCallbackSpec->PasswordIsDefined = true;
// extractCallbackSpec->Password = L"1";
HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback);
if (result != S_OK)
{
PrintError("Extract Error");
return 1;
}
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -