Jump to content
Starg

Calling 7z.dll

Recommended Posts

Starg

First of all, please read this:

>7z UDF WIP : Can 7z.dll be used in AutoIt?

I'd like to start a new topic because dany seems to have given up the idea and has been off-line for about eight months.

I've tried 7z.au3 and found a few bugs.

  • GUID verification fails due to the bad regex
  • GUIDs defined in the UDF are wrong. For example, $7Z_INTERFACE_IN_ARCHIVE should be {

    23170F69-40C1-278A-0000-000600

    600000}

After correcting them, I succeeded in calling CreateObject. However, I can't find a way to use the objects created by CreateObject.

Can anyone help me please?

Share this post


Link to post
Share on other sites
Artisan

My Google-fu is not up to this task, it seems.  The 7-Zip documentation is lacking in the extreme.  The only maybe-sorta helpful thing I could find was this:

http://www.codeproject.com/Articles/27148/C-NET-Interface-for-7-Zip-Archive-DLLs

It doesn't elaborate on what the objects are or how to interact with them, but I didn't get into the details and I'm not a C# person.  Maybe you'll have better luck with it.

Share this post


Link to post
Share on other sites
Starg

Artisan,

Thanks for providing me a link, but I've read that before.

Share this post


Link to post
Share on other sites
Starg

I managed to create IInArchive instance, but I don't know how to call open() method.

Share this post


Link to post
Share on other sites
Starg

Is IInArchive instance structure of function pointers?

From 7-Zip IArchive.h

#define INTERFACE_IInArchive(x) \
  STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \
  STDMETHOD(Close)() x; \
  STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \
  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
  STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \
  STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \
  STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
  STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
  STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \
  STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;
Edited by Starg

Share this post


Link to post
Share on other sites
trancexx

So if you know that what exactly is the problem?

 

#include <WinApi.au3>

; ZIP CLSID
Global Const $sCLSID_Zip = "{23170f69-40c1-278a-1000-000110010000}"

; Interface IInArchive is defined like this:
Global Const $sIID_IInArchive = "{23170F69-40C1-278A-0000-000600600000}"
Global Const $tagIInArchive = _
        "Open hresult(ptr;uint64*;ptr);" & _
        "Close hresult();" & _
        "GetNumberOfItems hresult(uint*);" & _
        "GetProperty hresult(uint;int;variant*);" & _
        "Extract hresult(uint;uint;int;ptr);" & _
        "GetArchiveProperty hresult(int;variant*);" & _
        "GetNumberOfProperties hresult(uint*);" & _
        "GetPropertyInfo hresult(uint;bstr*;int*;int*);" & _
        "GetNumberOfArchiveProperties hresult(uint*);" & _
        "GetArchivePropertyInfo hresult(uint;bstr*;int*;int*);"

Global Const $h7ZIP_DLL = DllOpen("C:\Program Files\7-Zip\7z.dll") ; for me it would be this location. You set yours.

Local $oIInArchive = Create_7Z_Object($sCLSID_Zip, $sIID_IInArchive, $tagIInArchive)

;... Do whatever you want with this object here...

; The end


; An super cool function would be:
Func Create_7Z_Object($sCLSID, $sIID, $sTag)
    ; Guids
    Local $tCLSID = _WinAPI_GUIDFromString($sCLSID)
    Local $tIID = _WinAPI_GUIDFromString($sIID)
    ; Actual call. $h7ZIP_DLL is DllOpen-ed 7z.dll
    Local $aCall = DllCall($h7ZIP_DLL, "long", "CreateObject", "struct*", $tCLSID, "struct*", $tIID, "ptr*", 0)
    ; Check for errors of some kind
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    ; Make object out of pointer
    Return ObjCreateInterface($aCall[3], $sIID, $sTag)
EndFunc
 

What I can see as possible problem is IInStream interface implementation. The thing is you have to do it manually but considering you had issues with the above, somehow I think you won't be able to do it.

...Ask for help when you hit the wall.

Edited by trancexx
  • Like 1

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
milky

Hello trancexx,

I ask for help ;)

Creating an object of IInArchive is really easy, thanks for pointing that out. But how to do the thing with the streams... I tried to wrap most of 7z.dll interface, but only the IInArchive thing seems working. But this one will need streams...

I also don't know, if DllCallbackRegister() and friends would be needed?

Could someone help me a bit with that... just some pointing out, not more :sweating:

; /TR ctime 2014-05-02
; -> totale alpha....
; vllt. wird es so etwas wie eine UDF für 7z.dll ... falls ich es hinbekomme, wirds auf jeden fall open source, gplv2

#include <Array.au3>
#include <WinApi.au3>

; 7-Zip CLSID Handler                               {23170F69-40C1-278A-1000-000110xx0000}
Global Const $sCLSID_Format7z                    = "{23170f69-40c1-278a-1000-000110070000}" ; 7z

; IProgress.h                                       {23170F69-40C1-278A-0000-000000050000}
Global Const $sIID_IProgress2                    = "{23170F69-40C1-278A-0000-000000050000}" ; $sTagIProgress2

; IFolderArchive.h                                  {23170F69-40C1-278A-0000-000100xx0000}
Global Const $sIID_IArchiveFolder                = "{23170F69-40C1-278A-0000-000100050000}" ;x $sTagIArchiveFolder
Global Const $sIID_IOutFolderArchive             = "{23170F69-40C1-278A-0000-0001000a0000}" ;x $sTagIOutFolderArchive
Global Const $sIID_IFolderArchiveUpdateCallback  = "{23170F69-40C1-278A-0000-0001000b0000}" ;x $sTagIFolderArchiveUpdateCallback
Global Const $sIID_IInFolderArchive              = "{23170F69-40C1-278A-0000-0001000e0000}" ;x $sTagIInFolderArchive

; IStream.h                                         {23170F69-40C1-278A-0000-000300xx0000}
Global Const $sIID_ISequentialInStream           = "{23170F69-40C1-278A-0000-000300010000}" ; $sTagISequentialInStream
Global Const $sIID_ISequentialOutStream          = "{23170F69-40C1-278A-0000-000300020000}" ; $sTagISequentialOutStream
Global Const $sIID_IInStream                     = "{23170F69-40C1-278A-0000-000300030000}" ; $sTagIInStream
Global Const $sIID_IOutStream                    = "{23170F69-40C1-278A-0000-000300040000}" ; $sTagIOutStream
Global Const $sIID_IStreamGetSize                = "{23170F69-40C1-278A-0000-000300060000}" ; $sTagIStreamGetSize
Global Const $sIID_IOutStreamFlush               = "{23170F69-40C1-278A-0000-000300070000}" ; $sTagIOutStreamFlush

; ICoder.h                                          {23170F69-40C1-278A-0000-000400xx0000}
; ...

; IPassword.h                                       {23170F69-40C1-278A-0000-000500xx0000}
Global Const $sIID_ICryptoGetTextPassword        = "{23170F69-40C1-278A-0000-000500100000}" ; $sTagICryptoGetTextPassword
Global Const $sIID_ICryptoGetTextPassword2       = "{23170F69-40C1-278A-0000-000500200000}" ; $sTagICryptoGetTextPassword2

; IArchive.h                                        {23170F69-40C1-278A-0000-000600xx0000}
Global Const $sIID_ISetProperties                = "{23170F69-40C1-278A-0000-000600030000}"
Global Const $sIID_IArchiveOpenCallback          = "{23170F69-40C1-278A-0000-000600100000}" ; $sTagIArchiveOpenCallback
Global Const $sIID_IArchiveExtractCallback       = "{23170F69-40C1-278A-0000-000600200000}" ; $sTagIArchiveExtractCallback
Global Const $sIID_IArchiveOpenVolumeCallback    = "{23170F69-40C1-278A-0000-000600300000}" ; $sTagIArchiveOpenVolumeCallback
Global Const $sIID_IInArchiveGetStream           = "{23170F69-40C1-278A-0000-000600400000}" ; $sTagIInArchiveGetStream
Global Const $sIID_IArchiveOpenSetSubArchiveName = "{23170F69-40C1-278A-0000-000600500000}" ; $sTagIArchiveOpenSetSubArchiveName
Global Const $sIID_IInArchive                    = "{23170F69-40C1-278A-0000-000600600000}" ; $sTagIInArchive
Global Const $sIID_IArchiveOpenSeq               = "{23170F69-40C1-278A-0000-000600610000}" ; $sTagIArchiveOpenSeq
Global Const $sIID_IArchiveUpdateCallback        = "{23170F69-40C1-278A-0000-000600800000}" ; $sTagIArchiveUpdateCallback
Global Const $sIID_IArchiveUpdateCallback2       = "{23170F69-40C1-278A-0000-000600820000}" ; $sTagIArchiveUpdateCallback2
Global Const $sIID_IOutArchive                   = "{23170F69-40C1-278A-0000-000600A00000}" ; $sTagIOutArchive

; IProgress.h $sIID_IProgress2
Global Const $sTagIProgress2 = _
    "SetTotal hresult(uint64);" & _             ; STDMETHOD(SetTotal)(UInt64 total) x; \
    "SetCompleted hresult(uint64*);"            ; STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \

; IStream.h  0x01  $sIID_ISequentialInStream
Global Const $sTagISequentialInStream = _
    "Read hresult(ptr,uint,uint32*);"           ; STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
#cs
   Out: if size != 0, return_value = S_OK and (*processedSize == 0),
    then there are no more bytes in stream.
  if (size > 0) && there are bytes in stream,
  this function must read at least 1 byte.
  This function is allowed to read less than number of remaining bytes in stream.
  You must call Read function in loop, if you need exact amount of data
#ce

; IStream.h  0x02  $sIID_ISequentialOutStream
Global Const $sTagISequentialOutStream = _
    "Write hresult(ptr,uint,uint32*);"          ; STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;
#cs
  if (size > 0) this function must write at least 1 byte.
  This function is allowed to write less than "size".
  You must call Write function in loop, if you need to write exact amount of data
#ce

; IStream.h  0x03  $sIID_IInStream
Global Const $sTagIInStream = _
    "Read hresult(ptr,uint,uint32*);" & _       ; STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
    "Seek hresult(int64,uint,uint64*);"         ; STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;

; IStream.h  0x04  $sIID_IOutStream
Global Const $sTagIOutStream = _
    "Write hresult(ptr,uint,uint32*);" & _      ; STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;
    "Seek hresult(int64,uint,uint64*);" & _     ; STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
    "SetSize hresult(uint64);"                  ; STDMETHOD(SetSize)(UInt64 newSize) PURE;

; IStream.h  0x06  $sIID_IStreamGetSize
Global Const $sTagIStreamGetSize = _
    "GetSize hresult(uint64*);"                 ; STDMETHOD(GetSize)(UInt64 *size) PURE;

; IStream.h  0x07  $sIID_IOutStreamFlush
Global Const $sTagIOutStreamFlush = _
    "Flush hresult();"                          ; STDMETHOD(Flush)() PURE;

; IPassword.h 0x10 $sIID_ICryptoGetTextPassword
Global Const $sTagICryptoGetTextPassword = _
    "CryptoGetTextPassword hresult(str);"       ; STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE;

; IPassword.h 0x11 $sIID_ICryptoGetTextPassword2
Global Const $sTagICryptoGetTextPassword2 = _
    "CryptoGetTextPassword2 hresult(int*,str);" ; STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE;

; IArchive.h 0x10 $sIID_IArchiveOpenCallback
Global Const $sTagIArchiveOpenCallback = _
    "SetTotal hresult(uint64*,uint64*);" & _   ; STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \
    "SetCompleted hresult(uint64*,uint64*);"   ; STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \

; IArchive.h 0x20 $sIID_IArchiveExtractCallback
Global Const $sTagIArchiveExtractCallback = _
    "SetTotal hresult(uint64);" & _            ; STDMETHOD(SetTotal)(UInt64 total) x; \
    "SetCompleted hresult(uint64*);" & _       ; STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \
    "GetStream hresult(uint,ptr*,int);" & _    ; STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream,  Int32 askExtractMode) x; \
    "PrepareOperation hresult(int);" & _       ; STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \
    "SetOperationResult hresult(int);"         ; STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \

; IArchive.h 0x30 $sIID_IArchiveOpenVolumeCallback
Global Const $sTagIArchiveOpenVolumeCallback = _
    "GetProperty hresult(int,variant*);" & _   ; STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \
    "GetStream hresult(wstr,ptr*);"            ; STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \

; IArchive.h 0x40 $sIID_IInArchiveGetStream
Global Const $sTagIInArchiveGetStream = _
    "GetStream hresult(uint,ptr*);"            ; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;

; IArchive.h 0x50 $sIID_IArchiveOpenSetSubArchiveName
Global Const $sTagIArchiveOpenSetSubArchiveName = _
    "SetSubArchiveName hresult(wstr);"         ; STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;

; IArchive.h 0x60 $sIID_IInArchive
Global Const $sTagIInArchive = _
    "Open hresult(ptr;uint64*;ptr);" & _                     ; STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \
    "Close hresult();" & _                                   ; STDMETHOD(Close)() x; \
    "GetNumberOfItems hresult(uint*);" & _                   ; STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \
    "GetProperty hresult(uint;int;variant*);" & _            ; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
    "Extract hresult(uint;uint;int;ptr);" & _                ; STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \
    "GetArchiveProperty hresult(int;variant*);" & _          ; STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \
    "GetNumberOfProperties hresult(uint*);" & _              ; STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
    "GetPropertyInfo hresult(uint;bstr*;int*;int*);" & _     ; STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
    "GetNumberOfArchiveProperties hresult(uint*);" & _       ; STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \
    "GetArchivePropertyInfo hresult(uint;bstr*;int*;int*);"  ; STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;

; IArchive.h 0x61 $sIID_IArchiveOpenSeq
Global Const $sTagIArchiveOpenSeq = "OpenSeq hresult();" ; STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE;

; IArchive.h 0x80 $sIID_IArchiveUpdateCallback
Global Const $sTagIArchiveUpdateCallback = _
    "SetTotal hresult(uint64);" & _                        ; STDMETHOD(SetTotal)(UInt64 total) x; \
    "SetCompleted hresult(uint64*);" & _                   ; STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \
    "GetUpdateItemInfo hresult(uint,int*,int*,int*);" & _  ; STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)  x; \
    "GetProperty hresult(uint,int,variant*);" &          _ ; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
    "GetStream hresult(uint,ptr*);" & _                    ; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \
    "SetOperationResult hresult(int);"                     ; STDMETHOD(SetOperationResult)(Int32 operationResult) x; \

; IArchive.h 0x82 $sIID_IArchiveUpdateCallback2
Global Const $sTagIArchiveUpdateCallback2 = _
    "SetTotal hresult(uint64);" & _                        ; STDMETHOD(SetTotal)(UInt64 total) x; \
    "SetCompleted hresult(uint64*);" & _                   ; STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \
    "GetUpdateItemInfo hresult(uint,int*,int*,uint*);" & _ ; STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)  x; \
    "GetProperty hresult(uint,int,variant*);" & _          ; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
    "GetStream hresult(uint,ptr*);" & _                    ; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \
    "SetOperationResult hresult(int);" & _                 ; STDMETHOD(SetOperationResult)(Int32 operationResult) x; \
    "GetVolumeSize hresult(uint,uint64*);" & _             ; STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \
    "GetVolumeStream hresult(uint,ptr*);"                  ; STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \

; IArchive.h 0xA0 $sIID_IOutArchive
Global Const $sTagIOutArchive = _
    "UpdateItems hresult(ptr;uint;ptr);" & _               ; STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \
    "GetFileTimeTypehresult(uint*);"                       ; STDMETHOD(GetFileTimeType)(UInt32 *type) x;

; XXX, später dann mal: 7za-x32.dll / 7za-x64.dll (von 7zip.org)
Global Const $h7Z_DLL = DllOpen(@ScriptDir & "\7z.dll") ; je nach system erstmal per hand anpassen
If $h7z_DLL = -1 Then
    MsgBox(0, "error", "fehler beim laden der dll")
    Exit
EndIf

#cs
7z.dll hat folgende Funktionen:
UInt32 WINAPI CreateObject(const GUID *clsID, const GUID *interfaceID, void **outObject);
UInt32 WINAPI GetNumberOfMethods(UInt32 *numMethods);
UInt32 WINAPI GetNumberOfFormats(UInt32 *numFormats);
UInt32 WINAPI GetMethodProperty(UInt32 index, PROPID propID, PROPVARIANT *value);
UInt32 WINAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value);
UInt32 WINAPI GetHandlerProperty2(UInt32 index, PROPID propID, PROPVARIANT *value);
UInt32 WINAPI SetLargePageMode();
#ce
; todo: beschreibung
Func _7z_GetNumberOfMethods()
    Local $aCall = DllCall($h7z_DLL, 'uint', 'GetNumberOfMethods', 'uint*', 0)
    If @error <> 0 Then
        MsgBox(0, "error", "fehler _7z_GetNumberOfMethods()")
        Exit
    EndIf
    Return $aCall[1]
EndFunc   ;==>_7z_GetNumberOfMethods

; todo: beschreibung
Func _7z_GetNumberOfFormats()
    Local $aCall = DllCall($h7z_DLL, 'uint', 'GetNumberOfFormats', 'uint*', 0)
    If @error <> 0 Then
        MsgBox(0, "error", "fehler _7z_GetNumberOfFormats()")
        Exit
    EndIf
    Return $aCall[1]
EndFunc   ;==>_7z_GetNumberOfMethods

Func Create_7Z_Object($sCLSID, $sIID, $sTag)
    Local $tCLSID = _WinAPI_GUIDFromString($sCLSID)
    Local $tIID = _WinAPI_GUIDFromString($sIID)

    ; CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
    Local $aCall = DllCall($h7z_DLL, "long", "CreateObject", "struct*", $tCLSID, "struct*", $tIID, "ptr*", 0)
    ;_ArrayDisplay($aCall)

    MsgBox(0,"call:", "DllCall() " & _
        @CRLF & "$sCLSID = " & $sCLSID & @CRLF & "sIID = " & $sIID & @CRLF & "$sTag = " & $sTag)

   If @error Or $aCall[0] Then
        MsgBox(0,"error", "DllCall() @ Create_7Z_Object nicht ok: " & @error & " @ " & $sIID)
        ;_ArrayDisplay($aCall)
        Exit
    EndIf

    Local $oObj = ObjCreateInterface($aCall[3], $sIID, $sTag)
    If IsObj($oObj) Then
        Return $oObj
    EndIf

    ; fatal error
    MsgBox(0,"Create_7Z_Object() fehlgeschlagen... obj=", IsObj($oObj))
    Exit
EndFunc


; das hier geht:
;MsgBox(0,@ScriptName, "methods=" & _7z_GetNumberOfMethods())
;MsgBox(0,@ScriptName, "methods=" & _7z_GetNumberOfFormats())
;Local $oIArchive = Create_7Z_Object($sCLSID_Format7z, $sIID_IInArchive, $sTagIInArchive)

; das geht nicht:
; Local $oTest = Create_7Z_Object($sCLSID_Format7z, $sIID_ISequentialOutStream, $sTagISequentialOutStream)

; wie muss ich hier das stream interface bereitstellen?
; muss ich so etwas wie AutoItObject 1.2.8.3 verwenden, oder geht das auch direkt via autoit?

Share this post


Link to post
Share on other sites
trancexx

Yes, you need callbacks to create stream object(s). Find function ObjectFromTag - I posted it in one thread in examples, it does everything for you. Then create windows' stream (IStream, or even a bit extended ISequentialStream) with CreateStreamOnHglobal and use it wrapped inside your stream object methods. It may sound complicated, but it's very simple task, you'll see.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
milky

Thank you, for the very fast reply.

I will try my best and give some information, when I got it ;)

Share this post


Link to post
Share on other sites
trancexx

Hah! Did you see that. I started writing the post as soon as you posted yours. If I'd be faster writer you would have my reply in the same minute. Hell, even before you posted the question.

...but I'm slow, don't know English that good, have a bit longer nails then I should for this sport, and was watching some porn thingy in another tab.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
milky

Hm, I don't get :(

I found these functions on MSDN, I think I have to use them via dllcall... but I don't get it managed with the object stuff of this DLL. It is a COM like interface, but the author says, it is not Standard... :(

HRESULT SHCreateStreamOnFile(
  _In_   LPCTSTR pszFile,
  _In_   DWORD grfMode,
  _Out_  IStream **ppstm
);

WINOLEAPI GetHGlobalFromStream(
  _In_   IStream *pstm,
  _Out_  HGLOBAL *phglobal
);

WINOLEAPI CreateStreamOnHGlobal(
  _In_   HGLOBAL hGlobal,
  _In_   BOOL fDeleteOnRelease,
  _Out_  LPSTREAM *ppstm
);

And with for ObjectFromTag() function, should I do it that way ?

Func ObjectFromTag($sFunctionPrefix, $tagInterface, ByRef $tInterface)
    Local Const $tagIUnknown = "QueryInterface hresult(ptr;ptr*); AddRef dword(); Release dword();"

    ; Adding IUnknown methods
    $tagInterface = $tagIUnknown & $tagInterface
    Local Const $PTR_SIZE = DllStructGetSize(DllStructCreate("ptr"))

    ; Below line really simple even though it looks super complex. It's just written weird to fit one line, not to steal your eyes
    Local $aMethods = StringSplit(StringReplace(StringReplace(StringReplace(StringReplace(StringTrimRight(StringReplace(StringRegExpReplace($tagInterface, "\h*(\w+)\h*(\w+\*?)\h*(\((.*?)\))\h*(;|;*\z)", "$1\|$2;$4" & @LF), ";" & @LF, @LF), 1), "object", "idispatch"), "variant*", "ptr"), "hresult", "long"), "bstr", "ptr"), @LF, 3)
    Local $iUbound = UBound($aMethods)
    Local $sMethod, $aSplit, $sNamePart, $aTagPart, $sTagPart, $sRet, $sParams

    ; Allocation. Read http://msdn.microsoft.com/en-us/library/ms810466.aspx to see why like this (object + methods):
    $tInterface = DllStructCreate("ptr[" & $iUbound + 1 & "]")
    If @error Then Return SetError(1, 0, 0)
    For $i = 0 To $iUbound - 1
        $aSplit = StringSplit($aMethods[$i], "|", 2)
        If UBound($aSplit) <> 2 Then ReDim $aSplit[2]
        $sNamePart = $aSplit[0]
        $sTagPart = $aSplit[1]
        $sMethod = $sFunctionPrefix & $sNamePart
        $aTagPart = StringSplit($sTagPart, ";", 2)
        $sRet = $aTagPart[0]
        $sParams = StringReplace($sTagPart, $sRet, "", 1)
        $sParams = "ptr" & $sParams
        DllStructSetData($tInterface, 1, DllCallbackGetPtr(DllCallbackRegister($sMethod, $sRet, $sParams)), $i + 2) ; Freeing is left to AutoIt.
    Next
    DllStructSetData($tInterface, 1, DllStructGetPtr($tInterface) + $PTR_SIZE) ; Interface method pointers are actually pointer size away
    ConsoleWrite("huhu@obj")
    Return ObjCreateInterface(DllStructGetPtr($tInterface), "", $tagInterface, False) ; and first pointer is object pointer that's wrapped
EndFunc

; Global Const $sIID_IArchiveOpenCallback          = "{23170F69-40C1-278A-0000-000600100000}" ; $sTagIArchiveOpenCallback
Local $thIArchiveOpenCallback
$o = ObjectFromTag("IArchiveOpenCallback_", $sIID_IArchiveOpenCallback, $thIArchiveOpenCallback)

; Handler methods. "_MyHandler_" is the specified prefix:
Func IArchiveOpenCallback_QueryInterface($pSelf, $pRIID, $pObj)
    Local $tStruct = DllStructCreate("ptr", $pObj)
    ConsoleWrite("@query")
    Switch _WinAPI_StringFromGUID($pRIID)
        Case $sIID_IArchiveOpenCallback
        Case Else
            ConsoleWrite("error @ ..." & @CRLF)
            Return 0x80004002 ; E_NOINTERFACE
    EndSwitch
    DllStructSetData($tStruct, 1, $pSelf)
    Return 0 ; S_OK
EndFunc
Func IArchiveOpenCallback_AddRef($pSelf)
    #forceref $pSelf
    ConsoleWrite("@addref")
    Return 1
EndFunc
Func IArchiveOpenCallback_Release($pSelf)
    #forceref $pSelf
    ConsoleWrite("@release")
    Return 1
EndFunc

Func IArchiveOpenCallback_SetTotal(ByRef $iFiles, ByRef $iBytes)
    ConsoleWrite("IArchiveOpenCallback: files:" & $iFiles & " bytes:" & $iBytes & @CRLF)
EndFunc

Func IArchiveOpenCallback_SetCompleted(ByRef $iFiles, ByRef $iBytes)
    ConsoleWrite("IArchiveOpenCallback: files:" & $iFiles & " bytes:" & $iBytes & @CRLF)
EndFunc

I am coding C for a very long time, but Autoit is new for me... but I am interested in it. So sorry for my newbie questions... and I am again going to take lunch. So I am away for some Minutes. But then, I am back on the notebook and could maybe answer as fast as you :)

Share this post


Link to post
Share on other sites
trancexx

The most correct ObjectFromTag is at

What yo should do is first create IInArchive object with Create_7Z_Object (already posted), then you create stream on archive file (go with SHCreateStreamOnFile for now, since you found it on msdn even though it will prove slower later). Then create IInStream with ObjectFromTag which is similar task as IArchiveOpenCallback you already did, only you wrapp IStream you got with SHCreateStreamOnFile.

Then load archive using Open method of IInArchive.

Then post your code if something wouldn't work as it should.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
milky

Yes, I got the fresher code of ObjectFromTag() and also DeleteObjectFromTag() ... and made it an include file. This is how it looks like:

; Copied and slightly modified by LarsJ (for print methods) from this post by trancexx:
; http://www.autoitscript.com/forum/topic/153520-iuiautomation-ms-framework-automate-chrome-ff-ie/page*#entry1143566
#include <WinApi.au3>

Global Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}"

; Global $tIShellBrowser, $oIShellBrowser
; Global Const $sIID_IShellBrowser = "{000214E2-0000-0000-C000-000000000046}"
; Global Const $dtag_IShellBrowser = "GetWindow hresult(hwnd*);" & "..."
; $oIShellBrowser = ObjectFromTag("oIShellBrowser_", $dtag_IShellBrowser, $tIShellBrowser, Default, $sIID_IShellBrowser)
; If Not IsObj($oIShellBrowser) Then Return
Func StringFromGUID( $pGUID )
  Local $aResult = DllCall( "ole32.dll", "int", "StringFromGUID2", "struct*", $pGUID, "wstr", "", "int", 40 )
  If @error Then Return SetError( @error, @extended, "" )
  Return SetExtended( $aResult[0], $aResult[2] )
EndFunc

; Copied and slightly modified (print methods) from this post by trancexx:
; http://www.autoitscript.com/forum/topic/153520-iuiautomation-ms-framework-automate-chrome-ff-ie/page*#entry1143566
Func ObjectFromTag($sFunctionPrefix, $tagInterface, ByRef $tInterface, $fPrint = False, $bIsUnknown = Default, $sIID = "{00000000-0000-0000-C000-000000000046}") ; last param is IID_IUnknown by default
    If $bIsUnknown = Default Then $bIsUnknown = True
    Local $sInterface = $tagInterface ; copy interface description
    Local $tagIUnknown = "QueryInterface hresult(ptr;ptr*);" & _
            "AddRef dword();" & _
            "Release dword();"
    ; Adding IUnknown methods
    If $bIsUnknown Then $tagInterface = $tagIUnknown & $tagInterface
    ; Below line is really simple even though it looks super complex. It's just written weird to fit in one line, not to steal your attention
    Local $aMethods = StringSplit(StringReplace(StringReplace(StringReplace(StringReplace(StringTrimRight(StringReplace(StringRegExpReplace(StringRegExpReplace($tagInterface, "\w+\*", "ptr"), "\h*(\w+)\h*(\w+\*?)\h*(\((.*?)\))\h*(;|;*\z)", "$1\|$2;$4" & @LF), ";" & @LF, @LF), 1), "object", "idispatch"), "hresult", "long"), "bstr", "ptr"), "variant", "ptr"), @LF, 3)
    Local $iUbound = UBound($aMethods)
    Local $sMethod, $aSplit, $sNamePart, $aTagPart, $sTagPart, $sRet, $sParams, $hCallback
    ; Allocation
    $tInterface = DllStructCreate("int RefCount;int Size;ptr Object;ptr Methods[" & $iUbound & "];int_ptr Callbacks[" & $iUbound & "];ulong_ptr Slots[16]") ; 16 pointer sized elements more to create space for possible private props
    If @error Then Return SetError(1, 0, 0)
    For $i = 0 To $iUbound - 1
        $aSplit = StringSplit($aMethods[$i], "|", 2)
        If UBound($aSplit) <> 2 Then ReDim $aSplit[2]
        $sNamePart = $aSplit[0]
        $sTagPart = $aSplit[1]
        $sMethod = $sFunctionPrefix & $sNamePart
        If $fPrint Then
            Local $iPar = StringInStr( $sTagPart, ";", 2 ), $t
            If $iPar Then
                $t = "Ret: " & StringLeft( $sTagPart, $iPar - 1 ) & "  " & _
                     "Par: " & StringRight( $sTagPart, StringLen( $sTagPart ) - $iPar )
            Else
                $t = "Ret: " & $sTagPart
            EndIf
            Local $s = "Func " & $sMethod & _
                "( $pSelf ) ; " & $t & @CRLF & _
                "EndFunc" & @CRLF
            ConsoleWrite( $s )
        EndIf
        $aTagPart = StringSplit($sTagPart, ";", 2)
        $sRet = $aTagPart[0]
        $sParams = StringReplace($sTagPart, $sRet, "", 1)
        $sParams = "ptr" & $sParams
        $hCallback = DllCallbackRegister($sMethod, $sRet, $sParams)
        ConsoleWrite(@error & @CRLF & @CRLF)
        DllStructSetData($tInterface, "Methods", DllCallbackGetPtr($hCallback), $i + 1) ; save callback pointer
        DllStructSetData($tInterface, "Callbacks", $hCallback, $i + 1) ; save callback handle
    Next
    DllStructSetData($tInterface, "RefCount", 1) ; initial ref count is 1
    DllStructSetData($tInterface, "Size", $iUbound) ; number of interface methods
    DllStructSetData($tInterface, "Object", DllStructGetPtr($tInterface, "Methods")) ; Interface method pointers
    Return ObjCreateInterface(DllStructGetPtr($tInterface, "Object"), $sIID, $sInterface, $bIsUnknown) ; pointer that's wrapped into object
EndFunc

Func DeleteObjectFromTag(ByRef $tInterface)
    For $i = 1 To DllStructGetData($tInterface, "Size")
        DllCallbackFree(DllStructGetData($tInterface, "Callbacks", $i))
    Next
    $tInterface = 0
EndFunc

Now the new coding stuff... object oriented programming is not as easy, as all other say... in C there are just functions, some structures... and of cause my lovely pointers... but OO .. :(

So then, I get some closer to the streaming thing, hopefully ;)

; /TR ctime 2014-05-02
; vllt. wird es so etwas wie eine UDF für 7z.dll ... falls ich es hinbekomme, wirds auf jeden fall open source, gplv2
; -> pre pre pre pre alpha....

#include <Array.au3>
#include <WinApi.au3>

#include "ObjectFromTag.au3"

; 7-Zip CLSID Handler                               {23170F69-40C1-278A-1000-000110xx0000}
Global Const $sCLSID_Format7z                    = "{23170f69-40c1-278a-1000-000110070000}" ; 7z

; IProgress.h                                       {23170F69-40C1-278A-0000-000000050000}
Global Const $sIID_IProgress2                    = "{23170F69-40C1-278A-0000-000000050000}" ; $sTagIProgress2

; IFolderArchive.h                                  {23170F69-40C1-278A-0000-000100xx0000}
Global Const $sIID_IArchiveFolder                = "{23170F69-40C1-278A-0000-000100050000}" ;x $sTagIArchiveFolder
Global Const $sIID_IOutFolderArchive             = "{23170F69-40C1-278A-0000-0001000a0000}" ;x $sTagIOutFolderArchive
Global Const $sIID_IFolderArchiveUpdateCallback  = "{23170F69-40C1-278A-0000-0001000b0000}" ;x $sTagIFolderArchiveUpdateCallback
Global Const $sIID_IInFolderArchive              = "{23170F69-40C1-278A-0000-0001000e0000}" ;x $sTagIInFolderArchive

; IStream.h                                         {23170F69-40C1-278A-0000-000300xx0000}
Global Const $sIID_ISequentialInStream           = "{23170F69-40C1-278A-0000-000300010000}" ; $sTagISequentialInStream
Global Const $sIID_ISequentialOutStream          = "{23170F69-40C1-278A-0000-000300020000}" ; $sTagISequentialOutStream
Global Const $sIID_IInStream                     = "{23170F69-40C1-278A-0000-000300030000}" ; $sTagIInStream
Global Const $sIID_IOutStream                    = "{23170F69-40C1-278A-0000-000300040000}" ; $sTagIOutStream
Global Const $sIID_IStreamGetSize                = "{23170F69-40C1-278A-0000-000300060000}" ; $sTagIStreamGetSize
Global Const $sIID_IOutStreamFlush               = "{23170F69-40C1-278A-0000-000300070000}" ; $sTagIOutStreamFlush

; ICoder.h                                          {23170F69-40C1-278A-0000-000400xx0000}
; ...

; IPassword.h                                       {23170F69-40C1-278A-0000-000500xx0000}
Global Const $sIID_ICryptoGetTextPassword        = "{23170F69-40C1-278A-0000-000500100000}" ; $sTagICryptoGetTextPassword
Global Const $sIID_ICryptoGetTextPassword2       = "{23170F69-40C1-278A-0000-000500200000}" ; $sTagICryptoGetTextPassword2

; IArchive.h                                        {23170F69-40C1-278A-0000-000600xx0000}
Global Const $sIID_ISetProperties                = "{23170F69-40C1-278A-0000-000600030000}"
Global Const $sIID_IArchiveOpenCallback          = "{23170F69-40C1-278A-0000-000600100000}" ; $sTagIArchiveOpenCallback
Global Const $sIID_IArchiveExtractCallback       = "{23170F69-40C1-278A-0000-000600200000}" ; $sTagIArchiveExtractCallback
Global Const $sIID_IArchiveOpenVolumeCallback    = "{23170F69-40C1-278A-0000-000600300000}" ; $sTagIArchiveOpenVolumeCallback
Global Const $sIID_IInArchiveGetStream           = "{23170F69-40C1-278A-0000-000600400000}" ; $sTagIInArchiveGetStream
Global Const $sIID_IArchiveOpenSetSubArchiveName = "{23170F69-40C1-278A-0000-000600500000}" ; $sTagIArchiveOpenSetSubArchiveName
Global Const $sIID_IInArchive                    = "{23170F69-40C1-278A-0000-000600600000}" ; $sTagIInArchive
Global Const $sIID_IArchiveOpenSeq               = "{23170F69-40C1-278A-0000-000600610000}" ; $sTagIArchiveOpenSeq
Global Const $sIID_IArchiveUpdateCallback        = "{23170F69-40C1-278A-0000-000600800000}" ; $sTagIArchiveUpdateCallback
Global Const $sIID_IArchiveUpdateCallback2       = "{23170F69-40C1-278A-0000-000600820000}" ; $sTagIArchiveUpdateCallback2
Global Const $sIID_IOutArchive                   = "{23170F69-40C1-278A-0000-000600A00000}" ; $sTagIOutArchive

; IProgress.h $sIID_IProgress2
Global Const $sTagIProgress2 = _
    "SetTotal hresult(uint64);" & _             ; STDMETHOD(SetTotal)(UInt64 total) x; \
    "SetCompleted hresult(uint64*);"            ; STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \

; IStream.h  0x01  $sIID_ISequentialInStream
Global Const $sTagISequentialInStream = _
    "Read hresult(ptr,uint,uint32*);"           ; STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
#cs
   Out: if size != 0, return_value = S_OK and (*processedSize == 0),
    then there are no more bytes in stream.
  if (size > 0) && there are bytes in stream,
  this function must read at least 1 byte.
  This function is allowed to read less than number of remaining bytes in stream.
  You must call Read function in loop, if you need exact amount of data
#ce

; IStream.h  0x02  $sIID_ISequentialOutStream
Global Const $sTagISequentialOutStream = _
    "Write hresult(ptr,uint,uint32*);"          ; STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;
#cs
  if (size > 0) this function must write at least 1 byte.
  This function is allowed to write less than "size".
  You must call Write function in loop, if you need to write exact amount of data
#ce

; IStream.h  0x03  $sIID_IInStream
Global Const $sTagIInStream = _
    "Read hresult(ptr,uint,uint32*);" & _       ; STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
    "Seek hresult(int64,uint,uint64*);"         ; STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;

; IStream.h  0x04  $sIID_IOutStream
Global Const $sTagIOutStream = _
    "Write hresult(ptr,uint,uint32*);" & _      ; STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;
    "Seek hresult(int64,uint,uint64*);" & _     ; STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
    "SetSize hresult(uint64);"                  ; STDMETHOD(SetSize)(UInt64 newSize) PURE;

; IStream.h  0x06  $sIID_IStreamGetSize
Global Const $sTagIStreamGetSize = _
    "GetSize hresult(uint64*);"                 ; STDMETHOD(GetSize)(UInt64 *size) PURE;

; IStream.h  0x07  $sIID_IOutStreamFlush
Global Const $sTagIOutStreamFlush = _
    "Flush hresult();"                          ; STDMETHOD(Flush)() PURE;

; IPassword.h 0x10 $sIID_ICryptoGetTextPassword
Global Const $sTagICryptoGetTextPassword = _
    "CryptoGetTextPassword hresult(str);"       ; STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE;

; IPassword.h 0x11 $sIID_ICryptoGetTextPassword2
Global Const $sTagICryptoGetTextPassword2 = _
    "CryptoGetTextPassword2 hresult(int*,str);" ; STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE;

; IArchive.h 0x10 $sIID_IArchiveOpenCallback
Global Const $sTagIArchiveOpenCallback = _
    "SetTotal hresult(uint64*,uint64*);" & _   ; STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \
    "SetCompleted hresult(uint64*,uint64*);"   ; STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \

; IArchive.h 0x20 $sIID_IArchiveExtractCallback
Global Const $sTagIArchiveExtractCallback = _
    "SetTotal hresult(uint64);" & _            ; STDMETHOD(SetTotal)(UInt64 total) x; \
    "SetCompleted hresult(uint64*);" & _       ; STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \
    "GetStream hresult(uint,ptr*,int);" & _    ; STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream,  Int32 askExtractMode) x; \
    "PrepareOperation hresult(int);" & _       ; STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \
    "SetOperationResult hresult(int);"         ; STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \

; IArchive.h 0x30 $sIID_IArchiveOpenVolumeCallback
Global Const $sTagIArchiveOpenVolumeCallback = _
    "GetProperty hresult(int,variant*);" & _   ; STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \
    "GetStream hresult(wstr,ptr*);"            ; STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \

; IArchive.h 0x40 $sIID_IInArchiveGetStream
Global Const $sTagIInArchiveGetStream = _
    "GetStream hresult(uint,ptr*);"            ; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;

; IArchive.h 0x50 $sIID_IArchiveOpenSetSubArchiveName
Global Const $sTagIArchiveOpenSetSubArchiveName = _
    "SetSubArchiveName hresult(wstr);"         ; STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;

; IArchive.h 0x60 $sIID_IInArchive
Global Const $sTagIInArchive = _
    "Open hresult(ptr;uint64*;ptr);" & _                     ; STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \
    "Close hresult();" & _                                   ; STDMETHOD(Close)() x; \
    "GetNumberOfItems hresult(uint*);" & _                   ; STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \
    "GetProperty hresult(uint;int;variant*);" & _            ; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
    "Extract hresult(uint;uint;int;ptr);" & _                ; STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \
    "GetArchiveProperty hresult(int;variant*);" & _          ; STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \
    "GetNumberOfProperties hresult(uint*);" & _              ; STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
    "GetPropertyInfo hresult(uint;bstr*;int*;int*);" & _     ; STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
    "GetNumberOfArchiveProperties hresult(uint*);" & _       ; STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \
    "GetArchivePropertyInfo hresult(uint;bstr*;int*;int*);"  ; STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;

; IArchive.h 0x61 $sIID_IArchiveOpenSeq
Global Const $sTagIArchiveOpenSeq = "OpenSeq hresult();" ; STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE;

; IArchive.h 0x80 $sIID_IArchiveUpdateCallback
Global Const $sTagIArchiveUpdateCallback = _
    "SetTotal hresult(uint64);" & _                        ; STDMETHOD(SetTotal)(UInt64 total) x; \
    "SetCompleted hresult(uint64*);" & _                   ; STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \
    "GetUpdateItemInfo hresult(uint,int*,int*,int*);" & _  ; STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)  x; \
    "GetProperty hresult(uint,int,variant*);" &          _ ; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
    "GetStream hresult(uint,ptr*);" & _                    ; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \
    "SetOperationResult hresult(int);"                     ; STDMETHOD(SetOperationResult)(Int32 operationResult) x; \

; IArchive.h 0x82 $sIID_IArchiveUpdateCallback2
Global Const $sTagIArchiveUpdateCallback2 = _
    "SetTotal hresult(uint64);" & _                        ; STDMETHOD(SetTotal)(UInt64 total) x; \
    "SetCompleted hresult(uint64*);" & _                   ; STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \
    "GetUpdateItemInfo hresult(uint,int*,int*,uint*);" & _ ; STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)  x; \
    "GetProperty hresult(uint,int,variant*);" & _          ; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
    "GetStream hresult(uint,ptr*);" & _                    ; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \
    "SetOperationResult hresult(int);" & _                 ; STDMETHOD(SetOperationResult)(Int32 operationResult) x; \
    "GetVolumeSize hresult(uint,uint64*);" & _             ; STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \
    "GetVolumeStream hresult(uint,ptr*);"                  ; STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \

; IArchive.h 0xA0 $sIID_IOutArchive
Global Const $sTagIOutArchive = _
    "UpdateItems hresult(ptr;uint;ptr);" & _               ; STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \
    "GetFileTimeTypehresult(uint*);"                       ; STDMETHOD(GetFileTimeType)(UInt32 *type) x;

; XXX, später dann mal: 7za-x32.dll / 7za-x64.dll (von 7zip.org)
Global Const $h7Z_DLL = DllOpen(@ScriptDir & "\7z.dll") ; je nach system erstmal per hand anpassen
If $h7z_DLL = -1 Then
    MsgBox(0, "error", "fehler beim laden der dll")
    Exit
EndIf

#cs
functions of 7z.dll:
UInt32 WINAPI CreateObject(const GUID *clsID, const GUID *interfaceID, void **outObject);
UInt32 WINAPI GetNumberOfMethods(UInt32 *numMethods);
UInt32 WINAPI GetNumberOfFormats(UInt32 *numFormats);
UInt32 WINAPI GetMethodProperty(UInt32 index, PROPID propID, PROPVARIANT *value);
UInt32 WINAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value);
UInt32 WINAPI GetHandlerProperty2(UInt32 index, PROPID propID, PROPVARIANT *value);
UInt32 WINAPI SetLargePageMode();
#ce

; todo: beschreibung
Func _7z_GetNumberOfMethods()
    Local $aCall = DllCall($h7z_DLL, 'uint', 'GetNumberOfMethods', 'uint*', 0)
    If @error <> 0 Then
        MsgBox(0, "error", "fehler _7z_GetNumberOfMethods()")
        Exit
    EndIf
    Return $aCall[1]
EndFunc   ;==>_7z_GetNumberOfMethods

; todo: beschreibung
Func _7z_GetNumberOfFormats()
    Local $aCall = DllCall($h7z_DLL, 'uint', 'GetNumberOfFormats', 'uint*', 0)
    If @error <> 0 Then
        MsgBox(0, "error", "fehler _7z_GetNumberOfFormats()")
        Exit
    EndIf
    Return $aCall[1]
EndFunc   ;==>_7z_GetNumberOfMethods

; ---------------------------------------------------------------------------------------------------------------------------------

Func Create_7Z_Object($sCLSID, $sIID, $sTag)
    Local $tCLSID = _WinAPI_GUIDFromString($sCLSID)
    Local $tIID = _WinAPI_GUIDFromString($sIID)

    ; CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
    Local $aCall = DllCall($h7z_DLL, "long", "CreateObject", "struct*", $tCLSID, "struct*", $tIID, "ptr*", 0)
    ;_ArrayDisplay($aCall)
    ;MsgBox(0,"call:", "DllCall() " & @CRLF & "$sCLSID = " & $sCLSID & @CRLF & "sIID = " & $sIID & @CRLF & "$sTag = " & $sTag)
   If @error Or $aCall[0] Then
        MsgBox(0,"error", "DllCall() @ Create_7Z_Object nicht ok: " & @error & " @ " & $sIID)
        ;_ArrayDisplay($aCall)
        Exit
    EndIf

    Local $oObj = ObjCreateInterface($aCall[3], $sIID, $sTag)
    If IsObj($oObj) Then
        Return $oObj
    EndIf

    ; fatal error
    MsgBox(0,"Create_7Z_Object() fehlgeschlagen... obj=", IsObj($oObj))
    Exit
EndFunc

; ---------------------------------------------------------------------------------------------------------------------------------

; 1) What yo should do is first create IInArchive object with Create_7Z_Object (already posted)
Local $oIInArchive = Create_7Z_Object($sCLSID_Format7z, $sIID_IInArchive, $sTagIInArchive)
;Local $iItems = 0
;$iRet = $oIArchive.GetNumberOfItems($iItems)
;MsgBox(0,"","x=" & $iItems & "  r=" & $iRet)

; 2) then you create stream on archive file (go with SHCreateStreamOnFile for now, since you found it on msdn even though it will prove slower later)
; STGM_READWRITE    0x00000002L
; STGM_CREATE   0x00001000L
Func _WinAPI_SHCreateStreamOnFile($sFile)
    Local $iGrfMode = BitOR(0x00000002,0x00001000)
    Local $aCall = DllCall('shlwapi.dll', 'long', 'SHCreateStreamOnFile', 'str', $sFile, 'uint', $iGrfMode, 'ptr*', 0)
    If @error Or $aCall[0] <> 0 Then
        ConsoleWrite("error @ _WinAPI_SHCreateStreamOnFile" & @CRLF)
        Exit
    EndIf
    ;_ArrayDisplay($aCall)

    Return $aCall[3]
EndFunc   ;==>_WinAPI_SHCreateStreamOnFile

; lala.7z is a small testfile (created with 7zip)
$stream1 = _WinAPI_SHCreateStreamOnFile("lala.7z")

; 3) Then create IInStream with ObjectFromTag which is similar task as IArchiveOpenCallback you already did, only you wrapp IStream you got with SHCreateStreamOnFile.
Local $tIInStream ; interface

;Func ObjectFromTag($sFunctionPrefix, $tagInterface, ByRef $tInterface, $fPrint = False, $bIsUnknown = Default, $sIID = "{00000000-0000-0000-C000-000000000046}") ; last param is IID_IUnknown by default
Local $oIInStream = ObjectFromTag("IInStream_", $sTagIInStream, $tIInStream, True, Default, $sIID_IInStream)
;DeleteObjectFromTag($tIInStream)

; IInStream interface
Func IInStream_QueryInterface($pSelf, $pRIID, $pObj)
    Local $tStruct = DllStructCreate("ptr", $pObj)
    ConsoleWrite("@IInStream_QueryInterface" & @CRLF)
    Switch _WinAPI_StringFromGUID($pRIID)
        Case $sIID_IInStream
        Case Else
            ConsoleWrite("error @ IInStream_QueryInterface" & @CRLF)
            Return 0x80004002 ; E_NOINTERFACE
    EndSwitch
    DllStructSetData($tStruct, 1, $pSelf)
    ConsoleWrite("@IInStream_QueryInterface -> return S_OK" & @CRLF)
    Return 0 ; S_OK
EndFunc

Func IInStream_AddRef($pSelf)
    #forceref $pSelf
    ConsoleWrite("@IInStream_AddRef" & @CRLF)
    Return 1
EndFunc

Func IInStream_Release($pSelf)
    #forceref $pSelf
    ConsoleWrite("@IInStream_Release" & @CRLF)
    Return 1
EndFunc

;   "Read hresult(ptr,uint,uint32*);" & _       ; STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
Func IInStream_Read(ByRef $pData, $iSize, ByRef $iProcessedSize)
    ConsoleWrite("@IInStream_Read: $iSize:" & $iSize & " $iProcessedSize:" & $iProcessedSize & @CRLF)
    ; $stream1 ??
EndFunc

;   "Seek hresult(int64,uint,uint64*);"         ; STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
Func IInStream_Seek($iOffset, $iSeekOrigin, ByRef $iNewPosition)
    ConsoleWrite("@IInStream_Seek: $iSeekOrigin:" & $iSeekOrigin & " $iNewPosition:" & $iNewPosition & @CRLF)
    ; $stream1 ??
EndFunc

Local $tIArchiveOpenCallback
Local $oIArchiveOpenCallback = ObjectFromTag("IInStream_", $sTagIArchiveOpenCallback, $tIArchiveOpenCallback, True, Default, $sIID_IArchiveOpenCallback)
Func IArchiveOpenCallback_QueryInterface($pSelf, $pRIID, $pObj)
    Local $tStruct = DllStructCreate("ptr", $pObj)
    ConsoleWrite("@IArchiveOpenCallback_QueryInterface" & @CRLF)
    Switch _WinAPI_StringFromGUID($pRIID)
        Case $sIID_IArchiveOpenCallback
        Case Else
            Return 0x80004002 ; E_NOINTERFACE
    EndSwitch
    DllStructSetData($tStruct, 1, $pSelf)
    ConsoleWrite("@IArchiveOpenCallback_QueryInterface = OK" & @CRLF)
    Return 0 ; S_OK
EndFunc

Func IArchiveOpenCallback_AddRef($pSelf)
    #forceref $pSelf
    ConsoleWrite("@IArchiveOpenCallback_AddRef" & @CRLF)
    Return 1
EndFunc

Func IArchiveOpenCallback_Release($pSelf)
    #forceref $pSelf
    ConsoleWrite("@IArchiveOpenCallback_Release" & @CRLF)
    Return 1
EndFunc

Func IArchiveOpenCallback_SetTotal(ByRef $iFiles, ByRef $iBytes)
    ConsoleWrite("@IArchiveOpenCallback: files:" & $iFiles & " bytes:" & $iBytes & @CRLF)
EndFunc

Func IArchiveOpenCallback_SetCompleted(ByRef $iFiles, ByRef $iBytes)
    ConsoleWrite("@IArchiveOpenCallback: files:" & $iFiles & " bytes:" & $iBytes & @CRLF)
EndFunc

; 4) Then load archive using Open method of IInArchive.
$i = $oIInArchive.Open($stream1, 4*1024*1024, $oIArchiveOpenCallback) ; this?
;$i = $oIInArchive.Open($oIInStream, 4*1024*1024, $oIArchiveOpenCallback) ; or this?
MsgBox(0,"i?", "i=" & $i & @CRLF)

;"Open hresult(ptr;uint64*;ptr);" & _                     ; STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \
;"Close hresult();" & _                                   ; STDMETHOD(Close)() x; \

; 5) Then post your code if something wouldn't work as it should.

; ---------------------------------------------------------------------------------------------------------------------------------
#cs
The most correct ObjectFromTag is at http://www.autoitscript.com/forum/topic/153520-iuiautomation-ms-framework-automate-chrome-ff-ie/page-7#entry1143993

HRESULT SHCreateStreamOnFile(
  _In_   LPCTSTR pszFile,
  _In_   DWORD grfMode,
  _Out_  IStream **ppstm
);

WINOLEAPI GetHGlobalFromStream(
  _In_   IStream *pstm,
  _Out_  HGLOBAL *phglobal
);

WINOLEAPI CreateStreamOnHGlobal(
  _In_   HGLOBAL hGlobal,
  _In_   BOOL fDeleteOnRelease,
  _Out_  LPSTREAM *ppstm
);
#ce

; this is IO:
;MsgBox(0,@ScriptName, "methods=" & _7z_GetNumberOfMethods())
;MsgBox(0,@ScriptName, "methods=" & _7z_GetNumberOfFormats())

Seems this the right way?

The output of the script is currently this:

 

Func IInStream_QueryInterface( $pSelf ) ; Ret: long  Par: ptr;ptr
EndFunc
0

Func IInStream_AddRef( $pSelf ) ; Ret: dword
EndFunc
0

Func IInStream_Release( $pSelf ) ; Ret: dword
EndFunc
0

Func IInStream_Read( $pSelf ) ; Ret: long  Par: ptr,uint,ptr
EndFunc
3

Func IInStream_Seek( $pSelf ) ; Ret: long  Par: int64,uint,ptr
EndFunc
3

@IInStream_QueryInterface
@IInStream_QueryInterface -> return S_OK
@IInStream_Release
Func IInStream_QueryInterface( $pSelf ) ; Ret: long  Par: ptr;ptr
EndFunc
0

Func IInStream_AddRef( $pSelf ) ; Ret: dword
EndFunc
0

Func IInStream_Release( $pSelf ) ; Ret: dword
EndFunc
0

Func IInStream_SetTotal( $pSelf ) ; Ret: long  Par: ptr,ptr
EndFunc
3

Func IInStream_SetCompleted( $pSelf ) ; Ret: long  Par: ptr,ptr
EndFunc
3

@IInStream_QueryInterface
error @ IInStream_QueryInterface

Share this post


Link to post
Share on other sites
trancexx

You have errors reported for your IInStream methods. That's because you use Byref keywords. Remove them from methods definitions.

Then add real code inside them. Inside Read method call IStream.Read, inside Write call IStream.Write, etc. To do that your _WinAPI_SHCreateStreamOnFile misses ObjCreateInterface call on the result ($aCall[3]).

Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
milky

Ah, okay, I will doit... Thank you a lot.

Share this post


Link to post
Share on other sites
milky

Hm... I get now an issue with ObjCreateInterface() @ _WinAPI_SHCreateStreamOnFile()

this code does not work:

; 2) then you create stream on archive file (go with SHCreateStreamOnFile for now, since you found it on msdn even though it will prove slower later)
; STGM_READWRITE    0x00000002L
Func _WinAPI_SHCreateStreamOnFile($sFile)
    Local $iGrfMode = 0x00000002
    Local $aCall = DllCall('shlwapi.dll', 'long', 'SHCreateStreamOnFile', 'str', $sFile, 'uint', $iGrfMode, 'ptr*', 0)
    If @error Or $aCall[0] <> 0 Then
        ConsoleWrite("error @ _WinAPI_SHCreateStreamOnFile" & @CRLF)
        Exit
    EndIf

    Local $oObj = ObjCreateInterface($aCall[3], $sIID_IInStream, $sTagIInStream)
    If IsObj($oObj) Then
        Return $oObj
    EndIf

    MsgBox(0,"error", "_WinAPI_SHCreateStreamOnFile() != obj")
    Exit
EndFunc   ;==>_WinAPI_SHCreateStreamOnFile

It ends with the error MsgBox() ... but I don't know why?

Share this post


Link to post
Share on other sites
trancexx

SHCreateStreamOnFile creates IStream.

IInStream is different stream which is why autor of 7z said it's not "standard". That's why you need ObjectFromTag - to make IInStream out of IStream.

Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
milky

I took now these:

;===============================================================================
#interface "ISequentialStream"
Global Const $sIID_ISequentialStream = "{0c733a30-2a1c-11ce-ade5-00aa0044773d}"
Global Const $tagISequentialStream = "Read hresult(struct*;dword;dword*);" & _
        "Write hresult(struct*;dword;dword*);"

#interface "IStream"
Global Const $sIID_IStream = "{0000000c-0000-0000-C000-000000000046}"
Global Const $tagIStream = $tagISequentialStream & _
        "Seek hresult(int64;dword;uint64*);" & _
        "SetSize hresult(uint64);" & _
        "CopyTo hresult(ptr;uint64;uint64*;uint64*);" & _
        "Commit hresult(dword);" & _
        "Revert hresult();" & _
        "LockRegion hresult(uint64;uint64;dword);" & _
        "UnlockRegion hresult(uint64;uint64;dword);" & _
        "Stat hresult(struct*;dword);" & _
        "Clone hresult(ptr*);"

I found them in this thread, which was also done by you: '?do=embed' frameborder='0' data-embedContent>>

Hm... I am looking at it... maybe I get it ... just in some minutes ... ;)

....

No, I don't know, what is wrong here.

I will take a new run on it tomorrow ;)

Edited by milky

Share this post


Link to post
Share on other sites
trancexx

It should be:

Local $oObj = ObjCreateInterface($aCall[3], $sIID_IStream, 
$tagIStream)

and you have IStream.

Then inside IInStream methods you call IStream methods passing (translating arguments).


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
milky

I had again some time for testing and trying. Here is my current (not working) state of the script:

; /TR ctime 2014-05-02
; vllt. wird es so etwas wie eine UDF für 7z.dll ... falls ich es hinbekomme, wirds auf jeden fall open source, gplv2
; -> pre pre pre pre alpha....

#include <Array.au3>
#include <WinApi.au3>
#include <WinAPICom.au3>
#include <GDIPlus.au3>
#include <Memory.au3>
#include <GUIConstantsEx.au3>

#include "ObjectFromTag.au3"

; 7-Zip CLSID Handler            {23170F69-40C1-278A-1000-000110xx0000}
Global Const $sCLSID_Format7z = "{23170f69-40c1-278a-1000-000110070000}" ; 7-Zip Handler

; IProgress.h
;===============================================================================
#interface "IProgress2"
Global Const $sIID_IProgress2 = "{23170F69-40C1-278A-0000-000000050000}" ; IUnknown
Global Const $dtag_IProgress2 = _
    "SetTotal hresult(uint64);" & _  ; STDMETHOD(SetTotal)(UInt64 total) x; \
    "SetCompleted hresult(uint64*);" ; STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \

; IFolderArchive.h
;===============================================================================
#interface "IArchiveFolder"
Global Const $sIID_IArchiveFolder = "{23170F69-40C1-278A-0000-000100050000}" ; IUnknown
#cs
#define INTERFACE_IInFolderArchive(x) \
  STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, BSTR *archiveTypeRes,
    IArchiveOpenCallback *openArchiveCallback) x; \
  STDMETHOD(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \
  STDMETHOD(Close)() x; \
  STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
  STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
  STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder) x; \
  STDMETHOD(Extract)(NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode,
    const wchar_t *path, Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) x; \
#ce

;===============================================================================
#interface "IOutFolderArchive"
Global Const $sIID_IOutFolderArchive = "{23170F69-40C1-278A-0000-0001000a0000}" ; IUnknown
#cs
#define INTERFACE_IOutFolderArchive(x) \
  STDMETHOD(SetFolder)(IFolderFolder *folder) x; \
  STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) x; \
  STDMETHOD(DeleteItems)(ISequentialOutStream *outArchiveStream, const UInt32 *indices, UInt32 numItems,
    IFolderArchiveUpdateCallback *updateCallback) x; \
  STDMETHOD(DoOperation)(CCodecs *codecs, int index, ISequentialOutStream *outArchiveStream, const Byte *stateActions,
    const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback) x; \
  STDMETHOD(DoOperation2)(ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule,
    IFolderArchiveUpdateCallback *updateCallback) x; \
#ce

;===============================================================================
#interface "IFolderArchiveUpdateCallback"
Global Const $sIID_IFolderArchiveUpdateCallback = "{23170F69-40C1-278A-0000-0001000b0000}" ; IProgress
#cs
#define INTERFACE_IFolderArchiveUpdateCallback(x) \
  STDMETHOD(CompressOperation)(const wchar_t *name) x; \
  STDMETHOD(DeleteOperation)(const wchar_t *name) x; \
  STDMETHOD(OperationResult)(Int32 operationResult) x; \
  STDMETHOD(UpdateErrorMessage)(const wchar_t *message) x; \
  STDMETHOD(SetNumFiles)(UInt64 numFiles) x; \
#ce

;===============================================================================
#interface "IInFolderArchive"
Global Const $sIID_IInFolderArchive = "{23170F69-40C1-278A-0000-0001000e0000}" ; IUnknown
#cs
#define INTERFACE_IInFolderArchive(x) \
  STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat,
    BSTR *archiveTypeRes, IArchiveOpenCallback *openArchiveCallback) x; \
  STDMETHOD(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \
  STDMETHOD(Close)() x; \
  STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
  STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
  STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder) x; \
  STDMETHOD(Extract)(NExtract::NPathMode::EEnum pathMode, \
      NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, \
      Int32 testMode, IFolderArchiveExtractCallback *extractCallback2) x; \
#ce

; IStream.h
;===============================================================================
#interface "ISequentialInStream"
Global Const $sIID_ISequentialInStream = "{23170F69-40C1-278A-0000-000300010000}" ; IUnknown
Global Const $dtag_ISequentialInStream = "Read hresult(ptr,uint,uint32*);"
#cs
    STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;

    Out: if size != 0, return_value = S_OK and (*processedSize == 0),
    then there are no more bytes in stream.
    if (size > 0) && there are bytes in stream,
    this function must read at least 1 byte.
    This function is allowed to read less than number of remaining bytes in stream.
    You must call Read function in loop, if you need exact amount of data
#ce

;===============================================================================
#interface "ISequentialOutStream"
Global Const $sIID_ISequentialOutStream = "{23170F69-40C1-278A-0000-000300020000}" ; IUnknown
Global Const $dtag_ISequentialOutStream = "Write hresult(ptr,uint,uint32*);"
#cs
    STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;

    if (size > 0) this function must write at least 1 byte.
    This function is allowed to write less than "size".
    You must call Write function in loop, if you need to write exact amount of data
#ce

;===============================================================================
#interface "IInStream"
Global Const $sIID_IInStream = "{23170F69-40C1-278A-0000-000300030000}" ; ISequentialInStream
Global Const $dtag_IInStream = _
    $dtag_ISequentialInStream & _
    "Seek hresult(int64,uint,uint64*);"   ; STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;

;===============================================================================
#interface "IOutStream"
Global Const $sIID_IOutStream = "{23170F69-40C1-278A-0000-000300040000}" ; ISequentialOutStream
Global Const $sdtag_IOutStream = _
    $dtag_ISequentialOutStream & _
    "Seek hresult(int64,uint,uint64*);" & _ ; STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
    "SetSize hresult(uint64);"              ; STDMETHOD(SetSize)(UInt64 newSize) PURE;

;===============================================================================
#interface "IStreamGetSize"
Global Const $sIID_IStreamGetSize = "{23170F69-40C1-278A-0000-000300060000}" ; IUnknown
Global Const $dtag_IStreamGetSize = _
    "GetSize hresult(uint64*);" ; STDMETHOD(GetSize)(UInt64 *size) PURE;

;===============================================================================
#interface "IOutStreamFlush"
Global Const $sIID_IOutStreamFlush = "{23170F69-40C1-278A-0000-000300070000}" ; IUnknown
Global Const $dtag_IOutStreamFlush = _
    "Flush hresult();" ; STDMETHOD(Flush)() PURE;

; IPassword.h
;===============================================================================
#interface "ICryptoGetTextPassword"
Global Const $sIID_ICryptoGetTextPassword = "{23170F69-40C1-278A-0000-000500100000}" ; IUnknown
Global Const $dtag_ICryptoGetTextPassword = _
    "CryptoGetTextPassword hresult(str);" ; STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE;

;===============================================================================
#interface "ICryptoGetTextPassword2"
Global Const $sIID_ICryptoGetTextPassword2 = "{23170F69-40C1-278A-0000-000500200000}" ; IUnknown
Global Const $dtag_ICryptoGetTextPassword2 = _
    "CryptoGetTextPassword2 hresult(int*,str);" ; STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE;

; IArchive.h
;===============================================================================
#interface "ISetProperties"
Global Const $sIID_ISetProperties = "{23170F69-40C1-278A-0000-000600030000}" ; IUnknown
Global Const $dtag_ISetProperties = _
    "SetProperties hresult(ptr,ptr,int);" ;  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE;

;===============================================================================
#interface "IArchiveOpenCallback"
Global Const $sIID_IArchiveOpenCallback = "{23170F69-40C1-278A-0000-000600100000}" ; IUnknown
Global Const $dtag_IArchiveOpenCallback = _
    "SetTotal hresult(uint64*,uint64*);" & _   ; STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \
    "SetCompleted hresult(uint64*,uint64*);"   ; STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \

;===============================================================================
#interface "IArchiveExtractCallback"
Global Const $sIID_IArchiveExtractCallback = "{23170F69-40C1-278A-0000-000600200000}" ; IProgress
Global Const $dtag_IArchiveExtractCallback = _
    $dtag_IProgress2 & _
    "GetStream hresult(uint,ptr*,int);" & _    ; STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream,  Int32 askExtractMode) x; \
    "PrepareOperation hresult(int);" & _       ; STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \
    "SetOperationResult hresult(int);"         ; STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \

;===============================================================================
#interface "IArchiveOpenVolumeCallback"
Global Const $sIID_IArchiveOpenVolumeCallback = "{23170F69-40C1-278A-0000-000600300000}" ; IUnknown
Global Const $sTagIArchiveOpenVolumeCallback = _
    "GetProperty hresult(int,variant*);" & _   ; STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \
    "GetStream hresult(wstr,ptr*);"            ; STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \

;===============================================================================
#interface "IInArchiveGetStream"
Global Const $sIID_IInArchiveGetStream = "{23170F69-40C1-278A-0000-000600400000}" ; IUnknown
Global Const $dtag_IInArchiveGetStream = _
    "GetStream hresult(uint,ptr*);" ; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;

;===============================================================================
#interface "IArchiveOpenSetSubArchiveName"
Global Const $sIID_IArchiveOpenSetSubArchiveName = "{23170F69-40C1-278A-0000-000600500000}" ; IUnknown
Global Const $dtag_IArchiveOpenSetSubArchiveName = _
    "SetSubArchiveName hresult(wstr);" ; STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;

;===============================================================================
#interface "IInArchive"
Global Const $sIID_IInArchive = "{23170F69-40C1-278A-0000-000600600000}" ; IUnknown
Global Const $dtag_IInArchive = _
    "Open hresult(ptr;uint64*;ptr);" & _                     ; STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \
    "Close hresult();" & _                                   ; STDMETHOD(Close)() x; \
    "GetNumberOfItems hresult(uint*);" & _                   ; STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \
    "GetProperty hresult(uint;int;variant*);" & _            ; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
    "Extract hresult(uint;uint;int;ptr);" & _                ; STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \
    "GetArchiveProperty hresult(int;variant*);" & _          ; STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \
    "GetNumberOfProperties hresult(uint*);" & _              ; STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
    "GetPropertyInfo hresult(uint;bstr*;int*;int*);" & _     ; STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
    "GetNumberOfArchiveProperties hresult(uint*);" & _       ; STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \
    "GetArchivePropertyInfo hresult(uint;bstr*;int*;int*);"  ; STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;

;===============================================================================
#interface "IArchiveOpenSeq"
Global Const $sIID_IArchiveOpenSeq = "{23170F69-40C1-278A-0000-000600610000}" ; IUnknown
Global Const $dtag_IArchiveOpenSeq = _
    "OpenSeq hresult();" ; STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE;

;===============================================================================
#interface "IArchiveUpdateCallback"
Global Const $sIID_IArchiveUpdateCallback = "{23170F69-40C1-278A-0000-000600800000}" ; IProgress
Global Const $dtag_IArchiveUpdateCallback = _
    $dtag_IProgress2 & _
    "GetUpdateItemInfo hresult(uint,int*,int*,int*);" & _  ; STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)  x; \
    "GetProperty hresult(uint,int,variant*);" & _          ; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
    "GetStream hresult(uint,ptr*);" & _                    ; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \
    "SetOperationResult hresult(int);"                     ; STDMETHOD(SetOperationResult)(Int32 operationResult) x; \

;===============================================================================
#interface "IArchiveUpdateCallback2"
Global Const $sIID_IArchiveUpdateCallback2 = "{23170F69-40C1-278A-0000-000600820000}" ; IArchiveUpdateCallback
Global Const $dtag_IArchiveUpdateCallback2 = _
    $dtag_IArchiveUpdateCallback & _
    "GetVolumeSize hresult(uint,uint64*);" & _  ; STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \
    "GetVolumeStream hresult(uint,ptr*);"       ; STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \

;===============================================================================
#interface "IOutArchive"
Global Const $sIID_IOutArchive = "{23170F69-40C1-278A-0000-000600A00000}" ; IUnknown
Global Const $dtag_IOutArchive = _
    "UpdateItems hresult(ptr;uint;ptr);" & _ ; STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \
    "GetFileTimeTypehresult(uint*);"         ; STDMETHOD(GetFileTimeType)(UInt32 *type) x;

;===============================================================================
#interface "ISequentialStream"
Global Const $sIID_ISequentialStream = "{0c733a30-2a1c-11ce-ade5-00aa0044773d}" ; IUnknown
Global Const $dtag_ISequentialStream = _
    "Read hresult(struct*;dword;dword*);" & _
    "Write hresult(struct*;dword;dword*);"

;===============================================================================
#interface "IStream"
Global Const $sIID_IStream = "{0000000c-0000-0000-C000-000000000046}" ; ISequentialStream
Global Const $dtag_IStream = _
    $dtag_ISequentialStream & _
    "Seek hresult(int64;dword;uint64*);" & _
    "SetSize hresult(uint64);" & _
    "CopyTo hresult(ptr;uint64;uint64*;uint64*);" & _
    "Commit hresult(dword);" & _
    "Revert hresult();" & _
    "LockRegion hresult(uint64;uint64;dword);" & _
    "UnlockRegion hresult(uint64;uint64;dword);" & _
    "Stat hresult(struct*;dword);" & _
    "Clone hresult(ptr*);"

;===============================================================================

; XXX, später dann mal: 7za-x32.dll / 7za-x64.dll (von 7zip.org)
; open 7z.dll
Global Const $h7Z_DLL = DllOpen(@ScriptDir & "\7z.dll") ; je nach system erstmal per hand anpassen
If $h7Z_DLL = -1 Then
    MsgBox(0, "error", "fehler beim laden der dll")
    Exit
EndIf

#cs
    exported functions of 7z.dll:
IO: UInt32 WINAPI CreateObject(const GUID *clsID, const GUID *interfaceID, void **outObject);
IO: UInt32 WINAPI GetNumberOfMethods(UInt32 *numMethods);
IO: UInt32 WINAPI GetNumberOfFormats(UInt32 *numFormats);

not used, currently:
    UInt32 WINAPI GetMethodProperty(UInt32 index, PROPID propID, PROPVARIANT *value);
    UInt32 WINAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value);
    UInt32 WINAPI GetHandlerProperty2(UInt32 index, PROPID propID, PROPVARIANT *value);
    UInt32 WINAPI SetLargePageMode();
#ce

Func _7z_GetNumberOfMethods()
    Local $aCall = DllCall($h7Z_DLL, 'uint', 'GetNumberOfMethods', 'uint*', 0)
    If @error <> 0 Then
        MsgBox(0, "error", "fehler _7z_GetNumberOfMethods()")
        Exit
    EndIf
    Return $aCall[1]
EndFunc   ;==>_7z_GetNumberOfMethods

Func _7z_GetNumberOfFormats()
    Local $aCall = DllCall($h7Z_DLL, 'uint', 'GetNumberOfFormats', 'uint*', 0)
    If @error <> 0 Then
        MsgBox(0, "error", "fehler _7z_GetNumberOfFormats()")
        Exit
    EndIf
    Return $aCall[1]
EndFunc   ;==>_7z_GetNumberOfFormats

Func _7z_CreateObject($sCLSID, $sIID, $sTag)
    Local $tCLSID = _WinAPI_GUIDFromString($sCLSID)
    Local $tIID = _WinAPI_GUIDFromString($sIID)

    ; CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
    Local $aCall = DllCall($h7Z_DLL, "long", "CreateObject", "struct*", $tCLSID, "struct*", $tIID, "ptr*", 0)
    ;_ArrayDisplay($aCall)
    ;MsgBox(0,"call:", "DllCall() " & @CRLF & "$sCLSID = " & $sCLSID & @CRLF & "sIID = " & $sIID & @CRLF & "$sTag = " & $sTag)
    If @error Or $aCall[0] Then
        MsgBox(0, "error", "DllCall() @ _7z_CreateObject nicht ok: " & @error & " @ " & $sIID)
        ;_ArrayDisplay($aCall)
        Exit
    EndIf

    Local $oObj = ObjCreateInterface($aCall[3], $sIID, $sTag)
    If IsObj($oObj) Then
        Return $oObj
    EndIf

    ; fatal error
    MsgBox(0, "_7z_CreateObject() fehlgeschlagen... obj=", IsObj($oObj))
    Exit
EndFunc   ;==>_7z_CreateObject

;===============================================================================
; 1) What yo should do is first create IInArchive object with _7z_CreateObject (already posted)
Local $oIInArchive = _7z_CreateObject($sCLSID_Format7z, $sIID_IInArchive, $dtag_IInArchive)

; 2) then you create stream on archive file (go with SHCreateStreamOnFile for now, since you found it on msdn even though it will prove slower later)
; STGM_READWRITE    0x00000002L
Func _WinAPI_SHCreateStreamOnFile($sFile)
    Local $iGrfMode = 0x00000002
    Local $aCall = DllCall('shlwapi.dll', 'long', 'SHCreateStreamOnFile', 'str', $sFile, 'uint', $iGrfMode, 'ptr*', 0)
    If @error Or $aCall[0] <> 0 Then
        ConsoleWrite("error @ _WinAPI_SHCreateStreamOnFile" & @CRLF)
        Exit
    EndIf

    Local $oObj = ObjCreateInterface($aCall[3], $sIID_IStream, $dtag_IStream)
    If IsObj($oObj) Then
        Return $oObj
    EndIf

    MsgBox(0, "error", "_WinAPI_SHCreateStreamOnFile() != obj")
    Exit
EndFunc   ;==>_WinAPI_SHCreateStreamOnFile

;===============================================================================
; 3) Then create IInStream with ObjectFromTag which is similar task as IArchiveOpenCallback you already did, only you wrapp IStream you got with SHCreateStreamOnFile.
Local $tIArchiveOpenCallback ; Interface for IArchiveOpenCallback
Local $oIArchiveOpenCallback = ObjectFromTag("IArchiveOpenCallback_", $dtag_IArchiveOpenCallback, $tIArchiveOpenCallback, True, Default, $sIID_IArchiveOpenCallback)

; lala.7z is a small testfile (created with 7zip)
Local Const $sFilePath = @TempDir & "\lala.7z"
Local $oIStream = _WinAPI_SHCreateStreamOnFile($sFilePath)
;Local $hData = _MemGlobalAlloc(4*1024*1024, $GMEM_MOVEABLE) -> later

Func IArchiveOpenCallback_QueryInterface($pSelf, $pRIID, $pObj)
    Local $tStruct = DllStructCreate("ptr", $pObj)
    ConsoleWrite("@IArchiveOpenCallback_QueryInterface" & @CRLF)
    Switch _WinAPI_StringFromGUID($pRIID)
        Case $sIID_IArchiveOpenCallback
        Case Else
                        ConsoleWrite("IArchiveOpenCallback_QueryInterface -> ERR (" & _WinAPI_StringFromGUID($pRIID) & ") " & @CRLF)
            Return $E_NOINTERFACE
    EndSwitch
    DllStructSetData($tStruct, 1, $pSelf)
    ConsoleWrite("@IArchiveOpenCallback_QueryInterface -> OK" & @CRLF)
    Return $S_OK
EndFunc   ;==>IArchiveOpenCallback_QueryInterface

Func IArchiveOpenCallback_AddRef($pSelf)
    #forceref $pSelf
    ConsoleWrite("@IArchiveOpenCallback_AddRef" & @CRLF)
    Return $S_OK
EndFunc   ;==>IArchiveOpenCallback_AddRef

Func IArchiveOpenCallback_Release($pSelf)
    #forceref $pSelf
    ConsoleWrite("@IArchiveOpenCallback_Release" & @CRLF)
    Return $S_OK
EndFunc   ;==>IArchiveOpenCallback_Release

Func IArchiveOpenCallback_SetTotal($iFiles, $iBytes)
    ConsoleWrite("@IArchiveOpenCallback: files:" & $iFiles & " bytes:" & $iBytes & @CRLF)
    $iFiles = 1
    $iBytes = FileGetSize($sFilePath)
    Return $S_OK
EndFunc   ;==>IArchiveOpenCallback_SetTotal

Func IArchiveOpenCallback_SetCompleted($iFiles, $iBytes)
    ConsoleWrite("@IArchiveOpenCallback: files:" & $iFiles & " bytes:" & $iBytes & @CRLF)
    $iFiles = 0
    $iBytes = 0
    Return $S_OK
EndFunc   ;==>IArchiveOpenCallback_SetCompleted

;===============================================================================
; 3) Then create IInStream with ObjectFromTag which is similar task as IArchiveOpenCallback you already did
; -> only you wrapp IStream you got with SHCreateStreamOnFile.

Local $tIInStream ; Interface for IInStream
Local $oIInStream = ObjectFromTag("IInStream_", $dtag_IInStream, $tIInStream, True, Default, $sIID_IInStream)

#cs
;Func ObjectFromTag(
    $sFunctionPrefix,
    $tagInterface,
    ByRef $tInterface,
    $fPrint = False,
    $bIsUnknown = Default,
    $sIID = "{00000000-0000-0000-C000-000000000046}") ; last param is IID_IUnknown by default
#ce

; IInStream interface
Func IInStream_QueryInterface($pSelf, $pRIID, $pObj)
    Local $tStruct = DllStructCreate("ptr", $pObj)
    ConsoleWrite("@IInStream_QueryInterface" & @CRLF)
    Switch _WinAPI_StringFromGUID($pRIID)
        Case $sIID_IInStream
        Case Else
            ConsoleWrite("@IInStream_QueryInterface -> ERR" & @CRLF)
            Return $E_NOINTERFACE
    EndSwitch
    DllStructSetData($tStruct, 1, $pSelf)
    ConsoleWrite("@IInStream_QueryInterface -> OK" & @CRLF)
    Return $S_OK
EndFunc   ;==>IInStream_QueryInterface

Func IInStream_AddRef($pSelf)
    #forceref $pSelf
    ConsoleWrite("@IInStream_AddRef" & @CRLF)
    Return $S_OK
EndFunc   ;==>IInStream_AddRef

Func IInStream_Release($pSelf)
    #forceref $pSelf
    ConsoleWrite("@IInStream_Release" & @CRLF)
    Return $S_OK
EndFunc   ;==>IInStream_Release

;   "Read hresult(ptr,uint,uint32*);" & _       ; STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
Func IInStream_Read($pData, $iSize, $iProcessedSize)
    ConsoleWrite("@IInStream_Read: $iSize:" & $iSize & " $iProcessedSize:" & $iProcessedSize & @CRLF)
    $oIStream.Read($pData, $iSize, $iProcessedSize)
    Return $S_OK
EndFunc   ;==>IInStream_Read

;   "Seek hresult(int64,uint,uint64*);"         ; STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
Func IInStream_Seek($iOffset, $iSeekOrigin, $iNewPosition)
    ConsoleWrite("@IInStream_Seek: $iSeekOrigin:" & $iSeekOrigin & " $iNewPosition:" & $iNewPosition & @CRLF)
    $oIStream.Seek($iOffset, $iSeekOrigin, $iNewPosition)
    Return $S_OK
EndFunc   ;==>IInStream_Seek

;===============================================================================
; 4) Then load archive using Open method of IInArchive.
$i = $oIInArchive.Open($oIInStream, 4 * 1024 * 1024, $oIArchiveOpenCallback)



;$oIStream.Release()
;DeleteObjectFromTag($tIInStream)
MsgBox(0, "i?", "i=" & $i & @CRLF)

; 5) Then post your code if something wouldn't work as it should.
; ...


; this works:
;MsgBox(0,@ScriptName, "methods=" & _7z_GetNumberOfMethods())
;MsgBox(0,@ScriptName, "methods=" & _7z_GetNumberOfFormats())
;Local $iItems = 0
;$iRet = $oIArchive.GetNumberOfItems($iItems)
;MsgBox(0,"","x=" & $iItems & "  r=" & $iRet)

This is the output:

Func IArchiveOpenCallback_QueryInterface( $pSelf ) ; Ret: long  Par: ptr;ptr
EndFunc
0

Func IArchiveOpenCallback_AddRef( $pSelf ) ; Ret: dword
EndFunc
0

Func IArchiveOpenCallback_Release( $pSelf ) ; Ret: dword
EndFunc
0

Func IArchiveOpenCallback_SetTotal( $pSelf ) ; Ret: long  Par: ptr,ptr
EndFunc
error=2 @extended=0 error @ method=IArchiveOpenCallback_SetTotal ret=long params=ptr;ptr,ptr0

Func IArchiveOpenCallback_SetCompleted( $pSelf ) ; Ret: long  Par: ptr,ptr
EndFunc
error=2 @extended=0 error @ method=IArchiveOpenCallback_SetCompleted ret=long params=ptr;ptr,ptr0

@IArchiveOpenCallback_QueryInterface
@IArchiveOpenCallback_QueryInterface -> OK
@IArchiveOpenCallback_Release
Func IInStream_QueryInterface( $pSelf ) ; Ret: long  Par: ptr;ptr
EndFunc
0

Func IInStream_AddRef( $pSelf ) ; Ret: dword
EndFunc
0

Func IInStream_Release( $pSelf ) ; Ret: dword
EndFunc
0

Func IInStream_Read( $pSelf ) ; Ret: long  Par: ptr,uint,ptr
EndFunc
error=2 @extended=0 error @ method=IInStream_Read ret=long params=ptr;ptr,uint,ptr0

Func IInStream_Seek( $pSelf ) ; Ret: long  Par: int64,uint,ptr
EndFunc
error=2 @extended=0 error @ method=IInStream_Seek ret=long params=ptr;int64,uint,ptr0

@IInStream_QueryInterface
@IInStream_QueryInterface -> OK
@IInStream_Release
@IArchiveOpenCallback_AddRef
@IArchiveOpenCallback_QueryInterface
IArchiveOpenCallback_QueryInterface -> ERR ({23170F69-40C1-278A-0000-000500100000}) -> {23170F69-40C1-278A-0000-000500100000} means $sIID_ICryptoGetTextPassword ?
@IArchiveOpenCallback_Release

Should I use FileOpen(), FileRead(), FileSetPos(), FileGetPos(), FileGetPos() and friends within the IInStream methods ?

Thanks for all the help.

Best regards, milky

Edited by milky

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×