ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/IBServices.pas
(Generate patch)

Comparing ibx/trunk/runtime/IBServices.pas (file contents):
Revision 37 by tony, Mon Feb 15 14:44:25 2016 UTC vs.
Revision 45 by tony, Tue Dec 6 10:33:46 2016 UTC

# Line 42 | Line 42
42   unit IBServices;
43  
44   {$Mode Delphi}
45 + {$codepage UTF8}
46  
47   interface
48  
# Line 51 | Line 52 | uses
52   {$ELSE}
53    unix,
54   {$ENDIF}
55 <  SysUtils, Classes, IBHeader, IB, IBExternals, CustApp;
55 >  SysUtils, Classes, IBHeader, IB, IBExternals, CustApp, IBTypes, IBSQL;
56  
57   const
58    DefaultBufferSize = 32000;
59  
60    SPBPrefix = 'isc_spb_';
61 +  isc_spb_last_spb_constant = 12;
62    SPBConstantNames: array[1..isc_spb_last_spb_constant] of String = (
63      'user_name',
64      'sys_user_name',
# Line 73 | Line 75 | const
75    );
76  
77    SPBConstantValues: array[1..isc_spb_last_spb_constant] of Integer = (
78 <    isc_spb_user_name_mapped_to_server,
79 <    isc_spb_sys_user_name_mapped_to_server,
80 <    isc_spb_sys_user_name_enc_mapped_to_server,
81 <    isc_spb_password_mapped_to_server,
82 <    isc_spb_password_enc_mapped_to_server,
83 <    isc_spb_command_line_mapped_to_server,
84 <    isc_spb_dbname_mapped_to_server,
85 <    isc_spb_verbose_mapped_to_server,
86 <    isc_spb_options_mapped_to_server,
87 <    isc_spb_connect_timeout_mapped_to_server,
88 <    isc_spb_dummy_packet_interval_mapped_to_server,
89 <    isc_spb_sql_role_name_mapped_to_server
78 >    isc_spb_user_name,
79 >    isc_spb_sys_user_name,
80 >    isc_spb_sys_user_name_enc,
81 >    isc_spb_password,
82 >    isc_spb_password_enc,
83 >    isc_spb_command_line,
84 >    isc_spb_dbname,
85 >    isc_spb_verbose,
86 >    isc_spb_options,
87 >    isc_spb_connect_timeout,
88 >    isc_spb_dummy_packet_interval,
89 >    isc_spb_sql_role_name
90    );
91  
92   type
91  TProtocol = (TCP, SPX, NamedPipe, Local);
93    TOutputBufferOption = (ByLine, ByChunk);
94  
95    TIBCustomService = class;
# Line 100 | Line 101 | type
101  
102    TIBCustomService = class(TComponent)
103    private
103    FIBLoaded: Boolean;
104      FParamsChanged : Boolean;
105 <    FSPB, FQuerySPB : PChar;
106 <    FSPBLength, FQuerySPBLength : Short;
105 >    FQueryParams: String;
106 >    FSPB : ISPB;
107 >    FSRB: ISRB;
108 >    FSQPB: ISQPB;
109      FTraceFlags: TTraceFlags;
110      FOnLogin: TLoginEvent;
111      FLoginPrompt: Boolean;
110    FBufferSize: Integer;
111    FOutputBuffer: PChar;
112    FQueryParams: String;
112      FServerName: string;
113 <    FHandle: TISC_SVC_HANDLE;
113 >    FService: IServiceManager;
114      FStreamedActive  : Boolean;
115      FOnAttach: TNotifyEvent;
116      FOutputBufferOption: TOutputBufferOption;
117      FProtocol: TProtocol;
118      FParams: TStrings;
119 +    FServiceQueryResults: IServiceQueryResults;
120      function GetActive: Boolean;
121      function GetServiceParamBySPB(const Idx: Integer): String;
122 +    function GetSQPB: ISQPB;
123 +    function GetSRB: ISRB;
124      procedure SetActive(const Value: Boolean);
123    procedure SetBufferSize(const Value: Integer);
125      procedure SetParams(const Value: TStrings);
126      procedure SetServerName(const Value: string);
127      procedure SetProtocol(const Value: TProtocol);
128 +    procedure SetService(AValue: IServiceManager);
129      procedure SetServiceParamBySPB(const Idx: Integer;
130        const Value: String);
131 <    function IndexOfSPBConst(st: String): Integer;
131 >    function IndexOfSPBConst(action: byte): Integer;
132 >    function GetSPBConstName(action: byte): string;
133      procedure ParamsChange(Sender: TObject);
134      procedure ParamsChanging(Sender: TObject);
135      procedure CheckServerName;
136 <    function Call(ErrCode: ISC_STATUS; RaiseError: Boolean): ISC_STATUS;
134 <    function ParseString(var RunLen: Integer): string;
135 <    function ParseInteger(var RunLen: Integer): Integer;
136 <    procedure GenerateSPB(sl: TStrings; var SPB: String; var SPBLength: Short);
136 >    function GenerateSPB(sl: TStrings): ISPB;
137  
138    protected
139      procedure Loaded; override;
140 <    function Login: Boolean;
140 >    function Login(var aServerName: string): Boolean;
141      procedure CheckActive;
142      procedure CheckInactive;
143      procedure HandleException(Sender: TObject);
144    property OutputBuffer : PChar read FOutputBuffer;
145    property OutputBufferOption : TOutputBufferOption read FOutputBufferOption write FOutputBufferOption;
146    property BufferSize : Integer read FBufferSize write SetBufferSize default DefaultBufferSize;
144      procedure InternalServiceQuery;
145 <    property ServiceQueryParams: String read FQueryParams write FQueryParams;
145 >    property SRB: ISRB read GetSRB;
146 >    property SQPB: ISQPB read GetSQPB;
147 >    property ServiceQueryResults: IServiceQueryResults read FServiceQueryResults;
148  
149    public
150      constructor Create(AOwner: TComponent); override;
151      destructor Destroy; override;
152      procedure Attach;
153      procedure Detach;
154 <    property Handle: TISC_SVC_HANDLE read FHandle;
154 >    property ServiceIntf: IServiceManager read FService write SetService;
155      property ServiceParamBySPB[const Idx: Integer]: String read GetServiceParamBySPB
156                                                        write SetServiceParamBySPB;
157    published
# Line 228 | Line 227 | type
227      FLicenseMaskInfo: TLicenseMaskInfo;
228      FVersionInfo: TVersionInfo;
229      FConfigParams: TConfigParams;
231    procedure ParseConfigFileData(var RunLen: Integer);
230    public
231      constructor Create(AOwner: TComponent); override;
232      destructor Destroy; override;
# Line 247 | Line 245 | type
245      property Options : TPropertyOptions read FOptions write FOptions;
246    end;
247  
248 +  { TIBControlService }
249 +
250    TIBControlService = class (TIBCustomService)
251    private
252    FStartParams: String;
253    FStartSPB: PChar;
254    FStartSPBLength: Integer;
252      function GetIsServiceRunning: Boolean;
253    protected
254 <    property ServiceStartParams: String read FStartParams write FStartParams;
258 <    procedure SetServiceStartOptions; virtual;
259 <    procedure ServiceStartAddParam (Value: string; param: Integer); overload;
260 <    procedure ServiceStartAddParam (Value: Integer; param: Integer); overload;
254 >    procedure CheckServiceNotRunning;
255      procedure InternalServiceStart;
256 +    procedure SetServiceStartOptions; virtual;
257  
258    public
259      constructor Create(AOwner: TComponent); override;
# Line 266 | Line 261 | type
261      property IsServiceRunning : Boolean read GetIsServiceRunning;
262    end;
263  
264 +  { TIBControlAndQueryService }
265 +
266    TIBControlAndQueryService = class (TIBControlService)
267    private
268      FEof: Boolean;
# Line 277 | Line 274 | type
274      constructor create (AOwner: TComponent); override;
275      function GetNextLine : String;
276      function GetNextChunk : String;
277 +    function WriteNextChunk(stream: TStream): integer;
278      property Eof: boolean read FEof;
281  published
282    property BufferSize;
279    end;
280  
281    TShutdownMode = (Forced, DenyTransaction, DenyAttachment);
# Line 314 | Line 310 | type
310    published
311    end;
312  
313 <  TStatOption = (DataPages, DbLog, HeaderPages, IndexPages, SystemRelations);
313 >  TStatOption = (DataPages, {DbLog,} HeaderPages, IndexPages, SystemRelations);
314    TStatOptions = set of TStatOption;
315  
316    TIBStatisticalService = class(TIBControlAndQueryService)
# Line 330 | Line 326 | type
326      property Options :  TStatOptions read FOptions write FOptions;
327    end;
328  
329 +  TBackupLocation = (flServerSide,flClientSide);
330 +
331 +  { TIBBackupRestoreService }
332  
333    TIBBackupRestoreService = class(TIBControlAndQueryService)
334    private
335 +    FBackupFileLocation: TBackupLocation;
336      FVerbose: Boolean;
337    protected
338    public
339 +    constructor Create(AOwner: TComponent); override;
340    published
341      property Verbose : Boolean read FVerbose write FVerbose default False;
342 +    property BackupFileLocation: TBackupLocation read FBackupFileLocation
343 +                                                      write FBackupFileLocation default flServerSide;
344    end;
345  
346    TBackupOption = (IgnoreChecksums, IgnoreLimbo, MetadataOnly, NoGarbageCollection,
# Line 369 | Line 372 | type
372      Replace, CreateNewDB, UseAllSpace);
373  
374    TRestoreOptions = set of TRestoreOption;
375 +
376 +  { TIBRestoreService }
377 +
378    TIBRestoreService = class (TIBBackupRestoreService)
379    private
380      FDatabaseName: TStrings;
# Line 376 | Line 382 | type
382      FOptions: TRestoreOptions;
383      FPageSize: Integer;
384      FPageBuffers: Integer;
385 +    FSendBytes: integer;
386      procedure SetBackupFile(const Value: TStrings);
387      procedure SetDatabaseName(const Value: TStrings);
388    protected
# Line 383 | Line 390 | type
390    public
391      constructor Create(AOwner: TComponent); override;
392      destructor Destroy; override;
393 +    function SendNextChunk(stream: TStream; var line: String): integer;
394    published
395      { a name=value pair of filename and length }
396      property DatabaseName: TStrings read FDatabaseName write SetDatabaseName;
# Line 513 | Line 521 | type
521   implementation
522  
523   uses
524 <  IBIntf , IBSQLMonitor, Math;
524 >  IBSQLMonitor, Math, FBMessages;
525 >
526 > { TIBBackupRestoreService }
527 >
528 > constructor TIBBackupRestoreService.Create(AOwner: TComponent);
529 > begin
530 >  inherited Create(AOwner);
531 >  FBackupFileLocation := flServerSide;
532 > end;
533  
534   { TIBCustomService }
535  
536   procedure TIBCustomService.Attach;
537 < var
522 <  SPB: String;
523 <  ConnectString: String;
537 > var aServerName: string;
538   begin
539    CheckInactive;
540    CheckServerName;
541  
542 <  if FLoginPrompt and not Login then
542 >  aServerName := FServerName;
543 >
544 >  if FLoginPrompt and not Login(aServerName) then
545      IBError(ibxeOperationCancelled, [nil]);
546  
547    { Generate a new SPB if necessary }
548    if FParamsChanged then
549    begin
550      FParamsChanged := False;
551 <    GenerateSPB(FParams, SPB, FSPBLength);
536 <    IBAlloc(FSPB, 0, FsPBLength);
537 <    Move(SPB[1], FSPB[0], FSPBLength);
538 <  end;
539 <  case FProtocol of
540 <    TCP: ConnectString := FServerName + ':service_mgr'; {do not localize}
541 <    SPX: ConnectString := FServerName + '@service_mgr'; {do not localize}
542 <    NamedPipe: ConnectString := '\\' + FServerName + '\service_mgr'; {do not localize}
543 <    Local: ConnectString := 'service_mgr'; {do not localize}
544 <  end;
545 <  if call(isc_service_attach(StatusVector, Length(ConnectString),
546 <                         PChar(ConnectString), @FHandle,
547 <                         FSPBLength, FSPB), False) > 0 then
548 <  begin
549 <    FHandle := nil;
550 <    IBDataBaseError;
551 >    FSPB := GenerateSPB(FParams);
552    end;
553  
554 +  FService := FirebirdAPI.GetServiceManager(aServerName,FProtocol,FSPB);
555 +
556    if Assigned(FOnAttach) then
557      FOnAttach(Self);
558  
# Line 570 | Line 573 | begin
573    end;
574   end;
575  
576 < function TIBCustomService.Login: Boolean;
576 > function TIBCustomService.Login(var aServerName: string): Boolean;
577   var
578    IndexOfUser, IndexOfPassword: Integer;
579    Username, Password: String;
# Line 583 | Line 586 | begin
586        LoginParams.Assign(Params);
587        FOnLogin(Self, LoginParams);
588        Params.Assign (LoginParams);
589 +      aServerName := ServerName;
590      finally
591        LoginParams.Free;
592      end;
# Line 590 | Line 594 | begin
594    else
595    if assigned(IBGUIInterface)  then
596    begin
597 <    IndexOfUser := IndexOfSPBConst(SPBConstantNames[isc_spb_user_name]);
597 >    IndexOfUser := IndexOfSPBConst(isc_spb_user_name);
598      if IndexOfUser <> -1 then
599        Username := Copy(Params[IndexOfUser],
600                                           Pos('=', Params[IndexOfUser]) + 1, {mbcs ok}
601                                           Length(Params[IndexOfUser]));
602 <    IndexOfPassword := IndexOfSPBConst(SPBConstantNames[isc_spb_password]);
602 >    IndexOfPassword := IndexOfSPBConst(isc_spb_password);
603      if IndexOfPassword <> -1 then
604        Password := Copy(Params[IndexOfPassword],
605                                           Pos('=', Params[IndexOfPassword]) + 1, {mbcs ok}
606                                           Length(Params[IndexOfPassword]));
607 <    result := IBGUIInterface.ServerLoginDialog(serverName, Username, Password);
607 >    result := IBGUIInterface.ServerLoginDialog(aServerName, Username, Password);
608      if result then
609      begin
610 <      IndexOfPassword := IndexOfSPBConst(SPBConstantNames[isc_spb_password]);
610 >      IndexOfPassword := IndexOfSPBConst(isc_spb_password);
611        if IndexOfUser = -1 then
612 <        Params.Add(SPBConstantNames[isc_spb_user_name] + '=' + Username)
612 >        Params.Add(GetSPBConstName(isc_spb_user_name) + '=' + Username)
613        else
614 <        Params[IndexOfUser] := SPBConstantNames[isc_spb_user_name] +
614 >        Params[IndexOfUser] := GetSPBConstName(isc_spb_user_name) +
615                                   '=' + Username;
616        if IndexOfPassword = -1 then
617 <        Params.Add(SPBConstantNames[isc_spb_password] + '=' + Password)
617 >        Params.Add(GetSPBConstName(isc_spb_password) + '=' + Password)
618        else
619 <        Params[IndexOfPassword] := SPBConstantNames[isc_spb_password] +
619 >        Params[IndexOfPassword] := GetSPBConstName(isc_spb_password) +
620                                       '=' + Password;
621      end
622    end
# Line 624 | Line 628 | procedure TIBCustomService.CheckActive;
628   begin
629    if FStreamedActive and (not Active) then
630      Loaded;
631 <  if FHandle = nil then
631 >  if FService = nil then
632      IBError(ibxeServiceActive, [nil]);
633   end;
634  
635   procedure TIBCustomService.CheckInactive;
636   begin
637 <  if FHandle <> nil then
637 >  if FService <> nil then
638      IBError(ibxeServiceInActive, [nil]);
639   end;
640  
# Line 653 | Line 657 | end;
657   constructor TIBCustomService.Create(AOwner: TComponent);
658   begin
659    inherited Create(AOwner);
656  FIBLoaded := False;
657  CheckIBLoaded;
658  FIBLoaded := True;
660    FserverName := '';
661    FParams := TStringList.Create;
662    FParamsChanged := True;
663    TStringList(FParams).OnChange := ParamsChange;
664    TStringList(FParams).OnChanging := ParamsChanging;
664  FSPB := nil;
665  FQuerySPB := nil;
666  FBufferSize := DefaultBufferSize;
667  FHandle := nil;
665    FLoginPrompt := True;
666    FTraceFlags := [];
667 <  FOutputbuffer := nil;
667 >  FService := nil;
668 >  FSRB := nil;
669 >  FSPB := nil;
670 >  FServiceQueryResults := nil;
671    FProtocol := Local;
672    if (AOwner <> nil) and
673       (AOwner is TCustomApplication) and
# Line 677 | Line 677 | end;
677  
678   destructor TIBCustomService.Destroy;
679   begin
680 <  if FIBLoaded then
681 <  begin
682 <    if FHandle <> nil then
680 >  if FService <> nil then
681        Detach;
682 <    FreeMem(FSPB);
683 <    FSPB := nil;
684 <    FParams.Free;
685 <  end;
688 <  ReallocMem(FOutputBuffer, 0);
682 >  FSRB := nil;
683 >  FSPB := nil;
684 >  FParams.Free;
685 >  FServiceQueryResults := nil;
686    inherited Destroy;
687   end;
688  
689   procedure TIBCustomService.Detach;
690   begin
691    CheckActive;
692 <  if (Call(isc_service_detach(StatusVector, @FHandle), False) > 0) then
693 <  begin
697 <    FHandle := nil;
698 <    IBDataBaseError;
699 <  end
700 <  else
701 <    FHandle := nil;
692 >  FService.Detach;
693 >  FService := nil;
694    MonitorHook.ServiceDetach(Self);
695   end;
696  
697   function TIBCustomService.GetActive: Boolean;
698   begin
699 <  result := FHandle <> nil;
699 >  result := FService <> nil;
700   end;
701  
702   function TIBCustomService.GetServiceParamBySPB(const Idx: Integer): String;
# Line 713 | Line 705 | var
705   begin
706    if (Idx > 0) and (Idx <= isc_spb_last_spb_constant) then
707    begin
708 <    ConstIdx := IndexOfSPBConst(SPBConstantNames[Idx]);
708 >    ConstIdx := IndexOfSPBConst(Idx);
709      if ConstIdx = -1 then
710        result := ''
711      else
# Line 730 | Line 722 | begin
722      result := '';
723   end;
724  
725 + function TIBCustomService.GetSQPB: ISQPB;
726 + begin
727 +  CheckActive;
728 +  if FSQPB = nil then
729 +    FSQPB := FService.AllocateSQPB;
730 +  Result := FSQPB;
731 + end;
732 +
733 + function TIBCustomService.GetSRB: ISRB;
734 + begin
735 +  CheckActive;
736 +  if FSRB = nil then
737 +    FSRB := FService.AllocateSRB;
738 +  Result := FSRB;
739 + end;
740 +
741   procedure TIBCustomService.InternalServiceQuery;
742   begin
743 <  FQuerySPBLength := Length(FQueryParams);
744 <  if FQuerySPBLength = 0 then
745 <    IBError(ibxeQueryParamsError, [nil]);
738 <  IBAlloc(FQuerySPB, 0, FQuerySPBLength);
739 <  Move(FQueryParams[1], FQuerySPB[0], FQuerySPBLength);
740 <  if (FOutputBuffer = nil) then
741 <    IBAlloc(FOutputBuffer, 0, FBufferSize);
742 <  try
743 <    if call(isc_service_query(StatusVector, @FHandle, nil, 0, nil,
744 <                           FQuerySPBLength, FQuerySPB,
745 <                           FBufferSize, FOutputBuffer), False) > 0 then
746 <    begin
747 <      FHandle := nil;
748 <      IBDataBaseError;
749 <    end;
750 <  finally
751 <    FreeMem(FQuerySPB);
752 <    FQuerySPB := nil;
753 <    FQuerySPBLength := 0;
754 <    FQueryParams := '';
755 <  end;
743 >  FServiceQueryResults := FService.Query(FSQPB,FSRB);
744 >  FSQPB := nil;
745 >  FSRB := nil;
746    MonitorHook.ServiceQuery(Self);
747   end;
748  
# Line 761 | Line 751 | begin
751    if csReading in ComponentState then
752      FStreamedActive := Value
753    else
754 <    if Value <> Active then  
754 >    if Value <> Active then
755 >    begin
756        if Value then
757          Attach
758        else
759          Detach;
760 < end;
761 <
762 < procedure TIBCustomService.SetBufferSize(const Value: Integer);
763 < begin
764 <  if (FOutputBuffer <> nil) and (Value <> FBufferSize) then
765 <    IBAlloc(FOutputBuffer, 0, FBufferSize);
760 >    end
761 >   else if Value then
762 >   begin
763 >     FService.Detach;
764 >     FService.Attach;
765 >   end;
766   end;
767  
768   procedure TIBCustomService.SetParams(const Value: TStrings);
# Line 799 | Line 790 | begin
790    end;
791   end;
792  
793 + procedure TIBCustomService.SetService(AValue: IServiceManager);
794 + begin
795 +  if FService = AValue then Exit;
796 +  FService := AValue;
797 +  if AValue <> nil then
798 +    FServerName := FService.getServerName;
799 + end;
800 +
801   procedure TIBCustomService.SetServiceParamBySPB(const Idx: Integer;
802    const Value: String);
803   var
804    ConstIdx: Integer;
805   begin
806 <  ConstIdx := IndexOfSPBConst(SPBConstantNames[Idx]);
806 >  ConstIdx := IndexOfSPBConst(Idx);
807    if (Value = '') then
808    begin
809      if ConstIdx <> -1 then
# Line 813 | Line 812 | begin
812    else
813    begin
814      if (ConstIdx = -1) then
815 <      Params.Add(SPBConstantNames[Idx] + '=' + Value)
815 >      Params.Add(GetSPBConstName(Idx) + '=' + Value)
816      else
817 <      Params[ConstIdx] := SPBConstantNames[Idx] + '=' + Value;
817 >      Params[ConstIdx] := GetSPBConstName(Idx) + '=' + Value;
818    end;
819   end;
820  
821 < function TIBCustomService.IndexOfSPBConst(st: String): Integer;
821 > function TIBCustomService.IndexOfSPBConst(action: byte): Integer;
822   var
823 <  i, pos_of_str: Integer;
823 >  i,  pos_of_str: Integer;
824 >  st: string;
825   begin
826    result := -1;
827 +  st := GetSPBConstName(action);
828 +  if st <> '' then
829    for i := 0 to Params.Count - 1 do
830    begin
831      pos_of_str := Pos(st, Params[i]); {mbcs ok}
# Line 835 | Line 837 | begin
837    end;
838   end;
839  
840 + function TIBCustomService.GetSPBConstName(action: byte): string;
841 + var i: integer;
842 + begin
843 +  Result := '';
844 +  for i := Low(SPBConstantValues) to High(SPBConstantValues) do
845 +    if SPBConstantValues[i] = action then
846 +    begin
847 +      Result := SPBConstantNames[i];
848 +      break;
849 +    end;
850 + end;
851 +
852   procedure TIBCustomService.ParamsChange(Sender: TObject);
853   begin
854    FParamsChanged := True;
# Line 851 | Line 865 | begin
865      IBError(ibxeServerNameMissing, [nil]);
866   end;
867  
854 function TIBCustomService.Call(ErrCode: ISC_STATUS;
855  RaiseError: Boolean): ISC_STATUS;
856 begin
857  result := ErrCode;
858  if RaiseError and (ErrCode > 0) then
859    IBDataBaseError;
860 end;
861
862 function TIBCustomService.ParseString(var RunLen: Integer): string;
863 var
864  Len: UShort;
865  tmp: Char;
866 begin
867  Len := isc_vax_integer(OutputBuffer + RunLen, 2);
868  RunLen := RunLen + 2;
869  if (Len <> 0) then
870  begin
871    tmp := OutputBuffer[RunLen + Len];
872    OutputBuffer[RunLen + Len] := #0;
873    result := String(PChar(@OutputBuffer[RunLen]));
874    OutputBuffer[RunLen + Len] := tmp;
875    RunLen := RunLen + Len;
876  end
877  else
878    result := '';
879 end;
880
881 function TIBCustomService.ParseInteger(var RunLen: Integer): Integer;
882 begin
883  result := isc_vax_integer(OutputBuffer + RunLen, 4);
884  RunLen := RunLen + 4;
885 end;
886
868   {
869   * GenerateSPB -
870   *  Given a string containing a textual representation
871   *  of the Service parameters, generate a service
872 < *  parameter buffer, and return it and its length
892 < *  in SPB and SPBLength, respectively.
872 > *  parameter buffer, and return it .
873   }
874 < procedure TIBCustomService.GenerateSPB(sl: TStrings; var SPB: String;
895 <  var SPBLength: Short);
874 > function TIBCustomService.GenerateSPB(sl: TStrings): ISPB;
875   var
876    i, j, SPBVal, SPBServerVal: UShort;
877    param_name, param_value: String;
# Line 900 | Line 879 | begin
879    { The SPB is initially empty, with the exception that
880     the SPB version must be the first byte of the string.
881    }
882 <  SPBLength := 2;
883 <  SPB := Char(isc_spb_version);
905 <  SPB := SPB + Char(isc_spb_current_version);
882 >  Result := FirebirdAPI.AllocateSPB;
883 >
884    { Iterate through the textual service parameters, constructing
885     a SPB on-the-fly }
886    if sl.Count > 0 then
# Line 929 | Line 907 | begin
907          SPBServerVal := SPBConstantValues[j];
908          break;
909        end;
910 <    case SPBVal of
910 >    case SPBServerVal of
911        isc_spb_user_name, isc_spb_password:
912 <      begin
935 <        SPB := SPB +
936 <               Char(SPBServerVal) +
937 <               Char(Length(param_value)) +
938 <               param_value;
939 <        Inc(SPBLength, 2 + Length(param_value));
940 <      end;
912 >        Result.Add(SPBServerVal).AsString := param_value;
913        else
914        begin
915 <        if (SPBVal > 0) and
944 <           (SPBVal <= isc_dpb_last_dpb_constant) then
915 >        if GetSPBConstName(SPBServerVal) <> '' then
916            IBError(ibxeSPBConstantNotSupported,
917 <                   [SPBConstantNames[SPBVal]])
917 >                   [GetSPBConstName(SPBServerVal)])
918          else
919 <          IBError(ibxeSPBConstantUnknown, [SPBVal]);
919 >          IBError(ibxeSPBConstantUnknown, [SPBServerVal]);
920        end;
921      end;
922    end;
# Line 972 | Line 943 | begin
943    inherited Destroy;
944   end;
945  
975 procedure TIBServerProperties.ParseConfigFileData(var RunLen: Integer);
976 begin
977  Inc(RunLen);
978  with FConfigParams.ConfigFileData do
979  begin
980    SetLength (ConfigFileValue, Length(ConfigFileValue)+1);
981    SetLength (ConfigFileKey, Length(ConfigFileKey)+1);
982
983    ConfigFileKey[High(ConfigFileKey)] := Integer(OutputBuffer[RunLen-1]);
984    ConfigFileValue[High(ConfigFileValue)] := ParseInteger(RunLen);
985  end;
986 end;
987
946   procedure TIBServerProperties.Fetch;
947   begin
948    if (Database in Options) then
# Line 1001 | Line 959 | end;
959  
960   procedure TIBServerProperties.FetchConfigParams;
961   var
962 <  RunLen: Integer;
962 >  i, j: Integer;
963  
964   begin
965 <  ServiceQueryParams := Char(isc_info_svc_get_config) +
966 <                        Char(isc_info_svc_get_env) +
967 <                        Char(isc_info_svc_get_env_lock) +
968 <                        Char(isc_info_svc_get_env_msg) +
969 <                        Char(isc_info_svc_user_dbpath);
965 >  SRB.Add(isc_info_svc_get_config);
966 >  SRB.Add(isc_info_svc_get_env);
967 >  SRB.Add(isc_info_svc_get_env_lock);
968 >  SRB.Add(isc_info_svc_get_env_msg);
969 >  SRB.Add(isc_info_svc_user_dbpath);
970  
971    InternalServiceQuery;
972 <  RunLen := 0;
973 <  While (not (Integer(OutputBuffer[RunLen]) = isc_info_end)) do
972 >
973 >  for i := 0 to FServiceQueryResults.Count - 1 do
974 >  with FServiceQueryResults[i] do
975    begin
976 <    case Integer(OutputBuffer[RunLen]) of
976 >    case getItemType of
977        isc_info_svc_get_config:
978        begin
979 <        FConfigParams.ConfigFileData.ConfigFileKey := nil;
980 <        FConfigParams.ConfigFileData.ConfigFileValue := nil;
981 <        Inc (RunLen);
982 <        while (not (Integer(OutputBuffer[RunLen]) = isc_info_flag_end)) do
983 <          ParseConfigFileData (RunLen);
984 <        if (Integer(OutputBuffer[RunLen]) = isc_info_flag_end) then
985 <          Inc (RunLen);
979 >        SetLength (FConfigParams.ConfigFileData.ConfigFileValue, Count);
980 >        SetLength (FConfigParams.ConfigFileData.ConfigFileKey, Count);
981 >
982 >        for j := 0 to Count - 1 do
983 >        begin
984 >          FConfigParams.ConfigFileData.ConfigFileKey[j] := getItemType;
985 >          FConfigParams.ConfigFileData.ConfigFileValue[j] := AsInteger;
986 >        end;
987        end;
988  
989        isc_info_svc_get_env:
990 <      begin
1031 <        Inc (RunLen);
1032 <        FConfigParams.BaseLocation := ParseString(RunLen);
1033 <      end;
990 >        FConfigParams.BaseLocation := AsString;
991  
992        isc_info_svc_get_env_lock:
993 <      begin
1037 <        Inc (RunLen);
1038 <        FConfigParams.LockFileLocation := ParseString(RunLen);
1039 <      end;
993 >        FConfigParams.LockFileLocation := AsString;
994  
995        isc_info_svc_get_env_msg:
996 <      begin
1043 <        Inc (RunLen);
1044 <        FConfigParams.MessageFileLocation := ParseString(RunLen);
1045 <      end;
996 >        FConfigParams.MessageFileLocation := AsString;
997  
998        isc_info_svc_user_dbpath:
999 <      begin
1000 <        Inc (RunLen);
1050 <        FConfigParams.SecurityDatabaseLocation := ParseString(RunLen);
1051 <      end;
999 >        FConfigParams.SecurityDatabaseLocation := AsString;
1000 >
1001        else
1002 <        IBError(ibxeOutputParsingError, [nil]);
1002 >        IBError(ibxeOutputParsingError, [getItemType]);
1003      end;
1004    end;
1005   end;
1006  
1007   procedure TIBServerProperties.FetchDatabaseInfo;
1008   var
1009 <  i, RunLen: Integer;
1009 >  i,j: Integer;
1010   begin
1011 <  ServiceQueryParams := Char(isc_info_svc_svr_db_info);
1011 >  SRB.Add(isc_info_svc_svr_db_info);
1012    InternalServiceQuery;
1013 <  if (OutputBuffer[0] <> Char(isc_info_svc_svr_db_info)) then
1014 <      IBError(ibxeOutputParsingError, [nil]);
1015 <  RunLen := 1;
1016 <  if (OutputBuffer[RunLen] <> Char(isc_spb_num_att)) then
1017 <      IBError(ibxeOutputParsingError, [nil]);
1018 <  Inc(RunLen);
1019 <  FDatabaseInfo.NoOfAttachments := ParseInteger(RunLen);
1020 <  if (OutputBuffer[RunLen] <> Char(isc_spb_num_db)) then
1021 <      IBError(ibxeOutputParsingError, [nil]);
1022 <  Inc(RunLen);
1023 <  FDatabaseInfo.NoOfDatabases := ParseInteger(RunLen);
1024 <  FDatabaseInfo.DbName := nil;
1025 <  SetLength(FDatabaseInfo.DbName, FDatabaseInfo.NoOfDatabases);
1026 <  i := 0;
1027 <  while (OutputBuffer[RunLen] <> Char(isc_info_flag_end)) do
1028 <  begin
1029 <    if (OutputBuffer[RunLen] <> Char(SPBConstantValues[isc_spb_dbname])) then
1030 <      IBError(ibxeOutputParsingError, [nil]);
1031 <    Inc(RunLen);
1032 <    FDatabaseInfo.DbName[i] := ParseString(RunLen);
1033 <    Inc (i);
1034 <  end;
1013 >
1014 >  SetLength(FDatabaseInfo.DbName,0);
1015 >  for i := 0 to FServiceQueryResults.Count - 1 do
1016 >  with FServiceQueryResults[i] do
1017 >  begin
1018 >    case getItemType of
1019 >      isc_info_svc_svr_db_info:
1020 >        for j := 0 to FServiceQueryResults[i].Count - 1 do
1021 >        with FServiceQueryResults[i][j] do
1022 >        case getItemType of
1023 >        isc_spb_num_att:
1024 >          FDatabaseInfo.NoOfAttachments := AsInteger;
1025 >
1026 >        isc_spb_num_db:
1027 >          FDatabaseInfo.NoOfDatabases := AsInteger;
1028 >
1029 >        isc_spb_dbname:
1030 >          begin
1031 >            SetLength(FDatabaseInfo.DbName,length(FDatabaseInfo.DbName)+1);
1032 >            FDatabaseInfo.DbName[length(FDatabaseInfo.DbName)-1] := AsString;
1033 >          end;
1034 >        else
1035 >          IBError(ibxeOutputParsingError, [getItemType]);
1036 >        end;
1037 >      else
1038 >        IBError(ibxeOutputParsingError, [getItemType]);
1039 >    end;
1040 > end;
1041   end;
1042  
1043   procedure TIBServerProperties.FetchLicenseInfo;
1044   var
1045 <  i, RunLen: Integer;
1091 <  done: Integer;
1045 >  i,j : Integer;
1046   begin
1047 <  ServiceQueryParams := Char(isc_info_svc_get_license) +
1048 <                        Char(isc_info_svc_get_licensed_users);
1047 >  SRB.Add(isc_info_svc_get_license);
1048 >  SRB.Add(isc_info_svc_get_licensed_users);
1049    InternalServiceQuery;
1050 <  RunLen := 0;
1051 <  done := 0;
1052 <  i := 0;
1053 <  FLicenseInfo.key := nil;
1054 <  FLicenseInfo.id := nil;
1055 <  FLicenseInfo.desc := nil;
1056 <
1057 <  While done < 2 do begin
1058 <    Inc(Done);
1105 <    Inc(RunLen);
1106 <    case Integer(OutputBuffer[RunLen-1]) of
1050 >
1051 >  SetLength(FLicenseInfo.key, 0);
1052 >  SetLength(FLicenseInfo.id, 0);
1053 >  SetLength(FLicenseInfo.desc, 0);
1054 >
1055 >  for i := 0 to FServiceQueryResults.Count - 1 do
1056 >  with FServiceQueryResults[i] do
1057 >  begin
1058 >    case getItemType of
1059        isc_info_svc_get_license:
1108      begin
1109        while (OutputBuffer[RunLen] <> Char(isc_info_flag_end)) do
1060          begin
1061 <          if (i >= Length(FLicenseInfo.key)) then
1062 <          begin
1063 <            SetLength(FLicenseInfo.key, i + 10);
1064 <            SetLength(FLicenseInfo.id, i + 10);
1065 <            SetLength(FLicenseInfo.desc, i + 10);
1061 >          SetLength(FLicenseInfo.key, Count);
1062 >          SetLength(FLicenseInfo.id, Count);
1063 >          SetLength(FLicenseInfo.desc, Count);
1064 >
1065 >          for j := 0 to Count -1 do
1066 >          with Items[j] do
1067 >          case getItemType of
1068 >             isc_spb_lic_id:
1069 >                FLicenseInfo.id[j] := AsString;
1070 >
1071 >             isc_spb_lic_key:
1072 >                FLicenseInfo.key[j] := AsString;
1073 >
1074 >             isc_spb_lic_desc:
1075 >               FLicenseInfo.desc[j] := AsString;
1076 >          else
1077 >            IBError(ibxeOutputParsingError, [getItemType]);
1078            end;
1117          if (OutputBuffer[RunLen] <> Char(isc_spb_lic_id)) then
1118              IBError(ibxeOutputParsingError, [nil]);
1119          Inc(RunLen);
1120          FLicenseInfo.id[i] := ParseString(RunLen);
1121          if (OutputBuffer[RunLen] <> Char(isc_spb_lic_key)) then
1122              IBError(ibxeOutputParsingError, [nil]);
1123          Inc(RunLen);
1124          FLicenseInfo.key[i] := ParseString(RunLen);
1125          if (OutputBuffer[RunLen] <> Char(7)) then
1126              IBError(ibxeOutputParsingError, [nil]);
1127          Inc(RunLen);
1128          FLicenseInfo.desc[i] := ParseString(RunLen);
1129          Inc(i);
1079          end;
1131        Inc(RunLen);
1132        if (Length(FLicenseInfo.key) > i) then
1133        begin
1134          SetLength(FLicenseInfo.key, i);
1135          SetLength(FLicenseInfo.id, i);
1136          SetLength(FLicenseInfo.desc, i);
1137        end;
1138      end;
1139      isc_info_svc_get_licensed_users:
1140        FLicenseInfo.LicensedUsers := ParseInteger(RunLen);
1080        else
1081 <        IBError(ibxeOutputParsingError, [nil]);
1081 >        IBError(ibxeOutputParsingError, [getItemType]);
1082      end;
1083    end;
1084   end;
1085  
1086   procedure TIBServerProperties.FetchLicenseMaskInfo();
1087   var
1088 <  done,RunLen:integer;
1088 >  i : Integer;
1089   begin
1090 <  ServiceQueryParams := Char(isc_info_svc_get_license_mask) +
1091 <                        Char(isc_info_svc_capabilities);
1090 >  SRB.Add(isc_info_svc_get_license_mask);
1091 >  SRB.Add(isc_info_svc_capabilities);
1092    InternalServiceQuery;
1093 <  RunLen := 0;
1094 <  done := 0;
1095 <  While done <= 1 do
1096 <  begin
1097 <    Inc(done);
1159 <    Inc(RunLen);
1160 <    case Integer(OutputBuffer[RunLen-1]) of
1093 >
1094 >  for i := 0 to FServiceQueryResults.Count - 1 do
1095 >  with FServiceQueryResults[i] do
1096 >  begin
1097 >    case getItemType of
1098        isc_info_svc_get_license_mask:
1099 <        FLicenseMaskInfo.LicenseMask := ParseInteger(RunLen);
1099 >        FLicenseMaskInfo.LicenseMask := AsInteger;
1100        isc_info_svc_capabilities:
1101 <        FLicenseMaskInfo.CapabilityMask := ParseInteger(RunLen);
1101 >        FLicenseMaskInfo.CapabilityMask := AsInteger;
1102        else
1103 <        IBError(ibxeOutputParsingError, [nil]);
1103 >        IBError(ibxeOutputParsingError, [getItemType]);
1104      end;
1105    end;
1106   end;
# Line 1171 | Line 1108 | end;
1108  
1109   procedure TIBServerProperties.FetchVersionInfo;
1110   var
1111 <  RunLen: Integer;
1175 <  done: Integer;
1111 >  i : Integer;
1112   begin
1113 <  ServiceQueryParams := Char(isc_info_svc_version) +
1114 <                        Char(isc_info_svc_server_version) +
1115 <                        Char(isc_info_svc_implementation);
1113 >  SRB.Add(isc_info_svc_version);
1114 >  SRB.Add(isc_info_svc_server_version);
1115 >  SRB.Add(isc_info_svc_implementation);
1116    InternalServiceQuery;
1181  RunLen := 0;
1182  done := 0;
1117  
1118 <  While done <= 2 do
1118 >  for i := 0 to FServiceQueryResults.Count - 1 do
1119 >  with FServiceQueryResults[i] do
1120    begin
1121 <    Inc(done);
1187 <    Inc(RunLen);
1188 <    case Integer(OutputBuffer[RunLen-1]) of
1121 >    case getItemType of
1122        isc_info_svc_version:
1123 <        FVersionInfo.ServiceVersion := ParseInteger(RunLen);
1123 >        FVersionInfo.ServiceVersion := AsInteger;
1124        isc_info_svc_server_version:
1125 <        FVersionInfo.ServerVersion := ParseString(RunLen);
1125 >        FVersionInfo.ServerVersion := AsString;
1126        isc_info_svc_implementation:
1127 <        FVersionInfo.ServerImplementation := ParseString(RunLen);
1127 >        FVersionInfo.ServerImplementation := AsString;
1128        else
1129 <        IBError(ibxeOutputParsingError, [nil]);
1129 >        IBError(ibxeOutputParsingError, [getItemType]);
1130      end;
1131    end;
1132   end;
1133  
1134   { TIBControlService }
1135 +
1136   procedure TIBControlService.SetServiceStartOptions;
1137   begin
1138  
1139   end;
1140  
1141   function TIBControlService.GetIsServiceRunning: Boolean;
1208 var
1209  RunLen: Integer;
1142   begin
1143 <  ServiceQueryParams := Char(isc_info_svc_running);
1143 >  SRB.Add(isc_info_svc_running);
1144    InternalServiceQuery;
1213  if (OutputBuffer[0] <> Char(isc_info_svc_running)) then
1214    IBError(ibxeOutputParsingError, [nil]);
1215  RunLen := 1;
1216  if (ParseInteger(RunLen) = 1) then
1217    result := True
1218  else
1219    result := False;
1220 end;
1145  
1146 < procedure TIBControlService.ServiceStartAddParam (Value: string; param: Integer);
1147 < var
1148 <  Len: UShort;
1225 < begin
1226 <  Len := Length(Value);
1227 <  if Len > 0 then
1228 <  begin
1229 <    FStartParams  := FStartParams +
1230 <                     Char(Param) +
1231 <                     PChar(@Len)[0] +
1232 <                     PChar(@Len)[1] +
1233 <                     Value;
1234 <  end;
1146 >  Result := (FServiceQueryResults.Count > 0) and
1147 >             (FServiceQueryResults[0].getItemType = isc_info_svc_running) and
1148 >              (FServiceQueryResults[0].AsInteger = 1);
1149   end;
1150  
1151 < procedure TIBControlService.ServiceStartAddParam (Value: Integer; param: Integer);
1151 > procedure TIBControlService.CheckServiceNotRunning;
1152   begin
1153 <  FStartParams  := FStartParams +
1154 <                   Char(Param) +
1241 <                   PChar(@Value)[0] +
1242 <                   PChar(@Value)[1] +
1243 <                   PChar(@Value)[2] +
1244 <                   PChar(@Value)[3];
1153 >  if IsServiceRunning then
1154 >    IBError(ibxeServiceRunning,[nil]);
1155   end;
1156  
1157   constructor TIBControlService.Create(AOwner: TComponent);
1158   begin
1159    inherited create(AOwner);
1160 <  FStartParams := '';
1161 <  FStartSPB := nil;
1252 <  FStartSPBLength := 0;
1160 >  FSRB := nil;
1161 >  FSPB := nil;
1162   end;
1163  
1164   procedure TIBControlService.InternalServiceStart;
1165   begin
1166 <  FStartSPBLength := Length(FStartParams);
1258 <  if FStartSPBLength = 0 then
1166 >  if SRB = nil then
1167      IBError(ibxeStartParamsError, [nil]);
1168 <  IBAlloc(FStartSPB, 0, FStartSPBLength);
1261 <  Move(FStartParams[1], FStartSPB[0], FstartSPBLength);
1168 >
1169    try
1170 <    if call(isc_service_start(StatusVector, @FHandle, nil,
1264 <                           FStartSPBLength, FStartSPB), False) > 0 then
1265 <    begin
1266 <      FHandle := nil;
1267 <      IBDataBaseError;
1268 <    end;
1170 >    FService.Start(SRB);
1171    finally
1172 <    FreeMem(FStartSPB);
1271 <    FStartSPB := nil;
1272 <    FStartSPBLength := 0;
1273 <    FStartParams := '';
1172 >    FSRB := nil;
1173    end;
1174    MonitorHook.ServiceStart(Self);
1175   end;
# Line 1278 | Line 1177 | end;
1177   procedure TIBControlService.ServiceStart;
1178   begin
1179    CheckActive;
1180 +  CheckServiceNotRunning;
1181    SetServiceStartOptions;
1182    InternalServiceStart;
1183   end;
# Line 1291 | Line 1191 | end;
1191  
1192   procedure TIBConfigService.ActivateShadow;
1193   begin
1194 <  ServiceStartParams  := Char(isc_action_svc_properties);
1195 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1196 <  ServiceStartAddParam (isc_spb_prp_activate, SPBConstantValues[isc_spb_options]);
1194 >  SRB.Add(isc_action_svc_properties);
1195 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1196 >  SRB.Add(isc_spb_options).AsInteger := isc_spb_prp_activate;
1197    InternalServiceStart;
1198   end;
1199  
1200   procedure TIBConfigService.BringDatabaseOnline;
1201   begin
1202 <  ServiceStartParams  := Char(isc_action_svc_properties);
1203 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1204 <  ServiceStartAddParam (isc_spb_prp_db_online, SPBConstantValues[isc_spb_options]);
1202 >  SRB.Add(isc_action_svc_properties);
1203 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1204 >  SRB.Add(isc_spb_options).AsInteger := isc_spb_prp_db_online;
1205    InternalServiceStart;
1206   end;
1207  
1208   procedure TIBConfigService.SetAsyncMode(Value: Boolean);
1209   begin
1210 <  ServiceStartParams  := Char(isc_action_svc_properties);
1211 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1212 <  ServiceStartParams := ServiceStartParams +
1313 <                        Char(isc_spb_prp_write_mode);
1210 >  SRB.Add(isc_action_svc_properties);
1211 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1212 >  with SRB.Add(isc_spb_prp_write_mode) do
1213    if Value then
1214 <    ServiceStartParams  := ServiceStartParams +
1316 <                           Char(isc_spb_prp_wm_async)
1214 >    AsInteger := isc_spb_prp_wm_async
1215    else
1216 <    ServiceStartParams  := ServiceStartParams +
1319 <                           Char(isc_spb_prp_wm_sync);
1216 >    AsInteger := isc_spb_prp_wm_sync;
1217    InternalServiceStart;
1218   end;
1219  
# Line 1327 | Line 1224 | end;
1224  
1225   procedure TIBConfigService.SetPageBuffers(Value: Integer);
1226   begin
1227 <  ServiceStartParams  := Char(isc_action_svc_properties);
1228 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1229 <  ServiceStartAddParam (Value, isc_spb_prp_page_buffers);
1227 >  SRB.Add(isc_action_svc_properties);
1228 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1229 >  SRB.Add(isc_spb_prp_page_buffers).AsInteger := Value;
1230    InternalServiceStart;
1231   end;
1232  
1233   procedure TIBConfigService.SetReadOnly(Value: Boolean);
1234   begin
1235 <  ServiceStartParams  := Char(isc_action_svc_properties);
1236 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1237 <  ServiceStartParams := ServiceStartParams +
1341 <                         Char(isc_spb_prp_access_mode);
1235 >  SRB.Add(isc_action_svc_properties);
1236 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1237 >  with SRB.Add(isc_spb_prp_access_mode) do
1238    if Value then
1239 <    ServiceStartParams  := ServiceStartParams +
1344 <                           Char(isc_spb_prp_am_readonly)
1239 >    AsInteger := isc_spb_prp_am_readonly
1240    else
1241 <    ServiceStartParams  := ServiceStartParams +
1347 <                           Char(isc_spb_prp_am_readwrite);
1241 >    AsInteger := isc_spb_prp_am_readwrite;
1242    InternalServiceStart;
1243   end;
1244  
1245   procedure TIBConfigService.SetReserveSpace(Value: Boolean);
1246   begin
1247 <  ServiceStartParams  := Char(isc_action_svc_properties);
1248 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1249 <  ServiceStartParams := ServiceStartParams +
1356 <                        Char(isc_spb_prp_reserve_space);
1247 >  SRB.Add(isc_action_svc_properties);
1248 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1249 >  with SRB.Add(isc_spb_prp_reserve_space) do
1250    if Value then
1251 <    ServiceStartParams  := ServiceStartParams +
1359 <                           Char(isc_spb_prp_res)
1251 >    AsInteger := isc_spb_prp_res
1252    else
1253 <    ServiceStartParams  := ServiceStartParams +
1362 <                           Char(isc_spb_prp_res_use_full);
1253 >    AsInteger := isc_spb_prp_res_use_full;
1254    InternalServiceStart;
1255   end;
1256  
1257   procedure TIBConfigService.SetSweepInterval(Value: Integer);
1258   begin
1259 <  ServiceStartParams  := Char(isc_action_svc_properties);
1260 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1261 <  ServiceStartAddParam (Value, isc_spb_prp_sweep_interval);
1259 >  SRB.Add(isc_action_svc_properties);
1260 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1261 >  SRB.Add(isc_spb_prp_sweep_interval).AsInteger := Value;
1262    InternalServiceStart;
1263   end;
1264  
1265   procedure TIBConfigService.SetDBSqlDialect(Value: Integer);
1266   begin
1267 <  ServiceStartParams  := Char(isc_action_svc_properties);
1268 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1269 <  ServiceStartAddParam (Value, isc_spb_prp_set_sql_dialect);
1267 >  SRB.Add(isc_action_svc_properties);
1268 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1269 >  SRB.Add(isc_spb_prp_set_sql_dialect).AsInteger := Value;
1270    InternalServiceStart;
1271   end;
1272  
1273   procedure TIBConfigService.ShutdownDatabase(Options: TShutdownMode;
1274    Wait: Integer);
1275   begin
1276 <  ServiceStartParams  := Char(isc_action_svc_properties);
1277 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1276 >  SRB.Add(isc_action_svc_properties);
1277 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1278    if (Options = Forced) then
1279 <    ServiceStartAddParam (Wait, isc_spb_prp_shutdown_db)
1279 >  SRB.Add(isc_spb_prp_shutdown_db).AsInteger := Wait
1280    else if (Options = DenyTransaction) then
1281 <    ServiceStartAddParam (Wait, isc_spb_prp_deny_new_transactions)
1281 >    SRB.Add(isc_spb_prp_deny_new_transactions).AsInteger := Wait
1282    else
1283 <    ServiceStartAddParam (Wait, isc_spb_prp_deny_new_attachments);
1283 >    SRB.Add(isc_spb_prp_deny_new_attachments).AsInteger := Wait;
1284    InternalServiceStart;
1285   end;
1286  
1287 +
1288   { TIBStatisticalService }
1289  
1290   procedure TIBStatisticalService.SetDatabaseName(const Value: string);
# Line 1401 | Line 1293 | begin
1293   end;
1294  
1295   procedure TIBStatisticalService.SetServiceStartOptions;
1296 < var
1405 <  param: Integer;
1296 > var param: integer;
1297   begin
1298    if FDatabaseName = '' then
1299      IBError(ibxeStartParamsError, [nil]);
1300 +
1301    param := 0;
1302    if (DataPages in Options) then
1303      param := param or isc_spb_sts_data_pages;
1304 <  if (DbLog in Options) then
1305 <    param := param or isc_spb_sts_db_log;
1304 > {  if (DbLog in Options) then
1305 >    param := param or isc_spb_sts_db_log; -- removed from Firebird 2}
1306    if (HeaderPages in Options) then
1307      param := param or isc_spb_sts_hdr_pages;
1308    if (IndexPages in Options) then
# Line 1418 | Line 1310 | begin
1310    if (SystemRelations in Options) then
1311      param := param or isc_spb_sts_sys_relations;
1312    Action := isc_action_svc_db_stats;
1313 <  ServiceStartParams  := Char(isc_action_svc_db_stats);
1314 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1315 <  ServiceStartAddParam (param, SPBConstantValues[isc_spb_options]);
1313 >  SRB.Add(isc_action_svc_db_stats);
1314 >  SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
1315 >  SRB.Add(isc_spb_options).AsInteger := param;
1316   end;
1317  
1318   { TIBBackupService }
# Line 1447 | Line 1339 | begin
1339    if (ConvertExtTables in Options) then
1340      param := param or isc_spb_bkp_convert;
1341    Action := isc_action_svc_backup;
1342 <  ServiceStartParams  := Char(isc_action_svc_backup);
1343 <  ServiceStartAddParam(FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1344 <  ServiceStartAddParam(param, SPBConstantValues[isc_spb_options]);
1345 <  if Verbose then
1346 <    ServiceStartParams := ServiceStartParams + Char(SPBConstantValues[isc_spb_verbose]);
1342 >  SRB.Add(isc_action_svc_backup);
1343 >  SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
1344 >  SRB.Add(isc_spb_options).AsInteger := param;
1345 >  if Verbose  and (BackupFileLocation = flServerSide) then
1346 >    SRB.Add(isc_spb_verbose);
1347    if FBlockingFactor > 0 then
1348 <    ServiceStartAddParam(FBlockingFactor, isc_spb_bkp_factor);
1348 >    SRB.Add(isc_spb_bkp_factor).AsInteger := FBlockingFactor;
1349 >  if BackupFileLocation = flServerSide then
1350    for i := 0 to FBackupFile.Count - 1 do
1351    begin
1352      if (Trim(FBackupFile[i]) = '') then
1353        continue;
1354      if (Pos('=', FBackupFile[i]) <> 0) then
1355      begin {mbcs ok}
1356 <      ServiceStartAddParam(FBackupFile.Names[i], isc_spb_bkp_file);
1356 >      SRB.Add(isc_spb_bkp_file).AsString := FBackupFile.Names[i];
1357        value := Copy(FBackupFile[i], Pos('=', FBackupFile[i]) + 1, Length(FBackupFile.Names[i])); {mbcs ok}
1358 <      param := StrToInt(value);
1466 <      ServiceStartAddParam(param, isc_spb_bkp_length);
1358 >      SRB.Add(isc_spb_bkp_length).AsInteger := StrToInt(value);;
1359      end
1360      else
1361 <      ServiceStartAddParam(FBackupFile[i], isc_spb_bkp_file);
1362 <  end;
1361 >      SRB.Add(isc_spb_bkp_file).AsString := FBackupFile[i];
1362 >  end
1363 >  else
1364 >  SRB.Add(isc_spb_bkp_file).AsString := 'stdout';
1365   end;
1366  
1367   constructor TIBBackupService.Create(AOwner: TComponent);
# Line 1510 | Line 1404 | begin
1404    if (UseAllSpace in Options) then
1405      param := param or isc_spb_res_use_all_space;
1406    Action := isc_action_svc_restore;
1407 <  ServiceStartParams  := Char(isc_action_svc_restore);
1408 <  ServiceStartAddParam(param, SPBConstantValues[isc_spb_options]);
1409 <  if Verbose then ServiceStartParams := ServiceStartParams + Char(SPBConstantValues[isc_spb_verbose]);
1407 >  SRB.Add(isc_action_svc_restore);
1408 >  SRB.Add(isc_spb_options).AsInteger := param;
1409 >  if Verbose then
1410 >    SRB.Add(isc_spb_verbose);
1411    if FPageSize > 0 then
1412 <    ServiceStartAddParam(FPageSize, isc_spb_res_page_size);
1412 >    SRB.Add(isc_spb_res_page_size).AsInteger := FPageSize;
1413    if FPageBuffers > 0 then
1414 <    ServiceStartAddParam(FPageBuffers, isc_spb_res_buffers);
1414 >    SRB.Add(isc_spb_res_buffers).AsInteger := FPageBuffers;
1415 >  if BackupFileLocation = flServerSide then
1416    for i := 0 to FBackupFile.Count - 1 do
1417    begin
1418      if (Trim(FBackupFile[i]) = '') then continue;
1419      if (Pos('=', FBackupFile[i]) <> 0) then  {mbcs ok}
1420      begin
1421 <      ServiceStartAddParam(AnsiUpperCase(FBackupFile.Names[i]), isc_spb_bkp_file);
1421 >      SRB.Add(isc_spb_bkp_file).AsString := FBackupFile.Names[i];
1422        value := Copy(FBackupFile[i], Pos('=', FBackupFile[i]) + 1, Length(FBackupFile.Names[i])); {mbcs ok}
1423 <      param := StrToInt(value);
1528 <      ServiceStartAddParam(param, isc_spb_bkp_length);
1423 >      SRB.Add(isc_spb_bkp_length).AsInteger := StrToInt(value);;
1424      end
1425      else
1426 <      ServiceStartAddParam(FBackupFile[i], isc_spb_bkp_file);
1427 <  end;
1426 >      SRB.Add(isc_spb_bkp_file).AsString := FBackupFile[i];
1427 >  end
1428 >  else
1429 >    SRB.Add(isc_spb_bkp_file).AsString := 'stdin';
1430 >
1431    for i := 0 to FDatabaseName.Count - 1 do
1432    begin
1433      if (Trim(FDatabaseName[i]) = '') then continue;
1434      if (Pos('=', FDatabaseName[i]) <> 0) then {mbcs ok}
1435 <    begin
1436 <      ServiceStartAddParam(FDatabaseName.Names[i], SPBConstantValues[isc_spb_dbname]);
1435 >    begin
1436 >      SRB.Add(isc_spb_dbname).AsString := FDatabaseName.Names[i];
1437        value := Copy(FDatabaseName[i], Pos('=', FDatabaseName[i]) + 1, Length(FDatabaseName[i])); {mbcs ok}
1438 <      param := StrToInt(value);
1541 <      ServiceStartAddParam(param, isc_spb_res_length);
1438 >      SRB.Add(isc_spb_res_length).AsInteger :=  StrToInt(value);
1439      end
1440      else
1441 <      ServiceStartAddParam(FDatabaseName[i], SPBConstantValues[isc_spb_dbname]);
1441 >      SRB.Add(isc_spb_dbname).AsString := FDatabaseName[i];
1442    end;
1443   end;
1444  
# Line 1560 | Line 1457 | begin
1457    inherited Destroy;
1458   end;
1459  
1460 + function TIBRestoreService.SendNextChunk(stream: TStream; var line: String
1461 +  ): integer;
1462 + var
1463 +  i: Integer;
1464 + begin
1465 +  Result := 0;
1466 +  line := '';
1467 +  if (FEof = True) then
1468 +    exit;
1469 +
1470 +  if (FAction = 0) then
1471 +    IBError(ibxeQueryParamsError, [nil]);
1472 +
1473 +  SRB.Add(isc_info_svc_line);
1474 +  SRB.Add(isc_info_svc_stdin);
1475 +
1476 +  SQPB.Add(isc_info_svc_timeout).AsInteger := 1;
1477 +  if FSendBytes > 0 then
1478 +    Result := SQPB.Add(isc_info_svc_line).CopyFrom(stream,FSendBytes);
1479 +  InternalServiceQuery;
1480 +
1481 +  FSendBytes := 0;
1482 +  for i := 0 to FServiceQueryResults.Count - 1 do
1483 +  with FServiceQueryResults[i] do
1484 +  begin
1485 +    case getItemType of
1486 +      isc_info_svc_line:
1487 +         line := AsString;
1488 +
1489 +      isc_info_svc_stdin:
1490 +        FSendBytes := AsInteger;
1491 +
1492 +      isc_info_svc_timeout,
1493 +      isc_info_data_not_ready:
1494 +        {ignore};
1495 +    else
1496 +      IBError(ibxeOutputParsingError, [getItemType]);
1497 +    end;
1498 +  end;
1499 +  FEOF := (FSendBytes = 0) and (line = '');
1500 + end;
1501 +
1502   procedure TIBRestoreService.SetBackupFile(const Value: TStrings);
1503   begin
1504    FBackupFile.Assign(Value);
# Line 1587 | Line 1526 | begin
1526   end;
1527  
1528   procedure TIBValidationService.FetchLimboTransactionInfo;
1529 +
1530 +  procedure NextLimboTransaction(index: integer);
1531 +  begin
1532 +    SetLength(FLimboTransactionInfo, index+1);
1533 +    FLimboTransactionInfo[index] := TLimboTransactionInfo.Create;
1534 +    { if no advice commit as default }
1535 +    FLimboTransactionInfo[index].Advise := UnknownAdvise;
1536 +    FLimboTransactionInfo[index].Action:= CommitAction;
1537 +  end;
1538 +
1539   var
1540 <  i, RunLen: Integer;
1540 >  i,j, k: Integer;
1541    Value: Char;
1542   begin
1594  ServiceQueryParams := Char(isc_info_svc_limbo_trans);
1595  InternalServiceQuery;
1596  RunLen := 0;
1597  if (OutputBuffer[RunLen] <> Char(isc_info_svc_limbo_trans)) then
1598    IBError(ibxeOutputParsingError, [nil]);
1599  Inc(RunLen, 3);
1543    for i := 0 to High(FLimboTransactionInfo) do
1544      FLimboTransactionInfo[i].Free;
1545 <  FLimboTransactionInfo := nil;
1546 <  i := 0;
1547 <  while (OutputBuffer[RunLen] <> Char(isc_info_end)) do
1548 <  begin
1549 <    if (i >= Length(FLimboTransactionInfo)) then
1550 <      SetLength(FLimboTransactionInfo, i + 10);
1551 <    if FLimboTransactionInfo[i] = nil then
1552 <      FLimboTransactionInfo[i] := TLimboTransactionInfo.Create;
1553 <    with FLimboTransactionInfo[i] do
1545 >  SetLength(FLimboTransactionInfo,0);
1546 >
1547 >  SRB.Add(isc_info_svc_limbo_trans);
1548 >  InternalServiceQuery;
1549 >
1550 >  k := -1;
1551 >  for i := 0 to FServiceQueryResults.Count - 1 do
1552 >  with FServiceQueryResults[i] do
1553 >  case getItemType of
1554 >  isc_info_svc_limbo_trans:
1555      begin
1556 <      if (OutputBuffer[RunLen] = Char(isc_spb_single_tra_id)) then
1557 <      begin
1558 <        Inc(RunLen);
1615 <        MultiDatabase := False;
1616 <        ID := ParseInteger(RunLen);
1617 <      end
1618 <      else
1556 >      if FServiceQueryResults[i].Count = 0 then continue;
1557 >      NextLimboTransaction(0);
1558 >      for j := 0 to FServiceQueryResults[i].Count - 1 do
1559        begin
1560 <        Inc(RunLen);
1621 <        MultiDatabase := True;
1622 <        ID := ParseInteger(RunLen);
1623 <        HostSite := ParseString(RunLen);
1624 <        if (OutputBuffer[RunLen] <> Char(isc_spb_tra_state)) then
1625 <          IBError(ibxeOutputParsingError, [nil]);
1626 <        Inc(RunLen);
1627 <        Value := OutputBuffer[RunLen];
1628 <        Inc(RunLen);
1629 <        if (Value = Char(isc_spb_tra_state_limbo)) then
1630 <          State := LimboState
1631 <        else
1632 <          if (Value = Char(isc_spb_tra_state_commit)) then
1633 <            State := CommitState
1634 <          else
1635 <            if (Value = Char(isc_spb_tra_state_rollback)) then
1636 <              State := RollbackState
1637 <            else
1638 <              State := UnknownState;
1639 <        RemoteSite := ParseString(RunLen);
1640 <        RemoteDatabasePath := ParseString(RunLen);
1641 <        Value := OutputBuffer[RunLen];
1642 <        Inc(RunLen);
1643 <        if (Value = Char(isc_spb_tra_advise_commit)) then
1560 >        with FServiceQueryResults[i][j] do
1561          begin
1562 <          Advise := CommitAdvise;
1563 <          Action:= CommitAction;
1564 <        end
1565 <        else
1566 <          if (Value = Char(isc_spb_tra_advise_rollback)) then
1567 <          begin
1568 <            Advise := RollbackAdvise;
1569 <            Action := RollbackAction;
1570 <          end
1571 <          else
1572 <          begin
1573 <            { if no advice commit as default }
1574 <            Advise := UnknownAdvise;
1575 <            Action:= CommitAction;
1562 >          case getItemType of
1563 >            isc_spb_single_tra_id:
1564 >            begin
1565 >              Inc(k);
1566 >              if k > 0 then
1567 >                NextLimboTransaction(k);
1568 >              FLimboTransactionInfo[k].MultiDatabase := False;
1569 >              FLimboTransactionInfo[k].ID := AsInteger;
1570 >            end;
1571 >
1572 >            isc_spb_multi_tra_id:
1573 >            begin
1574 >              Inc(k);
1575 >              if k > 0 then
1576 >                NextLimboTransaction(k);
1577 >              FLimboTransactionInfo[k].MultiDatabase := True;
1578 >              FLimboTransactionInfo[k].ID := AsInteger;
1579 >            end;
1580 >
1581 >            isc_spb_tra_host_site:
1582 >              FLimboTransactionInfo[k].HostSite := AsString;
1583 >
1584 >            isc_spb_tra_state:
1585 >              case AsByte of
1586 >                isc_spb_tra_state_limbo:
1587 >                  FLimboTransactionInfo[k].State := LimboState;
1588 >
1589 >                isc_spb_tra_state_commit:
1590 >                  FLimboTransactionInfo[k].State := CommitState;
1591 >
1592 >                isc_spb_tra_state_rollback:
1593 >                  FLimboTransactionInfo[k].State := RollbackState;
1594 >
1595 >                else
1596 >                  FLimboTransactionInfo[k].State := UnknownState;
1597 >              end;
1598 >
1599 >            isc_spb_tra_remote_site:
1600 >              FLimboTransactionInfo[k].RemoteSite := AsString;
1601 >
1602 >            isc_spb_tra_db_path:
1603 >              FLimboTransactionInfo[k].RemoteDatabasePath := AsString;
1604 >
1605 >            isc_spb_tra_advise:
1606 >            with FLimboTransactionInfo[k] do
1607 >            begin
1608 >              case (AsByte) of
1609 >              isc_spb_tra_advise_commit:
1610 >              begin
1611 >                Advise := CommitAdvise;
1612 >                Action:= CommitAction;
1613 >              end;
1614 >
1615 >              isc_spb_tra_advise_rollback:
1616 >              begin
1617 >                Advise := RollbackAdvise;
1618 >                Action := RollbackAction;
1619 >              end;
1620 >
1621 >              else
1622 >                Advise := UnknownAdvise;
1623 >              end;
1624 >            end;
1625 >
1626 >            else
1627 >              IBError(ibxeOutputParsingError, [getItemType]);
1628            end;
1629 +        end;
1630        end;
1661      Inc (i);
1631      end;
1632 +  else
1633 +    IBError(ibxeOutputParsingError, [getItemType]);
1634    end;
1664  if (i > 0) then
1665    SetLength(FLimboTransactionInfo, i+1);
1635   end;
1636  
1637   procedure TIBValidationService.FixLimboTransactionErrors;
1638   var
1639    i: Integer;
1640   begin
1641 <  ServiceStartParams  := Char(isc_action_svc_repair);
1642 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1643 <  if (FGlobalAction = NoGlobalAction) then
1644 <  begin
1676 <    i := 0;
1677 <    while (FLimboTransactionInfo[i].ID <> 0) do
1641 >  SRB.Add(isc_action_svc_repair);
1642 >  SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
1643 >  case FGlobalAction of
1644 >  NoGlobalAction:
1645      begin
1646 <      if (FLimboTransactionInfo[i].Action = CommitAction) then
1680 <        ServiceStartAddParam (FLimboTransactionInfo[i].ID, isc_spb_rpr_commit_trans)
1681 <      else
1682 <        ServiceStartAddParam (FLimboTransactionInfo[i].ID, isc_spb_rpr_rollback_trans);                              
1683 <      Inc(i);
1684 <    end;
1685 <  end
1686 <  else
1687 <  begin
1688 <    i := 0;
1689 <    if (FGlobalAction = CommitGlobal) then
1690 <      while (FLimboTransactionInfo[i].ID <> 0) do
1646 >      for i := 0 to LimboTransactionInfoCount - 1 do
1647        begin
1648 <        ServiceStartAddParam (FLimboTransactionInfo[i].ID, isc_spb_rpr_commit_trans);
1649 <        Inc(i);
1650 <      end
1651 <    else
1652 <      while (FLimboTransactionInfo[i].ID <> 0) do
1648 >        if (FLimboTransactionInfo[i].Action = CommitAction) then
1649 >          SRB.Add(isc_spb_rpr_commit_trans).AsInteger :=  FLimboTransactionInfo[i].ID
1650 >        else
1651 >          SRB.Add(isc_spb_rpr_rollback_trans).AsInteger :=  FLimboTransactionInfo[i].ID;
1652 >      end;
1653 >    end;
1654 >
1655 >  CommitGlobal:
1656 >    begin
1657 >      for i := 0 to LimboTransactionInfoCount - 1 do
1658 >        SRB.Add(isc_spb_rpr_commit_trans).AsInteger :=  FLimboTransactionInfo[i].ID;
1659 >    end;
1660 >
1661 >    RollbackGlobal:
1662        begin
1663 <        ServiceStartAddParam (FLimboTransactionInfo[i].ID, isc_spb_rpr_rollback_trans);
1664 <        Inc(i);
1663 >        for i := 0 to LimboTransactionInfoCount - 1 do
1664 >          SRB.Add(isc_spb_rpr_rollback_trans).AsInteger :=  FLimboTransactionInfo[i].ID;
1665        end;
1666 +
1667 +    RecoverTwoPhaseGlobal:
1668 +    begin
1669 +      for i := 0 to LimboTransactionInfoCount - 1 do
1670 +        SRB.Add(isc_spb_rpr_recover_two_phase).AsInteger :=  FLimboTransactionInfo[i].ID;
1671 +    end;
1672    end;
1673    InternalServiceStart;
1674   end;
# Line 1712 | Line 1683 | end;
1683  
1684   function TIBValidationService.GetLimboTransactionInfoCount: integer;
1685   begin
1686 <  Result := High(FLimboTransactionInfo);
1686 >  Result := Length(FLimboTransactionInfo);
1687   end;
1688  
1689   procedure TIBValidationService.SetDatabaseName(const Value: string);
# Line 1727 | Line 1698 | begin
1698    Action := isc_action_svc_repair;
1699    if FDatabaseName = '' then
1700      IBError(ibxeStartParamsError, [nil]);
1701 +  SRB.Add(isc_action_svc_repair);
1702 +  SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
1703    param := 0;
1704    if (SweepDB in Options) then
1705      param := param or isc_spb_rpr_sweep_db;
1706    if (ValidateDB in Options) then
1707      param := param or isc_spb_rpr_validate_db;
1708 <  ServiceStartParams  := Char(isc_action_svc_repair);
1736 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1737 <  if param > 0 then
1738 <    ServiceStartAddParam (param, SPBConstantValues[isc_spb_options]);
1739 <  param := 0;
1708 >
1709    if (LimboTransactions in Options) then
1710      param := param or isc_spb_rpr_list_limbo_trans;
1711    if (CheckDB in Options) then
# Line 1754 | Line 1723 | begin
1723         param := param or isc_spb_rpr_validate_db;
1724    end;
1725    if param > 0 then
1726 <    ServiceStartAddParam (param, SPBConstantValues[isc_spb_options]);
1726 >   SRB.Add(isc_spb_options).AsInteger := param;
1727   end;
1728  
1729   { TIBSecurityService }
# Line 1776 | Line 1745 | end;
1745  
1746   procedure TIBSecurityService.FetchUserInfo;
1747   var
1748 <  i, RunLen: Integer;
1748 >  i, j, k: Integer;
1749   begin
1750 <  ServiceQueryParams := Char(isc_info_svc_get_users);
1750 >  SRB.Add(isc_info_svc_get_users);
1751    InternalServiceQuery;
1752 <  RunLen := 0;
1784 <  if (OutputBuffer[RunLen] <> Char(isc_info_svc_get_users)) then
1785 <    IBError(ibxeOutputParsingError, [nil]);
1786 <  Inc(RunLen);
1752 >
1753    for i := 0 to High(FUserInfo) do
1754      FUserInfo[i].Free;
1755 <  FUserInfo := nil;
1756 <  i := 0;
1757 <  { Don't have any use for the combined length
1758 <   so increment past by 2 }
1759 <  Inc(RunLen, 2);
1760 <  while (OutputBuffer[RunLen] <> Char(isc_info_end)) do
1761 <  begin
1762 <    if (i >= Length(FUSerInfo)) then
1763 <      SetLength(FUserInfo, i + 10);
1764 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_username)) then
1765 <      IBError(ibxeOutputParsingError, [nil]);
1766 <    Inc(RunLen);
1767 <    if FUserInfo[i] = nil then
1768 <      FUserInfo[i] := TUserInfo.Create;
1769 <    FUserInfo[i].UserName := ParseString(RunLen);
1770 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_firstname)) then
1771 <      IBError(ibxeOutputParsingError, [nil]);
1772 <    Inc(RunLen);
1773 <    FUserInfo[i].FirstName := ParseString(RunLen);
1774 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_middlename)) then
1775 <      IBError(ibxeOutputParsingError, [nil]);
1776 <    Inc(RunLen);
1777 <    FUserInfo[i].MiddleName := ParseString(RunLen);
1778 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_lastname)) then
1779 <      IBError(ibxeOutputParsingError, [nil]);
1780 <    Inc(RunLen);
1781 <    FUserInfo[i].LastName := ParseString(RunLen);
1782 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_userId)) then
1783 <      IBError(ibxeOutputParsingError, [nil]);
1784 <    Inc(RunLen);
1785 <    FUserInfo[i].UserId := ParseInteger(RunLen);
1786 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_groupid)) then
1787 <      IBError(ibxeOutputParsingError, [nil]);
1788 <    Inc(RunLen);
1789 <    FUserInfo[i].GroupID := ParseInteger(RunLen);
1790 <    Inc (i);
1755 >  for i := 0 to FServiceQueryResults.Count - 1 do
1756 >  with FServiceQueryResults[i] do
1757 >  begin
1758 >    case getItemType of
1759 >    isc_info_svc_get_users:
1760 >      begin
1761 >        SetLength(FUserInfo,1);
1762 >        k := 0;
1763 >        FUserInfo[0] := TUserInfo.Create;
1764 >        FUserInfo[0].UserName := '';
1765 >        for j := 0 to FServiceQueryResults[i].Count - 1 do
1766 >        begin
1767 >          with FServiceQueryResults[i][j] do
1768 >          case getItemType of
1769 >          isc_spb_sec_username:
1770 >            begin
1771 >              if FUserInfo[k].UserName <> '' then
1772 >              begin
1773 >                Inc(k);
1774 >                SetLength(FUserInfo,k+1);
1775 >                if FUserInfo[k] = nil then
1776 >                  FUserInfo[k] := TUserInfo.Create;
1777 >              end;
1778 >              FUserInfo[k].UserName := AsString;
1779 >            end;
1780 >
1781 >          isc_spb_sec_firstname:
1782 >            FUserInfo[k].FirstName := AsString;
1783 >
1784 >          isc_spb_sec_middlename:
1785 >            FUserInfo[k].MiddleName := AsString;
1786 >
1787 >          isc_spb_sec_lastname:
1788 >            FUserInfo[k].LastName := AsString;
1789 >
1790 >          isc_spb_sec_userId:
1791 >            FUserInfo[k].UserId := AsInteger;
1792 >
1793 >          isc_spb_sec_groupid:
1794 >            FUserInfo[k].GroupID := AsInteger;
1795 >
1796 >          else
1797 >            IBError(ibxeOutputParsingError, [getItemType]);
1798 >          end;
1799 >        end;
1800 >      end;
1801 >    else
1802 >      IBError(ibxeOutputParsingError, [getItemType]);
1803 >    end;
1804    end;
1826  if (i > 0) then
1827    SetLength(FUserInfo, i+1);
1805   end;
1806  
1807   function TIBSecurityService.GetUserInfo(Index: Integer): TUserInfo;
# Line 1837 | Line 1814 | end;
1814  
1815   function TIBSecurityService.GetUserInfoCount: Integer;
1816   begin
1817 <  Result := Max(High(FUSerInfo),0);
1817 >  Result := Length(FUserInfo);
1818   end;
1819  
1820   procedure TIBSecurityService.AddUser;
# Line 1855 | Line 1832 | end;
1832   procedure TIBSecurityService.DisplayUsers;
1833   begin
1834    SecurityAction := ActionDisplayUser;
1835 <  ServiceStartParams  := Char(isc_action_svc_display_user);
1835 >  SRB.Add(isc_action_svc_display_user);
1836    InternalServiceStart;
1837    FetchUserInfo;
1838   end;
# Line 1863 | Line 1840 | end;
1840   procedure TIBSecurityService.DisplayUser(UserName: String);
1841   begin
1842    SecurityAction := ActionDisplayUser;
1843 <  ServiceStartParams  := Char(isc_action_svc_display_user);
1844 <  ServiceStartAddParam (UserName, isc_spb_sec_username);
1843 >  SRB.Add(isc_action_svc_display_user);
1844 >  SRB.Add(isc_spb_sec_username).AsString := UserName;
1845    InternalServiceStart;
1846    FetchUserInfo;
1847   end;
# Line 1949 | Line 1926 | begin
1926        Len := Length(FUserName);
1927        if (Len = 0) then
1928          IBError(ibxeStartParamsError, [nil]);
1929 <      ServiceStartParams  := Char(isc_action_svc_add_user);
1930 <      ServiceStartAddParam (FSQLRole, SPBConstantValues[isc_spb_sql_role_name]);
1931 <      ServiceStartAddParam (FUserName, isc_spb_sec_username);
1932 <      ServiceStartAddParam (FUserID, isc_spb_sec_userid);
1933 <      ServiceStartAddParam (FGroupID, isc_spb_sec_groupid);
1934 <      ServiceStartAddParam (FPassword, isc_spb_sec_password);
1935 <      ServiceStartAddParam (FFirstName, isc_spb_sec_firstname);
1936 <      ServiceStartAddParam (FMiddleName, isc_spb_sec_middlename);
1937 <      ServiceStartAddParam (FLastName, isc_spb_sec_lastname);
1929 >      SRB.Add(isc_action_svc_add_user);
1930 >      SRB.Add(isc_spb_sec_username).AsString := FUserName;
1931 >      SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1932 >      SRB.Add(isc_spb_sec_userid).AsInteger := FUserID;
1933 >      SRB.Add(isc_spb_sec_groupid).AsInteger := FGroupID;
1934 >      SRB.Add(isc_spb_sec_password).AsString := FPassword;
1935 >      SRB.Add(isc_spb_sec_firstname).AsString := FFirstName;
1936 >      SRB.Add(isc_spb_sec_middlename).AsString := FMiddleName;
1937 >      SRB.Add(isc_spb_sec_lastname).AsString := FLastName;
1938      end;
1939      ActionDeleteUser:
1940      begin
# Line 1965 | Line 1942 | begin
1942        Len := Length(FUserName);
1943        if (Len = 0) then
1944          IBError(ibxeStartParamsError, [nil]);
1945 <      ServiceStartParams  := Char(isc_action_svc_delete_user);
1946 <      ServiceStartAddParam (FSQLRole, SPBConstantValues[isc_spb_sql_role_name]);
1947 <      ServiceStartAddParam (FUserName, isc_spb_sec_username);
1945 >      SRB.Add(isc_action_svc_delete_user);
1946 >      SRB.Add(isc_spb_sec_username).AsString := FUserName;
1947 >      SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1948      end;
1949      ActionModifyUser:
1950      begin
# Line 1975 | Line 1952 | begin
1952        Len := Length(FUserName);
1953        if (Len = 0) then
1954          IBError(ibxeStartParamsError, [nil]);
1955 <      ServiceStartParams  := Char(isc_action_svc_modify_user);
1956 <      ServiceStartAddParam (FSQLRole, SPBConstantValues[isc_spb_sql_role_name]);
1957 <      ServiceStartAddParam (FUserName, isc_spb_sec_username);
1955 >      SRB.Add(isc_action_svc_modify_user);
1956 >      SRB.Add(isc_spb_sec_username).AsString := FUserName;
1957 >      SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1958        if (ModifyUserId in FModifyParams) then
1959 <        ServiceStartAddParam (FUserID, isc_spb_sec_userid);
1959 >        SRB.Add(isc_spb_sec_userid).AsInteger := FUserID;
1960        if (ModifyGroupId in FModifyParams) then
1961 <        ServiceStartAddParam (FGroupID, isc_spb_sec_groupid);
1961 >        SRB.Add(isc_spb_sec_groupid).AsInteger := FGroupID;
1962        if (ModifyPassword in FModifyParams) then
1963 <        ServiceStartAddParam (FPassword, isc_spb_sec_password);
1963 >        SRB.Add(isc_spb_sec_password).AsString := FPassword;
1964        if (ModifyFirstName in FModifyParams) then
1965 <        ServiceStartAddParam (FFirstName, isc_spb_sec_firstname);
1965 >        SRB.Add(isc_spb_sec_firstname).AsString := FFirstName;
1966        if (ModifyMiddleName in FModifyParams) then
1967 <        ServiceStartAddParam (FMiddleName, isc_spb_sec_middlename);
1967 >        SRB.Add(isc_spb_sec_middlename).AsString := FMiddleName;
1968        if (ModifyLastName in FModifyParams) then
1969 <        ServiceStartAddParam (FLastName, isc_spb_sec_lastname);
1969 >        SRB.Add(isc_spb_sec_lastname).AsString := FLastName;
1970      end;
1971    end;
1972    ClearParams;
1973   end;
1974  
1975   { TIBUnStructuredService }
1976 < constructor TIBControlAndQueryService.Create(AOwner: TComponent);
1976 > constructor TIBControlAndQueryService.create(AOwner: TComponent);
1977   begin
1978    inherited Create(AOwner);
1979    FEof := False;
# Line 2012 | Line 1989 | end;
1989  
1990   function TIBControlAndQueryService.GetNextChunk: String;
1991   var
1992 <  Length: Integer;
1992 >  i: Integer;
1993   begin
1994    if (FEof = True) then
1995    begin
# Line 2021 | Line 1998 | begin
1998    end;
1999    if (FAction = 0) then
2000      IBError(ibxeQueryParamsError, [nil]);
2001 <  ServiceQueryParams := Char(isc_info_svc_to_eof);
2001 >
2002 >  SRB.Add(isc_info_svc_to_eof);
2003    InternalServiceQuery;
2004 <  if (OutputBuffer[0] <> Char(isc_info_svc_to_eof)) then
2005 <    IBError(ibxeOutputParsingError, [nil]);
2006 <  Length := isc_vax_integer(OutputBuffer + 1, 2);
2007 <  if (OutputBuffer[3 + Length] = Char(isc_info_truncated)) then
2008 <    FEof := False
2009 <  else
2010 <    if (OutputBuffer[3 + Length] = Char(isc_info_end)) then
2011 <      FEof := True
2004 >
2005 >  FEof := True;
2006 >  for i := 0 to FServiceQueryResults.Count - 1 do
2007 >  with FServiceQueryResults[i] do
2008 >  begin
2009 >    case getItemType of
2010 >      isc_info_svc_to_eof:
2011 >        Result := AsString;
2012 >
2013 >      isc_info_truncated:
2014 >        FEof := False;
2015 >    else
2016 >      IBError(ibxeOutputParsingError, [getItemType]);
2017 >    end;
2018 >  end;
2019 > end;
2020 >
2021 > function TIBControlAndQueryService.WriteNextChunk(stream: TStream): integer;
2022 > var
2023 >  i: Integer;
2024 > begin
2025 >  result := 0;
2026 >  if (FEof = True) then
2027 >    exit;
2028 >  if (FAction = 0) then
2029 >    IBError(ibxeQueryParamsError, [nil]);
2030 >
2031 >  SQPB.Add(isc_info_svc_timeout).AsInteger := 1;
2032 >  SRB.Add(isc_info_svc_to_eof);
2033 >  InternalServiceQuery;
2034 >
2035 >  FEof := True;
2036 >  for i := 0 to FServiceQueryResults.Count - 1 do
2037 >  with FServiceQueryResults[i] do
2038 >  begin
2039 >    case getItemType of
2040 >      isc_info_svc_to_eof:
2041 >      begin
2042 >        Result := CopyTo(stream,0);
2043 >        FEof := Result = 0;
2044 >      end;
2045 >
2046 >      isc_info_truncated:
2047 >        FEof := False;
2048 >
2049 >      isc_info_svc_timeout:
2050 >        {ignore};
2051      else
2052 <      IBError(ibxeOutputParsingError, [nil]);
2053 <  OutputBuffer[3 + Length] := #0;
2054 <  result := String(PChar(@OutputBuffer[3]));
2052 >      IBError(ibxeOutputParsingError, [getItemType]);
2053 >    end;
2054 >  end;
2055   end;
2056  
2057   function TIBControlAndQueryService.GetNextLine: String;
2058   var
2059 <  Length: Integer;
2059 >  i: Integer;
2060   begin
2061 +  Result := '';
2062    if (FEof = True) then
2045  begin
2046    result := '';
2063      exit;
2064 <  end;
2064 >
2065    if (FAction = 0) then
2066      IBError(ibxeQueryParamsError, [nil]);
2067 <  ServiceQueryParams := Char(isc_info_svc_line);
2067 >
2068 >  SRB.Add(isc_info_svc_line);
2069    InternalServiceQuery;
2070 <  if (OutputBuffer[0] <> Char(isc_info_svc_line)) then
2071 <    IBError(ibxeOutputParsingError, [nil]);
2072 <  Length := isc_vax_integer(OutputBuffer + 1, 2);
2056 <  if (OutputBuffer[3 + Length] <> Char(isc_info_end)) then
2057 <    IBError(ibxeOutputParsingError, [nil]);
2058 <  if (length <> 0) then
2059 <    FEof := False
2060 <  else
2070 >
2071 >  for i := 0 to FServiceQueryResults.Count - 1 do
2072 >  with FServiceQueryResults[i] do
2073    begin
2074 <    result := '';
2075 <    FEof := True;
2076 <    exit;
2074 >    case getItemType of
2075 >      isc_info_svc_line:
2076 >         Result := AsString;
2077 >    else
2078 >      IBError(ibxeOutputParsingError, [getItemType]);
2079 >    end;
2080    end;
2081 <  OutputBuffer[3 + Length] := #0;
2067 <  result := String(PChar(@OutputBuffer[3]));
2081 >  FEOF := Result = '';
2082   end;
2083  
2084   { TIBLogService }
# Line 2072 | Line 2086 | end;
2086   procedure TIBLogService.SetServiceStartOptions;
2087   begin
2088    Action := isc_action_svc_get_ib_log;
2089 <  ServiceStartParams  := Char(isc_action_svc_get_ib_log);
2089 >  SRB.Add(isc_action_svc_get_ib_log);
2090   end;
2091  
2092   { TDatabaseInfo }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines