Jump to content
ProgAndy

AutoItObject UDF

Recommended Posts

Is the link list example intended only to be an example, or can we freely use it as a library? If we can, can you please make an explicit claim of authorship at the head of the script, so that no one will get confused if I distribute it along with projects I write that use it?

Thanks.


Spoiler

"This then is the message which we have heard of him, and declare unto you, that God is light, and in him is no darkness at all. If we say that we have fellowship with him, and walk in darkness, we lie, and do not the truth: But if we walk in the light, as he is in the light, we have fellowship one with another, and the blood of Jesus Christ his Son cleanseth us from all sin. If we say that we have no sin, we deceive ourselves, and the truth is not in us. If we confess our sins, he is faithful and just to forgive us our sins, and to cleanse us from all unrighteousness. If we say that we have not sinned, we make him a liar, and his word is not in us." (I John 1:5-10)

 

Share this post


Link to post
Share on other sites

You can use it as a library if you want.

Just add the same header we used in AutoItObject.au3 :mellow:


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

I have some questions about _AutoItObject_WrapperCreate():

  • Would it create an AutoIt object from any IUnknown pointer (there are several plain Win API functions that return interface pointers to system objects)?
  • If answer to #1 is yes, is the pointer freed after $obj = 0?
  • Does the interface definition ($tagInterface parameter in _AutoItObject_WrapperCreate()) need to be complete or will it suffice to define only some of methods the object implements? Looking at the samples I can't really get the clue...
  • Is it allowed for $tagInterface to contain ANY of super-interfaces or do I always have to create wrapper to IUnknown / base interface and QueryInterface() it then?

Particularly I'm trying to implement in-memory stream (IStream) object in AutoIt by utilizing CreateStreamOnHGlobal for use it in some COM calls, however it does not seem to work - either I get COM error ("Name unknown") or access violation. Here is the code:

#include <Memory.au3>
#include <WinAPI.au3>
#include "AutoItObject.au3"

Global $tagIStream = _
    "QueryInterface long(ptr;ptr;ptr);" & _
    "AddRef ulong();" & _
    "Release ulong();" & _ ; IUnknown
    "Read long(ptr;ULONG;ULONG_PTR);" & _
    "Write long(ptr;ULONG;ULONG_PTR);" ; ISequentialStream

Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
Func _ErrFunc()
    ConsoleWrite("! COM Error !  Number: 0x" & Hex($oError.number, 8) & "   ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
    Return
EndFunc   ;==>_ErrFunc

_AutoItObject_Startup()

Dim $hMem = _MemGlobalAlloc(0x1000, $GHND)
If $hMem Then
    
    Dim $tStream = DllStructCreate("ptr")
    Dim $res = DllCall("ole32.dll", "long", "CreateStreamOnHGlobal", "HANDLE", $hMem, "BOOL", 0, "ptr", DllStructGetPtr($tStream, 1))
    If 0 = $res[0] And 0 <> DllStructGetData($tStream, 1) Then
        Dim $oStream = _AutoItObject_WrapperCreate(DllStructGetData($tStream, 1), $tagIStream)
        If IsObj($oStream) Then
            MsgBox(0, "Test", "IStream Created!")
ConsoleWrite("Still there 1" & @LF)
            Dim $tw = DllStructCreate("wchar[128];ULONG")
            DllStructSetData($tw, 1, "Test string")
            Dim $hr = $oStream.Wtite(DllStructGetPtr($tw, 1), StringLen("Test string") * 2, DllStructGetPtr($tw, 2))
            ConsoleWrite("HR(" & VarGetType($hr) & ")=" & $hr & @LF)
            $oStream = 0
ConsoleWrite("Still there 2" & @LF)
        Else
            MsgBox(0, "Error _AutoItObject_WrapperCreate", _WinAPI_GetLastErrorMessage())
        EndIf
    Else
        MsgBox(0, "Error CreateStreamOnHGlobal", _WinAPI_GetLastErrorMessage())
    EndIf
    
    Dim $p = _MemGlobalLock($hMem)
    If $p Then
        Dim $tr = DllStructCreate("wchar[128]", $p)
        MsgBox(0, "Test", "" & DllStructGetData($tr, 1))
        _MemGlobalUnlock($hMem)
    Else
        MsgBox(0, "Error", _WinAPI_GetLastErrorMessage())
    EndIf
    
    $tStream = 0
ConsoleWrite("Still there 3" & @LF)
    _MemGlobalFree($hMem)
ConsoleWrite("Still there 4" & @LF)
Else
    MsgBox(0, "Error GlobalAlloc", _WinAPI_GetLastErrorMessage())
EndIf
ConsoleWrite("Still there 5" & @LF)

Comments and ideas are highly appriciated.


UDFS & Apps:


DDEML.au3 - DDE Client + Server[*]
Localization.au3- localize your scripts[*]
TLI.au3 - type information on COM objects (TLBINF emulation)[*]
TLBAutoEnum.au3 - auto-import of COM constants (enums)[*]
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector

- OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Share this post


Link to post
Share on other sites

Replace:

Dim $hr = $oStream.Wtite(DllStructGetPtr($tw, 1), StringLen("Test string") * 2, DllStructGetPtr($tw, 2))

With:

Local $hr = $oStream.Write(Number(DllStructGetPtr($tw, 1)), StringLen("Test string") * 2, Number(DllStructGetPtr($tw, 2)))

Number() is used because of bug in AutoIt.

1. Yes

2. Yes (object is freed if that's what you mean - Release() called)

3. Doesn't have to be complete, but if you want third method you have to list first and second too

4. QueryInterface() if/when needed

Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Replace:

Dim $hr = $oStream.Wtite(DllStructGetPtr($tw, 1), StringLen("Test string") * 2, DllStructGetPtr($tw, 2))

With:

Local $hr = $oStream.Write(Number(DllStructGetPtr($tw, 1)), StringLen("Test string") * 2, Number(DllStructGetPtr($tw, 2)))

Number() is used because of bug in AutoIt.

1. Yes

2. Yes (object is freed if that's what you mean - Release() called)

3. Doesn't have to be complete, but if you want third method you have to list first and second too

4. QueryInterface() if/when needed

Thx for your reply.

I'll try it with Number().

On 2.: no, I meant, f.i. CreateStreamOnHGlobal() allocates IStream object on stack so in C++ I would use ComPtr<ISream*> which frees memory pointed by LPSTREAM after it is destroyed. Actually I've no idea how stack pointers are handled in AutoIt, this is why my question.

On 3.: what do You mean by "first and second"? In the order they defined in their IDL? Do super-interfaces' methods come before? If yes, do I have to supply them all?

On 4.: it hangs together with 3. actually...

Pity AutoItObject is not yet documented better :mellow: , questions of the kind would be perfectly served with RTFM otherwise LOL


UDFS & Apps:


DDEML.au3 - DDE Client + Server[*]
Localization.au3- localize your scripts[*]
TLI.au3 - type information on COM objects (TLBINF emulation)[*]
TLBAutoEnum.au3 - auto-import of COM constants (enums)[*]
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector

- OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Share this post


Link to post
Share on other sites

Thx for your reply.

I'll try it with Number().

On 2.: no, I meant, f.i. CreateStreamOnHGlobal() allocates IStream object on stack so in C++ I would use ComPtr<ISream*> which frees memory pointed by LPSTREAM after it is destroyed. Actually I've no idea how stack pointers are handled in AutoIt, this is why my question.

We are both talking about calling Release().

When you are done with the object just reinitialize the variable holding the object and you'll be fine.

If the object is local you don't even have to do that. AutoIt will do it for you when returning from the function in which the object was made.

On 3.: what do You mean by "first and second"? In the order they defined in their IDL? Do super-interfaces' methods come before? If yes, do I have to supply them all?

On 4.: it hangs together with 3. actually...

In the AutoItObject package there are few examples included. Find DirectShow.au3 and open it. On line 124 of that file you will find interface tag for IGraphBuilder:
Local $tagInterface = "QueryInterface;" & _
            "AddRef;" & _
            "Release;" & _ ; IUnknown
            "AddFilter;" & _
            "RemoveFilter;" & _
            "EnumFilters;" & _
            "FindFilterByName;" & _
            "ConnectDirect;" & _
            "Reconnect;" & _
            "Disconnect;" & _
            "SetDefaultSyncSource;" & _ ; IFilterGraph
            "Connect;" & _
            "Render;" & _
            "RenderFile;" & _
            "AddSourceFilter;" & _
            "SetLogFile;" & _
            "Abort;" & _
            "ShouldOperationContinue;" ; IGraphBuilder

It's in alternate form; return values and parameter types not defined.

IGraphBuilder inherits from IFilterGraph which inherits from IUnknown. That's why IUnknown tag is first, then IFilterGraph methods names appended and then IGraphBuilder methods names appended more.

If I'm gonna use only SetLogFile method of IGraphBuilder interface I can't do this:

Local $tagInterface = "QueryInterface;" & _
            "AddRef;" & _
            "Release;" & _ ; IUnknown
            "AddFilter;" & _
            "RemoveFilter;" & _
            "EnumFilters;" & _
            "FindFilterByName;" & _
            "ConnectDirect;" & _
            "Reconnect;" & _
            "Disconnect;" & _
            "SetDefaultSyncSource;" & _ ; IFilterGraph
            "SetLogFile;"

But I can do this:

Local $tagInterface = "QueryInterface;" & _
            "AddRef;" & _
            "Release;" & _ ; IUnknown
            "AddFilter;" & _
            "RemoveFilter;" & _
            "EnumFilters;" & _
            "FindFilterByName;" & _
            "ConnectDirect;" & _
            "Reconnect;" & _
            "Disconnect;" & _
            "SetDefaultSyncSource;" & _ ; IFilterGraph
            "Connect;" & _
            "Render;" & _
            "RenderFile;" & _
            "AddSourceFilter;" & _
            "SetLogFile;"

edit:

Or to be specific for that script, since no methods of IGraphBuilder interface are used there (except QueryInterface), IGraphBuilder interface could have been defined as:

...
Local $tagInterface = "QueryInterface;" & _
            "AddRef;" & _
            "Release;" 
; Wrapp IGraphBuilder interface
    $oGraphBuilder = _AutoItObject_WrapperCreate($pGraphBuilder, $tagInterface)
    If @error Then Return SetError(2, 0, 0)

And all would work just fine.

Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

If you really need only one or two methods, you can leave the interface-definition empty (or use only the first three entries from IUnknown). Then call _AutoItObject_WrapperAddMethod, but you still have to know the position of the function in the vTable and specify it in the call.


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

...

And all would work just fine.

If you really need only one or two methods, you can leave the interface-definition empty (or use only the first three entries from IUnknown). Then call _AutoItObject_WrapperAddMethod, but you still have to know the position of the function in the vTable and specify it in the call.

Thanks to you both trancexx, ProgAndy. I think, you really should add your explanations to the AutoItObject docs (unless you like answering stupid questions :mellow: ).

I've changed my code accordingly:

#include <Memory.au3>
#include <WinAPI.au3>
#include "AutoItObject.au3"

Global $tagIStream = _
    "QueryInterface long(ptr;ptr;ptr);" & _
    "AddRef ulong();" & _
    "Release ulong();" & _ ; IUnknown
    "Read long(ptr;ULONG;ULONG_PTR);" & _
    "RemoteRead long(ptr;ULONG;ULONG_PTR);" & _
    "Write long(ptr;ULONG;ULONG_PTR);" ; ISequentialStream

Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
Func _ErrFunc()
    ConsoleWrite("! COM Error !  Number: 0x" & Hex($oError.number, 8) & "   ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
    Return
EndFunc   ;==>_ErrFunc

_AutoItObject_Startup()

Dim $hMem = _MemGlobalAlloc(0x1000, $GHND)
If $hMem Then
    
    Dim $tStream = DllStructCreate("ptr")
    Dim $res = DllCall("ole32.dll", "long", "CreateStreamOnHGlobal", "HANDLE", $hMem, "BOOL", 0, "ptr", DllStructGetPtr($tStream, 1))
    If 0 = $res[0] And 0 <> DllStructGetData($tStream, 1) Then
        Dim $oStream = _AutoItObject_WrapperCreate(DllStructGetData($tStream, 1), $tagIStream)
        If IsObj($oStream) Then
            MsgBox(0, "Test", "IStream " & ObjName($oStream) & " Created!")
ConsoleWrite("Still there 1" & @LF)
            Dim $tw = DllStructCreate("wchar[128];ULONG")
            DllStructSetData($tw, 1, "Test string")
            Dim $hr = $oStream.Wtite(Number(DllStructGetPtr($tw, 1)), StringLen("Test string") * 2, Number(DllStructGetPtr($tw, 2)))
            ConsoleWrite("HR(" & VarGetType($hr) & ")=" & $hr & @LF)
            $oStream = 0
ConsoleWrite("Still there 2" & @LF)
        Else
            MsgBox(0, "Error _AutoItObject_WrapperCreate", _WinAPI_GetLastErrorMessage())
        EndIf
    Else
        MsgBox(0, "Error CreateStreamOnHGlobal", _WinAPI_GetLastErrorMessage())
    EndIf
    
    Dim $p = _MemGlobalLock($hMem)
    If $p Then
        Dim $tr = DllStructCreate("wchar[128]", $p)
        MsgBox(0, "Test", "Buffer contents: [" & DllStructGetData($tr, 1) & "]")
        _MemGlobalUnlock($hMem)
    Else
        MsgBox(0, "Error", _WinAPI_GetLastErrorMessage())
    EndIf
    
    $tStream = 0
ConsoleWrite("Still there 3" & @LF)
    _MemGlobalFree($hMem)
ConsoleWrite("Still there 4" & @LF)
Else
    MsgBox(0, "Error GlobalAlloc", _WinAPI_GetLastErrorMessage())
EndIf
ConsoleWrite("Still there 5" & @LF)

But I still get: "COM Error ! Number: 0x80020006 ScriptLine: 33 - Name Unknown"

FYI, interfaces in question are declared in ObjIdl.idl like this:

interface ISequentialStream : IUnknown
{
    [local]
    HRESULT Read(
        [out, size_is(cb), length_is(*pcbRead)]
        void *pv,
        [in] ULONG cb,
        [out] ULONG *pcbRead);

    [call_as(Read)]
    HRESULT RemoteRead(
        [out, size_is(cb), length_is(*pcbRead)]
        byte *pv,
        [in] ULONG cb,
        [out] ULONG *pcbRead);

    [local]
    HRESULT Write(
        [in, size_is(cb)] void const *pv,
        [in] ULONG cb,
        [out] ULONG *pcbWritten);

    [call_as(Write)]
    HRESULT RemoteWrite(
        [in, size_is(cb)] byte const *pv,
        [in] ULONG cb,
        [out] ULONG *pcbWritten);
}
interface IStream : ISequentialStream
{
...
}

Since CreateStreamOnHGlobal() returns IStream* in the third parameter, it should be working but it isn't. Any ideas?


UDFS & Apps:


DDEML.au3 - DDE Client + Server[*]
Localization.au3- localize your scripts[*]
TLI.au3 - type information on COM objects (TLBINF emulation)[*]
TLBAutoEnum.au3 - auto-import of COM constants (enums)[*]
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector

- OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Share this post


Link to post
Share on other sites

Why should the Wrapper find the method Wtite, you did not define it.

Also, the function returns IStream, not ISequencialStream. Additionally, the vTable-Order of the functions is not the one you can find in MSDN. You have to search Wine source or the WinAPI C-headers.

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

Why should the Wrapper find the method Wtite, you did not define it.

Also, the function returns IStream, not ISequencialStream. Additionally, the vTable-Order of the functions is not the one you can find in MSDN. You have to search Wine source or the WinAPI C-headers.

LOL How could just this happen?

After fixing the typo I run in "Access violation in kernel32.dll at address 7C800007" calling $oStream.Write(). Can the different vTable-Order be the cause?

Would it be better way to QueryInterface(ISequentialStream*) on IStream* before everything else?


UDFS & Apps:


DDEML.au3 - DDE Client + Server[*]
Localization.au3- localize your scripts[*]
TLI.au3 - type information on COM objects (TLBINF emulation)[*]
TLBAutoEnum.au3 - auto-import of COM constants (enums)[*]
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector

- OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Share this post


Link to post
Share on other sites

Would it be better way to QueryInterface(ISequentialStream*) on IStream* before everything else?

If you need ISequencialStream, you really should use QueryInterface.

Another thing you have to change are the function definitions. The order is incorrect, you have to find the vTable and take the List from there!

Edit: OK, no. You acutally can use SequentialStream instead of Stream, it is just a shorter version having only the 2 funcs REad + Write. You have to remove RemoteRead from your table.

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

Got it!

Here is the working version (actually it's my original code with the typo fixed! :mellow: )

#include <Memory.au3>
#include <WinAPI.au3>
#include "AutoItObject.au3"

Global $tagIStream = _
    "QueryInterface long(ptr;ptr;ptr);" & _
    "AddRef ulong();" & _
    "Release ulong();" & _ ; IUnknown
    "Read long(ptr;ULONG;ULONG_PTR);" & _
    "Write long(ptr;ULONG;ULONG_PTR);" ; ISequentialStream

Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
Func _ErrFunc()
    ConsoleWrite("! COM Error !  Number: 0x" & Hex($oError.number, 8) & "   ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
    Return
EndFunc   ;==>_ErrFunc

_AutoItObject_Startup()

Dim $hMem = _MemGlobalAlloc(0x1000, $GHND)
If $hMem Then
    
    Dim $tStream = DllStructCreate("ptr")
    Dim $res = DllCall("ole32.dll", "long", "CreateStreamOnHGlobal", "HANDLE", $hMem, "BOOL", 0, "ptr", DllStructGetPtr($tStream, 1))
    If 0 = $res[0] And 0 <> DllStructGetData($tStream, 1) Then
        Dim $oStream = _AutoItObject_WrapperCreate(DllStructGetData($tStream, 1), $tagIStream)
        If IsObj($oStream) Then
            MsgBox(0, "Test", "IStream " & ObjName($oStream) & " Created!")
ConsoleWrite("Still there 1" & @LF)
            Dim $tw = DllStructCreate("wchar[128];ULONG")
            DllStructSetData($tw, 1, "Test string")
            Dim $hr = $oStream.Write(Number(DllStructGetPtr($tw, 1)), StringLen("Test string") * 2, Number(DllStructGetPtr($tw, 2)))
ConsoleWrite("Still there 2" & @LF)
            ConsoleWrite("HR(" & VarGetType($hr) & ")=" & $hr & @LF)
            $oStream = 0
ConsoleWrite("Still there 3" & @LF)
        Else
            MsgBox(0, "Error _AutoItObject_WrapperCreate", _WinAPI_GetLastErrorMessage())
        EndIf
    Else
        MsgBox(0, "Error CreateStreamOnHGlobal", _WinAPI_GetLastErrorMessage())
    EndIf
    
    Dim $p = _MemGlobalLock($hMem)
    If $p Then
        Dim $tr = DllStructCreate("wchar[128]", $p)
        MsgBox(0, "Test", "Buffer contents: [" & DllStructGetData($tr, 1) & "]")
        _MemGlobalUnlock($hMem)
    Else
        MsgBox(0, "Error", _WinAPI_GetLastErrorMessage())
    EndIf
    
    $tStream = 0
ConsoleWrite("Still there 4" & @LF)
    _MemGlobalFree($hMem)
ConsoleWrite("Still there 5" & @LF)
Else
    MsgBox(0, "Error GlobalAlloc", _WinAPI_GetLastErrorMessage())
EndIf
ConsoleWrite("Still there 6" & @LF)

RemoteRead isn't in the vtable of IStream at all because it is just an alias for DCOM calls.

Thx for help.


UDFS & Apps:


DDEML.au3 - DDE Client + Server[*]
Localization.au3- localize your scripts[*]
TLI.au3 - type information on COM objects (TLBINF emulation)[*]
TLBAutoEnum.au3 - auto-import of COM constants (enums)[*]
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector

- OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Share this post


Link to post
Share on other sites

Got it!

Here is the working version (actually it's my original code with the typo fixed! :mellow: )

#include <Memory.au3>
#include <WinAPI.au3>
#include "AutoItObject.au3"

Global $tagIStream = _
    "QueryInterface long(ptr;ptr;ptr);" & _
    "AddRef ulong();" & _
    "Release ulong();" & _ ; IUnknown
    "Read long(ptr;ULONG;ULONG_PTR);" & _
    "Write long(ptr;ULONG;ULONG_PTR);" ; ISequentialStream

Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
Func _ErrFunc()
    ConsoleWrite("! COM Error !  Number: 0x" & Hex($oError.number, 8) & "   ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
    Return
EndFunc   ;==>_ErrFunc

_AutoItObject_Startup()

Dim $hMem = _MemGlobalAlloc(0x1000, $GHND)
If $hMem Then
    
    Dim $tStream = DllStructCreate("ptr")
    Dim $res = DllCall("ole32.dll", "long", "CreateStreamOnHGlobal", "HANDLE", $hMem, "BOOL", 0, "ptr", DllStructGetPtr($tStream, 1))
    If 0 = $res[0] And 0 <> DllStructGetData($tStream, 1) Then
        Dim $oStream = _AutoItObject_WrapperCreate(DllStructGetData($tStream, 1), $tagIStream)
        If IsObj($oStream) Then
            MsgBox(0, "Test", "IStream " & ObjName($oStream) & " Created!")
ConsoleWrite("Still there 1" & @LF)
            Dim $tw = DllStructCreate("wchar[128];ULONG")
            DllStructSetData($tw, 1, "Test string")
            Dim $hr = $oStream.Write(Number(DllStructGetPtr($tw, 1)), StringLen("Test string") * 2, Number(DllStructGetPtr($tw, 2)))
ConsoleWrite("Still there 2" & @LF)
            ConsoleWrite("HR(" & VarGetType($hr) & ")=" & $hr & @LF)
            $oStream = 0
ConsoleWrite("Still there 3" & @LF)
        Else
            MsgBox(0, "Error _AutoItObject_WrapperCreate", _WinAPI_GetLastErrorMessage())
        EndIf
    Else
        MsgBox(0, "Error CreateStreamOnHGlobal", _WinAPI_GetLastErrorMessage())
    EndIf
    
    Dim $p = _MemGlobalLock($hMem)
    If $p Then
        Dim $tr = DllStructCreate("wchar[128]", $p)
        MsgBox(0, "Test", "Buffer contents: [" & DllStructGetData($tr, 1) & "]")
        _MemGlobalUnlock($hMem)
    Else
        MsgBox(0, "Error", _WinAPI_GetLastErrorMessage())
    EndIf
    
    $tStream = 0
ConsoleWrite("Still there 4" & @LF)
    _MemGlobalFree($hMem)
ConsoleWrite("Still there 5" & @LF)
Else
    MsgBox(0, "Error GlobalAlloc", _WinAPI_GetLastErrorMessage())
EndIf
ConsoleWrite("Still there 6" & @LF)

RemoteRead isn't in the vtable of IStream at all because it is just an alias for DCOM calls.

Thx for help.

So, when you read very first sentence addressed to you in this thread again, what comes to your mind?

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

So, when you read very first sentence addressed to you in this thread again, what comes to your mind?

Hmm... You mean, I should read carefully? Good idea. But hey, what do you expect from people who cannot read their own code?

Anyway all this has not been in vain: some aspects of _AutoItObject_WrapperCreate() functionality are much clearer now, at least to me.


UDFS & Apps:


DDEML.au3 - DDE Client + Server[*]
Localization.au3- localize your scripts[*]
TLI.au3 - type information on COM objects (TLBINF emulation)[*]
TLBAutoEnum.au3 - auto-import of COM constants (enums)[*]
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector

- OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Share this post


Link to post
Share on other sites

Hmm... You mean, I should read carefully? Good idea. But hey, what do you expect from people who cannot read their own code?

To read carefully.

Do you know what ULONG_PTR is?


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Do you know what ULONG_PTR is?

From AutoIt help: "an unsigned integer big enough to hold a pointer when running on x86 or x64 versions of AutoIt"

From BaseTsd.h (Win SDK):

#if ( 501 < __midl )

    typedef [public] __int3264 INT_PTR, *PINT_PTR;
    typedef [public] unsigned __int3264 UINT_PTR, *PUINT_PTR;

    typedef [public] __int3264 LONG_PTR, *PLONG_PTR;
    typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;

#else  // midl64
// old midl and C++ compiler

#if defined(_WIN64)
    typedef __int64 INT_PTR, *PINT_PTR;
    typedef unsigned __int64 UINT_PTR, *PUINT_PTR;

    typedef __int64 LONG_PTR, *PLONG_PTR;
    typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;

    #define __int3264   __int64

#else
    typedef _W64 int INT_PTR, *PINT_PTR;
    typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;

    typedef _W64 long LONG_PTR, *PLONG_PTR;
    typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;

    #define __int3264   __int32

#endif
#endif // midl64

Or what do you mean?


UDFS & Apps:


DDEML.au3 - DDE Client + Server[*]
Localization.au3- localize your scripts[*]
TLI.au3 - type information on COM objects (TLBINF emulation)[*]
TLBAutoEnum.au3 - auto-import of COM constants (enums)[*]
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector

- OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCE 

Share this post


Link to post
Share on other sites

From AutoIt help: "an unsigned integer big enough to hold a pointer when running on x86 or x64 versions of AutoIt"

From BaseTsd.h (Win SDK):

#if ( 501 < __midl )

    typedef [public] __int3264 INT_PTR, *PINT_PTR;
    typedef [public] unsigned __int3264 UINT_PTR, *PUINT_PTR;

    typedef [public] __int3264 LONG_PTR, *PLONG_PTR;
    typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;

#else  // midl64
// old midl and C++ compiler

#if defined(_WIN64)
    typedef __int64 INT_PTR, *PINT_PTR;
    typedef unsigned __int64 UINT_PTR, *PUINT_PTR;

    typedef __int64 LONG_PTR, *PLONG_PTR;
    typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;

    #define __int3264   __int64

#else
    typedef _W64 int INT_PTR, *PINT_PTR;
    typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;

    typedef _W64 long LONG_PTR, *PLONG_PTR;
    typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;

    #define __int3264   __int32

#endif
#endif // midl64

Or what do you mean?

I'm asking because I see you used ulong_ptr when defining $tagIStream.

And I don't see that types on msdn for that interface and those methods.


♡♡♡

.

eMyvnE

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

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...