ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/nongui/IBXServices.pas
Revision: 266
Committed: Wed Dec 26 18:34:32 2018 UTC (5 years, 4 months ago) by tony
Content type: text/x-pascal
File size: 91377 byte(s)
Log Message:
Fixes Merged

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