Recently there has been a 7-zip C# wrapper library in codeproject.com written by Eugene Sichkar. The author has done a tremendously great job he deserves a thank.
By default user can not simply use the native 7z.dll directly into the C# project this is because of the incomplete COM interfaces implementations in 7-Zip code. So his wrapper comes to a rescue but author says the wrapper is incomplete in fact it lacks everything (I don’t think he is true). What I found is Currently wrapper doesn’t support extract feature for password protected files.I tweak his wrapper class to make it work for password protected files
Looking in to the 7zip original source code. When user calls the extract method first it tries to Query for ICryptoGetTextPassword in the IArchiveExtractCallback .
Line no: 634 (7z457\CPP\7zip\Archive\Rar\RarHandler.cpp)
if (!getTextPassword)
extractCallback.QueryInterface(IID_ICryptoGetTextPassword,
&getTextPassword);
I am now tweaking the wrapper for IArchiveExtractCallback interface by inheriting it from the ICryptoGetTextPassword. As
[ComImport]
[Guid("23170F69-40C1-278A-0000-000600200000")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IArchiveExtractCallback:ICryptoGetTextPassword
{
void SetTotal(ulong total);
void SetCompleted([In] ref ulong completeValue);
[PreserveSig]
int GetStream(
uint index,
[MarshalAs(UnmanagedType.Interface)] out ISequentialOutStream outStream,
AskMode askExtractMode);
// GetStream OUT: S_OK – OK, S_FALSE – skeep this file
void PrepareOperation(AskMode askExtractMode);
void SetOperationResult(OperationResult resultEOperationResult);
}
Thus, our callback ,to get the password ,is now invoked from native 7zip as
Line: 640 (7z457\CPP\7zip\Archive\Rar\RarHandler.cpp)
RINOK(getTextPassword->CryptoGetTextPassword(&password));
The callback return 0 if success and 1 if error.
So now ArchiveCallback class looks like
class ArchiveCallback : IArchiveExtractCallback
{
private uint FileNumber;
private string FileName;
private OutStreamWrapper FileStream;
public ArchiveCallback(uint fileNumber, string fileName)
{
this.FileNumber = fileNumber;
this.FileName = fileName;
}
#region IArchiveExtractCallback Members
public void SetTotal(ulong total)
{
}
public void SetCompleted(ref ulong completeValue)
{
}
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
{
if ((index == FileNumber) && (askExtractMode == AskMode.kExtract))
{
string FileDir = Path.GetDirectoryName(FileName);
if (!string.IsNullOrEmpty(FileDir))
Directory.CreateDirectory(FileDir);
FileStream = new OutStreamWrapper(File.Create(FileName));
outStream = FileStream;
}
else
outStream = null;
return 0;
}
public void PrepareOperation(AskMode askExtractMode)
{
}
public void SetOperationResult(OperationResult resultEOperationResult)
{
FileStream.Dispose();
Console.WriteLine(resultEOperationResult);
}
#endregion
#region ICryptoGetTextPassword Members
public int CryptoGetTextPassword(out string password)
{
password = “secretbytes.wordpress.com”;
return 0;
}
#endregion
}
Filed under: C#



Hi,
Thank you very much for your code!
Do you have code sample that I can use to create 7-zip archive encrypted with password?
Thank you very much
Shota