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