Jump to content

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


Recommended Posts

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
Link to comment
Share on other sites

?? 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

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

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

Link to comment
Share on other sites

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*);",

 

Link to comment
Share on other sites

Link to comment
Share on other sites

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 ^^

Link to comment
Share on other sites

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

 

Saludos

 

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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)

 

Link to comment
Share on other sites

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

Yes.

 

Saludos

Link to comment
Share on other sites

  • 3 weeks later...

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 ^^

Link to comment
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
 Share

×
×
  • Create New...