home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Runimage / Delphi50 / Source / Rtl / Corba / CORBAOBJ.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-11  |  42.9 KB  |  1,601 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Borland Delphi Runtime Library                  }
  5. {                                                       }
  6. {       Copyright (C) 1999 Inprise Corporation          }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit CorbaObj;
  11.  
  12. {$T-,H+,X+}
  13.  
  14. interface
  15.  
  16. uses SysUtils, ORBPAS, ActiveX;
  17.  
  18. type
  19.   CorbaBoolean = ORBPAS.CorbaBoolean;
  20.   CorbaULong = ORBPAS.CorbaULong;
  21.   IObject = System.IUnknown;
  22.   TCorbaPrincipal = array of Byte;
  23.   TCommandLine = ORBPAS.TArgv;
  24.   TCKind = ORBPAS.TCKind;
  25.   TAny = Variant;
  26.   ITypeCode = ORBPAS.ITypeCode;
  27.   
  28.   ICorbaObject = interface
  29.     ['{0BAF8E01-CE38-11D1-AADC-00C04FB17A72}']
  30.     function NonExistent: Boolean;
  31.     function Hash(Maximum: Integer): Integer;
  32.     function IsA(const LogicalTypeId: string): Boolean;
  33.     procedure SetPrincipal(const Prinicpal: TCorbaPrincipal);
  34.   end;
  35.  
  36.   ECorbaException = class(Exception)
  37.   protected
  38.     function GetMessage: string;
  39.   public
  40.     property Name: string read GetMessage;
  41.   end;
  42.  
  43.   ECorbaDispatch = class(Exception);
  44.  
  45.   ECorbaUserException = class(ECorbaException)
  46.   private
  47.    FProxy: PUserExceptionProxy;
  48.   public
  49.     constructor Create(const Name: string);
  50.     procedure Copy(const InBuf: IMarshalInBuffer); virtual; abstract;
  51.     procedure Throw;
  52.     property Proxy: PUserExceptionProxy read FProxy;
  53.   end;
  54.  
  55.   TCorbaThreadModel = (tmMultiThreaded, tmSingleThread);
  56.  
  57.   TCorbaInstancing = (iSingleInstance, iMultiInstance);
  58.  
  59. {$M+}
  60.   TCorbaSkeleton = class(TInterfacedObject, ISkeletonObject)
  61.   protected
  62.     FSkeleton: ISkeleton;
  63.     procedure InitSkeleton(const InterfaceName, InstanceName, RepositoryID: string;
  64.       ThreadModel: TCorbaThreadModel; ClientRefCount: Boolean);
  65.   protected
  66.     { ISkeletonObject }
  67.     procedure GetSkeleton(out Skeleton: ISkeleton); stdcall;
  68.     procedure GetImplementation(out Impl: IObject); virtual; stdcall;
  69.     function Execute(Operation: PChar; const Strm: IMarshalInBuffer;
  70.       Cookie: Pointer): CorbaBoolean; stdcall;
  71.   public
  72.     constructor Create(const InstanceName: string; const Impl: IObject); virtual;
  73.     destructor Destroy; override;
  74.   end;
  75. {$M-}
  76.  
  77.   TCorbaStub = class(TInterfacedObject, IStubObject, ICorbaObject)
  78.   protected
  79.     FStub: IStub;
  80.   protected
  81.     { IStubObject }
  82.     procedure GetStub(out Stub: IStub); stdcall;
  83.     { ICorbaObject }
  84.     function NonExistent: Boolean;
  85.     function Hash(Maximum: Integer): Integer;
  86.     function IsA(const LogicalTypeId: string): Boolean;
  87.     procedure SetPrincipal(const Prinicpal: TCorbaPrincipal);
  88.   public
  89.     constructor Create(const Stub: IStub); virtual;
  90.     destructor Destroy; override;
  91.   end;
  92.  
  93.   TCorbaDispatchStub = class(TCorbaStub, IDispatch)
  94.   protected
  95.     { IDispatch }
  96.     function GetIDsOfNames(const IID: TGUID; Names: Pointer;
  97.       NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; virtual; stdcall;
  98.     function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; virtual; stdcall;
  99.     function GetTypeInfoCount(out Count: Integer): HResult; virtual; stdcall;
  100.     function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  101.       Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; virtual; stdcall;
  102.   end;
  103.  
  104.   TCorbaListManager = class
  105.   private
  106.     FSync: TMultiReadExclusiveWriteSynchronizer;
  107.   protected
  108.     procedure BeginRead;
  109.     procedure BeginWrite;
  110.     procedure EndRead;
  111.     procedure EndWrite;
  112.   public
  113.     constructor Create;
  114.     destructor Destroy; override;
  115.   end;
  116.  
  117.   TInterfaceIDEntryDesc = record
  118.     RepositoryID: string;
  119.     IID: TGUID;
  120.   end;
  121.   TInterfaceIDList = array of TInterfaceIDEntryDesc;
  122.  
  123.   TCorbaInterfaceIDManager = class(TCorbaListManager)
  124.   private
  125.     FList: TInterfaceIDList;
  126.     FUsed: Integer;
  127.   public
  128.     procedure RegisterInterface( const IID: TGUID; const RepositoryID: string);
  129.     function SearchGUID(const RepositoryID: string; out IID: TGUID): Boolean;
  130.     function SearchID(const IID: TGUID; out RepositoryID: string): Boolean;
  131.     function FindGUID(const RepositoryID: string): TGUID;
  132.     function FindID(const IID: TGUID): string;
  133.   end;
  134.  
  135.   TCorbaSkeletonClass = class of TCorbaSkeleton;
  136.  
  137.   TSkeletonEntryDesc = record
  138.     IID: TGUID;
  139.     SkeletonClass: TCorbaSkeletonClass;
  140.   end;
  141.   TSkeletonList = array of TSkeletonEntryDesc;
  142.  
  143.   TCorbaSkeletonManager = class(TCorbaListManager)
  144.   private
  145.     FList: TSkeletonList;
  146.     FUsed: Integer;
  147.   public
  148.     procedure RegisterSkeleton(IID: TGUID; Skeleton: TCorbaSkeletonClass);
  149.     function CreateSkeleton(IID: TGUID; const InstanceName: string;
  150.       const Impl: IObject): ISkeletonObject;
  151.   end;
  152.  
  153.   TCorbaStubClass = class of TCorbaStub;
  154.  
  155.   TStubEntryDesc = record
  156.     IID: TGUID;
  157.     StubClass: TCorbaStubClass;
  158.   end;
  159.   TStubList = array of TStubEntryDesc;
  160.  
  161.   TCorbaStubManager = class(TCorbaListManager)
  162.   private
  163.     FList: TStubList;
  164.     FUsed: Integer;
  165.   public
  166.     procedure RegisterStub(IID: TGUID; Stub: TCorbaStubClass);
  167.     function CreateStub(IID: TGUID; const Stub: IStub): IObject;
  168.   end;
  169.  
  170.   TCorbaFactory = class;
  171.  
  172.   TCorbaImplementation = class(TObject, IUnknown)
  173.   protected
  174.     FRefCount: Integer;
  175.     FController: Pointer;
  176.     FFactory: TCorbaFactory;
  177.     { IUnknown }
  178.     function IUnknown.QueryInterface = ObjQueryInterface;
  179.     function IUnknown._AddRef = ObjAddRef;
  180.     function IUnknown._Release = ObjRelease;
  181.     function ObjAddRef: Integer; virtual; stdcall;
  182.     function ObjQueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
  183.     function ObjRelease: Integer; virtual; stdcall;
  184.     { IUnknown methods for other interfaces }
  185.     function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
  186.     function _AddRef: Integer; stdcall;
  187.     function _Release: Integer; stdcall;
  188.     { Stub implementation for IDispatch }
  189.     function GetIDsOfNames(const IID: TGUID; Names: Pointer;
  190.       NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
  191.     function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
  192.     function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
  193.     function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  194.       Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
  195.   public
  196.     constructor Create(Controller: IObject; AFactory: TCorbaFactory); virtual;
  197.   end;
  198.  
  199.   TCorbaImplementationClass = class of TCorbaImplementation;
  200.  
  201.   TCorbaFactory = class(TInterfacedObject, ISkeletonObject)
  202.   private
  203.     FInterfaceName: string;
  204.     FInstanceName: string;
  205.     FRepositoryID: string;
  206.     FInstancing: TCorbaInstancing;
  207.     FThreadModel: TCorbaThreadModel;
  208.     FIID: TGUID;
  209.     FSkeleton: ISkeleton;
  210.     FSingleInstanceSkelton: ISkeletonObject;
  211.     FTypeInfo: ITypeInfo;
  212.   protected
  213.     { ISkeletonObject }
  214.     procedure GetSkeleton(out Skeleton: ISkeleton); stdcall;
  215.     procedure GetImplementation(out Impl: IObject); stdcall;
  216.     function Execute(Operation: PChar; const Strm: IMarshalInBuffer;
  217.       Cookie: Pointer): CorbaBoolean; stdcall;
  218.     function GetTypeInfo(out TypeInfo): HRESULT;
  219.   protected
  220.     function CreateInstance(const InstanceName: string): ISkeletonObject; virtual;
  221.     function CreateInterface(const InstanceName: string): IObject; virtual;
  222.     procedure RegisterFactory;
  223.   public
  224.     constructor Create(const InterfaceName, InstanceName, RepositoryId: string;
  225.       const ImplGUID: TGUID; Instancing: TCorbaInstancing = iMultiInstance;
  226.       ThreadModel: TCorbaThreadModel = tmSingleThread);
  227.     destructor Destroy; override;
  228.     property InterfaceName: string read FInterfaceName;
  229.     property InstanceName: string read FInstanceName;
  230.     property RepositoryID: string read FRepositoryID;
  231.     property Instancing: TCorbaInstancing read FInstancing;
  232.     property ThreadModel: TCorbaThreadModel read FThreadModel;
  233.   end;
  234.  
  235.   TCorbaObjectFactory = class(TCorbaFactory)
  236.   private
  237.     FImplementationClass: TCorbaImplementationClass;
  238.   protected
  239.     function CreateInterface(const InstanceName: string): IObject; override;
  240.   public
  241.     constructor Create(const InterfaceName, InstanceName, RepositoryId: string;
  242.       const ImplGUID: TGUID; ImplementationClass: TCorbaImplementationClass;
  243.       Instancing: TCorbaInstancing = iMultiInstance;
  244.       ThreadModel: TCorbaThreadModel = tmSingleThread);
  245.     property ImplementationClass: TCorbaImplementationClass read FImplementationClass;
  246.   end;
  247.  
  248.   TFactoryList = array of TCorbaFactory;
  249.  
  250.   TCorbaFactoryManager = class(TCorbaListManager)
  251.   private
  252.     FList: TFactoryList;
  253.     FUsed: Integer;
  254.     FRegistered: Boolean;
  255.   public
  256.     destructor Destroy; override;
  257.     procedure AddFactory(Factory: TCorbaFactory);
  258.     procedure RegisterFactories;
  259.     function Find(const RepositoryID, InterfaceName, InstanceName: string): TCorbaFactory;
  260.   end;
  261.  
  262.   TBOA = class
  263.   private
  264.     BOA: IBOA;
  265.   public
  266.     class procedure Initialize(const CommandLine: TCommandLine);
  267.     procedure ObjIsReady(const Obj: IObject);
  268.     procedure ImplIsReady;
  269.     procedure Deactivate(const Obj: IObject);
  270.     function GetPrincipal(const Obj: IObject): TCorbaPrincipal;
  271.   end;
  272.  
  273.   TORB = class
  274.   private
  275.     ORB: IORB;
  276.     function MakeComplexAny(TypeCode: ITypeCode; const Elements: array of TAny): TAny;
  277.   public
  278.     class procedure Initialize; overload;
  279.     class procedure Initialize(const CommandLine: TCommandLine); overload;
  280.     function StringToObject(const ObjectString: string): IObject;
  281.     function ObjectToString(const Obj: IObject): string;
  282.     procedure Shutdown;
  283.  
  284.     { Binding methods }
  285.     function Bind(const RepositoryID: string; const ObjectName: string = '';
  286.       const HostName: string = ''): IObject; overload;
  287.     function Bind(const InterfaceID: TGUID; const ObjectName: string = '';
  288.       const HostName: string = ''): IObject; overload;
  289.  
  290.     { Dynamic invocation methods }
  291.     function FindTypeCode(const RepositoryID: string): ITypeCode;
  292.     function MakeArray(Kind: TCKind; const Elements: array of TAny): TAny; overload;
  293.     function MakeArray(TypeCode: ITypeCode; const Elements: array of TAny): TAny; overload;
  294.     function MakeSequence(Kind: TCKind; const Elements: array of TAny): TAny; overload;
  295.     function MakeSequence(TypeCode: ITypeCode; const Elements: array of TAny): TAny; overload;
  296.     function MakeStructure(TypeCode: ITypeCode; const Elements: array of TAny): TAny;
  297.     function MakeAlias(const RepositoryID, TypeName: string; Value, Test: TAny): TAny;
  298.  
  299.     function MakeTypeCode(Kind: TCKind): ITypeCode;
  300.     function MakeSequenceTypeCode(Bound: CorbaULong; const TC: ITypeCode): ITypeCode;
  301.     function MakeStructureTypeCode(const RepositoryID, Name: string; Members: TStructMembers): ITypeCode;
  302.     function MakeAliasTypeCode(const RepositoryID, Name: string; const TC: ITypeCode): ITypeCode;
  303.     function MakeObjectRefTypeCode(const RepositoryID, Name: string): ITypeCode;
  304.   end;
  305.  
  306. { CORBA helper routines }
  307.  
  308. procedure CorbaInitialize;
  309. function CorbaBind(const RepositoryID: string; const ObjectName: string = '';
  310.   const HostName: string = ''): IObject; overload;
  311. function CorbaBind(const InterfaceID: TGUID; const ObjectName: string = '';
  312.   const HostName: string = ''): IObject; overload;
  313. function MakePrincipal(const Bytes: array of Byte): TCorbaPrincipal;
  314. function BOA: TBOA;
  315. function ORB: TORB;
  316.  
  317. { Any helpers }
  318.  
  319. function VariantArrayToSequence(TypeCode: ITypeCode; const VariantArray: Variant): TAny;
  320. function SequenceToVariantArray(Sequence: TAny): Variant;
  321. function AnyToObject(Any: TAny; IID: TGUID): IObject;
  322.  
  323. { Global variables }
  324.  
  325. var
  326.   CorbaSkeletonManager: TCorbaSkeletonManager;
  327.   CorbaStubManager: TCorbaStubManager;
  328.   CorbaInterfaceIDManager: TCorbaInterfaceIDManager;
  329.  
  330. { Internal marshalling routines }
  331.  
  332. procedure MarshalObject(const OutBuf: IMarshalOutBuffer; IID: TGUID;
  333.   const Intf: IObject);
  334. function UnmarshalObject(const InBuf: IMarshalInBuffer; IID: TGUID): IObject;
  335. procedure MarshalAny(const OutBuf: IMarshalOutBuffer; const OV: Variant);
  336. function UnmarshalAny(const InBuf: IMarshalInBuffer): Variant;
  337. function UnmarshalText(const InBuf: IMarshalInBuffer): string;
  338. function UnmarshalWideText(const InBuf: IMarshalInBuffer): WideString;
  339. procedure MarshalWordBool(const OutBuf: IMarshalOutBuffer; Value: WordBool);
  340. function UnmarshalWordBool(const InBuf: IMarshalInBuffer): WordBool;
  341. function CorbaFactoryCreateStub(const RepId, FactoryId, InstanceName, HostName: string;
  342.   IID: TGUID): IObject;
  343.  
  344. implementation
  345.  
  346. uses Windows, CorbCnst;
  347.  
  348. var
  349.   CorbaFactoryManager: TCorbaFactoryManager;
  350.   BOAVar: TBOA;
  351.   ORBVar: TORB;
  352.  
  353. type
  354.   TUnmarshalProc =  procedure (const Strm: IMarshalInBuffer; Cookie: Pointer) of object;
  355.  
  356. { ECorbaException }
  357.  
  358. function ECorbaException.GetMessage: string;
  359. begin
  360.   Result := Message;
  361. end;
  362.  
  363. { ECorbaUserException }
  364.  
  365. constructor ECorbaUserException.Create(const Name: string);
  366. begin
  367.   inherited Create(Name);
  368.   FProxy := CreateUserException(Copy, Throw);
  369. end;
  370.  
  371. procedure ECorbaUserException.Throw;
  372. begin
  373.   raise Self;
  374. end;
  375.  
  376. { TCorbaSkeleton }
  377.  
  378. constructor TCorbaSkeleton.Create(const InstanceName: string;
  379.   const Impl: IObject);
  380. begin
  381.   inherited Create;
  382. end;
  383.  
  384. destructor TCorbaSkeleton.Destroy;
  385. begin
  386.   FSkeleton := nil;
  387.   inherited Destroy;
  388. end;
  389.  
  390. procedure TCorbaSkeleton.InitSkeleton(const InterfaceName, InstanceName,
  391.   RepositoryID: string; ThreadModel: TCorbaThreadModel; ClientRefCount: Boolean);
  392. var
  393.   Factory: TCorbaFactory;
  394.   Serialize: Boolean;
  395. begin
  396.   Factory := CorbaFactoryManager.Find(RepositoryID, InterfaceName, InstanceName);
  397.   if Factory <> nil then
  398.     Serialize := Factory.ThreadModel = tmSingleThread
  399.   else
  400.     Serialize := ThreadModel = tmSingleThread;
  401.   CreateSkeleton(PChar(Pointer(InterfaceName)), Self, Serialize,
  402.     PChar(Pointer(InstanceName)),  PChar(Pointer(RepositoryID)),
  403.       ClientRefCount, FSkeleton);
  404. end;
  405.  
  406. procedure TCorbaSkeleton.GetSkeleton(out Skeleton: ISkeleton);
  407. begin
  408.   Skeleton := FSkeleton;
  409. end;
  410.  
  411. procedure TCorbaSkeleton.GetImplementation(out Impl: IObject);
  412. begin
  413.   Impl := nil;
  414. end;
  415.  
  416. function TCorbaSkeleton.Execute(Operation: PChar; const Strm: IMarshalInBuffer;
  417.  Cookie: Pointer): CorbaBoolean;
  418. var
  419.   M: TUnmarshalProc;
  420. begin
  421.   Result := False;
  422.   try
  423.     TMethod(M).Code := Self.MethodAddress(Operation);
  424.     if TMethod(M).Code = nil then Exit;
  425.     TMethod(M).Data := Self;
  426.     M(Strm, Cookie);
  427.   except
  428.     Exit;
  429.   end;
  430.   Result := True;
  431. end;
  432.  
  433. { TCorbaStub }
  434.  
  435. constructor TCorbaStub.Create(const Stub: IStub);
  436. begin
  437.   inherited Create;
  438.   FStub := Stub;
  439. end;
  440.  
  441. destructor TCorbaStub.Destroy;
  442. begin
  443.   try
  444.     FStub := nil;
  445.   except
  446.     // Ignore exceptions when disconnecting
  447.   end;
  448.   inherited Destroy;
  449. end;
  450.  
  451. procedure TCorbaStub.GetStub(out Stub :IStub); stdcall;
  452. begin
  453.   Stub := FStub;
  454. end;
  455.  
  456. function TCorbaStub.Hash(Maximum: Integer): Integer;
  457. begin
  458.   Result := Integer(FStub.Hash(CorbaULong(Maximum)));
  459. end;
  460.  
  461. function TCorbaStub.IsA(const LogicalTypeId: string): Boolean;
  462. begin
  463.   Result := FStub.IsA(Pointer(LogicalTypeId));
  464. end;
  465.  
  466. function TCorbaStub.NonExistent: Boolean;
  467. begin
  468.   Result := FStub.NonExistent;
  469. end;
  470.  
  471. procedure TCorbaStub.SetPrincipal(const Prinicpal: TCorbaPrincipal);
  472. begin
  473.   FStub.SetPrincipal(@Prinicpal[0], High(Prinicpal) + 1);
  474. end;
  475.  
  476. { TCorbaDispatchStub }
  477.  
  478. const
  479.   E_NOTIMPL = HResult($80004001);
  480.  
  481. function TCorbaDispatchStub.GetIDsOfNames(const IID: TGUID; Names: Pointer;
  482.       NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
  483. begin
  484.   Result := E_NOTIMPL;
  485. end;
  486.  
  487. function TCorbaDispatchStub.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult;
  488. begin
  489.   Result := E_NOTIMPL;
  490. end;
  491.  
  492. function TCorbaDispatchStub.GetTypeInfoCount(out Count: Integer): HResult;
  493. begin
  494.   Result := E_NOTIMPL;
  495. end;
  496.  
  497. function TCorbaDispatchStub.Invoke(DispID: Integer; const IID: TGUID;
  498.   LocaleID: Integer; Flags: Word; var Params;
  499.   VarResult, ExcepInfo, ArgErr: Pointer): HResult;
  500. begin
  501.   Result := E_NOTIMPL;
  502. end;
  503.  
  504. { TCorbaListManager }
  505.  
  506. constructor TCorbaListManager.Create;
  507. begin
  508.   FSync := TMultiReadExclusiveWriteSynchronizer.Create;
  509. end;
  510.  
  511. destructor TCorbaListManager.Destroy;
  512. begin
  513.   FSync.Free;
  514. end;
  515.  
  516. procedure TCorbaListManager.BeginRead;
  517. begin
  518.   FSync.BeginRead;
  519. end;
  520.  
  521. procedure TCorbaListManager.BeginWrite;
  522. begin
  523.   FSync.BeginWrite;
  524. end;
  525.  
  526. procedure TCorbaListManager.EndRead;
  527. begin
  528.   FSync.EndRead;
  529. end;
  530.  
  531. procedure TCorbaListManager.EndWrite;
  532. begin
  533.   FSync.EndWrite;
  534. end;
  535.  
  536. { TCorbaInterfaceIDManager }
  537.  
  538. function TCorbaInterfaceIDManager.FindID(const IID: TGUID): string;
  539. begin
  540.   if not SearchID(IID, Result) then
  541.     raise ECorbaException.CreateRes(@SCorbaInterfaceIDNotRegister);
  542. end;
  543.  
  544. function TCorbaInterfaceIDManager.FindGUID(const RepositoryID: string): TGUID;
  545. begin
  546.   if not SearchGUID(RepositoryID, Result) then
  547.     raise ECorbaException.CreateResFmt(@SCorbaRepositoryIDNotRegistered, [RepositoryID]);
  548. end;
  549.  
  550. procedure TCorbaInterfaceIDManager.RegisterInterface(const IID: TGUID;
  551.   const RepositoryID: string);
  552. var
  553.   L: Integer;
  554. begin
  555.   BeginWrite;
  556.   try
  557.     L := Length(FList);
  558.     if FUsed = L then
  559.     begin
  560.       if L = 0 then L := 8 else L := L * 2;
  561.       SetLength(FList, L);
  562.     end;
  563.     FList[FUsed].IID := IID;
  564.     FList[FUsed].RepositoryID := RepositoryID;
  565.     Inc(FUsed);
  566.   finally
  567.     EndWrite;
  568.   end;
  569. end;
  570.  
  571. function TCorbaInterfaceIDManager.SearchGUID(const RepositoryID: string;
  572.   out IID: TGUID): Boolean;
  573. var
  574.   I: Integer;
  575. begin
  576.   BeginRead;
  577.   try
  578.     for I := 0 to FUsed - 1 do
  579.       if FList[I].RepositoryID = RepositoryID then
  580.       begin
  581.         IID := FList[I].IID;
  582.         Result := True;
  583.         Exit;
  584.       end;
  585.   finally
  586.     EndRead;
  587.   end;
  588.   Result := False;
  589. end;
  590.  
  591. function TCorbaInterfaceIDManager.SearchID(const IID: TGUID;
  592.   out RepositoryID: string): Boolean;
  593. var
  594.   I: Integer;
  595. begin
  596.   BeginRead;
  597.   try
  598.     for I := 0 to FUsed - 1 do
  599.       if IsEqualGUID(FList[I].IID, IID) then
  600.       begin
  601.         RepositoryID := FList[I].RepositoryID;
  602.         Result := True;
  603.         Exit;
  604.       end;
  605.   finally
  606.     EndRead;
  607.   end;
  608.   Result := False;
  609. end;
  610.  
  611. { TCorbaSkeletonManager }
  612.  
  613. procedure TCorbaSkeletonManager.RegisterSkeleton(IID: TGUID;
  614.   Skeleton: TCorbaSkeletonClass);
  615. var
  616.   L: Integer;
  617. begin
  618.   BeginWrite;
  619.   try
  620.     L := Length(FList);
  621.     if FUsed = L then
  622.     begin
  623.       if L = 0 then L := 8 else L := L * 2;
  624.       SetLength(FList, L);
  625.     end;
  626.     FList[FUsed].IID := IID;
  627.     FList[FUsed].SkeletonClass := Skeleton;
  628.     Inc(FUsed);
  629.   finally
  630.     EndWrite;
  631.   end;
  632. end;
  633.  
  634. function TCorbaSkeletonManager.CreateSkeleton(IID: TGUID;
  635.   const InstanceName: string; const Impl: IObject): ISkeletonObject;
  636. var
  637.   I: Integer;
  638. begin
  639.   BeginRead;
  640.   try
  641.     for I := 0 to FUsed - 1 do
  642.       if IsEqualGUID(FList[I].IID, IID) then
  643.       begin
  644.         Result := FList[I].SkeletonClass.Create(InstanceName, Impl);
  645.         Exit;
  646.       end;
  647.   finally
  648.     EndRead;
  649.   end;
  650.   raise Exception.CreateResFmt(@SCorbaSkeletonNotRegistered, [InstanceName]);
  651. end;
  652.  
  653. { TCorbaStubManager }
  654.  
  655. procedure TCorbaStubManager.RegisterStub(IID: TGUID; Stub: TCorbaStubClass);
  656. var
  657.   L: Integer;
  658. begin
  659.   BeginWrite;
  660.   try
  661.     L := Length(FList);
  662.     if FUsed = L then
  663.     begin
  664.       if L = 0 then L := 8 else L := L * 2;
  665.       SetLength(FList, L);
  666.     end;
  667.     FList[FUsed].IID := IID;
  668.     FList[FUsed].StubClass := Stub;
  669.     Inc(FUsed);
  670.   finally
  671.     EndWrite;
  672.   end;
  673. end;
  674.  
  675. function TCorbaStubManager.CreateStub(IID: TGUID; const Stub: IStub): IObject;
  676. var
  677.   I: Integer;
  678. begin
  679.   BeginRead;
  680.   try
  681.     for I := 0 to FUsed - 1 do
  682.       if IsEqualGUID(FList[I].IID, IID) then
  683.       begin
  684.         Result := FList[I].StubClass.Create(Stub);
  685.         Exit;
  686.       end;
  687.   finally
  688.     EndRead;
  689.   end;
  690.   raise Exception.CreateRes(@SCorbaStubNotRegistered);
  691. end;
  692.  
  693. { TCorbaImplementation }
  694.  
  695. constructor TCorbaImplementation.Create(Controller: IObject; AFactory: TCorbaFactory);
  696. begin
  697.   inherited Create;
  698.   FFactory := AFactory;
  699.   FController := Pointer(Controller);
  700. end;
  701.  
  702. function TCorbaImplementation._AddRef: Integer;
  703. begin
  704.   if Assigned(FController) then
  705.     Result := IObject(FController)._AddRef else
  706.     Result := ObjAddRef;
  707. end;
  708.  
  709. function TCorbaImplementation._Release: Integer;
  710. begin
  711.   if Assigned(FController) then
  712.     Result := IObject(FController)._Release else
  713.     Result := ObjRelease;
  714. end;
  715.  
  716. function TCorbaImplementation.ObjAddRef: Integer;
  717. begin
  718.   Result := InterlockedIncrement(FRefCount);
  719. end;
  720.  
  721. function TCorbaImplementation.ObjQueryInterface(const IID: TGUID;
  722.   out Obj): HResult;
  723. begin
  724.   if GetInterface(IID, Obj) then Result := S_OK else Result := E_NOINTERFACE;
  725. end;
  726.  
  727. function TCorbaImplementation.ObjRelease: Integer;
  728. begin
  729.   Result := InterlockedDecrement(FRefCount);
  730.   if Result = 0 then Destroy;
  731. end;
  732.  
  733. function TCorbaImplementation.QueryInterface(const IID: TGUID;
  734.   out Obj): HResult;
  735. begin
  736.   if Assigned(FController) then
  737.     Result := IObject(FController).QueryInterface(IID, Obj) else
  738.     Result := ObjQueryInterface(IID, Obj);
  739. end;
  740.  
  741. function TCorbaImplementation.GetIDsOfNames(const IID: TGUID;
  742.   Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
  743. begin
  744.   Result := E_NOTIMPL;
  745. end;
  746.  
  747. function TCorbaImplementation.GetTypeInfo(Index, LocaleID: Integer;
  748.   out TypeInfo): HResult;
  749. begin
  750.   Result := FFactory.GetTypeInfo(TypeInfo);
  751. end;
  752.  
  753. function TCorbaImplementation.GetTypeInfoCount(
  754.   out Count: Integer): HResult;
  755. begin
  756.   Count := 1;
  757.   Result := S_OK;
  758. end;
  759.  
  760. function TCorbaImplementation.Invoke(DispID: Integer; const IID: TGUID;
  761.   LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
  762.   ArgErr: Pointer): HResult;
  763. begin
  764.   Result := E_NOTIMPL;
  765. end;
  766.  
  767. { TCorbaFactory }
  768.  
  769. constructor TCorbaFactory.Create(const InterfaceName, InstanceName,
  770.   RepositoryId: string; const ImplGUID: TGUID;
  771.   Instancing: TCorbaInstancing;
  772.   ThreadModel: TCorbaThreadModel);
  773. begin
  774.   inherited Create;
  775.   FIID := ImplGUID;
  776.   FInterfaceName := InterfaceName;
  777.   FInstanceName := InstanceName;
  778.   FRepositoryId := RepositoryId;
  779.   FInstancing := Instancing;
  780.   FThreadModel := ThreadModel;
  781.   CorbaFactoryManager.AddFactory(Self);
  782. end;
  783.  
  784. destructor TCorbaFactory.Destroy;
  785. begin
  786.   FSkeleton := nil;
  787.   inherited Destroy;
  788. end;
  789.  
  790. procedure TCorbaFactory.GetSkeleton(out Skeleton: ISkeleton);
  791. begin
  792.   Skeleton := FSkeleton;
  793. end;
  794.  
  795. procedure TCorbaFactory.GetImplementation(out Impl: IObject);
  796. begin
  797.   impl := nil;
  798. end;
  799.  
  800. function TCorbaFactory.Execute(Operation: PChar; const Strm: IMarshalInBuffer;
  801.  Cookie: Pointer): CorbaBoolean;
  802. var
  803.   InstanceName: string;
  804.   OutBuff: IMarshalOutBuffer;
  805.   Skeleton: ISkeleton;
  806. begin
  807.   Result := False;
  808.   if CompareStr(Operation, 'CreateInstance') <> 0 then Exit;
  809.   InstanceName := UnmarshalText(Strm);
  810.   if FSingleInstanceSkelton <> nil then
  811.     with FSingleInstanceSkelton do
  812.     begin
  813.       _AddRef;
  814.       GetSkeleton(Skeleton);
  815.     end
  816.   else
  817.     with CreateInstance(InstanceName) do
  818.       GetSkeleton(Skeleton);
  819.   FSkeleton.GetReplyBuffer(Cookie, OutBuff);
  820.   OutBuff.PutObject(Skeleton);
  821.   Result := True;
  822. end;
  823.  
  824. procedure TCorbaFactory.RegisterFactory;
  825. begin
  826.   CreateSkeleton(PChar(Pointer(FInterfaceName)), Self, True,
  827.     PChar(Pointer(FInstanceName)), PChar(Pointer(FRepositoryId)), False,
  828.     FSkeleton);
  829.   BOA.ObjIsReady(FSkeleton);
  830.   if FInstancing = iSingleInstance then
  831.     FSingleInstanceSkelton := CreateInstance('');
  832. end;
  833.  
  834. function TCorbaFactory.CreateInstance(const InstanceName: string): ISkeletonObject;
  835. var
  836.   Intf: IObject;
  837. begin
  838.   Intf := CreateInterface(InstanceName);
  839.   Result := CorbaSkeletonManager.CreateSkeleton(FIID, InstanceName, Intf);
  840.   if Assigned(Result) then Result._AddRef;
  841. end;
  842.  
  843. function TCorbaFactory.CreateInterface(const InstanceName: string): IObject;
  844. begin
  845.   raise ECorbaException.CreateRes(@SCorbaIncompleteFactory);
  846. end;
  847.  
  848. function TCorbaFactory.GetTypeInfo(out TypeInfo): HRESULT;
  849. var
  850.   TypeLib: ITypeLib;
  851.   Buffer: array[0..261] of Char;
  852. begin
  853.   if not Assigned(FTypeInfo) then
  854.   begin
  855.     Windows.GetModuleFileName(HInstance, Buffer, SizeOf(Buffer));
  856.     Result := LoadTypeLib(PWideChar(WideString(Buffer)), TypeLib);
  857.     if Result <> S_OK then Exit;
  858.     Result := TypeLib.GetTypeInfoOfGUID(FIID, FTypeInfo);
  859.     if Result <> S_OK then Exit;
  860.   end;
  861.   ITypeInfo(TypeInfo) := FTypeInfo;
  862.   Result := S_OK;
  863. end;
  864.  
  865. { TCorbaFactoryManager }
  866.  
  867. destructor TCorbaFactoryManager.Destroy;
  868. var
  869.   I: Integer;
  870. begin
  871.   for I := 0 to FUsed - 1 do FList[I].Free;
  872.   inherited Destroy;
  873. end;
  874.  
  875. procedure TCorbaFactoryManager.AddFactory(Factory: TCorbaFactory);
  876. var
  877.   L: Integer;
  878. begin
  879.   BeginWrite;
  880.   try
  881.     L := Length(FList);
  882.     if FUsed = L then
  883.     begin
  884.       if L = 0 then L := 8 else L := L * 2;
  885.       SetLength(FList, L);
  886.     end;
  887.     FList[FUsed] := Factory;
  888.     Inc(FUsed);
  889.   finally
  890.     EndWrite;
  891.   end;
  892.   if FRegistered then Factory.RegisterFactory;
  893. end;
  894.  
  895. procedure TCorbaFactoryManager.RegisterFactories;
  896. var
  897.   DoRegister: Boolean;
  898.   Used: Integer;
  899.   I: Integer;
  900. begin
  901.   if not FRegistered then
  902.   begin
  903.     // Assumes only adding of factories are possible.
  904.     // If removing is possilbe the Read/Write blocks need to be nested.
  905.     BeginWrite;
  906.     try
  907.       Used := FUsed;
  908.       DoRegister := not FRegistered;
  909.       FRegistered := True;
  910.     finally
  911.       EndWrite;
  912.     end;
  913.     if DoRegister then
  914.     begin
  915.       BeginRead;
  916.       try
  917.         for I := 0 to Used - 1 do FList[I].RegisterFactory;
  918.       finally
  919.         EndRead;
  920.       end;
  921.     end;
  922.   end;
  923. end;
  924.  
  925. function TCorbaFactoryManager.Find(const RepositoryID, InterfaceName,
  926.   InstanceName: string): TCorbaFactory;
  927. var
  928.   I: Integer;
  929. begin
  930.   if (InterfaceName <> '') or (RepositoryID <> '') then
  931.   begin
  932.     BeginRead;
  933.     try
  934.       for I := 0 to FUsed - 1 do
  935.       begin
  936.         Result := FList[I];
  937.         if ((RepositoryID = '') or (RepositoryID = Result.RepositoryID)) and
  938.           ((InterfaceName = '') or (InterfaceName = Result.InterfaceName)) and
  939.           ((InstanceName = '') or (InstanceName = Result.InstanceName)) then
  940.           Exit;
  941.       end;
  942.       Result := nil;
  943.     finally
  944.       EndRead;
  945.     end;
  946.   end
  947.   else Result := nil;
  948. end;
  949.  
  950. { TCorbaObjectFactory }
  951.  
  952. constructor TCorbaObjectFactory.Create(const InterfaceName, InstanceName,
  953.   RepositoryId: string; const ImplGUID: TGUID;
  954.   ImplementationClass: TCorbaImplementationClass;
  955.   Instancing: TCorbaInstancing; ThreadModel: TCorbaThreadModel);
  956. begin
  957.   inherited Create(InterfaceName, InstanceName, RepositoryID, ImplGUID,
  958.     Instancing, ThreadModel);
  959.   FImplementationClass := ImplementationClass;
  960. end;
  961.  
  962. function TCorbaObjectFactory.CreateInterface(const InstanceName: string): IObject;
  963. begin
  964.   Result := FImplementationClass.Create(nil, Self);
  965. end;
  966.  
  967. { TBOA }
  968.  
  969. class procedure TBOA.Initialize(const CommandLine: TCommandLine);
  970. begin
  971.   if CorbaObj.BOAVar = nil then
  972.   begin
  973.     CorbaObj.BOAVar := TBOA.Create;
  974.     CorbaObj.ORBVar.ORB.BOAInit(Length(CommandLine), CommandLine, CorbaObj.BOAVar.BOA);
  975.   end;
  976. end;
  977.  
  978. function TBOA.GetPrincipal(const Obj: IObject): TCorbaPrincipal;
  979. var
  980.   Length: Integer;
  981.   Skeleton: ISkeleton;
  982. begin
  983.   if Obj.QueryInterface(ISkeleton, Skeleton) <> S_OK then
  984.     (Obj as ISkeletonObject).GetSkeleton(Skeleton);
  985.   Length := BOA.GetPrincipalLength(Skeleton);
  986.   SetLength(Result, Length);
  987.   BOA.GetPrincipal(Skeleton, @Result[0]);
  988. end;
  989.  
  990. procedure TBOA.Deactivate(const Obj: IObject);
  991. begin
  992.   BOA.Deactivate(Obj as ISkeleton);
  993. end;
  994.  
  995. procedure TBOA.ImplIsReady;
  996. begin
  997.   BOA.ImplIsReady;
  998. end;
  999.  
  1000. procedure TBOA.ObjIsReady(const Obj: IObject);
  1001. begin
  1002.   BOA.ObjIsReady(Obj as ISkeleton);
  1003. end;
  1004.  
  1005. { TORB }
  1006. class procedure TORB.Initialize(const CommandLine: TCommandLine);
  1007. begin
  1008.   CorbaObj.ORBVar := TORB.Create;
  1009.   InitORB(CommandLine, CorbaObj.ORBVar.ORB);
  1010. end;
  1011.  
  1012. class procedure TORB.Initialize;
  1013. var
  1014.   CommandLine: TCommandLine;
  1015.   I: Integer;
  1016. begin
  1017.   if CorbaObj.ORBVar = nil then
  1018.   begin
  1019.     SetLength(CommandLine, ParamCount + 1);
  1020.     for I := 0 to ParamCount do CommandLine[I] := ParamStr(I);
  1021.     Initialize(CommandLine);
  1022.     if BOAVar = nil then TBOA.Initialize(CommandLine);
  1023.   end;
  1024. end;
  1025.  
  1026. function InternalBind(const RepositoryID, ObjectName, HostName: string): IStub;
  1027. begin
  1028.   BindStub(PChar(Pointer(RepositoryID)), PChar(Pointer(ObjectName)),
  1029.     PChar(Pointer(HostName)), ORB.ORB,
  1030.     False, Result)
  1031. end;
  1032.  
  1033. function TORB.Bind(const InterfaceID: TGUID; const ObjectName,
  1034.   HostName: string): IObject;
  1035. begin
  1036.   Result := CorbaStubManager.CreateStub(InterfaceID,
  1037.     InternalBind(CorbaInterfaceIDManager.FindID(InterfaceID),
  1038.     ObjectName, HostName));
  1039. end;
  1040.  
  1041. function TORB.Bind(const RepositoryID, ObjectName, HostName: string): IObject;
  1042. var
  1043.   Stub: IStub;
  1044.   IID: TGUID;
  1045. begin
  1046.   Stub := InternalBind(RepositoryID, ObjectName, HostName);
  1047.   if not CorbaInterfaceIDManager.SearchGUID(RepositoryID, IID) then
  1048.     IID := IStub;
  1049.   Result := CorbaStubManager.CreateStub(IID, Stub);
  1050. end;
  1051.  
  1052. function TORB.ObjectToString(const Obj: IObject): string;
  1053. var
  1054.   Stub: IStub;
  1055.   P: PChar;
  1056. begin
  1057.   if Obj.QueryInterface(IStub, Stub) <> S_OK then
  1058.     (Obj as IStubObject).GetStub(Stub);
  1059.   P := ORB.ObjectToString(Stub);
  1060.   Result := P;
  1061.   CorbaStringFree(P);
  1062. end;
  1063.  
  1064. function TORB.StringToObject(const ObjectString: string): IObject;
  1065. var
  1066.   Stub: IStub;
  1067.   ID: PChar;
  1068. begin
  1069.   ORB.StringToObject(PChar(Pointer(ObjectString)), Stub);
  1070.   if Stub = nil then
  1071.     Result := nil
  1072.   else
  1073.   begin
  1074.     ID := Stub.RepositoryID;
  1075.     try
  1076.       Result := CorbaStubManager.CreateStub(CorbaInterfaceIDManager.FindGUID(ID), Stub);
  1077.     finally
  1078.       CorbaStringFree(ID);
  1079.     end;
  1080.   end;
  1081. end;
  1082.  
  1083. procedure TORB.Shutdown;
  1084. begin
  1085.   ORB.Shutdown;
  1086. end;
  1087.  
  1088. { Dynamic invocation helper methods }
  1089.  
  1090. function TORB.FindTypeCode(const RepositoryID: string): ITypeCode;
  1091. begin
  1092.   ORB.FindRepositoryTC(PChar(RepositoryID), Result);
  1093. end;
  1094.  
  1095. function TORB.MakeArray(Kind: TCKind; const Elements: array of TAny): TAny;
  1096. var
  1097.   TC: ITypeCode;
  1098. begin
  1099.   ORB.CreateTC(Kind, TC);
  1100.   Result := MakeArray(TC, Elements);
  1101. end;
  1102.  
  1103. function TORB.MakeArray(TypeCode: ITypeCode; const Elements: array of TAny): TAny;
  1104. begin
  1105.   Result := MakeComplexAny(TypeCode, Elements);
  1106. end;
  1107.  
  1108. function TORB.MakeSequence(Kind: TCKind; const Elements: array of TAny): TAny;
  1109. var
  1110.   TC: ITypeCode;
  1111. begin
  1112.   ORB.CreateTC(Kind, TC);
  1113.   Result := MakeSequence(TC, Elements);
  1114. end;
  1115.  
  1116. function TORB.MakeSequence(TypeCode: ITypeCode; const Elements: array of TAny): TAny;
  1117. begin
  1118.   Result := MakeComplexAny(TypeCode, Elements);
  1119. end;
  1120.  
  1121. const
  1122.   reVarNotArray       = 19;
  1123.  
  1124. function GetVarArray(const A: Variant): PSafeArray;
  1125. begin
  1126.   if TVarData(A).VType and varArray = 0 then RunError(reVarNotArray);
  1127.   if TVarData(A).VType and varByRef <> 0 then
  1128.     Result := PSafeArray(TVarData(A).VPointer^) else
  1129.     Result := PSafeArray(TVarData(A).VArray);
  1130. end;
  1131.  
  1132. function TORB.MakeStructure(TypeCode: ITypeCode; const Elements: array of TAny): TAny;
  1133. begin
  1134.   Result := MakeComplexAny(TypeCode, Elements);
  1135. end;
  1136.  
  1137. function TORB.MakeAlias(const RepositoryID, TypeName: string; Value, Test: TAny): TAny;
  1138. var
  1139.   Temp: Variant;
  1140.   TC, TC2: ITypeCode;
  1141. begin
  1142.   TVarData(Temp).VAny := CorbaDuplicateAny(VariantToAny(@Value));
  1143.   TVarData(Temp).VType := varAny;
  1144.   CorbaAnyType(TVarData(Temp).VAny, TC);
  1145.   ORB.CreateAliasTC(PChar(Pointer(RepositoryID)), PChar(Pointer(TypeName)),
  1146.     TC, TC2);
  1147.   TVarData(Result).VAny := ORB.MakeAny(TC2, [Temp]);
  1148.   TVarData(Result).VType := varAny;
  1149. end;
  1150.  
  1151. function TORB.MakeTypeCode(Kind: TCKind): ITypeCode;
  1152. begin
  1153.   ORB.CreateTC(Kind, Result);
  1154. end;
  1155.  
  1156. function TORB.MakeSequenceTypeCode(Bound: CorbaULong; const TC: ITypeCode): ITypeCode;
  1157. begin
  1158.   ORB.CreateSequenceTC(Bound, TC, Result);
  1159. end;
  1160.  
  1161. function TORB.MakeStructureTypeCode(const RepositoryID, Name: string; Members: TStructMembers): ITypeCode;
  1162. begin
  1163.   ORB.CreateStructTC(tk_struct, PChar(Pointer(RepositoryID)), PChar(Pointer(Name)),
  1164.     Members, Length(Members), Result);
  1165. end;
  1166.  
  1167. function TORB.MakeAliasTypeCode(const RepositoryID, Name: string; const TC: ITypeCode): ITypeCode;
  1168. begin
  1169.   ORB.CreateAliasTC(PChar(Pointer(RepositoryID)), PChar(Pointer(Name)), TC, Result);
  1170. end;
  1171.  
  1172. function TORB.MakeObjectRefTypeCode(const RepositoryID, Name: string): ITypeCode;
  1173. begin
  1174.   ORB.CreateObjRefTC(PChar(Pointer(RepositoryID)), PChar(Pointer(Name)), Result);
  1175. end;
  1176.  
  1177. function TORB.MakeComplexAny(TypeCode: ITypeCode; const Elements: array of TAny): TAny;
  1178. begin
  1179.   TVarData(Result).VType := varAny;
  1180.   TVarData(Result).VAny := ORB.MakeAny(TypeCode, Elements);
  1181. end;
  1182.  
  1183. function VariantArrayToSequence(TypeCode: ITypeCode; const VariantArray: Variant): TAny;
  1184. type
  1185.   PAnyArray = ^TAnyArray;
  1186.   TAnyArray = array[0..100] of TAny;
  1187. var
  1188.   P: PAnyArray;
  1189.   I, C: Integer;
  1190. begin
  1191.   if TVarData(VariantArray).VType <> varVariant or varArray then
  1192.     raise ECorbaDispatch.Create(sInvalidTypeCast)
  1193.   else
  1194.   begin
  1195.     I := VarArrayLowBound(VariantArray, 1);
  1196.     C := VarArrayHighBound(VariantArray, 1) - I + 1;
  1197.     if SafeArrayPtrOfIndex(GetVarArray(VariantArray), I, Pointer(P)) <> 0 then
  1198.       raise ECorbaDispatch.Create(sInvalidTypeCast);
  1199.     Result := ORB.MakeComplexAny(TypeCode, Slice(PAnyArray(P)^, C));
  1200.   end;
  1201. end;
  1202.  
  1203. function SequenceToVariantArray(Sequence: TAny): Variant;
  1204. begin
  1205.   if (TVarData(Sequence).VType and varArray <> 0) then
  1206.     Result := Sequence
  1207.   else if (TVarData(Sequence).VType <> varAny) or
  1208.     not SequenceToVariant(PCorbaAny(TVarData(Sequence).VPointer), @Result) then
  1209.     raise ECorbaDispatch.Create(sInvalidTypeCast);
  1210. end;
  1211.  
  1212. function AnyToObject(Any: TAny; IID: TGUID): IObject;
  1213. var
  1214.   Unk: IUnknown;
  1215.   Obj: ICorbaObj;
  1216. begin
  1217.   Unk := Any;
  1218.   Obj := Unk as ICorbaObj;
  1219.   if Obj.IsLocal then
  1220.     with Obj as ISkeleton do
  1221.       GetImplementation(Result)
  1222.   else
  1223.     Result := CorbaStubManager.CreateStub(IID, Obj as IStub);
  1224. end;
  1225.  
  1226. { Marshalling methods }
  1227.  
  1228. procedure MarshalObject(const OutBuf: IMarshalOutBuffer; IID: TGUID;
  1229.   const Intf: IObject);
  1230. var
  1231.   StubObject: IStubObject;
  1232.   Stub: IStub;
  1233.   Skeleton: ISkeleton;
  1234. begin
  1235.   if Intf = nil then
  1236.   begin
  1237.     OutBuf.PutObject(nil);
  1238.     Exit;
  1239.   end;
  1240.   if Intf.QueryInterface(IStubObject, StubObject) = 0 then
  1241.   begin
  1242.     StubObject.GetStub(Stub);
  1243.     OutBuf.PutObject(Stub);
  1244.   end
  1245.   else
  1246.   begin
  1247.     with CorbaSkeletonManager.CreateSkeleton(IID, '', Intf) do
  1248.     begin
  1249.       _AddRef;
  1250.       GetSkeleton(Skeleton);
  1251.     end;
  1252.     OutBuf.PutObject(Skeleton);
  1253.   end;
  1254. end;
  1255.  
  1256. function UnmarshalObject(const InBuf: IMarshalInBuffer; IID: TGUID): IObject;
  1257. var
  1258.   Obj: ICorbaObj;
  1259. begin
  1260.   InBuf.GetObject(Obj);
  1261.   if Obj = nil then
  1262.   begin
  1263.     Result := nil;
  1264.     Exit;
  1265.   end;
  1266.   if Obj.IsLocal then
  1267.     with Obj as ISkeleton do
  1268.       GetImplementation(Result)
  1269.   else
  1270.     Result := CorbaStubManager.CreateStub(IID, Obj as IStub);
  1271. end;
  1272.  
  1273. procedure MarshalAny(const OutBuf: IMarshalOutBuffer; const OV: Variant);
  1274. var
  1275.   Temp: PCorbaAny;
  1276. begin
  1277.   Temp := VariantToAny(@OV);
  1278.   try
  1279.     OutBuf.PutAny(Temp);
  1280.   finally
  1281.     CorbaReleaseAny(Temp)
  1282.   end;
  1283. end;
  1284.  
  1285. function UnmarshalAny(const InBuf: IMarshalInBuffer): Variant;
  1286. var
  1287.   Temp: PCorbaAny;
  1288. begin
  1289.   Temp := InBuf.GetAny;
  1290.   try
  1291.     if not AnyToVariant(Temp, @Result) then
  1292.     begin
  1293.       TVarData(Result).VType := varAny;
  1294.       TVarData(Result).VAny := CorbaDuplicateAny(Temp);
  1295.       Exit;
  1296.     end
  1297.   finally
  1298.     CorbaReleaseAny(Temp);
  1299.   end;
  1300. end;
  1301.  
  1302. function UnmarshalText(const InBuf: IMarshalInBuffer): string;
  1303. var
  1304.   Temp: PChar;
  1305. begin
  1306.   Temp := InBuf.GetText;
  1307.   if (Temp <> nil) and (Temp[0] = #0) then
  1308.     Result := ''
  1309.   else
  1310.     Result := Temp;
  1311.   CorbaStringFree(Temp);
  1312. end;
  1313.  
  1314. function UnmarshalWideText(const InBuf: IMarshalInBuffer): WideString;
  1315. var
  1316.   Temp: PWideChar;
  1317. begin
  1318.   Temp := InBuf.GetWideText;
  1319.   Result := Temp;
  1320.   CorbaWStringFree(Temp);
  1321. end;
  1322.  
  1323. procedure MarshalWordBool(const OutBuf: IMarshalOutBuffer; Value: WordBool);
  1324. begin
  1325.   if Value then
  1326.     OutBuf.PutUnsignedChar(1)
  1327.   else
  1328.     OutBuf.PutUnsignedChar(0);
  1329. end;
  1330.  
  1331. function UnmarshalWordBool(const InBuf: IMarshalInBuffer): WordBool;
  1332. begin
  1333.   Result := InBuf.GetUnsignedChar <> 0;
  1334. end;
  1335.  
  1336. function CorbaFactoryCreateStub(const RepId, FactoryId, InstanceName, HostName: string;
  1337.   IID: TGUID): IObject;
  1338. var
  1339.   Factory: IStub;
  1340.   OutBuf: IMarshalOutBuffer;
  1341.   InBuf: IMarshalInBuffer;
  1342.   Obj: ICorbaObj;
  1343. begin
  1344.   BindStub(PChar(Pointer(RepId)), PChar(Pointer(FactoryId)),
  1345.     PChar(Pointer(HostName)), ORB.ORB, False, Factory);
  1346.   Factory.CreateRequest('CreateInstance', True, OutBuf);
  1347.   OutBuf.PutText(PChar(Pointer(InstanceName)));
  1348.   Factory.Invoke(OutBuf, InBuf);
  1349.   InBuf.GetObject(Obj);
  1350.   Result := CorbaStubManager.CreateStub(IID, Obj as IStub);
  1351. end;
  1352.  
  1353. procedure CorbaHookDispatch; forward;
  1354. procedure CorbaHookExceptions; forward;
  1355.  
  1356. function ORB: TORB;
  1357. begin
  1358.   if not Assigned(ORBVar) then
  1359.     CorbaInitialize;
  1360.   Result := ORBVar;
  1361. end;
  1362.  
  1363. function BOA: TBOA;
  1364. begin
  1365.   if not Assigned(BOAVar) then
  1366.     CorbaInitialize;
  1367.   Result := BOAVar;
  1368. end;
  1369.  
  1370. procedure CorbaInitialize;
  1371. const
  1372.   Initialized: Boolean = False;
  1373. begin
  1374.   if Initialized then Exit;
  1375.   Initialized := True;
  1376.   TORB.Initialize;
  1377.   CorbaFactoryManager.RegisterFactories;
  1378.   CorbaHookDispatch;
  1379.   CorbaHookExceptions;
  1380. end;
  1381.  
  1382. function CorbaBind(const RepositoryID: string; const ObjectName: string = '';
  1383.   const HostName: string = ''): IObject;
  1384. begin
  1385.   Result := ORB.Bind(RepositoryID, ObjectName, HostName);
  1386. end;
  1387.  
  1388. function CorbaBind(const InterfaceID: TGUID; const ObjectName: string = '';
  1389.   const HostName: string = ''): IObject;
  1390. begin
  1391.   Result := ORB.Bind(InterfaceID, ObjectName, HostName);
  1392. end;
  1393.  
  1394. function MakePrincipal(const Bytes: array of Byte): TCorbaPrincipal;
  1395. begin
  1396.   SetLength(Result, High(Bytes) + 1);
  1397.   Move(Bytes[0], Result[0], High(Bytes) + 1);
  1398. end;
  1399.  
  1400. { CORBA Dispatch }
  1401.  
  1402. var
  1403.   OldVarDispProc: Pointer;
  1404.  
  1405. procedure ClearAnyImpl(var V: Variant);
  1406. var
  1407.   P: Pointer;
  1408. begin
  1409.   if TVarData(V).VType = varAny then
  1410.   begin
  1411.     TVarData(V).VType := varEmpty;
  1412.     P := TVarData(V).VAny;
  1413.     if P <> nil then CorbaReleaseAny(P);
  1414.   end;
  1415. end;
  1416.  
  1417. procedure ChangeAnyImpl(var V: Variant);
  1418. var
  1419.   Tmp: Variant;
  1420. begin
  1421.   if TVarData(V).VType = varAny then
  1422.   begin
  1423.     if not AnyToVariant(PCorbaAny(TVarData(V).VAny), @Tmp) then
  1424.       raise ECorbaDispatch.Create(sInvalidTypeCast);
  1425.     V := Tmp;
  1426.   end;
  1427. end;
  1428.  
  1429. procedure RefAnyImpl(var V: Variant);
  1430. begin
  1431.   CorbaDuplicateAny(TVarData(V).VAny);
  1432. end;
  1433.  
  1434. procedure CorbaStructDispatch(Result: PVariant; const Instance: Variant;
  1435.   CallDesc: PCallDesc; Params: Pointer); cdecl; forward;
  1436. procedure CorbaObjectDispatch(Result: PVariant; const Instance: Variant;
  1437.   CallDesc: PCallDesc; Params: Pointer); cdecl; forward;
  1438.  
  1439. {$W-}
  1440. procedure CorbaDispProc;
  1441. asm
  1442.     MOV     EAX,[ESP+$8]
  1443.     CMP     [EAX].TVarData.VType,varAny
  1444.     JE      CorbaStructDispatch
  1445.     CMP     [EAX].TVarData.VType,varUnknown
  1446.     JE      CorbaObjectDispatch
  1447.     JMP     OldVarDispProc
  1448. end;
  1449.  
  1450. procedure CorbaDispatchError(Result: Integer; CallDesc: PCallDesc);
  1451. const
  1452.   NotCorbaObject = 0;
  1453.   InvalidParamCount = $1FFF;
  1454.   MethodNotFound = $1FFE;
  1455.   NoRepository = $1FFD;
  1456. var
  1457.   Msg: string;
  1458.  
  1459.   function MethodName: string;
  1460.   begin
  1461.     Result := PChar(@CallDesc^.ArgTypes[CallDesc^.ArgCount]);
  1462.   end;
  1463.  
  1464. begin
  1465.   case Result of
  1466.     InvalidParamCount: Msg := Format(sInvalidParameterCount, [MethodName]);
  1467.     MethodNotFound: Msg := Format(sMethodNotFound, [MethodName]);
  1468.     NoRepository: Msg := sNoRepository;
  1469.     NotCorbaObject: Msg := sNotCorbaObject;
  1470.   else
  1471.     if Result < 0 then
  1472.       Msg := Format(sParamOut, [-Result, MethodName]) else
  1473.       Msg := Format(sParamTypeCast, [Result, MethodName]);
  1474.   end;
  1475.   raise ECorbaDispatch.Create(Msg);
  1476. end;
  1477.  
  1478. procedure CorbaStructDispatch(Result: PVariant; const Instance: Variant;
  1479.   CallDesc: PCallDesc; Params: Pointer); cdecl;
  1480. var
  1481.   R: Integer;
  1482.   ProcResult: Variant;
  1483. begin
  1484.   if Result = nil then Result := @ProcResult;
  1485.   R := ORB.ORB.DispatchStruct(TVarData(Instance).VAny, CallDesc,
  1486.     @Params, Result^);
  1487.   if R <> 0 then
  1488.     CorbaDispatchError(R, CallDesc)
  1489.   else if CallDesc.CallType = DISPATCH_PROPERTYPUT then
  1490.     PVariant(@Instance)^ := Result^;
  1491. end;
  1492.  
  1493. procedure CorbaObjectDispatch(Result: PVariant; const Instance: Variant;
  1494.   CallDesc: PCallDesc; Params: Pointer); cdecl;
  1495. var
  1496.   U: IUnknown;
  1497.   StubObject: IStubObject;
  1498.   Stub: IStub;
  1499.   R: Integer;
  1500.   ProcResult: Variant;
  1501. begin
  1502.   if Result = nil then Result := @ProcResult;
  1503.   U := IUnknown(Instance);
  1504.   if U.QueryInterface(IStubObject, StubObject) = 0 then
  1505.     StubObject.GetStub(Stub)
  1506.   else if U.QueryInterface(IStub, Stub) <> 0 then
  1507.     CorbaDispatchError(0, CallDesc);
  1508.   R := Stub.Dispatch(CallDesc, @Params, Result^);
  1509.   if R <> 0 then CorbaDispatchError(R, CallDesc);
  1510. end;
  1511.  
  1512. procedure CorbaHookDispatch;
  1513. begin
  1514.   ClearAnyProc := @ClearAnyImpl;
  1515.   ChangeAnyProc := @ChangeAnyImpl;
  1516.   RefAnyProc := @RefAnyImpl;
  1517.   OldVarDispProc := VarDispProc;
  1518.   VarDispProc := @CorbaDispProc;
  1519. end;
  1520.  
  1521. procedure CorbaUnhookDispatch;
  1522. begin
  1523.   if ClearAnyProc = @ClearAnyImpl then
  1524.   begin
  1525.     ClearAnyProc := nil;
  1526.     ChangeAnyProc := nil;
  1527.     RefAnyProc := nil;
  1528.   end;
  1529.   if VarDispProc = @CorbaDispProc then
  1530.     VarDispProc := OldVarDispProc;
  1531. end;
  1532.  
  1533. { Corba exception mapper }
  1534. type
  1535.   TExceptClassProc = function (P: PExceptionRecord): ExceptClass;
  1536.   TExceptObjectProc = function (P: PExceptionRecord): Exception;
  1537.  
  1538. var
  1539.   OldExceptClassProc: TExceptClassProc;
  1540.   OldExceptObjectProc: TExceptObjectProc;
  1541.  
  1542. const
  1543.   cCPPException = $EEFFACE;
  1544.  
  1545. function IsCorba(P: PChar): Boolean;
  1546. begin
  1547.   Result := (P <> nil) and (StrLComp('CORBA_', P, 6) = 0);
  1548. end;
  1549.  
  1550. function CorbaGetExceptClass(P: PExceptionRecord): ExceptClass;
  1551. begin
  1552.   if (P.ExceptionCode = cCPPException) and
  1553.     IsCorba(PChar(P.ExceptionInformation[0])) then
  1554.     Result := ECorbaException else
  1555.     Result := OldExceptClassProc(P);
  1556. end;
  1557.  
  1558. function CorbaGetExceptObject(P: PExceptionRecord): Exception;
  1559. begin
  1560.   if (P.ExceptionCode = cCPPException) and
  1561.     IsCorba(PChar(P.ExceptionInformation[0])) then
  1562.     Result := ECorbaException.Create(PChar(@PChar(P.ExceptionInformation[0])[6])) else
  1563.     Result := OldExceptObjectProc(P);
  1564. end;
  1565.  
  1566. procedure CorbaHookExceptions;
  1567. begin
  1568.   OldExceptClassProc := ExceptClsProc;
  1569.   OldExceptObjectProc := ExceptObjProc;
  1570.   ExceptClsProc := @CorbaGetExceptClass;
  1571.   ExceptObjProc := @CorbaGetExceptObject;
  1572. end;
  1573.  
  1574. procedure CorbaUnhookExceptions;
  1575. begin
  1576.   if ExceptClsProc = @CorbaGetExceptClass then
  1577.   begin
  1578.     ExceptClsProc := @OldExceptClassProc;
  1579.     ExceptObjProc := @OldExceptObjectProc;
  1580.   end;
  1581. end;
  1582.  
  1583. initialization
  1584.   CorbaSkeletonManager := TCorbaSkeletonManager.Create;
  1585.   CorbaStubManager := TCorbaStubManager.Create;
  1586.   CorbaFactoryManager := TCorbaFactoryManager.Create;
  1587.   CorbaInterfaceIDManager := TCorbaInterfaceIDManager.Create;
  1588.   CorbaStubManager.RegisterStub(IStub, TCorbaStub);
  1589.  
  1590. finalization
  1591.   CorbaSkeletonManager.Free;
  1592.   CorbaStubManager.Free;
  1593.   CorbaFactoryManager.Free;
  1594.   CorbaInterfaceIDManager.Free;
  1595.   BOAVar.Free;
  1596.   ORBVar.Free;
  1597.   CorbaUnhookDispatch;
  1598.   CorbaUnhookExceptions;
  1599.  
  1600. end.
  1601.