home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Runimage / Delphi50 / Source / Vcl / SCONNECT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-11  |  63.1 KB  |  2,152 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Borland Delphi Visual Component Library         }
  5. {       Streamed Connection classes                     }
  6. {                                                       }
  7. {       Copyright (c) 1997,99 Inprise Corporation       }
  8. {                                                       }
  9. {*******************************************************}
  10.  
  11. unit SConnect;
  12.  
  13. {$R-}
  14.  
  15. interface
  16.  
  17. uses
  18.   Windows, Messages, Classes, SysUtils, MConnect, ScktComp, WinSock, WinINet;
  19.  
  20. type
  21.  
  22.   { IDataBlock }
  23.  
  24.   IDataBlock = interface(IUnknown)
  25.   ['{CA6564C2-4683-11D1-88D4-00A0248E5091}']
  26.     function GetBytesReserved: Integer; stdcall;
  27.     function GetMemory: Pointer; stdcall;
  28.     function GetSize: Integer; stdcall;
  29.     procedure SetSize(Value: Integer); stdcall;
  30.     function GetStream: TStream; stdcall;
  31.     function GetSignature: Integer; stdcall;
  32.     procedure SetSignature(Value: Integer); stdcall;
  33.     procedure Clear; stdcall;
  34.     function Write(const Buffer; Count: Integer): Integer; stdcall;
  35.     function Read(var Buffer; Count: Integer): Integer; stdcall;
  36.     procedure IgnoreStream; stdcall;
  37.     function InitData(Data: Pointer; DataLen: Integer; CheckLen: Boolean): Integer; stdcall;
  38.     property BytesReserved: Integer read GetBytesReserved;
  39.     property Memory: Pointer read GetMemory;
  40.     property Signature: Integer read GetSignature write SetSignature;
  41.     property Size: Integer read GetSize write SetSize;
  42.     property Stream: TStream read GetStream;
  43.   end;
  44.  
  45.   { ISendDataBlock }
  46.  
  47.   ISendDataBlock = interface
  48.   ['{87AD1043-470E-11D1-88D5-00A0248E5091}']
  49.     function Send(const Data: IDataBlock; WaitForResult: Boolean): IDataBlock; stdcall;
  50.   end;
  51.  
  52.   { ITransport }
  53.  
  54.   ITransport = interface(IUnknown)
  55.   ['{CA6564C1-4683-11D1-88D4-00A0248E5091}']
  56.     function GetWaitEvent: THandle; stdcall;
  57.     function GetConnected: Boolean; stdcall;
  58.     procedure SetConnected(Value: Boolean); stdcall;
  59.     function Receive(WaitForInput: Boolean; Context: Integer): IDataBlock; stdcall;
  60.     function Send(const Data: IDataBlock): Integer; stdcall;
  61.     property Connected: Boolean read GetConnected write SetConnected;
  62.   end;
  63.  
  64.   { IDataIntercept }
  65.  
  66.   IDataIntercept = interface
  67.   ['{B249776B-E429-11D1-AAA4-00C04FA35CFA}']
  68.     procedure DataIn(const Data: IDataBlock); stdcall;
  69.     procedure DataOut(const Data: IDataBlock); stdcall;
  70.   end;
  71.  
  72.   { TDataBlock }
  73.  
  74.   TDataBlock = class(TInterfacedObject, IDataBlock)
  75.   private
  76.     FStream: TMemoryStream;
  77.     FReadPos: Integer;
  78.     FWritePos: Integer;
  79.     FIgnoreStream: Boolean;
  80.   protected
  81.     { IDataBlock }
  82.     function GetBytesReserved: Integer; stdcall;
  83.     function GetMemory: Pointer; stdcall;
  84.     function GetSize: Integer; stdcall;
  85.     procedure SetSize(Value: Integer); stdcall;
  86.     function GetStream: TStream; stdcall;
  87.     function GetSignature: Integer; stdcall;
  88.     procedure SetSignature(Value: Integer); stdcall;
  89.     procedure Clear; stdcall;
  90.     function Write(const Buffer; Count: Integer): Integer; stdcall;
  91.     function Read(var Buffer; Count: Integer): Integer; stdcall;
  92.     procedure IgnoreStream; stdcall;
  93.     function InitData(Data: Pointer; DataLen: Integer; CheckLen: Boolean): Integer; stdcall;
  94.     property BytesReserved: Integer read GetBytesReserved;
  95.     property Memory: Pointer read GetMemory;
  96.     property Signature: Integer read GetSignature write SetSignature;
  97.     property Size: Integer read GetSize write SetSize;
  98.     property Stream: TStream read GetStream;
  99.   public
  100.     constructor Create;
  101.     destructor Destroy; override;
  102.   end;
  103.  
  104.   { TDataBlockInterpreter }
  105.  
  106. const
  107.  
  108.   { Action Signatures }
  109.  
  110.   CallSig         = $DA00; // Call signature
  111.   ResultSig       = $DB00; // Result signature
  112.   asError         = $01;   // Specify an exception was raised
  113.   asInvoke        = $02;   // Specify a call to Invoke
  114.   asGetID         = $03;   // Specify a call to GetIdsOfNames
  115.   asCreateObject  = $04;   // Specify a com object to create
  116.   asFreeObject    = $05;   // Specify a dispatch to free
  117.   asGetServers    = $10;   // Get classname list
  118.   asGetGUID       = $11;   // Get GUID for ClassName
  119.   asGetAppServers = $12;   // Get AppServer classname list
  120.   asMask          = $FF;   // Mask for action
  121.  
  122. type
  123.  
  124.   PIntArray = ^TIntArray;
  125.   TIntArray = array[0..0] of Integer;
  126.  
  127.   PVariantArray = ^TVariantArray;
  128.   TVariantArray = array[0..0] of OleVariant;
  129.  
  130.   TVarFlag = (vfByRef, vfVariant);
  131.   TVarFlags = set of TVarFlag;
  132.  
  133.   EInterpreterError = class(Exception);
  134.  
  135.   TDataDispatch = class;
  136.  
  137.   TDataBlockInterpreter = class
  138.   private
  139.     FDispatchList: TList;
  140.     FDispList: OleVariant;
  141.     FSendDataBlock: ISendDataBlock;
  142.     FCheckRegValue: string;
  143.     function GetVariantPointer(const Value: OleVariant): Pointer;
  144.     procedure CopyDataByRef(Source: TVarData; var Dest: TVarData);
  145.     function ReadArray(VType: Integer; const Data: IDataBlock): OleVariant;
  146.     procedure WriteArray(const Value: OleVariant; const Data: IDataBlock);
  147.     procedure DoException(const Data: IDataBlock);
  148.   protected
  149.     procedure AddDispatch(Value: TDataDispatch);
  150.     procedure RemoveDispatch(Value: TDataDispatch);
  151.     function InternalCreateObject(const ClassID: TGUID): OleVariant; virtual;
  152.     function CreateObject(const Name: string): OleVariant; virtual;
  153.     function StoreObject(const Value: OleVariant): Integer; virtual;
  154.     function LockObject(ID: Integer): IDispatch; virtual;
  155.     procedure UnlockObject(ID: Integer; const Disp: IDispatch); virtual;
  156.     procedure ReleaseObject(ID: Integer); virtual;
  157.     function CanCreateObject(const ClassID: TGUID): Boolean; virtual;
  158.     {Sending Calls}
  159.     procedure CallFreeObject(DispatchIndex: Integer);
  160.     function CallGetIDsOfNames(DispatchIndex: Integer; const IID: TGUID; Names: Pointer;
  161.       NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
  162.     function CallInvoke(DispatchIndex, DispID: Integer; const IID: TGUID; LocaleID: Integer;
  163.       Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
  164.     function CallGetServerList: OleVariant;
  165.     {Receiving Calls}
  166.     procedure DoCreateObject(const Data: IDataBlock);
  167.     procedure DoFreeObject(const Data: IDataBlock);
  168.     procedure DoGetIDsOfNames(const Data: IDataBlock);
  169.     procedure DoInvoke(const Data: IDataBlock);
  170.     function DoCustomAction(Action: Integer; const Data: IDataBlock): Boolean; virtual;
  171.     procedure DoGetAppServerList(const Data: IDataBlock);
  172.     procedure DoGetServerList(const Data: IDataBlock);
  173.   public
  174.     constructor Create(SendDataBlock: ISendDataBlock; CheckRegValue: string);
  175.     destructor Destroy; override;
  176.     function CallCreateObject(Name: string): OleVariant;
  177.     procedure InterpretData(const Data: IDataBlock);
  178.     function ReadVariant(out Flags: TVarFlags; const Data: IDataBlock): OleVariant;
  179.     procedure WriteVariant(const Value: OleVariant; const Data: IDataBlock);
  180.   end;
  181.  
  182. { TDataDispatch }
  183.  
  184.   TDataDispatch = class(TInterfacedObject, IDispatch)
  185.   private
  186.     FDispatchIndex: Integer;
  187.     FInterpreter: TDataBlockInterpreter;
  188.   protected
  189.     property DispatchIndex: Integer read FDispatchIndex;
  190.     { IDispatch }
  191.     function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
  192.     function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
  193.     function GetIDsOfNames(const IID: TGUID; Names: Pointer;
  194.       NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
  195.     function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  196.       Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
  197.   public
  198.     constructor Create(Interpreter: TDataBlockInterpreter; DispatchIndex: Integer);
  199.     destructor Destroy; override;
  200.   end;
  201.  
  202.   { TTransportThread }
  203.  
  204. const
  205.   THREAD_SENDSTREAM       = WM_USER + 1;
  206.   THREAD_RECEIVEDSTREAM   = THREAD_SENDSTREAM + 1;
  207.   THREAD_EXCEPTION        = THREAD_RECEIVEDSTREAM + 1;
  208.   THREAD_SENDNOTIFY       = THREAD_EXCEPTION + 1;
  209.   THREAD_REPLACETRANSPORT = THREAD_SENDNOTIFY + 1;
  210.  
  211. type
  212.  
  213.   TTransportThread = class(TThread)
  214.   private
  215.     FParentHandle: THandle;
  216.     FSemaphore: THandle;
  217.     FTransport: ITransport;
  218.   public
  219.     constructor Create(AHandle: THandle; Transport: ITransport); virtual;
  220.     destructor Destroy; override;
  221.     property Semaphore: THandle read FSemaphore;
  222.     procedure Execute; override;
  223.   end;
  224.  
  225.   { TStreamedConnection }
  226.  
  227.   TStreamedConnection = class(TDispatchConnection, ISendDataBlock)
  228.   private
  229.     FRefCount: Integer;
  230.     FHandle: THandle;
  231.     FTransport: TTransportThread;
  232.     FTransIntf: ITransport;
  233.     FInterpreter: TDataBlockInterpreter;
  234.     FSupportCallbacks: Boolean;
  235.     function GetHandle: THandle;
  236.     procedure TransportTerminated(Sender: TObject);
  237.     procedure SetSupportCallbacks(Value: Boolean);
  238.   protected
  239.     { IUnknown }
  240.     function QueryInterface(const IID: TGUID; out Obj): HResult; reintroduce; stdcall;
  241.     function _AddRef: Integer; stdcall;
  242.     function _Release: Integer; stdcall;
  243.     { ISendDataBlock }
  244.     function Send(const Data: IDataBlock; WaitForResult: Boolean): IDataBlock; stdcall;
  245.  
  246.     procedure InternalOpen; virtual;
  247.     procedure InternalClose; virtual;
  248.  
  249.     procedure ThreadReceivedStream(var Message: TMessage); message THREAD_RECEIVEDSTREAM;
  250.     procedure ThreadException(var Message: TMessage); message THREAD_EXCEPTION;
  251.     procedure WndProc(var Message: TMessage);
  252.     function CreateTransport: ITransport; virtual;
  253.     procedure DoConnect; override;
  254.     procedure DoDisconnect; override;
  255.     procedure DoError(E: Exception); virtual;
  256.     function GetServerList: OleVariant; override;
  257.  
  258.     property Interpreter: TDataBlockInterpreter read FInterpreter;
  259.     property Handle: THandle read GetHandle;
  260.     property SupportCallbacks: Boolean read FSupportCallbacks write SetSupportCallbacks default True;
  261.   public
  262.     constructor Create(AOwner: TComponent); override;
  263.     destructor Destroy; override;
  264.   end;
  265.  
  266.   { TSocketTransport }
  267.  
  268.   ESocketConnectionError = class(Exception);
  269.  
  270.   TSocketTransport = class(TInterfacedObject, ITransport)
  271.   private
  272.     FEvent: THandle;
  273.     FAddress: string;
  274.     FHost: string;
  275.     FPort: Integer;
  276.     FClientSocket: TClientSocket;
  277.     FSocket: TCustomWinSocket;
  278.     FInterceptGUID: string;
  279.     FInterceptor: IDataIntercept;
  280.     FCreateAttempted: Boolean;
  281.     function CheckInterceptor: Boolean;
  282.     procedure InterceptIncoming(const Data: IDataBlock);
  283.     procedure InterceptOutgoing(const Data: IDataBlock);
  284.   protected
  285.     { ITransport }
  286.     function GetWaitEvent: THandle; stdcall;
  287.     function GetConnected: Boolean; stdcall;
  288.     procedure SetConnected(Value: Boolean); stdcall;
  289.     function Receive(WaitForInput: Boolean; Context: Integer): IDataBlock; stdcall;
  290.     function Send(const Data: IDataBlock): Integer; stdcall;
  291.   public
  292.     constructor Create;
  293.     destructor Destroy; override;
  294.     property Host: string read FHost write FHost;
  295.     property Address: string read FAddress write FAddress;
  296.     property Port: Integer read FPort write FPort;
  297.     property Socket: TCustomWinSocket read FSocket write FSocket;
  298.     property InterceptGUID: string read FInterceptGUID write FInterceptGUID;
  299.   end;
  300.  
  301.   { TSocketConnection }
  302.  
  303.   TSocketConnection = class(TStreamedConnection)
  304.   private
  305.     FAddress: string;
  306.     FHost: string;
  307.     FPort: Integer;
  308.     FInterceptGUID: string;
  309.     procedure SetAddress(Value: string);
  310.     procedure SetHost(Value: string);
  311.     function IsHostStored: Boolean;
  312.     function IsAddressStored: Boolean;
  313.   protected
  314.     function CreateTransport: ITransport; override;
  315.     procedure DoConnect; override;
  316.   public
  317.     constructor Create(AOwner: TComponent); override;
  318.   published
  319.     property Address: string read FAddress write SetAddress stored IsAddressStored;
  320.     property Host: string read FHost write SetHost stored IsHostStored;
  321.     property InterceptGUID: string read FInterceptGUID write FInterceptGUID;
  322.     property Port: Integer read FPort write FPort default 211;
  323.     property SupportCallbacks;
  324.     property ObjectBroker;
  325.   end;
  326.  
  327.   { TWebConnection }
  328.  
  329.   TWebConnection = class(TStreamedConnection, ITransport)
  330.   private
  331.     FAgent: string;
  332.     FUserName: string;
  333.     FPassword: string;
  334.     FURL: string;
  335.     FURLHost: string;
  336.     FURLSite: string;
  337.     FURLPort: Integer;
  338.     FURLScheme: Integer;
  339.     FProxy: string;
  340.     FProxyByPass: string;
  341.     FInetRoot: HINTERNET;
  342.     FInetConnect: HINTERNET;
  343.     FInterpreter: TDataBlockInterpreter;
  344.     procedure Check(Error: Boolean);
  345.     function IsURLStored: Boolean;
  346.     procedure SetURL(const Value: string);
  347.   protected
  348.     { ITransport }
  349.     function GetWaitEvent: THandle; stdcall;
  350.     function Transport_GetConnected: Boolean; stdcall;
  351.     function ITransport.GetConnected = Transport_GetConnected;
  352.     procedure Transport_SetConnected(Value: Boolean); stdcall;
  353.     procedure ITransport.SetConnected = Transport_SetConnected;
  354.     function Receive(WaitForInput: Boolean; Context: Integer): IDataBlock; stdcall;
  355.     function Send(const Data: IDataBlock): Integer; stdcall;
  356.   protected
  357.     function CreateTransport: ITransport; override;
  358.     procedure DoConnect; override;
  359.     property SupportCallbacks default False;
  360.   public
  361.     constructor Create(AOwner: TComponent); override;
  362.     destructor Destroy; override;
  363.   published
  364.     property Agent: string read FAgent write FAgent;
  365.     property UserName: string read FUserName write FUserName;
  366.     property Password: string read FPassword write FPassword;
  367.     property URL: string read FURL write SetURL stored IsURLStored;
  368.     property Proxy: string read FProxy write FProxy;
  369.     property ProxyByPass: string read FProxyByPass write FProxyByPass;
  370.     property ObjectBroker;
  371.   end;
  372.  
  373. { Utility functions }
  374.  
  375. function LoadWinSock2: Boolean;
  376.  
  377. var
  378.   WSACreateEvent: function: THandle stdcall;
  379.   WSAResetEvent: function(hEvent: THandle): Boolean stdcall;
  380.   WSACloseEvent: function(hEvent: THandle): Boolean stdcall;
  381.   WSAEventSelect: function(s: TSocket; hEventObject: THandle; lNetworkEvents: Integer): Integer stdcall;
  382.  
  383. implementation
  384.  
  385. uses
  386.   ActiveX, ComObj, MidConst, Forms, Consts;
  387.  
  388. var
  389.   hWinSock2: THandle;
  390.  
  391. { Utility functions }
  392.  
  393. function LoadWinSock2: Boolean;
  394. const
  395.   DLLName = 'ws2_32.dll';
  396. begin
  397.   Result := hWinSock2 > HINSTANCE_ERROR;
  398.   if Result then Exit;
  399.   hWinSock2 := LoadLibrary(PChar(DLLName));
  400.   Result := hWinSock2 > HINSTANCE_ERROR;
  401.   if Result then
  402.   begin
  403.     WSACreateEvent := GetProcAddress(hWinSock2, 'WSACreateEvent');
  404.     WSAResetEvent := GetProcAddress(hWinSock2, 'WSAResetEvent');
  405.     WSACloseEvent := GetProcAddress(hWinSock2, 'WSACloseEvent');
  406.     WSAEventSelect := GetProcAddress(hWinSock2, 'WSAEventSelect');
  407.   end;
  408. end;
  409.  
  410. procedure FreeWinSock2;
  411. begin
  412.   if hWinSock2 > HINSTANCE_ERROR then
  413.   begin
  414.     WSACreateEvent := nil;
  415.     WSAResetEvent := nil;
  416.     WSACloseEvent := nil;
  417.     WSAEventSelect := nil;
  418.     FreeLibrary(hWinSock2);
  419.   end;
  420.   hWinSock2 := 0;
  421. end;
  422.  
  423. procedure GetDataBrokerList(List: TStringList; const RegCheck: string);
  424.  
  425.   function OpenRegKey(Key: HKey; const SubKey: string): HKey;
  426.   begin
  427.     if Windows.RegOpenKey(Key, PChar(SubKey), Result) <> 0 then Result := 0;
  428.   end;
  429.  
  430.   function EnumRegKey(Key: HKey; Index: Integer; var Value: string): Boolean;
  431.   var
  432.     Buffer: array[0..255] of Char;
  433.   begin
  434.     Result := False;
  435.     if Windows.RegEnumKey(Key, Index, Buffer, SizeOf(Buffer)) = 0 then
  436.     begin
  437.       Value := Buffer;
  438.       Result := True;
  439.     end;
  440.   end;
  441.  
  442.   function QueryRegKey(Key: HKey; const SubKey: string;
  443.     var Value: string): Boolean;
  444.   var
  445.     BufSize: Longint;
  446.     Buffer: array[0..255] of Char;
  447.   begin
  448.     Result := False;
  449.     BufSize := SizeOf(Buffer);
  450.     if Windows.RegQueryValue(Key, PChar(SubKey), Buffer, BufSize) = 0 then
  451.     begin
  452.       Value := Buffer;
  453.       Result := True;
  454.     end;
  455.   end;
  456.  
  457.   procedure CloseRegKey(Key: HKey);
  458.   begin
  459.     RegCloseKey(Key);
  460.   end;
  461.  
  462. var
  463.   I: Integer;
  464.   ClassIDKey: HKey;
  465.   ClassID, S: string;
  466. begin
  467.   List.Clear;
  468.   ClassIDKey := OpenRegKey(HKEY_CLASSES_ROOT, 'CLSID');
  469.   if ClassIDKey <> 0 then
  470.     try
  471.       I := 0;
  472.       while EnumRegKey(ClassIDKey, I, ClassID) do
  473.       begin
  474.         if RegCheck <> '' then
  475.         begin
  476.           QueryRegKey(ClassIDKey, ClassID + '\' + RegCheck, S);
  477.           if S <> SFlagOn then continue;
  478.         end;
  479.         if not QueryRegKey(ClassIDKey, ClassID + '\Control', S) and
  480.            QueryRegKey(ClassIDKey, ClassID + '\ProgID', S) and
  481.            QueryRegKey(ClassIDKey, ClassID + '\TypeLib', S) and
  482.            QueryRegKey(ClassIDKey, ClassID + '\Version', S) and
  483.            QueryRegKey(ClassIDKey, ClassID + '\Borland DataBroker', S) then
  484.           List.Add(ClassIDToProgID(StringToGUID(ClassID)));
  485.         Inc(I);
  486.       end;
  487.     finally
  488.       CloseRegKey(ClassIDKey);
  489.     end;
  490. end;
  491.  
  492. { TDataBlock }
  493.  
  494. constructor TDataBlock.Create;
  495. begin
  496.   inherited Create;
  497.   FIgnoreStream := False;
  498.   FStream := TMemoryStream.Create;
  499.   Clear;
  500. end;
  501.  
  502. destructor TDataBlock.Destroy;
  503. begin
  504.   if not FIgnoreStream then
  505.     FStream.Free;
  506.   inherited Destroy;
  507. end;
  508.  
  509. { TDataBlock.IDataBlock }
  510.  
  511. function TDataBlock.GetBytesReserved: Integer;
  512. begin
  513.   Result := SizeOf(Integer) * 2;
  514. end;
  515.  
  516. function TDataBlock.GetMemory: Pointer;
  517. var
  518.   DataSize: Integer;
  519. begin
  520.   FStream.Position := 4;
  521.   DataSize := FStream.Size - BytesReserved;
  522.   FStream.Write(DataSize, SizeOf(DataSize));
  523.   Result := FStream.Memory;
  524. end;
  525.  
  526. function TDataBlock.GetSize: Integer;
  527. begin
  528.   Result := FStream.Size - BytesReserved;
  529. end;
  530.  
  531. procedure TDataBlock.SetSize(Value: Integer);
  532. begin
  533.   FStream.Size := Value + BytesReserved;
  534. end;
  535.  
  536. function TDataBlock.GetStream: TStream;
  537. var
  538.   DataSize: Integer;
  539. begin
  540.   FStream.Position := 4;
  541.   DataSize := FStream.Size - BytesReserved;
  542.   FStream.Write(DataSize, SizeOf(DataSize));
  543.   FStream.Position := 0;
  544.   Result := FStream;
  545. end;
  546.  
  547. function TDataBlock.GetSignature: Integer;
  548. begin
  549.   FStream.Position := 0;
  550.   FStream.Read(Result, SizeOf(Result));
  551. end;
  552.  
  553. procedure TDataBlock.SetSignature(Value: Integer);
  554. begin
  555.   FStream.Position := 0;
  556.   FStream.Write(Value, SizeOf(Value));
  557. end;
  558.  
  559. procedure TDataBlock.Clear;
  560. begin
  561.   FStream.Size := BytesReserved;
  562.   FReadPos := BytesReserved;
  563.   FWritePos := BytesReserved;
  564. end;
  565.  
  566. function TDataBlock.Write(const Buffer; Count: Integer): Integer;
  567. begin
  568.   FStream.Position := FWritePos;
  569.   Result := FStream.Write(Buffer, Count);
  570.   FWritePos := FStream.Position;
  571. end;
  572.  
  573. function TDataBlock.Read(var Buffer; Count: Integer): Integer;
  574. begin
  575.   FStream.Position := FReadPos;
  576.   Result := FStream.Read(Buffer, Count);
  577.   FReadPos := FStream.Position;
  578. end;
  579.  
  580. procedure TDataBlock.IgnoreStream;
  581. begin
  582.   FIgnoreStream := True;
  583. end;
  584.  
  585. function TDataBlock.InitData(Data: Pointer; DataLen: Integer; CheckLen: Boolean): Integer; stdcall;
  586. var
  587.   Sig: Integer;
  588.   P: Pointer;
  589. begin
  590.   P := Data;
  591.   if DataLen < 8 then
  592.     raise Exception.CreateRes(@SInvalidDataPacket);
  593.   Sig := Integer(P^);
  594.   P := Pointer(Integer(Data) + SizeOf(Sig));
  595.   if (Sig and CallSig <> CallSig) and
  596.      (Sig and ResultSig <> ResultSig) then
  597.     raise Exception.CreateRes(@SInvalidDataPacket);
  598.   Signature := Sig;
  599.   Result := Integer(P^);
  600.   P := Pointer(Integer(P) + SizeOf(Result));
  601.   if CheckLen then
  602.   begin
  603.     if (Result <> DataLen - 8) then
  604.       raise Exception.CreateRes(@SInvalidDataPacket);
  605.     Size := Result;
  606.     if Result > 0 then
  607.       Write(P^, Result);
  608.   end else
  609.   begin
  610.     Size := DataLen - 8;
  611.     if Size > 0 then
  612.       Write(P^, Size);
  613.   end;
  614. end;
  615.  
  616. { TDataBlockInterpreter }
  617.  
  618. const
  619.  
  620.   EasyArrayTypes = [varSmallInt, varInteger, varSingle, varDouble, varCurrency,
  621.                     varDate, varBoolean, varByte];
  622.  
  623.   VariantSize: array[0..varByte] of Word  = (0, 0, SizeOf(SmallInt), SizeOf(Integer),
  624.     SizeOf(Single), SizeOf(Double), SizeOf(Currency), SizeOf(TDateTime), 0, 0,
  625.     SizeOf(Integer), SizeOf(WordBool), 0, 0, 0, 0, 0, SizeOf(Byte));
  626.  
  627. constructor TDataBlockInterpreter.Create(SendDataBlock: ISendDataBlock; CheckRegValue: string);
  628. begin
  629.   inherited Create;
  630.   FSendDataBlock := SendDataBlock;
  631.   FDispatchList := TList.Create;
  632.   FCheckRegValue := CheckRegValue;
  633. end;
  634.  
  635. destructor TDataBlockInterpreter.Destroy;
  636. var
  637.   i: Integer;
  638. begin
  639.   for i := FDispatchList.Count - 1 downto 0 do
  640.     TDataDispatch(FDispatchList[i]).FInterpreter := nil;
  641.   FDispatchList.Free;
  642.   FSendDataBlock := nil;
  643.   inherited Destroy;
  644. end;
  645.  
  646. procedure TDataBlockInterpreter.AddDispatch(Value: TDataDispatch);
  647. begin
  648.   if FDispatchList.IndexOf(Value) = -1 then
  649.     FDispatchList.Add(Value);
  650. end;
  651.  
  652. procedure TDataBlockInterpreter.RemoveDispatch(Value: TDataDispatch);
  653. begin
  654.   FDispatchList.Remove(Value);
  655. end;
  656.  
  657. { Variant conversion methods }
  658.  
  659. function TDataBlockInterpreter.GetVariantPointer(const Value: OleVariant): Pointer;
  660. begin
  661.   case VarType(Value) of
  662.     varEmpty, varNull: Result := nil;
  663.     varDispatch: Result := TVarData(Value).VDispatch;
  664.     varVariant: Result := @Value;
  665.     varUnknown: Result := TVarData(Value).VUnknown;
  666.   else
  667.     Result := @TVarData(Value).VPointer;
  668.   end;
  669. end;
  670.  
  671. procedure TDataBlockInterpreter.CopyDataByRef(Source: TVarData; var Dest: TVarData);
  672. var
  673.   VType: Integer;
  674. begin
  675.   VType := Source.VType;
  676.   if Source.VType and varArray = varArray then
  677.   begin
  678.     VarClear(OleVariant(Dest));
  679.     SafeArrayCopy(PSafeArray(Source.VArray), PSafeArray(Dest.VArray));
  680.   end else
  681.     case Source.VType and varTypeMask of
  682.       varEmpty, varNull: ;
  683.       varOleStr:
  684.       begin
  685.         if (Dest.VType and varTypeMask) <> varOleStr then
  686.           Dest.VOleStr := SysAllocString(Source.VOleStr) else
  687.         if (Dest.VType and varByRef) = varByRef then
  688.           SysReallocString(PBStr(Dest.VOleStr)^,Source.VOleStr) else
  689.           SysReallocString(Dest.VOleStr,Source.VOleStr);
  690.       end;
  691.       varDispatch: Dest.VDispatch := Source.VDispatch;
  692.       varVariant: CopyDataByRef(PVarData(Source.VPointer)^, Dest);
  693.       varUnknown: Dest.VUnknown := Source.VUnknown;
  694.     else
  695.       if Dest.VType = 0 then
  696.         OleVariant(Dest) := OleVariant(Source) else
  697.       if Dest.VType and varByRef = varByRef then
  698.       begin
  699.         VType := VType or varByRef;
  700.         Move(Source.VPointer, Dest.VPointer^, VariantSize[Source.VType and varTypeMask]);
  701.       end else
  702.         Move(Source.VPointer, Dest.VPointer, VariantSize[Source.VType and varTypeMask]);
  703.     end;
  704.   Dest.VType := VType;
  705. end;
  706.  
  707. function TDataBlockInterpreter.ReadArray(VType: Integer;
  708.   const Data: IDataBlock): OleVariant;
  709. var
  710.   Flags: TVarFlags;
  711.   LoDim, HiDim, Indices, Bounds: PIntArray;
  712.   DimCount, VSize, i: Integer;
  713.   P: Pointer;
  714.   V: OleVariant;
  715.   VarArrayPtr: PSafeArray;
  716. begin
  717.   VarClear(Result);
  718.   Data.Read(DimCount, SizeOf(DimCount));
  719.   VSize := DimCount * SizeOf(Integer);
  720.   GetMem(LoDim, VSize);
  721.   try
  722.     GetMem(HiDim, VSize);
  723.     try
  724.       Data.Read(LoDim^, VSize);
  725.       Data.Read(HiDim^, VSize);
  726.       GetMem(Bounds, VSize * 2);
  727.       try
  728.         for i := 0 to DimCount - 1 do
  729.         begin
  730.           Bounds[i * 2] := LoDim[i];
  731.           Bounds[i * 2 + 1] := HiDim[i];
  732.         end;
  733.         Result := VarArrayCreate(Slice(Bounds^,DimCount * 2), VType and varTypeMask);
  734.       finally
  735.         FreeMem(Bounds);
  736.       end;
  737.       VarArrayPtr := PSafeArray(TVarData(Result).VArray);
  738.       if VType and varTypeMask in EasyArrayTypes then
  739.       begin
  740.         Data.Read(VSize, SizeOf(VSize));
  741.         P := VarArrayLock(Result);
  742.         try
  743.           Data.Read(P^, VSize);
  744.         finally
  745.           VarArrayUnlock(Result);
  746.         end;
  747.       end else
  748.       begin
  749.         GetMem(Indices, VSize);
  750.         try
  751.           FillChar(Indices^, VSize, 0);
  752.           for I := 0 to DimCount - 1 do
  753.             Indices[I] := LoDim[I];
  754.           while True do
  755.           begin
  756.             V := ReadVariant(Flags, Data);
  757.             if VType and varTypeMask = varVariant then
  758.               OleCheck(SafeArrayPutElement(VarArrayPtr, Indices^, V)) else
  759.               OleCheck(SafeArrayPutElement(VarArrayPtr, Indices^, TVarData(V).VPointer^));
  760.             Inc(Indices[DimCount - 1]);
  761.             if Indices[DimCount - 1] > HiDim[DimCount - 1] then
  762.               for i := DimCount - 1 downto 0 do
  763.                 if Indices[i] > HiDim[i] then
  764.                 begin
  765.                   if i = 0 then Exit;
  766.                   Inc(Indices[i - 1]);
  767.                   Indices[i] := LoDim[i];
  768.                 end;
  769.           end;
  770.         finally
  771.           FreeMem(Indices);
  772.         end;
  773.       end;
  774.     finally
  775.       FreeMem(HiDim);
  776.     end;
  777.   finally
  778.     FreeMem(LoDim);
  779.   end;
  780. end;
  781.  
  782. procedure TDataBlockInterpreter.WriteArray(const Value: OleVariant;
  783.   const Data: IDataBlock);
  784. var
  785.   VType, VSize, i, DimCount, ElemSize: Integer;
  786.   VarArrayPtr: PSafeArray;
  787.   LoDim, HiDim, Indices: PIntArray;
  788.   V: OleVariant;
  789.   P: Pointer;
  790. begin
  791.   VType := VarType(Value);
  792.   Data.Write(VType, SizeOf(Integer));
  793.   DimCount := VarArrayDimCount(Value);
  794.   Data.Write(DimCount, SizeOf(DimCount));
  795.   VarArrayPtr := PSafeArray(TVarData(Value).VArray);
  796.   VSize := SizeOf(Integer) * DimCount;
  797.   GetMem(LoDim, VSize);
  798.   try
  799.     GetMem(HiDim, VSize);
  800.     try
  801.       for i := 1 to DimCount do
  802.       begin
  803.         LoDim[i - 1] := VarArrayLowBound(Value, i);
  804.         HiDim[i - 1] := VarArrayHighBound(Value, i);
  805.       end;
  806.       Data.Write(LoDim^,VSize);
  807.       Data.Write(HiDim^,VSize);
  808.       if VType and varTypeMask in EasyArrayTypes then
  809.       begin
  810.         ElemSize := SafeArrayGetElemSize(VarArrayPtr);
  811.         VSize := 1;
  812.         for i := 0 to DimCount - 1 do
  813.           VSize := (HiDim[i] - LoDim[i] + 1) * VSize;
  814.         VSize := VSize * ElemSize;
  815.         P := VarArrayLock(Value);
  816.         try
  817.           Data.Write(VSize, SizeOf(VSize));
  818.           Data.Write(P^,VSize);
  819.         finally
  820.           VarArrayUnlock(Value);
  821.         end;
  822.       end else
  823.       begin
  824.         GetMem(Indices, VSize);
  825.         try
  826.           for I := 0 to DimCount - 1 do
  827.             Indices[I] := LoDim[I];
  828.           while True do
  829.           begin
  830.             if VType and varTypeMask <> varVariant then
  831.             begin
  832.               OleCheck(SafeArrayGetElement(VarArrayPtr, Indices^, TVarData(V).VPointer));
  833.               TVarData(V).VType := VType and varTypeMask;
  834.             end else
  835.               OleCheck(SafeArrayGetElement(VarArrayPtr, Indices^, V));
  836.             WriteVariant(V, Data);
  837.             Inc(Indices[DimCount - 1]);
  838.             if Indices[DimCount - 1] > HiDim[DimCount - 1] then
  839.               for i := DimCount - 1 downto 0 do
  840.                 if Indices[i] > HiDim[i] then
  841.                 begin
  842.                   if i = 0 then Exit;
  843.                   Inc(Indices[i - 1]);
  844.                   Indices[i] := LoDim[i];
  845.                 end;
  846.           end;
  847.         finally
  848.           FreeMem(Indices);
  849.         end;
  850.       end;
  851.     finally
  852.       FreeMem(HiDim);
  853.     end;
  854.   finally
  855.     FreeMem(LoDim);
  856.   end;
  857. end;
  858.  
  859. function TDataBlockInterpreter.ReadVariant(out Flags: TVarFlags;
  860.   const Data: IDataBlock): OleVariant;
  861. var
  862.   I, VType: Integer;
  863.   W: WideString;
  864.   TmpFlags: TVarFlags;
  865. begin
  866.   VarClear(Result);
  867.   Flags := [];
  868.   Data.Read(VType, SizeOf(VType));
  869.   if VType and varByRef = varByRef then Include(Flags, vfByRef);
  870.   if VType = varByRef then
  871.   begin
  872.     Include(Flags, vfVariant);
  873.     Result := ReadVariant(TmpFlags, Data);
  874.     Exit;
  875.   end;
  876.   if vfByRef in Flags then VType := VType xor varByRef;
  877.   if (VType and varArray) = varArray then
  878.     Result := ReadArray(VType, Data) else
  879.   case VType and varTypeMask of
  880.     varEmpty: VarClear(Result);
  881.     varNull: Result := NULL;
  882.     varOleStr:
  883.     begin
  884.       Data.Read(I, SizeOf(Integer));
  885.       SetLength(W, I);
  886.       Data.Read(W[1], I * 2);
  887.       Result := W;
  888.     end;
  889.     varDispatch:
  890.     begin
  891.       Data.Read(I, SizeOf(Integer));
  892.       Result := TDataDispatch.Create(Self, I) as IDispatch;
  893.     end;
  894.     varUnknown:
  895.       raise EInterpreterError.CreateResFmt(@SBadVariantType,[IntToHex(VType,4)]);
  896.   else
  897.     TVarData(Result).VType := VType;
  898.     Data.Read(TVarData(Result).VPointer, VariantSize[VType and varTypeMask]);
  899.   end;
  900. end;
  901.  
  902. function TDataBlockInterpreter.CanCreateObject(const ClassID: TGUID): Boolean;
  903. begin
  904.   Result := (FCheckRegValue = '') or
  905.     (GetRegStringValue(SClsid + GuidToString(ClassID), FCheckRegValue) = SFlagOn);
  906. end;
  907.  
  908. function TDataBlockInterpreter.InternalCreateObject(const ClassID: TGUID): OleVariant;
  909. var
  910.   Unk: IUnknown;
  911. begin
  912.   OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or
  913.     CLSCTX_LOCAL_SERVER or CLSCTX_REMOTE_SERVER, IUnknown, Unk));
  914.   Result := Unk as IDispatch;
  915. end;
  916.  
  917. function TDataBlockInterpreter.CreateObject(const Name: string): OleVariant;
  918. var
  919.   ClassID: TGUID;
  920. begin
  921.   if (Name[1] = '{') and (Name[Length(Name)] = '}') then
  922.     ClassID := StringToGUID(Name) else
  923.     ClassID := ProgIDToClassID(Name);
  924.   if CanCreateObject(ClassID) then
  925.     Result := InternalCreateObject(ClassID) else
  926.     raise Exception.CreateResFmt(@SObjectNotAvailable, [GuidToString(ClassID)]);
  927. end;
  928.  
  929. function TDataBlockInterpreter.StoreObject(const Value: OleVariant): Integer;
  930. begin
  931.   if not VarIsArray(FDispList) then
  932.     FDispList := VarArrayCreate([0,10], varVariant);
  933.   Result := 0;
  934.   while Result <= VarArrayHighBound(FDispList, 1) do
  935.     if VarIsEmpty(FDispList[Result]) then break else Inc(Result);
  936.   if Result > VarArrayHighBound(FDispList, 1) then
  937.     VarArrayRedim(FDispList, Result + 10);
  938.   FDispList[Result] := Value;
  939. end;
  940.  
  941. function TDataBlockInterpreter.LockObject(ID: Integer): IDispatch;
  942. begin
  943.   Result := FDispList[ID];
  944. end;
  945.  
  946. procedure TDataBlockInterpreter.UnlockObject(ID: Integer; const Disp: IDispatch);
  947. begin
  948. end;
  949.  
  950. procedure TDataBlockInterpreter.ReleaseObject(ID: Integer);
  951. begin
  952.   if (ID >= 0) and (VarIsArray(FDispList)) and
  953.      (ID < VarArrayHighBound(FDispList, 1)) then
  954.     FDispList[ID] := UNASSIGNED;
  955. end;
  956.  
  957. procedure TDataBlockInterpreter.WriteVariant(const Value: OleVariant;
  958.   const Data: IDataBlock);
  959. var
  960.   I, VType: Integer;
  961.   W: WideString;
  962. begin
  963.   VType := VarType(Value);
  964.   if VarIsArray(Value) then
  965.     WriteArray(Value, Data) else
  966.   case (VType and varTypeMask) of
  967.     varEmpty, varNull: Data.Write(VType, SizeOf(Integer));
  968.     varOleStr:
  969.     begin
  970.       W := WideString(Value);
  971.       I := Length(W);
  972.       Data.Write(VType, SizeOf(Integer));
  973.       Data.Write(I,SizeOf(Integer));
  974.       Data.Write(W[1], I * 2);
  975.     end;
  976.     varDispatch:
  977.     begin
  978.       if VType and varByRef = varByRef then
  979.         raise EInterpreterError.CreateResFmt(@SBadVariantType,[IntToHex(VType,4)]);
  980.       I := StoreObject(Value);
  981.       Data.Write(VType, SizeOf(Integer));
  982.       Data.Write(I, SizeOf(Integer));
  983.     end;
  984.     varVariant:
  985.     begin
  986.       if VType and varByRef <> varByRef then
  987.         raise EInterpreterError.CreateResFmt(@SBadVariantType,[IntToHex(VType,4)]);
  988.       I := varByRef;
  989.       Data.Write(I, SizeOf(Integer));
  990.       WriteVariant(Variant(TVarData(Value).VPointer^), Data);
  991.     end;
  992.     varUnknown:
  993.       raise EInterpreterError.CreateResFmt(@SBadVariantType,[IntToHex(VType,4)]);
  994.   else
  995.     Data.Write(VType, SizeOf(Integer));
  996.     if VType and varByRef = varByRef then
  997.       Data.Write(TVarData(Value).VPointer^, VariantSize[VType and varTypeMask]) else
  998.       Data.Write(TVarData(Value).VPointer, VariantSize[VType and varTypeMask]);
  999.   end;
  1000. end;
  1001.  
  1002. { Sending Calls }
  1003.  
  1004. function TDataBlockInterpreter.CallGetServerList: OleVariant;
  1005. var
  1006.   Flags: TVarFlags;
  1007.   Data: IDataBlock;
  1008. begin
  1009.   Data := TDataBlock.Create as IDataBlock;
  1010.   Data.Signature := CallSig or asGetAppServers;
  1011.   Data := FSendDataBlock.Send(Data, True);
  1012.   Result := ReadVariant(Flags, Data);
  1013. end;
  1014.  
  1015. function TDataBlockInterpreter.CallCreateObject(Name: string): OleVariant;
  1016. var
  1017.   Flags: TVarFlags;
  1018.   Data: IDataBlock;
  1019. begin
  1020.   Data := TDataBlock.Create as IDataBlock;
  1021.   WriteVariant(Name, Data);
  1022.   Data.Signature := CallSig or asCreateObject;
  1023.   Data := FSendDataBlock.Send(Data, True);
  1024.   Result := ReadVariant(Flags, Data);
  1025. end;
  1026.  
  1027. procedure TDataBlockInterpreter.CallFreeObject(DispatchIndex: Integer);
  1028. var
  1029.   Data: IDataBlock;
  1030. begin
  1031.   Data := TDataBlock.Create as IDataBlock;
  1032.   WriteVariant(DispatchIndex, Data);
  1033.   Data.Signature := CallSig or asFreeObject;
  1034.   FSendDataBlock.Send(Data, False);
  1035. end;
  1036.  
  1037. function TDataBlockInterpreter.CallGetIDsOfNames(DispatchIndex: Integer;
  1038.   const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer;
  1039.   DispIDs: Pointer): HResult; stdcall;
  1040. var
  1041.   Flags: TVarFlags;
  1042.   Data: IDataBlock;
  1043. begin
  1044.   if NameCount <> 1 then
  1045.     Result := E_NOTIMPL else
  1046.   begin
  1047.     Data := TDataBlock.Create as IDataBlock;
  1048.     WriteVariant(DispatchIndex, Data);
  1049.     WriteVariant(WideString(POleStrList(Names)^[0]), Data);
  1050.     Data.Signature := CallSig or asGetID;
  1051.     Data := FSendDataBlock.Send(Data, True);
  1052.     Result := ReadVariant(Flags, Data);
  1053.     if Result = S_OK then
  1054.       PDispIdList(DispIDs)^[0] := ReadVariant(Flags, Data);
  1055.   end;
  1056. end;
  1057.  
  1058. function TDataBlockInterpreter.CallInvoke(DispatchIndex, DispID: Integer; const IID: TGUID; LocaleID: Integer;
  1059.   Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
  1060. var
  1061.   VarFlags: TVarFlags;
  1062.   PDest: PVarData;
  1063.   i: Integer;
  1064.   Data: IDataBlock;
  1065. begin
  1066.   Data := TDataBlock.Create as IDataBlock;
  1067.   WriteVariant(DispatchIndex, Data);
  1068.   WriteVariant(DispID, Data);
  1069.   WriteVariant(Flags, Data);
  1070.   WriteVariant(VarResult <> nil, Data);
  1071.   WriteVariant(PDispParams(@Params).cArgs, Data);
  1072.   WriteVariant(PDispParams(@Params).cNamedArgs, Data);
  1073.   for i := 0 to PDispParams(@Params).cNamedArgs - 1 do
  1074.     WriteVariant(PDispParams(@Params).rgdispidNamedArgs[i], Data);
  1075.   for i := 0 to PDispParams(@Params).cArgs - 1 do
  1076.     WriteVariant(OleVariant(PDispParams(@Params).rgvarg^[i]), Data);
  1077.   Data.Signature := CallSig or asInvoke;
  1078.   Data := FSendDataBlock.Send(Data, True);
  1079.   Result := ReadVariant(VarFlags, Data);
  1080.   if (Result = DISP_E_EXCEPTION) then
  1081.   begin
  1082.     PExcepInfo(ExcepInfo).scode := ReadVariant(VarFlags, Data);
  1083.     PExcepInfo(ExcepInfo).bstrDescription := ReadVariant(VarFlags, Data);
  1084.   end;
  1085.   for i := 0 to PDispParams(@Params).cArgs - 1 do
  1086.     with PDispParams(@Params)^ do
  1087.       if rgvarg^[i].vt and varByRef = varByRef then
  1088.       begin
  1089.         if rgvarg^[i].vt = (varByRef or varVariant) then
  1090.           PDest := @TVarData(TVarData(rgvarg^[i]).VPointer^) else
  1091.           PDest := @TVarData(rgvarg^[i]);
  1092.         CopyDataByRef(TVarData(ReadVariant(VarFlags, Data)), PDest^);
  1093.       end;
  1094.   if VarResult <> nil then
  1095.     PVariant(VarResult)^ := ReadVariant(VarFlags, Data);
  1096. end;
  1097.  
  1098. { Receiving Calls }
  1099.  
  1100. procedure TDataBlockInterpreter.InterpretData(const Data: IDataBlock);
  1101. var
  1102.   Action: Integer;
  1103. begin
  1104.   Action := Data.Signature;
  1105.   if (Action and asMask) = asError then DoException(Data);
  1106.   try
  1107.     case (Action and asMask) of
  1108.       asInvoke: DoInvoke(Data);
  1109.       asGetID: DoGetIDsOfNames(Data);
  1110.       asCreateObject: DoCreateObject(Data);
  1111.       asFreeObject: DoFreeObject(Data);
  1112.       asGetServers: DoGetServerList(Data);
  1113.       asGetAppServers: DoGetAppServerList(Data);
  1114.     else
  1115.       if not DoCustomAction(Action and asMask, Data) then
  1116.         raise EInterpreterError.CreateResFmt(@SInvalidAction, [Action and asMask]);
  1117.     end;
  1118.   except
  1119.     on E: Exception do
  1120.     begin
  1121.       Data.Clear;
  1122.       WriteVariant(E.Message, Data);
  1123.       Data.Signature := ResultSig or asError;
  1124.       FSendDataBlock.Send(Data, False);
  1125.     end;
  1126.   end;
  1127. end;
  1128.  
  1129. procedure TDataBlockInterpreter.DoException(const Data: IDataBlock);
  1130. var
  1131.   VarFlags: TVarFlags;
  1132. begin
  1133.   raise Exception.Create(ReadVariant(VarFlags, Data));
  1134. end;
  1135.  
  1136. procedure TDataBlockInterpreter.DoGetAppServerList(const Data: IDataBlock);
  1137. var
  1138.   VList: OleVariant;
  1139.   List: TStringList;
  1140.   i: Integer;
  1141. begin
  1142.   Data.Clear;
  1143.   List := TStringList.Create;
  1144.   try
  1145.     GetMIDASAppServerList(List, FCheckRegValue);
  1146.     if List.Count > 0 then
  1147.     begin
  1148.       VList := VarArrayCreate([0, List.Count - 1], varOleStr);
  1149.       for i := 0 to List.Count - 1 do
  1150.         VList[i] := List[i];
  1151.     end else
  1152.       VList := NULL;
  1153.   finally
  1154.     List.Free;
  1155.   end;
  1156.   WriteVariant(VList, Data);
  1157.   Data.Signature := ResultSig or asGetAppServers;
  1158.   FSendDataBlock.Send(Data, False);
  1159. end;
  1160.  
  1161. procedure TDataBlockInterpreter.DoGetServerList(const Data: IDataBlock);
  1162. var
  1163.   VList: OleVariant;
  1164.   List: TStringList;
  1165.   i: Integer;
  1166. begin
  1167.   Data.Clear;
  1168.   List := TStringList.Create;
  1169.   try
  1170.     GetDataBrokerList(List, FCheckRegValue);
  1171.     if List.Count > 0 then
  1172.     begin
  1173.       VList := VarArrayCreate([0, List.Count - 1], varOleStr);
  1174.       for i := 0 to List.Count - 1 do
  1175.         VList[i] := List[i];
  1176.     end else
  1177.       VList := NULL;
  1178.   finally
  1179.     List.Free;
  1180.   end;
  1181.   WriteVariant(VList, Data);
  1182.   Data.Signature := ResultSig or asGetServers;
  1183.   FSendDataBlock.Send(Data, False);
  1184. end;
  1185.  
  1186. procedure TDataBlockInterpreter.DoCreateObject(const Data: IDataBlock);
  1187. var
  1188.   V: OleVariant;
  1189.   VarFlags: TVarFlags;
  1190.   I: Integer;
  1191. begin
  1192.   V := CreateObject(ReadVariant(VarFlags, Data));
  1193.   Data.Clear;
  1194.   I := TVarData(V).VType;
  1195.   if (I and varTypeMask) = varInteger then
  1196.   begin
  1197.     I := varDispatch;
  1198.     Data.Write(I, SizeOf(Integer));
  1199.     I := V;
  1200.     Data.Write(I, SizeOf(Integer));
  1201.   end else
  1202.     WriteVariant(V, Data);
  1203.   Data.Signature := ResultSig or asCreateObject;
  1204.   FSendDataBlock.Send(Data, False);
  1205. end;
  1206.  
  1207. procedure TDataBlockInterpreter.DoFreeObject(const Data: IDataBlock);
  1208. var
  1209.   VarFlags: TVarFlags;
  1210. begin
  1211.   try
  1212.     ReleaseObject(ReadVariant(VarFlags, Data));
  1213.   except
  1214.     { Don't return any exceptions }
  1215.   end;
  1216. end;
  1217.  
  1218. procedure TDataBlockInterpreter.DoGetIDsOfNames(const Data: IDataBlock);
  1219. var
  1220.   ObjID, RetVal, DispID: Integer;
  1221.   Disp: IDispatch;
  1222.   W: WideString;
  1223.   VarFlags: TVarFlags;
  1224. begin
  1225.   ObjID := ReadVariant(VarFlags, Data);
  1226.   Disp := LockObject(ObjID);
  1227.   try
  1228.     W := ReadVariant(VarFlags, Data);
  1229.     Data.Clear;
  1230.     RetVal := Disp.GetIDsOfNames(GUID_NULL, @W, 1, 0, @DispID);
  1231.   finally
  1232.     UnlockObject(ObjID, Disp);
  1233.   end;
  1234.   WriteVariant(RetVal, Data);
  1235.   if RetVal = S_OK then
  1236.     WriteVariant(DispID, Data);
  1237.   Data.Signature := ResultSig or asGetID;
  1238.   FSendDataBlock.Send(Data, False);
  1239. end;
  1240.  
  1241. procedure TDataBlockInterpreter.DoInvoke(const Data: IDataBlock);
  1242. var
  1243.   ExcepInfo: TExcepInfo;
  1244.   DispParams: TDispParams;
  1245.   ObjID, DispID, Flags, i: Integer;
  1246.   RetVal: HRESULT;
  1247.   ExpectResult: Boolean;
  1248.   VarFlags: TVarFlags;
  1249.   Disp: IDispatch;
  1250.   VarList: PVariantArray;
  1251.   V: OleVariant;
  1252. begin
  1253.   VarList := nil;
  1254.   FillChar(ExcepInfo, SizeOf(ExcepInfo), 0);
  1255.   FillChar(DispParams, SizeOf(DispParams), 0);
  1256.   ObjID := ReadVariant(VarFlags, Data);
  1257.   Disp := LockObject(ObjID);
  1258.   try
  1259.     DispID := ReadVariant(VarFlags, Data);
  1260.     Flags := ReadVariant(VarFlags, Data);
  1261.     ExpectResult := ReadVariant(VarFlags, Data);
  1262.     DispParams.cArgs := ReadVariant(VarFlags, Data);
  1263.     DispParams.cNamedArgs := ReadVariant(VarFlags, Data);
  1264.     try
  1265.       DispParams.rgdispidNamedArgs := nil;
  1266.       if DispParams.cNamedArgs > 0 then
  1267.       begin
  1268.         GetMem(DispParams.rgdispidNamedArgs, DispParams.cNamedArgs * SizeOf(Integer));
  1269.         for i := 0 to DispParams.cNamedArgs - 1 do
  1270.           DispParams.rgdispidNamedArgs[i] := ReadVariant(VarFlags, Data);
  1271.       end;
  1272.       if DispParams.cArgs > 0 then
  1273.       begin
  1274.         GetMem(DispParams.rgvarg, DispParams.cArgs * SizeOf(TVariantArg));
  1275.         GetMem(VarList, DispParams.cArgs * SizeOf(OleVariant));
  1276.         Initialize(VarList^, DispParams.cArgs);
  1277.         for i := 0 to DispParams.cArgs - 1 do
  1278.         begin
  1279.           VarList[i] := ReadVariant(VarFlags, Data);
  1280.           if vfByRef in VarFlags then
  1281.           begin
  1282.             if vfVariant in VarFlags then
  1283.             begin
  1284.               DispParams.rgvarg[i].vt := varVariant or varByRef;
  1285.               TVarData(DispParams.rgvarg[i]).VPointer := @VarList[i];
  1286.             end else
  1287.             begin
  1288.               DispParams.rgvarg[i].vt := VarType(VarList[i]) or varByRef;
  1289.               TVarData(DispParams.rgvarg[i]).VPointer := GetVariantPointer(VarList[i]);
  1290.             end;
  1291.           end else
  1292.             DispParams.rgvarg[i] := TVariantArg(VarList[i]);
  1293.         end;
  1294.       end;
  1295.       Data.Clear;
  1296.       RetVal := Disp.Invoke(DispID, GUID_NULL, 0, Flags, DispParams, @V, @ExcepInfo, nil);
  1297.       WriteVariant(RetVal, Data);
  1298.       if RetVal = DISP_E_EXCEPTION then
  1299.       begin
  1300.         WriteVariant(ExcepInfo.scode, Data);
  1301.         WriteVariant(ExcepInfo.bstrDescription, Data);
  1302.       end;
  1303.       if DispParams.rgvarg <> nil then
  1304.       begin
  1305.         for i := 0 to DispParams.cArgs - 1 do
  1306.           if DispParams.rgvarg[i].vt and varByRef = varByRef then
  1307.             WriteVariant(OleVariant(DispParams.rgvarg[i]), Data);
  1308.       end;
  1309.       if ExpectResult then WriteVariant(V, Data);
  1310.       Data.Signature := ResultSig or asInvoke;
  1311.       FSendDataBlock.Send(Data, False);
  1312.     finally
  1313.       if DispParams.rgdispidNamedArgs <> nil then
  1314.         FreeMem(DispParams.rgdispidNamedArgs);
  1315.       if VarList <> nil then
  1316.       begin
  1317.         Finalize(VarList^, DispParams.cArgs);
  1318.         FreeMem(VarList);
  1319.       end;
  1320.       if DispParams.rgvarg <> nil then
  1321.         FreeMem(DispParams.rgvarg);
  1322.     end;
  1323.   finally
  1324.     UnlockObject(ObjID, Disp);
  1325.   end;
  1326. end;
  1327.  
  1328. function TDataBlockInterpreter.DoCustomAction(Action: Integer;
  1329.   const Data: IDataBlock): Boolean;
  1330. begin
  1331.   Result := False;
  1332. end;
  1333.  
  1334. { TDataDispatch }
  1335.  
  1336. constructor TDataDispatch.Create(Interpreter: TDataBlockInterpreter; DispatchIndex: Integer);
  1337. begin
  1338.   inherited Create;
  1339.   FDispatchIndex := DispatchIndex;
  1340.   FInterpreter := Interpreter;
  1341.   Interpreter.AddDispatch(Self);
  1342. end;
  1343.  
  1344. destructor TDataDispatch.Destroy;
  1345. begin
  1346.   if Assigned(FInterpreter) then
  1347.   begin
  1348.     FInterpreter.CallFreeObject(FDispatchIndex);
  1349.     FInterpreter.RemoveDispatch(Self);
  1350.   end;
  1351.   inherited Destroy;
  1352. end;
  1353.  
  1354. { TDataDispatch.IDispatch }
  1355.  
  1356. function TDataDispatch.GetTypeInfoCount(out Count: Integer): HResult; stdcall;
  1357. begin
  1358.   Count := 0;
  1359.   Result := S_OK;
  1360. end;
  1361.  
  1362. function TDataDispatch.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
  1363. begin
  1364.   Result := E_NOTIMPL;
  1365. end;
  1366.  
  1367. function TDataDispatch.GetIDsOfNames(const IID: TGUID; Names: Pointer;
  1368.   NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
  1369. begin
  1370.   Result := FInterpreter.CallGetIDsOfNames(FDispatchIndex, IID, Names, NameCount,
  1371.     LocaleID, DispIDs);
  1372. end;
  1373.  
  1374. function TDataDispatch.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  1375.   Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
  1376. begin
  1377.   Result := FInterpreter.CallInvoke(FDispatchIndex, DispID, IID, LocaleID, Flags,
  1378.     Params, VarResult, ExcepInfo, ArgErr);
  1379. end;
  1380.  
  1381.  
  1382. { TTransportThread }
  1383.  
  1384. type
  1385.   PRaiseFrame = ^TRaiseFrame;
  1386.   TRaiseFrame = record
  1387.     NextRaise: PRaiseFrame;
  1388.     ExceptAddr: Pointer;
  1389.     ExceptObject: TObject;
  1390.     ExceptionRecord: PExceptionRecord;
  1391.   end;
  1392.  
  1393. constructor TTransportThread.Create(AHandle: THandle; Transport: ITransport);
  1394. begin
  1395.   FParentHandle := AHandle;
  1396.   FTransport := Transport;
  1397.   FreeOnTerminate := True;
  1398.   FSemaphore := CreateSemaphore(nil, 0, 1, nil);
  1399.   inherited Create(False);
  1400. end;
  1401.  
  1402. destructor TTransportThread.Destroy;
  1403. begin
  1404.   CloseHandle(FSemaphore);
  1405.   inherited Destroy;
  1406. end;
  1407.  
  1408. procedure TTransportThread.Execute;
  1409.  
  1410.   procedure SynchronizeException;
  1411.   var
  1412.     SendException: TObject;
  1413.   begin
  1414.     if RaiseList <> nil then
  1415.     begin
  1416.       SendException := PRaiseFrame(RaiseList)^.ExceptObject;
  1417.       PRaiseFrame(RaiseList)^.ExceptObject := nil;
  1418.       if Assigned(FTransport) and (SendException is ESocketConnectionError) then
  1419.         FTransport.Connected := False;
  1420.       PostMessage(FParentHandle, THREAD_EXCEPTION, 0, Integer(Pointer(SendException)));
  1421.     end;
  1422.   end;
  1423.  
  1424. var
  1425.   msg: TMsg;
  1426.   Data: IDataBlock;
  1427.   Event: THandle;
  1428.   Context: Integer;
  1429. begin
  1430.   CoInitialize(nil);
  1431.   try
  1432.     PeekMessage(msg, 0, WM_USER, WM_USER, PM_NOREMOVE);
  1433.     ReleaseSemaphore(FSemaphore, 1, nil);
  1434.     try
  1435.       FTransport.Connected := True;
  1436.       try
  1437.         Event := FTransport.GetWaitEvent;
  1438.         while not Terminated and FTransport.Connected do
  1439.         try
  1440.           case MsgWaitForMultipleObjects(1, Event, False, INFINITE, QS_ALLINPUT) of
  1441.             WAIT_OBJECT_0:
  1442.             begin
  1443.               WSAResetEvent(Event);
  1444.               Data := FTransport.Receive(False, 0);
  1445.               if Assigned(Data) then
  1446.               begin
  1447.                 Data._AddRef;
  1448.                 PostMessage(FParentHandle, THREAD_RECEIVEDSTREAM, 0, Integer(Pointer(Data)));
  1449.                 Data := nil;
  1450.               end;
  1451.             end;
  1452.             WAIT_OBJECT_0 + 1:
  1453.             begin
  1454.               while PeekMessage(msg, 0, 0, 0, PM_REMOVE) do
  1455.               begin
  1456.                 if (msg.hwnd = 0) then
  1457.                   case msg.message of
  1458.                     THREAD_SENDSTREAM:
  1459.                     begin
  1460.                       Data := IDataBlock(msg.lParam);
  1461.                       Data._Release;
  1462.                       Context := FTransport.Send(Data);
  1463.                       if msg.wParam = 1 then
  1464.                       begin
  1465.                         Data := FTransport.Receive(True, Context);
  1466.                         Data._AddRef;
  1467.                         PostMessage(FParentHandle, THREAD_RECEIVEDSTREAM, 0, Integer(Pointer(Data)));
  1468.                         Data := nil;
  1469.                       end else
  1470.                         PostMessage(FParentHandle, THREAD_SENDNOTIFY, 0, 0);
  1471.                     end;
  1472.                     THREAD_REPLACETRANSPORT:
  1473.                     begin
  1474.                       FTransport := ITransport(msg.lParam);
  1475.                       FTransport._Release;
  1476.                     end;
  1477.                   else
  1478.                     DispatchMessage(msg);
  1479.                   end
  1480.                 else
  1481.                   DispatchMessage(msg);
  1482.               end;
  1483.             end;
  1484.           end;
  1485.         except
  1486.           SynchronizeException;
  1487.         end;
  1488.       finally
  1489.         Data := nil;
  1490.         FTransport.Connected := False;
  1491.       end;
  1492.     except
  1493.       SynchronizeException;
  1494.     end;
  1495.   finally
  1496.     FTransport := nil;
  1497.     CoUninitialize();
  1498.   end;
  1499. end;
  1500.  
  1501. { TStreamedConnection }
  1502.  
  1503. constructor TStreamedConnection.Create(AOwner: TComponent);
  1504. var
  1505.   Obj: ISendDataBlock;
  1506. begin
  1507.   inherited Create(AOwner);
  1508.   GetInterface(ISendDataBlock, Obj);
  1509.   FInterpreter := TDataBlockInterpreter.Create(Self, SSockets);
  1510.   FSupportCallbacks := True;
  1511. end;
  1512.  
  1513. destructor TStreamedConnection.Destroy;
  1514. begin
  1515.   SetConnected(False);
  1516.   FInterpreter.Free;
  1517.   if FHandle <> 0 then DeallocateHWnd(FHandle);
  1518.   if Assigned(FTransport) then FTransport.OnTerminate := nil;
  1519.   FTransIntf := nil;
  1520.   inherited Destroy;
  1521. end;
  1522.  
  1523. procedure TStreamedConnection.SetSupportCallbacks(Value: Boolean);
  1524. begin
  1525.   if Connected then Connected := False;
  1526.   FSupportCallbacks := Value;
  1527. end;
  1528.  
  1529. procedure TStreamedConnection.InternalOpen;
  1530. begin
  1531.   if FSupportCallbacks then
  1532.   begin
  1533.     FTransport := TTransportThread.Create(Handle, CreateTransport);
  1534.     FTransport.OnTerminate := TransportTerminated;
  1535.     WaitForSingleObject(FTransport.Semaphore, INFINITE);
  1536.   end else
  1537.   begin
  1538.     FTransIntf := CreateTransport;
  1539.     FTransIntf.SetConnected(True);
  1540.   end;
  1541. end;
  1542.  
  1543. procedure TStreamedConnection.InternalClose;
  1544. begin
  1545.   if Assigned(FTransport) then
  1546.   begin
  1547.     FTransport.OnTerminate := nil;
  1548.     FTransport.Terminate;
  1549.     PostThreadMessage(FTransport.ThreadID, WM_USER, 0, 0);
  1550.     WaitForSingleObject(FTransport.Handle, 180000);
  1551.     FTransport := nil;
  1552.   end else
  1553.   if Assigned(FTransIntf) then
  1554.   begin
  1555.     FTransIntf.Connected := False;
  1556.     FTransIntf := nil;
  1557.   end;
  1558. end;
  1559.  
  1560. function TStreamedConnection.GetServerList: OleVariant;
  1561. var
  1562.   DidConnect: Boolean;
  1563. begin
  1564.   DidConnect := not Connected;
  1565.   if DidConnect then InternalOpen;
  1566.   try
  1567.     Result := Interpreter.CallGetServerList;
  1568.   finally
  1569.     if DidConnect then InternalClose;
  1570.   end;
  1571. end;
  1572.  
  1573. function TStreamedConnection.GetHandle: THandle;
  1574. begin
  1575.   if FHandle = 0 then
  1576.     FHandle := AllocateHwnd(WndProc);
  1577.   Result := FHandle;
  1578. end;
  1579.  
  1580. procedure TStreamedConnection.WndProc(var Message: TMessage);
  1581. begin
  1582.   try
  1583.     Dispatch(Message);
  1584.   except
  1585.     Application.HandleException(Self);
  1586.   end;
  1587. end;
  1588.  
  1589. procedure TStreamedConnection.ThreadReceivedStream(var Message: TMessage);
  1590. var
  1591.   Data: IDataBlock;
  1592. begin
  1593.   Data := IDataBlock(Message.lParam);
  1594.   Data._Release;
  1595.   Interpreter.InterpretData(Data);
  1596. end;
  1597.  
  1598. procedure TStreamedConnection.ThreadException(var Message: TMessage);
  1599. begin
  1600.   DoError(Exception(Message.lParam));
  1601. end;
  1602.  
  1603. procedure TStreamedConnection.DoError(E: Exception);
  1604. begin
  1605.   raise E;
  1606. end;
  1607.  
  1608. procedure TStreamedConnection.TransportTerminated(Sender: TObject);
  1609. begin
  1610.   FTransport := nil;
  1611.   SetConnected(False);
  1612. end;
  1613.  
  1614. procedure TStreamedConnection.DoConnect;
  1615. var
  1616.   TempStr: string;
  1617. begin
  1618.   try
  1619.     if ServerGUID <> '' then
  1620.       TempStr := ServerGUID else
  1621.       TempStr := ServerName;
  1622.     if TempStr = '' then
  1623.       raise Exception.CreateResFmt(@SServerNameBlank, [Name]);
  1624.     InternalOpen;
  1625.     SetAppServer(Interpreter.CallCreateObject(TempStr));
  1626.   except
  1627.     InternalClose;
  1628.     raise;
  1629.   end;
  1630. end;
  1631.  
  1632. procedure TStreamedConnection.DoDisconnect;
  1633. begin
  1634.   inherited DoDisconnect;
  1635.   InternalClose;
  1636. end;
  1637.  
  1638. function TStreamedConnection.CreateTransport: ITransport;
  1639. begin
  1640.   Result := nil;
  1641. end;
  1642.  
  1643. { TStreamedConnection.IUnknown }
  1644.  
  1645. function TStreamedConnection.QueryInterface(const IID: TGUID; out Obj): HResult;
  1646. begin
  1647.   if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE;
  1648. end;
  1649.  
  1650. function TStreamedConnection._AddRef: Integer;
  1651. begin
  1652.   Inc(FRefCount);
  1653.   Result := FRefCount;
  1654. end;
  1655.  
  1656. function TStreamedConnection._Release: Integer;
  1657. begin
  1658.   Dec(FRefCount);
  1659.   Result := FRefCount;
  1660. end;
  1661.  
  1662. { TStreamedConnection.ISendDataBlock }
  1663.  
  1664. function TStreamedConnection.Send(const Data: IDataBlock; WaitForResult: Boolean): IDataBlock;
  1665. var
  1666.   Msg: TMsg;
  1667.   Context: Integer;
  1668. begin
  1669.   if FSupportCallbacks then
  1670.   begin
  1671.     if not Assigned(FTransport) then Exit;
  1672.     Data._AddRef;
  1673.     PostThreadMessage(FTransport.ThreadID, THREAD_SENDSTREAM, Ord(WaitForResult),
  1674.       Integer(Pointer(Data)));
  1675.     if WaitForResult then
  1676.       while True do
  1677.       begin
  1678.         if GetMessage(Msg, FHandle, THREAD_RECEIVEDSTREAM, THREAD_EXCEPTION) then
  1679.         begin
  1680.           if Msg.message = THREAD_RECEIVEDSTREAM then
  1681.           begin
  1682.             Result := IDataBlock(Msg.lParam);
  1683.             Result._Release;
  1684.             if (Result.Signature and ResultSig) = ResultSig then
  1685.               break else
  1686.               Interpreter.InterpretData(Result);
  1687.           end else
  1688.             DoError(Exception(Msg.lParam));
  1689.         end else
  1690.           raise Exception.CreateRes(@SReturnError);
  1691.       end
  1692.     else
  1693.       GetMessage(Msg, FHandle, THREAD_SENDNOTIFY, THREAD_SENDNOTIFY);
  1694.   end else
  1695.   begin
  1696.     if not Assigned(FTransIntf) then Exit;
  1697.     Context := FTransIntf.Send(Data);
  1698.     Result := FTransIntf.Receive(WaitForResult, Context);
  1699.   end;
  1700.   if Assigned(Result) and ((Result.Signature and asMask) = asError) then
  1701.     Interpreter.InterpretData(Result);
  1702. end;
  1703.  
  1704. { TSocketTransport }
  1705.  
  1706. constructor TSocketTransport.Create;
  1707. begin
  1708.   inherited Create;
  1709.   FInterceptor := nil;
  1710.   FEvent := 0;
  1711. end;
  1712.  
  1713. destructor TSocketTransport.Destroy;
  1714. begin
  1715.   FInterceptor := nil;
  1716.   SetConnected(False);
  1717.   inherited Destroy;
  1718. end;
  1719.  
  1720. function TSocketTransport.GetWaitEvent: THandle;
  1721. begin
  1722.   FEvent := WSACreateEvent;
  1723.   WSAEventSelect(FSocket.SocketHandle, FEvent, FD_READ or FD_CLOSE);
  1724.   Result := FEvent;
  1725. end;
  1726.  
  1727. function TSocketTransport.GetConnected: Boolean;
  1728. begin
  1729.   Result := (FSocket <> nil) and (FSocket.Connected);
  1730. end;
  1731.  
  1732. procedure TSocketTransport.SetConnected(Value: Boolean);
  1733. begin
  1734.   if GetConnected = Value then Exit;
  1735.   if Value then
  1736.   begin
  1737.     if (FAddress = '') and (FHost = '') then
  1738.       raise ESocketConnectionError.CreateRes(@SNoAddress);
  1739.     FClientSocket := TClientSocket.Create(nil);
  1740.     FClientSocket.ClientType := ctBlocking;
  1741.     FSocket := FClientSocket.Socket;
  1742.     FClientSocket.Port := FPort;
  1743.     if FAddress <> '' then
  1744.       FClientSocket.Address := FAddress else
  1745.       FClientSocket.Host := FHost;
  1746.     FClientSocket.Open;
  1747.   end else
  1748.   begin
  1749.     FSocket.Close;
  1750.     FClientSocket.Free;
  1751.     if FEvent <> 0 then WSACloseEvent(FEvent);
  1752.   end;
  1753. end;
  1754.  
  1755. function TSocketTransport.Receive(WaitForInput: Boolean; Context: Integer): IDataBlock;
  1756. var
  1757.   RetLen, Sig, StreamLen: Integer;
  1758.   P: Pointer;
  1759.   FDSet: TFDSet;
  1760.   TimeVal: PTimeVal;
  1761.   RetVal: Integer;
  1762. begin
  1763.   Result := nil;
  1764.   TimeVal := nil;
  1765.   FD_ZERO(FDSet);
  1766.   FD_SET(FSocket.SocketHandle, FDSet);
  1767.   if not WaitForInput then
  1768.   begin
  1769.     New(TimeVal);
  1770.     TimeVal.tv_sec := 0;
  1771.     TimeVal.tv_usec := 1;
  1772.   end;
  1773.   RetVal := select(0, @FDSet, nil, nil, TimeVal);
  1774.   if Assigned(TimeVal) then
  1775.     FreeMem(TimeVal);
  1776.   if RetVal = SOCKET_ERROR then
  1777.     raise ESocketConnectionError.Create(SysErrorMessage(WSAGetLastError));
  1778.   if (RetVal = 0) then Exit;
  1779.   RetLen := FSocket.ReceiveBuf(Sig, SizeOf(Sig));
  1780.   if RetLen <> SizeOf(Sig) then
  1781.     raise ESocketConnectionError.CreateRes(@SSocketReadError);
  1782.   if (Sig and CallSig <> CallSig) and
  1783.      (Sig and ResultSig <> ResultSig) then
  1784.     raise Exception.CreateRes(@SInvalidDataPacket);
  1785.   RetLen := FSocket.ReceiveBuf(StreamLen, SizeOf(StreamLen));
  1786.   if RetLen = 0 then
  1787.     raise ESocketConnectionError.CreateRes(@SSocketReadError);
  1788.   if RetLen <> SizeOf(StreamLen) then
  1789.     raise ESocketConnectionError.CreateRes(@SSocketReadError);
  1790.   Result := TDataBlock.Create as IDataBlock;
  1791.   Result.Size := StreamLen;
  1792.   Result.Signature := Sig;
  1793.   P := Result.Memory;
  1794.   Inc(Integer(P), Result.BytesReserved);
  1795.   while StreamLen > 0 do
  1796.   begin
  1797.     RetLen := FSocket.ReceiveBuf(P^, StreamLen);
  1798.     if RetLen = 0 then
  1799.       raise ESocketConnectionError.CreateRes(@SSocketReadError);
  1800.     if RetLen > 0 then
  1801.     begin
  1802.       Dec(StreamLen, RetLen);
  1803.       Inc(Integer(P), RetLen);
  1804.     end;
  1805.   end;
  1806.   if StreamLen <> 0 then
  1807.     raise ESocketConnectionError.CreateRes(@SInvalidDataPacket);
  1808.   InterceptIncoming(Result);
  1809. end;
  1810.  
  1811. function TSocketTransport.Send(const Data: IDataBlock): Integer;
  1812. var
  1813.   P: Pointer;
  1814. begin
  1815.   Result := 0;
  1816.   InterceptOutgoing(Data);
  1817.   P := Data.Memory;
  1818.   FSocket.SendBuf(P^, Data.Size + Data.BytesReserved);
  1819. end;
  1820.  
  1821. function TSocketTransport.CheckInterceptor: Boolean;
  1822. var
  1823.   GUID: TGUID;
  1824. begin
  1825.   if not Assigned(FInterceptor) and (FInterceptGUID <> '') then
  1826.     if not FCreateAttempted then
  1827.     try
  1828.       FCreateAttempted := True;
  1829.       Guid := StringToGuid(FInterceptGUID);
  1830.       FInterceptor := CreateComObject(Guid) as IDataIntercept;
  1831.     except
  1832.       { raise no exception if the creating failed }
  1833.     end;
  1834.   Result := Assigned(FInterceptor);
  1835. end;
  1836.  
  1837. procedure TSocketTransport.InterceptIncoming(const Data: IDataBlock);
  1838. begin
  1839.   if CheckInterceptor then
  1840.     FInterceptor.DataIn(Data);
  1841. end;
  1842.  
  1843. procedure TSocketTransport.InterceptOutgoing(const Data: IDataBlock);
  1844. begin
  1845.   if CheckInterceptor then
  1846.     FInterceptor.DataOut(Data);
  1847. end;
  1848.  
  1849. { TSocketConnection }
  1850.  
  1851. constructor TSocketConnection.Create(AOwner: TComponent);
  1852. begin
  1853.   inherited Create(AOwner);
  1854.   FPort := 211;
  1855. end;
  1856.  
  1857. function TSocketConnection.IsAddressStored: Boolean;
  1858. begin
  1859.   Result := (ObjectBroker = nil) and (Address <> '');
  1860. end;
  1861.  
  1862. procedure TSocketConnection.SetAddress(Value: string);
  1863. begin
  1864.   if Value <> '' then
  1865.     FHost := '';
  1866.   FAddress := Value;
  1867. end;
  1868.  
  1869. function TSocketConnection.IsHostStored: Boolean;
  1870. begin
  1871.   Result := (ObjectBroker = nil) and (Host <> '');
  1872. end;
  1873.  
  1874. procedure TSocketConnection.SetHost(Value: string);
  1875. begin
  1876.   if Value <> '' then
  1877.     FAddress := '';
  1878.   FHost := Value;
  1879. end;
  1880.  
  1881. function TSocketConnection.CreateTransport: ITransport;
  1882. var
  1883.   SocketTransport: TSocketTransport;
  1884. begin
  1885.   if SupportCallbacks then
  1886.     if not LoadWinSock2 then raise Exception.CreateRes(@SNoWinSock2);
  1887.   if (FAddress = '') and (FHost = '') then
  1888.     raise ESocketConnectionError.CreateRes(@SNoAddress);
  1889.   SocketTransport := TSocketTransport.Create;
  1890.   SocketTransport.Host := FHost;
  1891.   SocketTransport.Address := FAddress;
  1892.   SocketTransport.Port := FPort;
  1893.   SocketTransport.InterceptGUID := InterceptGUID;
  1894.   Result := SocketTransport as ITransport;
  1895. end;
  1896.  
  1897. procedure TSocketConnection.DoConnect;
  1898. var
  1899.   Comp: string;
  1900.   p, i: Integer;
  1901. begin
  1902.   if (ObjectBroker <> nil) then
  1903.   begin
  1904.     repeat
  1905.       if FAddress <> '' then
  1906.         Comp := FAddress else
  1907.       if FHost <> '' then
  1908.         Comp := FHost else
  1909.       if ServerGUID <> '' then
  1910.         Comp := ObjectBroker.GetComputerForGUID(GetServerCLSID) else
  1911.         Comp := ObjectBroker.GetComputerForProgID(ServerName);
  1912.       try
  1913.         p := ObjectBroker.GetPortForComputer(Comp);
  1914.         if p > 0 then
  1915.           FPort := p;
  1916.         p := 0;
  1917.         for i := 1 to Length(Comp) do
  1918.           if (Comp[i] in ['0'..'9', '.']) then
  1919.             Inc(p, Ord(Comp[i] = '.')) else
  1920.             break;
  1921.         if p <> 3 then
  1922.           Host := Comp else
  1923.           Address := Comp;
  1924.         inherited DoConnect;
  1925.         ObjectBroker.SetConnectStatus(Comp, True);
  1926.       except
  1927.         ObjectBroker.SetConnectStatus(Comp, False);
  1928.         FAddress := '';
  1929.         FHost := '';
  1930.       end;
  1931.     until Connected;
  1932.   end else
  1933.     inherited DoConnect;
  1934. end;
  1935.  
  1936. { TWebConnection }
  1937.  
  1938. constructor TWebConnection.Create(AOwner: TComponent);
  1939. begin
  1940.   inherited Create(AOwner);
  1941.   FInterpreter := TDataBlockInterpreter.Create(Self, SWeb);
  1942.   SupportCallbacks := False;
  1943.   FInetRoot := nil;
  1944.   FInetConnect := nil;
  1945.   FAgent := 'MIDAS 3.0';
  1946.   URL := SDefaultURL;
  1947. end;
  1948.  
  1949. destructor TWebConnection.Destroy;
  1950. begin
  1951.   SetConnected(False);
  1952.   FInterpreter.Free;
  1953.   inherited Destroy;
  1954. end;
  1955.  
  1956. procedure TWebConnection.SetURL(const Value: string);
  1957. var
  1958.   URLComp: TURLComponents;
  1959.   P: PChar;
  1960. begin
  1961.   SetConnected(False);
  1962.   if FURL = Value then Exit;
  1963.   if Value <> '' then
  1964.   begin
  1965.     FillChar(URLComp, SizeOf(URLComp), 0);
  1966.     URLComp.dwStructSize := SizeOf(URLComp);
  1967.     URLComp.dwSchemeLength := 1;
  1968.     URLComp.dwHostNameLength := 1;
  1969.     URLComp.dwURLPathLength := 1;
  1970.     P := PChar(Value);
  1971.     InternetCrackUrl(P, 0, 0, URLComp);
  1972.     if not (URLComp.nScheme in [INTERNET_SCHEME_HTTP, INTERNET_SCHEME_HTTPS]) then
  1973.       raise Exception.CreateRes(@SInvalidURL);
  1974.     FURLScheme := URLComp.nScheme;
  1975.     FURLPort := URLComp.nPort;
  1976.     FURLHost := Copy(Value, URLComp.lpszHostName - P + 1, URLComp.dwHostNameLength);
  1977.     FURLSite := Copy(Value, URLComp.lpszUrlPath - P + 1, URLComp.dwUrlPathLength);
  1978.   end else
  1979.   begin
  1980.     FURLPort := 0;
  1981.     FURLHost := '';
  1982.     FURLSite := '';
  1983.     FURLScheme := 0;
  1984.   end;
  1985.   FURL := Value;
  1986. end;
  1987.  
  1988. function TWebConnection.CreateTransport: ITransport;
  1989. begin
  1990.   if FURLHost = '' then
  1991.     raise Exception.CreateRes(@SURLRequired);
  1992.   Result := Self;
  1993. end;
  1994.  
  1995. function TWebConnection.IsURLStored: Boolean;
  1996. begin
  1997.   Result := (ObjectBroker = nil) and (URL <> '');
  1998. end;
  1999.  
  2000. procedure TWebConnection.Check(Error: Boolean);
  2001. var
  2002.   ErrCode: Integer;
  2003.   S: string;
  2004. begin
  2005.   ErrCode := GetLastError;
  2006.   if Error and (ErrCode <> 0) then
  2007.   begin
  2008.     SetLength(S, 256);
  2009.     FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, Pointer(GetModuleHandle('wininet.dll')),
  2010.       ErrCode, 0, PChar(S), Length(S), nil);
  2011.     SetLength(S, StrLen(PChar(S)));
  2012.     while (Length(S) > 0) and (S[Length(S)] in [#10, #13]) do
  2013.       SetLength(S, Length(S) - 1);
  2014.     raise Exception.Create(S);
  2015.   end;
  2016. end;
  2017.  
  2018. function TWebConnection.GetWaitEvent: THandle;
  2019. begin
  2020.   Result := 0;
  2021. end;
  2022.  
  2023. function TWebConnection.Transport_GetConnected: Boolean;
  2024. begin
  2025.   Result := Assigned(FinetConnect);
  2026. end;
  2027.  
  2028. procedure TWebConnection.Transport_SetConnected(Value: Boolean);
  2029. var
  2030.   AccessType: Integer;
  2031. begin
  2032.   if Value and not GetConnected then
  2033.   begin
  2034.     if Length(FProxy) > 0 then
  2035.       AccessType := INTERNET_OPEN_TYPE_PROXY else
  2036.       AccessType := INTERNET_OPEN_TYPE_PRECONFIG;
  2037.     FInetRoot := InternetOpen(PChar(Agent), AccessType, PChar(FProxy), PChar(FProxyByPass), 0);
  2038.     if InternetAttemptConnect(0) <> ERROR_SUCCESS then SysUtils.Abort;
  2039.     Check(not Assigned(FInetRoot));
  2040.     try
  2041.       FInetConnect := InternetConnect(FInetRoot, PChar(FURLHost), FURLPort, PChar(FUserName),
  2042.         PChar(FPassword), INTERNET_SERVICE_HTTP, 0, Cardinal(Self));
  2043.       Check(not Assigned(FInetConnect));
  2044.     except
  2045.       InternetCloseHandle(FInetRoot);
  2046.     end;
  2047.   end else
  2048.   if not Value then
  2049.   begin
  2050.     if Assigned(FInetConnect) then
  2051.       InternetCloseHandle(FInetConnect);
  2052.     FInetConnect := nil;
  2053.     if Assigned(FInetRoot) then
  2054.       InternetCloseHandle(FInetRoot);
  2055.     FInetRoot := nil;
  2056.   end;
  2057. end;
  2058.  
  2059. function TWebConnection.Receive(WaitForInput: Boolean; Context: Integer): IDataBlock;
  2060. var
  2061.   Size, Downloaded, Status, Len, Index: DWord;
  2062.   S: string;
  2063. begin
  2064.   Len := SizeOf(Status);
  2065.   Index := 0;
  2066.   if HttpQueryInfo(Pointer(Context), HTTP_QUERY_STATUS_CODE or HTTP_QUERY_FLAG_NUMBER,
  2067.     @Status, Len, Index) and (Status >= 300) then
  2068.   begin
  2069.     Index := 0;
  2070.     SetLength(S, Size);
  2071.     if HttpQueryInfo(Pointer(Context), HTTP_QUERY_STATUS_TEXT, @S[1], Size, Index) then
  2072.     begin
  2073.       SetLength(S, Size);
  2074.       raise Exception.CreateFmt('%s (%d)', [S, Status]);
  2075.     end;
  2076.   end;
  2077.   Len := 0;
  2078.   repeat
  2079.     Check(not InternetQueryDataAvailable(Pointer(Context), Size, 0, 0));
  2080.     if Size > 0 then
  2081.     begin
  2082.       SetLength(S, Size);
  2083.       Check(not InternetReadFile(Pointer(Context), @S[1], Size, Downloaded));
  2084.       if not Assigned(Result) then
  2085.       begin
  2086.         Result := TDataBlock.Create;
  2087.         Len := Result.InitData(@S[1], Downloaded, False);
  2088.       end else
  2089.         Result.Write(S[1], Downloaded);
  2090.     end;
  2091.   until Size = 0;
  2092.   if Assigned(Result) and (Len <> DWord(Result.Size)) then
  2093.     raise Exception.CreateRes(@SInvalidDataPacket);
  2094. end;
  2095.  
  2096. function TWebConnection.Send(const Data: IDataBlock): Integer;
  2097. var
  2098.   Request: HINTERNET;
  2099.   RetVal, Flags: DWord;
  2100.   P: Pointer;
  2101.   AcceptTypes: array of PChar;
  2102. begin
  2103.   SetLength(AcceptTypes, 2);
  2104.   AcceptTypes[0] := PChar('application/octet-stream');
  2105.   AcceptTypes[1] := nil;
  2106.   Flags := INTERNET_FLAG_KEEP_CONNECTION or INTERNET_FLAG_NO_CACHE_WRITE;
  2107.   if FURLScheme = INTERNET_SCHEME_HTTPS then
  2108.     Flags := Flags or INTERNET_FLAG_SECURE;
  2109.   Request := HttpOpenRequest(FInetConnect, 'POST', PChar(FURLSite), nil,
  2110.     nil, Pointer(AcceptTypes), Flags, Integer(Self));
  2111.   Check(not Assigned(Request));
  2112.   while True do
  2113.   begin
  2114.     Check(not HttpSendRequest(Request, nil, 0, Data.Memory, Data.Size + Data.BytesReserved));
  2115.     RetVal := InternetErrorDlg(GetDesktopWindow(), Request, GetLastError,
  2116.       FLAGS_ERROR_UI_FILTER_FOR_ERRORS or FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS or
  2117.       FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, P);
  2118.     case RetVal of
  2119.       ERROR_SUCCESS: break;
  2120.       ERROR_CANCELLED: SysUtils.Abort;
  2121.       ERROR_INTERNET_FORCE_RETRY: {Retry the operation};
  2122.     end;
  2123.   end;
  2124.   Result := Integer(Request)
  2125. end;
  2126.  
  2127. procedure TWebConnection.DoConnect;
  2128. begin
  2129.   if (ObjectBroker <> nil) then
  2130.   begin
  2131.     repeat
  2132.       if URL = '' then
  2133.         if ServerGUID <> '' then
  2134.           URL := ObjectBroker.GetComputerForGUID(GetServerCLSID) else
  2135.           URL := ObjectBroker.GetComputerForProgID(ServerName);
  2136.       try
  2137.         inherited DoConnect;
  2138.         ObjectBroker.SetConnectStatus(URL, True);
  2139.       except
  2140.         ObjectBroker.SetConnectStatus(URL, False);
  2141.         URL := '';
  2142.       end;
  2143.     until Connected;
  2144.   end else
  2145.     inherited DoConnect;
  2146. end;
  2147.  
  2148. initialization
  2149. finalization
  2150.   FreeWinSock2;
  2151. end.
  2152.