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 5 by tony, Fri Feb 18 16:26:16 2011 UTC vs.
Revision 80 by tony, Mon Jan 1 11:31:07 2018 UTC

# Line 24 | Line 24
24   {       Corporation. All Rights Reserved.                                }
25   {    Contributor(s): Jeff Overcash                                       }
26   {                                                                        }
27 + {    IBX For Lazarus (Firebird Express)                                  }
28 + {    Contributor: Tony Whyman, MWA Software http://www.mwasoftware.co.uk }
29 + {    Portions created by MWA Software are copyright McCallum Whyman      }
30 + {    Associates Ltd 2011                                                 }
31 + {                                                                        }
32   {************************************************************************}
33  
34   {
35    InterBase Express provides component interfaces to
36    functions introduced in InterBase 6.0.  The Services
37 <  components (TIB*Service, TIBServerProperties) and
33 <  Install components (TIBInstall, TIBUninstall, TIBSetup)
37 >  components (TIB*Service, TIBServerProperties)
38    function only if you have installed InterBase 6.0 or
39 <  later software
39 >  later software, including Firebird
40   }
41  
42   unit IBServices;
43  
44   {$Mode Delphi}
45 + {$codepage UTF8}
46  
47   interface
48  
49   uses
50 < {$IFDEF LINUX }
46 <  unix,
47 < {$ELSE}
48 < {$DEFINE HAS_SQLMONITOR}
50 > {$IFDEF WINDOWS }
51    Windows,
52 + {$ELSE}
53 +  unix,
54   {$ENDIF}
55 <  Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
52 <  IBDialogs, IBHeader, IB, IBExternals;
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 71 | 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
89  TProtocol = (TCP, SPX, NamedPipe, Local);
93    TOutputBufferOption = (ByLine, ByChunk);
94  
95    TIBCustomService = class;
# Line 94 | Line 97 | type
97    TLoginEvent = procedure(Database: TIBCustomService;
98      LoginParams: TStrings) of object;
99  
100 +  { TIBCustomService }
101 +
102    TIBCustomService = class(TComponent)
103    private
99    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;
106    FBufferSize: Integer;
107    FOutputBuffer: PChar;
108    FQueryParams: String;
111      FServerName: string;
112 <    FHandle: TISC_SVC_HANDLE;
112 >    FService: IServiceManager;
113      FStreamedActive  : Boolean;
114      FOnAttach: TNotifyEvent;
113    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);
119    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;
130 <    function ParseString(var RunLen: Integer): string;
131 <    function ParseInteger(var RunLen: Integer): Integer;
132 <    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 <    property OutputBuffer : PChar read FOutputBuffer;
140 <    property OutputBufferOption : TOutputBufferOption read FOutputBufferOption write FOutputBufferOption;
141 <    property BufferSize : Integer read FBufferSize write SetBufferSize default DefaultBufferSize;
141 >    procedure HandleException(Sender: TObject);
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 223 | Line 231 | type
231      FLicenseMaskInfo: TLicenseMaskInfo;
232      FVersionInfo: TVersionInfo;
233      FConfigParams: TConfigParams;
226    procedure ParseConfigFileData(var RunLen: Integer);
234    public
235      constructor Create(AOwner: TComponent); override;
236      destructor Destroy; override;
# Line 242 | Line 249 | type
249      property Options : TPropertyOptions read FOptions write FOptions;
250    end;
251  
252 +  { TIBControlService }
253 +
254    TIBControlService = class (TIBCustomService)
255    private
247    FStartParams: String;
248    FStartSPB: PChar;
249    FStartSPBLength: Integer;
256      function GetIsServiceRunning: Boolean;
257    protected
258 <    property ServiceStartParams: String read FStartParams write FStartParams;
253 <    procedure SetServiceStartOptions; virtual;
254 <    procedure ServiceStartAddParam (Value: string; param: Integer); overload;
255 <    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 261 | 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 272 | 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;
276  published
277    property BufferSize;
283    end;
284  
285    TShutdownMode = (Forced, DenyTransaction, DenyAttachment);
# Line 309 | 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 325 | 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 364 | 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 371 | 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 378 | 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 508 | Line 525 | type
525   implementation
526  
527   uses
528 <  IBIntf {$IFDEF HAS_SQLMONITOR}, IBSQLMonitor {$ENDIF};
528 >  IBSQLMonitor, Math, 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
517 <  SPB: String;
518 <  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);
531 <    IBAlloc(FSPB, 0, FsPBLength);
532 <    Move(SPB[1], FSPB[0], FSPBLength);
533 <  end;
534 <  case FProtocol of
535 <    TCP: ConnectString := FServerName + ':service_mgr'; {do not localize}
536 <    SPX: ConnectString := FServerName + '@service_mgr'; {do not localize}
537 <    NamedPipe: ConnectString := '\\' + FServerName + '\service_mgr'; {do not localize}
538 <    Local: ConnectString := 'service_mgr'; {do not localize}
539 <  end;
540 <  if call(isc_service_attach(StatusVector, Length(ConnectString),
541 <                         PChar(ConnectString), @FHandle,
542 <                         FSPBLength, FSPB), False) > 0 then
543 <  begin
544 <    FHandle := nil;
545 <    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  
551  {$IFDEF HAS_SQLMONITOR}
563    MonitorHook.ServiceAttach(Self);
553  {$ENDIF}
564   end;
565  
566   procedure TIBCustomService.Loaded;
# Line 561 | Line 571 | begin
571        Attach;
572    except
573      if csDesigning in ComponentState then
574 <      Application.HandleException(Self)
574 >       HandleException(self)
575      else
576        raise;
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 580 | 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;
597    end
598 <  else begin
599 <    IndexOfUser := IndexOfSPBConst(SPBConstantNames[isc_spb_user_name]);
598 >  else
599 >  if assigned(IBGUIInterface)  then
600 >  begin
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 := 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;
625 >    end
626 >  end
627 >  else
628 >    IBError(ibxeNoLoginDialog,[]);
629   end;
630  
631   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  
645 + procedure TIBCustomService.HandleException(Sender: TObject);
646 + var aParent: TComponent;
647 + begin
648 +  aParent := Owner;
649 +  while aParent <> nil do
650 +  begin
651 +    if aParent is TCustomApplication then
652 +    begin
653 +      TCustomApplication(aParent).HandleException(Sender);
654 +      Exit;
655 +    end;
656 +    aParent := aParent.Owner;
657 +  end;
658 +  SysUtils.ShowException(ExceptObject,ExceptAddr);
659 + end;
660 +
661   constructor TIBCustomService.Create(AOwner: TComponent);
662   begin
663    inherited Create(AOwner);
633  FIBLoaded := False;
634  CheckIBLoaded;
635  FIBLoaded := True;
664    FserverName := '';
665    FParams := TStringList.Create;
666    FParamsChanged := True;
667    TStringList(FParams).OnChange := ParamsChange;
668    TStringList(FParams).OnChanging := ParamsChanging;
641  FSPB := nil;
642  FQuerySPB := nil;
643  FBufferSize := DefaultBufferSize;
644  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
678 >     TCustomApplication(AOwner).ConsoleApplication then
679 >    LoginPrompt := false;
680   end;
681  
682   destructor TIBCustomService.Destroy;
683   begin
684 <  if FIBLoaded then
653 <  begin
654 <    if FHandle <> nil then
684 >  if FService <> nil then
685        Detach;
686 <    FreeMem(FSPB);
687 <    FSPB := nil;
688 <    FParams.Free;
689 <  end;
660 <  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
669 <    FHandle := nil;
670 <    IBDataBaseError;
671 <  end
672 <  else
673 <    FHandle := nil;
674 <  {$IFDEF HAS_SQLMONITOR}
696 >  FService.Detach;
697 >  FService := nil;
698    MonitorHook.ServiceDetach(Self);
699 <  {$ENDIF}
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 687 | 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 704 | 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);
713 <  Move(FQueryParams[1], FQuerySPB[0], FQuerySPBLength);
714 <  if (FOutputBuffer = nil) then
715 <    IBAlloc(FOutputBuffer, 0, FBufferSize);
716 <  try
717 <    if call(isc_service_query(StatusVector, @FHandle, nil, 0, nil,
718 <                           FQuerySPBLength, FQuerySPB,
719 <                           FBufferSize, FOutputBuffer), False) > 0 then
720 <    begin
721 <      FHandle := nil;
722 <      IBDataBaseError;
723 <    end;
724 <  finally
725 <    FreeMem(FQuerySPB);
726 <    FQuerySPB := nil;
727 <    FQuerySPBLength := 0;
728 <    FQueryParams := '';
729 <  end;
730 <  {$IFDEF HAS_SQLMONITOR}
768 >  CheckActive;
769 >  FServiceQueryResults := FService.Query(FSQPB,FSRB);
770 >  FSQPB := nil;
771 >  FSRB := nil;
772    MonitorHook.ServiceQuery(Self);
732  {$ENDIF}
773   end;
774  
775   procedure TIBCustomService.SetActive(const Value: Boolean);
# Line 737 | 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 775 | 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 789 | 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 811 | 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 827 | Line 891 | begin
891      IBError(ibxeServerNameMissing, [nil]);
892   end;
893  
830 function TIBCustomService.Call(ErrCode: ISC_STATUS;
831  RaiseError: Boolean): ISC_STATUS;
832 begin
833  result := ErrCode;
834  if RaiseError and (ErrCode > 0) then
835    IBDataBaseError;
836 end;
837
838 function TIBCustomService.ParseString(var RunLen: Integer): string;
839 var
840  Len: UShort;
841  tmp: Char;
842 begin
843  Len := isc_vax_integer(OutputBuffer + RunLen, 2);
844  RunLen := RunLen + 2;
845  if (Len <> 0) then
846  begin
847    tmp := OutputBuffer[RunLen + Len];
848    OutputBuffer[RunLen + Len] := #0;
849    result := String(PChar(@OutputBuffer[RunLen]));
850    OutputBuffer[RunLen + Len] := tmp;
851    RunLen := RunLen + Len;
852  end
853  else
854    result := '';
855 end;
856
857 function TIBCustomService.ParseInteger(var RunLen: Integer): Integer;
858 begin
859  result := isc_vax_integer(OutputBuffer + RunLen, 4);
860  RunLen := RunLen + 4;
861 end;
862
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
868 < *  in SPB and SPBLength, respectively.
898 > *  parameter buffer, and return it .
899   }
900 < procedure TIBCustomService.GenerateSPB(sl: TStrings; var SPB: String;
871 <  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 876 | 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);
881 <  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
913    for i := 0 to sl.Count - 1 do
914    begin
915     { Get the parameter's name and value from the list,
# Line 904 | 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
910 <        SPB := SPB +
911 <               Char(SPBServerVal) +
912 <               Char(Length(param_value)) +
913 <               param_value;
914 <        Inc(SPBLength, 2 + Length(param_value));
915 <      end;
938 >        Result.Add(SPBServerVal).AsString := param_value;
939        else
940        begin
941 <        if (SPBVal > 0) and
919 <           (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 947 | Line 969 | begin
969    inherited Destroy;
970   end;
971  
950 procedure TIBServerProperties.ParseConfigFileData(var RunLen: Integer);
951 begin
952  Inc(RunLen);
953  with FConfigParams.ConfigFileData do
954  begin
955    SetLength (ConfigFileValue, Length(ConfigFileValue)+1);
956    SetLength (ConfigFileKey, Length(ConfigFileKey)+1);
957
958    ConfigFileKey[High(ConfigFileKey)] := Integer(OutputBuffer[RunLen-1]);
959    ConfigFileValue[High(ConfigFileValue)] := ParseInteger(RunLen);
960  end;
961 end;
962
972   procedure TIBServerProperties.Fetch;
973   begin
974    if (Database in Options) then
# Line 976 | 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
1006 <        Inc (RunLen);
1007 <        FConfigParams.BaseLocation := ParseString(RunLen);
1008 <      end;
1016 >        FConfigParams.BaseLocation := AsString;
1017  
1018        isc_info_svc_get_env_lock:
1019 <      begin
1012 <        Inc (RunLen);
1013 <        FConfigParams.LockFileLocation := ParseString(RunLen);
1014 <      end;
1019 >        FConfigParams.LockFileLocation := AsString;
1020  
1021        isc_info_svc_get_env_msg:
1022 <      begin
1018 <        Inc (RunLen);
1019 <        FConfigParams.MessageFileLocation := ParseString(RunLen);
1020 <      end;
1022 >        FConfigParams.MessageFileLocation := AsString;
1023  
1024        isc_info_svc_user_dbpath:
1025 <      begin
1026 <        Inc (RunLen);
1025 <        FConfigParams.SecurityDatabaseLocation := ParseString(RunLen);
1026 <      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;
1066 <  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);
1080 <    Inc(RunLen);
1081 <    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:
1083      begin
1084        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;
1092          if (OutputBuffer[RunLen] <> Char(isc_spb_lic_id)) then
1093              IBError(ibxeOutputParsingError, [nil]);
1094          Inc(RunLen);
1095          FLicenseInfo.id[i] := ParseString(RunLen);
1096          if (OutputBuffer[RunLen] <> Char(isc_spb_lic_key)) then
1097              IBError(ibxeOutputParsingError, [nil]);
1098          Inc(RunLen);
1099          FLicenseInfo.key[i] := ParseString(RunLen);
1100          if (OutputBuffer[RunLen] <> Char(7)) then
1101              IBError(ibxeOutputParsingError, [nil]);
1102          Inc(RunLen);
1103          FLicenseInfo.desc[i] := ParseString(RunLen);
1104          Inc(i);
1105        end;
1106        Inc(RunLen);
1107        if (Length(FLicenseInfo.key) > i) then
1108        begin
1109          SetLength(FLicenseInfo.key, i);
1110          SetLength(FLicenseInfo.id, i);
1111          SetLength(FLicenseInfo.desc, i);
1105          end;
1113      end;
1114      isc_info_svc_get_licensed_users:
1115        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);
1134 <    Inc(RunLen);
1135 <    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 1146 | Line 1134 | end;
1134  
1135   procedure TIBServerProperties.FetchVersionInfo;
1136   var
1137 <  RunLen: Integer;
1150 <  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;
1156  RunLen := 0;
1157  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);
1162 <    Inc(RunLen);
1163 <    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;
1183 var
1184  RunLen: Integer;
1168   begin
1169 <  ServiceQueryParams := Char(isc_info_svc_running);
1169 >  SRB.Add(isc_info_svc_running);
1170    InternalServiceQuery;
1188  if (OutputBuffer[0] <> Char(isc_info_svc_running)) then
1189    IBError(ibxeOutputParsingError, [nil]);
1190  RunLen := 1;
1191  if (ParseInteger(RunLen) = 1) then
1192    result := True
1193  else
1194    result := False;
1195 end;
1171  
1172 < procedure TIBControlService.ServiceStartAddParam (Value: string; param: Integer);
1173 < var
1174 <  Len: UShort;
1200 < begin
1201 <  Len := Length(Value);
1202 <  if Len > 0 then
1203 <  begin
1204 <    FStartParams  := FStartParams +
1205 <                     Char(Param) +
1206 <                     PChar(@Len)[0] +
1207 <                     PChar(@Len)[1] +
1208 <                     Value;
1209 <  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) +
1216 <                   PChar(@Value)[0] +
1217 <                   PChar(@Value)[1] +
1218 <                   PChar(@Value)[2] +
1219 <                   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;
1227 <  FStartSPBLength := 0;
1186 >  FSRB := nil;
1187 >  FSPB := nil;
1188   end;
1189  
1190   procedure TIBControlService.InternalServiceStart;
1191   begin
1192 <  FStartSPBLength := Length(FStartParams);
1233 <  if FStartSPBLength = 0 then
1192 >  if SRB = nil then
1193      IBError(ibxeStartParamsError, [nil]);
1194 <  IBAlloc(FStartSPB, 0, FStartSPBLength);
1236 <  Move(FStartParams[1], FStartSPB[0], FstartSPBLength);
1194 >
1195    try
1196 <    if call(isc_service_start(StatusVector, @FHandle, nil,
1239 <                           FStartSPBLength, FStartSPB), False) > 0 then
1240 <    begin
1241 <      FHandle := nil;
1242 <      IBDataBaseError;
1243 <    end;
1196 >    FService.Start(SRB);
1197    finally
1198 <    FreeMem(FStartSPB);
1246 <    FStartSPB := nil;
1247 <    FStartSPBLength := 0;
1248 <    FStartParams := '';
1198 >    FSRB := nil;
1199    end;
1250  {$IFDEF HAS_SQLMONITOR}
1200    MonitorHook.ServiceStart(Self);
1252  {$ENDIF}
1201   end;
1202  
1203   procedure TIBControlService.ServiceStart;
1204   begin
1205    CheckActive;
1206 +  CheckServiceNotRunning;
1207    SetServiceStartOptions;
1208    InternalServiceStart;
1209   end;
# Line 1268 | 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 +
1290 <                        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 +
1293 <                           Char(isc_spb_prp_wm_async)
1240 >    AsByte := isc_spb_prp_wm_async
1241    else
1242 <    ServiceStartParams  := ServiceStartParams +
1296 <                           Char(isc_spb_prp_wm_sync);
1242 >    AsByte := isc_spb_prp_wm_sync;
1243    InternalServiceStart;
1244   end;
1245  
# Line 1304 | 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 +
1318 <                         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 +
1321 <                           Char(isc_spb_prp_am_readonly)
1265 >    AsByte := isc_spb_prp_am_readonly
1266    else
1267 <    ServiceStartParams  := ServiceStartParams +
1324 <                           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 +
1333 <                        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 +
1336 <                           Char(isc_spb_prp_res)
1277 >    AsByte := isc_spb_prp_res
1278    else
1279 <    ServiceStartParams  := ServiceStartParams +
1339 <                           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 1378 | Line 1319 | begin
1319   end;
1320  
1321   procedure TIBStatisticalService.SetServiceStartOptions;
1322 < var
1382 <  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 1395 | 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 1424 | 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);
1443 <      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 1487 | 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(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);
1505 <      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);
1518 <      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 1537 | 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 1564 | 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;
1566 >  i,j, k: Integer;
1567    Value: Char;
1568   begin
1571  ServiceQueryParams := Char(isc_info_svc_limbo_trans);
1572  InternalServiceQuery;
1573  RunLen := 0;
1574  if (OutputBuffer[RunLen] <> Char(isc_info_svc_limbo_trans)) then
1575    IBError(ibxeOutputParsingError, [nil]);
1576  Inc(RunLen, 3);
1569    for i := 0 to High(FLimboTransactionInfo) do
1570      FLimboTransactionInfo[i].Free;
1571 <  FLimboTransactionInfo := nil;
1572 <  i := 0;
1573 <  while (OutputBuffer[RunLen] <> Char(isc_info_end)) do
1574 <  begin
1575 <    if (i >= Length(FLimboTransactionInfo)) then
1576 <      SetLength(FLimboTransactionInfo, i + 10);
1577 <    if FLimboTransactionInfo[i] = nil then
1578 <      FLimboTransactionInfo[i] := TLimboTransactionInfo.Create;
1579 <    with FLimboTransactionInfo[i] do
1571 >  SetLength(FLimboTransactionInfo,0);
1572 >
1573 >  SRB.Add(isc_info_svc_limbo_trans);
1574 >  InternalServiceQuery;
1575 >
1576 >  k := -1;
1577 >  for i := 0 to FServiceQueryResults.Count - 1 do
1578 >  with FServiceQueryResults[i] do
1579 >  case getItemType of
1580 >  isc_info_svc_limbo_trans:
1581      begin
1582 <      if (OutputBuffer[RunLen] = Char(isc_spb_single_tra_id)) then
1582 >      if FServiceQueryResults[i].Count = 0 then continue;
1583 >      NextLimboTransaction(0);
1584 >      for j := 0 to FServiceQueryResults[i].Count - 1 do
1585        begin
1586 <        Inc(RunLen);
1592 <        MultiDatabase := False;
1593 <        ID := ParseInteger(RunLen);
1594 <      end
1595 <      else
1596 <      begin
1597 <        Inc(RunLen);
1598 <        MultiDatabase := True;
1599 <        ID := ParseInteger(RunLen);
1600 <        HostSite := ParseString(RunLen);
1601 <        if (OutputBuffer[RunLen] <> Char(isc_spb_tra_state)) then
1602 <          IBError(ibxeOutputParsingError, [nil]);
1603 <        Inc(RunLen);
1604 <        Value := OutputBuffer[RunLen];
1605 <        Inc(RunLen);
1606 <        if (Value = Char(isc_spb_tra_state_limbo)) then
1607 <          State := LimboState
1608 <        else
1609 <          if (Value = Char(isc_spb_tra_state_commit)) then
1610 <            State := CommitState
1611 <          else
1612 <            if (Value = Char(isc_spb_tra_state_rollback)) then
1613 <              State := RollbackState
1614 <            else
1615 <              State := UnknownState;
1616 <        RemoteSite := ParseString(RunLen);
1617 <        RemoteDatabasePath := ParseString(RunLen);
1618 <        Value := OutputBuffer[RunLen];
1619 <        Inc(RunLen);
1620 <        if (Value = Char(isc_spb_tra_advise_commit)) then
1586 >        with FServiceQueryResults[i][j] do
1587          begin
1588 <          Advise := CommitAdvise;
1589 <          Action:= CommitAction;
1590 <        end
1591 <        else
1592 <          if (Value = Char(isc_spb_tra_advise_rollback)) then
1593 <          begin
1594 <            Advise := RollbackAdvise;
1595 <            Action := RollbackAction;
1596 <          end
1597 <          else
1598 <          begin
1599 <            { if no advice commit as default }
1600 <            Advise := UnknownAdvise;
1601 <            Action:= CommitAction;
1588 >          case getItemType of
1589 >            isc_spb_single_tra_id:
1590 >            begin
1591 >              Inc(k);
1592 >              if k > 0 then
1593 >                NextLimboTransaction(k);
1594 >              FLimboTransactionInfo[k].MultiDatabase := False;
1595 >              FLimboTransactionInfo[k].ID := AsInteger;
1596 >            end;
1597 >
1598 >            isc_spb_multi_tra_id:
1599 >            begin
1600 >              Inc(k);
1601 >              if k > 0 then
1602 >                NextLimboTransaction(k);
1603 >              FLimboTransactionInfo[k].MultiDatabase := True;
1604 >              FLimboTransactionInfo[k].ID := AsInteger;
1605 >            end;
1606 >
1607 >            isc_spb_tra_host_site:
1608 >              FLimboTransactionInfo[k].HostSite := AsString;
1609 >
1610 >            isc_spb_tra_state:
1611 >              case AsByte of
1612 >                isc_spb_tra_state_limbo:
1613 >                  FLimboTransactionInfo[k].State := LimboState;
1614 >
1615 >                isc_spb_tra_state_commit:
1616 >                  FLimboTransactionInfo[k].State := CommitState;
1617 >
1618 >                isc_spb_tra_state_rollback:
1619 >                  FLimboTransactionInfo[k].State := RollbackState;
1620 >
1621 >                else
1622 >                  FLimboTransactionInfo[k].State := UnknownState;
1623 >              end;
1624 >
1625 >            isc_spb_tra_remote_site:
1626 >              FLimboTransactionInfo[k].RemoteSite := AsString;
1627 >
1628 >            isc_spb_tra_db_path:
1629 >              FLimboTransactionInfo[k].RemoteDatabasePath := AsString;
1630 >
1631 >            isc_spb_tra_advise:
1632 >            with FLimboTransactionInfo[k] do
1633 >            begin
1634 >              case (AsByte) of
1635 >              isc_spb_tra_advise_commit:
1636 >              begin
1637 >                Advise := CommitAdvise;
1638 >                Action:= CommitAction;
1639 >              end;
1640 >
1641 >              isc_spb_tra_advise_rollback:
1642 >              begin
1643 >                Advise := RollbackAdvise;
1644 >                Action := RollbackAction;
1645 >              end;
1646 >
1647 >              else
1648 >                Advise := UnknownAdvise;
1649 >              end;
1650 >            end;
1651 >
1652 >            else
1653 >              IBError(ibxeOutputParsingError, [getItemType]);
1654            end;
1655 +        end;
1656        end;
1638      Inc (i);
1657      end;
1658 +  else
1659 +    IBError(ibxeOutputParsingError, [getItemType]);
1660    end;
1641  if (i > 0) then
1642    SetLength(FLimboTransactionInfo, i+1);
1661   end;
1662  
1663   procedure TIBValidationService.FixLimboTransactionErrors;
1664   var
1665    i: Integer;
1666   begin
1667 <  ServiceStartParams  := Char(isc_action_svc_repair);
1668 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1669 <  if (FGlobalAction = NoGlobalAction) then
1670 <  begin
1653 <    i := 0;
1654 <    while (FLimboTransactionInfo[i].ID <> 0) do
1667 >  SRB.Add(isc_action_svc_repair);
1668 >  SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
1669 >  case FGlobalAction of
1670 >  NoGlobalAction:
1671      begin
1672 <      if (FLimboTransactionInfo[i].Action = CommitAction) then
1657 <        ServiceStartAddParam (FLimboTransactionInfo[i].ID, isc_spb_rpr_commit_trans)
1658 <      else
1659 <        ServiceStartAddParam (FLimboTransactionInfo[i].ID, isc_spb_rpr_rollback_trans);                              
1660 <      Inc(i);
1661 <    end;
1662 <  end
1663 <  else
1664 <  begin
1665 <    i := 0;
1666 <    if (FGlobalAction = CommitGlobal) then
1667 <      while (FLimboTransactionInfo[i].ID <> 0) do
1672 >      for i := 0 to LimboTransactionInfoCount - 1 do
1673        begin
1674 <        ServiceStartAddParam (FLimboTransactionInfo[i].ID, isc_spb_rpr_commit_trans);
1675 <        Inc(i);
1676 <      end
1677 <    else
1678 <      while (FLimboTransactionInfo[i].ID <> 0) do
1674 >        if (FLimboTransactionInfo[i].Action = CommitAction) then
1675 >          SRB.Add(isc_spb_rpr_commit_trans).AsInteger :=  FLimboTransactionInfo[i].ID
1676 >        else
1677 >          SRB.Add(isc_spb_rpr_rollback_trans).AsInteger :=  FLimboTransactionInfo[i].ID;
1678 >      end;
1679 >    end;
1680 >
1681 >  CommitGlobal:
1682 >    begin
1683 >      for i := 0 to LimboTransactionInfoCount - 1 do
1684 >        SRB.Add(isc_spb_rpr_commit_trans).AsInteger :=  FLimboTransactionInfo[i].ID;
1685 >    end;
1686 >
1687 >    RollbackGlobal:
1688        begin
1689 <        ServiceStartAddParam (FLimboTransactionInfo[i].ID, isc_spb_rpr_rollback_trans);
1690 <        Inc(i);
1689 >        for i := 0 to LimboTransactionInfoCount - 1 do
1690 >          SRB.Add(isc_spb_rpr_rollback_trans).AsInteger :=  FLimboTransactionInfo[i].ID;
1691        end;
1692 +
1693 +    RecoverTwoPhaseGlobal:
1694 +    begin
1695 +      for i := 0 to LimboTransactionInfoCount - 1 do
1696 +        SRB.Add(isc_spb_rpr_recover_two_phase).AsInteger :=  FLimboTransactionInfo[i].ID;
1697 +    end;
1698    end;
1699    InternalServiceStart;
1700   end;
# Line 1689 | Line 1709 | end;
1709  
1710   function TIBValidationService.GetLimboTransactionInfoCount: integer;
1711   begin
1712 <  Result := High(FLimboTransactionInfo);
1712 >  Result := Length(FLimboTransactionInfo);
1713   end;
1714  
1715   procedure TIBValidationService.SetDatabaseName(const Value: string);
# Line 1704 | Line 1724 | begin
1724    Action := isc_action_svc_repair;
1725    if FDatabaseName = '' then
1726      IBError(ibxeStartParamsError, [nil]);
1727 +  SRB.Add(isc_action_svc_repair);
1728 +  SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
1729    param := 0;
1730    if (SweepDB in Options) then
1731      param := param or isc_spb_rpr_sweep_db;
1732    if (ValidateDB in Options) then
1733      param := param or isc_spb_rpr_validate_db;
1734 <  ServiceStartParams  := Char(isc_action_svc_repair);
1713 <  ServiceStartAddParam (FDatabaseName, SPBConstantValues[isc_spb_dbname]);
1714 <  if param > 0 then
1715 <    ServiceStartAddParam (param, SPBConstantValues[isc_spb_options]);
1716 <  param := 0;
1734 >
1735    if (LimboTransactions in Options) then
1736      param := param or isc_spb_rpr_list_limbo_trans;
1737    if (CheckDB in Options) then
# Line 1731 | Line 1749 | begin
1749         param := param or isc_spb_rpr_validate_db;
1750    end;
1751    if param > 0 then
1752 <    ServiceStartAddParam (param, SPBConstantValues[isc_spb_options]);
1752 >   SRB.Add(isc_spb_options).AsInteger := param;
1753   end;
1754  
1755   { TIBSecurityService }
# Line 1753 | Line 1771 | end;
1771  
1772   procedure TIBSecurityService.FetchUserInfo;
1773   var
1774 <  i, RunLen: Integer;
1774 >  i, j, k: Integer;
1775   begin
1776 <  ServiceQueryParams := Char(isc_info_svc_get_users);
1776 >  SRB.Add(isc_info_svc_get_users);
1777    InternalServiceQuery;
1778 <  RunLen := 0;
1761 <  if (OutputBuffer[RunLen] <> Char(isc_info_svc_get_users)) then
1762 <    IBError(ibxeOutputParsingError, [nil]);
1763 <  Inc(RunLen);
1778 >
1779    for i := 0 to High(FUserInfo) do
1780      FUserInfo[i].Free;
1781 <  FUserInfo := nil;
1782 <  i := 0;
1783 <  { Don't have any use for the combined length
1784 <   so increment past by 2 }
1785 <  Inc(RunLen, 2);
1786 <  while (OutputBuffer[RunLen] <> Char(isc_info_end)) do
1787 <  begin
1788 <    if (i >= Length(FUSerInfo)) then
1789 <      SetLength(FUserInfo, i + 10);
1790 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_username)) then
1791 <      IBError(ibxeOutputParsingError, [nil]);
1792 <    Inc(RunLen);
1793 <    if FUserInfo[i] = nil then
1794 <      FUserInfo[i] := TUserInfo.Create;
1795 <    FUserInfo[i].UserName := ParseString(RunLen);
1796 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_firstname)) then
1797 <      IBError(ibxeOutputParsingError, [nil]);
1798 <    Inc(RunLen);
1799 <    FUserInfo[i].FirstName := ParseString(RunLen);
1800 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_middlename)) then
1801 <      IBError(ibxeOutputParsingError, [nil]);
1802 <    Inc(RunLen);
1803 <    FUserInfo[i].MiddleName := ParseString(RunLen);
1804 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_lastname)) then
1805 <      IBError(ibxeOutputParsingError, [nil]);
1806 <    Inc(RunLen);
1807 <    FUserInfo[i].LastName := ParseString(RunLen);
1808 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_userId)) then
1809 <      IBError(ibxeOutputParsingError, [nil]);
1810 <    Inc(RunLen);
1811 <    FUserInfo[i].UserId := ParseInteger(RunLen);
1812 <    if (OutputBuffer[RunLen] <> Char(isc_spb_sec_groupid)) then
1813 <      IBError(ibxeOutputParsingError, [nil]);
1814 <    Inc(RunLen);
1815 <    FUserInfo[i].GroupID := ParseInteger(RunLen);
1816 <    Inc (i);
1781 >  for i := 0 to FServiceQueryResults.Count - 1 do
1782 >  with FServiceQueryResults[i] do
1783 >  begin
1784 >    case getItemType of
1785 >    isc_info_svc_get_users:
1786 >      begin
1787 >        SetLength(FUserInfo,1);
1788 >        k := 0;
1789 >        FUserInfo[0] := TUserInfo.Create;
1790 >        FUserInfo[0].UserName := '';
1791 >        for j := 0 to FServiceQueryResults[i].Count - 1 do
1792 >        begin
1793 >          with FServiceQueryResults[i][j] do
1794 >          case getItemType of
1795 >          isc_spb_sec_username:
1796 >            begin
1797 >              if FUserInfo[k].UserName <> '' then
1798 >              begin
1799 >                Inc(k);
1800 >                SetLength(FUserInfo,k+1);
1801 >                if FUserInfo[k] = nil then
1802 >                  FUserInfo[k] := TUserInfo.Create;
1803 >              end;
1804 >              FUserInfo[k].UserName := AsString;
1805 >            end;
1806 >
1807 >          isc_spb_sec_firstname:
1808 >            FUserInfo[k].FirstName := AsString;
1809 >
1810 >          isc_spb_sec_middlename:
1811 >            FUserInfo[k].MiddleName := AsString;
1812 >
1813 >          isc_spb_sec_lastname:
1814 >            FUserInfo[k].LastName := AsString;
1815 >
1816 >          isc_spb_sec_userId:
1817 >            FUserInfo[k].UserId := AsInteger;
1818 >
1819 >          isc_spb_sec_groupid:
1820 >            FUserInfo[k].GroupID := AsInteger;
1821 >
1822 >          else
1823 >            IBError(ibxeOutputParsingError, [getItemType]);
1824 >          end;
1825 >        end;
1826 >      end;
1827 >    else
1828 >      IBError(ibxeOutputParsingError, [getItemType]);
1829 >    end;
1830    end;
1803  if (i > 0) then
1804    SetLength(FUserInfo, i+1);
1831   end;
1832  
1833   function TIBSecurityService.GetUserInfo(Index: Integer): TUserInfo;
# Line 1814 | Line 1840 | end;
1840  
1841   function TIBSecurityService.GetUserInfoCount: Integer;
1842   begin
1843 <  Result := High(FUSerInfo);
1843 >  Result := Length(FUserInfo);
1844   end;
1845  
1846   procedure TIBSecurityService.AddUser;
# Line 1832 | Line 1858 | end;
1858   procedure TIBSecurityService.DisplayUsers;
1859   begin
1860    SecurityAction := ActionDisplayUser;
1861 <  ServiceStartParams  := Char(isc_action_svc_display_user);
1861 >  SRB.Add(isc_action_svc_display_user);
1862    InternalServiceStart;
1863    FetchUserInfo;
1864   end;
# Line 1840 | Line 1866 | end;
1866   procedure TIBSecurityService.DisplayUser(UserName: String);
1867   begin
1868    SecurityAction := ActionDisplayUser;
1869 <  ServiceStartParams  := Char(isc_action_svc_display_user);
1870 <  ServiceStartAddParam (UserName, isc_spb_sec_username);
1869 >  SRB.Add(isc_action_svc_display_user);
1870 >  SRB.Add(isc_spb_sec_username).AsString := UserName;
1871    InternalServiceStart;
1872    FetchUserInfo;
1873   end;
# Line 1926 | Line 1952 | begin
1952        Len := Length(FUserName);
1953        if (Len = 0) then
1954          IBError(ibxeStartParamsError, [nil]);
1955 <      ServiceStartParams  := Char(isc_action_svc_add_user);
1956 <      ServiceStartAddParam (FSQLRole, SPBConstantValues[isc_spb_sql_role_name]);
1957 <      ServiceStartAddParam (FUserName, isc_spb_sec_username);
1958 <      ServiceStartAddParam (FUserID, isc_spb_sec_userid);
1959 <      ServiceStartAddParam (FGroupID, isc_spb_sec_groupid);
1960 <      ServiceStartAddParam (FPassword, isc_spb_sec_password);
1961 <      ServiceStartAddParam (FFirstName, isc_spb_sec_firstname);
1962 <      ServiceStartAddParam (FMiddleName, isc_spb_sec_middlename);
1963 <      ServiceStartAddParam (FLastName, isc_spb_sec_lastname);
1955 >      SRB.Add(isc_action_svc_add_user);
1956 >      SRB.Add(isc_spb_sec_username).AsString := FUserName;
1957 >      SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1958 >      SRB.Add(isc_spb_sec_userid).AsInteger := FUserID;
1959 >      SRB.Add(isc_spb_sec_groupid).AsInteger := FGroupID;
1960 >      SRB.Add(isc_spb_sec_password).AsString := FPassword;
1961 >      SRB.Add(isc_spb_sec_firstname).AsString := FFirstName;
1962 >      SRB.Add(isc_spb_sec_middlename).AsString := FMiddleName;
1963 >      SRB.Add(isc_spb_sec_lastname).AsString := FLastName;
1964      end;
1965      ActionDeleteUser:
1966      begin
# Line 1942 | Line 1968 | begin
1968        Len := Length(FUserName);
1969        if (Len = 0) then
1970          IBError(ibxeStartParamsError, [nil]);
1971 <      ServiceStartParams  := Char(isc_action_svc_delete_user);
1972 <      ServiceStartAddParam (FSQLRole, SPBConstantValues[isc_spb_sql_role_name]);
1973 <      ServiceStartAddParam (FUserName, isc_spb_sec_username);
1971 >      SRB.Add(isc_action_svc_delete_user);
1972 >      SRB.Add(isc_spb_sec_username).AsString := FUserName;
1973 >      SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1974      end;
1975      ActionModifyUser:
1976      begin
# Line 1952 | Line 1978 | begin
1978        Len := Length(FUserName);
1979        if (Len = 0) then
1980          IBError(ibxeStartParamsError, [nil]);
1981 <      ServiceStartParams  := Char(isc_action_svc_modify_user);
1982 <      ServiceStartAddParam (FSQLRole, SPBConstantValues[isc_spb_sql_role_name]);
1983 <      ServiceStartAddParam (FUserName, isc_spb_sec_username);
1981 >      SRB.Add(isc_action_svc_modify_user);
1982 >      SRB.Add(isc_spb_sec_username).AsString := FUserName;
1983 >      SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1984        if (ModifyUserId in FModifyParams) then
1985 <        ServiceStartAddParam (FUserID, isc_spb_sec_userid);
1985 >        SRB.Add(isc_spb_sec_userid).AsInteger := FUserID;
1986        if (ModifyGroupId in FModifyParams) then
1987 <        ServiceStartAddParam (FGroupID, isc_spb_sec_groupid);
1987 >        SRB.Add(isc_spb_sec_groupid).AsInteger := FGroupID;
1988        if (ModifyPassword in FModifyParams) then
1989 <        ServiceStartAddParam (FPassword, isc_spb_sec_password);
1989 >        SRB.Add(isc_spb_sec_password).AsString := FPassword;
1990        if (ModifyFirstName in FModifyParams) then
1991 <        ServiceStartAddParam (FFirstName, isc_spb_sec_firstname);
1991 >        SRB.Add(isc_spb_sec_firstname).AsString := FFirstName;
1992        if (ModifyMiddleName in FModifyParams) then
1993 <        ServiceStartAddParam (FMiddleName, isc_spb_sec_middlename);
1993 >        SRB.Add(isc_spb_sec_middlename).AsString := FMiddleName;
1994        if (ModifyLastName in FModifyParams) then
1995 <        ServiceStartAddParam (FLastName, isc_spb_sec_lastname);
1995 >        SRB.Add(isc_spb_sec_lastname).AsString := FLastName;
1996      end;
1997    end;
1998    ClearParams;
1999   end;
2000  
2001   { TIBUnStructuredService }
2002 < constructor TIBControlAndQueryService.Create(AOwner: TComponent);
2002 > constructor TIBControlAndQueryService.create(AOwner: TComponent);
2003   begin
2004    inherited Create(AOwner);
2005    FEof := False;
# Line 1989 | Line 2015 | end;
2015  
2016   function TIBControlAndQueryService.GetNextChunk: String;
2017   var
2018 <  Length: Integer;
2018 >  i: Integer;
2019   begin
2020    if (FEof = True) then
2021    begin
# Line 1998 | Line 2024 | begin
2024    end;
2025    if (FAction = 0) then
2026      IBError(ibxeQueryParamsError, [nil]);
2027 <  ServiceQueryParams := Char(isc_info_svc_to_eof);
2027 >
2028 >  SRB.Add(isc_info_svc_to_eof);
2029    InternalServiceQuery;
2030 <  if (OutputBuffer[0] <> Char(isc_info_svc_to_eof)) then
2031 <    IBError(ibxeOutputParsingError, [nil]);
2032 <  Length := isc_vax_integer(OutputBuffer + 1, 2);
2033 <  if (OutputBuffer[3 + Length] = Char(isc_info_truncated)) then
2034 <    FEof := False
2035 <  else
2036 <    if (OutputBuffer[3 + Length] = Char(isc_info_end)) then
2037 <      FEof := True
2030 >
2031 >  FEof := True;
2032 >  for i := 0 to FServiceQueryResults.Count - 1 do
2033 >  with FServiceQueryResults[i] do
2034 >  begin
2035 >    case getItemType of
2036 >      isc_info_svc_to_eof:
2037 >        Result := AsString;
2038 >
2039 >      isc_info_truncated:
2040 >        FEof := False;
2041      else
2042 <      IBError(ibxeOutputParsingError, [nil]);
2043 <  OutputBuffer[3 + Length] := #0;
2044 <  result := String(PChar(@OutputBuffer[3]));
2042 >      IBError(ibxeOutputParsingError, [getItemType]);
2043 >    end;
2044 >  end;
2045   end;
2046  
2047 < function TIBControlAndQueryService.GetNextLine: String;
2047 > function TIBControlAndQueryService.WriteNextChunk(stream: TStream): integer;
2048   var
2049 <  Length: Integer;
2049 >  i: Integer;
2050   begin
2051 +  result := 0;
2052    if (FEof = True) then
2022  begin
2023    result := '';
2053      exit;
2025  end;
2054    if (FAction = 0) then
2055      IBError(ibxeQueryParamsError, [nil]);
2056 <  ServiceQueryParams := Char(isc_info_svc_line);
2056 >
2057 >  SQPB.Add(isc_info_svc_timeout).AsInteger := 1;
2058 >  SRB.Add(isc_info_svc_to_eof);
2059    InternalServiceQuery;
2060 <  if (OutputBuffer[0] <> Char(isc_info_svc_line)) then
2061 <    IBError(ibxeOutputParsingError, [nil]);
2062 <  Length := isc_vax_integer(OutputBuffer + 1, 2);
2063 <  if (OutputBuffer[3 + Length] <> Char(isc_info_end)) then
2034 <    IBError(ibxeOutputParsingError, [nil]);
2035 <  if (length <> 0) then
2036 <    FEof := False
2037 <  else
2060 >
2061 >  FEof := True;
2062 >  for i := 0 to FServiceQueryResults.Count - 1 do
2063 >  with FServiceQueryResults[i] do
2064    begin
2065 <    result := '';
2066 <    FEof := True;
2065 >    case getItemType of
2066 >      isc_info_svc_to_eof:
2067 >      begin
2068 >        Result := CopyTo(stream,0);
2069 >        FEof := Result = 0;
2070 >      end;
2071 >
2072 >      isc_info_truncated:
2073 >        FEof := False;
2074 >
2075 >      isc_info_svc_timeout:
2076 >        {ignore};
2077 >    else
2078 >      IBError(ibxeOutputParsingError, [getItemType]);
2079 >    end;
2080 >  end;
2081 > end;
2082 >
2083 > function TIBControlAndQueryService.GetNextLine: String;
2084 > var
2085 >  i: Integer;
2086 > begin
2087 >  Result := '';
2088 >  if (FEof = True) then
2089      exit;
2090 +
2091 +  if (FAction = 0) then
2092 +    IBError(ibxeQueryParamsError, [nil]);
2093 +
2094 +  SRB.Add(isc_info_svc_line);
2095 +  InternalServiceQuery;
2096 +
2097 +  for i := 0 to FServiceQueryResults.Count - 1 do
2098 +  with FServiceQueryResults[i] do
2099 +  begin
2100 +    case getItemType of
2101 +      isc_info_svc_line:
2102 +         Result := AsString;
2103 +    else
2104 +      IBError(ibxeOutputParsingError, [getItemType]);
2105 +    end;
2106    end;
2107 <  OutputBuffer[3 + Length] := #0;
2044 <  result := String(PChar(@OutputBuffer[3]));
2107 >  FEOF := Result = '';
2108   end;
2109  
2110   { TIBLogService }
# Line 2049 | Line 2112 | end;
2112   procedure TIBLogService.SetServiceStartOptions;
2113   begin
2114    Action := isc_action_svc_get_ib_log;
2115 <  ServiceStartParams  := Char(isc_action_svc_get_ib_log);
2115 >  SRB.Add(isc_action_svc_get_ib_log);
2116   end;
2117  
2118   { TDatabaseInfo }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines