GLPlugInManager.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. {
  5. An old PlugIn Manager unit. Don't know if if ever wa used...
  6. }
  7. unit GLPlugInManager;
  8. interface
  9. {$I GLScene.inc}
  10. uses
  11. Winapi.Windows,
  12. System.Classes,
  13. System.SysUtils,
  14. VCL.Dialogs,
  15. VCL.Forms,
  16. GLPlugInIntf;
  17. type
  18. PPlugInEntry = ^TGLPlugInEntry;
  19. TGLPlugInEntry = record
  20. Path: TFileName;
  21. Handle: HINST;
  22. FileSize: Integer;
  23. FileDate: TDateTime;
  24. EnumResourcenames: TEnumResourceNames;
  25. GetServices: TGetServices;
  26. GetVendor: TGetVendor;
  27. GetDescription: TGetDescription;
  28. GetVersion: TGetVersion;
  29. end;
  30. TGLPlugInManager = class;
  31. TGLResourceManager = class(TComponent)
  32. public
  33. procedure Notify(Sender: TGLPlugInManager; Operation: TOperation;
  34. Service: TPIServiceType; PlugIn: Integer); virtual; abstract;
  35. end;
  36. TGLPlugInList = class(TStringList)
  37. private
  38. FOwner: TGLPlugInManager;
  39. function GetPlugInEntry(Index: Integer): PPlugInEntry;
  40. procedure SetPlugInEntry(Index: Integer; AEntry: PPlugInEntry);
  41. protected
  42. procedure DefineProperties(Filer: TFiler); override;
  43. procedure ReadPlugIns(Reader: TReader);
  44. procedure WritePlugIns(Writer: TWriter);
  45. public
  46. constructor Create(AOwner: TGLPlugInManager); virtual;
  47. procedure ClearList;
  48. property Objects[Index: Integer]: PPlugInEntry read GetPlugInEntry
  49. write SetPlugInEntry; default;
  50. property Owner: TGLPlugInManager read FOwner;
  51. end;
  52. PResManagerEntry = ^TResManagerEntry;
  53. TResManagerEntry = record
  54. Manager: TGLResourceManager;
  55. Services: TPIServices;
  56. end;
  57. TGLPlugInManager = class(TComponent)
  58. private
  59. FLibraryList: TGLPlugInList;
  60. FResManagerList: TList;
  61. protected
  62. procedure DoNotify(Operation: TOperation; Service: TPIServiceType;
  63. PlugIn: Integer);
  64. function FindResManager(AManager: TGLResourceManager): PResManagerEntry;
  65. function GetIndexFromFilename(FileName: String): Integer;
  66. function GetPlugInFromFilename(FileName: String): PPlugInEntry;
  67. public
  68. constructor Create(AOwner: TComponent); override;
  69. destructor Destroy; override;
  70. function AddPlugIn(Path: TFileName): Integer;
  71. procedure EditPlugInList;
  72. procedure RegisterResourceManager(AManager: TGLResourceManager;
  73. Services: TPIServices);
  74. procedure RemovePlugIn(Index: Integer);
  75. procedure UnRegisterRessourceManager(AManager: TGLResourceManager;
  76. Services: TPIServices);
  77. published
  78. property PlugIns: TGLPlugInList read FLibraryList write FLibraryList;
  79. end;
  80. // ------------------------------------------------------------------------------
  81. implementation
  82. // ------------------------------------------------------------------------------
  83. // ----------------- TGLPlugInList ------------------------------------------------
  84. constructor TGLPlugInList.Create(AOwner: TGLPlugInManager);
  85. begin
  86. inherited Create;
  87. FOwner := AOwner;
  88. Sorted := False;
  89. Duplicates := DupAccept;
  90. end;
  91. // ------------------------------------------------------------------------------
  92. procedure TGLPlugInList.ClearList;
  93. begin
  94. while Count > 0 do
  95. FOwner.RemovePlugIn(0);
  96. end;
  97. // ------------------------------------------------------------------------------
  98. function TGLPlugInList.GetPlugInEntry(Index: Integer): PPlugInEntry;
  99. begin
  100. Result := PPlugInEntry( inherited Objects[Index]);
  101. end;
  102. // ------------------------------------------------------------------------------
  103. procedure TGLPlugInList.SetPlugInEntry(Index: Integer; AEntry: PPlugInEntry);
  104. begin
  105. inherited Objects[Index] := Pointer(AEntry);
  106. end;
  107. // ------------------------------------------------------------------------------
  108. procedure TGLPlugInList.WritePlugIns(Writer: TWriter);
  109. var
  110. I: Integer;
  111. begin
  112. Writer.WriteListBegin;
  113. for I := 0 to Count - 1 do
  114. Writer.WriteString(Objects[I].Path);
  115. Writer.WriteListEnd;
  116. end;
  117. // ------------------------------------------------------------------------------
  118. procedure TGLPlugInList.ReadPlugIns(Reader: TReader);
  119. begin
  120. ClearList;
  121. Reader.ReadListBegin;
  122. while not Reader.EndOfList do
  123. FOwner.AddPlugIn(Reader.ReadString);
  124. Reader.ReadListEnd;
  125. end;
  126. // ------------------------------------------------------------------------------
  127. procedure TGLPlugInList.DefineProperties(Filer: TFiler);
  128. begin
  129. Filer.DefineProperty('Paths', ReadPlugIns, WritePlugIns, Count > 0);
  130. end;
  131. // ----------------- TGLPlugInManager ---------------------------------------------
  132. constructor TGLPlugInManager.Create(AOwner: TComponent);
  133. begin
  134. inherited Create(AOwner);
  135. FLibraryList := TGLPlugInList.Create(Self);
  136. FResManagerList := TList.Create;
  137. end;
  138. // ------------------------------------------------------------------------------
  139. destructor TGLPlugInManager.Destroy;
  140. var
  141. I: Integer;
  142. begin
  143. FLibraryList.ClearList;
  144. FLibraryList.Free;
  145. for I := 0 to FResManagerList.Count - 1 do
  146. FreeMem(PResManagerEntry(FResManagerList[I]), SizeOf(TResManagerEntry));
  147. FResManagerList.Free;
  148. inherited Destroy;
  149. end;
  150. // ------------------------------------------------------------------------------
  151. function TGLPlugInManager.AddPlugIn(Path: TFileName): Integer;
  152. // open the given DLL and read its properties, to identify
  153. // whether it's a valid plug-in or not
  154. var
  155. NewPlugIn: PPlugInEntry;
  156. OldError: Integer;
  157. NewHandle: HINST;
  158. ServiceFunc: TGetServices;
  159. SearchRec: TSearchRec;
  160. Service: TPIServiceType;
  161. Services: TPIServices;
  162. begin
  163. Result := -1;
  164. OldError := SetErrorMode(SEM_NOOPENFILEERRORBOX);
  165. if Length(Path) > 0 then
  166. try
  167. Result := GetIndexFromFilename(Path);
  168. // plug-in already registered?
  169. if Result > -1 then
  170. Exit;
  171. // first step is loading the file into client memory
  172. NewHandle := LoadLibrary(PChar(Path));
  173. // loading failed -> exit
  174. if NewHandle = 0 then
  175. Abort;
  176. // get the service function address to identify the plug-in
  177. ServiceFunc := GetProcAddress(NewHandle, 'GetServices');
  178. if not assigned(ServiceFunc) then
  179. begin
  180. // if address not found then the given library is not valid
  181. // release it from client memory
  182. FreeLibrary(NewHandle);
  183. Abort;
  184. end;
  185. // all went fine so far, we just loaded a valid plug-in
  186. // allocate a new entry for the plug-in list and fill it
  187. New(NewPlugIn);
  188. NewPlugIn.Path := Path;
  189. with NewPlugIn^ do
  190. begin
  191. Handle := NewHandle;
  192. FindFirst(Path, faAnyFile, SearchRec);
  193. FileSize := SearchRec.Size;
  194. FileDate := SearchRec.TimeStamp;
  195. FindClose(SearchRec);
  196. GetServices := ServiceFunc;
  197. EnumResourcenames := GetProcAddress(Handle, 'EnumResourceNames');
  198. GetVendor := GetProcAddress(Handle, 'GetVendor');
  199. GetVersion := GetProcAddress(Handle, 'GetVersion');
  200. GetDescription := GetProcAddress(Handle, 'GetDescription');
  201. end;
  202. Result := FLibraryList.Add(string(NewPlugIn.GetVendor));
  203. FLibraryList.Objects[Result] := NewPlugIn;
  204. // now notify (for all provided services) all registered resource managers
  205. // for which these services are relevant
  206. Services := NewPlugIn.GetServices;
  207. for Service := Low(TPIServiceType) to High(TPIServiceType) do
  208. if Service in Services then
  209. DoNotify(opInsert, Service, Result);
  210. finally
  211. SetErrorMode(OldError);
  212. end;
  213. end;
  214. // ------------------------------------------------------------------------------
  215. procedure TGLPlugInManager.DoNotify(Operation: TOperation;
  216. Service: TPIServiceType; PlugIn: Integer);
  217. var
  218. I: Integer;
  219. begin
  220. for I := 0 TO FResManagerList.Count - 1 do
  221. if Service in PResManagerEntry(FResManagerList[I]).Services then
  222. PResManagerEntry(FResManagerList[I]).Manager.Notify(Self, Operation,
  223. Service, PlugIn);
  224. end;
  225. // ------------------------------------------------------------------------------
  226. function TGLPlugInManager.FindResManager(AManager: TGLResourceManager)
  227. : PResManagerEntry;
  228. var
  229. I: Integer;
  230. begin
  231. Result := nil;
  232. for I := 0 to FResManagerList.Count - 1 do
  233. if PResManagerEntry(FResManagerList[I]).Manager = AManager then
  234. begin
  235. Result := PResManagerEntry(FResManagerList[I]);
  236. Exit;
  237. end;
  238. end;
  239. // ------------------------------------------------------------------------------
  240. function TGLPlugInManager.GetIndexFromFilename(FileName: String): Integer;
  241. var
  242. I: Integer;
  243. begin
  244. Result := -1;
  245. for I := 0 to FLibraryList.Count - 1 do
  246. if CompareText(FLibraryList[I].Path, FileName) = 0 then
  247. begin
  248. Result := I;
  249. Exit;
  250. end;
  251. end;
  252. // ------------------------------------------------------------------------------
  253. function TGLPlugInManager.GetPlugInFromFilename(FileName: String): PPlugInEntry;
  254. var
  255. I: Integer;
  256. begin
  257. I := GetIndexFromFilename(FileName);
  258. if I > -1 then
  259. Result := FLibraryList[I]
  260. else
  261. Result := nil;
  262. end;
  263. // ------------------------------------------------------------------------------
  264. procedure TGLPlugInManager.RegisterResourceManager(AManager: TGLResourceManager;
  265. Services: TPIServices);
  266. var
  267. ManagerEntry: PResManagerEntry;
  268. begin
  269. ManagerEntry := FindResManager(AManager);
  270. if assigned(ManagerEntry) then
  271. ManagerEntry.Services := ManagerEntry.Services + Services
  272. else
  273. begin
  274. New(ManagerEntry);
  275. ManagerEntry.Manager := AManager;
  276. ManagerEntry.Services := Services;
  277. FResManagerList.Add(ManagerEntry);
  278. end;
  279. end;
  280. // ------------------------------------------------------------------------------
  281. procedure TGLPlugInManager.RemovePlugIn(Index: Integer);
  282. var
  283. Entry: PPlugInEntry;
  284. Service: TPIServiceType;
  285. Services: TPIServices;
  286. begin
  287. Entry := FLibraryList.Objects[Index];
  288. Services := Entry.GetServices;
  289. // notify for all services to be deleted all registered resource managers
  290. // for which these services are relevant
  291. for Service := Low(TPIServiceType) to High(TPIServiceType) do
  292. if Service in Services then
  293. DoNotify(opRemove, Service, Index);
  294. FreeLibrary(Entry.Handle);
  295. Dispose(Entry);
  296. FLibraryList.Delete(Index);
  297. end;
  298. // ------------------------------------------------------------------------------
  299. procedure TGLPlugInManager.EditPlugInList;
  300. begin
  301. ///TGLPlugInManagerEditor.EditPlugIns(Self); //Circular call to edit Listbox items?
  302. end;
  303. // ------------------------------------------------------------------------------
  304. procedure TGLPlugInManager.UnRegisterRessourceManager(AManager: TGLResourceManager;
  305. Services: TPIServices);
  306. var
  307. ManagerEntry: PResManagerEntry;
  308. Index: Integer;
  309. begin
  310. ManagerEntry := FindResManager(AManager);
  311. if assigned(ManagerEntry) then
  312. begin
  313. ManagerEntry.Services := ManagerEntry.Services - Services;
  314. if ManagerEntry.Services = [] then
  315. begin
  316. Index := FResManagerList.IndexOf(ManagerEntry);
  317. Dispose(ManagerEntry);
  318. FResManagerList.Delete(Index);
  319. end;
  320. end;
  321. end;
  322. // ------------------------------------------------------------------------------
  323. end.