shadowswitcherdlg.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. // ShadowSwitcherDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "ShadowSwitcher.h"
  5. #include "ShadowSwitcherDlg.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. void assert(bool b)
  9. {
  10. if (!b) {
  11. DebugBreak();
  12. }
  13. }
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #else
  17. void assert(bool b) {}
  18. #endif
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CShadowSwitcherDlg dialog
  21. CShadowSwitcherDlg::CShadowSwitcherDlg(CWnd* pParent /*=NULL*/)
  22. : CDialog(CShadowSwitcherDlg::IDD, pParent)
  23. {
  24. //{{AFX_DATA_INIT(CShadowSwitcherDlg)
  25. // NOTE: the ClassWizard will add member initialization here
  26. //}}AFX_DATA_INIT
  27. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  28. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  29. }
  30. CShadowSwitcherDlg::~CShadowSwitcherDlg()
  31. {
  32. ::RegCloseKey(m_hKey);
  33. }
  34. void CShadowSwitcherDlg::DoDataExchange(CDataExchange* pDX)
  35. {
  36. CDialog::DoDataExchange(pDX);
  37. //{{AFX_DATA_MAP(CShadowSwitcherDlg)
  38. DDX_Control(pDX, IDC_Shadow, m_btnShadow);
  39. DDX_Control(pDX, IDC_Retail, m_btnRetail);
  40. DDX_Control(pDX, IDC_Delete, m_btnDelete);
  41. DDX_Control(pDX, IDC_Text, m_text);
  42. //}}AFX_DATA_MAP
  43. }
  44. BEGIN_MESSAGE_MAP(CShadowSwitcherDlg, CDialog)
  45. //{{AFX_MSG_MAP(CShadowSwitcherDlg)
  46. ON_WM_PAINT()
  47. ON_WM_QUERYDRAGICON()
  48. ON_BN_CLICKED(IDC_Delete, OnDelete)
  49. ON_BN_CLICKED(IDC_Retail, OnRetail)
  50. ON_BN_CLICKED(IDC_Shadow, OnShadow)
  51. //}}AFX_MSG_MAP
  52. END_MESSAGE_MAP()
  53. /////////////////////////////////////////////////////////////////////////////
  54. // CShadowSwitcherDlg message handlers
  55. BOOL CShadowSwitcherDlg::OnInitDialog()
  56. {
  57. CDialog::OnInitDialog();
  58. // Set the icon for this dialog. The framework does this automatically
  59. // when the application's main window is not a dialog
  60. SetIcon(m_hIcon, TRUE); // Set big icon
  61. SetIcon(m_hIcon, FALSE); // Set small icon
  62. //
  63. // Get the reg key
  64. //
  65. HRESULT hr =
  66. ::RegCreateKeyEx(
  67. HKEY_LOCAL_MACHINE,
  68. "Software\\Microsoft\\Microsoft Games\\Allegiance\\1.0",
  69. 0,
  70. "",
  71. REG_OPTION_NON_VOLATILE,
  72. KEY_READ | KEY_WRITE,
  73. NULL,
  74. &m_hKey,
  75. NULL
  76. );
  77. //
  78. // Get the exe and art paths
  79. //
  80. if (
  81. FAILED(hr)
  82. || (!GetRegistrySetting("EXE Path", m_achExePath, sizeof(m_achExePath)))
  83. || (!GetRegistrySetting( "ArtPath", m_achArtPath, sizeof(m_achArtPath)))
  84. ) {
  85. Error("Failure accessing Allegiance registry settings.");
  86. }
  87. //
  88. // Make sure the art path is in a valid location relative to the exe
  89. //
  90. if (!CheckArtPath()) {
  91. Error("The artpath must be a direct child of the Allegiance exe path for this utility to work.");
  92. }
  93. //
  94. // Figure out the paths for the shadow and retail directories
  95. //
  96. strcpy(m_achShadowPath, m_achExePath);
  97. strcpy(m_achShadowPath + strlen(m_achExePath), "Shadow");
  98. strcpy(m_achRetailPath, m_achExePath);
  99. strcpy(m_achRetailPath + strlen(m_achExePath), "Retail");
  100. //
  101. // Update the internal state
  102. //
  103. Update();
  104. // TODO: Add extra initialization here
  105. return TRUE; // return TRUE unless you set the focus to a control
  106. }
  107. // If you add a minimize button to your dialog, you will need the code below
  108. // to draw the icon. For MFC applications using the document/view model,
  109. // this is automatically done for you by the framework.
  110. void CShadowSwitcherDlg::OnPaint()
  111. {
  112. if (IsIconic())
  113. {
  114. CPaintDC dc(this); // device context for painting
  115. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  116. // Center icon in client rectangle
  117. int cxIcon = GetSystemMetrics(SM_CXICON);
  118. int cyIcon = GetSystemMetrics(SM_CYICON);
  119. CRect rect;
  120. GetClientRect(&rect);
  121. int x = (rect.Width() - cxIcon + 1) / 2;
  122. int y = (rect.Height() - cyIcon + 1) / 2;
  123. // Draw the icon
  124. dc.DrawIcon(x, y, m_hIcon);
  125. }
  126. else
  127. {
  128. CDialog::OnPaint();
  129. }
  130. }
  131. // The system calls this to obtain the cursor to display while the user drags
  132. // the minimized window.
  133. HCURSOR CShadowSwitcherDlg::OnQueryDragIcon()
  134. {
  135. return (HCURSOR) m_hIcon;
  136. }
  137. void CShadowSwitcherDlg::DeleteDirectory(char* pch)
  138. {
  139. CString strMatch = CString(pch) + "\\*.*";
  140. WIN32_FIND_DATA data;
  141. HANDLE hff = FindFirstFile(strMatch, &data);
  142. if (hff == INVALID_HANDLE_VALUE) {
  143. Error("Error reading directory contents");
  144. }
  145. while (true) {
  146. UpdateText((char*)LPCTSTR(CString("Deleting ") + CString(data.cFileName)));
  147. if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  148. if (
  149. (strcmp(data.cFileName, "." ) != 0)
  150. && (strcmp(data.cFileName, "..") != 0)
  151. ) {
  152. DeleteDirectory(
  153. (char*)LPCTSTR(CString(pch) + CString("\\") + CString(data.cFileName))
  154. );
  155. }
  156. } else {
  157. CString strFile = CString(pch) + CString("\\") + CString(data.cFileName);
  158. if (
  159. (!SetFileAttributes((char*)LPCTSTR(strFile), FILE_ATTRIBUTE_NORMAL))
  160. || (!DeleteFile((char*)LPCTSTR(strFile)))
  161. ) {
  162. Error("Error deleting file.");
  163. }
  164. }
  165. if (!FindNextFile(hff, &data)) {
  166. if (GetLastError() == ERROR_NO_MORE_FILES) {
  167. FindClose(hff);
  168. if (!RemoveDirectory(pch)) {
  169. Error("Error removing directory");
  170. }
  171. return;
  172. }
  173. Error("Error deleting directory contents");
  174. }
  175. }
  176. }
  177. void CShadowSwitcherDlg::CopyDirectory(char* pchFrom, char* pchTo)
  178. {
  179. if (!CreateDirectory(pchTo, NULL)) {
  180. Error("Unable to create directory.");
  181. }
  182. CString strMatch = CString(pchFrom) + "\\*.*";
  183. WIN32_FIND_DATA data;
  184. HANDLE hff = FindFirstFile(strMatch, &data);
  185. if (hff == INVALID_HANDLE_VALUE) {
  186. Error("Error reading directory contents");
  187. }
  188. while (true) {
  189. UpdateText((char*)LPCTSTR(CString("Copying ") + CString(data.cFileName)));
  190. if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  191. if (
  192. (strcmp(data.cFileName, "." ) != 0)
  193. && (strcmp(data.cFileName, "..") != 0)
  194. ) {
  195. CopyDirectory(
  196. (char*)LPCTSTR(CString(pchFrom) + CString("\\") + CString(data.cFileName)),
  197. (char*)LPCTSTR(CString(pchTo ) + CString("\\") + CString(data.cFileName))
  198. );
  199. }
  200. } else {
  201. if (!
  202. CopyFile(
  203. (char*)LPCTSTR(CString(pchFrom) + CString("\\") + CString(data.cFileName)),
  204. (char*)LPCTSTR(CString(pchTo ) + CString("\\") + CString(data.cFileName)),
  205. true
  206. )
  207. ) {
  208. Error("Error copying file.");
  209. }
  210. }
  211. if (!FindNextFile(hff, &data)) {
  212. if (GetLastError() == ERROR_NO_MORE_FILES) {
  213. FindClose(hff);
  214. return;
  215. }
  216. Error("Error reading directory contents");
  217. }
  218. }
  219. }
  220. char g_achShadow[] = ". Betaworld is in use.";
  221. char g_achWasShadow[] = ". Betaworld has been used.";
  222. bool EndMatches(char* psz, char* pszLast)
  223. {
  224. int length = strlen(psz);
  225. int lengthLast = strlen(pszLast);
  226. if (length < lengthLast) {
  227. return false;
  228. }
  229. int delta = length - lengthLast;
  230. for (int index = 0; index < lengthLast; index++) {
  231. if (pszLast[index] != psz[index + delta]) {
  232. return false;
  233. }
  234. }
  235. return true;
  236. }
  237. void CShadowSwitcherDlg::Install()
  238. {
  239. if (!m_bInstalled) {
  240. m_bInstalled = true;
  241. CopyDirectory(m_achExePath, m_achShadowPath);
  242. if (!EndMatches(m_achPID, g_achWasShadow)) {
  243. CString strPID = m_achPID;
  244. CString newPID = strPID + CString(g_achWasShadow);
  245. SetRegistrySetting("PID", (char*)LPCTSTR(newPID));
  246. }
  247. SetRegistrySetting("SaveCfgFile", "None");
  248. Update();
  249. }
  250. }
  251. void CShadowSwitcherDlg::OnDelete()
  252. {
  253. assert(m_bInstalled);
  254. if (m_bShadow) {
  255. //
  256. // Switch back to retail
  257. //
  258. OnRetail();
  259. }
  260. assert(!m_bShadow);
  261. //
  262. // Delete the shadow path
  263. //
  264. DeleteDirectory(m_achShadowPath);
  265. ::RegDeleteValue(m_hKey, "SaveCfgFile");
  266. //
  267. // Update
  268. //
  269. Update();
  270. }
  271. #define ShadowCfgString "http://Allegiance.zone.com/allegianceshadow.cfg"
  272. void CShadowSwitcherDlg::OnShadow()
  273. {
  274. //
  275. // Copy if needed
  276. //
  277. Install();
  278. //
  279. //
  280. //
  281. assert(!m_bShadow);
  282. m_bShadow = true;
  283. //
  284. // Rename the directories
  285. //
  286. if (!MoveFile(m_achExePath, m_achRetailPath)) {
  287. Error("Error renaming the retail directory");
  288. }
  289. if (!MoveFile(m_achShadowPath, m_achExePath)) {
  290. Error("Error renaming the shadow directory");
  291. }
  292. //
  293. // Change the registry
  294. //
  295. SetRegistrySetting("SaveCfgFile", m_achCfgFile);
  296. SetRegistrySetting("CfgFile", ShadowCfgString);
  297. CString strPID = m_achPID;
  298. CString newPID = strPID.Left(strPID.GetLength() - (sizeof(g_achWasShadow) - 1)) + CString(g_achShadow);
  299. SetRegistrySetting("PID", (char*)LPCTSTR(newPID));
  300. //
  301. // Update
  302. //
  303. Update();
  304. }
  305. void CShadowSwitcherDlg::OnRetail()
  306. {
  307. assert(m_bInstalled);
  308. assert(m_bShadow);
  309. m_bShadow = false;
  310. //
  311. // Rename the directories
  312. //
  313. if (!MoveFile(m_achExePath, m_achShadowPath)) {
  314. Error("Error renaming the retail directory");
  315. }
  316. if (!MoveFile(m_achRetailPath, m_achExePath)) {
  317. Error("Error renaming the shadow directory");
  318. }
  319. //
  320. // Change the registry
  321. //
  322. SetRegistrySetting("SaveCfgFile", "None");
  323. if (strcmp(m_achCfgSave, "None") == 0) {
  324. ::RegDeleteValue(m_hKey, "CfgFile");
  325. } else {
  326. SetRegistrySetting("CfgFile", m_achCfgSave);
  327. }
  328. CString strPID = m_achPID;
  329. CString newPID = strPID.Left(strPID.GetLength() - (sizeof(g_achShadow) - 1)) + CString(g_achWasShadow);
  330. SetRegistrySetting("PID", (char*)LPCTSTR(newPID));
  331. //
  332. // Update
  333. //
  334. Update();
  335. }
  336. void CShadowSwitcherDlg::UpdateText(char* psz)
  337. {
  338. m_text.SetWindowText(psz);
  339. m_text.UpdateWindow();
  340. }
  341. void CShadowSwitcherDlg::Update()
  342. {
  343. bool bExists = GetRegistrySetting("CfgFile", m_achCfgFile, sizeof(m_achCfgFile));
  344. m_bShadow =
  345. bExists
  346. && (0 == strcmp(ShadowCfgString, m_achCfgFile));
  347. if (!bExists) {
  348. strcpy(m_achCfgFile, "None");
  349. }
  350. m_bInstalled = GetRegistrySetting("SaveCfgFile", m_achCfgSave, sizeof(m_achCfgSave));
  351. GetRegistrySetting("PID", m_achPID, sizeof(m_achPID));
  352. if (m_bShadow) {
  353. m_text.SetWindowText("You are currently using the Allegiance shadow servers.");
  354. m_btnShadow.EnableWindow(false);
  355. m_btnRetail.EnableWindow(true);
  356. m_btnDelete.EnableWindow(true);
  357. } else {
  358. m_text.SetWindowText("You are currently using the Allegiance retail servers.");
  359. m_btnShadow.EnableWindow(true);
  360. m_btnRetail.EnableWindow(false);
  361. m_btnDelete.EnableWindow(m_bInstalled);
  362. }
  363. }
  364. void CShadowSwitcherDlg::Error(char *psz)
  365. {
  366. DWORD error = GetLastError();
  367. MessageBox(psz, "Error", MB_ICONERROR | MB_OK);
  368. //
  369. // Better way to exit?
  370. //
  371. _exit(0);
  372. }
  373. bool CShadowSwitcherDlg::GetRegistrySetting(char *pszValue, char *pszResult, DWORD length)
  374. {
  375. DWORD dwSize = length;
  376. DWORD dwType = REG_SZ;
  377. return
  378. ::RegQueryValueEx(m_hKey, pszValue, NULL, &dwType, (BYTE*)pszResult, &dwSize)
  379. == ERROR_SUCCESS;
  380. }
  381. void CShadowSwitcherDlg::SetRegistrySetting(char *pszValue, char *psz)
  382. {
  383. int length = strlen(psz) + 1;
  384. long result =
  385. RegSetValueEx(
  386. m_hKey,
  387. pszValue,
  388. NULL,
  389. REG_SZ,
  390. (const unsigned char*)psz,
  391. length
  392. );
  393. if (result != ERROR_SUCCESS) {
  394. Error("Couldn't set registry key");
  395. }
  396. }
  397. bool CShadowSwitcherDlg::CheckArtPath()
  398. {
  399. int length = strlen(m_achExePath);
  400. for (int index = 0; index < length; index++) {
  401. if (m_achExePath[index] != m_achArtPath[index]) {
  402. return false;
  403. }
  404. }
  405. if (0 != strcmp(m_achArtPath + length, "\\Artwork")) {
  406. return false;
  407. }
  408. return true;
  409. }