comobj.pp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2006 by Florian Klaempfl
  4. member of the Free Pascal development team.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$H+}
  13. {$inline on}
  14. unit comobj;
  15. interface
  16. uses
  17. Windows,Types,Variants,Sysutils,ActiveX;
  18. type
  19. EOleError = class(Exception);
  20. EOleSysError = class(EOleError)
  21. private
  22. FErrorCode: HRESULT;
  23. public
  24. constructor Create(const Msg: string; aErrorCode: HRESULT;aHelpContext: Integer);
  25. property ErrorCode: HRESULT read FErrorCode write FErrorCode;
  26. end;
  27. EOleException = class(EOleSysError)
  28. private
  29. FHelpFile: string;
  30. FSource: string;
  31. public
  32. constructor Create(const Msg: string; aErrorCode: HRESULT;const aSource,aHelpFile: string;aHelpContext: Integer);
  33. property HelpFile: string read FHelpFile write FHelpFile;
  34. property Source: string read FSource write FSource;
  35. end;
  36. EOleRegistrationError = class(EOleError);
  37. TComServerObject = class(TObject)
  38. protected
  39. function CountObject(Created: Boolean): Integer; virtual; abstract;
  40. function CountFactory(Created: Boolean): Integer; virtual; abstract;
  41. function GetHelpFileName: string; virtual; abstract;
  42. function GetServerFileName: string; virtual; abstract;
  43. function GetServerKey: string; virtual; abstract;
  44. function GetServerName: string; virtual; abstract;
  45. function GetStartSuspended: Boolean; virtual; abstract;
  46. function GetTypeLib: ITypeLib; virtual; abstract;
  47. procedure SetHelpFileName(const Value: string); virtual; abstract;
  48. public
  49. property HelpFileName: string read GetHelpFileName write SetHelpFileName;
  50. property ServerFileName: string read GetServerFileName;
  51. property ServerKey: string read GetServerKey;
  52. property ServerName: string read GetServerName;
  53. property TypeLib: ITypeLib read GetTypeLib;
  54. property StartSuspended: Boolean read GetStartSuspended;
  55. end;
  56. {
  57. TComObject = class(TObject, IUnknown, ISupportErrorInfo)
  58. protected
  59. { IUnknown }
  60. function IUnknown.QueryInterface = ObjQueryInterface;
  61. function IUnknown._AddRef = ObjAddRef;
  62. function IUnknown._Release = ObjRelease;
  63. { IUnknown methods for other interfaces }
  64. function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  65. function _AddRef: Integer; stdcall;
  66. function _Release: Integer; stdcall;
  67. { ISupportErrorInfo }
  68. function InterfaceSupportsErrorInfo(const iid: TIID): HResult; stdcall;
  69. public
  70. constructor Create;
  71. constructor CreateAggregated(const Controller: IUnknown);
  72. constructor CreateFromFactory(Factory: TComObjectFactory; const Controller: IUnknown);
  73. destructor Destroy; override;
  74. procedure Initialize; virtual;
  75. function ObjAddRef: Integer; virtual; stdcall;
  76. function ObjQueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
  77. function ObjRelease: Integer; virtual; stdcall;
  78. function SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HResult; override;
  79. property Controller: IUnknown;
  80. property Factory: TComObjectFactory;
  81. property RefCount: Integer;
  82. property ServerExceptionHandler: IServerExceptionHandler;
  83. end;
  84. }
  85. function CreateClassID : ansistring;
  86. function CreateComObject(const ClassID: TGUID) : IUnknown;
  87. function CreateRemoteComObject(const MachineName : WideString;const ClassID : TGUID) : IUnknown;
  88. function CreateOleObject(const ClassName : string) : IDispatch;
  89. function GetActiveOleObject(const ClassName: string) : IDispatch;
  90. procedure OleCheck(Value : HResult);inline;
  91. procedure OleError(Code: HResult);
  92. function ProgIDToClassID(const id : string) : TGUID;
  93. procedure DispatchInvoke(const Dispatch: IDispatch; CallDesc: PCallDesc;
  94. DispIDs: PDispIDList; Params: Pointer; Result: PVariant);
  95. procedure DispatchInvokeError(Status: HRESULT; const ExceptInfo: TExcepInfo);
  96. type
  97. TCoCreateInstanceExProc = function(const clsid: TCLSID; unkOuter: IUnknown; dwClsCtx: DWORD; ServerInfo: PCoServerInfo;
  98. dwCount: ULONG; rgmqResults: PMultiQIArray): HResult stdcall;
  99. TCoInitializeExProc = function (pvReserved: Pointer;
  100. coInit: DWORD): HResult; stdcall;
  101. TCoAddRefServerProcessProc = function : ULONG; stdcall;
  102. TCoReleaseServerProcessProc = function : ULONG; stdcall;
  103. TCoResumeClassObjectsProc = function : HResult; stdcall;
  104. TCoSuspendClassObjectsProc = function : HResult; stdcall;
  105. const
  106. CoCreateInstanceEx : TCoCreateInstanceExProc = nil;
  107. CoInitializeEx : TCoInitializeExProc = nil;
  108. CoAddRefServerProcess : TCoAddRefServerProcessProc = nil;
  109. CoReleaseServerProcess : TCoReleaseServerProcessProc = nil;
  110. CoResumeClassObjects : TCoResumeClassObjectsProc = nil;
  111. CoSuspendClassObjects : TCoSuspendClassObjectsProc = nil;
  112. implementation
  113. uses
  114. ComConst,Ole2;
  115. constructor EOleSysError.Create(const Msg: string; aErrorCode: HRESULT; aHelpContext: Integer);
  116. var
  117. m : string;
  118. begin
  119. if Msg='' then
  120. m:=SysErrorMessage(aErrorCode)
  121. else
  122. m:=Msg;
  123. inherited CreateHelp(m,HelpContext);
  124. FErrorCode:=aErrorCode;
  125. end;
  126. constructor EOleException.Create(const Msg: string; aErrorCode: HRESULT;const aSource,aHelpFile: string; aHelpContext: Integer);
  127. begin
  128. inherited Create(Msg,aErrorCode,aHelpContext);
  129. FHelpFile:=aHelpFile;
  130. FSource:=aSource;
  131. end;
  132. {$define FPC_COMOBJ_HAS_CREATE_CLASS_ID}
  133. function CreateClassID : ansistring;
  134. var
  135. ClassID : TCLSID;
  136. p : PWideChar;
  137. begin
  138. CoCreateGuid(ClassID);
  139. StringFromCLSID(ClassID,p);
  140. result:=p;
  141. CoTaskMemFree(p);
  142. end;
  143. function CreateComObject(const ClassID : TGUID) : IUnknown;
  144. begin
  145. OleCheck(CoCreateInstance(ClassID,nil,CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER,IUnknown,result));
  146. end;
  147. function CreateRemoteComObject(const MachineName : WideString;const ClassID : TGUID) : IUnknown;
  148. var
  149. flags : DWORD;
  150. localhost : array[0..MAX_COMPUTERNAME_LENGTH] of WideChar;
  151. server : TCoServerInfo;
  152. mqi : TMultiQI;
  153. size : DWORD;
  154. begin
  155. if not(assigned(CoCreateInstanceEx)) then
  156. raise Exception.CreateRes(@SDCOMNotInstalled);
  157. FillChar(server,sizeof(server),0);
  158. server.pwszName:=PWideChar(MachineName);
  159. FillChar(mqi,sizeof(mqi),0);
  160. mqi.iid:=@IID_IUnknown;
  161. flags:=CLSCTX_LOCAL_SERVER or CLSCTX_REMOTE_SERVER or CLSCTX_INPROC_SERVER;
  162. { actually a remote call? }
  163. size:=sizeof(localhost);
  164. if (MachineName<>'') and
  165. (not(GetComputerNameW(localhost,size)) or
  166. (WideCompareText(localhost,MachineName)<>0)) then
  167. flags:=CLSCTX_REMOTE_SERVER;
  168. OleCheck(CoCreateInstanceEx(ClassID,nil,flags,@server,1,@mqi));
  169. OleCheck(mqi.hr);
  170. Result:=mqi.itf;
  171. end;
  172. function CreateOleObject(const ClassName : string) : IDispatch;
  173. var
  174. id : TCLSID;
  175. begin
  176. id:=ProgIDToClassID(ClassName);
  177. OleCheck(CoCreateInstance(id,nil,CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER,IDispatch,result));
  178. end;
  179. function GetActiveOleObject(const ClassName : string) : IDispatch;
  180. var
  181. intf : IUnknown;
  182. id : TCLSID;
  183. begin
  184. id:=ProgIDToClassID(ClassName);
  185. OleCheck(GetActiveObject(id,nil,intf));
  186. OleCheck(intf.QueryInterface(IDispatch,Result));
  187. end;
  188. procedure OleError(Code: HResult);
  189. begin
  190. raise EOleSysError.Create('',Code,0);
  191. end;
  192. procedure OleCheck(Value : HResult);inline;
  193. begin
  194. if not(Succeeded(Value)) then
  195. OleError(Value);
  196. end;
  197. function ProgIDToClassID(const id : string) : TGUID;
  198. begin
  199. OleCheck(CLSIDFromProgID(PWideChar(WideString(id)),result));
  200. end;
  201. procedure SafeCallErrorHandler(err : HResult;addr : pointer);
  202. var
  203. info : IErrorInfo;
  204. descr,src,helpfile : widestring;
  205. helpctx : DWORD;
  206. begin
  207. if GetErrorInfo(0,info)=S_OK then
  208. begin
  209. info.GetDescription(descr);
  210. info.GetSource(src);
  211. info.GetHelpFile(helpfile);
  212. info.GetHelpContext(helpctx);
  213. raise EOleException.Create(descr,err,src,helpfile,helpctx) at addr;
  214. end
  215. else
  216. raise EOleException.Create('',err,'','',0) at addr;
  217. end;
  218. procedure DispatchInvokeError(Status: HRESULT; const ExceptInfo: TExcepInfo);
  219. begin
  220. if Status=DISP_E_EXCEPTION then
  221. raise EOleException.Create(ExceptInfo.Description,ExceptInfo.scode,ExceptInfo.Source,
  222. ExceptInfo.HelpFile,ExceptInfo.dwHelpContext)
  223. else
  224. raise EOleSysError.Create('',Status,0);
  225. end;
  226. { $define DEBUG_COMDISPATCH}
  227. procedure DispatchInvoke(const Dispatch: IDispatch; CallDesc: PCallDesc;
  228. DispIDs: PDispIDList; Params: Pointer; Result: PVariant);
  229. var
  230. { we can't pass pascal ansistrings to COM routines so we've to convert them
  231. to/from widestring. This array contains the mapping to do so
  232. }
  233. StringMap : array[0..255] of record passtr : pansistring; comstr : pwidechar; end;
  234. invokekind,
  235. i : longint;
  236. invokeresult : HResult;
  237. exceptioninfo : TExcepInfo;
  238. dispparams : TDispParams;
  239. NextString : SizeInt;
  240. Arguments : array[0..255] of TVarData;
  241. CurrType : byte;
  242. MethodID : TDispID;
  243. begin
  244. NextString:=0;
  245. fillchar(dispparams,sizeof(dispparams),0);
  246. try
  247. {$ifdef DEBUG_COMDISPATCH}
  248. writeln('DispatchInvoke: Got ',CallDesc^.ArgCount,' arguments NamedArgs = ',CallDesc^.NamedArgCount);
  249. {$endif DEBUG_COMDISPATCH}
  250. { copy and prepare arguments }
  251. for i:=0 to CallDesc^.ArgCount-1 do
  252. begin
  253. {$ifdef DEBUG_COMDISPATCH}
  254. writeln('DispatchInvoke: Params = ',hexstr(PtrInt(Params),SizeOf(Pointer)*2));
  255. {$endif DEBUG_COMDISPATCH}
  256. { get plain type }
  257. CurrType:=CallDesc^.ArgTypes[i] and $3f;
  258. { by reference? }
  259. if (CallDesc^.ArgTypes[i] and $80)<>0 then
  260. begin
  261. case CurrType of
  262. varStrArg:
  263. begin
  264. {$ifdef DEBUG_COMDISPATCH}
  265. writeln('Translating var ansistring argument ',PString(Params^)^);
  266. {$endif DEBUG_COMDISPATCH}
  267. StringMap[NextString].ComStr:=StringToOleStr(PString(Params^)^);
  268. StringMap[NextString].PasStr:=PString(Params^);
  269. Arguments[i].VType:=varOleStr or varByRef;
  270. Arguments[i].VPointer:=StringMap[NextString].ComStr;
  271. inc(NextString);
  272. inc(PPointer(Params));
  273. end;
  274. varVariant:
  275. {$ifdef DEBUG_COMDISPATCH}
  276. writeln('Unimplemented ref variant dispatch');
  277. {$endif DEBUG_COMDISPATCH}
  278. else
  279. begin
  280. {$ifdef DEBUG_COMDISPATCH}
  281. write('DispatchInvoke: Got ref argument with type = ',CurrType);
  282. case CurrType of
  283. varOleStr:
  284. write(' Value = ',pwidestring(PPointer(Params)^)^);
  285. end;
  286. writeln;
  287. {$endif DEBUG_COMDISPATCH}
  288. Arguments[i].VType:=CurrType or VarByRef;
  289. Arguments[i].VPointer:=PPointer(Params)^;
  290. inc(PPointer(Params));
  291. end;
  292. end
  293. end
  294. else
  295. case CurrType of
  296. varStrArg:
  297. begin
  298. {$ifdef DEBUG_COMDISPATCH}
  299. writeln('Translating ansistring argument ',PString(Params)^);
  300. {$endif DEBUG_COMDISPATCH}
  301. StringMap[NextString].ComStr:=StringToOleStr(PString(Params)^);
  302. StringMap[NextString].PasStr:=nil;
  303. Arguments[i].VType:=varOleStr;
  304. Arguments[i].VPointer:=StringMap[NextString].ComStr;
  305. inc(NextString);
  306. inc(PPointer(Params));
  307. end;
  308. varVariant:
  309. begin
  310. {$ifdef DEBUG_COMDISPATCH}
  311. writeln('Unimplemented variant dispatch');
  312. {$endif DEBUG_COMDISPATCH}
  313. end;
  314. varCurrency,
  315. varDouble,
  316. VarDate:
  317. begin
  318. {$ifdef DEBUG_COMDISPATCH}
  319. writeln('Got 8 byte float argument');
  320. {$endif DEBUG_COMDISPATCH}
  321. Arguments[i].VType:=CurrType;
  322. move(PPointer(Params)^,Arguments[i].VDouble,sizeof(Double));
  323. inc(PDouble(Params));
  324. end;
  325. else
  326. begin
  327. {$ifdef DEBUG_COMDISPATCH}
  328. write('DispatchInvoke: Got argument with type ',CurrType);
  329. case CurrType of
  330. varOleStr:
  331. write(' Value = ',pwidestring(Params)^);
  332. else
  333. write(' Value = ',hexstr(PtrInt(PPointer(Params)^),SizeOf(Pointer)*2));
  334. end;
  335. writeln;
  336. {$endif DEBUG_COMDISPATCH}
  337. Arguments[i].VType:=CurrType;
  338. Arguments[i].VPointer:=PPointer(Params)^;
  339. inc(PPointer(Params));
  340. end;
  341. end;
  342. end;
  343. { finally prepare the call }
  344. with DispParams do
  345. begin
  346. rgvarg:=@Arguments;
  347. cNamedArgs:=CallDesc^.NamedArgCount;
  348. if cNamedArgs=0 then
  349. rgdispidNamedArgs:=nil
  350. else
  351. rgdispidNamedArgs:=@DispIDs^[1];
  352. cArgs:=CallDesc^.ArgCount;
  353. end;
  354. InvokeKind:=CallDesc^.CallType;
  355. MethodID:=DispIDs^[0];
  356. {$ifdef DEBUG_COMDISPATCH}
  357. writeln('DispatchInvoke: MethodID: ',MethodID,' InvokeKind: ',InvokeKind);
  358. {$endif DEBUG_COMDISPATCH}
  359. { do the call and check the result }
  360. invokeresult:=Dispatch.Invoke(MethodID,GUID_NULL,0,InvokeKind,DispParams,result,@exceptioninfo,nil);
  361. if invokeresult<>0 then
  362. DispatchInvokeError(invokeresult,exceptioninfo);
  363. { translate strings back }
  364. for i:=0 to NextString-1 do
  365. if assigned(StringMap[i].passtr) then
  366. OleStrToStrVar(StringMap[i].comstr,StringMap[i].passtr^);
  367. finally
  368. for i:=0 to NextString-1 do
  369. SysFreeString(StringMap[i].ComStr);
  370. end;
  371. end;
  372. procedure SearchIDs(const DispatchInterface : IDispatch; Names: PChar;
  373. Count: Integer; IDs: PDispIDList);
  374. var
  375. res : HRESULT;
  376. NamesArray : ^PWideChar;
  377. NamesData : PWideChar;
  378. OrigNames : PChar;
  379. NameCount,
  380. NameLen,
  381. NewNameLen,
  382. CurrentNameDataUsed,
  383. CurrentNameDataSize : SizeInt;
  384. i : longint;
  385. begin
  386. getmem(NamesArray,Count*sizeof(PWideChar));
  387. CurrentNameDataSize:=256;
  388. CurrentNameDataUsed:=0;
  389. getmem(NamesData,CurrentNameDataSize);
  390. NameCount:=0;
  391. OrigNames:=Names;
  392. {$ifdef DEBUG_COMDISPATCH}
  393. writeln('SearchIDs: Searching ',Count,' IDs');
  394. {$endif DEBUG_COMDISPATCH}
  395. for i:=1 to Count do
  396. begin
  397. NameLen:=strlen(Names);
  398. {$ifdef DEBUG_COMDISPATCH}
  399. writeln('SearchIDs: Original name: ',Names,' Len: ',NameLen);
  400. {$endif DEBUG_COMDISPATCH}
  401. NewNameLen:=MultiByteToWideChar(0,0,Names,NameLen,nil,0)+1;
  402. if (CurrentNameDataUsed+NewNameLen)*2>CurrentNameDataSize then
  403. begin
  404. inc(CurrentNameDataSize,256);
  405. reallocmem(NamesData,CurrentNameDataSize);
  406. end;
  407. NamesArray[i-1]:=@NamesData[CurrentNameDataUsed];
  408. MultiByteToWideChar(0,0,Names,NameLen,@NamesData[CurrentNameDataUsed],NewNameLen);
  409. NamesData[CurrentNameDataUsed+NewNameLen-1]:=#0;
  410. {$ifdef DEBUG_COMDISPATCH}
  411. writeln('SearchIDs: Translated name: ',WideString(PWideChar(@NamesData[CurrentNameDataUsed])));
  412. {$endif DEBUG_COMDISPATCH}
  413. inc(CurrentNameDataUsed,NewNameLen);
  414. inc(Names,NameLen+1);
  415. inc(NameCount);
  416. end;
  417. res:=DispatchInterface.GetIDsOfNames(GUID_NULL,NamesArray,NameCount,GetThreadLocale,IDs);
  418. {$ifdef DEBUG_COMDISPATCH}
  419. writeln('SearchIDs: GetIDsOfNames result = ',hexstr(res,SizeOf(HRESULT)*2));
  420. for i:=0 to Count-1 do
  421. writeln('SearchIDs: ID[',i,'] = ',ids^[i]);
  422. {$endif DEBUG_COMDISPATCH}
  423. if res=DISP_E_UNKNOWNNAME then
  424. raise EOleError.createresfmt(@snomethod,[OrigNames])
  425. else
  426. OleCheck(res);
  427. freemem(NamesArray);
  428. freemem(NamesData);
  429. end;
  430. procedure ComObjDispatchInvoke(dest : PVariant;const source : Variant;
  431. calldesc : pcalldesc;params : pointer);cdecl;
  432. var
  433. dispatchinterface : pointer;
  434. ids : array[0..255] of TDispID;
  435. begin
  436. fillchar(ids,sizeof(ids),0);
  437. {$ifdef DEBUG_COMDISPATCH}
  438. writeln('ComObjDispatchInvoke called');
  439. writeln('ComObjDispatchInvoke: @CallDesc = $',hexstr(PtrInt(CallDesc),SizeOf(Pointer)*2),' CallDesc^.ArgCount = ',CallDesc^.ArgCount);
  440. {$endif DEBUG_COMDISPATCH}
  441. if tvardata(source).vtype=VarDispatch then
  442. dispatchinterface:=tvardata(source).vdispatch
  443. else if tvardata(source).vtype=(VarDispatch or VarByRef) then
  444. dispatchinterface:=pvardata(tvardata(source).vpointer)^.vdispatch
  445. else
  446. raise eoleerror.createres(@SVarNotObject);
  447. SearchIDs(IDispatch(dispatchinterface),@CallDesc^.ArgTypes[CallDesc^.ArgCount],
  448. CallDesc^.NamedArgCount+1,@ids);
  449. if assigned(dest) then
  450. VarClear(dest^);
  451. DispatchInvoke(IDispatch(dispatchinterface),calldesc,@ids,params,dest);
  452. end;
  453. { $define DEBUG_DISPATCH}
  454. procedure DoDispCallByID(res : Pointer; const disp : IDispatch;desc : PDispDesc; params : Pointer);
  455. var
  456. exceptioninfo : TExcepInfo;
  457. dispparams : TDispParams;
  458. flags : WORD;
  459. invokeresult : HRESULT;
  460. preallocateddata : array[0..15] of TVarData;
  461. Arguments : ^TVarData;
  462. NamedArguments : PPointer;
  463. CurrType : byte;
  464. namedcount,i : byte;
  465. begin
  466. { use preallocated space, i.e. can we avoid a getmem call? }
  467. if desc^.calldesc.argcount<=Length(preallocateddata) then
  468. Arguments:=@preallocateddata
  469. else
  470. GetMem(Arguments,desc^.calldesc.argcount*sizeof(TVarData));
  471. { prepare parameters }
  472. for i:=0 to desc^.CallDesc.ArgCount-1 do
  473. begin
  474. {$ifdef DEBUG_DISPATCH}
  475. writeln('DoDispCallByID: Params = ',hexstr(PtrInt(Params),SizeOf(Pointer)*2));
  476. {$endif DEBUG_DISPATCH}
  477. { get plain type }
  478. CurrType:=desc^.CallDesc.ArgTypes[i] and $3f;
  479. { by reference? }
  480. if (desc^.CallDesc.ArgTypes[i] and $80)<>0 then
  481. begin
  482. {$ifdef DEBUG_DISPATCH}
  483. write('DispatchInvoke: Got ref argument with type = ',CurrType);
  484. writeln;
  485. {$endif DEBUG_DISPATCH}
  486. Arguments[i].VType:=CurrType or VarByRef;
  487. Arguments[i].VPointer:=PPointer(Params)^;
  488. inc(PPointer(Params));
  489. end
  490. else
  491. begin
  492. {$ifdef DEBUG_DISPATCH}
  493. writeln('DispatchInvoke: Got ref argument with type = ',CurrType);
  494. {$endif DEBUG_DISPATCH}
  495. case CurrType of
  496. varVariant:
  497. begin
  498. Arguments[i].VType:=CurrType;
  499. move(PVarData(Params)^,Arguments[i],sizeof(TVarData));
  500. inc(PVarData(Params));
  501. end;
  502. varCurrency,
  503. varDouble,
  504. VarDate:
  505. begin
  506. {$ifdef DEBUG_DISPATCH}
  507. writeln('DispatchInvoke: Got 8 byte float argument');
  508. {$endif DEBUG_DISPATCH}
  509. Arguments[i].VType:=CurrType;
  510. move(PPointer(Params)^,Arguments[i].VDouble,sizeof(Double));
  511. inc(PDouble(Params));
  512. end;
  513. else
  514. begin
  515. {$ifdef DEBUG_DISPATCH}
  516. writeln('DispatchInvoke: Got argument with type ',CurrType);
  517. {$endif DEBUG_DISPATCH}
  518. Arguments[i].VType:=CurrType;
  519. Arguments[i].VPointer:=PPointer(Params)^;
  520. inc(PPointer(Params));
  521. end;
  522. end;
  523. end;
  524. end;
  525. dispparams.cArgs:=desc^.calldesc.argcount;
  526. dispparams.rgvarg:=pointer(Arguments);
  527. { handle properties properly here ! }
  528. namedcount:=desc^.calldesc.namedargcount;
  529. if desc^.calldesc.calltype=DISPATCH_PROPERTYPUT then
  530. inc(namedcount)
  531. else
  532. NamedArguments:=@desc^.CallDesc.ArgTypes[desc^.CallDesc.ArgCount];
  533. dispparams.cNamedArgs:=namedcount;
  534. dispparams.rgdispidNamedArgs:=pointer(NamedArguments);
  535. flags:=0;
  536. invokeresult:=disp.Invoke(
  537. desc^.DispId, { DispID: LongInt; }
  538. GUID_NULL, { const iid : TGUID; }
  539. 0, { LocaleID : longint; }
  540. flags, { Flags: Word; }
  541. dispparams, { var params; }
  542. res,@exceptioninfo,nil { VarResult,ExcepInfo,ArgErr : pointer) }
  543. );
  544. if invokeresult<>0 then
  545. DispatchInvokeError(invokeresult,exceptioninfo);
  546. if desc^.calldesc.argcount>Length(preallocateddata) then
  547. FreeMem(Arguments);
  548. end;
  549. const
  550. Initialized : boolean = false;
  551. var
  552. Ole32Dll : HModule;
  553. initialization
  554. Ole32Dll:=GetModuleHandle('ole32.dll');
  555. if Ole32Dll<>0 then
  556. begin
  557. Pointer(CoCreateInstanceEx):=GetProcAddress(Ole32Dll,'CoCreateInstanceExProc');
  558. Pointer(CoInitializeEx):=GetProcAddress(Ole32Dll,'CoInitializeExProc');
  559. Pointer(CoAddRefServerProcess):=GetProcAddress(Ole32Dll,'CoAddRefServerProcessProc');
  560. Pointer(CoReleaseServerProcess):=GetProcAddress(Ole32Dll,'CoReleaseServerProcessProc');
  561. Pointer(CoResumeClassObjects):=GetProcAddress(Ole32Dll,'CoResumeClassObjectsProc');
  562. Pointer(CoSuspendClassObjects):=GetProcAddress(Ole32Dll,'CoSuspendClassObjectsProc');
  563. end;
  564. if not(IsLibrary) then
  565. Initialized:=Succeeded(CoInitialize(nil));
  566. SafeCallErrorProc:=@SafeCallErrorHandler;
  567. VarDispProc:=@ComObjDispatchInvoke;
  568. DispCallByIDProc:=@DoDispCallByID;
  569. finalization
  570. VarDispProc:=nil;
  571. SafeCallErrorProc:=nil;
  572. if Initialized then
  573. CoUninitialize;
  574. end.