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 139 by tony, Wed Jan 24 16:16:29 2018 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, IB, IBExternals, CustApp, IBTypes;
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 >    FSPB : ISPB;
106 >    FSRB: ISRB;
107 >    FSQPB: ISQPB;
108      FTraceFlags: TTraceFlags;
109      FOnLogin: TLoginEvent;
110      FLoginPrompt: Boolean;
110    FBufferSize: Integer;
111    FOutputBuffer: PChar;
112    FQueryParams: String;
111      FServerName: string;
112 <    FHandle: TISC_SVC_HANDLE;
112 >    FService: IServiceManager;
113      FStreamedActive  : Boolean;
114      FOnAttach: TNotifyEvent;
117    FOutputBufferOption: TOutputBufferOption;
115      FProtocol: TProtocol;
116      FParams: TStrings;
117 +    FServiceQueryResults: IServiceQueryResults;
118      function GetActive: Boolean;
119      function GetServiceParamBySPB(const Idx: Integer): String;
120 +    function GetSQPB: ISQPB;
121 +    function GetSRB: ISRB;
122      procedure SetActive(const Value: Boolean);
123    procedure SetBufferSize(const Value: Integer);
123      procedure SetParams(const Value: TStrings);
124      procedure SetServerName(const Value: string);
125      procedure SetProtocol(const Value: TProtocol);
126 +    procedure SetService(AValue: IServiceManager);
127      procedure SetServiceParamBySPB(const Idx: Integer;
128        const Value: String);
129 <    function IndexOfSPBConst(st: String): Integer;
129 >    function IndexOfSPBConst(action: byte): Integer;
130 >    function GetSPBConstName(action: byte): string;
131      procedure ParamsChange(Sender: TObject);
132      procedure ParamsChanging(Sender: TObject);
133      procedure CheckServerName;
134 <    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);
134 >    function GenerateSPB(sl: TStrings): ISPB;
135  
136    protected
137      procedure Loaded; override;
138 <    function Login: Boolean;
138 >    function Login(var aServerName: string): Boolean;
139      procedure CheckActive;
140      procedure CheckInactive;
141      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;
142      procedure InternalServiceQuery;
143 <    property ServiceQueryParams: String read FQueryParams write FQueryParams;
143 >    property SRB: ISRB read GetSRB;
144 >    property SQPB: ISQPB read GetSQPB;
145 >    property ServiceQueryResults: IServiceQueryResults read FServiceQueryResults;
146  
147    public
148      constructor Create(AOwner: TComponent); override;
149      destructor Destroy; override;
150      procedure Attach;
151      procedure Detach;
152 <    property Handle: TISC_SVC_HANDLE read FHandle;
152 >
153 >    {Copies database parameters as give in the DBParams to the Service
154 >      omitting any parameters not appropriate for TIBService. Typically, the
155 >      DBParams are TIBDatabase.Params}
156 >    procedure SetDBParams(DBParams: TStrings);
157 >
158 >    property ServiceIntf: IServiceManager read FService write SetService;
159      property ServiceParamBySPB[const Idx: Integer]: String read GetServiceParamBySPB
160                                                        write SetServiceParamBySPB;
161    published
# Line 228 | Line 231 | type
231      FLicenseMaskInfo: TLicenseMaskInfo;
232      FVersionInfo: TVersionInfo;
233      FConfigParams: TConfigParams;
231    procedure ParseConfigFileData(var RunLen: Integer);
234    public
235      constructor Create(AOwner: TComponent); override;
236      destructor Destroy; override;
# Line 247 | Line 249 | type
249      property Options : TPropertyOptions read FOptions write FOptions;
250    end;
251  
252 +  { TIBControlService }
253 +
254    TIBControlService = class (TIBCustomService)
255    private
252    FStartParams: String;
253    FStartSPB: PChar;
254    FStartSPBLength: Integer;
256      function GetIsServiceRunning: Boolean;
257    protected
258 <    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;
258 >    procedure CheckServiceNotRunning;
259      procedure InternalServiceStart;
260 +    procedure SetServiceStartOptions; virtual;
261  
262    public
263      constructor Create(AOwner: TComponent); override;
# Line 266 | Line 265 | type
265      property IsServiceRunning : Boolean read GetIsServiceRunning;
266    end;
267  
268 +  { TIBControlAndQueryService }
269 +
270    TIBControlAndQueryService = class (TIBControlService)
271    private
272      FEof: Boolean;
# Line 277 | Line 278 | type
278      constructor create (AOwner: TComponent); override;
279      function GetNextLine : String;
280      function GetNextChunk : String;
281 +    function WriteNextChunk(stream: TStream): integer;
282      property Eof: boolean read FEof;
281  published
282    property BufferSize;
283    end;
284  
285    TShutdownMode = (Forced, DenyTransaction, DenyAttachment);
# Line 314 | Line 314 | type
314    published
315    end;
316  
317 <  TStatOption = (DataPages, DbLog, HeaderPages, IndexPages, SystemRelations);
317 >  TStatOption = (DataPages, {DbLog,} HeaderPages, IndexPages, SystemRelations);
318    TStatOptions = set of TStatOption;
319  
320    TIBStatisticalService = class(TIBControlAndQueryService)
# Line 330 | Line 330 | type
330      property Options :  TStatOptions read FOptions write FOptions;
331    end;
332  
333 +  TBackupLocation = (flServerSide,flClientSide);
334 +
335 +  { TIBBackupRestoreService }
336  
337    TIBBackupRestoreService = class(TIBControlAndQueryService)
338    private
339 +    FBackupFileLocation: TBackupLocation;
340      FVerbose: Boolean;
341    protected
342    public
343 +    constructor Create(AOwner: TComponent); override;
344    published
345      property Verbose : Boolean read FVerbose write FVerbose default False;
346 +    property BackupFileLocation: TBackupLocation read FBackupFileLocation
347 +                                                      write FBackupFileLocation default flServerSide;
348    end;
349  
350    TBackupOption = (IgnoreChecksums, IgnoreLimbo, MetadataOnly, NoGarbageCollection,
# Line 369 | Line 376 | type
376      Replace, CreateNewDB, UseAllSpace);
377  
378    TRestoreOptions = set of TRestoreOption;
379 +
380 +  { TIBRestoreService }
381 +
382    TIBRestoreService = class (TIBBackupRestoreService)
383    private
384      FDatabaseName: TStrings;
# Line 376 | Line 386 | type
386      FOptions: TRestoreOptions;
387      FPageSize: Integer;
388      FPageBuffers: Integer;
389 +    FSendBytes: integer;
390      procedure SetBackupFile(const Value: TStrings);
391      procedure SetDatabaseName(const Value: TStrings);
392    protected
# Line 383 | Line 394 | type
394    public
395      constructor Create(AOwner: TComponent); override;
396      destructor Destroy; override;
397 +    function SendNextChunk(stream: TStream; var line: String): integer;
398    published
399      { a name=value pair of filename and length }
400      property DatabaseName: TStrings read FDatabaseName write SetDatabaseName;
# Line 513 | Line 525 | type
525   implementation
526  
527   uses
528 <  IBIntf , IBSQLMonitor, Math;
528 >  IBSQLMonitor, FBMessages;
529 >
530 > { TIBBackupRestoreService }
531 >
532 > constructor TIBBackupRestoreService.Create(AOwner: TComponent);
533 > begin
534 >  inherited Create(AOwner);
535 >  FBackupFileLocation := flServerSide;
536 > end;
537  
538   { TIBCustomService }
539  
540   procedure TIBCustomService.Attach;
541 < var
522 <  SPB: String;
523 <  ConnectString: String;
541 > var aServerName: string;
542   begin
543    CheckInactive;
544    CheckServerName;
545  
546 <  if FLoginPrompt and not Login then
546 >  aServerName := FServerName;
547 >
548 >  if FLoginPrompt and not Login(aServerName) then
549      IBError(ibxeOperationCancelled, [nil]);
550  
551    { Generate a new SPB if necessary }
552    if FParamsChanged then
553    begin
554      FParamsChanged := False;
555 <    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;
555 >    FSPB := GenerateSPB(FParams);
556    end;
557  
558 +  FService := FirebirdAPI.GetServiceManager(aServerName,FProtocol,FSPB);
559 +
560    if Assigned(FOnAttach) then
561      FOnAttach(Self);
562  
# Line 570 | Line 577 | begin
577    end;
578   end;
579  
580 < function TIBCustomService.Login: Boolean;
580 > function TIBCustomService.Login(var aServerName: string): Boolean;
581   var
582    IndexOfUser, IndexOfPassword: Integer;
583    Username, Password: String;
# Line 583 | Line 590 | begin
590        LoginParams.Assign(Params);
591        FOnLogin(Self, LoginParams);
592        Params.Assign (LoginParams);
593 +      aServerName := ServerName;
594      finally
595        LoginParams.Free;
596      end;
# Line 590 | Line 598 | begin
598    else
599    if assigned(IBGUIInterface)  then
600    begin
601 <    IndexOfUser := IndexOfSPBConst(SPBConstantNames[isc_spb_user_name]);
601 >    IndexOfUser := IndexOfSPBConst(isc_spb_user_name);
602      if IndexOfUser <> -1 then
603        Username := Copy(Params[IndexOfUser],
604                                           Pos('=', Params[IndexOfUser]) + 1, {mbcs ok}
605                                           Length(Params[IndexOfUser]));
606 <    IndexOfPassword := IndexOfSPBConst(SPBConstantNames[isc_spb_password]);
606 >    IndexOfPassword := IndexOfSPBConst(isc_spb_password);
607      if IndexOfPassword <> -1 then
608        Password := Copy(Params[IndexOfPassword],
609                                           Pos('=', Params[IndexOfPassword]) + 1, {mbcs ok}
610                                           Length(Params[IndexOfPassword]));
611 <    result := IBGUIInterface.ServerLoginDialog(serverName, Username, Password);
611 >    result := IBGUIInterface.ServerLoginDialog(aServerName, Username, Password);
612      if result then
613      begin
614 <      IndexOfPassword := IndexOfSPBConst(SPBConstantNames[isc_spb_password]);
614 >      IndexOfPassword := IndexOfSPBConst(isc_spb_password);
615        if IndexOfUser = -1 then
616 <        Params.Add(SPBConstantNames[isc_spb_user_name] + '=' + Username)
616 >        Params.Add(GetSPBConstName(isc_spb_user_name) + '=' + Username)
617        else
618 <        Params[IndexOfUser] := SPBConstantNames[isc_spb_user_name] +
618 >        Params[IndexOfUser] := GetSPBConstName(isc_spb_user_name) +
619                                   '=' + Username;
620        if IndexOfPassword = -1 then
621 <        Params.Add(SPBConstantNames[isc_spb_password] + '=' + Password)
621 >        Params.Add(GetSPBConstName(isc_spb_password) + '=' + Password)
622        else
623 <        Params[IndexOfPassword] := SPBConstantNames[isc_spb_password] +
623 >        Params[IndexOfPassword] := GetSPBConstName(isc_spb_password) +
624                                       '=' + Password;
625      end
626    end
# Line 624 | Line 632 | procedure TIBCustomService.CheckActive;
632   begin
633    if FStreamedActive and (not Active) then
634      Loaded;
635 <  if FHandle = nil then
635 >  if FService = nil then
636      IBError(ibxeServiceActive, [nil]);
637   end;
638  
639   procedure TIBCustomService.CheckInactive;
640   begin
641 <  if FHandle <> nil then
641 >  if FService <> nil then
642      IBError(ibxeServiceInActive, [nil]);
643   end;
644  
# Line 653 | Line 661 | end;
661   constructor TIBCustomService.Create(AOwner: TComponent);
662   begin
663    inherited Create(AOwner);
656  FIBLoaded := False;
657  CheckIBLoaded;
658  FIBLoaded := True;
664    FserverName := '';
665    FParams := TStringList.Create;
666    FParamsChanged := True;
667    TStringList(FParams).OnChange := ParamsChange;
668    TStringList(FParams).OnChanging := ParamsChanging;
664  FSPB := nil;
665  FQuerySPB := nil;
666  FBufferSize := DefaultBufferSize;
667  FHandle := nil;
669    FLoginPrompt := True;
670    FTraceFlags := [];
671 <  FOutputbuffer := nil;
671 >  FService := nil;
672 >  FSRB := nil;
673 >  FSPB := nil;
674 >  FServiceQueryResults := nil;
675    FProtocol := Local;
676    if (AOwner <> nil) and
677       (AOwner is TCustomApplication) and
# Line 677 | Line 681 | end;
681  
682   destructor TIBCustomService.Destroy;
683   begin
684 <  if FIBLoaded then
681 <  begin
682 <    if FHandle <> nil then
684 >  if FService <> nil then
685        Detach;
686 <    FreeMem(FSPB);
687 <    FSPB := nil;
688 <    FParams.Free;
689 <  end;
688 <  ReallocMem(FOutputBuffer, 0);
686 >  FSRB := nil;
687 >  FSPB := nil;
688 >  FParams.Free;
689 >  FServiceQueryResults := nil;
690    inherited Destroy;
691   end;
692  
693   procedure TIBCustomService.Detach;
694   begin
695    CheckActive;
696 <  if (Call(isc_service_detach(StatusVector, @FHandle), False) > 0) then
697 <  begin
697 <    FHandle := nil;
698 <    IBDataBaseError;
699 <  end
700 <  else
701 <    FHandle := nil;
696 >  FService.Detach;
697 >  FService := nil;
698    MonitorHook.ServiceDetach(Self);
699   end;
700  
701 + procedure TIBCustomService.SetDBParams(DBParams: TStrings);
702 + var i: integer;
703 +    j: integer;
704 +    k: integer;
705 +    ParamName: string;
706 + begin
707 +  Params.Clear;
708 +  for i := 0 to DBParams.Count - 1 do
709 +  begin
710 +    ParamName := DBParams[i];
711 +    k := Pos('=',ParamName);
712 +    if k > 0 then system.Delete(ParamName,k,Length(ParamName)-k+1);
713 +    for j := 1 to isc_spb_last_spb_constant do
714 +      if ParamName = SPBConstantNames[j] then
715 +      begin
716 +        Params.Add(DBParams[i]);
717 +        break;
718 +      end;
719 +  end;
720 + end;
721 +
722   function TIBCustomService.GetActive: Boolean;
723   begin
724 <  result := FHandle <> nil;
724 >  result := FService <> nil;
725   end;
726  
727   function TIBCustomService.GetServiceParamBySPB(const Idx: Integer): String;
# Line 713 | Line 730 | var
730   begin
731    if (Idx > 0) and (Idx <= isc_spb_last_spb_constant) then
732    begin
733 <    ConstIdx := IndexOfSPBConst(SPBConstantNames[Idx]);
733 >    ConstIdx := IndexOfSPBConst(Idx);
734      if ConstIdx = -1 then
735        result := ''
736      else
# Line 730 | Line 747 | begin
747      result := '';
748   end;
749  
750 + function TIBCustomService.GetSQPB: ISQPB;
751 + begin
752 +  CheckActive;
753 +  if FSQPB = nil then
754 +    FSQPB := FService.AllocateSQPB;
755 +  Result := FSQPB;
756 + end;
757 +
758 + function TIBCustomService.GetSRB: ISRB;
759 + begin
760 +  CheckActive;
761 +  if FSRB = nil then
762 +    FSRB := FService.AllocateSRB;
763 +  Result := FSRB;
764 + end;
765 +
766   procedure TIBCustomService.InternalServiceQuery;
767   begin
768 <  FQuerySPBLength := Length(FQueryParams);
769 <  if FQuerySPBLength = 0 then
770 <    IBError(ibxeQueryParamsError, [nil]);
771 <  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;
768 >  CheckActive;
769 >  FServiceQueryResults := FService.Query(FSQPB,FSRB);
770 >  FSQPB := nil;
771 >  FSRB := nil;
772    MonitorHook.ServiceQuery(Self);
773   end;
774  
# Line 761 | Line 777 | begin
777    if csReading in ComponentState then
778      FStreamedActive := Value
779    else
780 <    if Value <> Active then  
780 >    if Value <> Active then
781 >    begin
782        if Value then
783          Attach
784        else
785          Detach;
786 < end;
787 <
788 < procedure TIBCustomService.SetBufferSize(const Value: Integer);
789 < begin
790 <  if (FOutputBuffer <> nil) and (Value <> FBufferSize) then
791 <    IBAlloc(FOutputBuffer, 0, FBufferSize);
786 >    end
787 >   else if Value then
788 >   begin
789 >     FService.Detach;
790 >     FService.Attach;
791 >   end;
792   end;
793  
794   procedure TIBCustomService.SetParams(const Value: TStrings);
# Line 799 | Line 816 | begin
816    end;
817   end;
818  
819 + procedure TIBCustomService.SetService(AValue: IServiceManager);
820 + begin
821 +  if FService = AValue then Exit;
822 +  FService := AValue;
823 +  if AValue <> nil then
824 +    FServerName := FService.getServerName;
825 + end;
826 +
827   procedure TIBCustomService.SetServiceParamBySPB(const Idx: Integer;
828    const Value: String);
829   var
830    ConstIdx: Integer;
831   begin
832 <  ConstIdx := IndexOfSPBConst(SPBConstantNames[Idx]);
832 >  ConstIdx := IndexOfSPBConst(Idx);
833    if (Value = '') then
834    begin
835      if ConstIdx <> -1 then
# Line 813 | Line 838 | begin
838    else
839    begin
840      if (ConstIdx = -1) then
841 <      Params.Add(SPBConstantNames[Idx] + '=' + Value)
841 >      Params.Add(GetSPBConstName(Idx) + '=' + Value)
842      else
843 <      Params[ConstIdx] := SPBConstantNames[Idx] + '=' + Value;
843 >      Params[ConstIdx] := GetSPBConstName(Idx) + '=' + Value;
844    end;
845   end;
846  
847 < function TIBCustomService.IndexOfSPBConst(st: String): Integer;
847 > function TIBCustomService.IndexOfSPBConst(action: byte): Integer;
848   var
849 <  i, pos_of_str: Integer;
849 >  i,  pos_of_str: Integer;
850 >  st: string;
851   begin
852    result := -1;
853 +  st := GetSPBConstName(action);
854 +  if st <> '' then
855    for i := 0 to Params.Count - 1 do
856    begin
857      pos_of_str := Pos(st, Params[i]); {mbcs ok}
# Line 835 | Line 863 | begin
863    end;
864   end;
865  
866 + function TIBCustomService.GetSPBConstName(action: byte): string;
867 + var i: integer;
868 + begin
869 +  Result := '';
870 +  for i := Low(SPBConstantValues) to High(SPBConstantValues) do
871 +    if SPBConstantValues[i] = action then
872 +    begin
873 +      Result := SPBConstantNames[i];
874 +      break;
875 +    end;
876 + end;
877 +
878   procedure TIBCustomService.ParamsChange(Sender: TObject);
879   begin
880    FParamsChanged := True;
# Line 851 | Line 891 | begin
891      IBError(ibxeServerNameMissing, [nil]);
892   end;
893  
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
894   {
895   * GenerateSPB -
896   *  Given a string containing a textual representation
897   *  of the Service parameters, generate a service
898 < *  parameter buffer, and return it and its length
892 < *  in SPB and SPBLength, respectively.
898 > *  parameter buffer, and return it .
899   }
900 < procedure TIBCustomService.GenerateSPB(sl: TStrings; var SPB: String;
895 <  var SPBLength: Short);
900 > function TIBCustomService.GenerateSPB(sl: TStrings): ISPB;
901   var
902    i, j, SPBVal, SPBServerVal: UShort;
903    param_name, param_value: String;
# Line 900 | Line 905 | begin
905    { The SPB is initially empty, with the exception that
906     the SPB version must be the first byte of the string.
907    }
908 <  SPBLength := 2;
909 <  SPB := Char(isc_spb_version);
905 <  SPB := SPB + Char(isc_spb_current_version);
908 >  Result := FirebirdAPI.AllocateSPB;
909 >
910    { Iterate through the textual service parameters, constructing
911     a SPB on-the-fly }
912    if sl.Count > 0 then
# Line 929 | Line 933 | begin
933          SPBServerVal := SPBConstantValues[j];
934          break;
935        end;
936 <    case SPBVal of
936 >    case SPBServerVal of
937        isc_spb_user_name, isc_spb_password:
938 <      begin
935 <        SPB := SPB +
936 <               Char(SPBServerVal) +
937 <               Char(Length(param_value)) +
938 <               param_value;
939 <        Inc(SPBLength, 2 + Length(param_value));
940 <      end;
938 >        Result.Add(SPBServerVal).AsString := param_value;
939        else
940        begin
941 <        if (SPBVal > 0) and
944 <           (SPBVal <= isc_dpb_last_dpb_constant) then
941 >        if GetSPBConstName(SPBServerVal) <> '' then
942            IBError(ibxeSPBConstantNotSupported,
943 <                   [SPBConstantNames[SPBVal]])
943 >                   [GetSPBConstName(SPBServerVal)])
944          else
945 <          IBError(ibxeSPBConstantUnknown, [SPBVal]);
945 >          IBError(ibxeSPBConstantUnknown, [SPBServerVal]);
946        end;
947      end;
948    end;
# Line 972 | Line 969 | begin
969    inherited Destroy;
970   end;
971  
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
972   procedure TIBServerProperties.Fetch;
973   begin
974    if (Database in Options) then
# Line 1001 | Line 985 | end;
985  
986   procedure TIBServerProperties.FetchConfigParams;
987   var
988 <  RunLen: Integer;
988 >  i, j: Integer;
989  
990   begin
991 <  ServiceQueryParams := Char(isc_info_svc_get_config) +
992 <                        Char(isc_info_svc_get_env) +
993 <                        Char(isc_info_svc_get_env_lock) +
994 <                        Char(isc_info_svc_get_env_msg) +
995 <                        Char(isc_info_svc_user_dbpath);
991 >  SRB.Add(isc_info_svc_get_config);
992 >  SRB.Add(isc_info_svc_get_env);
993 >  SRB.Add(isc_info_svc_get_env_lock);
994 >  SRB.Add(isc_info_svc_get_env_msg);
995 >  SRB.Add(isc_info_svc_user_dbpath);
996  
997    InternalServiceQuery;
998 <  RunLen := 0;
999 <  While (not (Integer(OutputBuffer[RunLen]) = isc_info_end)) do
998 >
999 >  for i := 0 to FServiceQueryResults.Count - 1 do
1000 >  with FServiceQueryResults[i] do
1001    begin
1002 <    case Integer(OutputBuffer[RunLen]) of
1002 >    case getItemType of
1003        isc_info_svc_get_config:
1004        begin
1005 <        FConfigParams.ConfigFileData.ConfigFileKey := nil;
1006 <        FConfigParams.ConfigFileData.ConfigFileValue := nil;
1007 <        Inc (RunLen);
1008 <        while (not (Integer(OutputBuffer[RunLen]) = isc_info_flag_end)) do
1009 <          ParseConfigFileData (RunLen);
1010 <        if (Integer(OutputBuffer[RunLen]) = isc_info_flag_end) then
1011 <          Inc (RunLen);
1005 >        SetLength (FConfigParams.ConfigFileData.ConfigFileValue, Count);
1006 >        SetLength (FConfigParams.ConfigFileData.ConfigFileKey, Count);
1007 >
1008 >        for j := 0 to Count - 1 do
1009 >        begin
1010 >          FConfigParams.ConfigFileData.ConfigFileKey[j] := Items[j].getItemType;
1011 >          FConfigParams.ConfigFileData.ConfigFileValue[j] := Items[j].AsInteger;
1012 >        end;
1013        end;
1014  
1015        isc_info_svc_get_env:
1016 <      begin
1031 <        Inc (RunLen);
1032 <        FConfigParams.BaseLocation := ParseString(RunLen);
1033 <      end;
1016 >        FConfigParams.BaseLocation := AsString;
1017  
1018        isc_info_svc_get_env_lock:
1019 <      begin
1037 <        Inc (RunLen);
1038 <        FConfigParams.LockFileLocation := ParseString(RunLen);
1039 <      end;
1019 >        FConfigParams.LockFileLocation := AsString;
1020  
1021        isc_info_svc_get_env_msg:
1022 <      begin
1043 <        Inc (RunLen);
1044 <        FConfigParams.MessageFileLocation := ParseString(RunLen);
1045 <      end;
1022 >        FConfigParams.MessageFileLocation := AsString;
1023  
1024        isc_info_svc_user_dbpath:
1025 <      begin
1026 <        Inc (RunLen);
1050 <        FConfigParams.SecurityDatabaseLocation := ParseString(RunLen);
1051 <      end;
1025 >        FConfigParams.SecurityDatabaseLocation := AsString;
1026 >
1027        else
1028 <        IBError(ibxeOutputParsingError, [nil]);
1028 >        IBError(ibxeOutputParsingError, [getItemType]);
1029      end;
1030    end;
1031   end;
1032  
1033   procedure TIBServerProperties.FetchDatabaseInfo;
1034   var
1035 <  i, RunLen: Integer;
1035 >  i,j: Integer;
1036   begin
1037 <  ServiceQueryParams := Char(isc_info_svc_svr_db_info);
1037 >  SRB.Add(isc_info_svc_svr_db_info);
1038    InternalServiceQuery;
1039 <  if (OutputBuffer[0] <> Char(isc_info_svc_svr_db_info)) then
1040 <      IBError(ibxeOutputParsingError, [nil]);
1041 <  RunLen := 1;
1042 <  if (OutputBuffer[RunLen] <> Char(isc_spb_num_att)) then
1043 <      IBError(ibxeOutputParsingError, [nil]);
1044 <  Inc(RunLen);
1045 <  FDatabaseInfo.NoOfAttachments := ParseInteger(RunLen);
1046 <  if (OutputBuffer[RunLen] <> Char(isc_spb_num_db)) then
1047 <      IBError(ibxeOutputParsingError, [nil]);
1048 <  Inc(RunLen);
1049 <  FDatabaseInfo.NoOfDatabases := ParseInteger(RunLen);
1050 <  FDatabaseInfo.DbName := nil;
1051 <  SetLength(FDatabaseInfo.DbName, FDatabaseInfo.NoOfDatabases);
1052 <  i := 0;
1053 <  while (OutputBuffer[RunLen] <> Char(isc_info_flag_end)) do
1054 <  begin
1055 <    if (OutputBuffer[RunLen] <> Char(SPBConstantValues[isc_spb_dbname])) then
1056 <      IBError(ibxeOutputParsingError, [nil]);
1057 <    Inc(RunLen);
1058 <    FDatabaseInfo.DbName[i] := ParseString(RunLen);
1059 <    Inc (i);
1060 <  end;
1039 >
1040 >  SetLength(FDatabaseInfo.DbName,0);
1041 >  for i := 0 to FServiceQueryResults.Count - 1 do
1042 >  with FServiceQueryResults[i] do
1043 >  begin
1044 >    case getItemType of
1045 >      isc_info_svc_svr_db_info:
1046 >        for j := 0 to FServiceQueryResults[i].Count - 1 do
1047 >        with FServiceQueryResults[i][j] do
1048 >        case getItemType of
1049 >        isc_spb_num_att:
1050 >          FDatabaseInfo.NoOfAttachments := AsInteger;
1051 >
1052 >        isc_spb_num_db:
1053 >          FDatabaseInfo.NoOfDatabases := AsInteger;
1054 >
1055 >        isc_spb_dbname:
1056 >          begin
1057 >            SetLength(FDatabaseInfo.DbName,length(FDatabaseInfo.DbName)+1);
1058 >            FDatabaseInfo.DbName[length(FDatabaseInfo.DbName)-1] := AsString;
1059 >          end;
1060 >        else
1061 >          IBError(ibxeOutputParsingError, [getItemType]);
1062 >        end;
1063 >      else
1064 >        IBError(ibxeOutputParsingError, [getItemType]);
1065 >    end;
1066 > end;
1067   end;
1068  
1069   procedure TIBServerProperties.FetchLicenseInfo;
1070   var
1071 <  i, RunLen: Integer;
1091 <  done: Integer;
1071 >  i,j : Integer;
1072   begin
1073 <  ServiceQueryParams := Char(isc_info_svc_get_license) +
1074 <                        Char(isc_info_svc_get_licensed_users);
1073 >  SRB.Add(isc_info_svc_get_license);
1074 >  SRB.Add(isc_info_svc_get_licensed_users);
1075    InternalServiceQuery;
1076 <  RunLen := 0;
1077 <  done := 0;
1078 <  i := 0;
1079 <  FLicenseInfo.key := nil;
1080 <  FLicenseInfo.id := nil;
1081 <  FLicenseInfo.desc := nil;
1082 <
1083 <  While done < 2 do begin
1084 <    Inc(Done);
1105 <    Inc(RunLen);
1106 <    case Integer(OutputBuffer[RunLen-1]) of
1076 >
1077 >  SetLength(FLicenseInfo.key, 0);
1078 >  SetLength(FLicenseInfo.id, 0);
1079 >  SetLength(FLicenseInfo.desc, 0);
1080 >
1081 >  for i := 0 to FServiceQueryResults.Count - 1 do
1082 >  with FServiceQueryResults[i] do
1083 >  begin
1084 >    case getItemType of
1085        isc_info_svc_get_license:
1108      begin
1109        while (OutputBuffer[RunLen] <> Char(isc_info_flag_end)) do
1086          begin
1087 <          if (i >= Length(FLicenseInfo.key)) then
1088 <          begin
1089 <            SetLength(FLicenseInfo.key, i + 10);
1090 <            SetLength(FLicenseInfo.id, i + 10);
1091 <            SetLength(FLicenseInfo.desc, i + 10);
1087 >          SetLength(FLicenseInfo.key, Count);
1088 >          SetLength(FLicenseInfo.id, Count);
1089 >          SetLength(FLicenseInfo.desc, Count);
1090 >
1091 >          for j := 0 to Count -1 do
1092 >          with Items[j] do
1093 >          case getItemType of
1094 >             isc_spb_lic_id:
1095 >                FLicenseInfo.id[j] := AsString;
1096 >
1097 >             isc_spb_lic_key:
1098 >                FLicenseInfo.key[j] := AsString;
1099 >
1100 >             isc_spb_lic_desc:
1101 >               FLicenseInfo.desc[j] := AsString;
1102 >          else
1103 >            IBError(ibxeOutputParsingError, [getItemType]);
1104            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);
1105          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);
1106        else
1107 <        IBError(ibxeOutputParsingError, [nil]);
1107 >        IBError(ibxeOutputParsingError, [getItemType]);
1108      end;
1109    end;
1110   end;
1111  
1112   procedure TIBServerProperties.FetchLicenseMaskInfo();
1113   var
1114 <  done,RunLen:integer;
1114 >  i : Integer;
1115   begin
1116 <  ServiceQueryParams := Char(isc_info_svc_get_license_mask) +
1117 <                        Char(isc_info_svc_capabilities);
1116 >  SRB.Add(isc_info_svc_get_license_mask);
1117 >  SRB.Add(isc_info_svc_capabilities);
1118    InternalServiceQuery;
1119 <  RunLen := 0;
1120 <  done := 0;
1121 <  While done <= 1 do
1122 <  begin
1123 <    Inc(done);
1159 <    Inc(RunLen);
1160 <    case Integer(OutputBuffer[RunLen-1]) of
1119 >
1120 >  for i := 0 to FServiceQueryResults.Count - 1 do
1121 >  with FServiceQueryResults[i] do
1122 >  begin
1123 >    case getItemType of
1124        isc_info_svc_get_license_mask:
1125 <        FLicenseMaskInfo.LicenseMask := ParseInteger(RunLen);
1125 >        FLicenseMaskInfo.LicenseMask := AsInteger;
1126        isc_info_svc_capabilities:
1127 <        FLicenseMaskInfo.CapabilityMask := ParseInteger(RunLen);
1127 >        FLicenseMaskInfo.CapabilityMask := AsInteger;
1128        else
1129 <        IBError(ibxeOutputParsingError, [nil]);
1129 >        IBError(ibxeOutputParsingError, [getItemType]);
1130      end;
1131    end;
1132   end;
# Line 1171 | Line 1134 | end;
1134  
1135   procedure TIBServerProperties.FetchVersionInfo;
1136   var
1137 <  RunLen: Integer;
1175 <  done: Integer;
1137 >  i : Integer;
1138   begin
1139 <  ServiceQueryParams := Char(isc_info_svc_version) +
1140 <                        Char(isc_info_svc_server_version) +
1141 <                        Char(isc_info_svc_implementation);
1139 >  SRB.Add(isc_info_svc_version);
1140 >  SRB.Add(isc_info_svc_server_version);
1141 >  SRB.Add(isc_info_svc_implementation);
1142    InternalServiceQuery;
1181  RunLen := 0;
1182  done := 0;
1143  
1144 <  While done <= 2 do
1144 >  for i := 0 to FServiceQueryResults.Count - 1 do
1145 >  with FServiceQueryResults[i] do
1146    begin
1147 <    Inc(done);
1187 <    Inc(RunLen);
1188 <    case Integer(OutputBuffer[RunLen-1]) of
1147 >    case getItemType of
1148        isc_info_svc_version:
1149 <        FVersionInfo.ServiceVersion := ParseInteger(RunLen);
1149 >        FVersionInfo.ServiceVersion := AsInteger;
1150        isc_info_svc_server_version:
1151 <        FVersionInfo.ServerVersion := ParseString(RunLen);
1151 >        FVersionInfo.ServerVersion := AsString;
1152        isc_info_svc_implementation:
1153 <        FVersionInfo.ServerImplementation := ParseString(RunLen);
1153 >        FVersionInfo.ServerImplementation := AsString;
1154        else
1155 <        IBError(ibxeOutputParsingError, [nil]);
1155 >        IBError(ibxeOutputParsingError, [getItemType]);
1156      end;
1157    end;
1158   end;
1159  
1160   { TIBControlService }
1161 +
1162   procedure TIBControlService.SetServiceStartOptions;
1163   begin
1164  
1165   end;
1166  
1167   function TIBControlService.GetIsServiceRunning: Boolean;
1208 var
1209  RunLen: Integer;
1168   begin
1169 <  ServiceQueryParams := Char(isc_info_svc_running);
1169 >  SRB.Add(isc_info_svc_running);
1170    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;
1171  
1172 < procedure TIBControlService.ServiceStartAddParam (Value: string; param: Integer);
1173 < var
1174 <  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;
1172 >  Result := (FServiceQueryResults.Count > 0) and
1173 >             (FServiceQueryResults[0].getItemType = isc_info_svc_running) and
1174 >              (FServiceQueryResults[0].AsInteger = 1);
1175   end;
1176  
1177 < procedure TIBControlService.ServiceStartAddParam (Value: Integer; param: Integer);
1177 > procedure TIBControlService.CheckServiceNotRunning;
1178   begin
1179 <  FStartParams  := FStartParams +
1180 <                   Char(Param) +
1241 <                   PChar(@Value)[0] +
1242 <                   PChar(@Value)[1] +
1243 <                   PChar(@Value)[2] +
1244 <                   PChar(@Value)[3];
1179 >  if IsServiceRunning then
1180 >    IBError(ibxeServiceRunning,[nil]);
1181   end;
1182  
1183   constructor TIBControlService.Create(AOwner: TComponent);
1184   begin
1185    inherited create(AOwner);
1186 <  FStartParams := '';
1187 <  FStartSPB := nil;
1252 <  FStartSPBLength := 0;
1186 >  FSRB := nil;
1187 >  FSPB := nil;
1188   end;
1189  
1190   procedure TIBControlService.InternalServiceStart;
1191   begin
1192 <  FStartSPBLength := Length(FStartParams);
1258 <  if FStartSPBLength = 0 then
1192 >  if SRB = nil then
1193      IBError(ibxeStartParamsError, [nil]);
1194 <  IBAlloc(FStartSPB, 0, FStartSPBLength);
1261 <  Move(FStartParams[1], FStartSPB[0], FstartSPBLength);
1194 >
1195    try
1196 <    if call(isc_service_start(StatusVector, @FHandle, nil,
1264 <                           FStartSPBLength, FStartSPB), False) > 0 then
1265 <    begin
1266 <      FHandle := nil;
1267 <      IBDataBaseError;
1268 <    end;
1196 >    FService.Start(SRB);
1197    finally
1198 <    FreeMem(FStartSPB);
1271 <    FStartSPB := nil;
1272 <    FStartSPBLength := 0;
1273 <    FStartParams := '';
1198 >    FSRB := nil;
1199    end;
1200    MonitorHook.ServiceStart(Self);
1201   end;
# Line 1278 | Line 1203 | end;
1203   procedure TIBControlService.ServiceStart;
1204   begin
1205    CheckActive;
1206 +  CheckServiceNotRunning;
1207    SetServiceStartOptions;
1208    InternalServiceStart;
1209   end;
# Line 1291 | Line 1217 | end;
1217  
1218   procedure TIBConfigService.ActivateShadow;
1219   begin
1220 <  ServiceStartParams  := Char(isc_action_svc_properties);
1221 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1222 <  ServiceStartAddParam (isc_spb_prp_activate, SPBConstantValues[isc_spb_options]);
1220 >  SRB.Add(isc_action_svc_properties);
1221 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1222 >  SRB.Add(isc_spb_options).AsInteger := isc_spb_prp_activate;
1223    InternalServiceStart;
1224   end;
1225  
1226   procedure TIBConfigService.BringDatabaseOnline;
1227   begin
1228 <  ServiceStartParams  := Char(isc_action_svc_properties);
1229 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1230 <  ServiceStartAddParam (isc_spb_prp_db_online, SPBConstantValues[isc_spb_options]);
1228 >  SRB.Add(isc_action_svc_properties);
1229 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1230 >  SRB.Add(isc_spb_options).AsInteger := isc_spb_prp_db_online;
1231    InternalServiceStart;
1232   end;
1233  
1234   procedure TIBConfigService.SetAsyncMode(Value: Boolean);
1235   begin
1236 <  ServiceStartParams  := Char(isc_action_svc_properties);
1237 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1238 <  ServiceStartParams := ServiceStartParams +
1313 <                        Char(isc_spb_prp_write_mode);
1236 >  SRB.Add(isc_action_svc_properties);
1237 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1238 >  with SRB.Add(isc_spb_prp_write_mode) do
1239    if Value then
1240 <    ServiceStartParams  := ServiceStartParams +
1316 <                           Char(isc_spb_prp_wm_async)
1240 >    AsByte := isc_spb_prp_wm_async
1241    else
1242 <    ServiceStartParams  := ServiceStartParams +
1319 <                           Char(isc_spb_prp_wm_sync);
1242 >    AsByte := isc_spb_prp_wm_sync;
1243    InternalServiceStart;
1244   end;
1245  
# Line 1327 | Line 1250 | end;
1250  
1251   procedure TIBConfigService.SetPageBuffers(Value: Integer);
1252   begin
1253 <  ServiceStartParams  := Char(isc_action_svc_properties);
1254 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1255 <  ServiceStartAddParam (Value, isc_spb_prp_page_buffers);
1253 >  SRB.Add(isc_action_svc_properties);
1254 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1255 >  SRB.Add(isc_spb_prp_page_buffers).AsInteger := Value;
1256    InternalServiceStart;
1257   end;
1258  
1259   procedure TIBConfigService.SetReadOnly(Value: Boolean);
1260   begin
1261 <  ServiceStartParams  := Char(isc_action_svc_properties);
1262 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1263 <  ServiceStartParams := ServiceStartParams +
1341 <                         Char(isc_spb_prp_access_mode);
1261 >  SRB.Add(isc_action_svc_properties);
1262 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1263 >  with SRB.Add(isc_spb_prp_access_mode) do
1264    if Value then
1265 <    ServiceStartParams  := ServiceStartParams +
1344 <                           Char(isc_spb_prp_am_readonly)
1265 >    AsByte := isc_spb_prp_am_readonly
1266    else
1267 <    ServiceStartParams  := ServiceStartParams +
1347 <                           Char(isc_spb_prp_am_readwrite);
1267 >    AsByte := isc_spb_prp_am_readwrite;
1268    InternalServiceStart;
1269   end;
1270  
1271   procedure TIBConfigService.SetReserveSpace(Value: Boolean);
1272   begin
1273 <  ServiceStartParams  := Char(isc_action_svc_properties);
1274 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1275 <  ServiceStartParams := ServiceStartParams +
1356 <                        Char(isc_spb_prp_reserve_space);
1273 >  SRB.Add(isc_action_svc_properties);
1274 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1275 >  with SRB.Add(isc_spb_prp_reserve_space) do
1276    if Value then
1277 <    ServiceStartParams  := ServiceStartParams +
1359 <                           Char(isc_spb_prp_res)
1277 >    AsByte := isc_spb_prp_res
1278    else
1279 <    ServiceStartParams  := ServiceStartParams +
1362 <                           Char(isc_spb_prp_res_use_full);
1279 >    AsByte := isc_spb_prp_res_use_full;
1280    InternalServiceStart;
1281   end;
1282  
1283   procedure TIBConfigService.SetSweepInterval(Value: Integer);
1284   begin
1285 <  ServiceStartParams  := Char(isc_action_svc_properties);
1286 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1287 <  ServiceStartAddParam (Value, isc_spb_prp_sweep_interval);
1285 >  SRB.Add(isc_action_svc_properties);
1286 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1287 >  SRB.Add(isc_spb_prp_sweep_interval).AsInteger := Value;
1288    InternalServiceStart;
1289   end;
1290  
1291   procedure TIBConfigService.SetDBSqlDialect(Value: Integer);
1292   begin
1293 <  ServiceStartParams  := Char(isc_action_svc_properties);
1294 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1295 <  ServiceStartAddParam (Value, isc_spb_prp_set_sql_dialect);
1293 >  SRB.Add(isc_action_svc_properties);
1294 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1295 >  SRB.Add(isc_spb_prp_set_sql_dialect).AsInteger := Value;
1296    InternalServiceStart;
1297   end;
1298  
1299   procedure TIBConfigService.ShutdownDatabase(Options: TShutdownMode;
1300    Wait: Integer);
1301   begin
1302 <  ServiceStartParams  := Char(isc_action_svc_properties);
1303 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1302 >  SRB.Add(isc_action_svc_properties);
1303 >  SRB.Add(isc_spb_dbname).AsString :=  FDatabaseName;
1304    if (Options = Forced) then
1305 <    ServiceStartAddParam (Wait, isc_spb_prp_shutdown_db)
1305 >  SRB.Add(isc_spb_prp_shutdown_db).AsInteger := Wait
1306    else if (Options = DenyTransaction) then
1307 <    ServiceStartAddParam (Wait, isc_spb_prp_deny_new_transactions)
1307 >    SRB.Add(isc_spb_prp_deny_new_transactions).AsInteger := Wait
1308    else
1309 <    ServiceStartAddParam (Wait, isc_spb_prp_deny_new_attachments);
1309 >    SRB.Add(isc_spb_prp_deny_new_attachments).AsInteger := Wait;
1310    InternalServiceStart;
1311   end;
1312  
1313 +
1314   { TIBStatisticalService }
1315  
1316   procedure TIBStatisticalService.SetDatabaseName(const Value: string);
# Line 1401 | Line 1319 | begin
1319   end;
1320  
1321   procedure TIBStatisticalService.SetServiceStartOptions;
1322 < var
1405 <  param: Integer;
1322 > var param: integer;
1323   begin
1324    if FDatabaseName = '' then
1325      IBError(ibxeStartParamsError, [nil]);
1326 +
1327    param := 0;
1328    if (DataPages in Options) then
1329      param := param or isc_spb_sts_data_pages;
1330 <  if (DbLog in Options) then
1331 <    param := param or isc_spb_sts_db_log;
1330 > {  if (DbLog in Options) then
1331 >    param := param or isc_spb_sts_db_log; -- removed from Firebird 2}
1332    if (HeaderPages in Options) then
1333      param := param or isc_spb_sts_hdr_pages;
1334    if (IndexPages in Options) then
# Line 1418 | Line 1336 | begin
1336    if (SystemRelations in Options) then
1337      param := param or isc_spb_sts_sys_relations;
1338    Action := isc_action_svc_db_stats;
1339 <  ServiceStartParams  := Char(isc_action_svc_db_stats);
1340 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1341 <  ServiceStartAddParam (param, SPBConstantValues[isc_spb_options]);
1339 >  SRB.Add(isc_action_svc_db_stats);
1340 >  SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
1341 >  SRB.Add(isc_spb_options).AsInteger := param;
1342   end;
1343  
1344   { TIBBackupService }
# Line 1447 | Line 1365 | begin
1365    if (ConvertExtTables in Options) then
1366      param := param or isc_spb_bkp_convert;
1367    Action := isc_action_svc_backup;
1368 <  ServiceStartParams  := Char(isc_action_svc_backup);
1369 <  ServiceStartAddParam(FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1370 <  ServiceStartAddParam(param, SPBConstantValues[isc_spb_options]);
1371 <  if Verbose then
1372 <    ServiceStartParams := ServiceStartParams + Char(SPBConstantValues[isc_spb_verbose]);
1368 >  SRB.Add(isc_action_svc_backup);
1369 >  SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
1370 >  SRB.Add(isc_spb_options).AsInteger := param;
1371 >  if Verbose  and (BackupFileLocation = flServerSide) then
1372 >    SRB.Add(isc_spb_verbose);
1373    if FBlockingFactor > 0 then
1374 <    ServiceStartAddParam(FBlockingFactor, isc_spb_bkp_factor);
1374 >    SRB.Add(isc_spb_bkp_factor).AsInteger := FBlockingFactor;
1375 >  if BackupFileLocation = flServerSide then
1376    for i := 0 to FBackupFile.Count - 1 do
1377    begin
1378      if (Trim(FBackupFile[i]) = '') then
1379        continue;
1380      if (Pos('=', FBackupFile[i]) <> 0) then
1381      begin {mbcs ok}
1382 <      ServiceStartAddParam(FBackupFile.Names[i], isc_spb_bkp_file);
1382 >      SRB.Add(isc_spb_bkp_file).AsString := FBackupFile.Names[i];
1383        value := Copy(FBackupFile[i], Pos('=', FBackupFile[i]) + 1, Length(FBackupFile.Names[i])); {mbcs ok}
1384 <      param := StrToInt(value);
1466 <      ServiceStartAddParam(param, isc_spb_bkp_length);
1384 >      SRB.Add(isc_spb_bkp_length).AsInteger := StrToInt(value);;
1385      end
1386      else
1387 <      ServiceStartAddParam(FBackupFile[i], isc_spb_bkp_file);
1388 <  end;
1387 >      SRB.Add(isc_spb_bkp_file).AsString := FBackupFile[i];
1388 >  end
1389 >  else
1390 >  SRB.Add(isc_spb_bkp_file).AsString := 'stdout';
1391   end;
1392  
1393   constructor TIBBackupService.Create(AOwner: TComponent);
# Line 1510 | Line 1430 | begin
1430    if (UseAllSpace in Options) then
1431      param := param or isc_spb_res_use_all_space;
1432    Action := isc_action_svc_restore;
1433 <  ServiceStartParams  := Char(isc_action_svc_restore);
1434 <  ServiceStartAddParam(param, SPBConstantValues[isc_spb_options]);
1435 <  if Verbose then ServiceStartParams := ServiceStartParams + Char(SPBConstantValues[isc_spb_verbose]);
1433 >  SRB.Add(isc_action_svc_restore);
1434 >  SRB.Add(isc_spb_options).AsInteger := param;
1435 >  if Verbose then
1436 >    SRB.Add(isc_spb_verbose);
1437    if FPageSize > 0 then
1438 <    ServiceStartAddParam(FPageSize, isc_spb_res_page_size);
1438 >    SRB.Add(isc_spb_res_page_size).AsInteger := FPageSize;
1439    if FPageBuffers > 0 then
1440 <    ServiceStartAddParam(FPageBuffers, isc_spb_res_buffers);
1440 >    SRB.Add(isc_spb_res_buffers).AsInteger := FPageBuffers;
1441 >  if BackupFileLocation = flServerSide then
1442    for i := 0 to FBackupFile.Count - 1 do
1443    begin
1444      if (Trim(FBackupFile[i]) = '') then continue;
1445      if (Pos('=', FBackupFile[i]) <> 0) then  {mbcs ok}
1446      begin
1447 <      ServiceStartAddParam(AnsiUpperCase(FBackupFile.Names[i]), isc_spb_bkp_file);
1447 >      SRB.Add(isc_spb_bkp_file).AsString := FBackupFile.Names[i];
1448        value := Copy(FBackupFile[i], Pos('=', FBackupFile[i]) + 1, Length(FBackupFile.Names[i])); {mbcs ok}
1449 <      param := StrToInt(value);
1528 <      ServiceStartAddParam(param, isc_spb_bkp_length);
1449 >      SRB.Add(isc_spb_bkp_length).AsInteger := StrToInt(value);;
1450      end
1451      else
1452 <      ServiceStartAddParam(FBackupFile[i], isc_spb_bkp_file);
1453 <  end;
1452 >      SRB.Add(isc_spb_bkp_file).AsString := FBackupFile[i];
1453 >  end
1454 >  else
1455 >    SRB.Add(isc_spb_bkp_file).AsString := 'stdin';
1456 >
1457    for i := 0 to FDatabaseName.Count - 1 do
1458    begin
1459      if (Trim(FDatabaseName[i]) = '') then continue;
1460      if (Pos('=', FDatabaseName[i]) <> 0) then {mbcs ok}
1461 <    begin
1462 <      ServiceStartAddParam(FDatabaseName.Names[i], SPBConstantValues[isc_spb_dbname]);
1461 >    begin
1462 >      SRB.Add(isc_spb_dbname).AsString := FDatabaseName.Names[i];
1463        value := Copy(FDatabaseName[i], Pos('=', FDatabaseName[i]) + 1, Length(FDatabaseName[i])); {mbcs ok}
1464 <      param := StrToInt(value);
1541 <      ServiceStartAddParam(param, isc_spb_res_length);
1464 >      SRB.Add(isc_spb_res_length).AsInteger :=  StrToInt(value);
1465      end
1466      else
1467 <      ServiceStartAddParam(FDatabaseName[i], SPBConstantValues[isc_spb_dbname]);
1467 >      SRB.Add(isc_spb_dbname).AsString := FDatabaseName[i];
1468    end;
1469   end;
1470  
# Line 1560 | Line 1483 | begin
1483    inherited Destroy;
1484   end;
1485  
1486 + function TIBRestoreService.SendNextChunk(stream: TStream; var line: String
1487 +  ): integer;
1488 + var
1489 +  i: Integer;
1490 + begin
1491 +  Result := 0;
1492 +  line := '';
1493 +  if (FEof = True) then
1494 +    exit;
1495 +
1496 +  if (FAction = 0) then
1497 +    IBError(ibxeQueryParamsError, [nil]);
1498 +
1499 +  SRB.Add(isc_info_svc_line);
1500 +  SRB.Add(isc_info_svc_stdin);
1501 +
1502 +  SQPB.Add(isc_info_svc_timeout).AsInteger := 1;
1503 +  if FSendBytes > 0 then
1504 +    Result := SQPB.Add(isc_info_svc_line).CopyFrom(stream,FSendBytes);
1505 +  InternalServiceQuery;
1506 +
1507 +  FSendBytes := 0;
1508 +  for i := 0 to FServiceQueryResults.Count - 1 do
1509 +  with FServiceQueryResults[i] do
1510 +  begin
1511 +    case getItemType of
1512 +      isc_info_svc_line:
1513 +         line := AsString;
1514 +
1515 +      isc_info_svc_stdin:
1516 +        FSendBytes := AsInteger;
1517 +
1518 +      isc_info_svc_timeout,
1519 +      isc_info_data_not_ready:
1520 +        {ignore};
1521 +    else
1522 +      IBError(ibxeOutputParsingError, [getItemType]);
1523 +    end;
1524 +  end;
1525 +  FEOF := (FSendBytes = 0) and (line = '');
1526 + end;
1527 +
1528   procedure TIBRestoreService.SetBackupFile(const Value: TStrings);
1529   begin
1530    FBackupFile.Assign(Value);
# Line 1587 | Line 1552 | begin
1552   end;
1553  
1554   procedure TIBValidationService.FetchLimboTransactionInfo;
1555 +
1556 +  procedure NextLimboTransaction(index: integer);
1557 +  begin
1558 +    SetLength(FLimboTransactionInfo, index+1);
1559 +    FLimboTransactionInfo[index] := TLimboTransactionInfo.Create;
1560 +    { if no advice commit as default }
1561 +    FLimboTransactionInfo[index].Advise := UnknownAdvise;
1562 +    FLimboTransactionInfo[index].Action:= CommitAction;
1563 +  end;
1564 +
1565   var
1566 <  i, RunLen: Integer;
1592 <  Value: Char;
1566 >  i,j, k: Integer;
1567   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);
1568    for i := 0 to High(FLimboTransactionInfo) do
1569      FLimboTransactionInfo[i].Free;
1570 <  FLimboTransactionInfo := nil;
1571 <  i := 0;
1572 <  while (OutputBuffer[RunLen] <> Char(isc_info_end)) do
1573 <  begin
1574 <    if (i >= Length(FLimboTransactionInfo)) then
1575 <      SetLength(FLimboTransactionInfo, i + 10);
1576 <    if FLimboTransactionInfo[i] = nil then
1577 <      FLimboTransactionInfo[i] := TLimboTransactionInfo.Create;
1578 <    with FLimboTransactionInfo[i] do
1570 >  SetLength(FLimboTransactionInfo,0);
1571 >
1572 >  SRB.Add(isc_info_svc_limbo_trans);
1573 >  InternalServiceQuery;
1574 >
1575 >  k := -1;
1576 >  for i := 0 to FServiceQueryResults.Count - 1 do
1577 >  with FServiceQueryResults[i] do
1578 >  case getItemType of
1579 >  isc_info_svc_limbo_trans:
1580      begin
1581 <      if (OutputBuffer[RunLen] = Char(isc_spb_single_tra_id)) then
1582 <      begin
1583 <        Inc(RunLen);
1615 <        MultiDatabase := False;
1616 <        ID := ParseInteger(RunLen);
1617 <      end
1618 <      else
1581 >      if FServiceQueryResults[i].Count = 0 then continue;
1582 >      NextLimboTransaction(0);
1583 >      for j := 0 to FServiceQueryResults[i].Count - 1 do
1584        begin
1585 <        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
1585 >        with FServiceQueryResults[i][j] do
1586          begin
1587 <          Advise := CommitAdvise;
1588 <          Action:= CommitAction;
1589 <        end
1590 <        else
1591 <          if (Value = Char(isc_spb_tra_advise_rollback)) then
1592 <          begin
1593 <            Advise := RollbackAdvise;
1594 <            Action := RollbackAction;
1595 <          end
1596 <          else
1597 <          begin
1598 <            { if no advice commit as default }
1599 <            Advise := UnknownAdvise;
1600 <            Action:= CommitAction;
1587 >          case getItemType of
1588 >            isc_spb_single_tra_id:
1589 >            begin
1590 >              Inc(k);
1591 >              if k > 0 then
1592 >                NextLimboTransaction(k);
1593 >              FLimboTransactionInfo[k].MultiDatabase := False;
1594 >              FLimboTransactionInfo[k].ID := AsInteger;
1595 >            end;
1596 >
1597 >            isc_spb_multi_tra_id:
1598 >            begin
1599 >              Inc(k);
1600 >              if k > 0 then
1601 >                NextLimboTransaction(k);
1602 >              FLimboTransactionInfo[k].MultiDatabase := True;
1603 >              FLimboTransactionInfo[k].ID := AsInteger;
1604 >            end;
1605 >
1606 >            isc_spb_tra_host_site:
1607 >              FLimboTransactionInfo[k].HostSite := AsString;
1608 >
1609 >            isc_spb_tra_state:
1610 >              case AsByte of
1611 >                isc_spb_tra_state_limbo:
1612 >                  FLimboTransactionInfo[k].State := LimboState;
1613 >
1614 >                isc_spb_tra_state_commit:
1615 >                  FLimboTransactionInfo[k].State := CommitState;
1616 >
1617 >                isc_spb_tra_state_rollback:
1618 >                  FLimboTransactionInfo[k].State := RollbackState;
1619 >
1620 >                else
1621 >                  FLimboTransactionInfo[k].State := UnknownState;
1622 >              end;
1623 >
1624 >            isc_spb_tra_remote_site:
1625 >              FLimboTransactionInfo[k].RemoteSite := AsString;
1626 >
1627 >            isc_spb_tra_db_path:
1628 >              FLimboTransactionInfo[k].RemoteDatabasePath := AsString;
1629 >
1630 >            isc_spb_tra_advise:
1631 >            with FLimboTransactionInfo[k] do
1632 >            begin
1633 >              case (AsByte) of
1634 >              isc_spb_tra_advise_commit:
1635 >              begin
1636 >                Advise := CommitAdvise;
1637 >                Action:= CommitAction;
1638 >              end;
1639 >
1640 >              isc_spb_tra_advise_rollback:
1641 >              begin
1642 >                Advise := RollbackAdvise;
1643 >                Action := RollbackAction;
1644 >              end;
1645 >
1646 >              else
1647 >                Advise := UnknownAdvise;
1648 >              end;
1649 >            end;
1650 >
1651 >            else
1652 >              IBError(ibxeOutputParsingError, [getItemType]);
1653            end;
1654 +        end;
1655        end;
1661      Inc (i);
1656      end;
1657 +  else
1658 +    IBError(ibxeOutputParsingError, [getItemType]);
1659    end;
1664  if (i > 0) then
1665    SetLength(FLimboTransactionInfo, i+1);
1660   end;
1661  
1662   procedure TIBValidationService.FixLimboTransactionErrors;
1663   var
1664    i: Integer;
1665   begin
1666 <  ServiceStartParams  := Char(isc_action_svc_repair);
1667 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1668 <  if (FGlobalAction = NoGlobalAction) then
1669 <  begin
1676 <    i := 0;
1677 <    while (FLimboTransactionInfo[i].ID <> 0) do
1666 >  SRB.Add(isc_action_svc_repair);
1667 >  SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
1668 >  case FGlobalAction of
1669 >  NoGlobalAction:
1670      begin
1671 <      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
1671 >      for i := 0 to LimboTransactionInfoCount - 1 do
1672        begin
1673 <        ServiceStartAddParam (FLimboTransactionInfo[i].ID, isc_spb_rpr_commit_trans);
1674 <        Inc(i);
1675 <      end
1676 <    else
1677 <      while (FLimboTransactionInfo[i].ID <> 0) do
1673 >        if (FLimboTransactionInfo[i].Action = CommitAction) then
1674 >          SRB.Add(isc_spb_rpr_commit_trans).AsInteger :=  FLimboTransactionInfo[i].ID
1675 >        else
1676 >          SRB.Add(isc_spb_rpr_rollback_trans).AsInteger :=  FLimboTransactionInfo[i].ID;
1677 >      end;
1678 >    end;
1679 >
1680 >  CommitGlobal:
1681 >    begin
1682 >      for i := 0 to LimboTransactionInfoCount - 1 do
1683 >        SRB.Add(isc_spb_rpr_commit_trans).AsInteger :=  FLimboTransactionInfo[i].ID;
1684 >    end;
1685 >
1686 >    RollbackGlobal:
1687        begin
1688 <        ServiceStartAddParam (FLimboTransactionInfo[i].ID, isc_spb_rpr_rollback_trans);
1689 <        Inc(i);
1688 >        for i := 0 to LimboTransactionInfoCount - 1 do
1689 >          SRB.Add(isc_spb_rpr_rollback_trans).AsInteger :=  FLimboTransactionInfo[i].ID;
1690        end;
1691 +
1692 +    RecoverTwoPhaseGlobal:
1693 +    begin
1694 +      for i := 0 to LimboTransactionInfoCount - 1 do
1695 +        SRB.Add(isc_spb_rpr_recover_two_phase).AsInteger :=  FLimboTransactionInfo[i].ID;
1696 +    end;
1697    end;
1698    InternalServiceStart;
1699   end;
# Line 1712 | Line 1708 | end;
1708  
1709   function TIBValidationService.GetLimboTransactionInfoCount: integer;
1710   begin
1711 <  Result := High(FLimboTransactionInfo);
1711 >  Result := Length(FLimboTransactionInfo);
1712   end;
1713  
1714   procedure TIBValidationService.SetDatabaseName(const Value: string);
# Line 1727 | Line 1723 | begin
1723    Action := isc_action_svc_repair;
1724    if FDatabaseName = '' then
1725      IBError(ibxeStartParamsError, [nil]);
1726 +  SRB.Add(isc_action_svc_repair);
1727 +  SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
1728    param := 0;
1729    if (SweepDB in Options) then
1730      param := param or isc_spb_rpr_sweep_db;
1731    if (ValidateDB in Options) then
1732      param := param or isc_spb_rpr_validate_db;
1733 <  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;
1733 >
1734    if (LimboTransactions in Options) then
1735      param := param or isc_spb_rpr_list_limbo_trans;
1736    if (CheckDB in Options) then
# Line 1754 | Line 1748 | begin
1748         param := param or isc_spb_rpr_validate_db;
1749    end;
1750    if param > 0 then
1751 <    ServiceStartAddParam (param, SPBConstantValues[isc_spb_options]);
1751 >   SRB.Add(isc_spb_options).AsInteger := param;
1752   end;
1753  
1754   { TIBSecurityService }
# Line 1776 | Line 1770 | end;
1770  
1771   procedure TIBSecurityService.FetchUserInfo;
1772   var
1773 <  i, RunLen: Integer;
1773 >  i, j, k: Integer;
1774   begin
1775 <  ServiceQueryParams := Char(isc_info_svc_get_users);
1775 >  SRB.Add(isc_info_svc_get_users);
1776    InternalServiceQuery;
1777 <  RunLen := 0;
1784 <  if (OutputBuffer[RunLen] <> Char(isc_info_svc_get_users)) then
1785 <    IBError(ibxeOutputParsingError, [nil]);
1786 <  Inc(RunLen);
1777 >
1778    for i := 0 to High(FUserInfo) do
1779      FUserInfo[i].Free;
1780 <  FUserInfo := nil;
1781 <  i := 0;
1782 <  { Don't have any use for the combined length
1783 <   so increment past by 2 }
1784 <  Inc(RunLen, 2);
1785 <  while (OutputBuffer[RunLen] <> Char(isc_info_end)) do
1786 <  begin
1787 <    if (i >= Length(FUSerInfo)) then
1788 <      SetLength(FUserInfo, i + 10);
1789 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_username)) then
1790 <      IBError(ibxeOutputParsingError, [nil]);
1791 <    Inc(RunLen);
1792 <    if FUserInfo[i] = nil then
1793 <      FUserInfo[i] := TUserInfo.Create;
1794 <    FUserInfo[i].UserName := ParseString(RunLen);
1795 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_firstname)) then
1796 <      IBError(ibxeOutputParsingError, [nil]);
1797 <    Inc(RunLen);
1798 <    FUserInfo[i].FirstName := ParseString(RunLen);
1799 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_middlename)) then
1800 <      IBError(ibxeOutputParsingError, [nil]);
1801 <    Inc(RunLen);
1802 <    FUserInfo[i].MiddleName := ParseString(RunLen);
1803 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_lastname)) then
1804 <      IBError(ibxeOutputParsingError, [nil]);
1805 <    Inc(RunLen);
1806 <    FUserInfo[i].LastName := ParseString(RunLen);
1807 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_userId)) then
1808 <      IBError(ibxeOutputParsingError, [nil]);
1809 <    Inc(RunLen);
1810 <    FUserInfo[i].UserId := ParseInteger(RunLen);
1811 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_groupid)) then
1812 <      IBError(ibxeOutputParsingError, [nil]);
1813 <    Inc(RunLen);
1814 <    FUserInfo[i].GroupID := ParseInteger(RunLen);
1815 <    Inc (i);
1780 >  for i := 0 to FServiceQueryResults.Count - 1 do
1781 >  with FServiceQueryResults[i] do
1782 >  begin
1783 >    case getItemType of
1784 >    isc_info_svc_get_users:
1785 >      begin
1786 >        SetLength(FUserInfo,1);
1787 >        k := 0;
1788 >        FUserInfo[0] := TUserInfo.Create;
1789 >        FUserInfo[0].UserName := '';
1790 >        for j := 0 to FServiceQueryResults[i].Count - 1 do
1791 >        begin
1792 >          with FServiceQueryResults[i][j] do
1793 >          case getItemType of
1794 >          isc_spb_sec_username:
1795 >            begin
1796 >              if FUserInfo[k].UserName <> '' then
1797 >              begin
1798 >                Inc(k);
1799 >                SetLength(FUserInfo,k+1);
1800 >                if FUserInfo[k] = nil then
1801 >                  FUserInfo[k] := TUserInfo.Create;
1802 >              end;
1803 >              FUserInfo[k].UserName := AsString;
1804 >            end;
1805 >
1806 >          isc_spb_sec_firstname:
1807 >            FUserInfo[k].FirstName := AsString;
1808 >
1809 >          isc_spb_sec_middlename:
1810 >            FUserInfo[k].MiddleName := AsString;
1811 >
1812 >          isc_spb_sec_lastname:
1813 >            FUserInfo[k].LastName := AsString;
1814 >
1815 >          isc_spb_sec_userId:
1816 >            FUserInfo[k].UserId := AsInteger;
1817 >
1818 >          isc_spb_sec_groupid:
1819 >            FUserInfo[k].GroupID := AsInteger;
1820 >
1821 >          else
1822 >            IBError(ibxeOutputParsingError, [getItemType]);
1823 >          end;
1824 >        end;
1825 >      end;
1826 >    else
1827 >      IBError(ibxeOutputParsingError, [getItemType]);
1828 >    end;
1829    end;
1826  if (i > 0) then
1827    SetLength(FUserInfo, i+1);
1830   end;
1831  
1832   function TIBSecurityService.GetUserInfo(Index: Integer): TUserInfo;
# Line 1837 | Line 1839 | end;
1839  
1840   function TIBSecurityService.GetUserInfoCount: Integer;
1841   begin
1842 <  Result := Max(High(FUSerInfo),0);
1842 >  Result := Length(FUserInfo);
1843   end;
1844  
1845   procedure TIBSecurityService.AddUser;
# Line 1855 | Line 1857 | end;
1857   procedure TIBSecurityService.DisplayUsers;
1858   begin
1859    SecurityAction := ActionDisplayUser;
1860 <  ServiceStartParams  := Char(isc_action_svc_display_user);
1860 >  SRB.Add(isc_action_svc_display_user);
1861    InternalServiceStart;
1862    FetchUserInfo;
1863   end;
# Line 1863 | Line 1865 | end;
1865   procedure TIBSecurityService.DisplayUser(UserName: String);
1866   begin
1867    SecurityAction := ActionDisplayUser;
1868 <  ServiceStartParams  := Char(isc_action_svc_display_user);
1869 <  ServiceStartAddParam (UserName, isc_spb_sec_username);
1868 >  SRB.Add(isc_action_svc_display_user);
1869 >  SRB.Add(isc_spb_sec_username).AsString := UserName;
1870    InternalServiceStart;
1871    FetchUserInfo;
1872   end;
# Line 1949 | Line 1951 | begin
1951        Len := Length(FUserName);
1952        if (Len = 0) then
1953          IBError(ibxeStartParamsError, [nil]);
1954 <      ServiceStartParams  := Char(isc_action_svc_add_user);
1955 <      ServiceStartAddParam (FSQLRole, SPBConstantValues[isc_spb_sql_role_name]);
1956 <      ServiceStartAddParam (FUserName, isc_spb_sec_username);
1957 <      ServiceStartAddParam (FUserID, isc_spb_sec_userid);
1958 <      ServiceStartAddParam (FGroupID, isc_spb_sec_groupid);
1959 <      ServiceStartAddParam (FPassword, isc_spb_sec_password);
1960 <      ServiceStartAddParam (FFirstName, isc_spb_sec_firstname);
1961 <      ServiceStartAddParam (FMiddleName, isc_spb_sec_middlename);
1962 <      ServiceStartAddParam (FLastName, isc_spb_sec_lastname);
1954 >      SRB.Add(isc_action_svc_add_user);
1955 >      SRB.Add(isc_spb_sec_username).AsString := FUserName;
1956 >      SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1957 >      SRB.Add(isc_spb_sec_userid).AsInteger := FUserID;
1958 >      SRB.Add(isc_spb_sec_groupid).AsInteger := FGroupID;
1959 >      SRB.Add(isc_spb_sec_password).AsString := FPassword;
1960 >      SRB.Add(isc_spb_sec_firstname).AsString := FFirstName;
1961 >      SRB.Add(isc_spb_sec_middlename).AsString := FMiddleName;
1962 >      SRB.Add(isc_spb_sec_lastname).AsString := FLastName;
1963      end;
1964      ActionDeleteUser:
1965      begin
# Line 1965 | Line 1967 | begin
1967        Len := Length(FUserName);
1968        if (Len = 0) then
1969          IBError(ibxeStartParamsError, [nil]);
1970 <      ServiceStartParams  := Char(isc_action_svc_delete_user);
1971 <      ServiceStartAddParam (FSQLRole, SPBConstantValues[isc_spb_sql_role_name]);
1972 <      ServiceStartAddParam (FUserName, isc_spb_sec_username);
1970 >      SRB.Add(isc_action_svc_delete_user);
1971 >      SRB.Add(isc_spb_sec_username).AsString := FUserName;
1972 >      SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1973      end;
1974      ActionModifyUser:
1975      begin
# Line 1975 | Line 1977 | begin
1977        Len := Length(FUserName);
1978        if (Len = 0) then
1979          IBError(ibxeStartParamsError, [nil]);
1980 <      ServiceStartParams  := Char(isc_action_svc_modify_user);
1981 <      ServiceStartAddParam (FSQLRole, SPBConstantValues[isc_spb_sql_role_name]);
1982 <      ServiceStartAddParam (FUserName, isc_spb_sec_username);
1980 >      SRB.Add(isc_action_svc_modify_user);
1981 >      SRB.Add(isc_spb_sec_username).AsString := FUserName;
1982 >      SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1983        if (ModifyUserId in FModifyParams) then
1984 <        ServiceStartAddParam (FUserID, isc_spb_sec_userid);
1984 >        SRB.Add(isc_spb_sec_userid).AsInteger := FUserID;
1985        if (ModifyGroupId in FModifyParams) then
1986 <        ServiceStartAddParam (FGroupID, isc_spb_sec_groupid);
1986 >        SRB.Add(isc_spb_sec_groupid).AsInteger := FGroupID;
1987        if (ModifyPassword in FModifyParams) then
1988 <        ServiceStartAddParam (FPassword, isc_spb_sec_password);
1988 >        SRB.Add(isc_spb_sec_password).AsString := FPassword;
1989        if (ModifyFirstName in FModifyParams) then
1990 <        ServiceStartAddParam (FFirstName, isc_spb_sec_firstname);
1990 >        SRB.Add(isc_spb_sec_firstname).AsString := FFirstName;
1991        if (ModifyMiddleName in FModifyParams) then
1992 <        ServiceStartAddParam (FMiddleName, isc_spb_sec_middlename);
1992 >        SRB.Add(isc_spb_sec_middlename).AsString := FMiddleName;
1993        if (ModifyLastName in FModifyParams) then
1994 <        ServiceStartAddParam (FLastName, isc_spb_sec_lastname);
1994 >        SRB.Add(isc_spb_sec_lastname).AsString := FLastName;
1995      end;
1996    end;
1997    ClearParams;
1998   end;
1999  
2000   { TIBUnStructuredService }
2001 < constructor TIBControlAndQueryService.Create(AOwner: TComponent);
2001 > constructor TIBControlAndQueryService.create(AOwner: TComponent);
2002   begin
2003    inherited Create(AOwner);
2004    FEof := False;
# Line 2012 | Line 2014 | end;
2014  
2015   function TIBControlAndQueryService.GetNextChunk: String;
2016   var
2017 <  Length: Integer;
2017 >  i: Integer;
2018   begin
2019    if (FEof = True) then
2020    begin
# Line 2021 | Line 2023 | begin
2023    end;
2024    if (FAction = 0) then
2025      IBError(ibxeQueryParamsError, [nil]);
2026 <  ServiceQueryParams := Char(isc_info_svc_to_eof);
2026 >
2027 >  SRB.Add(isc_info_svc_to_eof);
2028    InternalServiceQuery;
2029 <  if (OutputBuffer[0] <> Char(isc_info_svc_to_eof)) then
2030 <    IBError(ibxeOutputParsingError, [nil]);
2031 <  Length := isc_vax_integer(OutputBuffer + 1, 2);
2032 <  if (OutputBuffer[3 + Length] = Char(isc_info_truncated)) then
2033 <    FEof := False
2034 <  else
2035 <    if (OutputBuffer[3 + Length] = Char(isc_info_end)) then
2036 <      FEof := True
2029 >
2030 >  FEof := True;
2031 >  for i := 0 to FServiceQueryResults.Count - 1 do
2032 >  with FServiceQueryResults[i] do
2033 >  begin
2034 >    case getItemType of
2035 >      isc_info_svc_to_eof:
2036 >        Result := AsString;
2037 >
2038 >      isc_info_truncated:
2039 >        FEof := False;
2040 >    else
2041 >      IBError(ibxeOutputParsingError, [getItemType]);
2042 >    end;
2043 >  end;
2044 > end;
2045 >
2046 > function TIBControlAndQueryService.WriteNextChunk(stream: TStream): integer;
2047 > var
2048 >  i: Integer;
2049 > begin
2050 >  result := 0;
2051 >  if (FEof = True) then
2052 >    exit;
2053 >  if (FAction = 0) then
2054 >    IBError(ibxeQueryParamsError, [nil]);
2055 >
2056 >  SQPB.Add(isc_info_svc_timeout).AsInteger := 1;
2057 >  SRB.Add(isc_info_svc_to_eof);
2058 >  InternalServiceQuery;
2059 >
2060 >  FEof := True;
2061 >  for i := 0 to FServiceQueryResults.Count - 1 do
2062 >  with FServiceQueryResults[i] do
2063 >  begin
2064 >    case getItemType of
2065 >      isc_info_svc_to_eof:
2066 >      begin
2067 >        Result := CopyTo(stream,0);
2068 >        FEof := Result = 0;
2069 >      end;
2070 >
2071 >      isc_info_truncated:
2072 >        FEof := False;
2073 >
2074 >      isc_info_svc_timeout:
2075 >        {ignore};
2076      else
2077 <      IBError(ibxeOutputParsingError, [nil]);
2078 <  OutputBuffer[3 + Length] := #0;
2079 <  result := String(PChar(@OutputBuffer[3]));
2077 >      IBError(ibxeOutputParsingError, [getItemType]);
2078 >    end;
2079 >  end;
2080   end;
2081  
2082   function TIBControlAndQueryService.GetNextLine: String;
2083   var
2084 <  Length: Integer;
2084 >  i: Integer;
2085   begin
2086 +  Result := '';
2087    if (FEof = True) then
2045  begin
2046    result := '';
2088      exit;
2089 <  end;
2089 >
2090    if (FAction = 0) then
2091      IBError(ibxeQueryParamsError, [nil]);
2092 <  ServiceQueryParams := Char(isc_info_svc_line);
2092 >
2093 >  SRB.Add(isc_info_svc_line);
2094    InternalServiceQuery;
2095 <  if (OutputBuffer[0] <> Char(isc_info_svc_line)) then
2096 <    IBError(ibxeOutputParsingError, [nil]);
2097 <  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
2095 >
2096 >  for i := 0 to FServiceQueryResults.Count - 1 do
2097 >  with FServiceQueryResults[i] do
2098    begin
2099 <    result := '';
2100 <    FEof := True;
2101 <    exit;
2099 >    case getItemType of
2100 >      isc_info_svc_line:
2101 >         Result := AsString;
2102 >    else
2103 >      IBError(ibxeOutputParsingError, [getItemType]);
2104 >    end;
2105    end;
2106 <  OutputBuffer[3 + Length] := #0;
2067 <  result := String(PChar(@OutputBuffer[3]));
2106 >  FEOF := Result = '';
2107   end;
2108  
2109   { TIBLogService }
# Line 2072 | Line 2111 | end;
2111   procedure TIBLogService.SetServiceStartOptions;
2112   begin
2113    Action := isc_action_svc_get_ib_log;
2114 <  ServiceStartParams  := Char(isc_action_svc_get_ib_log);
2114 >  SRB.Add(isc_action_svc_get_ib_log);
2115   end;
2116  
2117   { TDatabaseInfo }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines