Pelles C forum

C language => User contributions => Topic started by: TimoVJL on September 15, 2017, 11:52:25 AM

Title: 7z test
Post by: TimoVJL on September 15, 2017, 11:52:25 AM
A small test to list files in 7z file.
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ole2.h>
#include "7z.h"

int printf(const char * restrict format, ...);

const GUID CLSID_CFormat7z = {0x23170F69,0x40C1,0x278A,0x10,0x00,0x00,0x01,0x10,0x07,0x00,0x00};
const GUID IID_IInArchive = {0x23170F69,0x40C1,0x278A,0x00,0x00,0x00,0x06,0x00,0x60,0x00,0x00};;
//const GUID IID_IOutArchive = {0x23170F69,0x40C1,0x278A,0x00,0x00,0x00,0x06,0x00,0xA0,0x00,0x00};

extern IInStream InStream;
extern IArchiveOpenCallback ArchiveOpenCallback;
//extern IArchiveExtractCallback ArchiveExtractCallback;

int __cdecl main(int argc, char **argv)
{
IInArchive *pArc = NULL;
LONGLONG maxCheckStartPosition = 0;
#ifdef _WIN64
HMODULE hMod = LoadLibrary("x64/7za.dll");
#else
HMODULE hMod = LoadLibrary("7za.dll");
#endif
if (hMod) {
PCREATEOBJECT CreateObject = (PCREATEOBJECT)GetProcAddress(hMod, "CreateObject");
CreateObject(&CLSID_CFormat7z, &IID_IInArchive, (void**)&pArc);
if (pArc) {
HRESULT hr;
//printf("pObj %p\n", pArc);
//InStream.hFile = CreateFile("test.7z", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
InStream.hFile = CreateFile("C.7z", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
OutputDebugString("*** Test start ***");
hr = pArc->lpVtbl->Open(pArc, &InStream, &maxCheckStartPosition, &ArchiveOpenCallback);
//CloseHandle(InStream.hFile);
DWORD numItems;
hr = pArc->lpVtbl->GetNumberOfItems(pArc, &numItems);
printf("numItems= %u\n", numItems);
for (DWORD i = 0; i < numItems; i++) {
PROPVARIANT pvPath;
hr = pArc->lpVtbl->GetProperty(pArc, i, 3, &pvPath); // kpidPath = 3
printf("path: %ls\t", pvPath.bstrVal);
hr = pArc->lpVtbl->GetProperty(pArc, i, 4, &pvPath); // kpidName = 4
printf("name: %ls\n", pvPath.bstrVal);
}
}
FreeLibrary(hMod);
}
return 0;
}
7zC.h
Code: [Select]
#ifndef _7ZC_H
#define _7ZC_H
#pragma once

#ifndef UInt32
typedef long Int32;
typedef unsigned long UInt32;
typedef long long Int64;
typedef unsigned long long UInt64;
#endif

#ifndef OLE2ANSI
typedef WCHAR OLECHAR;
typedef OLECHAR *BSTR;
typedef ULONG PROPID;
typedef struct tagPROPVARIANT PROPVARIANT;
typedef unsigned short VARTYPE;
#endif

//typedef struct IInStream IInStream;
typedef struct IOutStream IOutStream;
typedef struct IArchiveOpenCallback IArchiveOpenCallback;
typedef struct IArchiveExtractCallback IArchiveExtractCallback;
typedef struct ISequentialInStream ISequentialInStream;
typedef struct ISequentialOutStream ISequentialOutStream;

extern const GUID IID_ISequentialInStream;
typedef struct ISequentialInStream ISequentialInStream;
typedef struct ISequentialInStreamVtbl {
// IUnknown methods
HRESULT (STDMETHODCALLTYPE *QueryInterface) (ISequentialInStream *, REFIID riid, void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef) (ISequentialInStream *This);
ULONG (STDMETHODCALLTYPE *Release) (ISequentialInStream *This);
// ISequentialInStream methods
HRESULT (STDMETHODCALLTYPE *Read) (ISequentialInStream *This, void *data, UInt32 size, UInt32 * processedSize);
}ISequentialInStreamVtbl;
typedef struct ISequentialInStream {
const struct ISequentialInStreamVtbl *lpVtbl;
DWORD nRefCount;
HANDLE hFile;
}ISequentialInStream;

extern const GUID IID_ISequentialOutStream;
typedef struct ISequentialOutStream ISequentialOutStream;
typedef struct ISequentialOutStreamVtbl {
// IUnknown methods
HRESULT (STDMETHODCALLTYPE *QueryInterface) (ISequentialOutStream *, REFIID riid, void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef) (ISequentialOutStream *This);
ULONG (STDMETHODCALLTYPE *Release) (ISequentialOutStream *This);
// ISequentialOutStream methods
HRESULT (STDMETHODCALLTYPE *Write) (ISequentialOutStream *This, const void *data, UInt32 size, UInt32 * processedSize);
}ISequentialOutStreamVtbl;
typedef struct ISequentialOutStream {
const struct ISequentialOutStreamVtbl *lpVtbl;
DWORD nRefCount;
HANDLE hFile;
}ISequentialOutStream;

extern const GUID IID_IInStream;
typedef struct IInStream IInStream;
typedef struct IInStreamVtbl {
// IUnknown methods
HRESULT (STDMETHODCALLTYPE *QueryInterface) (IInStream *, REFIID riid, void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef) (IInStream *This);
ULONG (STDMETHODCALLTYPE *Release) (IInStream *This);
// ISequentialInStream methods
HRESULT (STDMETHODCALLTYPE *Read) (ISequentialInStream *This, void *data, UInt32 size, UInt32 * processedSize);
// IInStream methods
HRESULT (STDMETHODCALLTYPE *Seek) (IInStream *This, Int64 offset, UInt32 seekOrigin, UInt64 * newPosition);
}IInStreamVtbl;
typedef struct IInStream {
const struct IInStreamVtbl *lpVtbl;
DWORD nRefCount;
HANDLE hFile;
}IInStream;

extern const GUID IID_IOutStream;
typedef struct IOutStream IOutStream;
typedef struct IOutStreamVtbl {
// IUnknown methods
HRESULT (STDMETHODCALLTYPE *QueryInterface) (IOutStream *, REFIID riid, void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef) (IOutStream *This);
ULONG (STDMETHODCALLTYPE *Release) (IOutStream *This);
// ISequentialOutStream methods
HRESULT (STDMETHODCALLTYPE *Write) (ISequentialOutStream *This, const void *data, UInt32 size, UInt32 * processedSize);
// IOutStream methods
HRESULT (STDMETHODCALLTYPE *Seek) (IOutStream *This, Int64 offset, UInt32 seekOrigin, UInt64 * newPosition);
HRESULT (STDMETHODCALLTYPE *SetSize) (IOutStream *This, UInt64 newSize);
}IOutStreamVtbl;
typedef struct IOutStream {
const struct IOutStreamVtbl *lpVtbl;
DWORD nRefCount;
HANDLE hFile;
}IOutStream;

extern const GUID IID_IInArchive;
typedef struct IInArchive IInArchive;
typedef struct IInArchiveVtbl {
// IUnknown methods
HRESULT (STDMETHODCALLTYPE *QueryInterface) (IInArchive *, REFIID riid, void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef) (IInArchive *This);
ULONG (STDMETHODCALLTYPE *Release) (IInArchive *This);
// IInArchive methods
HRESULT (STDMETHODCALLTYPE *Open) (IInArchive *This, IInStream * stream, const UInt64 * maxCheckStartPosition, IArchiveOpenCallback * openCallback);
HRESULT (STDMETHODCALLTYPE *Close) (IInArchive *This);
HRESULT (STDMETHODCALLTYPE *GetNumberOfItems) (IInArchive *This, UInt32 * numItems);
HRESULT (STDMETHODCALLTYPE *GetProperty) (IInArchive *This, UInt32 index, PROPID propID, PROPVARIANT * value);
HRESULT (STDMETHODCALLTYPE *Extract) (IInArchive *This, const UInt32 * indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback * extractCallback);
HRESULT (STDMETHODCALLTYPE *GetArchiveProperty) (IInArchive *This, PROPID propID, PROPVARIANT * value);
HRESULT (STDMETHODCALLTYPE *GetNumberOfProperties) (IInArchive *This, UInt32 * numProps);
HRESULT (STDMETHODCALLTYPE *GetPropertyInfo) (IInArchive *This, UInt32 index, BSTR * name, PROPID * propID, VARTYPE * varType);
HRESULT (STDMETHODCALLTYPE *GetNumberOfArchiveProperties) (IInArchive *This, UInt32 * numProps);
HRESULT (STDMETHODCALLTYPE *GetArchivePropertyInfo) (IInArchive *This, UInt32 index, BSTR * name, PROPID * propID, VARTYPE * varType);
}IInArchiveVtbl;
typedef struct IInArchive {
const struct IInArchiveVtbl *lpVtbl;
}IInArchive;

extern const GUID IID_IArchiveOpenCallback;
typedef struct IArchiveOpenCallback IArchiveOpenCallback;
typedef struct IArchiveOpenCallbackVtbl {
// IUnknown methods
HRESULT (STDMETHODCALLTYPE *QueryInterface) (IArchiveOpenCallback *, REFIID riid, void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef) (IArchiveOpenCallback *This);
ULONG (STDMETHODCALLTYPE *Release) (IArchiveOpenCallback *This);
// IArchiveOpenCallback methods
HRESULT (STDMETHODCALLTYPE *SetTotal) (IArchiveOpenCallback *This, const UInt64 * files, const UInt64 * bytes);
HRESULT (STDMETHODCALLTYPE *SetCompleted) (IArchiveOpenCallback *This, const UInt64 * files, const UInt64 * bytes);
}IArchiveOpenCallbackVtbl;
typedef struct IArchiveOpenCallback {
const struct IArchiveOpenCallbackVtbl *lpVtbl;
DWORD nRefCount;
IInArchive *pIInArchive;
}IArchiveOpenCallback;

extern const GUID IID_IArchiveExtractCallback;
typedef struct IArchiveExtractCallback IArchiveExtractCallback;
typedef struct IArchiveExtractCallbackVtbl {
// IUnknown methods
HRESULT (STDMETHODCALLTYPE *QueryInterface) (IArchiveExtractCallback *, REFIID riid, void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef) (IArchiveExtractCallback *This);
ULONG (STDMETHODCALLTYPE *Release) (IArchiveExtractCallback *This);
// IArchiveExtractCallback methods
HRESULT (STDMETHODCALLTYPE *SetTotal) (IArchiveExtractCallback *This, UInt64 total);
HRESULT (STDMETHODCALLTYPE *SetCompleted) (IArchiveExtractCallback *This, const UInt64 * completeValue);
HRESULT (STDMETHODCALLTYPE *GetStream) (IArchiveExtractCallback *This, UInt32 index, ISequentialOutStream ** outStream, Int32 askExtractMode);
HRESULT (STDMETHODCALLTYPE *PrepareOperation) (IArchiveExtractCallback *This, Int32 askExtractMode);
HRESULT (STDMETHODCALLTYPE *SetOperationResult) (IArchiveExtractCallback *This, Int32 opRes);
}IArchiveExtractCallbackVtbl;
typedef struct IArchiveExtractCallback {
const struct IArchiveExtractCallbackVtbl *lpVtbl;
DWORD nRefCount;
IInArchive *pIInArchive;
}IArchiveExtractCallback;

typedef int (WINAPI CREATEOBJECT)(const GUID *clsid, const GUID *iid, void **outObject);
typedef CREATEOBJECT *PCREATEOBJECT;

#endif // _7ZC_H
7zDll.c
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//#include <ole2.h>
#include <propidl.h>
#include "7zC1.h"

const GUID IID_IArchiveExtractCallback = {0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x20, 0x00, 0x00};
//const GUID IID_CompressProgressInfo = {0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00};
//const GUID IID_IArchiveExtractCallbackMessage = {0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x21, 0x00, 0x00};

HRESULT WINAPI IInStream_QueryInterface(IInStream * This, REFIID riid, void **ppvObject)
{
return E_NOINTERFACE;
}

ULONG WINAPI IInStream_AddRef(IInStream * This)
{
return This->nRefCount;
}

ULONG WINAPI IInStream_Release(IInStream * This)
{
This->nRefCount--;
if (This->nRefCount == 0) {
CloseHandle(This->hFile);
This->hFile = (void*)-1;
}
return This->nRefCount;
}

HRESULT WINAPI IInStream_Read(ISequentialInStream *This, void *data, UInt32 size, UInt32 *processedSize)
{
ReadFile(This->hFile, data, size, processedSize,  NULL);
return 0;
}

HRESULT WINAPI IInStream_Seek(IInStream *This, Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{// STREAM_SEEK_SET  = 0,STREAM_SEEK_CUR  = 1,STREAM_SEEK_END  = 2
if(seekOrigin >= 3)
return STG_E_INVALIDFUNCTION;
return !SetFilePointerEx(This->hFile, *(LARGE_INTEGER*)&offset, (LARGE_INTEGER*)newPosition, seekOrigin);
}

const IInStreamVtbl IInStreamTable = {
IInStream_QueryInterface,
IInStream_AddRef,
IInStream_Release,
IInStream_Read,
IInStream_Seek,
};
IInStream InStream = { &IInStreamTable, 0, (void*)-1 };

HRESULT WINAPI IOutStream_QueryInterface(IOutStream * This, REFIID riid, void **ppvObject)
{
return E_NOINTERFACE;
}

ULONG WINAPI IOutStream_AddRef(IOutStream * This)
{
This->nRefCount++;
return This->nRefCount;
}

ULONG WINAPI IOutStream_Release(IOutStream * This)
{
This->nRefCount--;
if (This->nRefCount == 0) {
CloseHandle(This->hFile);
This->hFile = (void*)-1;
}
return This->nRefCount;
}

HRESULT WINAPI IOutStream_Write(ISequentialOutStream *This, const void *data, UInt32 size, UInt32 *processedSize)
{
WriteFile(This->hFile, data, size, processedSize,  NULL);
return 0;
}

HRESULT WINAPI IOutStream_Seek(IOutStream *This, Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{// STREAM_SEEK_SET  = 0, STREAM_SEEK_CUR  = 1, STREAM_SEEK_END  = 2
if(seekOrigin >= 3)
return STG_E_INVALIDFUNCTION;
return !SetFilePointerEx(This->hFile, *(LARGE_INTEGER*)&offset, (LARGE_INTEGER*)newPosition, seekOrigin);
}

HRESULT WINAPI IOutStream_SetSize(IOutStream *This, UInt64 newSize)
{
return E_NOTIMPL;
}

const IOutStreamVtbl IOutStreamTable = {
IOutStream_QueryInterface,
IOutStream_AddRef,
IOutStream_Release,
IOutStream_Write,
IOutStream_Seek,
IOutStream_SetSize
};
IOutStream OutStream = { &IOutStreamTable, 0, (void*)-1 };

/// IArchiveOpenCallback
HRESULT WINAPI IArchiveOpenCallback_QueryInterface(IArchiveOpenCallback * This, REFIID riid, void **ppvObject)
{
*ppvObject = This;
return 0;
}

ULONG WINAPI IArchiveOpenCallback_AddRef(IArchiveOpenCallback * This)
{
This->nRefCount++;
//return InterlockedIncrement(This->nRefCount);
return This->nRefCount;
}

ULONG WINAPI IArchiveOpenCallback_Release(IArchiveOpenCallback * This)
{
This->nRefCount--;
//return InterlockedDecrement(This->nRefCount);
return This->nRefCount;
}

HRESULT WINAPI IArchiveOpenCallback_SetTotal(IArchiveOpenCallback *This, const UInt64 * files, const UInt64 * bytes)
{
return 0;
}

HRESULT WINAPI IArchiveOpenCallback_SetCompleted(IArchiveOpenCallback *This, const UInt64 * files, const UInt64 * bytes)
{
return E_NOTIMPL;
}

const IArchiveOpenCallbackVtbl IArchiveOpenCallbackTable = {
IArchiveOpenCallback_QueryInterface,
IArchiveOpenCallback_AddRef,
IArchiveOpenCallback_Release,
IArchiveOpenCallback_SetTotal,
IArchiveOpenCallback_SetCompleted
};
IArchiveOpenCallback ArchiveOpenCallback = { &IArchiveOpenCallbackTable, 0};

ULONG WINAPI IArchiveExtractCallback_AddRef(IArchiveExtractCallback *This);
/// IArchiveExtractCallback
HRESULT WINAPI IArchiveExtractCallback_QueryInterface(IArchiveExtractCallback *This, REFIID riid, void **ppvObject)
{
if (!memcmp(riid, &IID_IArchiveExtractCallback, sizeof(GUID))) {
IArchiveExtractCallback_AddRef(This);
*ppvObject = This;
return 0;
}
/* if (!memcmp(riid, &IID_CompressProgressInfo, sizeof(GUID))) {
*ppvObject = &CompressProgressInfo;
return 0;
}
if (!memcmp(riid, &IID_IArchiveExtractCallbackMessage, sizeof(GUID))) {
*ppvObject = &ArchiveExtractCallbackMessage;
return 0;
}*/
*ppvObject = 0;
return E_NOINTERFACE;
}

ULONG WINAPI IArchiveExtractCallback_AddRef(IArchiveExtractCallback *This)
{
This->nRefCount++;
return This->nRefCount;
}

ULONG WINAPI IArchiveExtractCallback_Release(IArchiveExtractCallback *This)
{
This->nRefCount--;
return This->nRefCount;
}

HRESULT WINAPI IArchiveExtractCallback_SetTotal(IArchiveExtractCallback *This, UInt64 total)
{
return 0;
}

HRESULT WINAPI IArchiveExtractCallback_SetCompleted(IArchiveExtractCallback *This, const UInt64 * completeValue)
{
return 0;
}

HRESULT WINAPI IArchiveExtractCallback_GetStream(IArchiveExtractCallback *This, UInt32 index, ISequentialOutStream ** outStream, Int32 askExtractMode)
{
if (askExtractMode)
return 0;
PROPVARIANT pv;
HRESULT hr;
IInArchive *pIInArchive = This->pIInArchive;
// hr = This->pIInArchive->lpVtbl->GetProperty(This->pIInArchive, index, 3, &pv); // kpidPath = 3
hr = pIInArchive->lpVtbl->GetProperty(pIInArchive, index, 3, &pv); // kpidPath = 3
OutStream.hFile = CreateFileW(pv.bstrVal, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
*outStream = (ISequentialOutStream*)&OutStream;
IOutStream_AddRef(&OutStream);
return 0;
}

HRESULT WINAPI IArchiveExtractCallback_PrepareOperation(IArchiveExtractCallback *This, Int32 askExtractMode)
{
return 0;
}

HRESULT WINAPI IArchiveExtractCallback_SetOperationResult(IArchiveExtractCallback *This, Int32 opRes)
{
return 0;
}

const IArchiveExtractCallbackVtbl IArchiveExtractCallbackTable = {
IArchiveExtractCallback_QueryInterface,
IArchiveExtractCallback_AddRef,
IArchiveExtractCallback_Release,
IArchiveExtractCallback_SetTotal,
IArchiveExtractCallback_SetCompleted,
IArchiveExtractCallback_GetStream,
IArchiveExtractCallback_PrepareOperation,
IArchiveExtractCallback_SetOperationResult
};
IArchiveExtractCallback ArchiveExtractCallback = { &IArchiveExtractCallbackTable, 0, 0};
Title: Re: 7z test
Post by: jj2007 on September 16, 2017, 02:01:04 AM
Interesting. Did you find proper documentation for the DLL?

I think your work deserves some good music (https://www.youtube.com/watch?v=zuImkmDCDME) ;-)
Title: Re: 7z test
Post by: TimoVJL on September 16, 2017, 10:46:29 AM
No i didn't :(
These headers was helpful:
IArchive.h
IStream.h
PropID.h
Guid.txt

and AutoIt3 forum examples helped me.

EDIT: Easier to read SevenZip++ (https://bitbucket.org/cmcnab/sevenzip/src/db32105a1995/SevenZip++/)
Title: Re: 7z test
Post by: Stefan Pendl on September 16, 2017, 12:53:23 PM
At http://www.7-zip.org/ you can download the SDK and the sources, so there should be enough information.