| 1 | #include<StructureConstants.au3>
|
|---|
| 2 | #include<Memory.au3>
|
|---|
| 3 |
|
|---|
| 4 | ;/* Flags for IDispatch::Invoke */
|
|---|
| 5 |
|
|---|
| 6 | Global Const $__Au3Obj_E_NOTIMPL = 0x80004001;
|
|---|
| 7 | Global Const $__Au3Obj_S_OK = 0;
|
|---|
| 8 | Global Const $__Au3Obj_DISP_E_BADINDEX = 0x8002000B
|
|---|
| 9 | Global Const $__Au3Obj_E_POINTER = 0x80004003
|
|---|
| 10 | Global Const $__Au3Obj_E_NOINTERFACE = 0x80004002
|
|---|
| 11 | Global Const $__AU3Obj_DISP_E_UNKNOWNNAME = 0x80020006
|
|---|
| 12 | Global Const $__AU3Obj_DISP_E_EXCEPTION = 0x80020009
|
|---|
| 13 | Global Const $__AU3Obj_DISPID_UNKNOWN = -1
|
|---|
| 14 |
|
|---|
| 15 | Global Const $__Au3Obj_vTable = DllStructCreate("ptr QueryInterface; ptr AddRef; ptr Release; ptr GetTypeInfoCount; ptr GetTypeInfo; ptr GetIDsOfNames; ptr Invoke;")
|
|---|
| 16 | ; set DllCallbacks
|
|---|
| 17 | Dim $aCallbacks[8]
|
|---|
| 18 | $aCallbacks[1] = DllCallbackRegister("__Au3Obj_QueryInterface", "long", "ptr;dword;dword") ;QureyInterface
|
|---|
| 19 | $aCallbacks[2] = DllCallbackRegister("__Au3Obj_AddRef", "long", "ptr") ;Addref
|
|---|
| 20 | $aCallbacks[3] = DllCallbackRegister("__Au3Obj_Release", "long", "ptr") ;Release
|
|---|
| 21 | $aCallbacks[4] = DllCallbackRegister("__Au3Obj_GetTypeInfoCount", "long", "ptr;ptr")
|
|---|
| 22 | $aCallbacks[5] = DllCallbackRegister("__Au3Obj_GetTypeInfo", "long", "ptr;uint;int;ptr")
|
|---|
| 23 | $aCallbacks[6] = DllCallbackRegister("__Au3Obj_GetIDsOfNames", "long", "ptr;ptr;ptr;uint;int;ptr")
|
|---|
| 24 | $aCallbacks[7] = DllCallbackRegister("__Au3Obj_Invoke", "long", "ptr;int;ptr;int;ushort;ptr;ptr;ptr;ptr")
|
|---|
| 25 | For $i = 1 To 7
|
|---|
| 26 | DllStructSetData($__Au3Obj_vTable, $i, DllCallbackGetPtr($aCallbacks[$i]))
|
|---|
| 27 | Next
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 | Global Const $__Au3Obj_DISPATCH_METHOD = 0x1
|
|---|
| 31 | Global Const $__Au3Obj_DISPATCH_PROPERTYGET = 0x2
|
|---|
| 32 | Global Const $__Au3Obj_DISPATCH_PROPERTYPUT = 0x4
|
|---|
| 33 | Global Const $__Au3Obj_DISPATCH_PROPERTYPUTREF = 0x8
|
|---|
| 34 |
|
|---|
| 35 | ; In the end we still want the autoit object. This function converts a raw pointer to an autoit object
|
|---|
| 36 | Func ConvertPtrToIDispatch($pIDispatch)
|
|---|
| 37 | ; Author: monoceres
|
|---|
| 38 | ; This would have been 10000x easier if autoit had supported the idispatch* type in dllstructs...
|
|---|
| 39 | ; Fortunetely memcpy can copy the pointer into a idispatch*, lucky us.
|
|---|
| 40 | Local $aCall = DllCall("kernel32.dll", "none", "RtlMoveMemory", "idispatch*", 0, "ptr*", $pIDispatch, "dword", DllStructGetSize(DllStructCreate('ptr',1)))
|
|---|
| 41 | If @error Then Return SetError(1, 0, 0)
|
|---|
| 42 | Return $aCall[1]
|
|---|
| 43 | EndFunc ;==>ConvertPtrToIDispatch
|
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 | Func __Au3Obj_QueryInterface($pObject, $iid, $ppvObject)
|
|---|
| 47 | ; Actually Autoit is not calling this function, so leave it empty for testing ;)
|
|---|
| 48 | Return $__Au3Obj_E_NOINTERFACE
|
|---|
| 49 | EndFunc ;==>__Au3Obj_QueryInterface
|
|---|
| 50 |
|
|---|
| 51 | Func __Au3Obj_AddRef($pObject)
|
|---|
| 52 | ; Author: Prog@ndy
|
|---|
| 53 | Local $st = DllStructCreate("ptr;dword", $pObject)
|
|---|
| 54 | Local $iCount = DllStructGetData($st, 2) + 1
|
|---|
| 55 | DllStructSetData($st, 2, $iCount)
|
|---|
| 56 | Return $iCount
|
|---|
| 57 | EndFunc ;==>__Au3Obj_AddRef
|
|---|
| 58 |
|
|---|
| 59 | Func __Au3Obj_Release($pObject)
|
|---|
| 60 | ; Author: Prog@ndy
|
|---|
| 61 | Local $st = DllStructCreate("ptr;dword", $pObject)
|
|---|
| 62 | Local $iCount = DllStructGetData($st, 2) - 1
|
|---|
| 63 | If $iCount < 0 Then Return 0
|
|---|
| 64 | DllStructSetData($st, 2, $iCount)
|
|---|
| 65 | If $iCount = 0 Then ; delete Object
|
|---|
| 66 | _MemGlobalFree($pObject)
|
|---|
| 67 | EndIf
|
|---|
| 68 | Return $iCount
|
|---|
| 69 | EndFunc ;==>__Au3Obj_Release
|
|---|
| 70 |
|
|---|
| 71 | Func __Au3Obj_GetTypeInfoCount($pObject, $pctinfo)
|
|---|
| 72 | ; Author: Prog@ndy
|
|---|
| 73 | Return $__Au3Obj_E_NOTIMPL
|
|---|
| 74 | EndFunc ;==>__Au3Obj_GetTypeInfoCount
|
|---|
| 75 | Func __Au3Obj_GetTypeInfo($pObject, $iTInfo, $lcid, $ppTInfo)
|
|---|
| 76 | ; Author: Prog@ndy
|
|---|
| 77 | Return $__Au3Obj_E_NOTIMPL
|
|---|
| 78 | EndFunc ;==>__Au3Obj_GetTypeInfo
|
|---|
| 79 | Func __Au3Obj_GetIDsOfNames($pObject, $riid, $rgszNames, $cNames, $lcid, $rgDispId)
|
|---|
| 80 | ; Author: Prog@ndy
|
|---|
| 81 | If $cNames = 0 Then Return $__AU3Obj_DISP_E_UNKNOWNNAME
|
|---|
| 82 |
|
|---|
| 83 | Local $sName = PtrStringRead(DllStructGetData(DllStructCreate('ptr', $rgszNames), 1))
|
|---|
| 84 | If $sName = "example" Then
|
|---|
| 85 | DllStructSetData(DllStructCreate("int", $rgDispId),1, 1) ; give $sName the DispID 1
|
|---|
| 86 | Return $__Au3Obj_S_OK
|
|---|
| 87 | EndIf
|
|---|
| 88 |
|
|---|
| 89 | Return $__AU3Obj_DISP_E_UNKNOWNNAME
|
|---|
| 90 | EndFunc ;==>__Au3Obj_GetIDsOfNames
|
|---|
| 91 | Func PtrStringRead($pStr)
|
|---|
| 92 | ; Author: Prog@ndy
|
|---|
| 93 | Local $aResult = DllCall("kernel32.dll", 'int', 'lstrlenW', 'ptr', $pStr)
|
|---|
| 94 | If @error Or $aResult<1 Then Return SetError(1, 0, 0)
|
|---|
| 95 | Return DllStructGetData(DllStructCreate("wchar[" & $aResult[0] & "]", $pStr), 1)
|
|---|
| 96 | EndFunc ;==>PtrStringRead
|
|---|
| 97 |
|
|---|
| 98 |
|
|---|
| 99 | Func __Au3Obj_Invoke($pObject, $dispIdMember, $riid, $lcid, $wFlags, $pDispParams, $pVarResult, $pExcepInfo, $puArgErr)
|
|---|
| 100 | ; Author: monoceres, Prog@ndy
|
|---|
| 101 | If $dispIdMember <> 1 Then Return $__AU3Obj_DISP_E_EXCEPTION ; we only support the call with ID 1
|
|---|
| 102 | Select
|
|---|
| 103 | Case BitAND($wFlags, $__Au3Obj_DISPATCH_PROPERTYPUTREF)
|
|---|
| 104 | ;$tExcepInfo = DllStructCreate("ushort wCode; ushort wReserved; ptr bstrSource; ptr bstrDescription; ptr bstrHelpFile; ulong dwHelpContext; ptr pvReserved; ptr pfnDeferredFillIn: ushort scode;", $pExcepInfo)
|
|---|
| 105 | ;DllStructSetData($tExcepInfo, 1, 1001)
|
|---|
| 106 | Return $__AU3Obj_DISP_E_EXCEPTION
|
|---|
| 107 | Case $wFlags = BitOR($__Au3Obj_DISPATCH_METHOD, $__Au3Obj_DISPATCH_PROPERTYGET)
|
|---|
| 108 | MsgBox(0, '', "Method call or GET property with dispId " & $dispIdMember)
|
|---|
| 109 | Return $__Au3Obj_S_OK
|
|---|
| 110 | Case BitAND($wFlags, $__Au3Obj_DISPATCH_PROPERTYPUT)
|
|---|
| 111 | MsgBox(0, '', "PUT property with DispId" & $dispIdMember)
|
|---|
| 112 | Return $__Au3Obj_S_OK
|
|---|
| 113 | Case Else
|
|---|
| 114 | Return $__AU3Obj_DISP_E_EXCEPTION
|
|---|
| 115 | EndSelect
|
|---|
| 116 | Return $__AU3Obj_DISP_E_EXCEPTION
|
|---|
| 117 | EndFunc ;==>__Au3Obj_Invoke
|
|---|
| 118 |
|
|---|
| 119 |
|
|---|
| 120 | ; construct object
|
|---|
| 121 | Local $iSize = DllStructGetSize(DllStructCreate("ptr vTable; dword refcount;", 1))
|
|---|
| 122 | Local $pMem = _MemGlobalAlloc($iSize, $GPTR) ; will be freed in Objectz::release
|
|---|
| 123 | Local $tStruct = DllStructCreate("ptr vTable; dword refcount;", $pMem)
|
|---|
| 124 | DllStructSetData($tStruct, 1, DllStructGetPtr($__Au3Obj_vTable))
|
|---|
| 125 | $object = ConvertPtrToIDispatch($pMem)
|
|---|
| 126 | OnAutoItExitRegister("__ReleaseObject")
|
|---|
| 127 |
|
|---|
| 128 | ; calling existing method/property
|
|---|
| 129 | $object.example ;defined in __Au3Obj_GetIDsOfNames
|
|---|
| 130 | $object.example = "bla"
|
|---|
| 131 |
|
|---|
| 132 | ; Test:
|
|---|
| 133 | ; Exit without releasing the object
|
|---|
| 134 | ;~ OnAutoItExitUnregister("__ReleaseObject")
|
|---|
| 135 |
|
|---|
| 136 | Func __ReleaseObject()
|
|---|
| 137 | $object=0
|
|---|
| 138 | EndFunc
|
|---|