Menu

[r2337]: / trunk / Src / USimpleDispatch.pas  Maximize  Restore  History

Download this file

325 lines (301 with data), 13.7 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
{
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/
*
* Copyright (C) 2007-2012, Peter Johnson (www.delphidabbler.com).
*
* $Rev$
* $Date$
*
* Provides an abstract base class that provides a simple, non reference
* counted, implementation of IDispatch.
}
unit USimpleDispatch;
interface
uses
// Delphi
ActiveX,
// Project
UBaseObjects;
type
{
TInvokeInfo:
Structure providing information about a method or property invocation on an
object. Implementors of TSimpleDispatch.DoInvoke must use and update this
structure. Note that locales and exception information are not supported.
}
TInvokeInfo = record
DispatchID: Integer; // provides dispatch id of method or property
Flags: Word; // flags describing context of invocation
Params: TDispParams; // provides parameters passed to method
FnResult: OleVariant; // set to return value from method
ArgErr: Cardinal; // set to index of error parameter
SCode: HResult; // set to HResult describing success of invocation
end;
{
TSimpleDispatch:
Abstract base class that implements IDispatch that can be subclassed by
classes that need to provide a simple, non reference counted, implementation
of IDispatch. Descendants override the abstract DoInvoke method.
}
TSimpleDispatch = class(TNonRefCountedObject,
IDispatch
)
protected
procedure DoInvoke(var InvokeInfo: TInvokeInfo); virtual; abstract;
{Abstract method to be implemented by sub-classes to invoke properties
and methods.
@param InvokeInfo [in/out] Information about method / property
invocation. Structure is to be updated with information about any
error and function results etc.
}
function GetValidParam(var InvokeInfo: TInvokeInfo; const Idx: Integer;
const VType: Byte; out Param: OleVariant): Boolean;
overload;
{Validates and retrieves value of a parameter of required type. Updates
InvokeInfo if parameter invalid.
@param InvokeInfo [in/out] Information about method invocation.
Structure is updated with information about any error.
@param Idx [in] Index of parameter (parameters stored in reverse order).
@param VType [in] Required parameter type.
@param Param [out] Receives value of parameter. Value is undefined if
parameter is invalid.
@return True if parameter is valid, False if not.
}
function GetValidParam(var InvokeInfo: TInvokeInfo; const Idx: Integer;
const VType: Byte; const IID: TGUID; out Param): Boolean;
overload;
{Validates and retrieves required interface to a parameter. Updates
InvokeInfo if parameter invalid.
@param InvokeInfo [in/out] Information about method invocation.
Structure is updated with information about any error.
@param Idx [in] Index of parameter (parameters stored in reverse order).
@param VType [in] Required parameter type. Must be either varUnknown or
varDispatch.
@param IID [in] Specifies required interface supported by parameter.
@param Param [out] Reference to required interface implementation.
Undefined if parameter wrong type or interface not supported.
@return True if parameter is valid and supports the required interface,
False if VType not varUnknowm or varDispatch, parameter is not
required VType or parameter does not support the required interface.
}
{ IDispatch methods }
function GetIDsOfNames(const IID: TGUID; Names: Pointer;
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
{Maps a single member and an optional set of argument names to a
corresponding set of integer DISPIDs, which may be used on subsequent
calls to IDispatch::Invoke.
@param IID [in] Reserved. Must be 0.
@param Names [in] Array of names to be mapped.
@param NameCount [in] Count of names in Names.
@param LocaleID [in] The locale context in which to interpret the names.
@param DispIDs [in] Caller-allocated array, each element of which
contains an ID corresponding to one of the names passed in the Names
array. The first element represents the member name. Subsequent
elements represent each of the member's parameters.
@return Success or failure code. We return E_NOTIMPL.
}
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult;
stdcall;
{Retrieves a type information object, which can be used to get the type
information for an interface.
@param Index [in] Index of type information to return. Pass 0 to
retrieve type information for the IDispatch implementation.
@param LocaleID [in] The locale ID for the type information.
@param TypeInfo [out] Set to ITypeInfo interface of type information
requested. We set to nil.
@return Success or failure code. We return E_NOTIMPL.
}
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
{Retrieves the number of type information interfaces that an object
provides (either 0 or 1).
@param Count [out] Receives the number of type information interfaces
that the object provides. If the object provides type information,
this number is 1; otherwise the number is 0. We set to 0.
@return Success of failure code. We return E_NOTIMPL.
}
function Invoke(ADispID: Integer; const AIID: TGUID; ALocaleID: Integer;
AFlags: Word; var AParams; AVarResult, AExcepInfo,
AArgErr: Pointer): HResult; stdcall;
{Provides access to properties and methods exposed by an object.
@param ADispId [in] Identifies the member of the object.
@param AIID [in] Reserved. Must be IID_NULL.
@param ALocaleID [in] The locale context in which to interpret
arguments. Not used.
@param AFlags [in] Flags describing the context of the Invoke call.
@param AParams [in/out] Pointer to structure containing an array of
arguments, array of argument dispatch IDs for named arguments, and
counts for number of elements in the arrays.
@param AVarResult [in/out] Pointer to where the result is to be stored,
or NULL if the caller expects no result.
@param AExcepInfo [in/out] Pointer to a structure containing any
exception information. Not used.
@param AArgErr [in/out] Index within AParams.rgvarg[] array of the first
argument that has an error.
@return Success or failure code.
}
end;
implementation
uses
// Delphi
Variants, Windows;
{ TSimpleDispatch }
function TSimpleDispatch.GetIDsOfNames(const IID: TGUID; Names: Pointer;
NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
{Maps a single member and an optional set of argument names to a corresponding
set of integer DISPIDs, which may be used on subsequent calls to
IDispatch.Invoke.
@param IID [in] Reserved. Must be 0.
@param Names [in] Array of names to be mapped.
@param NameCount [in] Count of names in Names.
@param LocaleID [in] The locale context in which to interpret the names.
@param DispIDs [in] Caller-allocated array, each element of which contains
an ID corresponding to one of the names passed in the Names array. The
first element represents the member name. Subsequent elements represent
each of the member's parameters.
@return Success or failure code. We return E_NOTIMPL.
}
begin
Result := E_NOTIMPL;
end;
function TSimpleDispatch.GetTypeInfo(Index, LocaleID: Integer;
out TypeInfo): HResult;
{Retrieves a type information object, which can be used to get the type
information for an interface.
@param Index [in] Index of type information to return. Pass 0 to retrieve
type information for the IDispatch implementation.
@param LocaleID [in] The locale ID for the type information.
@param TypeInfo [out] Set to ITypeInfo interface of type information
requested. We set to nil.
@return Success or failure code. We return E_NOTIMPL.
}
begin
Pointer(TypeInfo) := nil;
Result := E_NOTIMPL;
end;
function TSimpleDispatch.GetTypeInfoCount(out Count: Integer): HResult;
{Retrieves the number of type information interfaces that an object provides
(either 0 or 1).
@param Count [out] Receives the number of type information interfaces that
the object provides. If the object provides type information, this number
is 1; otherwise the number is 0. We set to 0.
@return Success of failure code. We return E_NOTIMPL.
}
begin
Count := 0;
Result := E_NOTIMPL;
end;
function TSimpleDispatch.GetValidParam(var InvokeInfo: TInvokeInfo;
const Idx: Integer; const VType: Byte; out Param: OleVariant): Boolean;
{Validates and retrieves value of a parameter of required type. Updates
InvokeInfo if parameter invalid.
@param InvokeInfo [in/out] Information about method invocation. Structure is
updated with information about any error.
@param Idx [in] Index of parameter (parameters stored in reverse order).
@param VType [in] Required parameter type.
@param Param [out] Receives value of parameter. Value is undefined if
parameter is invalid.
@return True if parameter is valid, False if not.
}
begin
if (Idx < 0) or (Idx >= InvokeInfo.Params.cArgs) then
begin
// Index is out of range: no such parameter
InvokeInfo.SCode := DISP_E_PARAMNOTFOUND;
InvokeInfo.ArgErr := Idx;
Result := False;
Exit;
end;
// Retrieve parameter as variant and check if it is required type
Param := OleVariant(InvokeInfo.Params.rgvarg^[Idx]);
Result := VarType(Param) = VType;
if not Result then
begin
// Parameter type is incorrect
InvokeInfo.SCode := DISP_E_TYPEMISMATCH;
InvokeInfo.ArgErr := Idx;
end;
end;
function TSimpleDispatch.GetValidParam(var InvokeInfo: TInvokeInfo;
const Idx: Integer; const VType: Byte; const IID: TGUID;
out Param): Boolean;
{Validates and retrieves required interface to a parameter. Updates InvokeInfo
if parameter invalid.
@param InvokeInfo [in/out] Information about method invocation. Structure is
updated with information about any error.
@param Idx [in] Index of parameter (parameters stored in reverse order).
@param VType [in] Required parameter type. Must be either varUnknown or
varDispatch.
@param IID [in] Specifies required interface supported by parameter.
@param Param [out] Reference to required interface implementation.
Undefined if parameter wrong type or interface not supported.
@return True if parameter is valid and supports the required interface,
False if VType not varUnknowm or varDispatch, parameter is not
required VType or parameter does not support the required interface.
}
var
Value: OleVariant; // parameter as variant
begin
// Get value of parameter, providing of required VType
Result := False;
if (VType = varUnknown) or (VType = varDispatch) then
begin
// VType is valid: check parameter supports required VType and get value
if GetValidParam(InvokeInfo, Idx, VType, Value) then
// Try to get required interface from parameter
Result := VarSupports(Value, IID, Param);
end;
if not Result then
begin
// Parameter type is incorrect
InvokeInfo.SCode := DISP_E_TYPEMISMATCH;
InvokeInfo.ArgErr := Idx;
end;
end;
function TSimpleDispatch.Invoke(ADispID: Integer; const AIID: TGUID;
ALocaleID: Integer; AFlags: Word; var AParams; AVarResult, AExcepInfo,
AArgErr: Pointer): HResult;
{Provides access to properties and methods exposed by an object.
@param ADispId [in] Identifies the member of the object.
@param AIID [in] Reserved. Must be IID_NULL.
@param ALocaleID [in] The locale context in which to interpret arguments.
Not used.
@param AFlags [in] Flags describing the context of the Invoke call.
@param AParams [in/out] Pointer to structure containing an array of
arguments, array of argument dispatch IDs for named arguments, and counts
for number of elements in the arrays.
@param AVarResult [in/out] Pointer to where the result is to be stored, or
NULL if the caller expects no result.
@param AExcepInfo [in/out] Pointer to a structure containing any exception
information. Not used.
@param AArgErr [in/out] Index within AParams.rgvarg[] array of the first
argument that has an error.
@return Success or failure code.
}
var
InvokeInfo: TInvokeInfo; // information about method invocation
begin
// Hand work to DoInvoke
// record invocation info
InvokeInfo.DispatchID := ADispID;
InvokeInfo.Flags := AFlags;
InvokeInfo.Params := TDispParams(AParams);
InvokeInfo.FnResult := Unassigned; // assume no function result
InvokeInfo.ArgErr := 0; // init ArgErr: ignored if no error
InvokeInfo.SCode := S_OK; // assume success
// do invocation
DoInvoke(InvokeInfo); // this may update InvokeInfo
// unpack results of invocation
Result := InvokeInfo.SCode;
if Succeeded(Result) then
begin
if Assigned(AVarResult) and not VarIsEmpty(InvokeInfo.FnResult) then
// record any function result
OleVariant(AVarResult^) := InvokeInfo.FnResult;
end
else
// set error code
Cardinal(AArgErr^) := InvokeInfo.ArgErr;
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.