Ticket #1395: LongerObjectWithProperty.au3

File LongerObjectWithProperty.au3, 5.7 KB (added by ProgAndy, 12 years ago)

just added a single property to the object, (the object is released on exit, uncomment OnAutoItExitUnregister to change)

Line 
1#include<StructureConstants.au3>
2#include<Memory.au3>
3
4;/* Flags for IDispatch::Invoke */
5
6Global Const $__Au3Obj_E_NOTIMPL = 0x80004001;
7Global Const $__Au3Obj_S_OK = 0;
8Global Const $__Au3Obj_DISP_E_BADINDEX = 0x8002000B
9Global Const $__Au3Obj_E_POINTER = 0x80004003
10Global Const $__Au3Obj_E_NOINTERFACE = 0x80004002
11Global Const $__AU3Obj_DISP_E_UNKNOWNNAME = 0x80020006
12Global Const $__AU3Obj_DISP_E_EXCEPTION = 0x80020009
13Global Const $__AU3Obj_DISPID_UNKNOWN = -1
14
15Global Const $__Au3Obj_vTable = DllStructCreate("ptr QueryInterface; ptr AddRef; ptr Release; ptr GetTypeInfoCount; ptr GetTypeInfo; ptr GetIDsOfNames; ptr Invoke;")
16; set DllCallbacks
17Dim $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
30Global Const $__Au3Obj_DISPATCH_METHOD = 0x1
31Global Const $__Au3Obj_DISPATCH_PROPERTYGET = 0x2
32Global Const $__Au3Obj_DISPATCH_PROPERTYPUT = 0x4
33Global 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
36Func 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]
43EndFunc   ;==>ConvertPtrToIDispatch
44
45
46Func __Au3Obj_QueryInterface($pObject, $iid, $ppvObject)
47        ; Actually Autoit is not calling this function, so leave it empty for testing ;)
48        Return $__Au3Obj_E_NOINTERFACE
49EndFunc   ;==>__Au3Obj_QueryInterface
50
51Func __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
57EndFunc   ;==>__Au3Obj_AddRef
58
59Func __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
69EndFunc   ;==>__Au3Obj_Release
70
71Func __Au3Obj_GetTypeInfoCount($pObject, $pctinfo)
72        ; Author: Prog@ndy
73        Return $__Au3Obj_E_NOTIMPL
74EndFunc   ;==>__Au3Obj_GetTypeInfoCount
75Func __Au3Obj_GetTypeInfo($pObject, $iTInfo, $lcid, $ppTInfo)
76        ; Author: Prog@ndy
77        Return $__Au3Obj_E_NOTIMPL
78EndFunc   ;==>__Au3Obj_GetTypeInfo
79Func __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
90EndFunc   ;==>__Au3Obj_GetIDsOfNames
91Func 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)
96EndFunc   ;==>PtrStringRead
97
98
99Func __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
117EndFunc   ;==>__Au3Obj_Invoke
118
119
120; construct object
121Local $iSize = DllStructGetSize(DllStructCreate("ptr vTable; dword refcount;", 1))
122Local $pMem = _MemGlobalAlloc($iSize, $GPTR) ; will be freed in Objectz::release
123Local $tStruct = DllStructCreate("ptr vTable; dword refcount;", $pMem)
124DllStructSetData($tStruct, 1, DllStructGetPtr($__Au3Obj_vTable))
125$object = ConvertPtrToIDispatch($pMem)
126OnAutoItExitRegister("__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
136Func __ReleaseObject()
137        $object=0
138EndFunc