{ Call GetIDsOfNames method on the given IDispatch interface }
procedure GetIDsOfNames(
const Dispatch: IDispatch; Names: PChar;
NameCount: Integer; DispIDs: PDispIDList);
procedure RaiseNameException;
begin
raise EOleError.CreateResFmt(@SNoMethod, [Names]);
end;
type
PNamesArray = ^TNamesArray;
TNamesArray =
array[0..0]
of PWideChar;
var
N, SrcLen, DestLen: Integer;
Src: PChar;
Dest: PWideChar;
NameRefs: PNamesArray;
StackTop: Pointer;
Temp: Integer;
begin
Src := Names;
N := 0;
asm
MOV StackTop, ESP
MOV EAX, NameCount
INC EAX
SHL EAX, 2
// sizeof pointer = 4
SUB ESP, EAX
LEA EAX, NameRefs
MOV [EAX], ESP
end;
repeat
SrcLen := StrLen(Src);
DestLen := MultiByteToWideChar(0, 0, Src, SrcLen,
nil, 0) + 1;
asm
MOV EAX, DestLen
ADD EAX, EAX
ADD EAX, 3
// round up to 4 byte boundary
AND EAX,
not 3
SUB ESP, EAX
LEA EAX, Dest
MOV [EAX], ESP
end;
if N = 0
then NameRefs[0] := Dest
else NameRefs[NameCount - N] := Dest;
MultiByteToWideChar(0, 0, Src, SrcLen, Dest, DestLen);
Dest[DestLen-1] := #0;
Inc(Src, SrcLen+1);
Inc(N);
until N = NameCount;
Temp := Dispatch.GetIDsOfNames(GUID_NULL, NameRefs, NameCount,
GetThreadLocale, DispIDs);
if Temp = Integer(DISP_E_UNKNOWNNAME)
then RaiseNameException
else OleCheck(Temp);
asm
MOV ESP, StackTop
end;
end;
{ Central call dispatcher }
procedure VarDispInvoke(Result: PVariant;
const Instance: Variant;
CallDesc: PCallDesc; Params: Pointer);
cdecl;
procedure RaiseException;
begin
raise EOleError.CreateRes(@SVarNotObject);
end;
var
Dispatch: Pointer;
DispIDs:
array[0..MaxDispArgs - 1]
of Integer;
begin
if TVarData(Instance).VType = varDispatch
then
Dispatch := TVarData(Instance).VDispatch
else if TVarData(Instance).VType = (varDispatch
or varByRef)
then
Dispatch := Pointer(TVarData(Instance).VPointer^)
else RaiseException;
GetIDsOfNames(IDispatch(Dispatch), @CallDesc^.ArgTypes[CallDesc^.ArgCount],
CallDesc^.NamedArgCount + 1, @DispIDs);
if Result <>
nil then VarClear(Result^);
DispatchInvoke(IDispatch(Dispatch), CallDesc, @DispIDs, @Params, Result);
end;