AdminServer.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. /*-------------------------------------------------------------------------
  2. * fedsrv\AdminServer.CPP
  3. *
  4. * Implementation of CAdminServer
  5. *
  6. * Owner:
  7. *
  8. * Copyright 1986-1999 Microsoft Corporation, All Rights Reserved
  9. *-----------------------------------------------------------------------*/
  10. #include "pch.h"
  11. /////////////////////////////////////////////////////////////////////////////
  12. // External References
  13. extern Global g;
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CAdminServer
  16. TC_OBJECT_EXTERN_NON_CREATEABLE_IMPL(CAdminServer)
  17. /////////////////////////////////////////////////////////////////////////////
  18. // ISupportsErrorInfo Interface Methods
  19. STDMETHODIMP CAdminServer::InterfaceSupportsErrorInfo(REFIID riid)
  20. {
  21. static const IID* arr[] =
  22. {
  23. &IID_IAdminServer
  24. };
  25. for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
  26. {
  27. if (InlineIsEqualGUID(*arr[i],riid))
  28. return S_OK;
  29. }
  30. return S_FALSE;
  31. }
  32. /////////////////////////////////////////////////////////////////////////////
  33. // IAdminServer Interface Methods
  34. /*-------------------------------------------------------------------------
  35. * get_Games()
  36. *-------------------------------------------------------------------------
  37. * Purpose:
  38. *
  39. *
  40. */
  41. STDMETHODIMP CAdminServer::get_Games(IAdminGames** ppAdminGames)
  42. {
  43. //
  44. // Create a Games object
  45. //
  46. return GetAGCGlobal()->GetAGCObject(CFSMission::GetMissions(),
  47. IID_IAdminGames, (void**)ppAdminGames);
  48. }
  49. /*-------------------------------------------------------------------------
  50. * get_cPlayers()
  51. *-------------------------------------------------------------------------
  52. * Purpose:
  53. * Determine the number of players currently playing
  54. *
  55. */
  56. STDMETHODIMP CAdminServer::get_PlayerCount(long* pVal)
  57. {
  58. CLEAROUT(pVal, (long)g.pServerCounters->cPlayersOnline);
  59. return S_OK;
  60. }
  61. /*-------------------------------------------------------------------------
  62. * get_cMissions()
  63. *-------------------------------------------------------------------------
  64. * Purpose:
  65. * Determine the number of missions (that is, games) currently running
  66. *
  67. */
  68. STDMETHODIMP CAdminServer::get_MissionCount(long* pVal)
  69. {
  70. const ListFSMission* plistMission = CFSMission::GetMissions();
  71. CLEAROUT(pVal, (long)plistMission->n());
  72. return S_OK;
  73. }
  74. /*-------------------------------------------------------------------------
  75. * SendMsg()
  76. *-------------------------------------------------------------------------
  77. * Purpose:
  78. * Send a message to everyone on the server
  79. *
  80. * Note: If no one is in the sector, no messages are sent
  81. */
  82. STDMETHODIMP CAdminServer::SendMsg(BSTR bstrMessage)
  83. {
  84. // Do nothing if specified string is empty
  85. if (!BSTRLen(bstrMessage))
  86. return S_OK;
  87. //
  88. // Iterate thru all missions
  89. //
  90. const ListFSMission * plistMission = CFSMission::GetMissions();
  91. if (plistMission->n())
  92. {
  93. // Convert the specified string to ANSI once
  94. USES_CONVERSION;
  95. LPCSTR pszMessage = OLE2CA(bstrMessage);
  96. // Loop through and send chat to each mission
  97. for (LinkFSMission* plinkMission = plistMission->first(); plinkMission; plinkMission = plinkMission->next())
  98. {
  99. CFSMission * pfsMission = plinkMission->data();
  100. pfsMission->GetSite()->SendChat(
  101. NULL, //from system
  102. CHAT_EVERYONE, //send to everyone
  103. NA, //no target ship
  104. NA, //No voice over
  105. pszMessage,
  106. c_cidNone,
  107. NA,
  108. NA,
  109. NULL,
  110. true); // true means object model generated
  111. }
  112. }
  113. // Indicate success
  114. return S_OK;
  115. }
  116. /*-------------------------------------------------------------------------
  117. * CAdminServer::get_Users()
  118. *-------------------------------------------------------------------------
  119. * Purpose:
  120. * Returns the collection of users currently on the server.
  121. *
  122. */
  123. STDMETHODIMP CAdminServer::get_Users(/*[out, retval]*/ IAdminUsers** ppAdminUsers)
  124. {
  125. static CAdminSponsor<CAdminUsers> s_UsersSponsor;
  126. RETURN_FAILED (s_UsersSponsor.Make(IID_IAdminUsers, (void**)ppAdminUsers));
  127. return S_OK;
  128. }
  129. /*-------------------------------------------------------------------------
  130. * get_FindUser()
  131. *-------------------------------------------------------------------------
  132. * Purpose:
  133. * Converts a user name to an CAdminUser Object.
  134. *
  135. * Input:
  136. * bstr: name of the user.
  137. *
  138. * Output:
  139. * a pointer to an User that cooresponds to the name supplied; or NULL if not found
  140. */
  141. STDMETHODIMP CAdminServer::get_FindUser(BSTR bstrName, IAdminUser** ppUser)
  142. {
  143. *ppUser = NULL; // assume not found for now
  144. USES_CONVERSION;
  145. char * szName = OLE2A(bstrName);
  146. const ListFSMission * plistMission = CFSMission::GetMissions();
  147. for (LinkFSMission * plinkMission = plistMission->first(); plinkMission; plinkMission = plinkMission->next())
  148. {
  149. CFSMission* pfsMission = (CFSMission*)(plinkMission->data());
  150. if (pfsMission)
  151. {
  152. ImissionIGC * pMission = pfsMission->GetIGCMission();
  153. if (pMission)
  154. {
  155. for (ShipLinkIGC* psl = pMission->GetShips()->first(); (psl != NULL); psl = psl->next())
  156. {
  157. CFSShip* pfsShip = (CFSShip*)(psl->data()->GetPrivateData());
  158. if(pfsShip->IsPlayer())
  159. {
  160. CFSPlayer * pfsPlayer = pfsShip->GetPlayer();
  161. if (_stricmp(szName, pfsShip->GetName()) == 0)
  162. {
  163. RETURN_FAILED (pfsPlayer->CAdminSponsor<CAdminUser>::Make(IID_IAdminUser, (void**)ppUser));
  164. pfsPlayer->CAdminSponsor<CAdminUser>::GetLimb()->Init(pfsPlayer);
  165. return S_OK;
  166. }
  167. }
  168. }
  169. }
  170. }
  171. }
  172. return S_OK; // not found, which is ok
  173. }
  174. /*-------------------------------------------------------------------------
  175. * get_LookupUser()
  176. *-------------------------------------------------------------------------
  177. * Purpose:
  178. * Converts a unique id to an CAdminUser Object.
  179. *
  180. * Input:
  181. * id: id of the user.
  182. *
  183. * Output:
  184. * a pointer to an User that cooresponds to the id supplied; or NULL if not found
  185. */
  186. STDMETHODIMP CAdminServer::get_LookupUser(AGCUniqueID userid, IAdminUser** ppUser)
  187. {
  188. *ppUser = NULL; // assume not found for now
  189. // CLEAROUT(ppUser, (IAdminUser*)NULL);
  190. if ((userid >> 16) != AGC_AdminUser)
  191. return S_OK;
  192. AdminUserID id = userid & 0x0000FFFF;
  193. const ListFSMission * plistMission = CFSMission::GetMissions();
  194. for (LinkFSMission * plinkMission = plistMission->first(); plinkMission; plinkMission = plinkMission->next())
  195. {
  196. CFSMission* pfsMission = (CFSMission*)(plinkMission->data());
  197. if (pfsMission)
  198. {
  199. ImissionIGC * pMission = pfsMission->GetIGCMission();
  200. if (pMission)
  201. {
  202. for (ShipLinkIGC* psl = pMission->GetShips()->first(); (psl != NULL); psl = psl->next())
  203. {
  204. CFSShip* pfsShip = (CFSShip*)(psl->data()->GetPrivateData());
  205. if(pfsShip->IsPlayer())
  206. {
  207. CFSPlayer * pfsPlayer = pfsShip->GetPlayer();
  208. if (CAdminUser::DetermineID(pfsPlayer) == id)
  209. {
  210. RETURN_FAILED (pfsPlayer->CAdminSponsor<CAdminUser>::Make(IID_IAdminUser, (void**)ppUser));
  211. pfsPlayer->CAdminSponsor<CAdminUser>::GetLimb()->Init(pfsPlayer);
  212. }
  213. }
  214. }
  215. }
  216. }
  217. }
  218. return S_OK;
  219. }
  220. /*-------------------------------------------------------------------------
  221. * get_PacketsInPerSecond()
  222. *-------------------------------------------------------------------------
  223. */
  224. STDMETHODIMP CAdminServer::get_PacketsIn(long * pVal)
  225. {
  226. *pVal = 0;
  227. return Error("This property is no longer supported. Use AdminSession::PerfCounters now.");
  228. }
  229. /*-------------------------------------------------------------------------
  230. * get_PlayersOnline()
  231. *-------------------------------------------------------------------------
  232. */
  233. STDMETHODIMP CAdminServer::get_PlayersOnline(long * pVal)
  234. {
  235. *pVal = 0;
  236. return Error("This property is no longer supported. Use AdminSession::PerfCounters now.");
  237. }
  238. /*-------------------------------------------------------------------------
  239. * get_TimeInnerLoop()
  240. *-------------------------------------------------------------------------
  241. */
  242. STDMETHODIMP CAdminServer::get_TimeInnerLoop(long * pVal)
  243. {
  244. *pVal = 0;
  245. return Error("This property is no longer supported. Use AdminSession::PerfCounters now.");
  246. }
  247. /*-------------------------------------------------------------------------
  248. * get_MachineName()
  249. *-------------------------------------------------------------------------
  250. */
  251. STDMETHODIMP CAdminServer::get_MachineName(BSTR * pbstrMachine)
  252. {
  253. char szMachine[64];
  254. if (gethostname(szMachine, sizeof(szMachine)) != 0)
  255. {
  256. return Error("Cannot determine machine name.");
  257. }
  258. CComBSTR bstr(szMachine);
  259. // Detach the string to the [out] parameter
  260. CLEAROUT(pbstrMachine, (BSTR)bstr);
  261. bstr.Detach();
  262. return S_OK;
  263. }
  264. /////////////////////////////////////////////////////////////////////////////
  265. // Sets the LobbyServer onto which this server publishes its games
  266. //
  267. // Fails if called while any games are in existence.
  268. //
  269. STDMETHODIMP CAdminServer::put_LobbyServer(BSTR bstrLobbyServer)
  270. {
  271. #if defined(ALLSRV_STANDALONE)
  272. return Error("This method is not intended for standalone servers");
  273. #endif
  274. // Connect to the specified lobby, if any
  275. if (BSTRLen(bstrLobbyServer))
  276. {
  277. USES_CONVERSION;
  278. LPCSTR pszLobbyServer = OLE2CA(bstrLobbyServer);
  279. // Fail if any games are running and bstrLobbyServer is different
  280. if (0 != _stricmp(pszLobbyServer, g.strLobbyServer))
  281. {
  282. const ListFSMission * plistMission = CFSMission::GetMissions();
  283. if (plistMission->n())
  284. return Error(IDS_E_LOBBYSERVER_GAMES_EXIST, IID_IAdminServer);
  285. }
  286. HRESULT hr = ConnectToLobby(NULL);
  287. if (FAILED(hr))
  288. {
  289. #if !defined(ALLSRV_STANDALONE)
  290. _AGCModule.TriggerEvent(NULL, AllsrvEventID_ConnectError, "", -1, -1, -1, 0);
  291. #endif // !defined(ALLSRV_STANDALONE)
  292. return Error(IDS_E_CONNECT_LOBBY, IID_IAdminServer);
  293. }
  294. // Save the new LobbyServer value to the registry
  295. #if !defined(ALLSRV_STANDALONE)
  296. CRegKey key;
  297. LONG lr = key.Open(HKEY_LOCAL_MACHINE, HKLM_FedSrv);
  298. if (ERROR_SUCCESS != lr)
  299. {
  300. g.fmLobby.Shutdown();
  301. _AGCModule.TriggerEvent(NULL, AllsrvEventID_ConnectError, "", -1, -1, -1, 0);
  302. return HRESULT_FROM_WIN32(lr);
  303. }
  304. key.SetValue(pszLobbyServer, "LobbyServer");
  305. #endif // !defined(ALLSRV_STANDALONE)
  306. }
  307. else
  308. {
  309. // Disconnect from current lobby, if any
  310. DisconnectFromLobby();
  311. assert(!g.fmLobby.IsConnected());
  312. g.strLobbyServer.SetEmpty();
  313. }
  314. // Indicate success
  315. return S_OK;
  316. }
  317. /////////////////////////////////////////////////////////////////////////////
  318. //
  319. //
  320. STDMETHODIMP CAdminServer::get_LobbyServer(BSTR* pbstrLobbyServer)
  321. {
  322. // Get the current "LobbyServer" value
  323. CComBSTR bstr(g.strLobbyServer);
  324. // Detach to the [out] parameter
  325. CLEAROUT(pbstrLobbyServer, (BSTR)bstr);
  326. bstr.Detach();
  327. // Return the last HRESULT
  328. return S_OK;
  329. }
  330. /////////////////////////////////////////////////////////////////////////////
  331. //
  332. //
  333. STDMETHODIMP CAdminServer::CreateDefaultGames()
  334. {
  335. #if defined(ALLSRV_STANDALONE)
  336. // Don't create new games if any games are already there. This is to
  337. // prevent starting two copies of the default games.
  338. const ListFSMission * plistMission = CFSMission::GetMissions();
  339. if (plistMission->n())
  340. return S_FALSE;
  341. StartDefaultGames();
  342. return S_OK;
  343. #else
  344. return E_NOTIMPL;
  345. #endif
  346. }
  347. /////////////////////////////////////////////////////////////////////////////
  348. //
  349. //
  350. STDMETHODIMP CAdminServer::get_PublicLobby(VARIANT_BOOL *pVal)
  351. {
  352. CLEAROUT(pVal, VARBOOL(g.fm.GetHostApplicationGuid() == FEDSRV_GUID));
  353. return S_OK;
  354. }
  355. /////////////////////////////////////////////////////////////////////////////
  356. //
  357. //
  358. STDMETHODIMP CAdminServer::put_PublicLobby(VARIANT_BOOL bPublic)
  359. {
  360. // make sure no games are present; otherwise players could have there sessions
  361. // terminated
  362. const ListFSMission * plistMission = CFSMission::GetMissions();
  363. if (plistMission->n())
  364. return Error(IDS_E_LOBBYSERVER_GAMES_EXIST, IID_IAdminServer);
  365. //
  366. // Switch between sessions as needed; Private and Public games use different
  367. // session GUIDs
  368. //
  369. if (bPublic)
  370. {
  371. if (g.fm.GetHostApplicationGuid() != FEDSRV_GUID)
  372. {
  373. // if existing session running, kill it
  374. if (g.fm.GetHostApplicationGuid() != GUID_NULL)
  375. g.fm.Shutdown();
  376. printf("Preparing public session for clients ... ");
  377. #if !defined(ALLSRV_STANDALONE)
  378. _AGCModule.TriggerEvent(NULL, AllsrvEventID_HostSession, "", -1, -1, -1, 0);
  379. #endif
  380. HRESULT hr = g.fm.HostSession(FEDSRV_GUID, false, 0 /*g.hPlayerEvent*/, g.fProtocol
  381. #if defined(MONOLITHIC_DPLAY) && defined(ALLSRV_STANDALONE)
  382. , false
  383. #endif
  384. );
  385. if (FAILED(hr))
  386. {
  387. #if !defined(ALLSRV_STANDALONE)
  388. _AGCModule.TriggerEvent(NULL, AllsrvEventID_CantHostSession, "", -1, -1, -1, 0);
  389. #endif
  390. printf("failed.\n");
  391. return E_FAIL;
  392. }
  393. printf("succeeded.\n");
  394. }
  395. bool bSupposedToConnectToLobby;
  396. #if defined(ALLSRV_STANDALONE)
  397. bSupposedToConnectToLobby = true;
  398. #else
  399. bSupposedToConnectToLobby = !g.strLobbyServer.IsEmpty();
  400. #endif
  401. if (bSupposedToConnectToLobby)
  402. {
  403. HRESULT hr = ConnectToLobby(NULL);
  404. if (FAILED(hr))
  405. {
  406. #if !defined(ALLSRV_STANDALONE)
  407. _AGCModule.TriggerEvent(NULL, AllsrvEventID_ConnectError, "", -1, -1, -1, 0);
  408. #endif // !defined(ALLSRV_STANDALONE)
  409. return Error(IDS_E_CONNECT_LOBBY, IID_IAdminServer);
  410. }
  411. }
  412. else
  413. {
  414. #if !defined(ALLSRV_STANDALONE)
  415. _AGCModule.TriggerEvent(NULL, AllsrvEventID_NoLobby, "", -1, -1, -1, 0);
  416. #endif
  417. }
  418. }
  419. else
  420. {
  421. #if !defined(ALLSRV_STANDALONE)
  422. return Error("Only standalone servers can have private games");
  423. #endif
  424. //
  425. // Setup the private session for standalone server
  426. //
  427. if (g.fm.GetHostApplicationGuid() != FEDSRV_STANDALONE_PRIVATE_GUID)
  428. {
  429. // if existing session running, kill it
  430. if (g.fm.GetHostApplicationGuid() != GUID_NULL)
  431. g.fm.Shutdown();
  432. printf("Preparing LAN session for clients ... ");
  433. #if !defined(ALLSRV_STANDALONE)
  434. _AGCModule.TriggerEvent(NULL, AllsrvEventID_HostSession, "", -1, -1, -1, 0);
  435. #endif
  436. HRESULT hr = g.fm.HostSession(FEDSRV_STANDALONE_PRIVATE_GUID, false, 0 /*g.hPlayerEvent*/, g.fProtocol
  437. #if defined(MONOLITHIC_DPLAY) && defined(ALLSRV_STANDALONE)
  438. , false
  439. #endif
  440. );
  441. if (FAILED(hr))
  442. {
  443. #if !defined(ALLSRV_STANDALONE)
  444. _AGCModule.TriggerEvent(NULL, AllsrvEventID_CantHostSession, "", -1, -1, -1, 0);
  445. #endif
  446. printf("failed.\n");
  447. return E_FAIL;
  448. }
  449. printf("succeeded.\n");
  450. }
  451. }
  452. return S_OK;
  453. }