trekapp.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. #include "pch.h"
  2. #include <objbase.h>
  3. #include <malloc.h>
  4. //////////////////////////////////////////////////////////////////////////////
  5. //
  6. // Include the main function
  7. //
  8. //////////////////////////////////////////////////////////////////////////////
  9. #include "main.h"
  10. #include "regkey.h"
  11. extern bool g_bEnableSound = true;
  12. extern bool g_bCheckFiles;
  13. extern bool g_fZoneAuth;
  14. bool g_bSkipAutoUpdate = false;
  15. bool g_bDownloadZoneMessage = true;
  16. bool g_bDisableZoneClub = false;
  17. bool g_bDisableNewCivs = true;
  18. bool g_bQuickstart = false;
  19. bool g_bReloaded = false;
  20. int g_civStart = -1;
  21. bool g_bDownloadNewConfig = true;
  22. bool g_bAskForCDKey =
  23. #ifdef USEAUTH
  24. true;
  25. #else
  26. false;
  27. #endif
  28. //////////////////////////////////////////////////////////////////////////////
  29. //
  30. // Trek Application Implementation
  31. //
  32. //////////////////////////////////////////////////////////////////////////////
  33. #define GAME_REG_KEY "Software\\Microsoft\\Microsoft Games\\Allegiance\\1.0"
  34. typedef DWORD (*EBUPROC) (LPCTSTR lpRegKeyLocation, LPCTSTR lpEULAFileName, LPCSTR lpWarrantyFileName, BOOL fCheckForFirstRun);
  35. //
  36. // EULA related files should be in the artwork folder so that they may be autoupdated
  37. //
  38. HRESULT FirstRunEula(PathString strArtPath)
  39. {
  40. TCHAR szEULA[MAX_PATH];
  41. if (UTL::getFile("eula", ".rtf", szEULA, false, false) != S_OK)
  42. return false;
  43. // don't use += operator cause it's buggy with PathString
  44. strArtPath = strArtPath + "EBUEula.dll";
  45. HINSTANCE hMod = LoadLibrary(PCC(strArtPath));
  46. if (NULL == hMod) // can't attach to DLL
  47. {
  48. // this time, search path
  49. hMod = LoadLibrary("EBUEula.dll");
  50. if (NULL == hMod) // can't attach to DLL
  51. return E_FAIL;
  52. }
  53. EBUPROC pfnEBUEula = (EBUPROC) GetProcAddress(hMod, "EBUEula");
  54. if (NULL == pfnEBUEula) // can't find entry point
  55. {
  56. FreeLibrary(hMod);
  57. return E_FAIL;
  58. }
  59. /*
  60. TCHAR szWarranty[MAX_PATH];
  61. LoadString(GetModuleHandle(), STR_EULAFILENAME, szEULA, sizeof(szEULA));
  62. LoadString(GetModuleHandle(), STR_WARRANTYNAME, szWarranty, sizeof(szWarranty));
  63. //
  64. //This call enables both EULA and warranty accepting/viewing/printing. If your
  65. //game doesn't ship with a WARRANTY file, specifiy NULL instead of szWarranty…
  66. //The code below, for instance, works with both OEM and retail builds…
  67. //
  68. TCHAR *pszWarrantyParam = 0xFFFFFFFF != GetFileAttributes(szWarranty) ? szWarranty : NULL;
  69. */
  70. bool fAllowGameToRun = pfnEBUEula(GAME_REG_KEY, szEULA, NULL, TRUE) != 0;
  71. FreeLibrary(hMod);
  72. return (fAllowGameToRun ? S_OK : S_FALSE);
  73. }
  74. //
  75. // Check to make sure that they are running DX 7 Dsound or better
  76. //
  77. bool CheckDSoundVersion()
  78. {
  79. // Get version information from the application
  80. HMODULE hmodDSound = GetModuleHandle("dsound");
  81. if (NULL == hmodDSound) // why isn't the dll loaded???
  82. return false;
  83. char szDSoundPath[MAX_PATH];
  84. GetModuleFileName(hmodDSound, szDSoundPath, sizeof(szDSoundPath));
  85. DWORD dwTemp;
  86. DWORD dwVerInfoSize = GetFileVersionInfoSize(szDSoundPath, &dwTemp);
  87. if (0 == dwVerInfoSize)
  88. return false;
  89. void *pvVerInfo = _alloca(dwVerInfoSize);
  90. GetFileVersionInfo(szDSoundPath, NULL, dwVerInfoSize, pvVerInfo);
  91. VS_FIXEDFILEINFO *lpvsFixedFileInfo = NULL;
  92. unsigned uTemp;
  93. if (!VerQueryValue(pvVerInfo, "\\", (LPVOID*) &lpvsFixedFileInfo, &uTemp))
  94. return false;
  95. // check the version info
  96. WORD ver1 = HIWORD(lpvsFixedFileInfo->dwFileVersionMS);
  97. WORD ver2 = LOWORD(lpvsFixedFileInfo->dwFileVersionMS);
  98. WORD ver3 = HIWORD(lpvsFixedFileInfo->dwFileVersionLS);
  99. WORD ver4 = LOWORD(lpvsFixedFileInfo->dwFileVersionLS);
  100. if (ver1 > 5) // assume all major new versions work
  101. return true;
  102. if (ver1 == 5) // NT -- WARNING -- if future versions of DX go outside 4.??? and spill into NT versions, we're in trouble
  103. return ver2 > 0 || ver3 >= 2113; // ver3 == NT build #
  104. else if (ver1 == 4) // Stand-alone DX runtimes
  105. {
  106. if (ver2 > 7) // new major dx versions (DX8+)
  107. return true;
  108. else if (ver2 == 7) // DX7
  109. return ver3 > 0 || ver4 >= 700;
  110. }
  111. return false;
  112. }
  113. //
  114. // Check to make sure that they are running DX 7 Dsound or better
  115. //
  116. bool CheckFreeMemory()
  117. {
  118. const int nAppSize = 40 * 1024 * 1024;
  119. // first, try a non-invasive check to see if we would fit in the current
  120. // swap file.
  121. MEMORYSTATUS ms;
  122. GlobalMemoryStatus(&ms);
  123. if (ms.dwAvailVirtual == -1 || ms.dwAvailPhys == -1
  124. || ms.dwAvailVirtual + ms.dwAvailPhys >= nAppSize)
  125. {
  126. return true;
  127. }
  128. // if that fails, try allocating a big chunk of memory to try to force the
  129. // swap file to grow.
  130. void *pv = VirtualAlloc(NULL, nAppSize, MEM_COMMIT, PAGE_NOACCESS);
  131. if (pv)
  132. {
  133. VirtualFree(pv, 0, MEM_RELEASE);
  134. return true;
  135. }
  136. else
  137. return false;
  138. }
  139. bool CheckForAllGuard()
  140. {
  141. // Bypass any other tests if -nod is specified on the command line
  142. ZString strCmdLine(::GetCommandLine());
  143. while (!strCmdLine.IsEmpty())
  144. if (strCmdLine.GetToken() == "-nod")
  145. return true;
  146. // Load KERNEL32
  147. HINSTANCE hinstKernel32 = ::GetModuleHandle("kernel32.dll");
  148. assert(hinstKernel32);
  149. // Get the address of IsDebuggerPresent, if available
  150. typedef BOOL (WINAPI* PFNIsDebuggerPresent)(VOID);
  151. PFNIsDebuggerPresent pfnIsDebuggerPresent = (PFNIsDebuggerPresent)
  152. ::GetProcAddress(hinstKernel32, "IsDebuggerPresent");
  153. if (pfnIsDebuggerPresent)
  154. {
  155. // Indicate that we are being debugged, if we are
  156. if ((*pfnIsDebuggerPresent)())
  157. return true;
  158. }
  159. else
  160. {
  161. // Win95 doesn't support IsDebuggerPresent, so we must check some other ways
  162. // Format an event name using the current process ID
  163. char szEvent[24];
  164. sprintf(szEvent, "MSRGuard_%08X", GetCurrentProcessId());
  165. // Determine if the named event already exists
  166. HANDLE hEvent = ::OpenEvent(EVENT_ALL_ACCESS, false, szEvent);
  167. if (hEvent)
  168. {
  169. // Close the event handle and indicate that we are being debugged
  170. ::CloseHandle(hEvent);
  171. return true;
  172. }
  173. }
  174. // Get the command-line options (again)
  175. strCmdLine = ::GetCommandLine();
  176. strCmdLine.GetToken();
  177. // Get the fully-qualified path to the current process
  178. char szModulePath[_MAX_PATH];
  179. GetModuleFileName(NULL, szModulePath, sizeof(szModulePath));
  180. char szDrive[_MAX_DRIVE], szDir[_MAX_DIR];
  181. _splitpath(szModulePath, szDrive, szDir, NULL, NULL);
  182. _makepath(szModulePath, szDrive, szDir, NULL, NULL);
  183. // Get the ArtPath, since that's where AllGuard.exe should be
  184. HKEY hKey = NULL;
  185. if (ERROR_SUCCESS != ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, ALLEGIANCE_REGISTRY_KEY_ROOT, 0, KEY_READ, &hKey))
  186. return true; // If it can't be read, just keep running
  187. char szArtPath[_MAX_PATH];
  188. DWORD cbArtPath = sizeof(szArtPath);
  189. if (ERROR_SUCCESS != ::RegQueryValueEx(hKey, "ArtPath", NULL, NULL, (BYTE*)&szArtPath, &cbArtPath))
  190. {
  191. lstrcpy(szArtPath, szModulePath);
  192. lstrcat(szArtPath, "artwork\\");
  193. cbArtPath = lstrlen(szArtPath);
  194. }
  195. else if ('\\' != szArtPath[cbArtPath - 1])
  196. {
  197. lstrcat(szArtPath, "\\");
  198. ++cbArtPath;
  199. }
  200. ::RegCloseKey(hKey);
  201. // Append the AllGuard.exe filename and parameters
  202. char szAllGuard[_MAX_PATH * 4];
  203. sprintf(szAllGuard, "\"%sAllGuard.exe\" %s", szArtPath, (LPCSTR)strCmdLine);
  204. // Create the AllGuard.exe process
  205. STARTUPINFO si = {sizeof(si)};
  206. PROCESS_INFORMATION pi;
  207. if (!::CreateProcess(NULL, szAllGuard, NULL, NULL, false, 0, NULL, szModulePath, &si, &pi))
  208. return true; // If it can't be created, just keep running
  209. // Indicate false to exit this instance of the process
  210. return false;
  211. }
  212. class TrekAppImpl : public EffectApp {
  213. public:
  214. TrekAppImpl()
  215. {
  216. AddRef();
  217. }
  218. HRESULT Initialize(const ZString& strCommandLine)
  219. {
  220. _controlfp(_PC_53, _MCW_PC);
  221. //
  222. // Make sure reloader finished correctly--this must be first before any other files are opened
  223. //
  224. //
  225. {
  226. // Make sure the current path is where Allegiance.exe is for the AutoUpdate:
  227. // For Download -AND- for Reloader.exe -AND- Loading FileList which happens
  228. // when client logs onto lobby
  229. //
  230. char path[MAX_PATH + 16];
  231. ::GetModuleFileName(NULL, path, MAX_PATH);
  232. char* p = strrchr(path, '\\');
  233. if (!p)
  234. p = path;
  235. else
  236. p++;
  237. *p = 0; // erase filename
  238. ::SetCurrentDirectory(path);
  239. HKEY hKey;
  240. DWORD dwType;
  241. char szValue[MAX_PATH];
  242. DWORD cbValue = MAX_PATH;
  243. // NOTE: please keep reloader.cpp's GetArtPath() in sync with this!!!
  244. if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, ALLEGIANCE_REGISTRY_KEY_ROOT, 0, KEY_READ, &hKey))
  245. {
  246. // Get MoveInProgress from registry
  247. if (ERROR_SUCCESS == ::RegQueryValueEx(hKey, "MoveInProgress", NULL, &dwType, (unsigned char*)&szValue, &cbValue) &&
  248. *((DWORD*)szValue) == 1)
  249. {
  250. if (::MessageBox(NULL, "The AutoUpdate process failed to finish. Try again to finish? (YES is recommended)", "Error", MB_ICONERROR | MB_YESNO) == IDYES)
  251. {
  252. if (!LaunchReloaderAndExit(false))
  253. {
  254. ::MessageBox(NULL, "Couldn't launch Reloader.exe", "Fatal Error", MB_ICONERROR);
  255. ::ExitProcess(0);
  256. return S_FALSE;
  257. }
  258. }
  259. else
  260. {
  261. ::ExitProcess(0);
  262. return S_FALSE;
  263. }
  264. }
  265. ::RegCloseKey(hKey);
  266. }
  267. }
  268. //
  269. // Check to see if we are being debugged
  270. //
  271. if (!CheckForAllGuard())
  272. return S_FALSE;
  273. //
  274. // Check for sufficient free memory
  275. //
  276. if (!CheckFreeMemory())
  277. {
  278. if (MessageBox(NULL,
  279. "You are low on free memory and/or hard drive space. "
  280. "You may experience proplems running Allegiance. Run anyway?",
  281. "Allegiance",
  282. MB_ICONERROR | MB_YESNO
  283. ) != IDYES)
  284. {
  285. ::ExitProcess(0);
  286. return S_FALSE;
  287. }
  288. }
  289. //
  290. // Check the DSound version
  291. //
  292. if (!CheckDSoundVersion())
  293. {
  294. MessageBox(NULL,
  295. "Allegiance requires DirectX 7 or higher, which was not detected. "
  296. "Please re-run setup and choose to install DirectX 7.",
  297. "Allegiance",
  298. MB_ICONERROR | MB_OK
  299. );
  300. return E_FAIL;
  301. }
  302. HRESULT hr = CoInitialize(NULL);
  303. if (FAILED(hr))
  304. return hr;
  305. // Fix success HRESULT
  306. hr = S_OK;
  307. EffectApp::Initialize(strCommandLine);
  308. //
  309. // get the artpath
  310. //
  311. PathString pathStr; // = ZString::GetProfileString("Federation", "ArtPath");
  312. HKEY hKey;
  313. DWORD dwType;
  314. char szValue[MAX_PATH];
  315. DWORD dwValue;
  316. DWORD cbValue = MAX_PATH;
  317. // NOTE: please keep reloader.cpp's GetArtPath() in sync with this!!!
  318. if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, ALLEGIANCE_REGISTRY_KEY_ROOT, 0, KEY_READ, &hKey))
  319. {
  320. // Get the art path from the registry
  321. if (ERROR_SUCCESS != ::RegQueryValueEx(hKey, "ArtPath", NULL, &dwType, (unsigned char*)&szValue, &cbValue))
  322. {
  323. // Set ArtPath to be relative to the application path
  324. GetModuleFileNameA(NULL, szValue, MAX_PATH);
  325. char* p = strrchr(szValue, '\\');
  326. if (!p)
  327. p = szValue;
  328. else
  329. p++;
  330. strcpy(p, "artwork");
  331. //Create a subdirectory for the artwork (nothing will happen if it already there)
  332. CreateDirectoryA(szValue, NULL);
  333. }
  334. pathStr = szValue;
  335. cbValue = MAX_PATH; // reset this
  336. // Start the frame rate data log, if necessary
  337. if (ERROR_SUCCESS == ::RegQueryValueEx(hKey, "LogFrameData", NULL, &dwType, (unsigned char*)&dwValue, &cbValue))
  338. {
  339. cbValue = MAX_PATH;
  340. if (dwValue==1)
  341. {
  342. if (ERROR_SUCCESS == ::RegQueryValueEx(hKey, "LogFrameDataPath", NULL, &dwType, (unsigned char*)&szValue, &cbValue))
  343. {
  344. if (strlen(szValue)>0)
  345. {
  346. ZString strFile = szValue;
  347. g_pzfFrameDump = new ZWriteFile(strFile);
  348. // check for a valid file handle
  349. if (g_pzfFrameDump->IsValid())
  350. {
  351. // dump out the header row of data
  352. g_pzfFrameDump->Write(
  353. "Mspf,"
  354. "Fps,"
  355. "Warps,"
  356. "Ships,"
  357. "Projectiles,"
  358. "Asteroids,"
  359. "Stations,"
  360. "Treasures,"
  361. "Missiles,"
  362. "SectorWarps,"
  363. "SectorShips,"
  364. "SectorProjectiles,"
  365. "SectorAsteroids,"
  366. "SectorStations,"
  367. "SectorTreasures,"
  368. "SectorMissiles,"
  369. "Triangles,"
  370. "DrawStringCalls,"
  371. "Chars"
  372. "\n"
  373. );
  374. }
  375. else
  376. {
  377. // pop up error message box
  378. MessageBox(NULL, "Framerate log file location is invalid.\n"
  379. "Use CliConfig to set the framerate log file location to "
  380. "a valid location.",
  381. "Framerate Logging Error", MB_ICONEXCLAMATION | MB_OK);
  382. }
  383. }
  384. }
  385. }
  386. }
  387. ::RegCloseKey(hKey);
  388. }
  389. if (pathStr.IsEmpty()) {
  390. // marksn: to make everyone consistent, this should go back to getmodulefilename path
  391. // like for convex hull and sounds
  392. // pathStr = PathString::GetCurrentDirectory() + "artwork";
  393. char logFileName[MAX_PATH + 16];
  394. GetModuleFileName(NULL, logFileName, MAX_PATH);
  395. char* p = strrchr(logFileName, '\\');
  396. if (!p)
  397. p = logFileName;
  398. else
  399. p++;
  400. strcpy(p, "artwork");
  401. pathStr = logFileName;
  402. }
  403. GetModeler()->SetArtPath(pathStr);
  404. UTL::SetArtPath(pathStr);
  405. {
  406. HRESULT hr = FirstRunEula(pathStr);
  407. if (hr == E_FAIL)
  408. {
  409. ::MessageBox(NULL, "Error while trying to load ebueula.dll. Please reboot and retry. If it still fails, reinstall Allegiance", "Initialization Error", MB_OK);
  410. return S_FALSE;
  411. }
  412. else
  413. if (hr == S_FALSE)
  414. {
  415. ::MessageBox(NULL, "You must accept the End User License Agreement before playing the Allegiance", "Allegiance", MB_OK);
  416. return S_FALSE;
  417. }
  418. else
  419. {
  420. assert(hr == S_OK);
  421. }
  422. }
  423. //
  424. // load the fonts
  425. //
  426. TrekResources::Initialize(GetModeler());
  427. //
  428. // Initialize the runtime
  429. //
  430. srand((unsigned)timeGetTime());
  431. //
  432. // Parse the command line
  433. //
  434. bool bLogonDialog = true;
  435. bool bStartOffline = false;
  436. bool bStartTraining = false;
  437. bool bMovies = true;
  438. bool bSingleInstance = true;
  439. bool bSoftware = false;
  440. bool bHardware = false;
  441. bool bPrimary = false;
  442. bool bSecondary = false;
  443. ZString strMap;
  444. PCC pcc = strCommandLine;
  445. CommandLineToken token(pcc, strCommandLine.GetLength());
  446. while (token.MoreTokens()) {
  447. ZString str;
  448. if (token.IsMinus(str))
  449. {
  450. if (str == "training") {
  451. bStartTraining = true;
  452. bLogonDialog = false;
  453. bMovies = false;
  454. } else if (str == "software") {
  455. bSoftware = true;
  456. } else if (str == "hardware") {
  457. bHardware = true;
  458. } else if (str == "primary") {
  459. bPrimary = true;
  460. } else if (str == "secondary") {
  461. bSecondary = true;
  462. } else if (str == "nooutput") {
  463. g_bOutput = false;
  464. } else if (str == "quickstart") {
  465. g_bQuickstart = true;
  466. float civStart;
  467. if (token.IsNumber(civStart))
  468. g_civStart = (int)civStart;
  469. } else if (str == "nocfgdl") {
  470. g_bDownloadNewConfig = false;
  471. } else if (str == "checkfiles") {
  472. g_bCheckFiles = true;
  473. } else if (str == "noautoupdate") {
  474. g_bSkipAutoUpdate = true;
  475. } else if (str == "nosound") {
  476. g_bEnableSound = false;
  477. } else if (str == "nomessage") {
  478. g_bDownloadZoneMessage = false;
  479. } else if (str == "nomovies") {
  480. bMovies = false;
  481. } else if (str == "zone") {
  482. g_bDisableZoneClub = false;
  483. } else if (str == "newcivs") {
  484. g_bDisableNewCivs = false;
  485. } else if (str == "map") {
  486. if (token.IsString(strMap))
  487. {
  488. bStartOffline = true;
  489. bLogonDialog = false;
  490. }
  491. } else if(str == "reloaded") {
  492. //
  493. // reloaded after an auto-update
  494. //
  495. //g_bReloaded = true;
  496. // TODO: make two types of reloaded: one for internet, one for zone
  497. // that way we know how to log on. Right now there it just relogs on
  498. // using internet connect
  499. } else if (str == "multi") {
  500. bSingleInstance = false;
  501. } else if (str == "noauth") {
  502. g_fZoneAuth = false;
  503. } else if (str == "cdkey") {
  504. g_bAskForCDKey = true;
  505. }
  506. }
  507. else
  508. if (token.IsString(str))
  509. {
  510. // do nothing if string (just skip it!)...this avoids infinite loops if given bad command-lines
  511. }
  512. }
  513. //
  514. // Check for other running copies of the app
  515. //
  516. if (bSingleInstance)
  517. {
  518. HWND hOldInstance = FindWindow(TrekWindow::GetTopLevelWindowClassname(),
  519. TrekWindow::GetWindowTitle());
  520. // if we found another copy of the app
  521. if (hOldInstance)
  522. {
  523. // find out if it has any popups
  524. HWND hPopup = GetLastActivePopup(hOldInstance);
  525. // Bring the main window to the top.
  526. if (SetForegroundWindow(hOldInstance))
  527. {
  528. // If the old instance was minimized, restore it.
  529. if (IsIconic(hOldInstance))
  530. {
  531. ShowWindow(hOldInstance, SW_RESTORE);
  532. }
  533. // If the old instance had a pop-up, bring that to the foreground
  534. if (hPopup != hOldInstance)
  535. {
  536. SetForegroundWindow(hPopup);
  537. }
  538. }
  539. return S_FALSE;
  540. }
  541. }
  542. //
  543. // Create the window
  544. //
  545. TRef<TrekWindow> pwindow =
  546. TrekWindow::Create(
  547. this,
  548. strCommandLine,
  549. bMovies,
  550. bSoftware,
  551. bHardware,
  552. bPrimary,
  553. bSecondary
  554. );
  555. if (!pwindow->IsValid()) {
  556. return E_FAIL;
  557. }
  558. //
  559. // Handling command line options
  560. //
  561. if (bStartTraining)
  562. GetWindow ()->screen (ScreenIDTrainScreen);
  563. return hr;
  564. }
  565. void Terminate()
  566. {
  567. EffectApp::Terminate();
  568. CoUninitialize();
  569. }
  570. } g_trekImpl;