daemonapp.pp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374
  1. {
  2. $Id: header,v 1.1 2000/07/13 06:33:45 michael Exp $
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit daemonapp;
  12. {$mode objfpc}{$H+}
  13. interface
  14. uses
  15. Custapp, Classes, SysUtils, eventlog, rtlconsts;
  16. Type
  17. TCustomDaemon = Class;
  18. TDaemonController = Class;
  19. TDaemonEvent = procedure(Sender: TCustomDaemon) of object;
  20. TDaemonOKEvent = procedure(Sender: TCustomDaemon; var OK: Boolean) of object;
  21. TDaemonOption = (doAllowStop,doAllowPause,doInteractive);
  22. TDaemonOptions = Set of TDaemonOption;
  23. TDaemonRunMode = (drmUnknown,drmInstall,drmUninstall,drmRun);
  24. { TCustomDaemonDescription }
  25. TDaemonDef = Class;
  26. TCurrentStatus =
  27. (csStopped, csStartPending, csStopPending, csRunning,
  28. csContinuePending, csPausePending, csPaused);
  29. TCustomDaemon = Class(TDataModule)
  30. private
  31. FController: TDaemonController;
  32. FDaemonDef: TDaemonDef;
  33. FThread : TThread;
  34. FStatus: TCurrentStatus;
  35. function GetLogger: TEventLog;
  36. procedure SetStatus(const AValue: TCurrentStatus);
  37. Protected
  38. Function Start : Boolean; virtual;
  39. Function Stop : Boolean; virtual;
  40. Function Pause : Boolean; virtual;
  41. Function Continue : Boolean; virtual;
  42. Function Execute : Boolean; virtual;
  43. Function ShutDown : Boolean; virtual;
  44. Function Install : Boolean; virtual;
  45. Function UnInstall: boolean; virtual;
  46. Function HandleCustomCode(ACode : DWord) : Boolean; Virtual;
  47. Public
  48. Procedure LogMessage(Msg : String);
  49. Procedure ReportStatus;
  50. // Filled in at runtime by controller
  51. Property Definition : TDaemonDef Read FDaemonDef;
  52. Property DaemonThread : TThread Read FThread;
  53. Property Controller : TDaemonController Read FController;
  54. Property Status : TCurrentStatus Read FStatus Write SetStatus;
  55. Property Logger : TEventLog Read GetLogger;
  56. end;
  57. TCustomDaemonClass = Class of TCustomDaemon;
  58. { TDaemon }
  59. TCustomControlCodeEvent = Procedure(Sender : TCustomDaemon; ACode : DWord; Var Handled : Boolean) of object;
  60. TDaemon = Class(TCustomDaemon)
  61. private
  62. FAfterInstall: TDaemonEvent;
  63. FAfterUnInstall: TDaemonEvent;
  64. FBeforeInstall: TDaemonEvent;
  65. FBeforeUnInstall: TDaemonEvent;
  66. FOnContinue: TDaemonOKEvent;
  67. FOnCustomControl: TCustomControlCodeEvent;
  68. FOnExecute: TDaemonEvent;
  69. FOnPause: TDaemonOKEvent;
  70. FOnShutDown: TDaemonEvent;
  71. FOnStart: TDaemonOKEvent;
  72. FOnStop: TDaemonOKEvent;
  73. Protected
  74. Function Start : Boolean; override;
  75. Function Stop : Boolean; override;
  76. Function Pause : Boolean; override;
  77. Function Continue : Boolean; override;
  78. Function Execute : Boolean; override;
  79. Function ShutDown : Boolean; override;
  80. Function Install : Boolean; override;
  81. Function UnInstall: boolean; override;
  82. Function HandleCustomCode(ACode : DWord) : Boolean; Override;
  83. Public
  84. Property Definition;
  85. Property Status;
  86. Published
  87. Property OnStart : TDaemonOKEvent Read FOnStart Write FOnStart;
  88. Property OnStop : TDaemonOKEvent Read FOnStop Write FOnStop;
  89. Property OnPause : TDaemonOKEvent Read FOnPause Write FOnPause;
  90. Property OnContinue : TDaemonOKEvent Read FOnContinue Write FOnContinue;
  91. Property OnShutDown : TDaemonEvent Read FOnShutDown Write FOnShutDown;
  92. Property OnExecute : TDaemonEvent Read FOnExecute Write FOnExecute;
  93. Property BeforeInstall : TDaemonEvent Read FBeforeInstall Write FBeforeInstall;
  94. Property AfterInstall : TDaemonEvent Read FAfterInstall Write FAfterInstall;
  95. Property BeforeUnInstall : TDaemonEvent Read FBeforeUnInstall Write FBeforeUnInstall;
  96. Property AfterUnInstall : TDaemonEvent Read FAfterUnInstall Write FAfterUnInstall;
  97. Property OnControlCode : TCustomControlCodeEvent Read FOnCustomControl Write FOnCustomControl;
  98. end;
  99. { TDaemonController }
  100. TDaemonController = Class(TComponent)
  101. Private
  102. FDaemon : TCustomDaemon;
  103. FLastStatus: TCurrentStatus;
  104. FSysData : TObject;
  105. FParams : TStrings;
  106. FCheckPoint : DWord;
  107. procedure ThreadTerminated(Sender: TObject);
  108. Public
  109. Constructor Create(AOwner : TComponent); override;
  110. Destructor Destroy; override;
  111. Procedure StartService; virtual;
  112. Procedure Main(Argc : DWord; Args : PPChar); Virtual;
  113. Procedure Controller(ControlCode,EventType : DWord; EventData : Pointer); Virtual;
  114. Function ReportStatus : Boolean; virtual;
  115. Property Daemon : TCustomDaemon Read FDaemon;
  116. Property Params : TStrings Read FParams;
  117. Property LastStatus : TCurrentStatus Read FLastStatus;
  118. Property CheckPoint : DWord;
  119. end;
  120. TDaemonClass = Class of TDaemon;
  121. { Windows specific service registration types }
  122. TServiceType = (stWin32, stDevice, stFileSystem);
  123. TErrorSeverity = (esIgnore, esNormal, esSevere, esCritical);
  124. TStartType = (stBoot, stSystem, stAuto, stManual, stDisabled);
  125. { TDependency }
  126. TDependency = class(TCollectionItem)
  127. private
  128. FName: String;
  129. FIsGroup: Boolean;
  130. protected
  131. function GetDisplayName: string; override;
  132. Public
  133. Procedure Assign(Source : TPersistent); override;
  134. published
  135. property Name: String read FName write FName;
  136. property IsGroup: Boolean read FIsGroup write FIsGroup;
  137. end;
  138. { TDependencies }
  139. TDependencies = class(TCollection)
  140. private
  141. FOwner: TPersistent;
  142. function GetItem(Index: Integer): TDependency;
  143. procedure SetItem(Index: Integer; Value: TDependency);
  144. protected
  145. function GetOwner: TPersistent; override;
  146. public
  147. constructor Create(AOwner: TPersistent);
  148. property Items[Index: Integer]: TDependency read GetItem write SetItem; default;
  149. end;
  150. { TWinBindings }
  151. TWinBindings = class(TPersistent)
  152. private
  153. FDependencies: TDependencies;
  154. FErrCode: DWord;
  155. FErrorSeverity: TErrorSeverity;
  156. FLoadGroup: String;
  157. FPassWord: String;
  158. FServiceType: TServiceType;
  159. FStartType: TStartType;
  160. FTagID: DWord;
  161. FUserName: String;
  162. FWaitHint: Integer;
  163. FWin32ErrorCode: DWord;
  164. procedure SetDependencies(const AValue: TDependencies);
  165. Public
  166. Constructor Create;
  167. Destructor Destroy; override;
  168. Procedure Assign(Source : TPersistent); override;
  169. property ErrCode: DWord read FErrCode write FErrCode;
  170. property Win32ErrCode: DWord read FWin32ErrorCode write FWin32ErrorCode;
  171. Published
  172. Property Dependencies : TDependencies Read FDependencies Write SetDependencies;
  173. Property GroupName : String Read FLoadGroup Write FLoadGroup;
  174. Property Password : String Read FPassWord Write FPassword;
  175. Property UserName : String Read FUserName Write FUserName;
  176. Property StartType : TStartType Read FStartType Write FStartType;
  177. Property WaitHint : Integer Read FWaitHint Write FWaitHint;
  178. Property IDTag : DWord Read FTagID Write FTagID;
  179. Property ServiceType : TServiceType Read FServiceType Write FServiceType;
  180. Property ErrorSeverity : TErrorSeverity Read FErrorSeverity Write FErrorSeverity;
  181. end;
  182. { TDaemonDef }
  183. TDaemonDef = Class(TCollectionItem)
  184. private
  185. FDaemonClass: TCustomDaemonClass;
  186. FDaemonClassName: String;
  187. FDescription: String;
  188. FDisplayName: String;
  189. FEnabled: Boolean;
  190. FInstance: TCustomDaemon;
  191. FLogStatusReport: Boolean;
  192. FName: String;
  193. FOnCreateInstance: TNotifyEvent;
  194. FOptions: TDaemonOptions;
  195. FServiceName: String;
  196. FWinBindings: TWinBindings;
  197. procedure SetName(const AValue: String);
  198. procedure SetWinBindings(const AValue: TWinBindings);
  199. Protected
  200. function GetDisplayName: string; override;
  201. Public
  202. Constructor Create(ACollection : TCollection); override;
  203. Destructor Destroy; override;
  204. Property DaemonClass : TCustomDaemonClass read FDaemonClass;
  205. Property Instance : TCustomDaemon Read FInstance Write FInstance;
  206. Published
  207. Property DaemonClassName : String Read FDaemonClassName Write FDaemonClassName;
  208. Property Name : String Read FName Write SetName;
  209. Property DisplayName : String Read FDisplayName Write FDisplayName;
  210. Property Options : TDaemonOptions Read FOptions Write FOptions;
  211. Property Enabled : Boolean Read FEnabled Write FEnabled default true;
  212. Property WinBindings : TWinBindings Read FWinBindings Write SetWinBindings;
  213. Property OnCreateInstance : TNotifyEvent Read FOnCreateInstance Write FOnCreateInstance;
  214. Property LogStatusReport : Boolean Read FLogStatusReport Write FLogStatusReport;
  215. end;
  216. { TDaemonDefs }
  217. TDaemonDefs = Class(TCollection)
  218. FOwner : TPersistent;
  219. private
  220. function GetDaemonDef(Index : Integer): TDaemonDef;
  221. procedure SetDaemonDef(Index : Integer; const AValue: TDaemonDef);
  222. Protected
  223. Procedure BindClasses;
  224. Function GetOwner : TPersistent; override;
  225. Public
  226. Constructor Create(AOwner : TPersistent; AClass : TCollectionItemClass);
  227. Function IndexOfDaemonDef(Const DaemonName : String) : Integer;
  228. Function FindDaemonDef(Const DaemonName : String) : TDaemonDef;
  229. Function DaemonDefByName(Const DaemonName : String) : TDaemonDef;
  230. Property Daemons[Index : Integer] : TDaemonDef Read GetDaemonDef Write SetDaemonDef; default;
  231. end;
  232. { TCustomDaemonMapper }
  233. TCustomDaemonMapper = Class(TComponent)
  234. private
  235. FDaemonDefs: TDaemonDefs;
  236. FOnCreate: TNotifyEvent;
  237. FOnDestroy: TNotifyEvent;
  238. FOnInstall: TNotifyEvent;
  239. FOnRun: TNotifyEvent;
  240. FOnUnInStall: TNotifyEvent;
  241. procedure SetDaemonDefs(const AValue: TDaemonDefs);
  242. Protected
  243. Procedure CreateDefs; virtual;
  244. Procedure DoOnCreate; virtual;
  245. Procedure DoOnDestroy; virtual;
  246. Procedure DoOnInstall; virtual;
  247. Procedure DoOnUnInstall; virtual;
  248. Procedure DoOnRun; virtual;
  249. Public
  250. Constructor Create(AOwner : TComponent); override;
  251. Destructor Destroy; override;
  252. Published
  253. Property DaemonDefs : TDaemonDefs Read FDaemonDefs Write SetDaemonDefs;
  254. Property OnCreate : TNotifyEvent Read FOnCreate Write FOnCreate;
  255. Property OnDestroy : TNotifyEvent Read FOnDestroy Write FOnDestroy;
  256. Property OnRun : TNotifyEvent Read FOnRun Write FOnRun;
  257. Property OnInstall : TNotifyEvent Read FOnInstall Write FOnInstall;
  258. Property OnUnInstall : TNotifyEvent Read FOnUnInStall Write FOnUninStall;
  259. end;
  260. { TDaemonMapper }
  261. TDaemonMapper = Class(TCustomDaemonMapper)
  262. Constructor Create(AOwner : TComponent); override;
  263. Constructor CreateNew(AOwner : TComponent; Dummy : Integer = 0);
  264. end;
  265. TCustomDaemonMapperClass = Class of TCustomDaemonMapper;
  266. { TDaemonThread }
  267. TDaemonThread = Class(TThread)
  268. Private
  269. FDaemon : TCustomDaemon;
  270. Protected
  271. procedure StartServiceExecute; virtual;
  272. procedure HandleControlCode(ACode : DWord); virtual;
  273. Public
  274. Constructor Create(ADaemon : TCustomDaemon);
  275. Procedure Execute; override;
  276. Procedure CheckControlMessage(WaitForMessage : Boolean);
  277. Function StopDaemon : Boolean; virtual;
  278. Function PauseDaemon : Boolean; virtual;
  279. Function ContinueDaemon : Boolean; virtual;
  280. Function ShutDownDaemon : Boolean; virtual;
  281. Function InterrogateDaemon : Boolean; virtual;
  282. Property Daemon : TCustomDaemon Read FDaemon;
  283. end;
  284. { TCustomDaemonApplication }
  285. TGuiLoopEvent = Procedure Of Object;
  286. TCustomDaemonApplication = Class(TCustomApplication)
  287. private
  288. FGUIHandle: THandle;
  289. FGUIMainLoop: TGuiLoopEvent;
  290. FLogger: TEventLog;
  291. FMapper : TCustomDaemonMapper;
  292. FOnRun: TNotifyEvent;
  293. FRunMode: TDaemonRunMode;
  294. FSysData: TObject;
  295. FControllerCount : Integer;
  296. procedure BindDaemonDefs(AMapper: TCustomDaemonMapper);
  297. function InstallRun: Boolean;
  298. procedure SysInstallDaemon(Daemon: TCustomDaemon);
  299. procedure SysUnInstallDaemon(Daemon: TCustomDaemon);
  300. function UnInstallRun: Boolean;
  301. function RunDaemonsRun: Boolean;
  302. Procedure Main(Argc : DWord; Args : PPchar);
  303. Function RunGUIloop(P : Pointer) : integer;
  304. Protected
  305. // OS (System) dependent calls
  306. Procedure SysStartUnInstallDaemons;
  307. Procedure SysEndUnInstallDaemons;
  308. Procedure SysStartInstallDaemons;
  309. Procedure SysEndInstallDaemons;
  310. Procedure SysStartRunDaemons;
  311. Procedure SysEndRunDaemons;
  312. // Customizable behaviour
  313. procedure CreateDaemonController(Var AController : TDaemonController); virtual;
  314. Procedure CreateServiceMapper(Var AMapper : TCustomDaemonMapper); virtual;
  315. Procedure CreateDaemonInstance(Var ADaemon : TCustomDaemon; DaemonDef : TDaemonDef); virtual;
  316. Procedure RemoveController(AController : TDaemonController); virtual;
  317. procedure SetupLogger;
  318. procedure StopLogger;
  319. Procedure DoRun; override;
  320. Property OnRun : TNotifyEvent Read FOnRun Write FOnRun;
  321. Property SysData : TObject Read FSysData Write FSysData;
  322. Public
  323. Procedure ShowException(E : Exception); override;
  324. Function CreateDaemon(DaemonDef : TDaemonDef) : TCustomDaemon;
  325. Procedure StopDaemons(Force : Boolean);
  326. procedure InstallDaemons;
  327. procedure RunDaemons;
  328. procedure UnInstallDaemons;
  329. procedure CreateForm(InstanceClass: TComponentClass; var Reference); virtual;
  330. Property Logger : TEventLog Read FLogger;
  331. Property GUIMainLoop : TGuiLoopEvent Read FGUIMainLoop Write FGuiMainLoop;
  332. Property GuiHandle : THandle Read FGUIHandle Write FGUIHandle;
  333. Property RunMode : TDaemonRunMode Read FRunMode;
  334. end;
  335. TCustomDaemonApplicationClass = Class of TCustomDaemonApplication;
  336. TDaemonApplication = Class(TCustomDaemonApplication);
  337. EDaemon = Class(Exception);
  338. Function Application : TCustomDaemonApplication;
  339. Procedure RegisterDaemonMapper(AMapperClass : TCustomDaemonMapperClass);
  340. Procedure RegisterDaemonClass(AClass : TCustomDaemonClass);
  341. Procedure RegisterDaemonApplicationClass(AClass : TCustomDaemonApplicationClass);
  342. Procedure DaemonError(Msg : String);
  343. Procedure DaemonError(Fmt : String; Args : Array of const);
  344. Resourcestring
  345. SErrNoServiceMapper = 'No daemon mapper class registered.';
  346. SErrOnlyOneMapperAllowed = 'Not changing daemon mapper class %s with %s: Only 1 mapper allowed.';
  347. SErrNothingToDo = 'Options do not allow determining what needs to be done.';
  348. SErrDuplicateName = 'Duplicate daemon name: %s';
  349. SErrUnknownDaemonClass = 'Unknown daemon class name: %s';
  350. SErrDaemonStartFailed = 'Failed to start daemon %s : %s';
  351. SDaemonStatus = 'Daemon %s current status: %s';
  352. SControlFailed = 'Control code %s handling failed: %s';
  353. SCustomCode = '[Custom code %d]';
  354. SErrServiceManagerStartFailed = 'Failed to start service manager: %s';
  355. SErrNoDaemonForStatus = '%s: No daemon for status report';
  356. SErrNoDaemonDefForStatus = '%s: No daemon definition for status report';
  357. SErrWindowClass = 'Could not register window class';
  358. SErrApplicationAlreadyCreated = 'An application instance of class %s was already created.';
  359. { $define svcdebug}
  360. {$ifdef svcdebug}
  361. Procedure DebugLog(Msg : String);
  362. {$endif}
  363. Var
  364. CurrentStatusNames : Array[TCurrentStatus] of string =
  365. ('Stopped', 'Start Pending', 'Stop Pending', 'Running',
  366. 'Continue Pending', 'Pause Pending', 'Paused');
  367. SStatus : Array[1..5] of string =
  368. ('Stop','Pause','Continue','Interrogate','Shutdown');
  369. DefaultDaemonOptions : TDaemonOptions = [doAllowStop,doAllowPause];
  370. implementation
  371. // This must come first, so a uses clause can be added.
  372. {$i daemonapp.inc}
  373. Var
  374. AppInstance : TCustomDaemonApplication;
  375. MapperClass : TCustomDaemonMapperClass;
  376. DesignMapper : TCustomDaemonMapper;
  377. DaemonClasses : TStringList;
  378. AppClass : TCustomDaemonApplicationClass;
  379. {$ifdef svcdebug}
  380. Var
  381. FL : Text;
  382. LCS : TRTLCriticalSection;
  383. Procedure StartLog;
  384. begin
  385. {$ifdef win32}
  386. Assign(FL,'c:\service.log');
  387. {$else}
  388. Assign(FL,'/tmp/service.log');
  389. {$endif}
  390. Rewrite(FL);
  391. InitCriticalSection(LCS);
  392. DebugLog('Start logging');
  393. end;
  394. Procedure DebugLog(Msg : String);
  395. begin
  396. EnterCriticalSection(LCS);
  397. try
  398. Writeln(FL,Msg);
  399. Flush(FL);
  400. Finally
  401. LeaveCriticalSection(LCS);
  402. end;
  403. end;
  404. Procedure EndLog;
  405. begin
  406. DebugLog('Done logging');
  407. Close(FL);
  408. DoneCriticalSection(LCS);
  409. end;
  410. {$endif svcdebug}
  411. Procedure RegisterDaemonApplicationClass(AClass : TCustomDaemonApplicationClass);
  412. begin
  413. If (AppInstance<>Nil) then
  414. DaemonError(SErrApplicationAlreadyCreated,[AppInstance.ClassName]);
  415. AppClass:=AClass;
  416. end;
  417. Procedure RegisterDaemonClass(AClass : TCustomDaemonClass);
  418. Var
  419. DN : String;
  420. I : Integer;
  421. begin
  422. If Not Assigned(DaemonClasses) then
  423. begin
  424. DaemonClasses:=TStringList.Create;
  425. DaemonClasses.Sorted:=True;
  426. end;
  427. DN:=AClass.ClassName;
  428. I:=DaemonClasses.IndexOf(DN);
  429. If (I=-1) then
  430. I:=DaemonClasses.Add(DN);
  431. DaemonClasses.Objects[I]:=TObject(AClass);
  432. end;
  433. Procedure CreateDaemonApplication;
  434. begin
  435. If (AppClass=Nil) then
  436. AppClass:=TCustomDaemonApplication;
  437. AppInstance:=AppClass.Create(Nil);
  438. end;
  439. Procedure DoneDaemonApplication;
  440. begin
  441. FreeAndNil(AppInstance);
  442. FreeAndNil(DaemonClasses);
  443. end;
  444. function Application: TCustomDaemonApplication;
  445. begin
  446. If (AppInstance=Nil) then
  447. CreateDaemonApplication;
  448. Result:=AppInstance;
  449. end;
  450. Procedure RegisterDaemonMapper(AMapperClass : TCustomDaemonMapperClass);
  451. begin
  452. If Assigned(MapperClass) then
  453. DaemonError(SErrOnlyOneMapperAllowed,[MapperClass.ClassName,AMapperClass.ClassName]);
  454. MapperClass:=AMapperClass;
  455. end;
  456. procedure DaemonError(Msg: String);
  457. begin
  458. Raise EDaemon.Create(MSg);
  459. end;
  460. procedure DaemonError(Fmt: String; Args: array of const);
  461. begin
  462. Raise EDaemon.CreateFmt(Fmt,Args);
  463. end;
  464. { TDaemon }
  465. function TDaemon.Start: Boolean;
  466. begin
  467. Result:=inherited Start;
  468. If assigned(FOnStart) then
  469. FOnStart(Self,Result);
  470. end;
  471. function TDaemon.Stop: Boolean;
  472. begin
  473. Result:=inherited Start;
  474. If assigned(FOnStop) then
  475. FOnStop(Self,Result);
  476. end;
  477. function TDaemon.Pause: Boolean;
  478. begin
  479. Result:=inherited Start;
  480. If assigned(FOnPause) then
  481. FOnPause(Self,Result);
  482. end;
  483. function TDaemon.Continue: Boolean;
  484. begin
  485. Result:=inherited Continue;
  486. If assigned(FOnContinue) then
  487. FOnContinue(Self,Result);
  488. end;
  489. function TDaemon.Execute: Boolean;
  490. begin
  491. Result:=Assigned(FOnExecute);
  492. If Result Then
  493. FOnExecute(Self);
  494. end;
  495. function TDaemon.ShutDown: Boolean;
  496. begin
  497. Result:=Inherited ShutDown;
  498. If Assigned(FOnShutDown) then
  499. FOnShutDown(Self);
  500. end;
  501. function TDaemon.Install: Boolean;
  502. begin
  503. If Assigned(FBeforeInstall) then
  504. FBeforeInstall(Self);
  505. Result:=inherited Install;
  506. If Assigned(FAfterInstall) then
  507. FAfterInstall(Self)
  508. end;
  509. function TDaemon.UnInstall: boolean;
  510. begin
  511. If Assigned(FBeforeUnInstall) then
  512. FBeforeUnInstall(Self);
  513. Result:=inherited UnInstall;
  514. If Assigned(FAfterUnInstall) then
  515. FAfterUnInstall(Self)
  516. end;
  517. function TDaemon.HandleCustomCode(ACode: DWord): Boolean;
  518. begin
  519. Result:=Assigned(FOnCustomControl);
  520. If Result then
  521. FOnCustomControl(Self,ACode,Result);
  522. end;
  523. { TCustomDaemon }
  524. Function TCustomDaemon.Start : Boolean;
  525. begin
  526. Result:=True;
  527. end;
  528. Function TCustomDaemon.Stop : Boolean;
  529. begin
  530. Result:=True;
  531. end;
  532. Function TCustomDaemon.Pause : Boolean;
  533. begin
  534. Result:=True;
  535. end;
  536. Function TCustomDaemon.Continue : Boolean;
  537. begin
  538. Result:=True;
  539. end;
  540. function TCustomDaemon.Execute: Boolean;
  541. begin
  542. Result:=False;
  543. end;
  544. Function TCustomDaemon.ShutDown : Boolean;
  545. begin
  546. Result:=True;
  547. end;
  548. Procedure TCustomDaemon.ReportStatus;
  549. begin
  550. Controller.ReportStatus;
  551. end;
  552. procedure TCustomDaemon.LogMessage(Msg: String);
  553. begin
  554. Application.Logger.Error(Msg);
  555. end;
  556. function TCustomDaemon.GetLogger: TEventLog;
  557. begin
  558. Result:=Application.Logger;
  559. end;
  560. procedure TCustomDaemon.SetStatus(const AValue: TCurrentStatus);
  561. begin
  562. FStatus:=AValue;
  563. Controller.ReportStatus;
  564. end;
  565. Function TCustomDaemon.Install : Boolean;
  566. begin
  567. Result:=True;
  568. Application.SysInstallDaemon(Self);
  569. end;
  570. Function TCustomDaemon.UnInstall : Boolean;
  571. begin
  572. Result:=True;
  573. Application.SysInstallDaemon(Self);
  574. end;
  575. function TCustomDaemon.HandleCustomCode(ACode: DWord): Boolean;
  576. begin
  577. Result:=False
  578. end;
  579. { TCustomServiceApplication }
  580. procedure TCustomDaemonApplication.CreateServiceMapper(Var AMapper : TCustomDaemonMapper);
  581. begin
  582. AMapper:=MapperClass.Create(Self);
  583. BindDaemonDefs(Amapper);
  584. end;
  585. procedure TCustomDaemonApplication.BindDaemonDefs(AMapper : TCustomDaemonMapper);
  586. begin
  587. AMApper.DaemonDefs.BindClasses;
  588. end;
  589. procedure TCustomDaemonApplication.CreateDaemonController(Var AController : TDaemonController);
  590. begin
  591. ACOntroller:=TDaemonController.Create(Self);
  592. end;
  593. Function TCustomDaemonApplication.RunDaemonsRun : Boolean;
  594. begin
  595. Result:=HasOption('r','run');
  596. // No Borland compatibility needed, as the install will take care of the -r
  597. end;
  598. procedure TCustomDaemonApplication.Main(Argc: DWord; Args: PPchar);
  599. Var
  600. SN : String;
  601. DD : TDaemonDef;
  602. begin
  603. If (Args=Nil) then
  604. Exit;
  605. SN:=StrPas(Args^);
  606. DD:=FMapper.DaemonDefs.FindDaemonDef(SN);
  607. If (DD<>Nil) then
  608. DD.Instance.Controller.Main(Argc,Args);
  609. end;
  610. Function TCustomDaemonApplication.InstallRun : Boolean;
  611. begin
  612. Result:=HasOption('i','install');
  613. // Borland compatibility.
  614. If not Result then
  615. Result:=FindCmdLineSwitch ('install',['/'],True);
  616. end;
  617. Function TCustomDaemonApplication.UnInstallRun : Boolean;
  618. begin
  619. Result:=HasOption('u','uninstall');
  620. // Borland compatibility.
  621. If not Result then
  622. Result:=FindCmdLineSwitch ('uninstall',['/'],True);
  623. end;
  624. Procedure TCustomDaemonApplication.InstallDaemons;
  625. Var
  626. D : TCustomDaemon;
  627. DD : TDaemonDef;
  628. C : TDaemonController;
  629. I : Integer;
  630. begin
  631. FrunMode:=drmInstall;
  632. SysStartInstallDaemons;
  633. try
  634. FMapper.DoOnInstall;
  635. For I:=0 to FMapper.DaemonDefs.Count-1 do
  636. begin
  637. DD:=FMapper.DaemonDefs[i];
  638. If DD.Enabled then
  639. begin
  640. D:=CreateDaemon(DD);
  641. Try
  642. // Need to call this because of the before/after events.
  643. D.Install;
  644. Finally
  645. D.Free;
  646. end;
  647. end;
  648. end;
  649. Finally
  650. SysEndInstallDaemons;
  651. end;
  652. end;
  653. Procedure TCustomDaemonApplication.UnInstallDaemons;
  654. Var
  655. D : TCustomDaemon;
  656. DD : TDaemonDef;
  657. I : Integer;
  658. begin
  659. FrunMode:=drmUnInstall;
  660. SysStartUnInstallDaemons;
  661. Try
  662. FMapper.DoOnUnInstall;
  663. // Uninstall in reverse order. One never knows.
  664. For I:=FMapper.DaemonDefs.Count-1 downto 0 do
  665. begin
  666. DD:=FMapper.DaemonDefs[i];
  667. If DD.Enabled then
  668. begin
  669. D:=CreateDaemon(FMapper.DaemonDefs[i]);
  670. Try
  671. // Need to call this because of the before/after events.
  672. D.UnInstall
  673. Finally
  674. D.Free;
  675. end;
  676. end;
  677. end;
  678. Finally
  679. SysEndUnInstallDaemons;
  680. end;
  681. end;
  682. procedure TCustomDaemonApplication.CreateForm(InstanceClass: TComponentClass;
  683. var Reference);
  684. Var
  685. Instance: TComponent;
  686. begin
  687. // Allocate the instance, without calling the constructor
  688. Instance := TComponent(InstanceClass.NewInstance);
  689. // set the Reference before the constructor is called, so that
  690. // events and constructors can refer to it
  691. TComponent(Reference) := Instance;
  692. try
  693. Instance.Create(Self);
  694. except
  695. TComponent(Reference) := nil;
  696. Raise;
  697. end;
  698. end;
  699. Procedure TCustomDaemonApplication.RunDaemons;
  700. Var
  701. D : TCustomDaemon;
  702. DD : TDaemonDef;
  703. I : Integer;
  704. begin
  705. FRunMode:=drmRun;
  706. SysStartRunDaemons;
  707. FMapper.DoOnRun;
  708. For I:=0 to FMapper.DaemonDefs.Count-1 do
  709. begin
  710. DD:=FMapper.DaemonDefs[i];
  711. If DD.Enabled then
  712. D:=CreateDaemon(FMapper.DaemonDefs[i]);
  713. end;
  714. try
  715. SysEndRunDaemons;
  716. except
  717. HandleException(Self);
  718. Terminate;
  719. end;
  720. end;
  721. procedure TCustomDaemonApplication.SetupLogger;
  722. begin
  723. FLogger:=TEventlog.Create(Self);
  724. FLogger.RegisterMessageFile('');
  725. end;
  726. procedure TCustomDaemonApplication.StopLogger;
  727. begin
  728. Flogger.Active:=False;
  729. FreeAndNil(Flogger);
  730. end;
  731. procedure TCustomDaemonApplication.DoRun;
  732. begin
  733. SetupLogger;
  734. Try
  735. try
  736. If Not Assigned(MapperClass) then
  737. DaemonError(SErrNoServiceMapper);
  738. CreateServiceMapper(FMapper);
  739. If InstallRun then
  740. InstallDaemons
  741. else If UnInstallRun then
  742. UnInstallDaemons
  743. else if RunDaemonsRun then
  744. RunDaemons
  745. else if Assigned(OnRun) then
  746. OnRun(Self)
  747. else
  748. DaemonError(SErrNothingToDo);
  749. {$ifdef svcdebug}DebugLog('Terminating');{$endif svcdebug}
  750. Terminate;
  751. {$ifdef svcdebug}DebugLog('Terminated');{$endif svcdebug}
  752. except
  753. Terminate;
  754. Raise
  755. end;
  756. Finally
  757. StopLogger;
  758. end;
  759. end;
  760. procedure TCustomDaemonApplication.ShowException(E: Exception);
  761. begin
  762. If assigned(Flogger) then
  763. FLogger.Error(E.Message)
  764. else
  765. inherited ShowException(E)
  766. end;
  767. Procedure TCustomDaemonApplication.CreateDaemonInstance(Var ADaemon : TCustomDaemon; DaemonDef : TDaemonDef);
  768. begin
  769. ADaemon:=DaemonDef.DaemonClass.CreateNew(Self,0);
  770. end;
  771. function TCustomDaemonApplication.CreateDaemon(DaemonDef: TDaemonDef): TCustomDaemon;
  772. Var
  773. C : TDaemonController;
  774. begin
  775. CreateDaemonInstance(Result,DaemonDef);
  776. CreateDaemonController(C);
  777. C.FDaemon:=Result;
  778. Result.FController:=C;
  779. Result.FDaemonDef:=DaemonDef;
  780. If (Daemondef.Instance=Nil) then
  781. DaemonDef.Instance:=Result;
  782. end;
  783. procedure TCustomDaemonApplication.StopDaemons(Force: Boolean);
  784. Const
  785. ControlCodes : Array[Boolean] of DWord
  786. = (SERVICE_CONTROL_STOP,SERVICE_CONTROL_SHUTDOWN);
  787. Var
  788. L : TFPList;
  789. I : Integer;
  790. begin
  791. L:=TFPList.Create;
  792. try
  793. For I:=0 to ComponentCount-1 do
  794. If Components[i] is TDaemonController then
  795. L.Add(Components[i]);
  796. For I:=L.Count-1 downto 0 do
  797. TDaemonController(L[i]).Controller(ControlCodes[Force],0,Nil);
  798. finally
  799. L.Free;
  800. end;
  801. end;
  802. { TDaemonDefs }
  803. function TDaemonDefs.GetDaemonDef(Index : Integer): TDaemonDef;
  804. begin
  805. Result:=TDaemonDef(Items[index]);
  806. end;
  807. procedure TDaemonDefs.SetDaemonDef(Index : Integer; const AValue: TDaemonDef);
  808. begin
  809. Items[Index]:=AValue;
  810. end;
  811. procedure TDaemonDefs.BindClasses;
  812. Var
  813. D : TDaemonDef;
  814. I,J : Integer;
  815. begin
  816. For I:=0 to Count-1 do
  817. begin
  818. D:=GetDaemonDef(I);
  819. J:=DaemonClasses.IndexOf(D.DaemonClassName);
  820. If (J=-1) then
  821. DaemonError(SErrUnknownDaemonClass,[D.DaemonClassName])
  822. else
  823. D.FDaemonClass:=TCustomDaemonClass(DaemonClasses.Objects[J]);
  824. end;
  825. end;
  826. function TDaemonDefs.GetOwner: TPersistent;
  827. begin
  828. Result:=FOwner;
  829. end;
  830. constructor TDaemonDefs.Create(AOwner: TPersistent; AClass : TCollectionItemClass);
  831. begin
  832. Inherited Create(AClass);
  833. FOwner:=AOwner;
  834. end;
  835. function TDaemonDefs.IndexOfDaemonDef(Const DaemonName: String): Integer;
  836. begin
  837. Result:=Count-1;
  838. While (Result>=0) and (CompareText(GetDaemonDef(Result).Name,DaemonName)<>0) do
  839. Dec(Result);
  840. end;
  841. function TDaemonDefs.FindDaemonDef(Const DaemonName: String): TDaemonDef;
  842. Var
  843. I : Integer;
  844. begin
  845. I:=IndexOfDaemonDef(DaemonName);
  846. If I<>-1 then
  847. Result:=GetDaemonDef(I)
  848. else
  849. Result:=Nil;
  850. end;
  851. function TDaemonDefs.DaemonDefByName(Const DaemonName: String): TDaemonDef;
  852. begin
  853. Result:=FindDaemonDef(DaemonName);
  854. end;
  855. { TDaemonDef }
  856. procedure TDaemonDef.SetName(const AValue: String);
  857. begin
  858. If (AValue<>FName) then
  859. begin
  860. If (AValue<>'') and (Collection<>Nil)
  861. and (Collection is TDaemonDefs)
  862. and ((Collection as TDaemonDefs).IndexOfDaemonDef(AValue)<>-1) then
  863. DaemonError(SErrDuplicateName,[Avalue]);
  864. FName:=AValue;
  865. end;
  866. end;
  867. procedure TDaemonDef.SetWinBindings(const AValue: TWinBindings);
  868. begin
  869. FWinBindings.Assign(AValue);
  870. end;
  871. function TDaemonDef.GetDisplayName: string;
  872. begin
  873. Result:=Name;
  874. end;
  875. constructor TDaemonDef.Create(ACollection: TCollection);
  876. begin
  877. inherited Create(ACollection);
  878. FWinBindings:=TWinBindings.Create;
  879. FEnabled:=True;
  880. FOptions:=DefaultDaemonOptions;
  881. end;
  882. destructor TDaemonDef.Destroy;
  883. begin
  884. FreeAndNil(FWinBindings);
  885. inherited Destroy;
  886. end;
  887. { TCustomDaemonMapper }
  888. procedure TCustomDaemonMapper.SetDaemonDefs(const AValue: TDaemonDefs);
  889. begin
  890. if (FDaemonDefs=AValue) then
  891. exit;
  892. FDaemonDefs.Assign(AValue);
  893. end;
  894. procedure TCustomDaemonMapper.CreateDefs;
  895. begin
  896. FDaemonDefs:=TDaemonDefs.Create(Self,TDaemonDef);
  897. end;
  898. procedure TCustomDaemonMapper.DoOnCreate;
  899. begin
  900. If Assigned(FOnCreate) then
  901. FOnCreate(Self);
  902. end;
  903. procedure TCustomDaemonMapper.DoOnDestroy;
  904. begin
  905. If Assigned(FOnDestroy) then
  906. FOnDestroy(Self);
  907. end;
  908. procedure TCustomDaemonMapper.DoOnInstall;
  909. begin
  910. If Assigned(FOnInstall) then
  911. FOnInstall(Self);
  912. end;
  913. procedure TCustomDaemonMapper.DoOnUnInstall;
  914. begin
  915. If Assigned(FOnUnInstall) then
  916. FOnUnInstall(Self);
  917. end;
  918. procedure TCustomDaemonMapper.DoOnRun;
  919. begin
  920. If Assigned(FOnRun) then
  921. FOnRun(Self);
  922. end;
  923. constructor TCustomDaemonMapper.Create(AOwner: TComponent);
  924. begin
  925. CreateDefs; // First, otherwise streaming will fail.
  926. inherited Create(AOwner);
  927. DoOnCreate;
  928. end;
  929. destructor TCustomDaemonMapper.Destroy;
  930. begin
  931. DoOnDestroy;
  932. FreeAndNil(FDaemonDefs);
  933. inherited Destroy;
  934. end;
  935. { TDaemonThread }
  936. constructor TDaemonThread.Create(ADaemon: TCustomDaemon);
  937. begin
  938. FDaemon:=ADAemon;
  939. FDaemon.FThread:=Self;
  940. FreeOnTerminate:=False;
  941. Inherited Create(True);
  942. end;
  943. procedure TDaemonThread.Execute;
  944. begin
  945. If FDaemon.Start then
  946. begin
  947. FDaemon.Status:=csRunning;
  948. StartServiceExecute;
  949. if not FDaemon.Execute then
  950. begin
  951. While Not Terminated do
  952. CheckControlMessage(True);
  953. CheckControlMessage(False);
  954. end;
  955. end;
  956. end;
  957. procedure TDaemonThread.HandleControlCode(ACode : DWord);
  958. Var
  959. CS : TCurrentStatus;
  960. CC,OK : Boolean;
  961. S : String;
  962. begin
  963. CS:=FDaemon.Status;
  964. Try
  965. OK:=True;
  966. CC:=False;
  967. Case ACode of
  968. SERVICE_CONTROL_STOP : OK:=StopDaemon;
  969. SERVICE_CONTROL_PAUSE : OK:=PauseDaemon;
  970. SERVICE_CONTROL_CONTINUE : OK:=ContinueDaemon;
  971. SERVICE_CONTROL_SHUTDOWN : OK:=ShutDownDaemon;
  972. SERVICE_CONTROL_INTERROGATE : OK:=InterrogateDaemon;
  973. else
  974. CC:=True;
  975. FDaemon.HandleCustomCode(ACode);
  976. end;
  977. If not OK then
  978. FDaemon.Status:=CS;
  979. Except
  980. On E : Exception do
  981. begin
  982. // Shutdown MUST be done, in all other cases roll back status.
  983. If (ACode<>SERVICE_CONTROL_SHUTDOWN) then
  984. FDaemon.Status:=CS;
  985. If (ACode in [1..5]) then
  986. S:=SStatus[ACode]
  987. else
  988. S:=Format(SCustomCode,[ACode]);
  989. Application.Logger.Error(SControlFailed,[S,E.Message]);
  990. end;
  991. end;
  992. end;
  993. function TDaemonThread.StopDaemon: Boolean;
  994. begin
  995. FDaemon.Status:=csStopPending;
  996. Result:=FDaemon.Stop;
  997. If Result then
  998. begin
  999. FDaemon.Status:=csStopped;
  1000. Terminate;
  1001. end;
  1002. end;
  1003. function TDaemonThread.PauseDaemon: Boolean;
  1004. begin
  1005. FDaemon.Status:=csPausePending;
  1006. Result:=FDaemon.Pause;
  1007. If Result then
  1008. begin
  1009. FDaemon.Status:=csPaused;
  1010. Suspend;
  1011. end;
  1012. end;
  1013. function TDaemonThread.ContinueDaemon: Boolean;
  1014. begin
  1015. FDaemon.Status:=csContinuePending;
  1016. Result:=FDaemon.Continue;
  1017. If Result then
  1018. FDaemon.Status:=csRunning;
  1019. end;
  1020. function TDaemonThread.ShutDownDaemon: Boolean;
  1021. begin
  1022. FDaemon.Status:=csStopPending;
  1023. Try
  1024. Result:=FDaemon.ShutDown;
  1025. except
  1026. FDaemon.Status:=csStopped;
  1027. Terminate;
  1028. end;
  1029. end;
  1030. Function TDaemonThread.InterrogateDaemon: Boolean;
  1031. begin
  1032. FDaemon.ReportStatus;
  1033. Result:=True;
  1034. end;
  1035. { ---------------------------------------------------------------------
  1036. TDaemonController - Global implementation
  1037. ---------------------------------------------------------------------}
  1038. constructor TDaemonController.Create(AOwner: TComponent);
  1039. begin
  1040. inherited Create(AOwner);
  1041. FParams:=TStringList.Create;
  1042. end;
  1043. destructor TDaemonController.Destroy;
  1044. begin
  1045. FreeAndNil(FSysData);
  1046. FreeAndNil(FParams);
  1047. inherited Destroy;
  1048. end;
  1049. { TWinBindings }
  1050. procedure TWinBindings.SetDependencies(const AValue: TDependencies);
  1051. begin
  1052. if (FDependencies<>AValue) then
  1053. FDependencies.Assign(AValue);
  1054. end;
  1055. Constructor TWinBindings.Create;
  1056. begin
  1057. FDependencies:=TDependencies.Create(Self);
  1058. end;
  1059. destructor TWinBindings.Destroy;
  1060. begin
  1061. FreeAndNil(FDependencies);
  1062. inherited Destroy;
  1063. end;
  1064. procedure TWinBindings.Assign(Source: TPersistent);
  1065. Var
  1066. WB : TWinBindings;
  1067. begin
  1068. if Source is TWinBindings then
  1069. begin
  1070. WB:=Source as TWinBindings;
  1071. GroupName:=WB.GroupName;
  1072. Password:=WB.PassWord;
  1073. UserName:=WB.UserName;
  1074. StartType:=WB.StartType;
  1075. WaitHint:=WB.WaitHint;
  1076. IDTag:=WB.IDTag;
  1077. ServiceType:=WB.ServiceType;
  1078. ErrorSeverity:=WB.ErrorSeverity;
  1079. Dependencies.Assign(WB.Dependencies);
  1080. ErrCode:=WB.ErrCode;
  1081. Win32ErrCode:=WB.Win32ErrCode;
  1082. end
  1083. else
  1084. inherited Assign(Source);
  1085. end;
  1086. { TDependency }
  1087. function TDependency.GetDisplayName: string;
  1088. begin
  1089. Result:=Name;
  1090. end;
  1091. procedure TDependency.Assign(Source: TPersistent);
  1092. Var
  1093. D : TDependency;
  1094. begin
  1095. if Source is TDependency then
  1096. begin
  1097. D:=Source as TDependency;
  1098. Name:=D.Name;
  1099. IsGroup:=D.IsGroup;
  1100. end
  1101. else
  1102. inherited Assign(Source);
  1103. end;
  1104. { TDependencies }
  1105. function TDependencies.GetItem(Index: Integer): TDependency;
  1106. begin
  1107. Result:=TDependency(Inherited GetItem(Index));
  1108. end;
  1109. procedure TDependencies.SetItem(Index: Integer; Value: TDependency);
  1110. begin
  1111. Inherited SetItem(Index,Value);
  1112. end;
  1113. function TDependencies.GetOwner: TPersistent;
  1114. begin
  1115. Result:=FOwner;
  1116. end;
  1117. constructor TDependencies.Create(AOwner: TPersistent);
  1118. begin
  1119. Inherited Create(TDependency);
  1120. FOwner:=AOwner;
  1121. end;
  1122. { TDaemonMapper }
  1123. constructor TDaemonMapper.Create(AOwner: TComponent);
  1124. begin
  1125. CreateNew(AOwner,0);
  1126. if (ClassType<>TDaemonMapper) and not (csDesigning in ComponentState) then
  1127. begin
  1128. if not InitInheritedComponent(Self,TDaemonMapper) then
  1129. raise EStreamError.CreateFmt(SErrNoSTreaming, [ClassName]);
  1130. end;
  1131. end;
  1132. constructor TDaemonMapper.CreateNew(AOwner: TComponent; Dummy: Integer);
  1133. begin
  1134. inherited Create(AOwner);
  1135. end;
  1136. Initialization
  1137. {$ifdef svcdebug}
  1138. StartLog;
  1139. {$endif}
  1140. SysInitDaemonApp;
  1141. Finalization
  1142. SysDoneDaemonApp;
  1143. DoneDaemonApplication;
  1144. {$ifdef svcdebug}
  1145. EndLog;
  1146. {$endif}
  1147. end.