genius257

[Solved] IRunningObjectTable.Register results in exception: Invalid number of parameters

14 posts in this topic

#1 ·  Posted (edited)

So I'm trying to register a object to the running object table (ROT).

I am doing something wrong, i just can't see what.

any help would be appreciated :)

AutoItObject_Internal.au3

IRunningObjectTable::Register method

#include "AutoItObject_Internal.au3"

$IID_IRunningObjectTable = "{00000010-0000-0000-C000-000000000046}"
$IID_IMoniker = "{0000000f-0000-0000-C000-000000000046}"

$AutoItError = ObjEvent("AutoIt.Error", "ErrFunc") ; Install a custom error handler
Func ErrFunc($oError)
    ConsoleWrite("!>COM Error !"&@CRLF&"!>"&@TAB&"Number: "&Hex($oError.Number,8)&@CRLF&"!>"&@TAB&"Windescription: "&StringRegExpReplace($oError.windescription,"\R$","")&@CRLF&"!>"&@TAB&"Source: "&$oError.source&@CRLF&"!>"&@TAB&"Description: "&$oError.description&@CRLF&"!>"&@TAB&"Helpfile: "&$oError.helpfile&@CRLF&"!>"&@TAB&"Helpcontext: "&$oError.helpcontext&@CRLF&"!>"&@TAB&"Lastdllerror: "&$oError.lastdllerror&@CRLF&"!>"&@TAB&"Scriptline: "&$oError.scriptline&@CRLF)
EndFunc ;==>ErrFunc

$IDispatch = IDispatch()
$IDispatch.name = "my name is Danny"
$IRunningObjectTable = DllCall("Ole32.dll","LONG","GetRunningObjectTable","DWORD",0,"PTR*",0)
If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)
$IRunningObjectTable = ObjCreateInterface($IRunningObjectTable[2],$IID_IRunningObjectTable,"Register HRESULT(DWORD,PTR*,PTR*,DWORD*);Revoke HRESULT(DWORD);IsRunning HRESULT(PTR*);GetObject HRESULT(PTR*,PTR**);NoteChangeTime HRESULT(DWORD,PTR*);GetTimeOfLastChange HRESULT(PTR*,PTR*);EnumRunning HRESULT(PTR*);",True)
If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)


$sCLSID="AutoIt.COMDemo"
$IMoniker=DllCall("Ole32.dll", "LONG", "CreateFileMoniker", "WSTR", $sCLSID, "PTR*", 0)
If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)

$dwRegister=0
$IRunningObjectTable.Register( 0, Ptr($IDispatch), $IMoniker[2], $dwRegister )
If @error<>0 Then Exit 1
If $dwRegister=0 Then Exit 2

$IRunningObjectTable.Revoke($dwRegister)

Opt("GuiOnEventMode", 1)

$hWnd=GUICreate("Title",700,320)
GUISetState(@SW_SHOW,$hWnd)

GUISetOnEvent(-3, "_MyExit", $hWnd)

While 1
    Sleep(10)
WEnd

Func _MyExit()
    $IDispatch=0
    Exit
EndFunc

Thanks in advance

Edited by genius257
1 person likes this

Share this post


Link to post
Share on other sites



#4 ·  Posted

?? are you referring to this line?

$IRunningObjectTable.Register( 0, Ptr($IDispatch), $IMoniker[2], $dwRegister )

if so, how can be used ";" instead of "," ?

(just curious)

Thanks


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

#5 ·  Posted

We are talking about this line section in the ObjCreateInterface function call:

"Register HRESULT(DWORD,PTR*,PTR*,DWORD*);Revoke HRESULT(DWORD);IsRunning HRESULT(PTR*);GetObject HRESULT(PTR*,PTR**);NoteChangeTime HRESULT(DWORD,PTR*);GetTimeOfLastChange HRESULT(PTR*,PTR*);EnumRunning HRESULT(PTR*);",

 

Share this post


Link to post
Share on other sites

#6 ·  Posted

I'm  curious About this. 

PTR**

Saludos

Share this post


Link to post
Share on other sites

#7 ·  Posted

11 minutes ago, Danyfirex said:

I'm  curious About this. 

PTR**

Saludos

Yeah ^^ not currently using GetObject, but it should be "PTR*" i think.

I only tested the Register, Revoke and EnumRunning so the rest of the methods will need to be corrected ^^

Share this post


Link to post
Share on other sites

#8 ·  Posted

AutoIt ObjCreateInterface also support idispatch, object type if you are interested.

 

Saludos

 

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

I made it work, only issue currently is IUnknown.Release is called on my object 3 or 1 time(s), depending if the object is used or not before calling $IRunningObjectTable.Revoke.

I suspect this may be an error in my custom object returned from IDispatch().

If not i will look into the other interfaces requested when calling IUnknown.QueryInterface

I will post the functional code in this post when i get home later today and can access my code.

 

#include <WinAPIDiag.au3>
#include "..\AutoItObject_Internal.au3"

$IID_IRunningObjectTable = "{00000010-0000-0000-C000-000000000046}"
$IID_IMoniker = "{0000000f-0000-0000-C000-000000000046}"

$AutoItError = ObjEvent("AutoIt.Error", "ErrFunc") ; Install a custom error handler
Func ErrFunc($oError)
    ConsoleWrite("!>COM Error !"&@CRLF&"!>"&@TAB&"Number: "&Hex($oError.Number,8)&@CRLF&"!>"&@TAB&"Windescription: "&StringRegExpReplace($oError.windescription,"\R$","")&@CRLF&"!>"&@TAB&"Source: "&$oError.source&@CRLF&"!>"&@TAB&"Description: "&$oError.description&@CRLF&"!>"&@TAB&"Helpfile: "&$oError.helpfile&@CRLF&"!>"&@TAB&"Helpcontext: "&$oError.helpcontext&@CRLF&"!>"&@TAB&"Lastdllerror: "&$oError.lastdllerror&@CRLF&"!>"&@TAB&"Scriptline: "&$oError.scriptline&@CRLF)
EndFunc ;==>ErrFunc

$IDispatch = IDispatch()

$IDispatch.name = "my name is Danny"
$IRunningObjectTable = DllCall("Ole32.dll","LONG","GetRunningObjectTable","DWORD",0,"PTR*",0)
If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)
$IRunningObjectTable = ObjCreateInterface($IRunningObjectTable[2],$IID_IRunningObjectTable,"Register HRESULT(DWORD;PTR;PTR;DWORD*);Revoke HRESULT(DWORD);IsRunning HRESULT(PTR*);GetObject HRESULT(PTR;PTR*);NoteChangeTime HRESULT(DWORD;PTR*);GetTimeOfLastChange HRESULT(PTR*;PTR*);EnumRunning HRESULT(PTR*);",True)
If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)

$sCLSID="AutoIt.COMDemo"
$IMoniker=DllCall("Ole32.dll", "LONG", "CreateFileMoniker", "WSTR", $sCLSID, "PTR*", 0)
If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)

Global Const $ROTFLAGS_REGISTRATIONKEEPSALIVE=0x01
Global Const $ROTFLAGS_ALLOWANYCLIENT=0x02

AddRef(Ptr($IDispatch))

$dwRegister=0
$r=$IRunningObjectTable.Register( 0, ptr($IDispatch), $IMoniker[2], $dwRegister )
If @error<>0 Then Exit 1
If $dwRegister=0 Then
    MsgBox(0, "", _WinAPI_GetErrorMessage($r))
    Exit 2
EndIf

$IMoniker = ObjCreateInterface($IMoniker[2], $IID_IMoniker)

AddRef(Ptr($IDispatch))
AddRef(Ptr($IDispatch))
AddRef(Ptr($IDispatch));TODO: look into RunningObjectTable calling IUnknown:Release 3 times if used one or more times, but only once if not used before release @.@

$IMoniker=0

$IRunningObjectTable=0

Opt("GuiOnEventMode", 1)

$hWnd=GUICreate("Title",700,320)
GUISetState(@SW_SHOW,$hWnd)

GUISetOnEvent(-3, "_MyExit", $hWnd)

While 1
    Sleep(10)
WEnd

Func _MyExit()
    Local $IRunningObjectTable = DllCall("Ole32.dll","LONG","GetRunningObjectTable","DWORD",0,"PTR*",0)
    If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)
    $IRunningObjectTable = ObjCreateInterface($IRunningObjectTable[2],$IID_IRunningObjectTable,"Register HRESULT(DWORD;PTR;PTR;DWORD*);Revoke HRESULT(DWORD);IsRunning HRESULT(PTR*);GetObject HRESULT(PTR*;PTR**);NoteChangeTime HRESULT(DWORD;PTR*);GetTimeOfLastChange HRESULT(PTR*;PTR*);EnumRunning HRESULT(PTR*);",True)
    If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)

    $IRunningObjectTable.Revoke($dwRegister)
    ConsoleWrite("IRunningObjectTable.Revoke"&@CRLF)
    $IRunningObjectTable=0
    $IDispatch=0
    Exit
EndFunc

AutoItObject_Internal.au3

Files to test while the script is running

test.vbs

com.php

Change first parameter in IRunningObjectTable.Register to $ROTFLAGS_REGISTRATIONKEEPSALIVE and the object won't be released from the ROT until IRunningObjectTable.Revoke is called

Edited by genius257
1 person likes this

Share this post


Link to post
Share on other sites

#11 ·  Posted

On 20-8-2017 at 4:06 PM, Danyfirex said:

AutoIt ObjCreateInterface also support idispatch, object type if you are interested.

Saludos

@Danyfirex

  • did you mean Genius257 can change the PTR references he uses in the objCreateInfterface call?

or

  • did you mean to create an idispatch object quicker/easier then how its done in for example

https://github.com/turbo/OOPEAu3/blob/master/OOPE/OOPE.au3

I can see the memory reservation and filling of all the COM reference functions

Local $tObj = __DllStructCreateProtected($__OOPE_ObjectInstanceVariables & $sObjVars & '; ' & $__OOPE_ObjectStdMethods & StringTrimRight($sObjTypes, 1))

and then later onwards the final creation of the object with help of objCreateInterface

$oObj = ObjCreateInterface(DllStructGetPtr($tObj), _WinAPI_CreateGUID(), $sObjMethods)

 

Share this post


Link to post
Share on other sites

#12 ·  Posted

  • did you mean Genius257 can change the PTR references he uses in the objCreateInfterface call?

Yes.

 

Saludos

Share this post


Link to post
Share on other sites

Hi @junkew.

Yeah i plan on adding ROT registration to the library, but i prefer not to do it, as long as it suffers from the reference miscount problem.

Here's the code i use to look into the problem for now:

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.2
 Author:         genius257

#ce ----------------------------------------------------------------------------
#include <WinAPIDiag.au3>
#include "..\AutoItObject_Internal.au3"

$IID_IRunningObjectTable = "{00000010-0000-0000-C000-000000000046}"
$IID_IMoniker = "{0000000f-0000-0000-C000-000000000046}"

$AutoItError = ObjEvent("AutoIt.Error", "ErrFunc") ; Install a custom error handler
Func ErrFunc($oError)
    ConsoleWrite("!>COM Error !"&@CRLF&"!>"&@TAB&"Number: "&Hex($oError.Number,8)&@CRLF&"!>"&@TAB&"Windescription: "&StringRegExpReplace($oError.windescription,"\R$","")&@CRLF&"!>"&@TAB&"Source: "&$oError.source&@CRLF&"!>"&@TAB&"Description: "&$oError.description&@CRLF&"!>"&@TAB&"Helpfile: "&$oError.helpfile&@CRLF&"!>"&@TAB&"Helpcontext: "&$oError.helpcontext&@CRLF&"!>"&@TAB&"Lastdllerror: "&$oError.lastdllerror&@CRLF&"!>"&@TAB&"Scriptline: "&$oError.scriptline&@CRLF)
EndFunc ;==>ErrFunc

$IDispatch = IDispatch(QueryInterface2, AddRef2, Release2)

$IDispatch.name = "my name is Danny"
$IRunningObjectTable = DllCall("Ole32.dll","LONG","GetRunningObjectTable","DWORD",0,"PTR*",0)
If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)
$IRunningObjectTable = ObjCreateInterface($IRunningObjectTable[2],$IID_IRunningObjectTable,"Register HRESULT(DWORD;PTR;PTR;DWORD*);Revoke HRESULT(DWORD);IsRunning HRESULT(PTR*);GetObject HRESULT(PTR;PTR*);NoteChangeTime HRESULT(DWORD;PTR*);GetTimeOfLastChange HRESULT(PTR*;PTR*);EnumRunning HRESULT(PTR*);",True)
If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)

$sCLSID="AutoIt.COMDemo"
$IMoniker=DllCall("Ole32.dll", "LONG", "CreateFileMoniker", "WSTR", $sCLSID, "PTR*", 0)
If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)
;~ $IMoniker = ObjCreateInterface($IMoniker[2], $IID_IMoniker, "GetClassID;IsDirty;Load;Save;GetSizeMax;BindToObject;BindToStorage;Reduce;ComposeWith;Enum;IsEqual;Hash;IsRunning;GetTimeOfLastChange;Inverse;CommonPrefixWith;RelativePathTo;GetDisplayName;ParseDisplayName;IsSystemMoniker")

Global Const $ROTFLAGS_REGISTRATIONKEEPSALIVE=0x01
Global Const $ROTFLAGS_ALLOWANYCLIENT=0x02

AddRef(Ptr($IDispatch))

$dwRegister=0
ConsoleWrite("Before $IRunningObjectTable.Register"&@CRLF)
;~ $r=$IRunningObjectTable.Register( $ROTFLAGS_REGISTRATIONKEEPSALIVE, ptr($IDispatch), $IMoniker[2], $dwRegister ) ; use this to allow multiple use for now
$r=$IRunningObjectTable.Register( 0, ptr($IDispatch), $IMoniker[2], $dwRegister )
;~ MsgBox(0, "$IRunningObjectTable.Register", $r)
If @error<>0 Then Exit 1
If $dwRegister=0 Then
    MsgBox(0, "", _WinAPI_GetErrorMessage($r))
    Exit 2
EndIf
ConsoleWrite("After $IRunningObjectTable.Register"&@CRLF)

$IMoniker = ObjCreateInterface($IMoniker[2], $IID_IMoniker)

ConsoleWrite("BeforePadding"&@CRLF);adding extra count, to prevent miscount if object is used before release from ROT
AddRef(Ptr($IDispatch))
AddRef(Ptr($IDispatch))
AddRef(Ptr($IDispatch));TODO: look into RunningObjectTable calling IUnknown:Release 3 times if used one or more times, but only once if not used before release @.@
ConsoleWrite("AfterPadding"&@CRLF)

$IMoniker=0

$IRunningObjectTable=0

Opt("GuiOnEventMode", 1)

$hWnd=GUICreate("Title",700,320)
GUISetState(@SW_SHOW,$hWnd)

GUISetOnEvent(-3, "_MyExit", $hWnd)

While 1
    Sleep(10)
WEnd

Func _MyExit()
    Local $IRunningObjectTable = DllCall("Ole32.dll","LONG","GetRunningObjectTable","DWORD",0,"PTR*",0)
    If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)
    $IRunningObjectTable = ObjCreateInterface($IRunningObjectTable[2],$IID_IRunningObjectTable,"Register HRESULT(DWORD;PTR;PTR;DWORD*);Revoke HRESULT(DWORD);IsRunning HRESULT(PTR*);GetObject HRESULT(PTR*;PTR**);NoteChangeTime HRESULT(DWORD;PTR*);GetTimeOfLastChange HRESULT(PTR*;PTR*);EnumRunning HRESULT(PTR*);",True)
    If @error<>0 Then Exit MsgBox(0, @ScriptLineNumber, @error)

    $IRunningObjectTable.Revoke($dwRegister)
    ConsoleWrite("IRunningObjectTable.Revoke"&@CRLF)
    $IRunningObjectTable=0
    $IDispatch=0
    Exit
EndFunc

Func QueryInterface2($pSelf, $pRIID, $pObj)
    Local $sGUID=DllCall("ole32.dll", "int", "StringFromGUID2", "PTR", $pRIID, "wstr", "", "int", 40)[2]
    ConsoleWrite("["&@ScriptLineNumber&"]: QueryInterface - "&$sGUID&@CRLF)
    Local $_ = QueryInterface($pSelf, $pRIID, $pObj)
;~  If $sGUID="{4C1E39E1-E3E3-4296-AA86-EC938D896E92}" Then Return $S_OK ;more problems
    Return $_
EndFunc

Func AddRef2($pSelf)
    Local $_=AddRef($pSelf)
    ConsoleWrite("AddRef: "&$_&@CRLF)
    Return $_
EndFunc

Func Release2($pSelf)
    Local $_=Release($pSelf)
    ConsoleWrite("Release: "&$_&@CRLF)
    Return $_
EndFunc

output:

>"C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "C:\Users\...\AutoItObject Internal\Examples\05.au3" /UserParams    
+>11:30:31 Starting AutoIt3Wrapper v.2.1.0.33    Environment(Language:0409  Keyboard:00000406  OS:WIN_7/Service Pack 1  CPU:X64 OS:X64)
>Running AU3Check (3.3.14.2)  from:C:\Program Files (x86)\AutoIt3
+>11:30:31 AU3Check ended.rc:0
>Running:(3.3.14.2):C:\Program Files (x86)\AutoIt3\autoit3.exe "C:\Users\...\AutoItObject Internal\Examples\05.au3"    
--> Press Ctrl+Alt+F5 to Restart or Ctrl+Break to Stop
[86]: QueryInterface - {00020400-0000-0000-C000-000000000046}
Release: 1
AddRef: 2
Release: 1
AddRef: 2
Release: 1
AddRef: 2
Release: 1
AddRef: 2
Release: 1
AddRef: 2
Release: 1
Before $IRunningObjectTable.Register
AddRef: 3
Release: 2
[86]: QueryInterface - {00000008-0000-0000-C000-000000000046}
[86]: QueryInterface - {00000003-0000-0000-C000-000000000046}
[86]: QueryInterface - {0000001B-0000-0000-C000-000000000046}
[86]: QueryInterface - {00000000-0000-0000-C000-000000000046}
AddRef: 3
[86]: QueryInterface - {00000018-0000-0000-C000-000000000046}
[86]: QueryInterface - {00000019-0000-0000-C000-000000000046}
[86]: QueryInterface - {4C1E39E1-E3E3-4296-AA86-EC938D896E92}
Release: 2
[86]: QueryInterface - {00000003-0000-0000-C000-000000000046}
[86]: QueryInterface - {0000001B-0000-0000-C000-000000000046}
[86]: QueryInterface - {00000000-0000-0000-C000-000000000046}
Release: 1
After $IRunningObjectTable.Register
BeforePadding
AddRef: 2
Release: 1
AddRef: 3
Release: 2
AddRef: 4
Release: 3
AfterPadding
[86]: QueryInterface - {FC4801A3-2BA9-11CF-A229-00AA003D7352}
[86]: QueryInterface - {00020400-0000-0000-C000-000000000046}
AddRef: 5
[86]: QueryInterface - {A6EF9860-C720-11D0-9337-00A0C90DCAA9}
[86]: QueryInterface - {1C733A30-2A1C-11CE-ADE5-00AA0044773D}
[86]: QueryInterface - {00020400-0000-0000-C000-000000000046}
[86]: QueryInterface - {A6EF9860-C720-11D0-9337-00A0C90DCAA9}
Release: 4
Release: 3
Release: 2
Release: 1
IRunningObjectTable.Revoke
Release: 0
+>11:30:48 AutoIT3.exe ended.rc:0
>Exit code: 0    Time: 18.177

the output between AfterPadding and IRunningObjectTable.Revoke is when i use the vbs script to access the object

test.vbs

Dim objXL
Set objXL = GetObject("AutoIt.COMDemo")
MsgBox(objXL.name)
Set objXL = Nothing

Any help would be nice ^^

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