ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/nongui/IBXServices.pas
Revision: 263
Committed: Thu Dec 6 15:55:01 2018 UTC (5 years, 4 months ago) by tony
Content type: text/x-pascal
File size: 91169 byte(s)
Log Message:
Release 2.3.2 committed

File Contents

# User Rev Content
1 tony 209 {************************************************************************}
2     { }
3     { Borland Delphi Visual Component Library }
4     { InterBase Express core components }
5     { }
6     { Copyright (c) 1998-2000 Inprise Corporation }
7     { }
8     { InterBase Express is based in part on the product }
9     { Free IB Components, written by Gregory H. Deatz for }
10     { Hoagland, Longo, Moran, Dunst & Doukas Company. }
11     { Free IB Components is used under license. }
12     { }
13     { The contents of this file are subject to the InterBase }
14     { Public License Version 1.0 (the "License"); you may not }
15     { use this file except in compliance with the License. You }
16     { may obtain a copy of the License at http://www.Inprise.com/IPL.html }
17     { Software distributed under the License is distributed on }
18     { an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
19     { express or implied. See the License for the specific language }
20     { governing rights and limitations under the License. }
21     { The Original Code was created by InterBase Software Corporation }
22     { and its successors. }
23     { Portions created by Inprise Corporation are Copyright (C) Inprise }
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 - 2018 }
31     { }
32     {************************************************************************}
33    
34     unit IBXServices;
35    
36     {$mode objfpc}{$H+}
37    
38     interface
39    
40     uses
41     Classes, SysUtils, DB, IB, IBDatabase, IBTypes, IBSQLMonitor, IBExternals, memds;
42    
43     type
44     TIBXCustomService = class;
45     TIBXControlService = class;
46     TIBXServicesConnection = class;
47    
48     IIBXServicesClient = interface
49     procedure OnAfterConnect(Sender: TIBXServicesConnection; aDatabaseName: string);
50     procedure OnBeforeDisconnect(Sender: TIBXServicesConnection);
51     end;
52    
53     TSecContextAction = (scRaiseError, scReconnect);
54    
55     TIBXServicesLoginEvent = procedure(Service: TIBXServicesConnection; var aServerName: string; LoginParams: TStrings) of object;
56     TIBXServicesSecContextEvent = procedure(Service: TIBXServicesConnection; var aAction: TSecContextAction) of object;
57    
58     { TIBXServicesConnection }
59    
60     TIBXServicesConnection = class(TIBXMonitoredConnection)
61     private
62     FDatabase: TIBDatabase;
63 tony 263 FFirebirdAPI: IFirebirdAPI;
64 tony 209 FConnectString: string;
65 tony 263 FFirebirdLibraryPathName: TIBFileName;
66 tony 209 FOnSecurityContextException: TIBXServicesSecContextEvent;
67     FParams: TStrings;
68     FIBXServices: array of IIBXServicesClient;
69     FOnLogin: TIBXServicesLoginEvent;
70     FService: IServiceManager;
71     FPortNo: string;
72     FServerName: string;
73     FProtocol: TProtocol;
74     FServerVersionNo: array [1..4] of integer;
75     FExpectedDB: string;
76     procedure CheckActive;
77     procedure CheckInactive;
78     procedure CheckServerName;
79     function GenerateSPB(sl: TStrings): ISPB;
80 tony 263 function GetFirebirdAPI: IFirebirdAPI;
81 tony 209 function GetServerVersionNo(index: integer): integer;
82     function GetSPBConstName(action: byte): string;
83     procedure HandleException(Sender: TObject);
84     procedure HandleSecContextException(Sender: TIBXControlService; var action: TSecContextAction);
85     function Login(var aServerName: string; LoginParams: TStrings): Boolean;
86     procedure ParamsChanging(Sender: TObject);
87     procedure SetConnectString(AValue: string);
88 tony 263 procedure SetFirebirdLibraryPathName(AValue: TIBFileName);
89 tony 209 procedure SetParams(AValue: TStrings);
90     procedure SetPortNo(AValue: string);
91     procedure SetProtocol(AValue: TProtocol);
92     procedure SetServerName(AValue: string);
93     protected
94     procedure DoConnect; override;
95     procedure DoDisconnect; override;
96     function GetConnected: Boolean; override;
97     function GetDataset(Index : longint) : TDataset; override;
98     function GetDataSetCount : Longint; override;
99     procedure ReadState(Reader: TReader); override;
100     procedure RegisterIntf(intf: IIBXServicesClient);
101     procedure UnRegisterIntf(intf: IIBXServicesClient);
102     public
103     constructor Create(AOwner: TComponent); override;
104     destructor Destroy; override;
105     procedure ConnectUsing(aDatabase: TIBDatabase);
106     {Copies database parameters as give in the DBParams to the Services connection
107     omitting any parameters not appropriate for Services API. Typically, the
108     DBParams are TIBDatabase.Params}
109     procedure SetDBParams(DBParams: TStrings);
110 tony 263 property FirebirdAPI: IFirebirdAPI read GetFirebirdAPI;
111 tony 209 property ServerVersionNo[index: integer]: integer read GetServerVersionNo;
112     property ServiceIntf: IServiceManager read FService;
113     published
114     property Connected;
115     property ConnectString: string read FConnectString write SetConnectString;
116 tony 263 property FirebirdLibraryPathName: TIBFileName read FFirebirdLibraryPathName
117     write SetFirebirdLibraryPathName;
118 tony 209 property LoginPrompt default True;
119     property Protocol: TProtocol read FProtocol write SetProtocol default Local;
120     property PortNo: string read FPortNo write SetPortNo;
121     property Params: TStrings read FParams write SetParams;
122     property ServerName: string read FServerName write SetServerName;
123     property TraceFlags;
124     property AfterConnect;
125     property AfterDisconnect;
126     property BeforeConnect;
127     property BeforeDisconnect;
128     property OnLogin: TIBXServicesLoginEvent read FOnLogin write FOnLogin;
129     property OnSecurityContextException: TIBXServicesSecContextEvent read FOnSecurityContextException
130     write FOnSecurityContextException;
131     end;
132    
133     { TIBXCustomService }
134    
135     TIBXCustomService = class(TIBXMonitoredService,IIBXServicesClient)
136     private
137     FSRB: ISRB;
138     FSQPB: ISQPB;
139     FServiceQueryResults: IServiceQueryResults;
140     FServicesConnection: TIBXServicesConnection;
141     procedure CheckActive;
142     function GetSQPB: ISQPB;
143     function GetSRB: ISRB;
144     procedure SetServicesConnection(AValue: TIBXServicesConnection);
145     protected
146     procedure Clear; virtual;
147     procedure OnAfterConnect(Sender: TIBXServicesConnection; aDatabaseName: string); virtual;
148     procedure OnBeforeDisconnect(Sender: TIBXServicesConnection); virtual;
149     procedure InternalServiceQuery(RaiseExceptionOnError: boolean=true);
150     procedure DoServiceQuery; virtual;
151     procedure Notification( AComponent: TComponent; Operation: TOperation); override;
152     property SRB: ISRB read GetSRB;
153     property SQPB: ISQPB read GetSQPB;
154     property ServiceQueryResults: IServiceQueryResults read FServiceQueryResults;
155     public
156     constructor Create(AOwner: TComponent); override;
157     destructor Destroy; override;
158     procedure Assign(Source: TPersistent); override;
159     published
160     property ServicesConnection: TIBXServicesConnection read FServicesConnection
161     write SetServicesConnection;
162     property TraceFlags;
163     end;
164    
165     { TDatabaseInfo }
166    
167     TDatabaseInfo = class
168     public
169     NoOfAttachments: Integer;
170     NoOfDatabases: Integer;
171     DbName: array of string;
172     constructor Create;
173     destructor Destroy; override;
174     end;
175    
176     { TConfigFileData }
177    
178     TConfigFileData = class
179     public
180     ConfigFileValue: array of integer;
181     ConfigFileKey: array of integer;
182     constructor Create;
183     destructor Destroy; override;
184     end;
185    
186     { TConfigParams }
187    
188     TConfigParams = class
189     public
190     ConfigFileData: TConfigFileData;
191     ConfigFileParams: array of string;
192     BaseLocation: string;
193     LockFileLocation: string;
194     MessageFileLocation: string;
195     SecurityDatabaseLocation: string;
196     constructor Create;
197     destructor Destroy; override;
198     end;
199    
200     TVersionInfo = class
201     ServerVersion: String;
202     ServerImplementation: string;
203     ServiceVersion: Integer;
204     end;
205    
206     { TIBXServerProperties }
207    
208     TIBXServerProperties = class(TIBXCustomService)
209     private
210     FDatabaseInfo: TDatabaseInfo;
211     FVersionInfo: TVersionInfo;
212     FConfigParams: TConfigParams;
213     function GetConfigParams: TConfigParams;
214     function GetDatabaseInfo: TDatabaseInfo;
215     function GetVersionInfo: TVersionInfo;
216     protected
217     procedure Clear; override;
218     public
219     property DatabaseInfo: TDatabaseInfo read GetDatabaseInfo;
220     property VersionInfo: TVersionInfo read GetVersionInfo;
221     property ConfigParams: TConfigParams read GetConfigParams;
222     end;
223    
224     { TIBXControlService }
225    
226     TIBXControlService = class(TIBXCustomService)
227     private
228     FDatabaseName: string;
229     FAction: TSecContextAction;
230     FLastStartSRB: ISRB;
231     function GetIsServiceRunning: Boolean;
232     procedure HandleSecContextErr;
233     procedure CallSecContextException;
234     procedure SetDatabaseName(AValue: string);
235     protected
236     procedure DatabaseNameChanged; virtual;
237     procedure OnAfterConnect(Sender: TIBXServicesConnection; aDatabaseName: string); override;
238     procedure AddDBNameToSRB;
239     procedure CheckServiceNotRunning;
240     procedure InternalServiceStart;
241     procedure DoServiceQuery; override;
242     procedure SetServiceStartOptions; virtual;
243     procedure ServiceStart; virtual;
244     property DatabaseName: string read FDatabaseName write SetDatabaseName;
245     public
246     procedure Assign(Source: TPersistent); override;
247     property IsServiceRunning : Boolean read GetIsServiceRunning;
248     end;
249    
250     TIBXOnGetNextLine = procedure(Sender: TObject; var Line: string) of object;
251    
252     { TIBXControlAndQueryService }
253    
254     TIBXControlAndQueryService = class (TIBXControlService)
255     private
256     FEof: Boolean;
257     FSendBytes: integer;
258     FOnGetNextLine: TIBXOnGetNextLine;
259     FServiceStarted: boolean;
260     FDataSets: TList;
261     protected
262     function GetNextLine : String;
263     function GetNextChunk : String;
264     procedure ServiceStart; override;
265     function ReceiveNextChunk(stream: TStream): integer;
266     function SendNextChunk(stream: TStream; var line: String): integer;
267     procedure DoOnGetNextLine(Line: string);
268     procedure OnBeforeDisconnect(Sender: TIBXServicesConnection); override;
269     procedure Notification( AComponent: TComponent; Operation: TOperation); override;
270     procedure RegisterDataSet(aDataSet: TDataSet);
271     procedure UnRegisterDataSet(aDataSet: TDataSet);
272     public
273     constructor Create(aOwner: TComponent); override;
274     destructor Destroy; override;
275     procedure Execute(OutputLog: TStrings); virtual;
276     property Eof: boolean read FEof;
277     published
278     property OnGetNextLine: TIBXOnGetNextLine read FOnGetNextLine write FOnGetNextLine;
279     end;
280    
281     { TIBXLogService }
282    
283     TIBXLogService = class(TIBXControlAndQueryService)
284     protected
285     procedure SetServiceStartOptions; override;
286     end;
287    
288     TDBShutdownMode = (Forced, DenyTransaction, DenyAttachment);
289    
290     { TIBXConfigService }
291    
292     TIBXConfigService = class(TIBXControlService)
293     public
294     procedure ShutdownDatabase (Options: TDBShutdownMode; Wait: Integer);
295     procedure SetSweepInterval (Value: Integer);
296     procedure SetDBSqlDialect (Value: Integer);
297     procedure SetPageBuffers (Value: Integer);
298     procedure ActivateShadow;
299     procedure BringDatabaseOnline;
300     procedure SetReserveSpace (Value: Boolean);
301     procedure SetAsyncMode (Value: Boolean);
302     procedure SetReadOnly (Value: Boolean);
303     procedure SetNoLinger;
304     published
305     property DatabaseName;
306     end;
307    
308     TStatOption = (DataPages, HeaderPages, IndexPages, SystemRelations);
309     TStatOptions = set of TStatOption;
310    
311     { TIBXStatisticalService }
312    
313     TIBXStatisticalService = class(TIBXControlAndQueryService)
314     private
315     FOptions: TStatOptions;
316     protected
317     procedure SetServiceStartOptions; override;
318     published
319     property DatabaseName;
320     property Options: TStatOptions read FOptions write FOptions;
321     end;
322    
323     TBackupStatsOption = (bsTotalTime,bsTimeDelta,bsPageReads,bsPageWrites);
324     TBackupStatsOptions = set of TBackupStatsOption;
325    
326     { TIBXBackupRestoreService }
327    
328     TIBXBackupRestoreService = class(TIBXControlAndQueryService)
329     private
330     FStatisticsRequested: TBackupStatsOptions;
331     FVerbose: Boolean;
332     protected
333     procedure SetServiceStartOptions; override;
334     property Verbose : Boolean read FVerbose write FVerbose default False;
335     property StatisticsRequested: TBackupStatsOptions read FStatisticsRequested write FStatisticsRequested;
336     published
337     end;
338    
339     TBackupOption = (IgnoreChecksums, IgnoreLimbo, MetadataOnly, NoGarbageCollection,
340     OldMetadataDesc, NonTransportable, ConvertExtTables, NoDBTriggers);
341     TBackupOptions = set of TBackupOption;
342    
343     { TIBXBackupService }
344    
345     TIBXBackupService = class (TIBXBackupRestoreService)
346     private
347     FOptions: TBackupOptions;
348     FBlockingFactor: Integer;
349     protected
350     procedure SetServiceStartOptions; override;
351     procedure SetBackupTarget; virtual; abstract;
352     published
353     property BlockingFactor: Integer read FBlockingFactor write FBlockingFactor;
354     property DatabaseName;
355     property Options : TBackupOptions read FOptions write FOptions;
356     end;
357    
358     { TIBXClientSideBackupService }
359    
360     TIBXClientSideBackupService = class(TIBXBackupService)
361     protected
362     procedure Execute(OutputLog: TStrings); override;
363     procedure SetBackupTarget; override;
364     public
365     procedure BackupToStream(S: TStream; var BytesWritten: integer);
366     procedure BackupToFile(aFileName: string; var BytesWritten: integer);
367     end;
368    
369     { TIBXServerSideBackupService }
370    
371     TIBXServerSideBackupService = class(TIBXBackupService)
372     private
373     FBackupFiles: TStrings;
374     procedure SetBackupFile(const Value: TStrings);
375     protected
376     procedure SetBackupTarget; override;
377     public
378     constructor Create(AOwner: TComponent); override;
379     destructor Destroy; override;
380     {Use inherited Execute method to perform backup}
381     published
382     { a name=value pair of filename and length }
383     property BackupFiles: TStrings read FBackupFiles write SetBackupFile;
384     property StatisticsRequested;
385     property Verbose;
386     end;
387    
388     TRestoreOption = (DeactivateIndexes, NoShadow, NoValidityCheck, OneRelationAtATime,
389     Replace, CreateNewDB, UseAllSpace, RestoreMetaDataOnly);
390    
391     TRestoreOptions = set of TRestoreOption;
392    
393     { TIBXRestoreService }
394    
395     TIBXRestoreService = class (TIBXBackupRestoreService)
396     private
397     FDatabaseFiles: TStrings;
398     FOptions: TRestoreOptions;
399     FPageSize: Integer;
400     FPageBuffers: Integer;
401     procedure SetDatabaseFiles(const Value: TStrings);
402     protected
403     procedure DatabaseNameChanged; override;
404     procedure SetServiceStartOptions; override;
405     procedure SetArchiveSource; virtual; abstract;
406     public
407     constructor Create(AOwner: TComponent); override;
408     destructor Destroy; override;
409     published
410     { a name=value pair of filename and length }
411     property DatabaseFiles: TStrings read FDatabaseFiles write SetDatabaseFiles;
412     property PageSize: Integer read FPageSize write FPageSize;
413     property PageBuffers: Integer read FPageBuffers write FPageBuffers;
414     property Options : TRestoreOptions read FOptions write FOptions default [CreateNewDB];
415     property StatisticsRequested;
416     property Verbose;
417     end;
418    
419     { TIBXClientSideRestoreService }
420    
421     TIBXClientSideRestoreService = class(TIBXRestoreService)
422     protected
423     procedure Execute(OutputLog: TStrings); override;
424     procedure SetArchiveSource; override;
425     public
426     procedure RestoreFromStream(S: TStream; OutputLog: TStrings);
427     procedure RestoreFromFile(aFileName: string; OutputLog: TStrings);
428     procedure RestoreFromFiles(FileList: TStrings; OutputLog: TStrings);
429     end;
430    
431     { TIBXServerSideRestoreService }
432    
433     TIBXServerSideRestoreService = class(TIBXRestoreService)
434     private
435     FBackupFiles: TStrings;
436     procedure SetBackupFiles(const Value: TStrings);
437     protected
438     procedure SetArchiveSource; override;
439     public
440     constructor Create(AOwner: TComponent); override;
441     destructor Destroy; override;
442     {use inherited Execute method to perform restore}
443     published
444     property BackupFiles: TStrings read FBackupFiles write SetBackupFiles;
445     end;
446    
447     { TIBXOnlineValidationService }
448    
449     TIBXOnlineValidationService = class(TIBXControlAndQueryService)
450     private
451     FExcludeIndexes: string;
452     FExcludeTables: string;
453     FIncludeIndexes: string;
454     FIncludeTables: string;
455     FLockTimeout: integer;
456     protected
457     procedure SetServiceStartOptions; override;
458     procedure ServiceStart; override;
459     public
460     constructor Create(AOwner: TComponent); override;
461     published
462     property IncludeTables: string read FIncludeTables write FIncludeTables;
463     property ExcludeTables: string read FExcludeTables write FExcludeTables;
464     property IncludeIndexes: string read FIncludeIndexes write FIncludeIndexes;
465     property ExcludeIndexes: string read FExcludeIndexes write FExcludeIndexes;
466     property LockTimeout: integer read FLockTimeout write FLockTimeout default 10;
467     property DatabaseName;
468     end;
469    
470     TValidateOption = (CheckDB, IgnoreChecksum, KillShadows, MendDB,
471     SweepDB, ValidateDB, ValidateFull);
472     TValidateOptions = set of TValidateOption;
473    
474     { TIBXValidationService }
475    
476     TIBXValidationService = class(TIBXControlAndQueryService)
477     private
478     FOptions: TValidateOptions;
479     protected
480     procedure SetServiceStartOptions; override;
481     public
482     {use inherited Execute method to perform validation}
483     published
484     property DatabaseName;
485     property Options: TValidateOptions read FOptions write FOptions;
486     end;
487    
488     TUserInfo = class
489     public
490     UserName: string;
491     FirstName: string;
492     MiddleName: string;
493     LastName: string;
494     GroupID: Integer;
495     UserID: Integer;
496     AdminRole: boolean;
497     end;
498    
499     TSecurityAction = (ActionAddUser, ActionDeleteUser, ActionModifyUser, ActionDisplayUser);
500     TSecurityModifyParam = (ModifyFirstName, ModifyMiddleName, ModifyLastName, ModifyUserId,
501     ModifyGroupId, ModifyPassword, ModifyAdminRole);
502     TSecurityModifyParams = set of TSecurityModifyParam;
503    
504     { TIBXSecurityService }
505    
506     TIBXSecurityService = class(TIBXControlAndQueryService)
507     private
508     FAdminRole: boolean;
509     FUserID: Integer;
510     FGroupID: Integer;
511     FFirstName: string;
512     FUserName: string;
513     FPassword: string;
514     FSQLRole: string;
515     FLastName: string;
516     FMiddleName: string;
517     FUserInfo: array of TUserInfo;
518     FSecurityAction: TSecurityAction;
519     FModifyParams: TSecurityModifyParams;
520     procedure ClearParams;
521     procedure SetAdminRole(AValue: boolean);
522     procedure SetSecurityAction (Value: TSecurityAction);
523     procedure SetFirstName (Value: String);
524     procedure SetMiddleName (Value: String);
525     procedure SetLastName (Value: String);
526     procedure SetPassword (Value: String);
527     procedure SetUserId (Value: Integer);
528     procedure SetGroupId (Value: Integer);
529    
530     procedure FetchUserInfo;
531     function GetUserInfo(Index: Integer): TUserInfo;
532     function GetUserInfoCount: Integer;
533    
534     protected
535     procedure Execute(OutputLog: TStrings); override;
536     procedure Loaded; override;
537     procedure SetServiceStartOptions; override;
538     property SecurityAction: TSecurityAction read FSecurityAction
539     write SetSecurityAction;
540     public
541     constructor Create(AOwner: TComponent); override;
542     destructor Destroy; override;
543     procedure DisplayUsers;
544     procedure DisplayUser(aUserName: string);
545     procedure AddUser;
546     procedure DeleteUser;
547     procedure ModifyUser;
548     function HasAdminRole: boolean;
549     procedure SetAutoAdmin(Value: Boolean);
550     property UserInfo[Index: Integer]: TUserInfo read GetUserInfo;
551     property UserInfoCount: Integer read GetUserInfoCount;
552    
553     published
554     property SQlRole : string read FSQLRole write FSQLrole;
555     property UserName : string read FUserName write FUserName;
556     property FirstName : string read FFirstName write SetFirstName;
557     property MiddleName : string read FMiddleName write SetMiddleName;
558     property LastName : string read FLastName write SetLastName;
559     property UserID : Integer read FUserID write SetUserID;
560     property GroupID : Integer read FGroupID write SetGroupID;
561     property Password : string read FPassword write setPassword;
562     property AdminRole: boolean read FAdminRole write SetAdminRole;
563     end;
564    
565     TTransactionGlobalAction = (CommitGlobal, RollbackGlobal, RecoverTwoPhaseGlobal,
566     NoGlobalAction);
567     TTransactionState = (LimboState, CommitState, RollbackState, UnknownState);
568     TTransactionAdvise = (CommitAdvise, RollbackAdvise, UnknownAdvise);
569     TTransactionAction = (CommitAction, RollbackAction);
570    
571     TLimboTransactionInfo = class
572     public
573     MultiDatabase: Boolean;
574     ID: Integer;
575     HostSite: String;
576     RemoteSite: String;
577     RemoteDatabasePath: String;
578     State: TTransactionState;
579     Advise: TTransactionAdvise;
580     Action: TTransactionAction;
581     end;
582    
583     { TIBXLimboTransactionResolutionService }
584    
585     TIBXLimboTransactionResolutionService = class(TIBXControlAndQueryService)
586     private
587     FLimboTransactionInfo: array of TLimboTransactionInfo;
588     FGlobalAction: TTransactionGlobalAction;
589     function GetLimboTransactionInfo(index: integer): TLimboTransactionInfo;
590     function GetLimboTransactionInfoCount: integer;
591     function FetchLimboTransactionInfo: integer;
592    
593     protected
594     procedure SetServiceStartOptions; override;
595     public
596     destructor Destroy; override;
597     procedure Clear; override;
598     procedure Execute(OutputLog: TStrings); override;
599     property LimboTransactionInfo[Index: integer]: TLimboTransactionInfo read GetLimboTransactionInfo;
600     property LimboTransactionInfoCount: Integer read GetLimboTransactionInfoCount;
601    
602     published
603     property DatabaseName;
604     property GlobalAction: TTransactionGlobalAction read FGlobalAction
605     write FGlobalAction;
606    
607     end;
608    
609     TRequiredSources = class of TIBXControlAndQueryService;
610    
611     { TIBXServicesDataSet }
612    
613     TIBXServicesDataSet = class(TMemDataSet)
614     private
615     FSource: TIBXControlAndQueryService;
616     procedure SetSource(AValue: TIBXControlAndQueryService);
617     protected
618     FRequiredSource: TRequiredSources;
619     procedure DoBeforeClose; override;
620     procedure Notification( AComponent: TComponent; Operation: TOperation); override;
621     public
622     destructor Destroy; override;
623     published
624     property Source: TIBXControlAndQueryService read FSource write SetSource;
625     end;
626    
627     { TIBXServicesUserList }
628    
629     TIBXServicesUserList = class(TIBXServicesDataSet)
630     private
631     FLoading: boolean;
632     protected
633     procedure DoBeforePost; override;
634     procedure DoAfterInsert; override;
635     procedure DoAfterPost; override;
636     procedure DoAfterOpen; override;
637     procedure InternalDelete; override;
638     public
639     constructor Create(AOwner:TComponent); override;
640     end;
641    
642     { TIBXServicesLimboTransactionsList }
643    
644     TIBXServicesLimboTransactionsList = class(TIBXServicesDataSet)
645     private
646     FLoading: boolean;
647     protected
648     procedure DoBeforeInsert; override;
649     procedure DoAfterOpen; override;
650 tony 210 procedure DoAfterPost; override;
651 tony 209 procedure DoBeforePost; override;
652     public
653     constructor Create(AOwner:TComponent); override;
654     procedure Delete; override;
655     procedure FixErrors(GlobalAction: TTransactionGlobalAction; OutputLog: TStrings);
656     end;
657    
658     implementation
659    
660     uses FBMessages, IBUtils, RegExpr, CustApp, IBErrorCodes;
661    
662     const
663     SPBPrefix = 'isc_spb_';
664     isc_spb_last_spb_constant = 13;
665     SPBConstantNames: array[1..isc_spb_last_spb_constant] of String = (
666     'user_name',
667     'sys_user_name',
668     'sys_user_name_enc',
669     'password',
670     'password_enc',
671     'command_line',
672     'db_name',
673     'verbose',
674     'options',
675     'connect_timeout',
676     'dummy_packet_interval',
677     'sql_role_name',
678     'expected_db'
679     );
680    
681     SPBConstantValues: array[1..isc_spb_last_spb_constant] of Integer = (
682     isc_spb_user_name,
683     isc_spb_sys_user_name,
684     isc_spb_sys_user_name_enc,
685     isc_spb_password,
686     isc_spb_password_enc,
687     isc_spb_command_line,
688     isc_spb_dbname,
689     isc_spb_verbose,
690     isc_spb_options,
691     isc_spb_connect_timeout,
692     isc_spb_dummy_packet_interval,
693     isc_spb_sql_role_name,
694     isc_spb_expected_db
695     );
696    
697     { TIBXClientSideRestoreService }
698    
699     procedure TIBXClientSideRestoreService.Execute(OutputLog: TStrings);
700     begin
701     // Do nothing
702     end;
703    
704     procedure TIBXClientSideRestoreService.SetArchiveSource;
705     begin
706     SRB.Add(isc_spb_bkp_file).AsString := 'stdin';
707     end;
708    
709     procedure TIBXClientSideRestoreService.RestoreFromStream(S: TStream;
710     OutputLog: TStrings);
711     var line: string;
712     begin
713     ServiceStart;
714     try
715     while not Eof do
716     begin
717     SendNextChunk(S,line);
718     if line <> '' then
719     begin
720     DoOnGetNextLine(line);
721     if OutputLog <> nil then
722     OutputLog.Add(line);
723     end;
724     end;
725     finally
726     while IsServiceRunning do; {flush}
727     end;
728     end;
729    
730     procedure TIBXClientSideRestoreService.RestoreFromFile(aFileName: string;
731     OutputLog: TStrings);
732     var F: TFileStream;
733     begin
734     F := TFileStream.Create(aFileName,fmOpenRead);
735     try
736     RestoreFromStream(F,OutputLog)
737     finally
738     F.Free;
739     end;
740     end;
741    
742     procedure TIBXClientSideRestoreService.RestoreFromFiles(FileList: TStrings;
743     OutputLog: TStrings);
744     var i: integer;
745     F: TFileStream;
746     line: string;
747     begin
748     ServiceStart;
749     for i := 0 to FileList.Count - 1 do
750     begin
751     F := TFileStream.Create(FileList[i],fmOpenRead);
752     try
753     while Eof do
754     begin
755     SendNextChunk(F,line);
756     if line <> '' then
757     begin
758     DoOnGetNextLine(line);
759     if OutputLog <> nil then
760     OutputLog.Add(line);
761     end;
762     end;
763     finally
764     F.Free;
765     while IsServiceRunning do; {flush}
766     FEof := false;
767     end;
768     end;
769     end;
770    
771     { TIBXClientSideBackupService }
772    
773     procedure TIBXClientSideBackupService.Execute(OutputLog: TStrings);
774     begin
775     //Do nothing
776     end;
777    
778     procedure TIBXClientSideBackupService.SetBackupTarget;
779     begin
780     SRB.Add(isc_spb_bkp_file).AsString := 'stdout';
781     end;
782    
783     procedure TIBXClientSideBackupService.BackupToStream(S: TStream;
784     var BytesWritten: integer);
785     var InitialSize: integer;
786     begin
787     InitialSize := S.Size;
788     ServiceStart;
789     while not Eof do
790     ReceiveNextChunk(S);
791     BytesWritten := S.Size - InitialSize;
792     end;
793    
794     procedure TIBXClientSideBackupService.BackupToFile(aFileName: string;
795     var BytesWritten: integer);
796     var F: TFileStream;
797     begin
798     F := TFileStream.Create(aFileName,fmCreate);
799     try
800     BackupToStream(F,BytesWritten);
801     finally
802     F.Free;
803     end;
804     end;
805    
806     { TIBXServicesLimboTransactionsList }
807    
808     procedure TIBXServicesLimboTransactionsList.DoBeforeInsert;
809     begin
810     inherited DoBeforeInsert;
811     if not FLoading then
812     IBError(ibxeNoLimboTransactionInsert,[nil]);
813     end;
814    
815     procedure TIBXServicesLimboTransactionsList.DoAfterOpen;
816    
817     function TypeToStr(MultiDatabase: boolean): string;
818     begin
819     if MultiDatabase then
820     Result := 'Multi DB'
821     else
822     Result := 'Single DB';
823     end;
824    
825     function StateToStr(State: TTransactionState): string;
826     begin
827     case State of
828     LimboState:
829     Result := 'Limbo';
830     CommitState:
831     Result := 'Commit';
832     RollbackState:
833     Result := 'Rollback';
834     else
835     Result := 'Unknown';
836     end;
837     end;
838    
839     function AdviseToStr(Advise: TTransactionAdvise): string;
840     begin
841     case Advise of
842     CommitAdvise:
843     Result := 'Commit';
844     RollbackAdvise:
845     Result := 'Rollback';
846     else
847     Result := 'Unknown';
848     end;
849     end;
850    
851     function ActionToStr(anAction: TTransactionAction): string;
852     begin
853     case anAction of
854     CommitAction:
855     Result := 'Commit';
856     RollbackAction:
857     Result := 'Rollback';
858     end;
859     end;
860    
861     var i: integer;
862     begin
863     if FLoading then Exit;
864     FLoading := true;
865     with FSource as TIBXLimboTransactionResolutionService do
866     try
867     for i := 0 to LimboTransactionInfoCount - 1 do
868     with LimboTransactionInfo[i] do
869     begin
870     Append;
871     FieldByName('TransactionID').AsInteger := ID;
872     FieldByName('TransactionType').AsString := TypeToStr(MultiDatabase);
873     FieldByName('HostSite').AsString := HostSite;
874     FieldByName('RemoteSite').AsString := RemoteSite;
875     FieldByName('DatabasePath').AsString := RemoteDatabasePath;
876     FieldByName('State').AsString := StateToStr(State);
877     FieldByName('RecommendedAction').AsString := AdviseToStr(Advise);
878     FieldByName('RequestedAction').AsString := ActionToStr(Action);
879     Post;
880     end;
881     finally
882     FLoading := false;
883     end;
884     inherited DoAfterOpen;
885     end;
886    
887 tony 210 procedure TIBXServicesLimboTransactionsList.DoAfterPost;
888     begin
889     if not FLoading then
890     inherited DoAfterPost;
891     end;
892    
893 tony 209 procedure TIBXServicesLimboTransactionsList.DoBeforePost;
894     var i: integer;
895     begin
896     inherited DoBeforePost;
897     if FLoading then Exit;
898     with FSource as TIBXLimboTransactionResolutionService do
899     for i := 0 to LimboTransactionInfoCount - 1 do
900     with LimboTransactionInfo[i] do
901     begin
902     if ID = FieldByName('TransactionID').AsInteger then
903     begin
904     if FieldByName('RequestedAction').AsString = 'Commit' then
905     Action := CommitAction
906     else
907     if FieldByName('RequestedAction').AsString = 'Rollback' then
908     Action := RollbackAction;
909     break;
910     end;
911     end;
912     end;
913    
914    
915     constructor TIBXServicesLimboTransactionsList.Create(AOwner: TComponent);
916     var i: integer;
917     begin
918     inherited Create(AOwner);
919     FRequiredSource := TIBXLimboTransactionResolutionService;
920     with FieldDefs do
921     if Count = 0 then
922     begin
923     Add('TransactionID',ftInteger);
924     Add('TransactionType',ftString,16);
925     Add('HostSite',ftString,256);
926     Add('RemoteSite',ftString,256);
927     Add('DatabasePath',ftString,256);
928     Add('State',ftString,32);
929     Add('RecommendedAction',ftString,32);
930     Add('RequestedAction',ftString,32);
931     for i := 0 to Count - 2 do
932     Items[i].Attributes := Items[i].Attributes + [faReadOnly];
933     end;
934     end;
935    
936     procedure TIBXServicesLimboTransactionsList.Delete;
937     begin
938     //Do nothing
939     end;
940    
941     procedure TIBXServicesLimboTransactionsList.FixErrors(
942     GlobalAction: TTransactionGlobalAction; OutputLog: TStrings);
943     begin
944     if State = dsEdit then Post;
945     (FSource as TIBXLimboTransactionResolutionService).GlobalAction := GlobalAction;
946     (FSource as TIBXLimboTransactionResolutionService).Execute(OutputLog);
947     Active := false;
948     Active := true;
949     end;
950    
951     { TIBXServicesUserList }
952    
953     procedure TIBXServicesUserList.DoBeforePost;
954     procedure SetParams;
955     begin
956     with FSource as TIBXSecurityService do
957     begin
958     UserID := FieldByName('UserID').AsInteger;
959     GroupID := FieldByName('GroupID').AsInteger;
960     UserName := FieldByName('SEC$USER_NAME').AsString;
961     FirstName := FieldByName('SEC$FIRST_NAME').AsString;
962     MiddleName := FieldByName('SEC$MIDDLE_NAME').AsString;
963     LastName := FieldByName('SEC$LAST_NAME').AsString;
964     if not FieldByName('SEC$PASSWORD').IsNull then
965     Password := FieldByName('SEC$PASSWORD').AsString;
966     AdminRole := FieldByName('SEC$ADMIN').AsBoolean;
967     end;
968     end;
969    
970     begin
971     inherited DoBeforePost;
972     if FLoading then Exit;
973     case State of
974     dsEdit:
975     begin
976     SetParams;
977     (FSource as TIBXSecurityService).ModifyUser;
978     end;
979     dsInsert:
980     begin
981     SetParams;
982     (FSource as TIBXSecurityService).AddUser;
983     end;
984     end;
985     end;
986    
987     procedure TIBXServicesUserList.DoAfterInsert;
988     begin
989     FieldByName('UserID').AsInteger := 0;
990     FieldByName('GroupID').AsInteger := 0;
991     FieldByName('SEC$PASSWORD').Clear;
992     FieldByName('SEC$ADMIN').AsBoolean := false;
993     inherited DoAfterInsert;
994     end;
995    
996     procedure TIBXServicesUserList.DoAfterPost;
997     begin
998     {Refresh}
999     if not FLoading then
1000     begin
1001 tony 210 inherited DoAfterPost;
1002     with FSource as TIBXSecurityService do
1003 tony 209 begin
1004 tony 210 DisplayUser(FieldByName('SEC$USER_NAME').AsString);
1005     if UserInfoCount > 0 then
1006     with UserInfo[0] do
1007     begin
1008     FieldByName('UserID').AsInteger := UserID;
1009     FieldByName('GroupID').AsInteger := GroupID;
1010     FieldByName('SEC$USER_NAME').AsString := UserName;
1011     FieldByName('SEC$FIRST_NAME').AsString := FirstName;
1012     FieldByName('SEC$MIDDLE_NAME').AsString := MiddleName;
1013     FieldByName('SEC$LAST_NAME').AsString := LastName;
1014     FieldByName('SEC$PASSWORD').Clear;
1015     FieldByName('SEC$ADMIN').AsBoolean := AdminRole;
1016     end;
1017 tony 209 end;
1018     end;
1019     end;
1020    
1021     procedure TIBXServicesUserList.DoAfterOpen;
1022     var i: integer;
1023     Buf: TStringList;
1024     begin
1025     buf := TStringList.Create; {Used to sort user info}
1026     try
1027     with FSource as TIBXSecurityService do
1028     begin
1029     buf.Sorted := true;
1030     DisplayUsers;
1031     FLoading := true;
1032     try
1033     for i := 0 to UserInfoCount - 1 do
1034     buf.AddObject(UserInfo[i].UserName,UserInfo[i]);
1035    
1036     for i := 0 to buf.Count - 1 do
1037     with TUserInfo(buf.Objects[i]) do
1038     begin
1039     Append;
1040     FieldByName('UserID').AsInteger := UserID;
1041     FieldByName('GroupID').AsInteger := GroupID;
1042     FieldByName('SEC$USER_NAME').AsString := UserName;
1043     FieldByName('SEC$FIRST_NAME').AsString := FirstName;
1044     FieldByName('SEC$MIDDLE_NAME').AsString := MiddleName;
1045     FieldByName('SEC$LAST_NAME').AsString := LastName;
1046     FieldByName('SEC$PASSWORD').Clear;
1047     FieldByName('SEC$ADMIN').AsBoolean := AdminRole;
1048     Post;
1049     end;
1050     finally
1051     FLoading := false;
1052     end;
1053     end;
1054     finally
1055     Buf.Free;
1056     end;
1057     inherited DoAfterOpen;
1058     end;
1059    
1060     procedure TIBXServicesUserList.InternalDelete;
1061     begin
1062     with FSource as TIBXSecurityService do
1063     begin
1064     UserName := FieldByName('SEC$USER_NAME').AsString;
1065     DeleteUser;
1066     end;
1067     inherited InternalDelete;
1068     end;
1069    
1070     constructor TIBXServicesUserList.Create(AOwner: TComponent);
1071     begin
1072     inherited Create(AOwner);
1073     FRequiredSource := TIBXSecurityService;
1074     with FieldDefs do
1075     if Count = 0 then
1076     begin
1077     Add('UserID',ftInteger);
1078     Add('GroupID',ftInteger);
1079     Add('SEC$USER_NAME',ftString,31);
1080     Add('SEC$FIRST_NAME',ftString,32);
1081     Add('SEC$MIDDLE_NAME',ftString,32);
1082     Add('SEC$LAST_NAME',ftString,32);
1083     Add('SEC$PASSWORD',ftString,32);
1084     Add('SEC$ADMIN',ftBoolean);
1085     end;
1086     end;
1087    
1088     { TIBXServicesDataSet }
1089    
1090     procedure TIBXServicesDataSet.SetSource(AValue: TIBXControlAndQueryService);
1091     begin
1092     if FSource = AValue then Exit;
1093     if (AValue <> nil) and not (AValue is FRequiredSource) then
1094     IBError(ibxeNotRequiredDataSetSource,[AValue.ClassName]);
1095     if FSource <> nil then
1096     begin
1097     FSource.UnRegisterDataSet(self);
1098     RemoveFreeNotification(FSource);
1099     end;
1100     FSource := AValue;
1101     if FSource <> nil then
1102     begin
1103     FSource.RegisterDataSet(self);
1104     FreeNotification(FSource);
1105     end;
1106     end;
1107    
1108     procedure TIBXServicesDataSet.DoBeforeClose;
1109     begin
1110     if csDestroying in ComponentState then Exit;
1111     if State in [dsEdit,dsInsert] then Post;
1112     Clear(false);
1113     inherited DoBeforeClose;
1114     end;
1115    
1116     procedure TIBXServicesDataSet.Notification(AComponent: TComponent;
1117     Operation: TOperation);
1118     begin
1119     inherited Notification(AComponent, Operation);
1120     if (Operation = opRemove) and (AComponent = FSource) then
1121     FSource := nil;
1122     end;
1123    
1124     destructor TIBXServicesDataSet.Destroy;
1125     begin
1126     Source := nil;
1127     inherited Destroy;
1128     end;
1129    
1130     { TIBXLimboTransactionResolutionService }
1131    
1132     function TIBXLimboTransactionResolutionService.GetLimboTransactionInfo(
1133     index: integer): TLimboTransactionInfo;
1134     begin
1135     if index < GetLimboTransactionInfoCount then
1136     Result := FLimboTransactionInfo[index]
1137     else
1138     Result := nil;
1139     end;
1140    
1141     function TIBXLimboTransactionResolutionService.GetLimboTransactionInfoCount: integer;
1142     begin
1143     Result := Length(FLimboTransactionInfo);
1144     if Result = 0 then
1145     Result := FetchLimboTransactionInfo;
1146     end;
1147    
1148     procedure TIBXLimboTransactionResolutionService.SetServiceStartOptions;
1149     var i: integer;
1150     begin
1151     SRB.Add(isc_action_svc_repair);
1152     AddDBNameToSRB;
1153     if Length(FLimboTransactionInfo) = 0 then
1154     SRB.Add(isc_spb_options).AsInteger := isc_spb_rpr_list_limbo_trans
1155     else
1156     {Fixing existing transactions}
1157     begin
1158     case FGlobalAction of
1159     NoGlobalAction:
1160     begin
1161     for i := 0 to LimboTransactionInfoCount - 1 do
1162     begin
1163     if (FLimboTransactionInfo[i].Action = CommitAction) then
1164     SRB.Add(isc_spb_rpr_commit_trans).AsInteger := FLimboTransactionInfo[i].ID
1165     else
1166     SRB.Add(isc_spb_rpr_rollback_trans).AsInteger := FLimboTransactionInfo[i].ID;
1167     end;
1168     end;
1169    
1170     CommitGlobal:
1171     begin
1172     for i := 0 to LimboTransactionInfoCount - 1 do
1173     SRB.Add(isc_spb_rpr_commit_trans).AsInteger := FLimboTransactionInfo[i].ID;
1174     end;
1175    
1176     RollbackGlobal:
1177     begin
1178     for i := 0 to LimboTransactionInfoCount - 1 do
1179     SRB.Add(isc_spb_rpr_rollback_trans).AsInteger := FLimboTransactionInfo[i].ID;
1180     end;
1181    
1182     RecoverTwoPhaseGlobal:
1183     begin
1184     for i := 0 to LimboTransactionInfoCount - 1 do
1185     SRB.Add(isc_spb_rpr_recover_two_phase).AsInteger := FLimboTransactionInfo[i].ID;
1186     end;
1187     end;
1188     end;
1189     end;
1190    
1191     destructor TIBXLimboTransactionResolutionService.Destroy;
1192     begin
1193     Clear;
1194     inherited Destroy;
1195     end;
1196    
1197     procedure TIBXLimboTransactionResolutionService.Clear;
1198     var
1199     i : Integer;
1200     begin
1201     for i := 0 to High(FLimboTransactionInfo) do
1202     FLimboTransactionInfo[i].Free;
1203     SetLength(FLimboTransactionInfo,0);
1204     end;
1205    
1206    
1207     function TIBXLimboTransactionResolutionService.FetchLimboTransactionInfo: integer;
1208    
1209     procedure NextLimboTransaction(index: integer);
1210     begin
1211     SetLength(FLimboTransactionInfo, index+1);
1212     FLimboTransactionInfo[index] := TLimboTransactionInfo.Create;
1213     { if no advice commit as default }
1214     FLimboTransactionInfo[index].Advise := UnknownAdvise;
1215     FLimboTransactionInfo[index].Action:= CommitAction;
1216     end;
1217    
1218     var
1219     i,j, k: Integer;
1220     begin
1221     Clear;
1222     Result := 0;
1223     ServiceStart;
1224     SRB.Add(isc_info_svc_limbo_trans);
1225     InternalServiceQuery;
1226    
1227     k := -1;
1228     for i := 0 to FServiceQueryResults.Count - 1 do
1229     with FServiceQueryResults[i] do
1230     case getItemType of
1231     isc_info_svc_limbo_trans:
1232     begin
1233     if FServiceQueryResults[i].Count = 0 then continue;
1234     NextLimboTransaction(0);
1235     for j := 0 to FServiceQueryResults[i].Count - 1 do
1236     begin
1237     with FServiceQueryResults[i][j] do
1238     begin
1239     case getItemType of
1240     isc_spb_single_tra_id:
1241     begin
1242     Inc(k);
1243     if k > 0 then
1244     NextLimboTransaction(k);
1245     FLimboTransactionInfo[k].MultiDatabase := False;
1246     FLimboTransactionInfo[k].ID := AsInteger;
1247     end;
1248    
1249     isc_spb_multi_tra_id:
1250     begin
1251     Inc(k);
1252     if k > 0 then
1253     NextLimboTransaction(k);
1254     FLimboTransactionInfo[k].MultiDatabase := True;
1255     FLimboTransactionInfo[k].ID := AsInteger;
1256     end;
1257    
1258     isc_spb_tra_host_site:
1259     FLimboTransactionInfo[k].HostSite := AsString;
1260    
1261     isc_spb_tra_state:
1262     case AsByte of
1263     isc_spb_tra_state_limbo:
1264     FLimboTransactionInfo[k].State := LimboState;
1265    
1266     isc_spb_tra_state_commit:
1267     FLimboTransactionInfo[k].State := CommitState;
1268    
1269     isc_spb_tra_state_rollback:
1270     FLimboTransactionInfo[k].State := RollbackState;
1271    
1272     else
1273     FLimboTransactionInfo[k].State := UnknownState;
1274     end;
1275    
1276     isc_spb_tra_remote_site:
1277     FLimboTransactionInfo[k].RemoteSite := AsString;
1278    
1279     isc_spb_tra_db_path:
1280     FLimboTransactionInfo[k].RemoteDatabasePath := AsString;
1281    
1282     isc_spb_tra_advise:
1283     with FLimboTransactionInfo[k] do
1284     begin
1285     case (AsByte) of
1286     isc_spb_tra_advise_commit:
1287     begin
1288     Advise := CommitAdvise;
1289     Action:= CommitAction;
1290     end;
1291    
1292     isc_spb_tra_advise_rollback:
1293     begin
1294     Advise := RollbackAdvise;
1295     Action := RollbackAction;
1296     end;
1297    
1298     else
1299     Advise := UnknownAdvise;
1300     end;
1301     end;
1302    
1303     else
1304     IBError(ibxeOutputParsingError, [getItemType]);
1305     end;
1306     end;
1307     end;
1308     end;
1309     else
1310     IBError(ibxeOutputParsingError, [getItemType]);
1311     end;
1312     Result := Length(FLimboTransactionInfo);
1313     end;
1314    
1315     procedure TIBXLimboTransactionResolutionService.Execute(OutputLog: TStrings);
1316     begin
1317     if Length(FLimboTransactionInfo) > 0 then
1318     begin
1319     ServiceStart; {Fix is implicit in non-zero list of Limbo transactions}
1320     while not Eof do
1321     OutputLog.Add(GetNextLine);
1322     while IsServiceRunning do;
1323     Clear;
1324     end;
1325     end;
1326    
1327     { TIBXSecurityService }
1328    
1329     constructor TIBXSecurityService.Create(AOwner: TComponent);
1330     begin
1331     inherited Create(AOwner);
1332     FModifyParams := [];
1333     end;
1334    
1335     destructor TIBXSecurityService.Destroy;
1336     var
1337     i : Integer;
1338     begin
1339     for i := 0 to High(FUserInfo) do
1340     FUserInfo[i].Free;
1341     FUserInfo := nil;
1342     inherited Destroy;
1343     end;
1344    
1345     procedure TIBXSecurityService.Execute(OutputLog: TStrings);
1346     begin
1347     //Do nothing
1348     end;
1349    
1350     procedure TIBXSecurityService.FetchUserInfo;
1351     var
1352     i, j, k: Integer;
1353     begin
1354     SRB.Add(isc_info_svc_get_users);
1355     InternalServiceQuery;
1356    
1357     for i := 0 to High(FUserInfo) do
1358     FUserInfo[i].Free;
1359     for i := 0 to FServiceQueryResults.Count - 1 do
1360     with FServiceQueryResults[i] do
1361     begin
1362     case getItemType of
1363     isc_info_svc_get_users:
1364     begin
1365     SetLength(FUserInfo,1);
1366     k := 0;
1367     FUserInfo[0] := TUserInfo.Create;
1368     FUserInfo[0].UserName := '';
1369     for j := 0 to FServiceQueryResults[i].Count - 1 do
1370     begin
1371     with FServiceQueryResults[i][j] do
1372     case getItemType of
1373     isc_spb_sec_username:
1374     begin
1375     if FUserInfo[k].UserName <> '' then
1376     begin
1377     Inc(k);
1378     SetLength(FUserInfo,k+1);
1379     if FUserInfo[k] = nil then
1380     FUserInfo[k] := TUserInfo.Create;
1381     end;
1382     FUserInfo[k].UserName := AsString;
1383     end;
1384    
1385     isc_spb_sec_firstname:
1386     FUserInfo[k].FirstName := AsString;
1387    
1388     isc_spb_sec_middlename:
1389     FUserInfo[k].MiddleName := AsString;
1390    
1391     isc_spb_sec_lastname:
1392     FUserInfo[k].LastName := AsString;
1393    
1394     isc_spb_sec_userId:
1395     FUserInfo[k].UserId := AsInteger;
1396    
1397     isc_spb_sec_groupid:
1398     FUserInfo[k].GroupID := AsInteger;
1399    
1400     isc_spb_sec_admin:
1401     FUserInfo[k].AdminRole := AsInteger <> 0;
1402    
1403     else
1404     IBError(ibxeOutputParsingError, [getItemType]);
1405     end;
1406     end;
1407     end;
1408     else
1409     IBError(ibxeOutputParsingError, [getItemType]);
1410     end;
1411     end;
1412     end;
1413    
1414     function TIBXSecurityService.GetUserInfo(Index: Integer): TUserInfo;
1415     begin
1416     if Index <= High(FUSerInfo) then
1417     result := FUserInfo[Index]
1418     else
1419     result := nil;
1420     end;
1421    
1422     function TIBXSecurityService.GetUserInfoCount: Integer;
1423     begin
1424     Result := Length(FUserInfo);
1425     end;
1426    
1427     procedure TIBXSecurityService.AddUser;
1428     begin
1429     SecurityAction := ActionAddUser;
1430     ServiceStart;
1431     while IsServiceRunning do;
1432     end;
1433    
1434     procedure TIBXSecurityService.DeleteUser;
1435     begin
1436     SecurityAction := ActionDeleteUser;
1437     ServiceStart;
1438     while IsServiceRunning do;
1439     end;
1440    
1441     procedure TIBXSecurityService.DisplayUsers;
1442     begin
1443     SecurityAction := ActionDisplayUser;
1444     ClearParams;
1445     FUserName := '';
1446     ServiceStart;
1447     FetchUserInfo;
1448     end;
1449    
1450     procedure TIBXSecurityService.DisplayUser(aUserName: string);
1451     begin
1452     SecurityAction := ActionDisplayUser;
1453     ClearParams;
1454     FUserName := aUserName;
1455     ServiceStart;
1456     FetchUserInfo;
1457     end;
1458    
1459     procedure TIBXSecurityService.ModifyUser;
1460     begin
1461     SecurityAction := ActionModifyUser;
1462     ServiceStart;
1463     while IsServiceRunning do;
1464     end;
1465    
1466     function TIBXSecurityService.HasAdminRole: boolean;
1467     begin
1468     CheckActive;
1469     with ServicesConnection do
1470     Result := (ServerVersionNo[1] > 2) or
1471     ((ServerVersionNo[1] = 2) and (ServerVersionNo[2] = 5));
1472     end;
1473    
1474     procedure TIBXSecurityService.SetAutoAdmin(Value: Boolean);
1475     begin
1476     CheckActive;
1477     {only available for Firebird 2.5 and later}
1478     with ServicesConnection do
1479     if (ServerVersionNo[1] < 2) or
1480     ((ServerVersionNo[1] = 2) and (ServerVersionNo[2] < 5)) then Exit;
1481     if Value then
1482     SRB.Add(isc_action_svc_set_mapping)
1483     else
1484     SRB.Add(isc_action_svc_drop_mapping);
1485     InternalServiceStart;
1486     while IsServiceRunning do;
1487     end;
1488    
1489     procedure TIBXSecurityService.SetSecurityAction (Value: TSecurityAction);
1490     begin
1491     FSecurityAction := Value;
1492     if Value = ActionDeleteUser then
1493     ClearParams;
1494     end;
1495    
1496     procedure TIBXSecurityService.ClearParams;
1497     begin
1498     FModifyParams := [];
1499     FFirstName := '';
1500     FMiddleName := '';
1501     FLastName := '';
1502     FGroupID := 0;
1503     FUserID := 0;
1504     FPassword := '';
1505     end;
1506    
1507     procedure TIBXSecurityService.SetAdminRole(AValue: boolean);
1508     begin
1509     FAdminRole := AValue;
1510     Include (FModifyParams, ModifyAdminRole);
1511     end;
1512    
1513     procedure TIBXSecurityService.SetFirstName (Value: String);
1514     begin
1515     FFirstName := Value;
1516     Include (FModifyParams, ModifyFirstName);
1517     end;
1518    
1519     procedure TIBXSecurityService.SetMiddleName (Value: String);
1520     begin
1521     FMiddleName := Value;
1522     Include (FModifyParams, ModifyMiddleName);
1523     end;
1524    
1525     procedure TIBXSecurityService.SetLastName (Value: String);
1526     begin
1527     FLastName := Value;
1528     Include (FModifyParams, ModifyLastName);
1529     end;
1530    
1531     procedure TIBXSecurityService.SetPassword (Value: String);
1532     begin
1533     FPassword := Value;
1534     Include (FModifyParams, ModifyPassword);
1535     end;
1536    
1537     procedure TIBXSecurityService.SetUserId (Value: Integer);
1538     begin
1539     FUserId := Value;
1540     Include (FModifyParams, ModifyUserId);
1541     end;
1542    
1543     procedure TIBXSecurityService.SetGroupId (Value: Integer);
1544     begin
1545     FGroupId := Value;
1546     Include (FModifyParams, ModifyGroupId);
1547     end;
1548    
1549     procedure TIBXSecurityService.Loaded;
1550     begin
1551     inherited Loaded;
1552     ClearParams;
1553     end;
1554    
1555     procedure TIBXSecurityService.SetServiceStartOptions;
1556     var
1557     Len: UShort;
1558    
1559     begin
1560     case FSecurityAction of
1561     ActionDisplayUser:
1562     begin
1563     if HasAdminRole then
1564     SRB.Add(isc_action_svc_display_user_adm) {Firebird 2.5 and later only}
1565     else
1566     SRB.Add(isc_action_svc_display_user);
1567     if UserName <> '' then
1568     SRB.Add(isc_spb_sec_username).AsString := UserName;
1569     end;
1570    
1571     ActionAddUser:
1572     begin
1573     if ( Pos(' ', FUserName) > 0 ) then
1574     IBError(ibxeStartParamsError, [nil]);
1575     Len := Length(FUserName);
1576     if (Len = 0) then
1577     IBError(ibxeStartParamsError, [nil]);
1578     SRB.Add(isc_action_svc_add_user);
1579     SRB.Add(isc_spb_sec_username).AsString := FUserName;
1580     if FSQLRole <> '' then
1581     SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1582     SRB.Add(isc_spb_sec_userid).AsInteger := FUserID;
1583     SRB.Add(isc_spb_sec_groupid).AsInteger := FGroupID;
1584     SRB.Add(isc_spb_sec_password).AsString := FPassword;
1585     SRB.Add(isc_spb_sec_firstname).AsString := FFirstName;
1586     SRB.Add(isc_spb_sec_middlename).AsString := FMiddleName;
1587     SRB.Add(isc_spb_sec_lastname).AsString := FLastName;
1588     if HasAdminRole then
1589     SRB.Add(isc_spb_sec_admin).AsInteger := ord(FAdminRole);
1590     end;
1591    
1592     ActionDeleteUser:
1593     begin
1594     Len := Length(FUserName);
1595     if (Len = 0) then
1596     IBError(ibxeStartParamsError, [nil]);
1597     SRB.Add(isc_action_svc_delete_user);
1598     SRB.Add(isc_spb_sec_username).AsString := FUserName;
1599     if FSQLRole <> '' then
1600     SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1601     end;
1602    
1603     ActionModifyUser:
1604     begin
1605     Len := Length(FUserName);
1606     if (Len = 0) then
1607     IBError(ibxeStartParamsError, [nil]);
1608     SRB.Add(isc_action_svc_modify_user);
1609     SRB.Add(isc_spb_sec_username).AsString := FUserName;
1610     if FSQLRole <> '' then
1611     SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1612     if (ModifyUserId in FModifyParams) then
1613     SRB.Add(isc_spb_sec_userid).AsInteger := FUserID;
1614     if (ModifyGroupId in FModifyParams) then
1615     SRB.Add(isc_spb_sec_groupid).AsInteger := FGroupID;
1616     if (ModifyPassword in FModifyParams) then
1617     SRB.Add(isc_spb_sec_password).AsString := FPassword;
1618     if (ModifyFirstName in FModifyParams) then
1619     SRB.Add(isc_spb_sec_firstname).AsString := FFirstName;
1620     if (ModifyMiddleName in FModifyParams) then
1621     SRB.Add(isc_spb_sec_middlename).AsString := FMiddleName;
1622     if (ModifyLastName in FModifyParams) then
1623     SRB.Add(isc_spb_sec_lastname).AsString := FLastName;
1624     if (ModifyAdminRole in FModifyParams) and HasAdminRole then
1625     begin
1626     if FAdminRole then
1627     SRB.Add(isc_spb_sec_admin).AsInteger := 1
1628     else
1629     SRB.Add(isc_spb_sec_admin).AsInteger := 0;
1630     end;
1631     end;
1632     end;
1633     ClearParams;
1634     end;
1635    
1636    
1637     { TIBXValidationService }
1638    
1639     procedure TIBXValidationService.SetServiceStartOptions;
1640     var
1641     param: Integer;
1642     begin
1643     SRB.Add(isc_action_svc_repair);
1644     AddDBNAmeToSRB;
1645    
1646     param := 0;
1647     if (SweepDB in Options) then
1648     param := param or isc_spb_rpr_sweep_db;
1649     if (ValidateDB in Options) then
1650     param := param or isc_spb_rpr_validate_db;
1651    
1652     if (CheckDB in Options) then
1653     param := param or isc_spb_rpr_check_db;
1654     if (IgnoreChecksum in Options) then
1655     param := param or isc_spb_rpr_ignore_checksum;
1656     if (KillShadows in Options) then
1657     param := param or isc_spb_rpr_kill_shadows;
1658     if (MendDB in Options) then
1659     param := param or isc_spb_rpr_mend_db;
1660     if (ValidateFull in Options) then
1661     begin
1662     param := param or isc_spb_rpr_full;
1663     if not (MendDB in Options) then
1664     param := param or isc_spb_rpr_validate_db;
1665     end;
1666     if param > 0 then
1667     SRB.Add(isc_spb_options).AsInteger := param;
1668     end;
1669    
1670     { TIBXOnlineValidationService }
1671    
1672     procedure TIBXOnlineValidationService.SetServiceStartOptions;
1673     begin
1674     SRB.Add(isc_action_svc_validate);
1675     AddDBNameToSRB;
1676     if IncludeTables <> '' then
1677     SRB.Add(isc_spb_val_tab_incl).AsString := IncludeTables;
1678     if ExcludeTables <> '' then
1679     SRB.Add(isc_spb_val_tab_excl).AsString := ExcludeTables;
1680     if IncludeIndexes <> '' then
1681     SRB.Add(isc_spb_val_idx_incl).AsString := IncludeIndexes;
1682     if ExcludeIndexes <> '' then
1683     SRB.Add(isc_spb_val_idx_excl).AsString := ExcludeIndexes;
1684     if LockTimeout <> 0 then
1685     SRB.Add(isc_spb_val_lock_timeout).AsInteger := LockTimeout;
1686     end;
1687    
1688     constructor TIBXOnlineValidationService.Create(AOwner: TComponent);
1689     begin
1690     inherited Create(AOwner);
1691     FLockTimeout := 10;
1692     end;
1693    
1694     procedure TIBXOnlineValidationService.ServiceStart;
1695     begin
1696     CheckActive;
1697     {Firebird 2.5 and later}
1698     with ServicesConnection do
1699     if (ServerVersionNo[1] < 2) or
1700     ((ServerVersionNo[1] = 2) and (ServerVersionNo[2] < 5)) then
1701     IBError(ibxeServiceUnavailable,[]);
1702     inherited ServiceStart;
1703     end;
1704    
1705     { TIBXServerSideRestoreService }
1706    
1707     procedure TIBXServerSideRestoreService.SetBackupFiles(const Value: TStrings);
1708     begin
1709     FBackupFiles.Assign(Value);
1710     end;
1711    
1712     procedure TIBXServerSideRestoreService.SetArchiveSource;
1713     var i: integer;
1714     begin
1715     for i := 0 to FBackupFiles.Count - 1 do
1716     begin
1717     if (Trim(FBackupFiles[i]) = '') then continue;
1718     if (Pos('=', FBackupFiles[i]) <> 0) then {mbcs ok}
1719     begin
1720     SRB.Add(isc_spb_bkp_file).AsString := FBackupFiles.Names[i];
1721     SRB.Add(isc_spb_bkp_length).AsInteger := StrToInt(FBackupFiles.ValueFromIndex[i]);
1722     end
1723     else
1724     SRB.Add(isc_spb_bkp_file).AsString := FBackupFiles[i];
1725     end
1726     end;
1727    
1728     constructor TIBXServerSideRestoreService.Create(AOwner: TComponent);
1729     begin
1730     inherited Create(AOwner);
1731     FBackupFiles := TStringList.Create;
1732     end;
1733    
1734     destructor TIBXServerSideRestoreService.Destroy;
1735     begin
1736     if assigned(FBackupFiles) then FBackupFiles.Free;
1737     inherited Destroy;
1738     end;
1739    
1740     { TIBXRestoreService }
1741    
1742     procedure TIBXRestoreService.SetDatabaseFiles(const Value: TStrings);
1743     begin
1744     FDatabaseFiles.Assign(Value);
1745     end;
1746    
1747     procedure TIBXRestoreService.DatabaseNameChanged;
1748     begin
1749     inherited DatabaseNameChanged;
1750     DatabaseFiles.Clear;
1751     DatabaseFiles.Add(DatabaseName);
1752     end;
1753    
1754     procedure TIBXRestoreService.SetServiceStartOptions;
1755     var
1756     param: Integer;
1757     i: integer;
1758     begin
1759     SRB.Add(isc_action_svc_restore);
1760     inherited SetServiceStartOptions;
1761    
1762     param := 0;
1763     if (DeactivateIndexes in Options) then
1764     param := param or isc_spb_res_deactivate_idx;
1765     if (NoShadow in Options) then
1766     param := param or isc_spb_res_no_shadow;
1767     if (NoValidityCheck in Options) then
1768     param := param or isc_spb_res_no_validity;
1769     if (OneRelationAtATime in Options) then
1770     param := param or isc_spb_res_one_at_a_time;
1771     if (Replace in Options) then
1772     param := param or isc_spb_res_replace;
1773     if (CreateNewDB in Options) then
1774     param := param or isc_spb_res_create;
1775     if (UseAllSpace in Options) then
1776     param := param or isc_spb_res_use_all_space;
1777     if (RestoreMetaDataOnly in Options) then
1778     param := param or isc_spb_res_metadata_only;
1779     SRB.Add(isc_spb_options).AsInteger := param;
1780    
1781     if FPageSize > 0 then
1782     SRB.Add(isc_spb_res_page_size).AsInteger := FPageSize;
1783     if FPageBuffers > 0 then
1784     SRB.Add(isc_spb_res_buffers).AsInteger := FPageBuffers;
1785    
1786     SetArchiveSource;
1787    
1788     if FDatabaseFiles.Count > 0 then
1789     FDatabaseName := FDatabaseFiles[0]; {needed if an isc_sec_context error}
1790     for i := 0 to FDatabaseFiles.Count - 1 do
1791     begin
1792     if (Trim(FDatabaseFiles[i]) = '') then continue;
1793     if (Pos('=', FDatabaseFiles[i]) <> 0) then {mbcs ok}
1794     begin
1795     SRB.Add(isc_spb_dbname).AsString := FDatabaseFiles.Names[i];
1796     SRB.Add(isc_spb_res_length).AsInteger := StrToInt(FDatabaseFiles.ValueFromIndex[i]);
1797     end
1798     else
1799     SRB.Add(isc_spb_dbname).AsString := FDatabaseFiles[i];
1800     end;
1801     end;
1802    
1803     constructor TIBXRestoreService.Create(AOwner: TComponent);
1804     begin
1805     inherited Create(AOwner);
1806     FDatabaseFiles := TStringList.Create;
1807     Include (FOptions, CreateNewDB);
1808     end;
1809    
1810     destructor TIBXRestoreService.Destroy;
1811     begin
1812     if FDatabaseFiles <> nil then FDatabaseFiles.Free;
1813     inherited Destroy;
1814     end;
1815    
1816     { TIBXServerSideBackupService }
1817    
1818     procedure TIBXServerSideBackupService.SetBackupFile(const Value: TStrings);
1819     begin
1820     FBackupFiles.Assign(Value);
1821     end;
1822    
1823     procedure TIBXServerSideBackupService.SetBackupTarget;
1824     var i: integer;
1825     begin
1826     for i := 0 to FBackupFiles.Count - 1 do
1827     begin
1828     if (Trim(FBackupFiles[i]) = '') then
1829     continue;
1830     if (Pos('=', FBackupFiles[i]) <> 0) then
1831     begin {mbcs ok}
1832     SRB.Add(isc_spb_bkp_file).AsString := FBackupFiles.Names[i];
1833     SRB.Add(isc_spb_bkp_length).AsInteger := StrToInt(FBackupFiles.ValueFromIndex[i]);
1834     end
1835     else
1836     SRB.Add(isc_spb_bkp_file).AsString := FBackupFiles[i];
1837     end;
1838     end;
1839    
1840     constructor TIBXServerSideBackupService.Create(AOwner: TComponent);
1841     begin
1842     inherited Create(AOwner);
1843     FBackupFiles := TStringList.Create;
1844     end;
1845    
1846     destructor TIBXServerSideBackupService.Destroy;
1847     begin
1848     if assigned(FBackupFiles) then FBackupFiles.Free;
1849     inherited Destroy;
1850     end;
1851    
1852     { TIBXBackupService }
1853    
1854     procedure TIBXBackupService.SetServiceStartOptions;
1855     var
1856     param: Integer;
1857     begin
1858     SRB.Add(isc_action_svc_backup);
1859     AddDBNameToSRB;
1860     inherited SetServiceStartOptions;
1861    
1862     param := 0;
1863     if (IgnoreChecksums in Options) then
1864     param := param or isc_spb_bkp_ignore_checksums;
1865     if (IgnoreLimbo in Options) then
1866     param := param or isc_spb_bkp_ignore_limbo;
1867     if (MetadataOnly in Options) then
1868     param := param or isc_spb_bkp_metadata_only;
1869     if (NoGarbageCollection in Options) then
1870     param := param or isc_spb_bkp_no_garbage_collect;
1871     if (OldMetadataDesc in Options) then
1872     param := param or isc_spb_bkp_old_descriptions;
1873     if (NonTransportable in Options) then
1874     param := param or isc_spb_bkp_non_transportable;
1875     if (ConvertExtTables in Options) then
1876     param := param or isc_spb_bkp_convert;
1877     {Firebird 2.5 and later}
1878     with ServicesConnection do
1879     if (ServerVersionNo[1] > 2) or
1880     ((ServerVersionNo[1] = 2) and (ServerVersionNo[2] = 5)) then
1881     begin
1882     if (NoDBTriggers in Options) then
1883     param := param or isc_spb_bkp_no_triggers;
1884     end;
1885     SRB.Add(isc_spb_options).AsInteger := param;
1886    
1887     if FBlockingFactor > 0 then
1888     SRB.Add(isc_spb_bkp_factor).AsInteger := FBlockingFactor;
1889     SetBackupTarget;
1890     end;
1891    
1892     { TIBXBackupRestoreService }
1893    
1894     procedure TIBXBackupRestoreService.SetServiceStartOptions;
1895     var options: string;
1896     begin
1897     if Verbose then
1898     SRB.Add(isc_spb_verbose);
1899    
1900     with ServicesConnection do
1901     {Firebird 2.5.5 and later}
1902     if (ServerVersionNo[1] < 2) or
1903     ((ServerVersionNo[1] = 2) and ((ServerVersionNo[2] < 5) or
1904     ((ServerVersionNo[2] = 5) and (ServerVersionNo[3] < 5)))) then Exit;
1905    
1906     if StatisticsRequested <> [] then
1907     begin
1908     options := '';
1909     if bsTotalTime in StatisticsRequested then
1910     options += 'T';
1911     if bsTimeDelta in StatisticsRequested then
1912     options += 'D';
1913     if bsPageReads in StatisticsRequested then
1914     options += 'R';
1915     if bsPageWrites in StatisticsRequested then
1916     options += 'W';
1917     SRB.Add(isc_spb_bkp_stat).AsString := options;
1918     end;
1919     end;
1920    
1921    
1922     { TIBXStatisticalService }
1923    
1924     procedure TIBXStatisticalService.SetServiceStartOptions;
1925     var param: integer;
1926     begin
1927     SRB.Add(isc_action_svc_db_stats);
1928     AddDBNameToSRB;
1929    
1930     param := 0;
1931     if (DataPages in Options) then
1932     param := param or isc_spb_sts_data_pages;
1933     if (HeaderPages in Options) then
1934     param := param or isc_spb_sts_hdr_pages;
1935     if (IndexPages in Options) then
1936     param := param or isc_spb_sts_idx_pages;
1937     if (SystemRelations in Options) then
1938     param := param or isc_spb_sts_sys_relations;
1939     SRB.Add(isc_spb_options).AsInteger := param;
1940     end;
1941    
1942     { TIBXConfigService }
1943    
1944     procedure TIBXConfigService.ShutdownDatabase(Options: TDBShutdownMode;
1945     Wait: Integer);
1946     begin
1947     SRB.Add(isc_action_svc_properties);
1948     AddDBNameToSRB;
1949     if (Options = Forced) then
1950     SRB.Add(isc_spb_prp_shutdown_db).AsInteger := Wait
1951     else if (Options = DenyTransaction) then
1952     SRB.Add(isc_spb_prp_deny_new_transactions).AsInteger := Wait
1953     else
1954     SRB.Add(isc_spb_prp_deny_new_attachments).AsInteger := Wait;
1955     InternalServiceStart;
1956     while IsServiceRunning do;
1957     end;
1958    
1959     procedure TIBXConfigService.SetSweepInterval(Value: Integer);
1960     begin
1961     CheckActive;
1962     SRB.Add(isc_action_svc_properties);
1963     AddDBNameToSRB;
1964     SRB.Add(isc_spb_prp_sweep_interval).AsInteger := Value;
1965     InternalServiceStart;
1966     while IsServiceRunning do;
1967     end;
1968    
1969     procedure TIBXConfigService.SetDBSqlDialect(Value: Integer);
1970     begin
1971     SRB.Add(isc_action_svc_properties);
1972     AddDBNameToSRB;
1973     SRB.Add(isc_spb_prp_set_sql_dialect).AsInteger := Value;
1974     InternalServiceStart;
1975     while IsServiceRunning do;
1976     end;
1977    
1978     procedure TIBXConfigService.SetPageBuffers(Value: Integer);
1979     begin
1980     SRB.Add(isc_action_svc_properties);
1981     AddDBNameToSRB;
1982     SRB.Add(isc_spb_prp_page_buffers).AsInteger := Value;
1983     InternalServiceStart;
1984     while IsServiceRunning do;
1985     end;
1986    
1987     procedure TIBXConfigService.ActivateShadow;
1988     begin
1989     SRB.Add(isc_action_svc_properties);
1990     AddDBNameToSRB;
1991     SRB.Add(isc_spb_options).AsInteger := isc_spb_prp_activate;
1992     InternalServiceStart;
1993     while IsServiceRunning do;
1994     end;
1995    
1996     procedure TIBXConfigService.BringDatabaseOnline;
1997     begin
1998     SRB.Add(isc_action_svc_properties);
1999     AddDBNameToSRB;
2000     SRB.Add(isc_spb_options).AsInteger := isc_spb_prp_db_online;
2001     InternalServiceStart;
2002     while IsServiceRunning do;
2003     end;
2004    
2005     procedure TIBXConfigService.SetReserveSpace(Value: Boolean);
2006     begin
2007     SRB.Add(isc_action_svc_properties);
2008     AddDBNameToSRB;
2009     with SRB.Add(isc_spb_prp_reserve_space) do
2010     if Value then
2011     AsByte := isc_spb_prp_res
2012     else
2013     AsByte := isc_spb_prp_res_use_full;
2014     InternalServiceStart;
2015     while IsServiceRunning do;
2016     end;
2017    
2018     procedure TIBXConfigService.SetAsyncMode(Value: Boolean);
2019     begin
2020     SRB.Add(isc_action_svc_properties);
2021     AddDBNameToSRB;
2022     with SRB.Add(isc_spb_prp_write_mode) do
2023     if Value then
2024     AsByte := isc_spb_prp_wm_async
2025     else
2026     AsByte := isc_spb_prp_wm_sync;
2027     InternalServiceStart;
2028     while IsServiceRunning do;
2029     end;
2030    
2031     procedure TIBXConfigService.SetReadOnly(Value: Boolean);
2032     begin
2033     SRB.Add(isc_action_svc_properties);
2034     AddDBNameToSRB;
2035     with SRB.Add(isc_spb_prp_access_mode) do
2036     if Value then
2037     AsByte := isc_spb_prp_am_readonly
2038     else
2039     AsByte := isc_spb_prp_am_readwrite;
2040     InternalServiceStart;
2041     while IsServiceRunning do;
2042     end;
2043    
2044     procedure TIBXConfigService.SetNoLinger;
2045     begin
2046     SRB.Add(isc_action_svc_properties);
2047     AddDBNameToSRB;
2048     SRB.Add(isc_spb_options).AsInteger := isc_spb_prp_nolinger;
2049     InternalServiceStart;
2050     while IsServiceRunning do;
2051     end;
2052    
2053     { TIBXLogService }
2054    
2055     procedure TIBXLogService.SetServiceStartOptions;
2056     begin
2057     SRB.Add(isc_action_svc_get_ib_log);
2058     end;
2059    
2060     { TIBXControlAndQueryService }
2061    
2062     function TIBXControlAndQueryService.GetNextLine: String;
2063     var
2064     i: Integer;
2065     begin
2066     Result := '';
2067     if (FEof = True) then
2068     Exit;
2069     if not FServiceStarted then
2070     IBError(ibxeServiceNotStarted,[nil]);
2071    
2072     SRB.Add(isc_info_svc_line);
2073     InternalServiceQuery;
2074    
2075     for i := 0 to FServiceQueryResults.Count - 1 do
2076     with FServiceQueryResults[i] do
2077     begin
2078     case getItemType of
2079     isc_info_svc_line:
2080     Result := AsString;
2081     else
2082     IBError(ibxeOutputParsingError, [getItemType]);
2083     end;
2084     end;
2085     FEof := Result = '';
2086     Result := Trim(Result);
2087     DoOnGetNextLine(Result);
2088     if FEof then
2089     FServiceStarted := false;
2090     end;
2091    
2092     function TIBXControlAndQueryService.GetNextChunk: String;
2093     var
2094     i: Integer;
2095     begin
2096     if (FEof = True) then
2097     begin
2098     Result := '';
2099     exit;
2100     end;
2101     if not FServiceStarted then
2102     IBError(ibxeServiceNotStarted,[nil]);
2103    
2104     SRB.Add(isc_info_svc_to_eof);
2105     InternalServiceQuery;
2106    
2107     FEof := True;
2108     for i := 0 to FServiceQueryResults.Count - 1 do
2109     with FServiceQueryResults[i] do
2110     begin
2111     case getItemType of
2112     isc_info_svc_to_eof:
2113     Result := AsString;
2114    
2115     isc_info_truncated:
2116     FEof := False;
2117     else
2118     IBError(ibxeOutputParsingError, [getItemType]);
2119     end;
2120     end;
2121     if FEof then
2122     FServiceStarted := false;
2123     end;
2124    
2125     procedure TIBXControlAndQueryService.ServiceStart;
2126     begin
2127     FEof := false;
2128     FSendBytes := 0;
2129     inherited ServiceStart;
2130     FServiceStarted := true;
2131     end;
2132    
2133     function TIBXControlAndQueryService.ReceiveNextChunk(stream: TStream): integer;
2134     var
2135     i: Integer;
2136     TimeOut: boolean;
2137     begin
2138     Result := 0;
2139     TimeOut := false;
2140     if (FEof = True) then
2141     Exit;
2142     if not FServiceStarted then
2143     IBError(ibxeServiceNotStarted,[nil]);
2144    
2145     SQPB.Add(isc_info_svc_timeout).AsInteger := 1;
2146     SRB.Add(isc_info_svc_to_eof);
2147     InternalServiceQuery;
2148    
2149     FEof := True;
2150     for i := 0 to FServiceQueryResults.Count - 1 do
2151     with FServiceQueryResults[i] do
2152     begin
2153     case getItemType of
2154     isc_info_svc_to_eof:
2155     begin
2156     Result := CopyTo(stream,0);
2157     FEof := (Result = 0) and not TimeOut;
2158     end;
2159    
2160     isc_info_truncated:
2161     FEof := False;
2162    
2163     isc_info_svc_timeout:
2164     begin
2165     FEof := False;
2166     TimeOut := true;
2167     end
2168    
2169     else
2170     IBError(ibxeOutputParsingError, [getItemType]);
2171     end;
2172     end;
2173     if FEof then
2174     FServiceStarted := false;
2175     end;
2176    
2177     function TIBXControlAndQueryService.SendNextChunk(stream: TStream;
2178     var line: String): integer;
2179     var
2180     i: Integer;
2181     begin
2182     Result := 0;
2183     line := '';
2184     if (FEof = True) then
2185     Exit;
2186    
2187     if not FServiceStarted then
2188     IBError(ibxeServiceNotStarted,[nil]);
2189    
2190     SRB.Add(isc_info_svc_line);
2191     SRB.Add(isc_info_svc_stdin);
2192    
2193     SQPB.Add(isc_info_svc_timeout).AsInteger := 1;
2194     if FSendBytes > 0 then
2195     Result := SQPB.Add(isc_info_svc_line).CopyFrom(stream,FSendBytes);
2196     try
2197     InternalServiceQuery;
2198     except
2199     FSendBytes := 0;
2200     raise;
2201     end;
2202    
2203     FSendBytes := 0;
2204     for i := 0 to FServiceQueryResults.Count - 1 do
2205     with FServiceQueryResults[i] do
2206     begin
2207     case getItemType of
2208     isc_info_svc_line:
2209     line := AsString;
2210    
2211     isc_info_svc_stdin:
2212     FSendBytes := AsInteger;
2213    
2214     isc_info_svc_timeout,
2215     isc_info_data_not_ready:
2216     {ignore};
2217     else
2218     IBError(ibxeOutputParsingError, [getItemType]);
2219     end;
2220     end;
2221     FEOF := (FSendBytes = 0) and (line = '');
2222     if FEof then
2223     FServiceStarted := false;
2224     end;
2225    
2226     procedure TIBXControlAndQueryService.DoOnGetNextLine(Line: string);
2227     begin
2228     if assigned(FOnGetNextLine) then
2229     OnGetNextLine(self,Line);
2230     end;
2231    
2232     procedure TIBXControlAndQueryService.OnBeforeDisconnect(
2233     Sender: TIBXServicesConnection);
2234     var i: integer;
2235     begin
2236     inherited OnBeforeDisconnect(Sender);
2237     for i := 0 to FDataSets.Count - 1 do
2238     TDataSet(FDataSets[i]).Active := false;
2239     end;
2240    
2241     procedure TIBXControlAndQueryService.Notification(AComponent: TComponent;
2242     Operation: TOperation);
2243     begin
2244     inherited Notification(AComponent, Operation);
2245     if (Operation = opRemove) and (AComponent is TDataSet) then
2246     FDataSets.Remove(AComponent);
2247     end;
2248    
2249     procedure TIBXControlAndQueryService.RegisterDataSet(aDataSet: TDataSet);
2250     begin
2251     if FDataSets.IndexOf(aDataset) = -1 then
2252     begin
2253     FDataSets.Add(aDataSet);
2254     FreeNotification(ADataSet);
2255     end;
2256     end;
2257    
2258     procedure TIBXControlAndQueryService.UnRegisterDataSet(aDataSet: TDataSet);
2259     begin
2260     FDataSets.Remove(aDataSet);
2261     RemoveFreeNotification(aDataset);
2262     end;
2263    
2264     constructor TIBXControlAndQueryService.Create(aOwner: TComponent);
2265     begin
2266     inherited Create(aOwner);
2267     FDataSets := TList.Create;
2268     end;
2269    
2270     destructor TIBXControlAndQueryService.Destroy;
2271     begin
2272     inherited Destroy;
2273     if assigned(FDataSets) then FDataSets.Free;
2274     end;
2275    
2276     procedure TIBXControlAndQueryService.Execute(OutputLog: TStrings);
2277     begin
2278     ServiceStart;
2279     try
2280     while not Eof do
2281     if OutputLog <> nil then
2282     OutputLog.Add(GetNextLine)
2283     else
2284     GetNextLine;
2285     finally
2286     while IsServiceRunning do; {flush}
2287     end;
2288     end;
2289    
2290     { TIBXControlService }
2291    
2292     function TIBXControlService.GetIsServiceRunning: Boolean;
2293     begin
2294     Result := (ServicesConnection <> nil) and (ServicesConnection.Connected);
2295     if Result then
2296     begin
2297     SRB.Add(isc_info_svc_running);
2298     InternalServiceQuery(false);
2299     Result := (FServiceQueryResults <> nil) and (FServiceQueryResults.Count > 0) and
2300     (FServiceQueryResults[0].getItemType = isc_info_svc_running) and
2301     (FServiceQueryResults[0].AsInteger = 1);
2302     end;
2303     end;
2304    
2305     procedure TIBXControlService.HandleSecContextErr;
2306     begin
2307     FAction := scRaiseError;
2308     if MainThreadID = TThread.CurrentThread.ThreadID then
2309     CallSecContextException
2310     else
2311     TThread.Synchronize(TThread.CurrentThread,@CallSecContextException);
2312     end;
2313    
2314     procedure TIBXControlService.CallSecContextException;
2315     begin
2316     ServicesConnection.HandleSecContextException(self,FAction)
2317     end;
2318    
2319     procedure TIBXControlService.SetDatabaseName(AValue: string);
2320     begin
2321     if FDatabaseName = AValue then Exit;
2322     CheckServiceNotRunning;
2323     FDatabaseName := AValue;
2324     DatabaseNameChanged;
2325     end;
2326    
2327     procedure TIBXControlService.DatabaseNameChanged;
2328     begin
2329     //Do nothing
2330     end;
2331    
2332     procedure TIBXControlService.OnAfterConnect(Sender: TIBXServicesConnection;
2333     aDatabaseName: string);
2334     begin
2335     inherited OnAfterConnect(Sender,aDatabaseName);
2336     if aDatabaseName <> '' then
2337     DatabaseName := aDatabaseName;
2338     end;
2339    
2340     procedure TIBXControlService.AddDBNameToSRB;
2341     begin
2342     if FDatabaseName = '' then
2343     IBError(ibxeStartParamsError, [nil]);
2344     SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
2345     end;
2346    
2347     procedure TIBXControlService.CheckServiceNotRunning;
2348     begin
2349     if IsServiceRunning then
2350     IBError(ibxeServiceRunning,[nil]);
2351     end;
2352    
2353     procedure TIBXControlService.InternalServiceStart;
2354     var done: boolean;
2355     theError: EIBInterBaseError;
2356     begin
2357     if SRB = nil then
2358     IBError(ibxeStartParamsError, [nil]);
2359    
2360     FLastStartSRB := SRB;
2361     done := false;
2362     theError := nil;
2363     try
2364     repeat
2365     CheckActive;
2366     done := ServicesConnection.ServiceIntf.Start(SRB,false);
2367     if not done then
2368     begin
2369 tony 263 theError := EIBInterBaseError.Create(ServicesConnection.GetFirebirdAPI.GetStatus);
2370 tony 209 if theError.IBErrorCode = isc_sec_context then
2371     begin
2372     HandleSecContextErr;
2373     if FAction = scRaiseError then
2374     raise theError
2375     else
2376     begin
2377     theError.Free;
2378     FSRB := FLastStartSRB;
2379     end;
2380     end
2381     else
2382     raise theError;
2383     end;
2384     until done;
2385     finally
2386     FSRB := nil;
2387     end;
2388     if tfService in ServicesConnection.TraceFlags then
2389     MonitorHook.ServiceStart(Self);
2390     end;
2391    
2392     procedure TIBXControlService.DoServiceQuery;
2393     var done: boolean;
2394     LastSRB: ISRB;
2395     LastSQPB: ISQPB;
2396     theError: EIBInterBaseError;
2397     begin
2398     done := false;
2399     theError := nil;
2400     repeat
2401     LastSRB := SRB;
2402     LastSQPB := SQPB;
2403     inherited DoServiceQuery;
2404     done := FServiceQueryResults <> nil;
2405     if not done then
2406     begin
2407 tony 263 if ServicesConnection.GetFirebirdAPI.GetStatus.GetIBErrorCode = isc_sec_context then
2408 tony 209 begin
2409 tony 263 theError := EIBInterBaseError.Create(ServicesConnection.GetFirebirdAPI.GetStatus); {save exception}
2410 tony 209 HandleSecContextErr;
2411     if FAction = scReconnect then
2412     begin
2413     {Restart service}
2414     theError.Free;
2415     FSRB := FLastStartSRB;
2416     InternalServiceStart;
2417     FSRB := LastSRB;
2418     FSQPB := LastSQPB;
2419     end
2420     else
2421     raise theError;
2422     end
2423     else
2424     break; {Let the caller handle the error}
2425     end;
2426     until done;
2427     end;
2428    
2429     procedure TIBXControlService.SetServiceStartOptions;
2430     begin
2431     //Do nothing
2432     end;
2433    
2434     procedure TIBXControlService.ServiceStart;
2435     begin
2436     CheckActive;
2437     CheckServiceNotRunning;
2438     SetServiceStartOptions;
2439     InternalServiceStart;
2440     end;
2441    
2442     procedure TIBXControlService.Assign(Source: TPersistent);
2443     begin
2444     inherited Assign(Source);
2445     if Source is TIBXControlService then
2446     DatabaseName := TIBXControlService(Source).DatabaseName;
2447     end;
2448    
2449     { TConfigParams }
2450    
2451     constructor TConfigParams.Create;
2452     begin
2453     ConfigFileData := TConfigFileData.Create;
2454     ConfigFileParams := nil;
2455     end;
2456    
2457     destructor TConfigParams.Destroy;
2458     begin
2459     ConfigFileData.Free;
2460     ConfigFileParams := nil;
2461     inherited Destroy;
2462     end;
2463    
2464     { TConfigFileData }
2465    
2466     constructor TConfigFileData.Create;
2467     begin
2468     ConfigFileValue := nil;
2469     ConfigFileKey := nil;
2470     end;
2471    
2472     destructor TConfigFileData.Destroy;
2473     begin
2474     ConfigFileValue := nil;
2475     ConfigFileKey := nil;
2476     inherited Destroy;
2477     end;
2478    
2479     { TDatabaseInfo }
2480    
2481     constructor TDatabaseInfo.Create;
2482     begin
2483     DbName := nil;
2484     end;
2485    
2486     destructor TDatabaseInfo.Destroy;
2487     begin
2488     DbName := nil;
2489     inherited Destroy;
2490     end;
2491    
2492     { TIBXServerProperties }
2493    
2494     function TIBXServerProperties.GetConfigParams: TConfigParams;
2495     var i, j: Integer;
2496     begin
2497     CheckActive;
2498     if FConfigParams = nil then
2499     begin
2500     SRB.Add(isc_info_svc_get_config);
2501     SRB.Add(isc_info_svc_get_env);
2502     SRB.Add(isc_info_svc_get_env_lock);
2503     SRB.Add(isc_info_svc_get_env_msg);
2504     SRB.Add(isc_info_svc_user_dbpath);
2505    
2506     InternalServiceQuery;
2507    
2508     FConfigParams := TConfigParams.Create;
2509     for i := 0 to FServiceQueryResults.Count - 1 do
2510     with FServiceQueryResults[i] do
2511     begin
2512     case getItemType of
2513     isc_info_svc_get_config:
2514     begin
2515     SetLength (FConfigParams.ConfigFileData.ConfigFileValue, Count);
2516     SetLength (FConfigParams.ConfigFileData.ConfigFileKey, Count);
2517    
2518     for j := 0 to Count - 1 do
2519     begin
2520     FConfigParams.ConfigFileData.ConfigFileKey[j] := Items[j].getItemType;
2521     FConfigParams.ConfigFileData.ConfigFileValue[j] := Items[j].AsInteger;
2522     end;
2523     end;
2524    
2525     isc_info_svc_get_env:
2526     FConfigParams.BaseLocation := AsString;
2527    
2528     isc_info_svc_get_env_lock:
2529     FConfigParams.LockFileLocation := AsString;
2530    
2531     isc_info_svc_get_env_msg:
2532     FConfigParams.MessageFileLocation := AsString;
2533    
2534     isc_info_svc_user_dbpath:
2535     FConfigParams.SecurityDatabaseLocation := AsString;
2536    
2537     else
2538     IBError(ibxeOutputParsingError, [getItemType]);
2539     end;
2540     end;
2541     end;
2542     Result := FConfigParams;
2543     end;
2544    
2545     function TIBXServerProperties.GetDatabaseInfo: TDatabaseInfo;
2546     var i,j: Integer;
2547     begin
2548     if FDatabaseInfo = nil then
2549     begin
2550     SRB.Add(isc_info_svc_svr_db_info);
2551     InternalServiceQuery;
2552    
2553     FDatabaseInfo := TDatabaseInfo.Create;
2554     SetLength(FDatabaseInfo.DbName,0);
2555     for i := 0 to FServiceQueryResults.Count - 1 do
2556     with FServiceQueryResults[i] do
2557     begin
2558     case getItemType of
2559     isc_info_svc_svr_db_info:
2560     for j := 0 to FServiceQueryResults[i].Count - 1 do
2561     with FServiceQueryResults[i][j] do
2562     case getItemType of
2563     isc_spb_num_att:
2564     FDatabaseInfo.NoOfAttachments := AsInteger;
2565    
2566     isc_spb_num_db:
2567     FDatabaseInfo.NoOfDatabases := AsInteger;
2568    
2569     isc_spb_dbname:
2570     begin
2571     SetLength(FDatabaseInfo.DbName,length(FDatabaseInfo.DbName)+1);
2572     FDatabaseInfo.DbName[length(FDatabaseInfo.DbName)-1] := AsString;
2573     end;
2574     else
2575     IBError(ibxeOutputParsingError, [getItemType]);
2576     end;
2577     else
2578     IBError(ibxeOutputParsingError, [getItemType]);
2579     end;
2580     end;
2581     end;
2582     Result := FDatabaseInfo;
2583     end;
2584    
2585     function TIBXServerProperties.GetVersionInfo: TVersionInfo;
2586     var i : Integer;
2587     begin
2588     if FVersionInfo = nil then
2589     begin
2590     SRB.Add(isc_info_svc_version);
2591     SRB.Add(isc_info_svc_server_version);
2592     SRB.Add(isc_info_svc_implementation);
2593     InternalServiceQuery;
2594    
2595     FVersionInfo := TVersionInfo.Create;
2596     for i := 0 to FServiceQueryResults.Count - 1 do
2597     with FServiceQueryResults[i] do
2598     begin
2599     case getItemType of
2600     isc_info_svc_version:
2601     FVersionInfo.ServiceVersion := AsInteger;
2602     isc_info_svc_server_version:
2603     FVersionInfo.ServerVersion := AsString;
2604     isc_info_svc_implementation:
2605     FVersionInfo.ServerImplementation := AsString;
2606     else
2607     IBError(ibxeOutputParsingError, [getItemType]);
2608     end;
2609     end;
2610     end;
2611     Result := FVersionInfo;
2612     end;
2613    
2614     procedure TIBXServerProperties.Clear;
2615     begin
2616     inherited;
2617     if assigned(FDatabaseInfo) then FreeAndNil(FDatabaseInfo);
2618     if assigned(FVersionInfo) then FreeAndNil(FVersionInfo);
2619     if assigned(FConfigParams) then FreeAndNil(FConfigParams);
2620     end;
2621    
2622     { TIBXCustomService }
2623    
2624     procedure TIBXCustomService.CheckActive;
2625     begin
2626     if ServicesConnection = nil then
2627     IBError(ibxeServiceActive,[nil]);
2628     ServicesConnection.CheckActive;
2629     end;
2630    
2631     function TIBXCustomService.GetSQPB: ISQPB;
2632     begin
2633     CheckActive;
2634     if FSQPB = nil then
2635     FSQPB := ServicesConnection.ServiceIntf.AllocateSQPB;
2636     Result := FSQPB;
2637     end;
2638    
2639     function TIBXCustomService.GetSRB: ISRB;
2640     begin
2641     CheckActive;
2642     if FSRB = nil then
2643     FSRB := ServicesConnection.ServiceIntf.AllocateSRB;
2644     Result := FSRB;
2645     end;
2646    
2647     procedure TIBXCustomService.SetServicesConnection(AValue: TIBXServicesConnection
2648     );
2649     begin
2650     if FServicesConnection = AValue then Exit;
2651     if FServicesConnection <> nil then
2652     begin
2653     FServicesConnection.UnRegisterIntf(self);
2654     RemoveFreeNotification(FServicesConnection);
2655     end;
2656     Clear;
2657     FServicesConnection := AValue;
2658     if FServicesConnection <> nil then
2659     begin
2660     FServicesConnection.RegisterIntf(self);
2661     FreeNotification(FServicesConnection);
2662     end;
2663     end;
2664    
2665     procedure TIBXCustomService.OnBeforeDisconnect(Sender: TIBXServicesConnection);
2666     begin
2667     Clear;
2668     end;
2669    
2670     procedure TIBXCustomService.InternalServiceQuery(RaiseExceptionOnError: boolean
2671     );
2672     begin
2673     CheckActive;
2674     try
2675     FServiceQueryResults := nil;
2676     DoServiceQuery;
2677     if (FServiceQueryResults = nil) and RaiseExceptionOnError then
2678 tony 263 raise EIBInterBaseError.Create(ServicesConnection.GetFirebirdAPI.GetStatus);
2679 tony 209 finally
2680     FSQPB := nil;
2681     FSRB := nil;
2682     end;
2683     if tfService in ServicesConnection.TraceFlags then
2684     MonitorHook.ServiceQuery(Self);
2685     end;
2686    
2687     procedure TIBXCustomService.DoServiceQuery;
2688     begin
2689     FServiceQueryResults := ServicesConnection.ServiceIntf.Query(FSQPB,FSRB,false);
2690     end;
2691    
2692     procedure TIBXCustomService.Notification(AComponent: TComponent;
2693     Operation: TOperation);
2694     begin
2695     inherited Notification(AComponent, Operation);
2696     if (Operation = opRemove) and (AComponent = ServicesConnection) then
2697     ServicesConnection := nil;
2698     end;
2699    
2700     constructor TIBXCustomService.Create(AOwner: TComponent);
2701     begin
2702     inherited Create(AOwner);
2703     FSRB := nil;
2704     FServiceQueryResults := nil;
2705     FSQPB := nil;
2706     end;
2707    
2708     destructor TIBXCustomService.Destroy;
2709     begin
2710     if ServicesConnection <> nil then
2711     begin
2712     OnBeforeDisconnect(ServicesConnection);
2713     ServicesConnection := nil;
2714     end;
2715     inherited Destroy;
2716     end;
2717    
2718     procedure TIBXCustomService.Assign(Source: TPersistent);
2719     begin
2720     if Source is TIBXCustomService then
2721     ServicesConnection := TIBXCustomService(Source).ServicesConnection;
2722     end;
2723    
2724     procedure TIBXCustomService.Clear;
2725     begin
2726     FSRB := nil;
2727     FServiceQueryResults := nil;
2728     FSQPB := nil;
2729     end;
2730    
2731     procedure TIBXCustomService.OnAfterConnect(Sender: TIBXServicesConnection;
2732     aDatabaseName: string);
2733     begin
2734     //Do nothing
2735     end;
2736    
2737     { TIBXServicesConnection }
2738    
2739     procedure TIBXServicesConnection.SetParams(AValue: TStrings);
2740     begin
2741     FParams.Assign(AValue);
2742     end;
2743    
2744     procedure TIBXServicesConnection.SetPortNo(AValue: string);
2745     begin
2746     if FPortNo = AValue then Exit;
2747     Connected := false;
2748     FPortNo := AValue;
2749     FConnectString := MakeConnectString(FServerName,'service_mgr',FProtocol,FPortNo);
2750     end;
2751    
2752     procedure TIBXServicesConnection.CheckActive;
2753     begin
2754     if StreamedConnected and (not Connected) then
2755     Loaded;
2756     if FService = nil then
2757     IBError(ibxeServiceActive, [nil]);
2758     end;
2759    
2760     procedure TIBXServicesConnection.CheckInactive;
2761     begin
2762     if FService <> nil then
2763     IBError(ibxeServiceInActive, [nil]);
2764     end;
2765    
2766     procedure TIBXServicesConnection.CheckServerName;
2767     begin
2768     if (FServerName = '') and (FProtocol <> Local) then
2769     IBError(ibxeServerNameMissing, [nil]);
2770     end;
2771    
2772     {
2773     * GenerateSPB -
2774     * Given a string containing a textual representation
2775     * of the Service parameters, generate a service
2776     * parameter buffer, and return it .
2777     }
2778     function TIBXServicesConnection.GenerateSPB(sl: TStrings): ISPB;
2779     var
2780     i, j, SPBServerVal: UShort;
2781     param_name, param_value: String;
2782     begin
2783     { The SPB is initially empty, with the exception that
2784     the SPB version must be the first byte of the string.
2785     }
2786     Result := FirebirdAPI.AllocateSPB;
2787    
2788     { Iterate through the textual service parameters, constructing
2789     a SPB on-the-fly }
2790     if sl.Count > 0 then
2791     for i := 0 to sl.Count - 1 do
2792     begin
2793     { Get the parameter's name and value from the list,
2794     and make sure that the name is all lowercase with
2795     no leading 'isc_spb_' prefix }
2796     if (Trim(sl.Names[i]) = '') then continue;
2797     param_name := LowerCase(sl.Names[i]); {mbcs ok}
2798     param_value := sl.ValueFromIndex[i];
2799     if (Pos(SPBPrefix, param_name) = 1) then {mbcs ok}
2800     Delete(param_name, 1, Length(SPBPrefix));
2801     { We want to translate the parameter name to some integer
2802     value. We do this by scanning through a list of known
2803     service parameter names (SPBConstantNames, defined above). }
2804     SPBServerVal := 0;
2805     { Find the parameter }
2806     for j := 1 to isc_spb_last_spb_constant do
2807     if (param_name = SPBConstantNames[j]) then
2808     begin
2809     SPBServerVal := SPBConstantValues[j];
2810     break;
2811     end;
2812     case SPBServerVal of
2813     isc_spb_user_name,
2814     isc_spb_password,
2815     isc_spb_sql_role_name,
2816     isc_spb_expected_db:
2817     Result.Add(SPBServerVal).AsString := param_value;
2818     else
2819     begin
2820     if GetSPBConstName(SPBServerVal) <> '' then
2821     IBError(ibxeSPBConstantNotSupported,
2822     [GetSPBConstName(SPBServerVal)])
2823     else
2824     IBError(ibxeSPBConstantUnknown, [SPBServerVal]);
2825     end;
2826     end;
2827     end;
2828     end;
2829    
2830 tony 263 function TIBXServicesConnection.GetFirebirdAPI: IFirebirdAPI;
2831     var fblib: IFirebirdLibrary;
2832     begin
2833     if FFirebirdAPI = nil then
2834     begin
2835     if (csDesigning in ComponentState) or (Trim(FFirebirdLibraryPathName) = '') then
2836     FFirebirdAPI := IB.FirebirdAPI
2837     else
2838     begin
2839     fblib := IB.LoadFBLibrary(FFirebirdLibraryPathName);
2840     if assigned(fblib) then
2841     FFirebirdAPI := fblib.GetFirebirdAPI;
2842     end;
2843     end;
2844     Result := FFirebirdAPI;
2845     end;
2846    
2847 tony 209 function TIBXServicesConnection.GetServerVersionNo(index: integer): integer;
2848     begin
2849     CheckActive;
2850     if (index >= Low(FServerVersionNo)) and (index <= High(FServerVersionNo)) then
2851     Result := FServerVersionNo[index]
2852     else
2853     IBError(ibxeInfoBufferIndexError,[index]);
2854     end;
2855    
2856     function TIBXServicesConnection.GetSPBConstName(action: byte): string;
2857     var i: integer;
2858     begin
2859     Result := '';
2860     for i := Low(SPBConstantValues) to High(SPBConstantValues) do
2861     if SPBConstantValues[i] = action then
2862     begin
2863     Result := SPBConstantNames[i];
2864     break;
2865     end;
2866     end;
2867    
2868     procedure TIBXServicesConnection.HandleException(Sender: TObject);
2869     var aParent: TComponent;
2870     begin
2871     aParent := Owner;
2872     while aParent <> nil do
2873     begin
2874     if aParent is TCustomApplication then
2875     begin
2876     TCustomApplication(aParent).HandleException(Sender);
2877     Exit;
2878     end;
2879     aParent := aParent.Owner;
2880     end;
2881     SysUtils.ShowException(ExceptObject,ExceptAddr);
2882     end;
2883    
2884     procedure TIBXServicesConnection.HandleSecContextException(
2885     Sender: TIBXControlService; var action: TSecContextAction);
2886     var OldServiceIntf: IServiceManager;
2887     begin
2888     action := scRaiseError;
2889     if assigned(FOnSecurityContextException) then
2890     OnSecurityContextException(self,action);
2891    
2892     if action = scReconnect then
2893     begin
2894     FExpectedDB := Sender.DatabaseName;
2895     try
2896     OldServiceIntf := FService;
2897     Connected := false;
2898     while not Connected do
2899     begin
2900     try
2901     Connected := true;
2902     except
2903     on E:EIBClientError do
2904     begin
2905     action := scRaiseError;
2906     FService := OldServiceIntf;
2907     break;
2908     end;
2909     else
2910     HandleException(self);
2911     end;
2912     end;
2913     finally
2914     FExpectedDB := '';
2915     end;
2916     end;
2917     end;
2918    
2919     function TIBXServicesConnection.Login(var aServerName: string;
2920     LoginParams: TStrings): Boolean;
2921     var
2922     IndexOfUser, IndexOfPassword: Integer;
2923     Username, Password: String;
2924     ExtLoginParams: TStrings;
2925     begin
2926     if Assigned(FOnLogin) then
2927     begin
2928     Result := True;
2929     ExtLoginParams := TStringList.Create;
2930     try
2931     ExtLoginParams.Assign(Params);
2932     FOnLogin(Self, aServerName, ExtLoginParams);
2933     LoginParams.Assign (ExtLoginParams);
2934     finally
2935     ExtLoginParams.Free;
2936     end;
2937     end
2938     else
2939     if assigned(IBGUIInterface) then
2940     begin
2941     IndexOfUser := LoginParams.IndexOfName(GetSPBConstName(isc_spb_user_name));
2942     if IndexOfUser <> -1 then
2943     Username := LoginParams.ValueFromIndex[IndexOfUser]
2944     else
2945     UserName := '';
2946     IndexOfPassword :=LoginParams.IndexOfName(GetSPBConstName(isc_spb_password));
2947     if IndexOfPassword <> -1 then
2948     Password := LoginParams.ValueFromIndex[IndexOfPassword]
2949     else
2950     Password := '';
2951    
2952     result := IBGUIInterface.ServerLoginDialog(aServerName, Username, Password);
2953     if result then
2954     begin
2955     LoginParams.Values[GetSPBConstName(isc_spb_user_name)] := UserName;
2956     LoginParams.Values[GetSPBConstName(isc_spb_password)] := Password;
2957     end
2958     end
2959     else
2960     IBError(ibxeNoLoginDialog,[]);
2961     end;
2962    
2963     procedure TIBXServicesConnection.ParamsChanging(Sender: TObject);
2964     begin
2965     CheckInactive;
2966     end;
2967    
2968     procedure TIBXServicesConnection.SetConnectString(AValue: string);
2969     var aServiceName: AnsiString;
2970     aProtocol: TProtocolAll;
2971     begin
2972     if FConnectString = AValue then Exit;
2973     Connected := false;
2974     if not ParseConnectString(AValue,FServerName,aServiceName,aProtocol,FPortNo)
2975     or (aServiceName <> 'service_mgr') or (aProtocol = unknownProtocol) then
2976     IBError(ibxeBadConnectString, [nil]);
2977     FConnectString := AValue;
2978     FProtocol := TProtocol(aProtocol);
2979     end;
2980    
2981 tony 263 procedure TIBXServicesConnection.SetFirebirdLibraryPathName(AValue: TIBFileName
2982     );
2983     begin
2984     if FFirebirdLibraryPathName = AValue then Exit;
2985     FFirebirdLibraryPathName := AValue;
2986     Connected := false;
2987     FFirebirdAPI := nil;
2988     end;
2989    
2990 tony 209 procedure TIBXServicesConnection.SetProtocol(AValue: TProtocol);
2991     begin
2992     if FProtocol = AValue then Exit;
2993     Connected := false;
2994     FProtocol := AValue;
2995     FConnectString := MakeConnectString(FServerName,'service_mgr',FProtocol,FPortNo);
2996     end;
2997    
2998     procedure TIBXServicesConnection.SetServerName(AValue: string);
2999     begin
3000     if FServerName = AValue then Exit;
3001     Connected := false;
3002     FServerName := AValue;
3003     FConnectString := MakeConnectString(FServerName,'service_mgr',FProtocol,FPortNo);
3004     end;
3005    
3006     procedure TIBXServicesConnection.DoConnect;
3007    
3008     procedure ParseServerVersionNo;
3009     var Req: ISRB;
3010     Results: IServiceQueryResults;
3011     RegexObj: TRegExpr;
3012     s: string;
3013     begin
3014     Req := FService.AllocateSRB;
3015     Req.Add(isc_info_svc_server_version);
3016     Results := FService.Query(nil,Req);
3017     if (Results.Count = 1) and (Results[0].getItemType = isc_info_svc_server_version) then
3018     RegexObj := TRegExpr.Create;
3019     try
3020     {extact database file spec}
3021     RegexObj.ModifierG := false; {turn off greedy matches}
3022     RegexObj.Expression := '[A-Z][A-Z]-V([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+) .*';
3023     s := Results[0].AsString;
3024     if RegexObj.Exec(s) then
3025     begin
3026     FServerVersionNo[1] := StrToInt(RegexObj.Match[1]);
3027     FServerVersionNo[2] := StrToInt(RegexObj.Match[2]);
3028     FServerVersionNo[3] := StrToInt(RegexObj.Match[3]);
3029     FServerVersionNo[4] := StrToInt(RegexObj.Match[4]);
3030     end;
3031     finally
3032     RegexObj.Free;
3033     end;
3034     end;
3035    
3036     var aServerName: string;
3037     aProtocol: TProtocolAll;
3038     aPortNo: string;
3039     aDBName: string;
3040     TempSvcParams: TStrings;
3041     SPB: ISPB;
3042     PW: ISPBItem;
3043     i: integer;
3044     begin
3045     CheckInactive;
3046     CheckServerName;
3047    
3048     aServerName := FServerName;
3049     aProtocol := FProtocol;
3050     aPortNo := PortNo;
3051     aDBName := '';
3052    
3053     if FDatabase <> nil then
3054     {Get Connect String from Database Connect String}
3055     begin
3056 tony 263 FFirebirdAPI := FDatabase.FirebirdAPI;
3057 tony 209 if ParseConnectString(FDatabase.Attachment.GetConnectString,aServerName,aDBName,aProtocol,aPortNo) and
3058     (aProtocol = Local) and
3059     (FDatabase.Attachment.GetRemoteProtocol <> '') then
3060     begin
3061     {Use loopback if database does not use embedded server}
3062     aServerName := 'Localhost';
3063     aProtocol := TCP;
3064     end;
3065     end;
3066    
3067     TempSvcParams := TStringList.Create;
3068     try
3069     TempSvcParams.Assign(FParams);
3070     if LoginPrompt and not Login(aServerName,TempSvcParams) then
3071     IBError(ibxeOperationCancelled, [nil]);
3072    
3073     {Use of non-default security database}
3074     if FExpectedDB <> '' then {set when handling an isc_sec_context exception}
3075     TempSvcParams.Values['expected_db'] := FExpectedDB
3076     else
3077     if (FDatabase <> nil) and (FDatabase.Attachment.GetSecurityDatabase <> 'Default')
3078     and (aDBName <> '') then
3079     {Connect using database using non-default security database}
3080     TempSvcParams.Values['expected_db'] := aDBName;
3081     SPB := GenerateSPB(TempSvcParams);
3082     finally
3083     TempSvcParams.Free;
3084     end;
3085    
3086     FService := FirebirdAPI.GetServiceManager(aServerName,aPortNo,aProtocol,SPB);
3087 tony 231 FServername := aServerName;
3088     FProtocol := aProtocol;
3089     FPortNo := aPortNo;
3090     FConnectString := MakeConnectString(FServerName,'service_mgr',FProtocol,FPortNo);
3091 tony 209 PW := FService.getSPB.Find(isc_spb_password);
3092     if PW <> nil then PW.AsString := 'xxxxxxxx'; {Hide password}
3093    
3094     ParseServerVersionNo;
3095    
3096     for i := low(FIBXServices) to high(FIBXServices) do
3097     FIBXServices[i].OnAfterConnect(self,aDBName);
3098    
3099     if tfService in TraceFlags then
3100     MonitorHook.ServiceAttach(Self);
3101     end;
3102    
3103     procedure TIBXServicesConnection.DoDisconnect;
3104     var i: integer;
3105     begin
3106     CheckActive;
3107     for i := 0 to Length(FIBXServices) - 1 do
3108     FIBXServices[i].OnBeforeDisconnect(self);
3109     FService := nil;
3110     if tfService in TraceFlags then
3111     MonitorHook.ServiceDetach(Self);
3112     end;
3113    
3114     function TIBXServicesConnection.GetConnected: Boolean;
3115     begin
3116     Result := FService <> nil;
3117     end;
3118    
3119     function TIBXServicesConnection.GetDataset(Index: longint): TDataset;
3120     begin
3121     Result := inherited GetDataset(Index);
3122     end;
3123    
3124     function TIBXServicesConnection.GetDataSetCount: Longint;
3125     begin
3126     Result := inherited GetDataSetCount;
3127     end;
3128    
3129     procedure TIBXServicesConnection.ReadState(Reader: TReader);
3130     begin
3131     FParams.Clear;
3132     inherited ReadState(Reader);
3133     end;
3134    
3135     procedure TIBXServicesConnection.RegisterIntf(intf: IIBXServicesClient);
3136     begin
3137     Setlength(FIBXServices,Length(FIBXServices) + 1);
3138     FIBXServices[Length(FIBXServices)-1] := intf;
3139     end;
3140    
3141     procedure TIBXServicesConnection.UnRegisterIntf(intf: IIBXServicesClient);
3142     var i, j: integer;
3143     begin
3144     for i := length(FIBXServices) - 1 downto 0 do
3145     if FIBXServices[i] = intf then
3146     begin
3147     for j := i + 1 to length(FIBXServices) - 1 do
3148     FIBXServices[j-1] := FIBXServices[j];
3149     SetLength(FIBXServices,Length(FIBXServices)-1);
3150     break;
3151     end;
3152     end;
3153    
3154     constructor TIBXServicesConnection.Create(AOwner: TComponent);
3155     begin
3156     inherited Create(AOwner);
3157     FServerName := '';
3158     FParams := TStringList.Create;
3159     Setlength(FIBXServices,0);
3160     TStringList(FParams).OnChanging := @ParamsChanging;
3161     FService := nil;
3162     FProtocol := Local;
3163     LoginPrompt := true;
3164     if (AOwner <> nil) and
3165     (AOwner is TCustomApplication) and
3166     TCustomApplication(AOwner).ConsoleApplication then
3167     LoginPrompt := false;
3168     end;
3169    
3170     destructor TIBXServicesConnection.Destroy;
3171     begin
3172     inherited Destroy;
3173     Setlength(FIBXServices,0);
3174     if assigned(FParams) then FParams.Free;
3175 tony 263 FFirebirdAPI := nil;
3176 tony 209 end;
3177    
3178     procedure TIBXServicesConnection.ConnectUsing(aDatabase: TIBDatabase);
3179     begin
3180     if not aDatabase.Connected then
3181     IBError(ibxeDatabaseNotConnected,[nil]);
3182     Connected := false;
3183     FDatabase := aDatabase;
3184     try
3185     Connected := true;
3186     finally
3187     FDatabase := nil;
3188     end;
3189     end;
3190    
3191     procedure TIBXServicesConnection.SetDBParams(DBParams: TStrings);
3192     var i: integer;
3193     j: integer;
3194     k: integer;
3195     ParamName: string;
3196     begin
3197     Params.Clear;
3198     for i := 0 to DBParams.Count - 1 do
3199     begin
3200     ParamName := DBParams[i];
3201     k := Pos('=',ParamName);
3202     if k > 0 then system.Delete(ParamName,k,Length(ParamName)-k+1);
3203     for j := 1 to isc_spb_last_spb_constant do
3204 tony 221 if CompareText(ParamName,SPBConstantNames[j]) = 0 then
3205 tony 209 begin
3206     Params.Add(DBParams[i]);
3207     break;
3208     end;
3209     end;
3210     end;
3211    
3212     end.
3213