CnActiveScript.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. {******************************************************************************}
  2. { CnPack For Delphi/C++Builder }
  3. { 中国人自己的开放源码第三方开发包 }
  4. { (C)Copyright 2001-2018 CnPack 开发组 }
  5. { ------------------------------------ }
  6. { }
  7. { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
  8. { 改和重新发布这一程序。 }
  9. { }
  10. { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
  11. { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
  12. { }
  13. { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
  14. { 还没有,可访问我们的网站: }
  15. { }
  16. { 网站地址:http://www.cnpack.org }
  17. { 电子邮件:master@cnpack.org }
  18. { }
  19. {******************************************************************************}
  20. unit CnActiveScript;
  21. {* |<PRE>
  22. ================================================================================
  23. * 软件名称:不可视工具组件包
  24. * 单元名称:ActiveScript 脚本引擎封装组件单元
  25. * 单元作者:周劲羽 (zjy@cnpack.org)
  26. * 备 注:
  27. * 开发平台:PWin2K SP3 + Delphi 7
  28. * 兼容测试:PWin9X/2000/XP + Delphi 5/6/7 C++Builder 5/6
  29. * 本 地 化:该单元中的字符串均符合本地化处理方式
  30. * 单元标识:$Id$
  31. * 修改记录:2003.07.10
  32. * 创建单元
  33. ================================================================================
  34. |</PRE>}
  35. interface
  36. {$I CnPack.inc}
  37. uses
  38. Windows, Sysutils, ActiveX, ComObj, Contnrs, Classes,
  39. {$IFDEF COMPILER6_UP}
  40. Variants,
  41. {$ENDIF COMPILER6_UP}
  42. Forms,
  43. CnConsts, CnClasses, CnCompConsts;
  44. const
  45. SCATID_ActiveScript = '{F0B7A1A1-9847-11cf-8F20-00805F2CD064}';
  46. SCATID_ActiveScriptParse = '{F0B7A1A2-9847-11cf-8F20-00805F2CD064}';
  47. SID_IActiveScript = '{BB1A2AE1-A4F9-11cf-8F20-00805F2CD064}';
  48. SID_IActiveScriptParse = '{BB1A2AE2-A4F9-11cf-8F20-00805F2CD064}';
  49. SID_IActiveScriptParseProcedureOld ='{1CFF0050-6FDD-11d0-9328-00A0C90DCAA9}';
  50. SID_IActiveScriptParseProcedure = '{AA5B6A80-B834-11d0-932F-00A0C90DCAA9}';
  51. SID_IActiveScriptSite = '{DB01A1E3-A42B-11cf-8F20-00805F2CD064}';
  52. SID_IActiveScriptSiteWindow = '{D10F6761-83E9-11cf-8F20-00805F2CD064}';
  53. SID_IActiveScriptSiteInterruptPoll ='{539698A0-CDCA-11CF-A5EB-00AA0047A063}';
  54. SID_IActiveScriptError = '{EAE1BA61-A4ED-11cf-8F20-00805F2CD064}';
  55. SID_IBindEventHandler = '{63CDBCB0-C1B1-11d0-9336-00A0C90DCAA9}';
  56. SID_IActiveScriptStats = '{B8DA6310-E19B-11d0-933C-00A0C90DCAA9}';
  57. CATID_ActiveScript: TGUID = SCATID_ActiveScript;
  58. CATID_ActiveScriptParse: TGUID = SCATID_ActiveScriptParse;
  59. IID_IActiveScript: TGUID = SID_IActiveScript;
  60. IID_IActiveScriptParse: TGUID = SID_IActiveScriptParse;
  61. IID_IActiveScriptParseProcedureOld: TGUID = SID_IActiveScriptParseProcedureOld;
  62. IID_IActiveScriptParseProcedure: TGUID = SID_IActiveScriptParseProcedure;
  63. IID_IActiveScriptSite: TGUID = SID_IActiveScriptSite;
  64. IID_IActiveScriptSiteWindow: TGUID = SID_IActiveScriptSiteWindow;
  65. IID_IActiveScriptSiteInterruptPoll: TGUID = SID_IActiveScriptSiteInterruptPoll;
  66. IID_IActiveScriptError: TGUID = SID_IActiveScriptError;
  67. IID_IBindEventHandler: TGUID = SID_IBindEventHandler;
  68. IID_IActiveScriptStats: TGUID = SID_IActiveScriptStats;
  69. // Constants used by ActiveX Scripting:
  70. //
  71. (* IActiveScript::AddNamedItem() input flags *)
  72. SCRIPTITEM_ISVISIBLE = $00000002;
  73. SCRIPTITEM_ISSOURCE = $00000004;
  74. SCRIPTITEM_GLOBALMEMBERS = $00000008;
  75. SCRIPTITEM_ISPERSISTENT = $00000040;
  76. SCRIPTITEM_CODEONLY = $00000200;
  77. SCRIPTITEM_NOCODE = $00000400;
  78. SCRIPTITEM_ALL_FLAGS =(SCRIPTITEM_ISSOURCE or
  79. SCRIPTITEM_ISVISIBLE or
  80. SCRIPTITEM_ISPERSISTENT or
  81. SCRIPTITEM_GLOBALMEMBERS or
  82. SCRIPTITEM_NOCODE or
  83. SCRIPTITEM_CODEONLY);
  84. (* IActiveScript::AddTypeLib() input flags *)
  85. SCRIPTTYPELIB_ISCONTROL = $00000010;
  86. SCRIPTTYPELIB_ISPERSISTENT = $00000040;
  87. SCRIPTTYPELIB_ALL_FLAGS = (SCRIPTTYPELIB_ISCONTROL or
  88. SCRIPTTYPELIB_ISPERSISTENT);
  89. (* IActiveScriptParse::AddScriptlet() and
  90. IActiveScriptParse::ParseScriptText() input flags *)
  91. SCRIPTTEXT_DELAYEXECUTION = $00000001;
  92. SCRIPTTEXT_ISVISIBLE = $00000002;
  93. SCRIPTTEXT_ISEXPRESSION = $00000020;
  94. SCRIPTTEXT_ISPERSISTENT = $00000040;
  95. SCRIPTTEXT_HOSTMANAGESSOURCE = $00000080;
  96. SCRIPTTEXT_ALL_FLAGS = (SCRIPTTEXT_DELAYEXECUTION or
  97. SCRIPTTEXT_ISVISIBLE or
  98. SCRIPTTEXT_ISEXPRESSION or
  99. SCRIPTTEXT_ISPERSISTENT or
  100. SCRIPTTEXT_HOSTMANAGESSOURCE);
  101. (* IActiveScriptParseProcedure::ParseProcedureText() input flags *)
  102. SCRIPTPROC_HOSTMANAGESSOURCE = $00000080;
  103. SCRIPTPROC_IMPLICIT_THIS = $00000100;
  104. SCRIPTPROC_IMPLICIT_PARENTS = $00000200;
  105. SCRIPTPROC_ALL_FLAGS = (SCRIPTPROC_HOSTMANAGESSOURCE or
  106. SCRIPTPROC_IMPLICIT_THIS or
  107. SCRIPTPROC_IMPLICIT_PARENTS);
  108. (* IActiveScriptSite::GetItemInfo() input flags *)
  109. SCRIPTINFO_IUNKNOWN = $00000001;
  110. SCRIPTINFO_ITYPEINFO = $00000002;
  111. SCRIPTINFO_ALL_FLAGS = (SCRIPTINFO_IUNKNOWN or
  112. SCRIPTINFO_ITYPEINFO);
  113. (* IActiveScript::Interrupt() Flags *)
  114. SCRIPTINTERRUPT_DEBUG = $00000001;
  115. SCRIPTINTERRUPT_RAISEEXCEPTION = $00000002;
  116. SCRIPTINTERRUPT_ALL_FLAGS = (SCRIPTINTERRUPT_DEBUG or
  117. SCRIPTINTERRUPT_RAISEEXCEPTION);
  118. (* IActiveScriptStats::GetStat() values *)
  119. SCRIPTSTAT_STATEMENT_COUNT = 1;
  120. SCRIPTSTAT_INSTRUCTION_COUNT = 2;
  121. SCRIPTSTAT_INTSTRUCTION_TIME = 3;
  122. SCRIPTSTAT_TOTAL_TIME = 4;
  123. (* script state values *)
  124. type
  125. tagSCRIPTSTATE = integer;
  126. SCRIPTSTATE = tagSCRIPTSTATE;
  127. const
  128. SCRIPTSTATE_UNINITIALIZED = $00000000;
  129. SCRIPTSTATE_INITIALIZED = $00000005;
  130. SCRIPTSTATE_STARTED = $00000001;
  131. SCRIPTSTATE_CONNECTED = $00000002;
  132. SCRIPTSTATE_DISCONNECTED = $00000003;
  133. SCRIPTSTATE_CLOSED = $00000004;
  134. (* script thread state values *)
  135. type
  136. tagSCRIPTTHREADSTATE = integer;
  137. SCRIPTTHREADSTATE = tagSCRIPTTHREADSTATE;
  138. const
  139. SCRIPTTHREADSTATE_NOTINSCRIPT = $00000000;
  140. SCRIPTTHREADSTATE_RUNNING = $00000001;
  141. (* Thread IDs *)
  142. type
  143. SCRIPTTHREADID = DWORD;
  144. const
  145. SCRIPTTHREADID_CURRENT = SCRIPTTHREADID(-1);
  146. SCRIPTTHREADID_BASE = SCRIPTTHREADID(-2);
  147. SCRIPTTHREADID_ALL = SCRIPTTHREADID(-3);
  148. type
  149. IActiveScriptSite = interface;
  150. IActiveScriptSiteWindow = interface;
  151. IActiveScript = interface;
  152. IActiveScriptParse = interface;
  153. IActiveScriptParseProcedure = interface;
  154. IActiveScriptError = interface;
  155. LPCOLESTR = PWideChar;
  156. IActiveScriptSite = interface(IUnknown)
  157. [SID_IActiveScript]
  158. function GetLCID(out plcid: LCID): HResult; stdcall;
  159. function GetItemInfo(
  160. pstrName: LPCOLESTR;
  161. dwReturnMask: DWORD;
  162. out ppiunkItem: IUnknown;
  163. out ppti: ITypeInfo): HResult; stdcall;
  164. function GetDocVersionString(out pbstrVersion: WideString): HResult; stdcall;
  165. function OnScriptTerminate(
  166. var pvarResult: OleVariant;
  167. var pexcepinfo: EXCEPINFO): HResult; stdcall;
  168. function OnStateChange(ssScriptState: SCRIPTSTATE): HResult; stdcall;
  169. function OnScriptError(
  170. const pscripterror: IActiveScriptError): HResult; stdcall;
  171. function OnEnterScript: HResult; stdcall;
  172. function OnLeaveScript: HResult; stdcall;
  173. end;
  174. IActiveScriptError = interface(IUnknown)
  175. [SID_IActiveScriptError]
  176. function GetExceptionInfo(out pexcepinfo: EXCEPINFO): HResult; stdcall;
  177. function GetSourcePosition(
  178. out pdwSourceContext: DWORD;
  179. out pulLineNumber: ULONG;
  180. out plCharacterPosition: Integer): HResult; stdcall;
  181. function GetSourceLineText(out pbstrSourceLine: WideString): HResult; stdcall;
  182. end;
  183. IActiveScriptSiteWindow = interface(IUnknown)
  184. [SID_IActiveScriptSiteWindow]
  185. function GetWindow(out phwnd: HWND): HResult; stdcall;
  186. function EnableModeless(fEnable: BOOL): HResult; stdcall;
  187. end;
  188. IActiveScriptSiteInterruptPoll = interface(IUnknown)
  189. [SID_IActiveScriptSiteInterruptPoll]
  190. function QueryContinue: HResult; stdcall;
  191. end;
  192. IActiveScript = interface(IUnknown)
  193. [SID_IActiveScript]
  194. function SetScriptSite(const pass: IActiveScriptSite): HResult; stdcall;
  195. function GetScriptSite(
  196. const riid: TGUID;
  197. out ppvObject: Pointer): HResult; stdcall;
  198. function SetScriptState(ss: SCRIPTSTATE): HResult; stdcall;
  199. function GetScriptState(out pssState: SCRIPTSTATE): HResult; stdcall;
  200. function Close: HResult; stdcall;
  201. function AddNamedItem(
  202. pstrName: LPCOLESTR;
  203. dwFlags: DWORD): HResult; stdcall;
  204. function AddTypeLib(
  205. const rguidTypeLib: TGUID;
  206. dwMajor: DWORD;
  207. dwMinor: DWORD;
  208. dwFlags: DWORD): HResult; stdcall;
  209. function GetScriptDispatch(
  210. pstrItemName: LPCOLESTR;
  211. out ppdisp: IDispatch): HResult; stdcall;
  212. function GetCurrentScriptThreadID(
  213. out pstidThread: SCRIPTTHREADID): HResult; stdcall;
  214. function GetScriptThreadID(dwWin32ThreadId: DWORD;
  215. out pstidThread: SCRIPTTHREADID): HResult; stdcall;
  216. function GetScriptThreadState(
  217. stidThread: SCRIPTTHREADID;
  218. out pstsState: SCRIPTTHREADSTATE): HResult; stdcall;
  219. function InterruptScriptThread(
  220. stidThread: SCRIPTTHREADID;
  221. var pexcepinfo: EXCEPINFO;
  222. dwFlags: DWORD): HResult; stdcall;
  223. function Clone(out ppscript: IActiveScript): HResult; stdcall;
  224. end;
  225. IActiveScriptParse = interface(IUnknown)
  226. [SID_IActiveScriptParse]
  227. function InitNew: HResult; stdcall;
  228. function AddScriptlet(
  229. pstrDefaultName: LPCOLESTR;
  230. pstrCode: LPCOLESTR;
  231. pstrItemName: LPCOLESTR;
  232. pstrSubItemName: LPCOLESTR;
  233. pstrEventName: LPCOLESTR;
  234. pstrDelimiter: LPCOLESTR;
  235. dwSourceContextCookie: DWORD;
  236. ulStartingLineNumber: ULONG;
  237. dwFlags: DWORD;
  238. out pbstrName: WideString;
  239. out pexcepinfo: EXCEPINFO): HResult; stdcall;
  240. function ParseScriptText(
  241. pstrCode: LPCOLESTR;
  242. pstrItemName: LPCOLESTR;
  243. const punkContext: IUnknown;
  244. pstrDelimiter: LPCOLESTR;
  245. dwSourceContextCookie: DWORD;
  246. ulStartingLineNumber: ULONG;
  247. dwFlags: DWORD;
  248. out pvarResult: OleVariant;
  249. out pexcepinfo: EXCEPINFO): HResult; stdcall;
  250. end;
  251. IActiveScriptParseProcedureOld = interface(IUnknown)
  252. [SID_IActiveScriptParseProcedureOld]
  253. function ParseProcedureText(
  254. pstrCode: LPCOLESTR;
  255. pstrFormalParams: LPCOLESTR;
  256. pstrItemName: LPCOLESTR;
  257. const punkContext: IUnknown;
  258. pstrDelimiter: LPCOLESTR;
  259. dwSourceContextCookie: DWORD;
  260. ulStartingLineNumber: ULONG;
  261. dwFlags: DWORD;
  262. out ppdisp: IDispatch): HResult; stdcall;
  263. end;
  264. IActiveScriptParseProcedure = interface(IUnknown)
  265. [SID_IActiveScriptParseProcedure]
  266. function ParseProcedureText(
  267. pstrCode: LPCOLESTR;
  268. pstrFormalParams: LPCOLESTR;
  269. pstrProcedureName: LPCOLESTR;
  270. pstrItemName: LPCOLESTR;
  271. const punkContext: IUnknown;
  272. pstrDelimiter: LPCOLESTR;
  273. dwSourceContextCookie: DWORD;
  274. ulStartingLineNumber: ULONG;
  275. dwFlags: DWORD;
  276. out ppdisp: IDispatch): HResult; stdcall;
  277. end;
  278. IBindEventHandler = interface(IUnknown)
  279. [SID_IBindEventHandler]
  280. function BindHandler(
  281. pstrEvent: LPCOLESTR;
  282. const pdisp: IDispatch): HResult; stdcall;
  283. end;
  284. IActiveScriptStats = interface(IUnknown)
  285. [SID_IActiveScriptStats]
  286. function GetStat(
  287. stid: DWORD;
  288. out pluHi: ULONG;
  289. out pluLo: ULONG): HResult; stdcall;
  290. function GetStatEx(
  291. const guid: TGUID;
  292. out pluHi: ULONG;
  293. out pluLo: ULONG): HResult; stdcall;
  294. function ResetStats: HResult; stdcall;
  295. end;
  296. type
  297. TOnActiveScriptError = procedure(Sender: TObject; Line, Pos: Integer; ASrc:
  298. string; ADescription: string) of object;
  299. TCnScriptGlobalObjects = class(TObject)
  300. private
  301. FIntfList: IInterfaceList;
  302. FNamedList: TStrings;
  303. function GetNamedItemCount: Integer;
  304. function GetNamedItemName(I: Integer): string;
  305. public
  306. constructor Create;
  307. destructor Destroy; override;
  308. procedure AddNamedIntf(const AName: string; AIntf: IUnknown);
  309. procedure Clear;
  310. function FindNamedItemIntf(const AName: string): IUnknown;
  311. property NamedItemCount: Integer read GetNamedItemCount;
  312. property NamedItemName[I: Integer]: string read GetNamedItemName;
  313. end;
  314. TScriptLanguage = type string;
  315. TCnActiveScriptSite = class(TCnComponent, IActiveScriptSite)
  316. private
  317. FUseSafeSubset: Boolean;
  318. FDisp: OleVariant;
  319. FGlobalObjects: TCnScriptGlobalObjects;
  320. FOnError: TOnActiveScriptError;
  321. FEngine: IActiveScript;
  322. FParser: IActiveScriptParse;
  323. FScriptLanguage: TScriptLanguage;
  324. FCleanBeforeRun: Boolean;
  325. procedure CreateScriptEngine(language: string);
  326. procedure CloseScriptEngine;
  327. protected
  328. { IActiveScriptSite }
  329. function GetLCID(out plcid: Longword): hResult; stdcall;
  330. function GetItemInfo(
  331. pstrName: LPCOLESTR;
  332. dwReturnMask: DWORD;
  333. out ppiunkItem: IUnknown;
  334. out ppti: ITypeInfo): hResult; stdcall;
  335. function GetDocVersionString(out pbstrVersion: WideString): hResult; stdcall;
  336. function OnScriptTerminate(var pvarResult: OleVariant; var PExcepInfo:
  337. ExcepInfo): hResult; stdcall;
  338. function OnStateChange(ssScriptState: tagSCRIPTSTATE): hResult; stdcall;
  339. function OnScriptError(const pscripterror: IActiveScriptError): hResult;
  340. stdcall;
  341. function OnEnterScript: hResult; stdcall;
  342. function OnLeaveScript: hResult; stdcall;
  343. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  344. public
  345. constructor Create(AOwner: TComponent); override;
  346. destructor Destroy; override;
  347. function RunExpression(ACode: WideString): OleVariant;
  348. function Execute(ACode: WideString): OleVariant;
  349. procedure AddNamedItem(AName: string; AIntf: IUnknown);
  350. procedure Clear;
  351. property ScriptInterface: OleVariant read FDisp;
  352. published
  353. property ScriptLanguage: TScriptLanguage read FScriptLanguage write FScriptLanguage;
  354. property OnError: TOnActiveScriptError read FOnError write FOnError;
  355. property CleanBeforeRun: Boolean read FCleanBeforeRun write FCleanBeforeRun;
  356. property UseSafeSubset: Boolean read FUseSafeSubset write FUseSafeSubset default
  357. False;
  358. end;
  359. TCnActiveScriptWindow = class(TCnActiveScriptSite, IActiveScriptSiteWindow)
  360. protected
  361. {IActiveSriptSiteWindow}
  362. function GetWindow(out phwnd: HWND): hResult; stdcall;
  363. function EnableModeless(fEnable: BOOL): hResult; stdcall;
  364. procedure GetComponentInfo(var AName, Author, Email, Comment: string); override;
  365. end;
  366. procedure GetActiveScriptParse(List: TStrings);
  367. implementation
  368. const
  369. INTERFACESAFE_FOR_UNTRUSTED_CALLER = $00000001; // Caller of interface may be untrusted
  370. INTERFACESAFE_FOR_UNTRUSTED_DATA = $00000002; // Data passed into interface may be untrusted
  371. INTERFACE_USES_DISPEX = $00000004; // Object knows to use IDispatchEx
  372. INTERFACE_USES_SECURITY_MANAGER = $00000008; // Object knows to use IInternetHostSecurityManager
  373. procedure GetActiveScriptParse(List: TStrings);
  374. var
  375. ProgID: string;
  376. function ValidProgID: Boolean;
  377. var
  378. PID: string;
  379. begin
  380. if Length(ProgID) > 7 then
  381. Result := AnsiCompareStr('.Encode', Copy(ProgID, Length(ProgID) - 6, 7)) <> 0
  382. else
  383. Result := True;
  384. // Exclude XML script engine
  385. if CompareText(Copy(ProgID, 1, 3), 'XML') = 0 then
  386. Result := False;
  387. // Exclude "signed" script engines
  388. PID := UpperCase(ProgID);
  389. if Pos('SIGNED', PID) <> 0 then
  390. Result := False;
  391. end;
  392. var
  393. EnumGUID: IEnumGUID;
  394. Fetched: Cardinal;
  395. Guid: TGUID;
  396. Rslt: hResult;
  397. CatInfo: ICatInformation;
  398. I, BufSize: Integer;
  399. ClassIDKey: HKEY;
  400. S: string;
  401. Buffer: array[0..255] of Char;
  402. begin
  403. List.Clear;
  404. Rslt := CoCreateInstance(CLSID_StdComponentCategoryMgr, nil,
  405. CLSCTX_INPROC_SERVER, ICatInformation, CatInfo);
  406. if Succeeded(Rslt) then
  407. begin
  408. OleCheck(CatInfo.EnumClassesOfCategories(1, @CATID_ActiveScriptParse, 0, nil,
  409. EnumGUID));
  410. while EnumGUID.Next(1, Guid, Fetched) = S_OK do
  411. begin
  412. try
  413. ProgID := ClassIDToProgID(Guid);
  414. if ValidProgID then
  415. List.Add(ProgID);
  416. except
  417. ProgID := ClassIDToProgID(StringToGuid(Buffer));
  418. List.Add('Invalid Entry In Categories');
  419. end;
  420. end;
  421. end else
  422. begin
  423. if RegOpenKey(HKEY_CLASSES_ROOT, 'CLSID', ClassIDKey) <> 0 then
  424. try
  425. I := 0;
  426. while RegEnumKey(ClassIDKey, I, Buffer, SizeOf(Buffer)) = 0 do
  427. begin
  428. S := Format('%s\Implemented Categories\%s', [Buffer, { do not localize }
  429. GuidToString(CATID_ActiveScriptParse)]);
  430. if RegQueryValue(ClassIDKey, PChar(S), nil, BufSize) = 0 then
  431. begin
  432. ProgID := ClassIDToProgID(StringToGuid(Buffer));
  433. if ValidProgID then
  434. List.Add(ProgID);
  435. end;
  436. Inc(I);
  437. end;
  438. finally
  439. RegCloseKey(ClassIDKey);
  440. end;
  441. end;
  442. end;
  443. { TCnScriptGlobalObjects }
  444. procedure TCnScriptGlobalObjects.AddNamedIntf(const AName: string; AIntf: IUnknown);
  445. begin
  446. if FNamedList.IndexOf(AName) < 0 then
  447. begin
  448. FNamedList.Add(AName);
  449. FIntfList.Add(AIntf);
  450. end;
  451. end;
  452. procedure TCnScriptGlobalObjects.Clear;
  453. begin
  454. FNamedList.Clear;
  455. FIntfList.Clear;
  456. end;
  457. constructor TCnScriptGlobalObjects.Create;
  458. begin
  459. inherited Create;
  460. FNamedList := TStringList.Create;
  461. FIntfList := TInterfaceList.Create;
  462. end;
  463. destructor TCnScriptGlobalObjects.Destroy;
  464. begin
  465. FNamedList.Free;
  466. inherited;
  467. end;
  468. function TCnScriptGlobalObjects.FindNamedItemIntf(const AName: string): IUnknown;
  469. var
  470. I: Integer;
  471. begin
  472. I := FNamedList.IndexOf(AName);
  473. if I >= 0 then
  474. Result := FIntfList[I]
  475. else
  476. Result := nil;
  477. end;
  478. function TCnScriptGlobalObjects.GetNamedItemCount: Integer;
  479. begin
  480. Result := FNamedList.Count;
  481. end;
  482. function TCnScriptGlobalObjects.GetNamedItemName(I: Integer): string;
  483. begin
  484. Result := FNamedList[I];
  485. end;
  486. { TCnActiveScriptSite }
  487. constructor TCnActiveScriptSite.Create(AOwner: TComponent);
  488. begin
  489. inherited;
  490. FScriptLanguage := 'VBScript';
  491. FGlobalObjects := TCnScriptGlobalObjects.Create;
  492. FUseSafeSubset := False;
  493. CleanBeforeRun := True;
  494. FEngine := nil;
  495. FDisp := Null;
  496. FParser := nil;
  497. end;
  498. destructor TCnActiveScriptSite.Destroy;
  499. begin
  500. CloseScriptEngine;
  501. FGlobalObjects.Free;
  502. inherited;
  503. end;
  504. procedure TCnActiveScriptSite.AddNamedItem(AName: string;
  505. AIntf: IUnknown);
  506. begin
  507. FGlobalObjects.AddNamedIntf(AName, AIntf);
  508. end;
  509. procedure TCnActiveScriptSite.CreateScriptEngine(
  510. language: string);
  511. const
  512. NULL_GUID: TGUID = '{00000000-0000-0000-0000-000000000000}';
  513. var
  514. ScriptCLSID: TGUID;
  515. LanguageW: WideString;
  516. hr: hResult;
  517. i: Integer;
  518. Disp: IDispatch;
  519. Pos: IObjectSafety;
  520. dwSupported: DWORD;
  521. dwEnabled: DWORD;
  522. begin
  523. if FEngine <> nil then Exit;
  524. LanguageW := language;
  525. if CLSIDFromProgID(PWideChar(LanguageW), ScriptCLSID) <> S_OK
  526. then ScriptCLSID := NULL_GUID;
  527. FEngine := CreateComObject(ScriptCLSID) as IActiveScript;
  528. if FUseSafeSubset then
  529. begin
  530. dwSupported := 0;
  531. dwEnabled := 0;
  532. FEngine.QueryInterface(IObjectSafety, Pos);
  533. if Assigned(Pos) then
  534. begin
  535. Pos.GetInterfaceSafetyOptions(IDispatch, @dwSupported, @dwEnabled);
  536. if (INTERFACE_USES_SECURITY_MANAGER and dwSupported) =
  537. INTERFACE_USES_SECURITY_MANAGER then
  538. begin
  539. dwEnabled := dwEnabled or INTERFACE_USES_SECURITY_MANAGER;
  540. end;
  541. Pos.SetInterfaceSafetyOptions(IDispatch, INTERFACE_USES_SECURITY_MANAGER,
  542. dwEnabled);
  543. end;
  544. end;
  545. hr := FEngine.QueryInterface(IActiveScriptParse, FParser);
  546. OleCheck(hr);
  547. hr := FEngine.SetScriptSite(Self);
  548. OleCheck(hr);
  549. hr := FParser.InitNew();
  550. OleCheck(hr);
  551. for I := 0 to FGlobalObjects.NamedItemCount - 1 do
  552. FEngine.AddNamedItem(PWideChar(WideString(FGlobalObjects.NamedItemName[I])),
  553. SCRIPTITEM_ISVISIBLE);
  554. FEngine.GetScriptDispatch(nil, Disp);
  555. FDisp := Disp;
  556. end;
  557. procedure TCnActiveScriptSite.CloseScriptEngine;
  558. begin
  559. FParser := nil;
  560. if FEngine <> nil then FEngine.Close;
  561. FEngine := nil;
  562. FDisp := Unassigned;
  563. end;
  564. function TCnActiveScriptSite.RunExpression(ACode: WideString): OleVariant;
  565. var
  566. AResult: OleVariant;
  567. ExcepInfo: TExcepInfo;
  568. begin
  569. if FCleanBeforeRun then CloseScriptEngine;
  570. CreateScriptEngine(FScriptLanguage);
  571. if FParser.ParseScriptText(PWideChar(ACode), nil, nil, nil, 0, 0,
  572. SCRIPTTEXT_ISEXPRESSION, AResult, ExcepInfo) = S_OK then
  573. Result := AResult
  574. else
  575. Result := Null;
  576. if FCleanBeforeRun then CloseScriptEngine;
  577. end;
  578. function TCnActiveScriptSite.Execute(ACode: WideString): OleVariant;
  579. var
  580. AResult: OleVariant;
  581. ExcepInfo: TExcepInfo;
  582. begin
  583. if FCleanBeforeRun then CloseScriptEngine;
  584. CreateScriptEngine(FScriptLanguage);
  585. if FParser.ParseScriptText(PWideChar(ACode), nil, nil, nil, 0, 0, 0, AResult,
  586. ExcepInfo) = S_Ok then
  587. Result := AResult
  588. else
  589. Result := Null;
  590. FEngine.SetScriptState(SCRIPTSTATE_CONNECTED);
  591. if FCleanBeforeRun then CloseScriptEngine;
  592. end;
  593. function TCnActiveScriptSite.GetDocVersionString(
  594. out pbstrVersion: WideString): hResult;
  595. begin
  596. Result := E_NOTIMPL;
  597. end;
  598. function TCnActiveScriptSite.GetItemInfo(pstrName: LPCOLESTR;
  599. dwReturnMask: DWORD;
  600. out ppiunkItem: IUnknown;
  601. out ppti: ITypeInfo): hResult; stdcall;
  602. begin
  603. if @ppiunkItem <> nil then Pointer(ppiunkItem) := nil;
  604. if @ppti <> nil then Pointer(ppti) := nil;
  605. if (dwReturnMask and SCRIPTINFO_IUNKNOWN) <> 0
  606. then ppiunkItem := FGlobalObjects.FindNamedItemIntf(pstrName);
  607. Result := S_OK;
  608. end;
  609. function TCnActiveScriptSite.GetLCID(out plcid: Longword): hResult;
  610. begin
  611. plcid := GetSystemDefaultLCID;
  612. Result := S_OK;
  613. end;
  614. function TCnActiveScriptSite.OnEnterScript: hResult;
  615. begin
  616. Result := S_OK;
  617. end;
  618. function TCnActiveScriptSite.OnLeaveScript: hResult;
  619. begin
  620. Result := S_OK;
  621. end;
  622. function TCnActiveScriptSite.OnScriptError(
  623. const pscripterror: IActiveScriptError): hResult;
  624. var
  625. wCookie: DWORD;
  626. ExcepInfo: TExcepInfo;
  627. CharNo: Integer;
  628. LineNo: DWORD;
  629. SourceLineW: WideString;
  630. SourceLine: string;
  631. Desc: string;
  632. begin
  633. Result := S_OK;
  634. wCookie := 0;
  635. LineNo := 0;
  636. CharNo := 0;
  637. if Assigned(pscripterror) then
  638. begin
  639. pscripterror.GetExceptionInfo(ExcepInfo);
  640. Desc := ExcepInfo.bstrDescription;
  641. pscripterror.GetSourcePosition(wCookie, LineNo, CharNo);
  642. pscripterror.GetSourceLineText(SourceLineW);
  643. SourceLine := SourceLineW;
  644. if Assigned(FOnError) then
  645. FOnError(Self, LineNo, CharNo, SourceLine, Desc);
  646. end;
  647. end;
  648. function TCnActiveScriptSite.OnScriptTerminate(var pvarResult: OleVariant;
  649. var PExcepInfo: ExcepInfo): hResult;
  650. begin
  651. Result := S_OK;
  652. end;
  653. function TCnActiveScriptSite.OnStateChange(
  654. ssScriptState: tagSCRIPTSTATE): hResult;
  655. begin
  656. case ssScriptState of
  657. SCRIPTSTATE_UNINITIALIZED: ;
  658. SCRIPTSTATE_INITIALIZED: ;
  659. SCRIPTSTATE_STARTED: ;
  660. SCRIPTSTATE_CONNECTED: ;
  661. SCRIPTSTATE_DISCONNECTED: ;
  662. SCRIPTSTATE_CLOSED: ;
  663. end;
  664. Result := S_OK;
  665. end;
  666. procedure TCnActiveScriptSite.Clear;
  667. begin
  668. CloseScriptEngine;
  669. FGlobalObjects.Clear;
  670. end;
  671. procedure TCnActiveScriptSite.GetComponentInfo(var AName, Author, Email,
  672. Comment: string);
  673. begin
  674. AName := SCnActiveScriptSiteName;
  675. Author := SCnPack_Zjy;
  676. Email := SCnPack_ZjyEmail;
  677. Comment := SCnActiveScriptSiteComment;
  678. end;
  679. { TCnActiveScriptWindow }
  680. function TCnActiveScriptWindow.EnableModeless(fEnable: BOOL): hResult;
  681. begin
  682. Result := S_OK;
  683. end;
  684. procedure TCnActiveScriptWindow.GetComponentInfo(var AName, Author, Email,
  685. Comment: string);
  686. begin
  687. AName := SCnActiveScriptWindowName;
  688. Author := SCnPack_Zjy;
  689. Email := SCnPack_ZjyEmail;
  690. Comment := SCnActiveScriptWindowComment;
  691. end;
  692. function TCnActiveScriptWindow.GetWindow(out phwnd: HWND): hResult;
  693. begin
  694. if (Owner is TCustomForm) then
  695. begin
  696. phwnd := (Owner as TCustomForm).Handle;
  697. Result := S_OK;
  698. end
  699. else
  700. begin
  701. phwnd := 0;
  702. Result := S_FALSE;
  703. end;
  704. end;
  705. end.