Daemon.cpp
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:19k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. // This is part of the WAR SOFTWARE SERIES initiated by Jarle Aase
  2. // Copyright 1996 by Jarle Aase. All rights reserved.
  3. // See the "War Software Series Licende Agreement" for details concerning 
  4. // use and distribution.
  5. // ---
  6. // This source code, executables and programs containing source code or
  7. // binaries or proprietetary technology from the War Software Series are
  8. // NOT alloed used, viewed or tested by any governmental agencies in
  9. // any countries. This includes the government, departments, police, 
  10. // military etc.
  11. // ---
  12. // This file is intended for use with Tab space = 2
  13. // Created and maintained in MSVC Developer Studio
  14. // ---
  15. // NAME : Daemon.cpp
  16. // PURPOSE : General entry point module for War Daemons
  17. // PROGRAM : 
  18. // DATE : Sept. 19 1996
  19. // AUTHOR : Jarle Aase
  20. // ---
  21. // REVISION HISTORY
  22. // 
  23. #include "stdafx.h"
  24. #include "..IncludeWarDaemon.h"
  25. #include "..IncludeWarService.h"
  26. #include "FsysSecurity.h"
  27. #include "ServerDlg.h"
  28. #include <process.h>
  29. #include <direct.h>
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. static CDaemon *DaemonPtr; // Pointer to the deamon object
  36. static WSADATA socInfo; // Windows socket info
  37. DLL_WAR_DAEMON_ BOOL g_DoRestart = FALSE; // Restart
  38. VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD  dwTime);
  39. ////////////////////////////////////////////////////////////////////
  40. // CDaemon class
  41. IMPLEMENT_DYNAMIC(CDaemon, CObject)
  42. CDaemon::CDaemon()
  43. {
  44. DaemonPtr = this;
  45. m_pWnd = NULL;
  46. }
  47. CDaemon::~CDaemon()
  48. {
  49. DaemonPtr = NULL;
  50. if (m_pWnd)
  51. delete m_pWnd;
  52. }
  53. // Main entry point. Does not return until the server is
  54. // terminated.
  55. void CDaemon::Process(
  56. LPCSTR SvrType, 
  57. LPCSTR ProgramName, 
  58. LPCSTR ProgramVersion, 
  59. LPCSTR ProgramCopyright,
  60. CRuntimeClass *MainThreadClass)
  61. {
  62. char *CmdLine = GetCommandLine();
  63. #ifdef _DEBUG
  64. //DebugBreak();
  65. #endif
  66. CString cMyHomeDir, cMyName, cBuf;
  67. ::GetLineParam("-Name", cMyName, "Default");
  68. cBuf = GetStartupPath();
  69. LPSTR p = cBuf.GetBuffer(1);
  70. if (p = strrchr(p, '\'))
  71. *p = 0;
  72. cBuf.ReleaseBuffer();
  73. cMyHomeDir.Format("%s\Daemons\%s\%s",cBuf, SvrType, cMyName);
  74. if (_chdir(cMyHomeDir))
  75. {
  76. cBuf.Format("Unable to change directory to '%s'.rnPlease reinstall the server.", cMyHomeDir);
  77. AfxMessageBox(cBuf);
  78. return;
  79. }
  80. if (CmdLine && ((CmdLine = strrchr(CmdLine,' ')) != NULL))
  81. ++CmdLine;
  82. m_NTSoptions = new CDaemonNTSOptions();
  83. m_NTSoptions->Create(NULL, NULL, "NTService", COPTION_NTSERVICE);
  84. m_NTSoptions->LoadAll();
  85. if (m_NTSoptions->m_ServiceName.IsEmpty())
  86. {
  87. // Assign default values
  88. m_NTSoptions->m_ServiceName.Format("%s V2", ProgramName);
  89. m_NTSoptions->m_VisualName.Format("%s %s", ProgramName, ProgramVersion);
  90. m_NTSoptions->m_ServiceMode = 3;
  91. m_NTSoptions->m_LoginAsLocalAdmin = TRUE;
  92. m_NTSoptions->SaveAll();
  93. }
  94. m_Service = new CNTService(m_NTSoptions->m_ServiceName, MainThreadClass);
  95. ::GetLineParam("-ServiceMode", cBuf, "auto");
  96. BOOL SuspendService = (cBuf == "off");
  97. if (SuspendService
  98. || !m_Service->IsInstalled() 
  99. || !m_Service->StartService())
  100. {
  101. delete m_Service;
  102. m_Service = NULL;
  103. g_DoRestart = TRUE;
  104. m_pWnd = new CWnd;
  105. m_pWnd->m_hWnd = NULL;
  106. if (!m_pWnd->CreateEx(0, AfxRegisterWndClass(0),
  107. _T("War Daemon App Message Sink"),
  108. WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL))
  109. {
  110. TRACE0("Warning: unable to create War Daemon App Message Sink window!n");
  111. AfxThrowResourceException();
  112. }
  113. ASSERT(m_pWnd->m_hWnd != NULL);
  114. ASSERT(CWnd::FromHandlePermanent(m_pWnd->m_hWnd) == m_pWnd);
  115. AfxGetThread()->m_pMainWnd = CDaemonNotificationWnd::GetWin();
  116. while(g_DoRestart)
  117. {
  118. _chdir(cMyHomeDir);
  119. g_DoRestart = FALSE;
  120. // Start the thread and run quiet as a normal program
  121. m_MainThread = AfxBeginThread(MainThreadClass);
  122. HANDLE hList[2];
  123. hList[0] = m_MainThread->m_hThread;
  124. hList[1] = INVALID_HANDLE_VALUE;
  125. again:
  126. DWORD Rval = MsgWaitForMultipleObjects(1, hList, FALSE, INFINITE, QS_ALLINPUT);
  127. if (Rval == (WAIT_OBJECT_0 + 1 ))
  128. {
  129. // Message
  130. MSG Msg;
  131. if (PeekMessage(&Msg, m_pWnd->m_hWnd, 0, 0, PM_REMOVE))
  132. {
  133. TranslateMessage(&Msg);
  134. DispatchMessage(&Msg);
  135. }
  136. goto again;
  137. }
  138. //WaitForSingleObject(m_MainThread->m_hThread,INFINITE);
  139. }
  140. }
  141. m_NTSoptions->SaveAll();
  142. delete m_NTSoptions;
  143. m_NTSoptions = NULL;
  144. }
  145. /////////////////////////////////////////////////////////////////////////////
  146. // CDaemonBase
  147. IMPLEMENT_DYNCREATE(CDaemonBase, CWinThread)
  148. CDaemonBase *CDaemonBase::m_pDaemonBase = NULL;
  149. CDaemonBase::CDaemonBase()
  150. {
  151. m_RemoteAdminListenSocket = NULL;
  152. m_pDaemonBase = this;
  153. m_TrayIsInitialized = 0;
  154. m_hIcon = (HICON)0;
  155. m_SysTrayIdle = (HICON)0;
  156. m_SysTrayOnline = (HICON)0;
  157. m_SysTrayOffline = (HICON)0;
  158. m_pWnd = NULL;
  159. }
  160. CDaemonBase::~CDaemonBase()
  161. {
  162. m_pDaemonBase = NULL;
  163. if (m_pWnd)
  164. delete (CDaemonNotificationWnd *)m_pWnd;
  165. }
  166. void CDaemonBase::LogMsg(int flag, LPCSTR Format, ...)
  167. {
  168. if (!ShouldLog(m_Log, flag))
  169. return;
  170. ASSERT(AfxIsValidString(Format, FALSE));
  171. va_list argList;
  172. va_start(argList, Format);
  173. m_Log->LogMsgV(flag, Format, argList);
  174. va_end(argList);
  175. }
  176. BOOL CDaemonBase::InitInstance()
  177. {
  178. #ifdef _DEBUG
  179. //DebugBreak();
  180. #endif
  181. CString cMyHomeDir, cMyName, cBuf;
  182. ::GetLineParam("-Name", cMyName, "Default");
  183. cBuf = GetStartupPath();
  184. LPSTR p = cBuf.GetBuffer(1);
  185. if (p = strrchr(p, '\'))
  186. *p = 0;
  187. cBuf.ReleaseBuffer();
  188. cMyHomeDir.Format("%s\Daemons\%s\%s",cBuf, m_ServerStat.m_ServerType, cMyName);
  189. if (_chdir(cMyHomeDir))
  190. {
  191. cBuf.Format("Unable to change directory to '%s'.rnPlease reinstall the server.", cMyHomeDir);
  192. AfxMessageBox(cBuf);
  193. return FALSE;
  194. }
  195. CDaemonNotificationWnd* pWnd = new CDaemonNotificationWnd;
  196. m_pWnd = pWnd;
  197. pWnd->m_hWnd = NULL;
  198. if (!pWnd->CreateEx(0, AfxRegisterWndClass(0),
  199. _T("War Daemon Notification Sink"),
  200. WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL))
  201. {
  202. TRACE0("Warning: unable to create War Daemon notify window!n");
  203. AfxThrowResourceException();
  204. }
  205. ASSERT(pWnd->m_hWnd != NULL);
  206. ASSERT(CWnd::FromHandlePermanent(pWnd->m_hWnd) == pWnd);
  207. m_pMainWnd = CDaemonNotificationWnd::GetWin();
  208. CSock::SetDNSWin(m_pMainWnd);
  209. // Load options
  210. m_RAOptions.Create(NULL, NULL, "Remote Admin", COPTION_RA_DAEMON);
  211. m_RAOptions.LoadAll();
  212. m_AdvancedOptions.Create(NULL,NULL,"Advanced",COPTION_ADVANCEDOPTIONS);
  213. m_AdvancedOptions.LoadAll();
  214. // Set priority
  215. SetPriorityClass(GetCurrentProcess(),CAdvancedOptions::GetPriority(m_AdvancedOptions.m_TaskPriority));
  216. LogMsg(LOGF_SYSTEM,"%s %s %s", 
  217. CProgramInfo::m_PROGRAM,
  218. CProgramInfo::m_VERSION,
  219. CProgramInfo::m_COPYRIGHT);
  220. LogMsg(LOGF_SYSTEM,"This program is not lisenced to governmental or military use.");
  221. LogMsg(LOGF_SYSTEM,"%s detected.", OsName());
  222. if (DaemonPtr->m_Service)
  223. {
  224. LogMsg(LOGF_SYSTEM,"Running as NT service '%s' (%s).",
  225. COptions::GetOption(COPTION_NTSERVICE, NTSERVICE__VISUALNAME),
  226. COptions::GetOption(COPTION_NTSERVICE, NTSERVICE__SERVICENAME));
  227. }
  228. {
  229. char buf[MAX_PATH];
  230. if (_getcwd(buf,sizeof(buf)))
  231. LogMsg(LOGF_SYSTEM,"Current Server homedir is: '%s'", buf);
  232. else
  233. LogMsg(LOGF_ERROR,"Current Server homedir is -UNKNOWN-");
  234. }
  235. // We need sockets for the server control network interface
  236. #ifndef _MAC
  237. if (!AfxSocketInit(&socInfo))
  238. {
  239. //AfxMessageBox(CG_IDS_SOCKETS_INIT_FAILED1);
  240. return FALSE;
  241. }
  242. #endif  // _MAC
  243. LogMsg(LOGF_SYSTEM,"%s", socInfo.szDescription);
  244. CSock::GetHostIpNumber(cBuf);
  245. LogMsg(LOGF_SYSTEM,"Primary local IP number reported by Winsock is %s", cBuf);
  246. LogMsg(LOGF_SYSTEM,"Services online on 0.0.0.0 will use any local IP number.");
  247. m_TimerID = ::SetTimer(NULL,0,1000,TimerProc);
  248. if (!m_TimerID)
  249. LogMsg(LOGF_WARNINGS,"CWarMainThread::InitInstance(): Failed to start primary timer. Server might be unreliable.");
  250. // Set priority
  251. //switch(g_Priority)
  252. //{
  253. // case 0: SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS); break;
  254. // case 1: SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); break;
  255. // case 2: SetPriorityClass(GetCurrentProcess(),NORMAL_PRIORITY_CLASS); break;
  256. // case 3: SetPriorityClass(GetCurrentProcess(),IDLE_PRIORITY_CLASS); break;
  257. //}
  258. // Initialize user
  259. ASSERT(m_User != NULL);
  260. if (!m_User->Create(m_Log))
  261. {
  262. LogMsg(LOGF_ERROR,"Failed to initialize user database. Terminating.");
  263. return FALSE;
  264. }
  265. // Initialize vfsys
  266. /*
  267. ASSERT(m_Fsys != NULL);
  268. if (!m_Fsys->Create(m_Log))
  269. {
  270. LogMsg(LOGF_ERROR,"Failed to initialize file system. Terminating.");
  271. return FALSE;
  272. }
  273. */
  274. ASSERT(m_RemoteAdminListenSocket != NULL);
  275. // Set the static log pointer for all sockets in this server
  276. m_RemoteAdminListenSocket->SetLog(m_Log);
  277. // Enable remote admin...
  278. if (!m_RemoteAdminListenSocket->Initialize(m_RAOptions.m_Port, NULL, m_RAOptions.m_IPname))
  279. {
  280. m_RemoteAdminListenSocket = NULL;
  281. LogMsg(LOGF_ERROR,"CDaemonBase::InitInstance(): Failed to start remote admin service. Terminating.");
  282. return FALSE;
  283. }
  284. CTextSock::InitSvrEvents();
  285. if (!DaemonPtr->m_Service)
  286. {
  287. // Not a service
  288. UpdateSystemTray("Initializing");
  289. }
  290. GoOnline(TRUE);
  291. // Load extention dll's
  292. m_pExtModules = new CAPIHandler;
  293. m_pExtModules->LoadExtentions();
  294. return TRUE;
  295. }
  296. int CDaemonBase::ExitInstance()
  297. {
  298. if (m_Log)
  299. {
  300. m_Log->SaveAll();
  301. LogMsg(LOGF_DEBUG,"ExitInstance() - Shutting down basic server resources.");
  302. m_Log->m_LogWin = NULL;
  303. }
  304. if (m_pExtModules)
  305. {
  306. delete m_pExtModules;
  307. m_pExtModules = NULL;
  308. }
  309. m_RAOptions.SaveAll();
  310. m_AdvancedOptions.SaveAll();
  311. if (m_RemoteAdminListenSocket)
  312. delete m_RemoteAdminListenSocket;
  313. CTextSock::TerminateSvrEvents();
  314. if (m_TrayIsInitialized)
  315. UpdateSystemTray(NULL);
  316. return CWinThread::ExitInstance();
  317. }
  318. BEGIN_MESSAGE_MAP(CDaemonBase, CWinThread)
  319. //{{AFX_MSG_MAP(CDaemonBase)
  320. // NOTE - the ClassWizard will add and remove mapping macros here.
  321. //}}AFX_MSG_MAP
  322. END_MESSAGE_MAP()
  323. /////////////////////////////////////////////////////////////////////////////
  324. // CDaemonBase message handlers
  325. // Override to fix MSVC 4.2 bug
  326. BOOL CDaemonBase::PreTranslateMessage(MSG* pMsg) 
  327. {
  328. // If this is a timer callback message let it pass on through to the
  329.   // DispatchMessage call.
  330.   if( (pMsg->message==WM_TIMER) && (pMsg->hwnd==NULL) )
  331. return FALSE;
  332. return CWinThread::PreTranslateMessage(pMsg);
  333. }
  334. // General purpose message handler
  335. LRESULT CDaemonBase::GenericProcessMessage(WPARAM WParam, LPARAM LParam)
  336. {
  337. switch(WParam)
  338. {
  339. case PPT_SHUTDOWN:
  340. Shutdown((BOOL)LParam,TRUE);
  341. break;
  342. case PPT_SHUTDOWN_FAST:
  343. Shutdown((BOOL)LParam,TRUE,TRUE);
  344. break;
  345. case PPT_PAUSE:
  346. //GoOffline(TRUE);
  347. break;
  348. case PPT_CONTINUE:
  349. //GoOnlineInit(dlg->m_portNumber);
  350. break;
  351. }
  352. return TRUE;
  353. }
  354. void CDaemonBase::Shutdown(BOOL DoSave, BOOL Force, BOOL Critcal)
  355. {
  356. PostQuitMessage(0);
  357. }
  358. BOOL CDaemonBase::OnIdle( LONG lCount )
  359. {
  360. //MsgWaitForMultipleObjects(0, NULL, FALSE, 0, QS_ALLINPUT);
  361. CWinThread::OnIdle(lCount);
  362. return CSock::OnIdle(lCount);
  363. }
  364. void CDaemonBase::RefreshStats()
  365. {
  366. // Must be initialized by derived class
  367. ASSERT(GetSvrStat()->m_ServerName.IsEmpty() == FALSE);
  368. // Update Admin port number
  369. GetSvrStat()->m_RemoteAPort = m_RAOptions.m_Port;
  370. // Update events.
  371. }
  372. BOOL CDaemonBase::UpdateSystemTray(LPCSTR ToolTip)
  373. {
  374. if (DaemonPtr->m_Service)
  375. return FALSE; // Not allowed when running as a service...
  376. if (!HasShell())
  377. return FALSE; // NT 3.51 does not have the system tray.
  378. NOTIFYICONDATA nd;
  379. if (ToolTip)
  380. sprintf(nd.szTip,"%s", ToolTip);
  381. else
  382. nd.szTip[0] = 0;
  383. nd.cbSize = sizeof(nd);
  384. nd.hWnd = m_pMainWnd->m_hWnd;
  385. nd.uID = 1;
  386. nd.uFlags = NIF_ICON | NIF_MESSAGE | (*nd.szTip ? NIF_TIP : 0);
  387. nd.uCallbackMessage = WMU_SNM;
  388. if (m_ServerStat.m_IsOnline)
  389. {
  390. if (m_ServerStat.m_UserConnections)
  391. nd.hIcon = m_SysTrayOnline;
  392. else
  393. nd.hIcon = m_SysTrayIdle;
  394. }
  395. else
  396. nd.hIcon = m_SysTrayOffline;
  397. m_TrayIsInitialized = Shell_NotifyIcon(
  398. ToolTip ? m_TrayIsInitialized ? NIM_MODIFY : NIM_ADD : NIM_DELETE , &nd);
  399. return m_TrayIsInitialized;
  400. }
  401. LONG CDaemonBase::OnTrayIconMessage(WPARAM WParam, LPARAM LParam)
  402. {
  403. if (!m_pDaemonBase)
  404. return FALSE;
  405. if (WParam == 1) 
  406. {
  407. if (LParam == WM_LBUTTONDOWN) 
  408. {
  409. //ShowWindow(SW_SHOWNORMAL);
  410. //MessageBox("Icon Clicked");
  411. return TRUE;
  412. }
  413. if (LParam == WM_RBUTTONDOWN)
  414. {
  415. POINT MousePos;
  416. GetCursorPos(&MousePos);
  417. CMenu Menu, *pMenu;
  418. Menu.LoadMenu(IDR_SVRPOPUPMENU); 
  419. pMenu = Menu.GetSubMenu(0);
  420. if (m_pDaemonBase->m_ServerStat.m_IsOnline)
  421. pMenu->EnableMenuItem(ID_MENU_GOONLINE, MF_GRAYED);
  422. else
  423. pMenu->EnableMenuItem(ID_MENU_GOOFFLINE, MF_GRAYED);
  424. CDaemonNotificationWnd::GetWin()->SetForegroundWindow();
  425. pMenu->TrackPopupMenu(TPM_RIGHTBUTTON | TPM_RIGHTALIGN, MousePos.x, MousePos.y, CDaemonNotificationWnd::GetWin());
  426. pMenu->DestroyMenu();
  427. return TRUE;
  428. }
  429. }
  430. return FALSE;
  431. }
  432. BOOL CDaemonBase::GoOnline(BOOL Online)
  433. {
  434. ASSERT(FALSE); // Must be overridden.
  435. return FALSE;
  436. }
  437. BOOL CDaemonBase::StartManager()
  438. {
  439. CString cBuf;
  440. LPTSTR NotUsed;
  441. char Path[MAX_PATH];
  442. GetFullPathName(".\Daemon.wdm", MAX_PATH, Path, &NotUsed);
  443. HINSTANCE Rval = ShellExecute(
  444. AfxGetThread()->m_pMainWnd->m_hWnd,
  445. "open",
  446. Path,
  447. NULL,
  448. "",
  449. SW_SHOW);
  450. if (Rval <= (HINSTANCE)32)
  451. LogMsg(LOGF_ERROR,"StartManager() - Unable to start manager.");
  452. return (Rval > (HINSTANCE)32);
  453. }
  454. ///////////////////////////////////////////////////////////////////////////////////////
  455. // Support functions
  456. VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD  dwTime)
  457. {
  458. static long count;
  459. static BOOL blink;
  460. static long LastSave;
  461. static DWORD LastCalled;
  462. if (((LastCalled + 999) > GetTickCount()) && (LastCalled < GetTickCount()))
  463. return; // Just ignore queued TIMER messages
  464. LastCalled = GetTickCount();
  465. CDaemonBase *pSvr = CDaemonBase::GetSvr();
  466. if (pSvr)
  467. pSvr->m_Log->Flush(FALSE);
  468. // Call thread idle functions and check for shutdown...
  469. }
  470. ///////////////////////////////////////////////////////////////////////////////////////
  471. // CDaemonStatusSvr
  472. CDaemonStatusSvr::CDaemonStatusSvr()
  473. {
  474. m_EventHandle = CDaemonEvent::DsRegister(EVT_STAT, (LPVOID)this, SendStat);
  475. }
  476. CDaemonStatusSvr::~CDaemonStatusSvr()
  477. {
  478. if (m_EventHandle)
  479. CDaemonEvent::DsClose(m_EventHandle);
  480. m_ServerName.Empty();
  481. m_ServerEmail.Empty();
  482. m_ServerType.Empty();
  483. m_ServerListeningIP.Empty();
  484. m_ServerStartedFmt.Empty();
  485. }
  486. // Format data for telnet output
  487. LPCSTR CDaemonStatusSvr::FormatStats(CString& cReturnBuf, BOOL IsInteractive)
  488. {
  489. char timebuf[32];
  490. CString cBuf;
  491. char RS = IsInteractive ? 'n' : 1;
  492. int Padding = IsInteractive ? 20 : 0;
  493. CLog::FormatTime(m_ServerStarted, timebuf);
  494. cReturnBuf.Empty();
  495. cBuf.Format("00 %s%c", IsInteractive ? "Server information:" : "", RS);
  496. cReturnBuf += cBuf;
  497. cBuf.Format("01 %-*s%s%c", Padding, IsInteractive ? "Type:" : "", m_ServerType, RS);
  498. cReturnBuf += cBuf;
  499. cBuf.Format("02 %-*s%s%c", Padding, IsInteractive ? "Name:" : "", m_ServerName, RS);
  500. cReturnBuf += cBuf;
  501. cBuf.Format("03 %-*s%s%c", Padding, IsInteractive ? "Created:" : "", timebuf, RS);
  502. cReturnBuf += cBuf;
  503. cBuf.Format("04 %-*s%s%c", Padding, IsInteractive ? "Shutdown:" : "", m_ShutdownPending ? "Pending" : "Not set", RS);
  504. cReturnBuf += cBuf;
  505. cBuf.Format("05 %-*s%s%c", Padding, IsInteractive ? "Online:" : "", m_IsOnline ? "Yes" : "No", RS);
  506. cReturnBuf += cBuf;
  507. cBuf.Format("06 %-*s%s%c", Padding, IsInteractive ? "Listening IP:" : "", m_ServerListeningIP, RS);
  508. cReturnBuf += cBuf;
  509. cBuf.Format("07 %-*s%d%c", Padding, IsInteractive ? "Port number:" : "", m_ServerPort, RS);
  510. cReturnBuf += cBuf;
  511. cBuf.Format("08 %-*s%d%c", Padding, IsInteractive ? "Current users:" : "", m_UserConnections, RS);
  512. cReturnBuf += cBuf;
  513. cBuf.Format("09 %-*s%d%c", Padding, IsInteractive ? "Current operators:" : "", m_OperatorConnections, RS);
  514. cReturnBuf += cBuf;
  515. cBuf.Format("10 %-*s%d%c", Padding, IsInteractive ? "Current xfers:" : "", m_FileXfers, RS);
  516. cReturnBuf += cBuf;
  517. cBuf.Format("11 %-*s%d%c", Padding, IsInteractive ? "Total users:" : "", m_UserConnectionsTotal, RS);
  518. cReturnBuf += cBuf;
  519. cBuf.Format("12 %-*s%d%c", Padding, IsInteractive ? "Total operators" : "", m_OperatorConnectionsTotal, RS);
  520. cReturnBuf += cBuf;
  521. cBuf.Format("13 %-*s%d%c", Padding, IsInteractive ? "Total xfers:" : "", m_FileXfersTotal, RS);
  522. cReturnBuf += cBuf;
  523. return cReturnBuf;
  524. }
  525. LPCSTR CDaemonStatusSvr::GetStats(CString& cBuf)
  526. {
  527. return CDaemonBase::GetSvrStat()->FormatStats(cBuf);
  528. }
  529. // Send stats to a single client (called when the clinet register to the stats.. 
  530. void CDaemonStatusSvr::SendStat(LPVOID pOrigin, CDaemonEvent *pCliEv)
  531. {
  532. CString cBuf;
  533. CDaemonStatusSvr *pMe = (CDaemonStatusSvr *)pOrigin;
  534. LPCSTR Stats = CDaemonBase::GetSvrStat()->FormatStats(cBuf, FALSE);
  535. ASSERT(AfxIsValidString(Stats));
  536. pCliEv->Event(pMe->m_EventHandle, Stats);
  537. }
  538. void CDaemonStatusSvr::SendStatToAll()
  539. {
  540. CString cBuf;
  541. LPCSTR Stats = CDaemonBase::GetSvrStat()->FormatStats(cBuf, FALSE);
  542. ASSERT(AfxIsValidString(Stats));
  543. CDaemonEvent::DsEvent(CDaemonBase::GetSvrStat()->m_EventHandle, Stats);
  544. // Update the tray icon.
  545. CString cState;
  546. if (CDaemonBase::GetSvrStat()->m_UserConnections)
  547. cState.Format("%d users", CDaemonBase::GetSvrStat()->m_UserConnections);
  548. else
  549. cState = CDaemonBase::GetSvrStat()->m_IsOnline ? "Online" : "Offline";
  550. cBuf.Format("Port %d: %s", CDaemonBase::GetSvrStat()->m_ServerPort, cState);
  551. CDaemonBase::GetSvr()->UpdateSystemTray(cBuf);
  552. }
  553. // Increment/decrement the connection counters
  554. void CDaemonStatusSvr::IncCounter(int& Current, int& Total, BOOL Add)
  555. {
  556. if (Add)
  557. {
  558. ++Current;
  559. ++Total;
  560. }
  561. else
  562. {
  563. --Current;
  564. ASSERT(Current >= 0);
  565. }
  566. SendStatToAll();
  567. }
  568. void CDaemonStatusSvr::IncUserCnt(BOOL Add)
  569. {
  570. CDaemonStatusSvr *pStat = CDaemonBase::GetSvrStat();
  571. ASSERT(AfxIsValidAddress(pStat, sizeof(CDaemonStatusSvr)));
  572. IncCounter(pStat->m_UserConnections,pStat->m_UserConnectionsTotal, Add);
  573. }
  574. void CDaemonStatusSvr::IncOperatorCnt(BOOL Add)
  575. {
  576. CDaemonStatusSvr *pStat = CDaemonBase::GetSvrStat();
  577. ASSERT(AfxIsValidAddress(pStat, sizeof(CDaemonStatusSvr)));
  578. IncCounter(pStat->m_OperatorConnections,pStat->m_OperatorConnectionsTotal, Add);
  579. }
  580. void CDaemonStatusSvr::IncXferCnt(BOOL Add)
  581. {
  582. CDaemonStatusSvr *pStat = CDaemonBase::GetSvrStat();
  583. ASSERT(AfxIsValidAddress(pStat, sizeof(CDaemonStatusSvr)));
  584. IncCounter(pStat->m_FileXfers,pStat->m_FileXfersTotal, Add);
  585. }
  586. void CDaemonStatusSvr::SetOnline(BOOL IsOnline)
  587. {
  588. CDaemonStatusSvr *pStat = CDaemonBase::GetSvrStat();
  589. ASSERT(AfxIsValidAddress(pStat, sizeof(CDaemonStatusSvr)));
  590. pStat->m_IsOnline = IsOnline;
  591. SendStatToAll();
  592. }
  593. /////////////////////////////////////////////////////////////////////////////
  594. // CMyDaemonNTSOptions - Spesific routines for logging to daemons