Ticket #1395: LongerObjectWithProperty.au3

File LongerObjectWithProperty.au3, 5.7 KB (added by ProgAndy, on Jan 6, 2010 at 11:25:10 AM)

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