7-zip wrapper, Extracting password protected file

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

}

Advertisement

One Response

  1. 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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.