📄 imp_activex.pas
字号:
////////////////////////////////////////////////////////////////////////////
// PAXScript Interpreter
// Author: Alexander Baranovsky (ab@cable.netlux.org)
// ========================================================================
// Copyright (c) Alexander Baranovsky, 2003-2005. All rights reserved.
// Code Version: 3.0
// ========================================================================
// Unit: IMP_ActiveX.pas
// ========================================================================
////////////////////////////////////////////////////////////////////////////
{$I PaxScript.def}
unit IMP_ActiveX;
interface
{$IFDEF LINUX}
implementation
end.
{$ENDIF}
uses
{$IFDEF VARIANTS}
Variants,
{$ENDIF}
Windows,
ComObj,
ActiveX,
BASE_SYS,
BASE_SCRIPTER,
BASE_CLASS,
BASE_EXTERN;
implementation
uses
SysUtils,
ComConst;
const
{ Maximum number of dispatch arguments }
MaxDispArgs = 64; {!!!}
{ Special variant type codes }
varStrArg = $0048;
{ Parameter type masks }
atVarMask = $3F;
atTypeMask = $7F;
atByRef = $80;
{ Call GetIDsOfNames method on the given IDispatch interface }
procedure GetIDsOfNames(const Dispatch: IDispatch; Names: PChar;
NameCount: Integer; DispIDs: PDispIDList);
procedure RaiseNameException;
begin
raise EOleError.CreateFmt(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 := SysUtils.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;
function HasNames(const Dispatch: IDispatch; Names: PChar;
NameCount: Integer; DispIDs: PDispIDList): Boolean;
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
result := true;
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 := SysUtils.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
result := false
else
OleCheck(Temp);
asm
MOV ESP, StackTop
end;
end;
function DispHasNames(const Instance: Variant;
CallDesc: PCallDesc): Boolean;
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
begin
result := false;
Exit;
end;
result := HasNames(IDispatch(Dispatch), @CallDesc^.ArgTypes[CallDesc^.ArgCount],
CallDesc^.NamedArgCount + 1, @DispIDs);
end;
function DispatchHasNames(ModeCall: Byte; const Instance: Variant; const Name: String;
P: Variant; ParamsCount: Integer): Boolean;
var
CallDesc: TCallDesc;
S: ShortString;
I, VCount: Integer;
VT: Byte;
begin
FillChar(CallDesc, SizeOf(TCallDesc ), 0);
S := Name;
with CallDesc do
begin
CallType := ModeCall;
NamedArgCount := 0;
ArgCount := 0;
for I := 1 to ParamsCount do
begin
VT := TVarData(P[I]).VType;
VCount := VarArrayDimCount(P[I]);
ArgTypes[ArgCount] := VT;
if VT = VarOleStr then
ArgTypes[ArgCount] := VarStrArg
else if (VT = VarVariant) or (VT = VarDispatch) or (VCount > 0) then
ArgTypes[ArgCount] := VarVariant;
Inc(ArgCount);
end;
Move(S[1], ArgTypes[ArgCount], Length(S));
end;
result := DispHasNames(Instance, @CallDesc);
end;
{ Call Invoke method on the given IDispatch interface using the given
call descriptor, dispatch IDs, parameters, and result }
procedure MyDispatchInvoke(const Dispatch: IDispatch; CallDesc: PCallDesc;
DispIDs: PDispIDList; Params: Pointer; Result: PVariant);
type
PVarArg = ^TVarArg;
TVarArg = array[0..3] of DWORD;
TStringDesc = record
BStr: PWideChar;
PStr: PString;
end;
var
I, J, K, ArgType, ArgCount, StrCount, DispID, InvKind, Status: Integer;
VarFlag: Byte;
ParamPtr: ^Integer;
ArgPtr, VarPtr: PVarArg;
DispParams: TDispParams;
ExcepInfo: TExcepInfo;
Strings: array[0..MaxDispArgs - 1] of TStringDesc;
Args: array[0..MaxDispArgs - 1] of TVarArg;
begin
StrCount := 0;
try
ArgCount := CallDesc^.ArgCount;
if ArgCount <> 0 then
begin
ParamPtr := Params;
ArgPtr := @Args[ArgCount];
I := 0;
repeat
Dec(Integer(ArgPtr), SizeOf(TVarData));
ArgType := CallDesc^.ArgTypes[I]; { and atTypeMask; }
VarFlag := 0; { CallDesc^.ArgTypes[I] and atByRef; }
if ArgType = varError then
begin
ArgPtr^[0] := varError;
// ArgPtr^[2] := DISP_E_PARAMNOTFOUND;
end else
begin
if ArgType = varStrArg then
begin
with Strings[StrCount] do
if VarFlag <> 0 then
begin
BStr := StringToOleStr(PString(ParamPtr^)^);
PStr := PString(ParamPtr^);
ArgPtr^[0] := varOleStr or varByRef;
ArgPtr^[2] := Integer(@BStr);
end else
begin
BStr := StringToOleStr(PString(ParamPtr)^);
PStr := nil;
ArgPtr^[0] := varOleStr;
ArgPtr^[2] := Integer(BStr);
end;
Inc(StrCount);
end else
if VarFlag <> 0 then
begin
if (ArgType = varVariant) and
(PVarData(ParamPtr^)^.VType = varString) then
VarCast(PVariant(ParamPtr^)^, PVariant(ParamPtr^)^, varOleStr);
ArgPtr^[0] := ArgType or varByRef;
ArgPtr^[2] := ParamPtr^;
end else
if ArgType = varVariant then
begin
if PVarData(ParamPtr)^.VType = varString then
begin
with Strings[StrCount] do
begin
BStr := StringToOleStr(string(PVarData(ParamPtr^)^.VString));
PStr := nil;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -