home *** CD-ROM | disk | FTP | other *** search
/ Delphi Anthology / aDELPHI.iso / Runimage / Delphi50 / Source / Vcl / vclcom.pas < prev    next >
Pascal/Delphi Source File  |  1999-08-11  |  7KB  |  243 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Borland Delphi Visual Component Library         }
  5. {                                                       }
  6. {       Copyright (c) 1997,99 Inprise Corporation       }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit VCLCom;
  11.  
  12. {$H+,X+}
  13.  
  14. interface
  15.  
  16. uses ActiveX, ComObj, Classes;
  17.  
  18. type
  19.  
  20. { Component object factory }
  21.  
  22.   TComponentFactory = class(TAutoObjectFactory, IClassFactory)
  23.   protected
  24.     function CreateInstance(const UnkOuter: IUnknown; const IID: TGUID;
  25.       out Obj): HResult; stdcall;
  26.   public
  27.     constructor Create(ComServer: TComServerObject;
  28.       ComponentClass: TComponentClass; const ClassID: TGUID;
  29.       Instancing: TClassInstancing; ThreadingModel: TThreadingModel = tmSingle);
  30.     function CreateComObject(const Controller: IUnknown): TComObject; override;
  31.     procedure UpdateRegistry(Register: Boolean); override;
  32.   end;
  33.  
  34. implementation
  35.  
  36. uses
  37.   Windows, SysUtils;
  38.  
  39. type
  40.  
  41. { TApartmentThread }
  42.  
  43.   TApartmentThread = class(TThread)
  44.   private
  45.     FFactory: IClassFactory2;
  46.     FUnkOuter: IUnknown;
  47.     FIID: TGuid;
  48.     FSemaphore: THandle;
  49.     FStream: Pointer;
  50.     FCreateResult: HResult;
  51.   protected
  52.     procedure Execute; override;
  53.   public
  54.     constructor Create(Factory: IClassFactory2; UnkOuter: IUnknown; IID: TGuid);
  55.     destructor Destroy; override;
  56.     property Semaphore: THandle read FSemaphore;
  57.     property CreateResult: HResult read FCreateResult;
  58.     property ObjStream: Pointer read FStream;
  59.   end;
  60.  
  61. { VCL OLE Automation object }
  62.  
  63.   TVCLAutoObject = class(TAutoObject, IVCLComObject)
  64.   private
  65.     FComponent: TComponent;
  66.     FOwnsComponent: Boolean;
  67.   protected
  68.     procedure FreeOnRelease;
  69.     function Invoke(DispID: Integer; const IID: TGUID;
  70.       LocaleID: Integer; Flags: Word; var Params;
  71.       VarResult, ExcepInfo, ArgErr: Pointer): HResult; override;
  72.   public
  73.     constructor Create(Factory: TComObjectFactory; Component: TComponent);
  74.     destructor Destroy; override;
  75.     procedure Initialize; override;
  76.     function ObjQueryInterface(const IID: TGUID; out Obj): HResult; override;
  77.   end;
  78.  
  79. { TApartmentThread }
  80.  
  81. constructor TApartmentThread.Create(Factory: IClassFactory2;
  82.   UnkOuter: IUnknown; IID: TGuid);
  83. begin
  84.   FFactory := Factory;
  85.   FUnkOuter := UnkOuter;
  86.   FIID := IID;
  87.   FSemaphore := CreateSemaphore(nil, 0, 1, nil);
  88.   FreeOnTerminate := True;
  89.   inherited Create(False);
  90. end;
  91.  
  92. destructor TApartmentThread.Destroy;
  93. begin
  94.   CloseHandle(FSemaphore);
  95.   inherited Destroy;
  96. end;
  97.  
  98. procedure TApartmentThread.Execute;
  99. var
  100.   msg: TMsg;
  101.   Unk: IUnknown;
  102. begin
  103.   try
  104.     CoInitialize(nil);
  105.     try
  106.       FCreateResult := FFactory.CreateInstanceLic(FUnkOuter, nil, FIID, '', Unk);
  107.       FUnkOuter := nil;
  108.       FFactory := nil;
  109.       if FCreateResult = S_OK then
  110.         CoMarshalInterThreadInterfaceInStream(FIID, Unk, IStream(FStream));
  111.       ReleaseSemaphore(FSemaphore, 1, nil);
  112.       if FCreateResult = S_OK then
  113.         while GetMessage(msg, 0, 0, 0) do
  114.         begin
  115.           DispatchMessage(msg);
  116.           Unk._AddRef;
  117.           if Unk._Release = 1 then break;
  118.         end;
  119.     finally
  120.       Unk := nil;
  121.       CoUninitialize;
  122.     end;
  123.   except
  124.     { No exceptions should go unhandled }
  125.   end;
  126. end;
  127.  
  128. { TVCLAutoObject }
  129.  
  130. constructor TVCLAutoObject.Create(Factory: TComObjectFactory;
  131.   Component: TComponent);
  132. begin
  133.   FComponent := Component;
  134.   CreateFromFactory(Factory, nil);
  135. end;
  136.  
  137. destructor TVCLAutoObject.Destroy;
  138. begin
  139.   if FComponent <> nil then
  140.   begin
  141.     FComponent.VCLComObject := nil;
  142.     if FOwnsComponent then FComponent.Free;
  143.   end;
  144.   inherited Destroy;
  145. end;
  146.  
  147. procedure TVCLAutoObject.FreeOnRelease;
  148. begin
  149.   FOwnsComponent := True;
  150. end;
  151.  
  152. procedure TVCLAutoObject.Initialize;
  153. begin
  154.   inherited Initialize;
  155.   if FComponent = nil then
  156.   begin
  157.     FComponent := TComponentClass(Factory.ComClass).Create(nil);
  158.     FOwnsComponent := True;
  159.   end;
  160.   FComponent.VCLComObject := Pointer(IVCLComObject(Self));
  161. end;
  162.  
  163. function TVCLAutoObject.Invoke(DispID: Integer; const IID: TGUID;
  164.   LocaleID: Integer; Flags: Word; var Params;
  165.   VarResult, ExcepInfo, ArgErr: Pointer): HResult;
  166. begin
  167.   Result := DispInvoke(Pointer(Integer(FComponent) +
  168.     TComponentFactory(Factory).DispIntfEntry^.IOffset),
  169.     TComponentFactory(Factory).DispTypeInfo, DispID, Flags,
  170.     TDispParams(Params), VarResult, ExcepInfo, ArgErr);
  171. end;
  172.  
  173. function TVCLAutoObject.ObjQueryInterface(const IID: TGUID; out Obj): HResult;
  174. begin
  175.   Result := inherited ObjQueryInterface(IID, Obj);
  176.   if (Result <> 0) and (FComponent <> nil) then
  177.     if FComponent.GetInterface(IID, Obj) then Result := 0;
  178. end;
  179.  
  180. { TComponentFactory }
  181.  
  182. constructor TComponentFactory.Create(ComServer: TComServerObject;
  183.   ComponentClass: TComponentClass; const ClassID: TGUID;
  184.   Instancing: TClassInstancing; ThreadingModel: TThreadingModel);
  185. begin
  186.   inherited Create(ComServer, TAutoClass(ComponentClass),
  187.     ClassID, Instancing, ThreadingModel);
  188. end;
  189.  
  190. function TComponentFactory.CreateInstance(const UnkOuter: IUnknown;
  191.   const IID: TGUID; out Obj): HResult; stdcall;
  192. begin
  193.   if not IsLibrary and (ThreadingModel = tmApartment) then
  194.   begin
  195.     LockServer(True);
  196.     try
  197.       with TApartmentThread.Create(Self, UnkOuter, IID) do
  198.       begin
  199.         if WaitForSingleObject(Semaphore, INFINITE) = WAIT_OBJECT_0 then
  200.         begin
  201.           Result := CreateResult;
  202.           if Result <> S_OK then Exit;
  203.           Result := CoGetInterfaceAndReleaseStream(IStream(ObjStream), IID, Obj);
  204.         end else
  205.           Result := E_FAIL
  206.       end;
  207.     finally
  208.       LockServer(False);
  209.     end;
  210.   end else
  211.     Result := inherited CreateInstance(UnkOuter, IID, Obj);
  212. end;
  213.  
  214. type
  215.   TComponentProtectedAccess = class(TComponent);
  216.   TComponentProtectedAccessClass = class of TComponentProtectedAccess;
  217.  
  218. procedure TComponentFactory.UpdateRegistry(Register: Boolean);
  219. begin
  220.   if Register then inherited UpdateRegistry(Register);
  221.   TComponentProtectedAccessClass(ComClass).UpdateRegistry(Register, GUIDToString(ClassID), ProgID);
  222.   if not Register then inherited UpdateRegistry(Register);
  223. end;
  224.  
  225. function TComponentFactory.CreateComObject(const Controller: IUnknown): TComObject;
  226. begin
  227.   Result := TVCLAutoObject.CreateFromFactory(Self, Controller);
  228. end;
  229.  
  230. { Global routines }
  231.  
  232. procedure CreateVCLComObject(Component: TComponent);
  233. begin
  234.   TVCLAutoObject.Create(ComClassManager.GetFactoryFromClass(
  235.     Component.ClassType), Component);
  236. end;
  237.  
  238. initialization
  239.   CreateVCLComObjectProc := CreateVCLComObject;
  240. finalization
  241.   CreateVCLComObjectProc := nil;
  242. end.
  243.