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

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

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

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

 

Saludos

 

Link to post
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 post
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 post
Share on other sites
  • did you mean Genius257 can change the PTR references he uses in the objCreateInfterface call?

Yes.

 

Saludos

Link to post
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 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.

  • Similar Content

    • By SEuBo
      Hi there,
      while I created an example script to generate and execute a function during runtime, I stumbled across a neat way to share data between running autoit scripts.
      This is done using the amazing magic of  AutoItObject_Internal . (You'll need at least Version 3.0.0 of AutoItObject_Internal)
      Using this UDF, you can create a shared data storage, basically an empty "AutoitObject_Internal-"Object which you can then use to write / read data Inline. no set/get methods, just
      #include "AutoItSharedData.au3" $oShare = _AutoIt_SharedData_CreateOrAttach("MyCustomID") $oShare.some_data = 'foo' and you're done. any other script accessing this data will have to do:
      #include "AutoItSharedData.au3" $oShare = _AutoIt_SharedData_CreateOrAttach("MyCustomID") ConsoleWrite($oShare.some_data & @LF)  
      Basically it's Larsj's Implementing IRunningObjectTable Interface, but you dont have a Dictionary, but an IDIspatch Object instead.
      There are already a bunch of IPC options available - and this is another one.
      AutoItSharedData.au3
       
      Example Script 1
       
      Example Script 2
      Output: 
      To test: run Example Script 1, Then run example Script 2.. or the other way around.
      Example Script 3
      Example_sharedata3.au3
      Example_sharedata3_Controlsend.au3
      Example_sharedata3_Tooltip.au3
      To test: run Example_sharedata3.au3.
      Output: 
       
       Example SharedData4:
      Output: 
      /Edit: Please note that there's a limitation with the Running object table :
      The Script accessing a variable first, will be the "server" for this variable. This means, access to that variable from other scripts should only be possible, as long the "server" script is running! Use appropriate Object Error handlers in case you don't want the surviving "clients" to crash.
      Feedback and/or improvements appreciated
       
      changelog
      version 2.0
      Removed need for AutoItObject, as AutoItObject_Internal now comes with ROT support Added UDF Header Fixed typo on "#include AutoItObjectInternal.au3" -> "#include AutoItObject_Internal.au3" Added ObjGet() after registering the object fails (in case 2 programs tried to register the same ID simultaneously) Updated Examples & zip archive. Cheers,
       
      AutoItSharedData.zip
×
×
  • Create New...