CHATAPI.CPP 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. //
  19. // This module takes care of all the Chat API stuff
  20. //
  21. #include <list>
  22. #include "GameSpy/ghttp/ghttp.h"
  23. #include "downloadManager.h"
  24. #include "chatapi.h"
  25. //#include "api/wolapi_i.c" // This should only be in one .cpp file
  26. #include <objbase.h>
  27. #include <windows.h>
  28. #include <initguid.h>
  29. #include <olectl.h>
  30. #include <mapicode.h>
  31. #include "resource.h"
  32. #include "winblows.h"
  33. #include <crtdbg.h>
  34. #include "process.h"
  35. #include "WWDownload/registry.h"
  36. #include "WWDownload/urlBuilder.h"
  37. #include "debug.h"
  38. enum EVENT_TYPES
  39. {
  40. NOUPDATE_EVENT=0, // don't need to update
  41. ABORT_EVENT,
  42. NUM_EVENTS // keep last
  43. };
  44. HANDLE Events[NUM_EVENTS];
  45. char g_UpdateString[256]; // for the filename
  46. char g_DLTimeRem[80];
  47. char g_DLBytesLeft[80];
  48. char g_DLBPS[80];
  49. int g_Finished=0;
  50. HWND g_DownloadWindow;
  51. HWND g_ContactWindow;
  52. HWND g_PrimaryWindow;
  53. static bool checkingForPatch = false;
  54. static int checksLeft = 0;
  55. static bool cantConnect = false;
  56. static std::list<QueuedDownload> queuedDownloads;
  57. BOOL CALLBACK downloadDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam,
  58. LPARAM lParam );
  59. ///////////////////////////////////////////////////////////////////////////////////////
  60. static void startOnline( void );
  61. ///////////////////////////////////////////////////////////////////////////////////////
  62. QueuedDownload TheDownload;
  63. class DownloadManagerMunkee : public DownloadManager
  64. {
  65. public:
  66. DownloadManagerMunkee() { }
  67. virtual HRESULT OnError( int error );
  68. virtual HRESULT OnEnd();
  69. virtual HRESULT OnProgressUpdate( int bytesread, int totalsize, int timetaken, int timeleft );
  70. virtual HRESULT OnStatusUpdate( int status );
  71. virtual HRESULT downloadFile( std::string server, std::string username, std::string password, std::string file, std::string localfile, std::string regkey, bool tryResume );
  72. };
  73. ///////////////////////////////////////////////////////////////////////////////////////
  74. HRESULT DownloadManagerMunkee::downloadFile( std::string server, std::string username, std::string password, std::string file, std::string localfile, std::string regkey, bool tryResume )
  75. {
  76. /*
  77. if (staticTextFile)
  78. {
  79. UnicodeString fileString;
  80. fileString.translate(file);
  81. GadgetStaticTextSetText(staticTextFile, fileString);
  82. }
  83. */
  84. return DownloadManager::downloadFile( server, username, password, file, localfile, regkey, tryResume );
  85. }
  86. HRESULT DownloadManagerMunkee::OnError( int error )
  87. {
  88. HRESULT ret = DownloadManager::OnError( error );
  89. g_Finished = -1;
  90. return ret;
  91. }
  92. HRESULT DownloadManagerMunkee::OnEnd()
  93. {
  94. HRESULT ret = DownloadManager::OnEnd();
  95. g_Finished = 1;
  96. return ret;
  97. }
  98. HRESULT DownloadManagerMunkee::OnProgressUpdate( int bytesread, int totalsize, int timetaken, int timeleft )
  99. {
  100. HRESULT ret = DownloadManager::OnProgressUpdate( bytesread, totalsize, timetaken, timeleft );
  101. SendDlgItemMessage( g_DownloadWindow, IDC_PROGRESS, PBM_SETPOS, (WPARAM)(bytesread * 100) / totalsize, 0 );
  102. char temp[256];
  103. if( timeleft > 0 )
  104. {
  105. //DBGMSG("Bytes read: "<<bytesread<<". Time left: "<<timeleft<<" seconds");
  106. LoadString(Global_instance, TXT_TIME_REMAIN, temp, sizeof(temp));
  107. sprintf(g_DLTimeRem,temp,(timeleft/60),(timeleft%60));
  108. LoadString(Global_instance, TXT_BPS, temp, sizeof(temp));
  109. sprintf(g_DLBPS,temp,bytesread/timetaken);
  110. }
  111. LoadString(Global_instance, TXT_BYTES_READ, temp, sizeof(temp));
  112. sprintf(g_DLBytesLeft,temp,bytesread,totalsize);
  113. return ret;
  114. }
  115. HRESULT DownloadManagerMunkee::OnStatusUpdate( int status )
  116. {
  117. HRESULT ret = DownloadManager::OnStatusUpdate( status );
  118. SetWindowText(g_DownloadWindow, getStatusString().c_str());
  119. return ret;
  120. }
  121. ///////////////////////////////////////////////////////////////////////////////////////
  122. BOOL CALLBACK simpleDialogProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  123. {
  124. switch( uMsg )
  125. {
  126. case WM_INITDIALOG:
  127. return(TRUE);
  128. break;
  129. case WM_CLOSE:
  130. DestroyWindow(hwnd);
  131. PostQuitMessage(0);
  132. exit(0);
  133. break;
  134. }
  135. return(FALSE);
  136. }
  137. static void startOnline( void )
  138. {
  139. checkingForPatch = false;
  140. // Close that contacting window
  141. DestroyWindow(g_ContactWindow);
  142. g_ContactWindow=NULL;
  143. if (cantConnect)
  144. {
  145. MessageBox(NULL, "Can't Connect", "Command and Conquer Generals", MB_OK);
  146. exit(0);
  147. }
  148. else if (queuedDownloads.size())
  149. {
  150. if (MessageBox(NULL, "Patches Available. Download?", "Command and Conquer Generals", MB_YESNO) == IDYES)
  151. {
  152. DEBUG_LOG(("Downloading patches\n"));
  153. while (queuedDownloads.size())
  154. {
  155. TheDownload = queuedDownloads.front();
  156. queuedDownloads.pop_front();
  157. TheDownloadManager = new DownloadManagerMunkee;
  158. /**/
  159. int retVal = DialogBox(Global_instance, MAKEINTRESOURCE(IDD_DOWNLOAD_DIALOG), g_PrimaryWindow, downloadDialogProc);
  160. if (retVal)
  161. {
  162. DEBUG_LOG(("Error %d\n", GetLastError()));
  163. }
  164. /**/
  165. /*
  166. {
  167. //char *res = MAKEINTRESOURCE(IDD_CONNECTING);
  168. char *res = MAKEINTRESOURCE(IDD_DOWNLOAD_DIALOG1);
  169. g_DownloadWindow=CreateDialog(Global_instance,res,g_PrimaryWindow,simpleDialogProc);
  170. ShowWindow(g_DownloadWindow,SW_SHOWNORMAL);
  171. SetForegroundWindow(g_DownloadWindow);
  172. }
  173. */
  174. delete TheDownloadManager;
  175. TheDownloadManager = NULL;
  176. if (g_Finished != 1)
  177. {
  178. // Download failed
  179. //DBGMSG("Download failed: "<<retval);
  180. SetEvent(Events[ABORT_EVENT]);
  181. return;
  182. }
  183. }
  184. exit(0);
  185. }
  186. else
  187. {
  188. exit(0);
  189. }
  190. }
  191. else
  192. {
  193. MessageBox(NULL, "No Patches Available", "Command and Conquer Generals", MB_OK);
  194. exit(0);
  195. }
  196. }
  197. ///////////////////////////////////////////////////////////////////////////////////////
  198. static std::string trim(std::string s, const std::string& delim)
  199. {
  200. unsigned int i;
  201. i = s.find_first_not_of(delim);
  202. if (i != s.npos)
  203. {
  204. s = s.substr(i);
  205. }
  206. i = s.find_last_not_of(delim);
  207. if (i>=0 && i<s.npos)
  208. {
  209. s = s.substr(0, i+1);
  210. }
  211. return s;
  212. }
  213. ///////////////////////////////////////////////////////////////////////////////////////
  214. static std::string getNextLine(std::string in, std::string& remainder)
  215. {
  216. int lineEnd;
  217. lineEnd = in.find_first_of("\n\r", 0);
  218. if (lineEnd < 1)
  219. {
  220. remainder = "";
  221. return in;
  222. }
  223. std::string out = in.substr(0, lineEnd);
  224. remainder = in.substr(lineEnd+1);
  225. remainder = trim(remainder, "\r\n\t ");
  226. out = trim(out, "\r\t\n ");
  227. }
  228. ///////////////////////////////////////////////////////////////////////////////////////
  229. //-----------------------------------------------------------------------------
  230. inline const char* skipSeps(const char* p, const char* seps)
  231. {
  232. while (*p && strchr(seps, *p) != NULL)
  233. ++p;
  234. return p;
  235. }
  236. //-----------------------------------------------------------------------------
  237. inline const char* skipNonSeps(const char* p, const char* seps)
  238. {
  239. while (*p && strchr(seps, *p) == NULL)
  240. ++p;
  241. return p;
  242. }
  243. //-----------------------------------------------------------------------------
  244. bool nextToken(std::string& base, std::string& tok, const char* seps = NULL)
  245. {
  246. if (base.empty())
  247. return false;
  248. if (seps == NULL)
  249. seps = " \n\r\t";
  250. const char* start = skipSeps(base.c_str(), seps);
  251. const char* end = skipNonSeps(start, seps);
  252. if (end > start)
  253. {
  254. int len = end - start;
  255. char* tmp = new char[len+1];
  256. memcpy(tmp, start, len);
  257. tmp[len] = 0;
  258. tok = tmp;
  259. delete[] tmp;
  260. base = end;
  261. return true;
  262. }
  263. else
  264. {
  265. base = tok = "";
  266. return false;
  267. }
  268. }
  269. ///////////////////////////////////////////////////////////////////////////////////////
  270. static void queuePatch(bool mandatory, std::string downloadURL)
  271. {
  272. // downloadURL is of the form "ftp://ftp.ea.com:user@pass/pub/munkee/bananna.rtp"
  273. QueuedDownload q;
  274. bool success = true;
  275. std::string connectionType;
  276. success = success && nextToken(downloadURL, connectionType, ":");
  277. std::string server;
  278. success = success && nextToken(downloadURL, server, ":/");
  279. std::string user;
  280. success = success && nextToken(downloadURL, user, ":@");
  281. std::string pass;
  282. success = success && nextToken(downloadURL, pass, "@/");
  283. std::string filePath;
  284. success = success && nextToken(downloadURL, filePath, "");
  285. if (!success && !user.empty())
  286. {
  287. // no user/pass combo - move the file into it's proper place
  288. filePath = user;
  289. user = ""; // LFeenanEA - Credentials removed as per Security requirements
  290. pass = "";
  291. success = true;
  292. }
  293. std::string fileStr = filePath;
  294. unsigned int slashPos = filePath.find_last_of('/');
  295. std::string fileDir = "patches\\";
  296. std::string fileName = "";
  297. if (slashPos == filePath.npos)
  298. {
  299. fileName = filePath;
  300. }
  301. else
  302. {
  303. fileName = filePath.substr(slashPos+1);
  304. }
  305. fileDir.append(fileName);
  306. DEBUG_LOG(("download URL split: %d [%s] [%s] [%s] [%s] [%s] [%s] [%s]\n",
  307. success, connectionType.c_str(), server.c_str(), user.c_str(), pass.c_str(),
  308. filePath.c_str(), fileName.c_str(), fileDir.c_str()));
  309. if (!success)
  310. return;
  311. q.file = filePath;
  312. q.localFile = fileDir;
  313. q.password = pass;
  314. q.regKey = "";
  315. q.server = server;
  316. q.tryResume = true;
  317. q.userName = user;
  318. std::list<QueuedDownload>::iterator it = queuedDownloads.begin();
  319. while (it != queuedDownloads.end())
  320. {
  321. if (it->localFile == q.localFile)
  322. return; // don't add it if it exists already (because we can check multiple times)
  323. ++it;
  324. }
  325. queuedDownloads.push_back(q);
  326. }
  327. ///////////////////////////////////////////////////////////////////////////////////////
  328. static GHTTPBool patchCheckCallback( GHTTPRequest request, GHTTPResult result, char * buffer, int bufferLen, void * param )
  329. {
  330. --checksLeft;
  331. DEBUG_ASSERTCRASH(checksLeft>=0, ("Too many callbacks"));
  332. DEBUG_LOG(("Result=%d, buffer=[%s], len=%d\n", result, buffer, bufferLen));
  333. if (result != GHTTPSuccess)
  334. {
  335. cantConnect = true;
  336. if (!checksLeft)
  337. {
  338. startOnline();
  339. }
  340. return GHTTPTrue;
  341. }
  342. std::string message = buffer;
  343. std::string line;
  344. while (nextToken(message, line, "\r\n"))
  345. {
  346. std::string type, req, url;
  347. bool ok = true;
  348. ok = ok && nextToken(line, type, " ");
  349. ok = ok && nextToken(line, req, " ");
  350. ok = ok && nextToken(line, url, " ");
  351. if (ok && type == "patch")
  352. {
  353. DEBUG_LOG(("Saw a patch: %d/[%s]\n", atoi(req.c_str()), url.c_str()));
  354. queuePatch( atoi(req.c_str()), url );
  355. }
  356. else if (ok && type == "server")
  357. {
  358. }
  359. }
  360. if (!checksLeft)
  361. {
  362. startOnline();
  363. }
  364. return GHTTPTrue;
  365. }
  366. ///////////////////////////////////////////////////////////////////////////////////////
  367. static void StartPatchCheck( void )
  368. {
  369. checkingForPatch = true;
  370. std::string gameURL, mapURL;
  371. std::string configURL, motdURL;
  372. FormatURLFromRegistry(gameURL, mapURL, configURL, motdURL);
  373. std::string proxy;
  374. if (GetStringFromRegistry("", "Proxy", proxy))
  375. {
  376. if (!proxy.empty())
  377. {
  378. ghttpSetProxy(proxy.c_str());
  379. }
  380. }
  381. // check for a patch first
  382. checksLeft = 2;
  383. cantConnect = false;
  384. ghttpGet(gameURL.c_str(), GHTTPFalse, patchCheckCallback, NULL);
  385. ghttpGet(mapURL.c_str(), GHTTPFalse, patchCheckCallback, NULL);
  386. DEBUG_LOG(("Started looking for patches at '%s' && '%s'\n", gameURL.c_str(), mapURL.c_str()));
  387. }
  388. ///////////////////////////////////////////////////////////////////////////////////////
  389. BOOL CALLBACK downloadDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  390. {
  391. // HRESULT res;
  392. int cmd = LOWORD(wParam);
  393. switch( uMsg )
  394. {
  395. case WM_COMMAND:
  396. if ( cmd == IDC_DLABORT )
  397. {
  398. char abort[128];
  399. char abortdload[256];
  400. LoadString(Global_instance, TXT_ABORT_DOWNLOAD, abortdload, sizeof(abortdload));
  401. LoadString(Global_instance, TXT_ABORT, abort, sizeof(abort));
  402. if (MessageBox(g_PrimaryWindow,abortdload,abort,MB_YESNO)==IDYES)
  403. {
  404. TheDownloadManager->reset();
  405. EndDialog( hwndDlg, g_Finished );
  406. DestroyWindow(hwndDlg);
  407. }
  408. }
  409. else
  410. {
  411. return FALSE;
  412. }
  413. break;
  414. case WM_INITDIALOG:
  415. //SetupDownload();
  416. SendMessage(hwndDlg, WM_SETICON,(WPARAM)ICON_SMALL,
  417. (LPARAM)LoadIcon(Global_instance, MAKEINTRESOURCE(IDI_ICON1)));
  418. g_DLTimeRem[0]=0;
  419. g_DLBytesLeft[0]=0;
  420. g_DLBPS[0]=0;
  421. //SetDlgItemText( hwndDlg, IDC_DOWNLOADTITLE, g_UpdateString);
  422. //SetWindowText(hwndDlg, g_UpdateString);
  423. SetDlgItemText( hwndDlg, IDC_TIMEREM, g_DLTimeRem);
  424. SetDlgItemText( hwndDlg, IDC_BYTESLEFT, g_DLBytesLeft);
  425. // SetDlgItemText( hwndDlg, IDC_BPS, g_DLBPS );
  426. // Work out the full file name
  427. //char fullpath[_MAX_PATH];
  428. //char localfile[_MAX_PATH];
  429. //sprintf( fullpath, "%s/%s", g_Update->patchpath,g_Update->patchfile);
  430. //sprintf(localfile,"%s\\%s",g_Update->localpath,g_Update->patchfile);
  431. // Create the directory
  432. //CreateDirectory((char *)g_Update->localpath, NULL );
  433. TheDownloadManager->downloadFile(TheDownload.server, TheDownload.userName, TheDownload.password,
  434. TheDownload.file, TheDownload.localFile, TheDownload.regKey, TheDownload.tryResume);
  435. /*
  436. res=pDownload->DownloadFile((char *)g_Update->server, (char *)g_Update->login, (char *)g_Update->password,
  437. fullpath, localfile, APP_REG_KEY);
  438. */
  439. g_DownloadWindow = hwndDlg;
  440. g_Finished = 0;
  441. SetTimer( hwndDlg, 1, 200, NULL ); // was 50
  442. break;
  443. case WM_TIMER:
  444. DEBUG_LOG(("TIMER\n"));
  445. if( g_Finished == 0 )
  446. {
  447. DEBUG_LOG(("Entering PumpMsgs\n"));
  448. TheDownloadManager->update();
  449. /*
  450. pDownload->PumpMessages();
  451. */
  452. DEBUG_LOG(("Done with PumpMsgs\n"));
  453. if (strlen(g_DLTimeRem))
  454. SetDlgItemText( hwndDlg, IDC_TIMEREM, g_DLTimeRem );
  455. if (strlen(g_DLBytesLeft))
  456. SetDlgItemText( hwndDlg, IDC_BYTESLEFT, g_DLBytesLeft );
  457. //if (strlen(g_DLBPS))
  458. // SetDlgItemText( hwndDlg, IDC_BPS, g_DLBPS );
  459. }
  460. else
  461. {
  462. DEBUG_LOG(("TIMER: Finished\n"));
  463. EndDialog( hwndDlg, g_Finished );
  464. DestroyWindow( hwndDlg );
  465. }
  466. break;
  467. case WM_DESTROY:
  468. KillTimer( hwndDlg, 1 );
  469. //ClosedownDownload();
  470. //DBGMSG("WM_DESTROY");
  471. break;
  472. case WM_SETFONT:
  473. return TRUE;
  474. default:
  475. return FALSE;
  476. }
  477. return TRUE;
  478. }
  479. DWORD dwChatAdvise;
  480. DWORD dwDownloadAdvise;
  481. //Update *g_Update;
  482. uint32 g_AppVer=-1;
  483. BOOL CALLBACK Download_Dialog_Proc( HWND hwndDlg, UINT uMsg, WPARAM wParam,
  484. LPARAM lParam );
  485. BOOL CALLBACK Simple_Dialog_Proc( HWND hwndDlg, UINT uMsg, WPARAM wParam,
  486. LPARAM lParam );
  487. HWND CreatePrimaryWin(void);
  488. char const * Fetch_String(int id);
  489. //
  490. // Create a primary window
  491. //
  492. HWND CreatePrimaryWin(void)
  493. {
  494. HWND hwnd;
  495. WNDCLASS wc;
  496. char name[256];
  497. sprintf(name,Fetch_String(TXT_TITLE));
  498. //DBGMSG("CreatePrimary: "<<name);
  499. /*
  500. ** set up and register window class
  501. */
  502. wc.style = CS_HREDRAW | CS_VREDRAW;
  503. wc.lpfnWndProc = DefWindowProc;
  504. wc.cbClsExtra = 0; // Don't need any extra class data
  505. wc.cbWndExtra = 0; // No extra win data
  506. wc.hInstance = Global_instance;
  507. wc.hIcon=LoadIcon(Global_instance, MAKEINTRESOURCE(IDI_ICON1));
  508. wc.hCursor = NULL; /////////LoadCursor( NULL, IDC_ARROW );
  509. wc.hbrBackground = NULL;
  510. wc.lpszMenuName = name;
  511. wc.lpszClassName = name;
  512. RegisterClass( &wc );
  513. /*
  514. ** create a window
  515. */
  516. hwnd = CreateWindowEx(
  517. WS_EX_APPWINDOW,
  518. name,
  519. name,
  520. WS_POPUP,
  521. 0, 0,
  522. //GetSystemMetrics( SM_CXSCREEN ),
  523. //GetSystemMetrics( SM_CYSCREEN ),
  524. 0,0,
  525. NULL,
  526. NULL,
  527. Global_instance,
  528. NULL );
  529. SendMessage(hwnd,WM_SETICON,(WPARAM)ICON_SMALL,
  530. (LPARAM)LoadIcon(Global_instance, MAKEINTRESOURCE(IDI_ICON1)));
  531. ShowWindow(hwnd,SW_SHOWNORMAL);
  532. return(hwnd);
  533. }
  534. //
  535. // Dispatch pending windows events
  536. //
  537. void DispatchEvents(void)
  538. {
  539. MSG msg;
  540. int counter=0;
  541. while(PeekMessage(&msg,NULL,0,0, PM_REMOVE))
  542. {
  543. TranslateMessage(&msg);
  544. DispatchMessage(&msg);
  545. counter++;
  546. if (counter==256) // just in case
  547. break;
  548. }
  549. }
  550. //
  551. // Check for patches
  552. //
  553. int main(int argc, char *argv[])
  554. {
  555. InitCommonControls();
  556. /*
  557. g_PrimaryWindow=CreatePrimaryWin(); // Create the main window
  558. DispatchEvents(); // process some win messages
  559. */
  560. /*
  561. // Check if they've registered before, if not ask them if they want to
  562. bool have_registered=false;
  563. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,REGISTER_REG_KEY,0,KEY_READ,&rKey)==ERROR_SUCCESS)
  564. {
  565. char username[64];
  566. valuesize=sizeof(username);
  567. if (RegQueryValueEx(rKey,"UserName",NULL,&type,(uint8 *)username,&valuesize)==ERROR_SUCCESS)
  568. have_registered=true;
  569. RegCloseKey(rKey);
  570. }
  571. if (!have_registered)
  572. {
  573. if (RegOpenKeyEx(HKEY_CLASSES_ROOT,NICK_REG_KEY,0,KEY_READ,&rKey)==ERROR_SUCCESS)
  574. {
  575. have_registered=true;
  576. RegCloseKey(rKey);
  577. }
  578. }
  579. if (!have_registered)
  580. {
  581. if (MessageBox(NULL,Fetch_String(TXT_REGNOW),Fetch_String(TXT_TITLE),MB_YESNO)==IDNO)
  582. have_registered=true; // pretend they've alredy registered
  583. }
  584. if (!have_registered)
  585. {
  586. // figure out where the registration app is installed & launch it, continue
  587. // after it exits.
  588. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,REGISTER_REG_APP,0,KEY_READ,&rKey)==ERROR_SUCCESS)
  589. {
  590. char regapp[300];
  591. valuesize=sizeof(regapp);
  592. if ((RegQueryValueEx(rKey,"InstallPath",NULL,&type,(uint8 *)regapp,&valuesize)==ERROR_SUCCESS)&&
  593. (strlen(regapp) > 8))
  594. {
  595. // Launch the process
  596. SHELLEXECUTEINFO info;
  597. memset(&info,0,sizeof(info));
  598. info.cbSize=sizeof(info);
  599. info.fMask=SEE_MASK_NOCLOSEPROCESS;
  600. info.hwnd=g_PrimaryWindow;
  601. info.lpVerb=NULL;
  602. info.lpFile=regapp;
  603. info.lpParameters=NULL;
  604. info.lpDirectory=".";
  605. info.nShow=SW_SHOW;
  606. ShellExecuteEx(&info);
  607. // Can't wait infinite or the other process will never create its window
  608. // Only Bill himself knows why this is happening
  609. while(1) // Wait for completion
  610. {
  611. DispatchEvents();
  612. if (WaitForSingleObject(info.hProcess,500)!=WAIT_TIMEOUT)
  613. break;
  614. }
  615. }
  616. RegCloseKey(rKey);
  617. }
  618. }
  619. // OK, done with that crap go on to the task at hand now....
  620. */
  621. // Find the game version
  622. g_AppVer = -1;
  623. if (!GetUnsignedIntFromRegistry("", "Version", g_AppVer))
  624. {
  625. MessageBox(g_PrimaryWindow,Fetch_String(TXT_INSTALL_PROBLEM),Fetch_String(TXT_ERROR),MB_OK);
  626. exit(0);
  627. }
  628. // OK, have the current game version now
  629. g_PrimaryWindow=CreatePrimaryWin(); // Create the main window
  630. DispatchEvents(); // process some win messages
  631. // Popup the "contacting" window
  632. g_ContactWindow=CreateDialog(Global_instance,MAKEINTRESOURCE(IDD_CONNECTING),g_PrimaryWindow,Simple_Dialog_Proc);
  633. ShowWindow(g_ContactWindow,SW_SHOWNORMAL);
  634. SetForegroundWindow(g_ContactWindow);
  635. DispatchEvents(); // process some win messages
  636. // Setup the Westwood Online stuff
  637. Startup_Chat();
  638. Update_If_Required();
  639. Shutdown_Chat();
  640. return(0);
  641. }
  642. typedef struct SRecord {
  643. int ID; // ID number of the string resource.
  644. int TimeStamp; // 'Time' that this string was last requested.
  645. char String[2048]; // Copy of string resource.
  646. SRecord(void) : ID(-1), TimeStamp(-1) {}
  647. } SRecord;
  648. /***********************************************************************************************
  649. * Fetch_String -- Fetches a string resource. *
  650. * *
  651. * Fetches a string resource and returns a pointer to its text. *
  652. * *
  653. * INPUT: id -- The ID number of the string resource to fetch. *
  654. * *
  655. * OUTPUT: Returns with a pointer to the actual text of the string resource. *
  656. * *
  657. * WARNINGS: none *
  658. * *
  659. * HISTORY: *
  660. * 12/25/1996 JLB : Created. *
  661. *=============================================================================================*/
  662. char const * Fetch_String(int id)
  663. {
  664. static SRecord _buffers[64];
  665. static int _time = 0;
  666. /*
  667. ** Determine if the string ID requested is valid. If not then return an empty string pointer.
  668. */
  669. if (id == -1 || id == TXT_NONE) return("");
  670. /*
  671. ** Adjust the 'time stamp' tracking value. This is an artificial value used merely to track
  672. ** the relative age of the strings requested.
  673. */
  674. _time = _time+1;
  675. /*
  676. ** Check to see if the requested string has already been fetched into a buffer. If so, then
  677. ** return a pointer to that string (update the time stamp as well).
  678. */
  679. for (int index = 0; index < ARRAY_SIZE(_buffers); index++) {
  680. if (_buffers[index].ID == id) {
  681. _buffers[index].TimeStamp = _time;
  682. return(_buffers[index].String);
  683. }
  684. }
  685. /*
  686. ** Find a suitable buffer to hold the string to be fetched. The buffer should either be
  687. ** empty or have the oldest fetched string.
  688. */
  689. int oldest = -1;
  690. int oldtime = -1;
  691. for (int text = 0; text < ARRAY_SIZE(_buffers); text++) {
  692. if (oldest == -1 || oldtime > _buffers[text].TimeStamp) {
  693. oldest = text;
  694. oldtime = _buffers[text].TimeStamp;
  695. if (oldtime == -1 || _buffers[text].ID == -1) break;
  696. }
  697. }
  698. /*
  699. ** A suitable buffer has been found so fetch the string resource and then return a pointer
  700. ** to the string.
  701. */
  702. char * stringptr = _buffers[oldest].String;
  703. _buffers[oldest].ID = id;
  704. _buffers[oldest].TimeStamp = _time;
  705. if (LoadString(Global_instance, id, stringptr, sizeof(_buffers[oldest].String)) == 0) {
  706. return("");
  707. }
  708. /******
  709. char resname[32];
  710. sprintf(resname,"#%d",id);
  711. HMODULE hmod=GetModuleHandle(NULL);
  712. HRSRC hrsrc=FindResourceEx(hmod, RT_STRING, MAKEINTRESOURCE(id), LANGID);
  713. if (hrsrc==0)
  714. {
  715. char message_buffer[256];
  716. FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &message_buffer[0], 256, NULL );
  717. }
  718. HGLOBAL resdata=LoadResource(NULL,hrsrc);
  719. LPVOID vdata=LockResource(resdata);
  720. strcpy(stringptr,(char *)vdata);
  721. *********/
  722. stringptr[sizeof(_buffers[oldest].String)-1] = '\0';
  723. return(stringptr);
  724. }
  725. void LogMsg(char *msg)
  726. {
  727. #ifdef _DEBUG
  728. FILE *out=fopen("register.log","a");
  729. fprintf(out,"%s\n",msg);
  730. fflush(out);
  731. fclose(out);
  732. #endif
  733. }
  734. void Startup_Chat(void)
  735. {
  736. /*
  737. //////CComObject<CChatEventSink>* g_pChatSink;
  738. HRESULT hRes;
  739. g_pChatSink=NULL;
  740. CoCreateInstance(CLSID_Chat, NULL, CLSCTX_INPROC_SERVER,
  741. IID_IChat, (void**)&pChat);
  742. if (pChat==NULL)
  743. {
  744. char error[128];
  745. char apimissing[256];
  746. LoadString(Global_instance, TXT_API_MISSING, apimissing, sizeof(apimissing));
  747. LoadString(Global_instance, TXT_ERROR, error, sizeof(error));
  748. MessageBox(g_PrimaryWindow,apimissing,error,MB_OK);
  749. exit(-5);
  750. }
  751. g_pChatSink=new CChatEventSink;
  752. // Get a connection point from the chat class
  753. IConnectionPoint *pConnectionPoint=NULL;
  754. IConnectionPointContainer *pContainer=NULL;
  755. dwChatAdvise=0;
  756. hRes=pChat->QueryInterface(IID_IConnectionPointContainer,(void**)&pContainer);
  757. _ASSERTE(SUCCEEDED(hRes));
  758. hRes=pContainer->FindConnectionPoint(IID_IChatEvent,&pConnectionPoint);
  759. _ASSERTE(SUCCEEDED(hRes));
  760. hRes=pConnectionPoint->Advise((IChatEvent *)g_pChatSink,&dwChatAdvise);
  761. _ASSERTE(SUCCEEDED(hRes));
  762. pChat->SetAttributeValue("RegPath",APP_REG_KEY);
  763. // ADD pConnectionPoint->Release();
  764. */
  765. }
  766. void Shutdown_Chat(void)
  767. {
  768. /*
  769. /////AtlUnadvise(pChat, IID_IChatEvent, dwChatAdvise);
  770. IConnectionPoint *pConnectionPoint=NULL;
  771. IConnectionPointContainer *pContainer=NULL;
  772. HRESULT hRes;
  773. hRes=pChat->QueryInterface(IID_IConnectionPointContainer,(void**)&pContainer);
  774. _ASSERTE(SUCCEEDED(hRes));
  775. hRes=pContainer->FindConnectionPoint(IID_IChatEvent,&pConnectionPoint);
  776. _ASSERTE(SUCCEEDED(hRes));
  777. pConnectionPoint->Unadvise(dwChatAdvise);
  778. pChat->Release();
  779. /////delete(g_pChatSink); This appears to be bad....
  780. // ADD g_pChatSink->Release();
  781. // ADD pConnectionPoint->Release();
  782. // ADD pContainer->Release();
  783. */
  784. }
  785. //
  786. // Download a patch for the registration client if required
  787. // This uses the chat API for ver checking and FTP.
  788. //
  789. void Update_If_Required(void)
  790. {
  791. int retval;
  792. int i;
  793. // Create the events
  794. for (i=0; i<NUM_EVENTS; i++)
  795. Events[i]=CreateEvent(NULL,FALSE,FALSE,NULL);
  796. StartPatchCheck();
  797. while (1)
  798. {
  799. ghttpThink();
  800. MSG msg;
  801. while(PeekMessage(&msg,NULL,0,0, PM_REMOVE))
  802. {
  803. TranslateMessage(&msg);
  804. DispatchMessage(&msg);
  805. }
  806. retval=WaitForMultipleObjectsEx(NUM_EVENTS,Events,FALSE,50,FALSE);
  807. if (retval==WAIT_TIMEOUT)
  808. continue;
  809. //DBGMSG("An event was set");
  810. retval-=WAIT_OBJECT_0;
  811. break;
  812. }
  813. //DBGMSG("Out of the loop")
  814. if (retval==ABORT_EVENT)
  815. {
  816. exit(0);
  817. }
  818. else
  819. {
  820. //DBGMSG("NO update required");
  821. }
  822. //DBGMSG("Shutting down");
  823. // close all the event objects
  824. for (i=0; i<NUM_EVENTS; i++)
  825. CloseHandle(Events[i]);
  826. /*
  827. Startup_Chat();
  828. int retval;
  829. int i;
  830. // Create the events
  831. for (i=0; i<NUM_EVENTS; i++)
  832. Events[i]=CreateEvent(NULL,FALSE,FALSE,NULL);
  833. /// For Testing....
  834. ///pChat->RequestServerList(1000,262364,"register","regpas98",15);
  835. ///pChat->RequestServerList(1000,300,"register","regpas98",15);
  836. pChat->RequestServerList(g_AppSku,g_AppVer,"register","regpas98",40);
  837. while(1)
  838. {
  839. pChat->PumpMessages();
  840. MSG msg;
  841. while(PeekMessage(&msg,NULL,0,0, PM_REMOVE))
  842. {
  843. TranslateMessage(&msg);
  844. DispatchMessage(&msg);
  845. }
  846. retval=WaitForMultipleObjectsEx(NUM_EVENTS,Events,FALSE,50,FALSE);
  847. if (retval==WAIT_TIMEOUT)
  848. continue;
  849. //DBGMSG("An event was set");
  850. retval-=WAIT_OBJECT_0;
  851. break;
  852. }
  853. //DBGMSG("Out of the loop")
  854. if (retval==ABORT_EVENT)
  855. {
  856. exit(0);
  857. }
  858. else
  859. {
  860. //DBGMSG("NO update required");
  861. }
  862. //DBGMSG("Shutting down");
  863. // close all the event objects
  864. for (i=0; i<NUM_EVENTS; i++)
  865. CloseHandle(Events[i]);
  866. Shutdown_Chat();
  867. */
  868. }
  869. /*
  870. CChatEventSink::CChatEventSink()
  871. {
  872. m_cRef=0; // init the refrence count
  873. }
  874. ///////////////////////////////////////////////////////////
  875. //
  876. // Interface IUnknown Methods
  877. //
  878. ///////////////////////////////////////////////////////////
  879. //
  880. // QueryInterface
  881. //
  882. HRESULT __stdcall
  883. CChatEventSink::QueryInterface(const IID& iid, void** ppv)
  884. {
  885. if ((iid == IID_IUnknown) ||(iid == IID_IChatEvent))
  886. {
  887. *ppv = static_cast<IChatEvent*>(this) ;
  888. }
  889. else
  890. {
  891. *ppv = NULL;
  892. return E_NOINTERFACE;
  893. }
  894. (reinterpret_cast<IUnknown*>(*ppv))->AddRef() ;
  895. return S_OK ;
  896. }
  897. ///////////////////////////////////////////////////////////
  898. //
  899. // AddRef
  900. //
  901. ULONG __stdcall
  902. CChatEventSink::AddRef()
  903. {
  904. return InterlockedIncrement(&m_cRef) ;
  905. }
  906. ///////////////////////////////////////////////////////////
  907. //
  908. // Release
  909. //
  910. ULONG __stdcall
  911. CChatEventSink::Release()
  912. {
  913. if (InterlockedDecrement(&m_cRef) == 0)
  914. {
  915. delete this ;
  916. return 0 ;
  917. }
  918. return m_cRef;
  919. }
  920. ///// DOWNLOAD
  921. CDownloadEventSink::CDownloadEventSink()
  922. {
  923. m_cRef=0; // Ref counter
  924. }
  925. ///////////////////////////////////////////////////////////
  926. //
  927. // Interface IUnknown Methods
  928. //
  929. ///////////////////////////////////////////////////////////
  930. //
  931. // QueryInterface
  932. //
  933. HRESULT __stdcall
  934. CDownloadEventSink::QueryInterface(const IID& iid, void** ppv)
  935. {
  936. if ((iid == IID_IUnknown) ||(iid == IID_IDownloadEvent))
  937. {
  938. *ppv = static_cast<IDownloadEvent*>(this) ;
  939. }
  940. else
  941. {
  942. *ppv = NULL;
  943. return E_NOINTERFACE;
  944. }
  945. (reinterpret_cast<IUnknown*>(*ppv))->AddRef() ;
  946. return S_OK ;
  947. }
  948. ///////////////////////////////////////////////////////////
  949. //
  950. // AddRef
  951. //
  952. ULONG __stdcall
  953. CDownloadEventSink::AddRef()
  954. {
  955. return InterlockedIncrement(&m_cRef) ;
  956. }
  957. ///////////////////////////////////////////////////////////
  958. //
  959. // Release
  960. //
  961. ULONG __stdcall
  962. CDownloadEventSink::Release()
  963. {
  964. if (InterlockedDecrement(&m_cRef) == 0)
  965. {
  966. delete this ;
  967. return 0 ;
  968. }
  969. return m_cRef;
  970. }
  971. */
  972. //// FTP Download stuff
  973. void SetupDownload( void )
  974. {
  975. /*
  976. HRESULT hRes;
  977. g_pDownloadSink=NULL;
  978. CoCreateInstance(CLSID_Download, NULL, CLSCTX_INPROC_SERVER,
  979. IID_IDownload, (void**)&pDownload);
  980. _ASSERTE(pDownload);
  981. g_pDownloadSink=new CDownloadEventSink;
  982. // Get a connection point from the chat class
  983. IConnectionPoint *pConnectionPoint=NULL;
  984. IConnectionPointContainer *pContainer=NULL;
  985. dwDownloadAdvise = 0;
  986. hRes=pDownload->QueryInterface(IID_IConnectionPointContainer,(void**)&pContainer);
  987. _ASSERTE(SUCCEEDED(hRes));
  988. hRes=pContainer->FindConnectionPoint(IID_IDownloadEvent,&pConnectionPoint);
  989. _ASSERTE(SUCCEEDED(hRes));
  990. hRes=pConnectionPoint->Advise((IDownloadEvent *)g_pDownloadSink,&dwDownloadAdvise);
  991. _ASSERTE(SUCCEEDED(hRes));
  992. */
  993. }
  994. void ClosedownDownload( void )
  995. {
  996. /*
  997. // AtlUnadvise(pDownload, IID_IDownloadEvent, dwDownloadAdvise);
  998. IConnectionPoint *pConnectionPoint=NULL;
  999. IConnectionPointContainer *pContainer=NULL;
  1000. HRESULT hRes;
  1001. hRes=pDownload->QueryInterface(IID_IConnectionPointContainer,(void**)&pContainer);
  1002. _ASSERTE(SUCCEEDED(hRes));
  1003. hRes=pContainer->FindConnectionPoint(IID_IDownloadEvent,&pConnectionPoint);
  1004. _ASSERTE(SUCCEEDED(hRes));
  1005. pConnectionPoint->Unadvise(dwDownloadAdvise);
  1006. pDownload->Release();
  1007. //////delete(g_pDownloadSink); This appears to be bad....
  1008. */
  1009. }
  1010. BOOL CALLBACK Download_Dialog_Proc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1011. {
  1012. // char fullpath[ 256 ];
  1013. // char localfile[ 256];
  1014. // HRESULT res;
  1015. switch( uMsg )
  1016. {
  1017. case WM_COMMAND:
  1018. switch( LOWORD( wParam ) )
  1019. {
  1020. case IDC_DLABORT:
  1021. {
  1022. char abort[128];
  1023. char abortdload[256];
  1024. LoadString(Global_instance, TXT_ABORT_DOWNLOAD, abortdload, sizeof(abortdload));
  1025. LoadString(Global_instance, TXT_ABORT, abort, sizeof(abort));
  1026. if (MessageBox(g_PrimaryWindow,abortdload,abort,MB_YESNO)==IDYES)
  1027. {
  1028. /*
  1029. pDownload->Abort();
  1030. */
  1031. EndDialog( hwndDlg, g_Finished );
  1032. DestroyWindow(hwndDlg);
  1033. }
  1034. }
  1035. break;
  1036. default:
  1037. return FALSE;
  1038. }
  1039. break;
  1040. case WM_INITDIALOG:
  1041. SetupDownload();
  1042. SendMessage(hwndDlg, WM_SETICON,(WPARAM)ICON_SMALL,
  1043. (LPARAM)LoadIcon(Global_instance, MAKEINTRESOURCE(IDI_ICON1)));
  1044. g_DLTimeRem[0]=0;
  1045. g_DLBytesLeft[0]=0;
  1046. g_DLBPS[0]=0;
  1047. //SetDlgItemText( hwndDlg, IDC_DOWNLOADTITLE, g_UpdateString);
  1048. //SetWindowText(hwndDlg, g_UpdateString);
  1049. SetDlgItemText( hwndDlg, IDC_TIMEREM, g_DLTimeRem);
  1050. SetDlgItemText( hwndDlg, IDC_BYTESLEFT, g_DLBytesLeft);
  1051. // SetDlgItemText( hwndDlg, IDC_BPS, g_DLBPS );
  1052. /*
  1053. // Work out the full file name
  1054. sprintf( fullpath, "%s/%s", g_Update->patchpath,g_Update->patchfile);
  1055. sprintf(localfile,"%s\\%s",g_Update->localpath,g_Update->patchfile);
  1056. // Create the directory
  1057. CreateDirectory((char *)g_Update->localpath, NULL );
  1058. res=pDownload->DownloadFile((char *)g_Update->server, (char *)g_Update->login, (char *)g_Update->password,
  1059. fullpath, localfile, APP_REG_KEY);
  1060. */
  1061. g_DownloadWindow = hwndDlg;
  1062. g_Finished = 0;
  1063. SetTimer( hwndDlg, 1, 200, NULL ); // was 50
  1064. break;
  1065. case WM_TIMER:
  1066. LogMsg("TIMER");
  1067. if( g_Finished == 0 )
  1068. {
  1069. LogMsg("Entering PumpMsgs");
  1070. /*
  1071. pDownload->PumpMessages();
  1072. */
  1073. LogMsg("Done with PumpMsgs");
  1074. if (strlen(g_DLTimeRem))
  1075. SetDlgItemText( hwndDlg, IDC_TIMEREM, g_DLTimeRem );
  1076. if (strlen(g_DLBytesLeft))
  1077. SetDlgItemText( hwndDlg, IDC_BYTESLEFT, g_DLBytesLeft );
  1078. //if (strlen(g_DLBPS))
  1079. // SetDlgItemText( hwndDlg, IDC_BPS, g_DLBPS );
  1080. }
  1081. else
  1082. {
  1083. LogMsg("TIMER: Finished");
  1084. EndDialog( hwndDlg, g_Finished );
  1085. DestroyWindow( hwndDlg );
  1086. }
  1087. break;
  1088. case WM_DESTROY:
  1089. KillTimer( hwndDlg, 1 );
  1090. ClosedownDownload();
  1091. //DBGMSG("WM_DESTROY");
  1092. break;
  1093. case WM_SETFONT:
  1094. return TRUE;
  1095. default:
  1096. return FALSE;
  1097. }
  1098. return TRUE;
  1099. }
  1100. // Whoeee this is an exciting one...
  1101. BOOL CALLBACK Simple_Dialog_Proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1102. {
  1103. switch( uMsg )
  1104. {
  1105. case WM_INITDIALOG:
  1106. return(TRUE);
  1107. break;
  1108. case WM_CLOSE:
  1109. DestroyWindow(hwnd);
  1110. PostQuitMessage(0);
  1111. exit(0);
  1112. break;
  1113. }
  1114. return(FALSE);
  1115. }
  1116. /////////////////////////////////////////////////////////////////////////////
  1117. // CDownloadEventSink
  1118. //////////////////////////////////////////////////////////////////////////////
  1119. /*
  1120. STDMETHODIMP CDownloadEventSink::OnEnd(void)
  1121. {
  1122. LogMsg("Finished!");
  1123. g_Finished = 1;
  1124. return(S_OK);
  1125. }
  1126. STDMETHODIMP CDownloadEventSink::OnError(int error)
  1127. {
  1128. LogMsg("ERROR");
  1129. g_Finished = -1;
  1130. return(S_OK);
  1131. }
  1132. STDMETHODIMP CDownloadEventSink::OnProgressUpdate(int bytesread, int totalsize,
  1133. int timetaken, int timeleft)
  1134. {
  1135. SendDlgItemMessage( g_DownloadWindow, IDC_PROGRESS, PBM_SETPOS, (WPARAM)(bytesread * 100) / totalsize, 0 );
  1136. char temp[256];
  1137. if( timeleft > 0 )
  1138. {
  1139. //DBGMSG("Bytes read: "<<bytesread<<". Time left: "<<timeleft<<" seconds");
  1140. LoadString(Global_instance, TXT_TIME_REMAIN, temp, sizeof(temp));
  1141. sprintf(g_DLTimeRem,temp,(timeleft/60),(timeleft%60));
  1142. LoadString(Global_instance, TXT_BPS, temp, sizeof(temp));
  1143. sprintf(g_DLBPS,temp,bytesread/timetaken);
  1144. }
  1145. LoadString(Global_instance, TXT_BYTES_READ, temp, sizeof(temp));
  1146. sprintf(g_DLBytesLeft,temp,bytesread,totalsize);
  1147. return(S_OK);
  1148. }
  1149. STDMETHODIMP CDownloadEventSink::OnStatusUpdate(int status)
  1150. {
  1151. switch( status )
  1152. {
  1153. case DOWNLOADSTATUS_CONNECTING:
  1154. {
  1155. //LogMsg( "Connecting..." );
  1156. SetWindowText(g_DownloadWindow, Fetch_String(TXT_CONNECTING));
  1157. }
  1158. break;
  1159. case DOWNLOADSTATUS_FINDINGFILE:
  1160. //LogMsg( "Finding patch..." );
  1161. SetWindowText(g_DownloadWindow, g_UpdateString);
  1162. break;
  1163. case DOWNLOADSTATUS_DOWNLOADING:
  1164. //LogMsg( "Downloading patch..." );
  1165. SetWindowText(g_DownloadWindow, g_UpdateString);
  1166. break;
  1167. default:
  1168. //LogMsg("Unknown status update!");
  1169. break;
  1170. }
  1171. return(S_OK);
  1172. }
  1173. //
  1174. // Just tell the FTP module to go ahead and resume
  1175. //
  1176. STDMETHODIMP CDownloadEventSink::OnQueryResume(void)
  1177. {
  1178. return(DOWNLOADEVENT_RESUME);
  1179. }
  1180. /////////////////////////////////////////////////////////////////////////////
  1181. // CChatEventSink
  1182. //////////////////////////////////////////////////////////////////////////////
  1183. STDMETHODIMP CChatEventSink::OnServerList(HRESULT res, Server* servers)
  1184. {
  1185. // If we get this, then we don't need to patch
  1186. // Close that contacting window
  1187. DestroyWindow(g_ContactWindow);
  1188. g_ContactWindow=NULL;
  1189. LogMsg("Server List");
  1190. MessageBox(g_PrimaryWindow,Fetch_String(TXT_NO_PATCHES),Fetch_String(TXT_AUTO_UPDATE),MB_OK);
  1191. SetEvent(Events[NOUPDATE_EVENT]);
  1192. return(S_OK);
  1193. }
  1194. STDMETHODIMP CChatEventSink::OnServerBannedYou(HRESULT, time_t)
  1195. {
  1196. return(S_OK);
  1197. }
  1198. STDMETHODIMP CChatEventSink::OnPageSend(HRESULT)
  1199. {
  1200. return(S_OK);
  1201. }
  1202. STDMETHODIMP CChatEventSink::OnPaged(HRESULT, User *, LPCSTR)
  1203. {
  1204. return(S_OK);
  1205. }
  1206. STDMETHODIMP CChatEventSink::OnFind(HRESULT, Channel *)
  1207. {
  1208. return(S_OK);
  1209. }
  1210. STDMETHODIMP CChatEventSink::OnLogout(HRESULT, User *)
  1211. {
  1212. return(S_OK);
  1213. }
  1214. STDMETHODIMP CChatEventSink::OnBusy(HRESULT)
  1215. {
  1216. return(S_OK);
  1217. }
  1218. STDMETHODIMP CChatEventSink::OnIdle(HRESULT)
  1219. {
  1220. return(S_OK);
  1221. }
  1222. STDMETHODIMP CChatEventSink::OnConnection(HRESULT, LPCSTR)
  1223. {
  1224. return(S_OK);
  1225. }
  1226. STDMETHODIMP CChatEventSink::OnUserFlags(HRESULT,LPCSTR,unsigned int, unsigned int)
  1227. {
  1228. return(S_OK);
  1229. }
  1230. STDMETHODIMP CChatEventSink::OnChannelCreate(HRESULT, Channel *)
  1231. {
  1232. return(S_OK);
  1233. }
  1234. STDMETHODIMP CChatEventSink::OnChannelModify(HRESULT, Channel *)
  1235. {
  1236. return(S_OK);
  1237. }
  1238. STDMETHODIMP CChatEventSink::OnChannelJoin(HRESULT, Channel *, User *)
  1239. {
  1240. return(S_OK);
  1241. }
  1242. STDMETHODIMP CChatEventSink::OnChannelLeave(HRESULT, Channel *, User *)
  1243. {
  1244. return(S_OK);
  1245. }
  1246. STDMETHODIMP CChatEventSink::OnChannelTopic(HRESULT, Channel *, LPCSTR)
  1247. {
  1248. return(S_OK);
  1249. }
  1250. STDMETHODIMP CChatEventSink::OnChannelBan(HRESULT, LPCSTR, int)
  1251. {
  1252. return(S_OK);
  1253. }
  1254. STDMETHODIMP CChatEventSink::OnGroupList(HRESULT, Group *)
  1255. {
  1256. return(S_OK);
  1257. }
  1258. STDMETHODIMP CChatEventSink::OnPublicMessage(HRESULT, Channel *, User *, LPCSTR)
  1259. {
  1260. return(S_OK);
  1261. }
  1262. STDMETHODIMP CChatEventSink::OnPrivateMessage(HRESULT, User *,LPCSTR)
  1263. {
  1264. return(S_OK);
  1265. }
  1266. STDMETHODIMP CChatEventSink::OnSystemMessage(HRESULT, LPCSTR)
  1267. {
  1268. return(S_OK);
  1269. }
  1270. STDMETHODIMP CChatEventSink::OnUserLocale(long, struct User *)
  1271. {
  1272. return(S_OK);
  1273. }
  1274. STDMETHODIMP CChatEventSink::OnUserTeam(long, struct User *)
  1275. {
  1276. return(S_OK);
  1277. }
  1278. STDMETHODIMP CChatEventSink::OnSetLocale(long, enum Locale)
  1279. {
  1280. return(S_OK);
  1281. }
  1282. STDMETHODIMP CChatEventSink::OnSetTeam(long, int)
  1283. {
  1284. return(S_OK);
  1285. }
  1286. STDMETHODIMP CChatEventSink::OnNetStatus(HRESULT hr)
  1287. {
  1288. char string[60];
  1289. sprintf(string,"NetStatus %ld",hr);
  1290. LogMsg(string);
  1291. if ((hr==CHAT_E_CON_NETDOWN)||(hr==CHAT_E_CON_LOOKUP_FAILED)||
  1292. (hr==CHAT_E_CON_ERROR)||(hr==CHAT_E_TIMEOUT))
  1293. {
  1294. char error[128];
  1295. char cantconn[256];
  1296. LoadString(Global_instance, TXT_CANT_CONTACT, cantconn, sizeof(cantconn));
  1297. LoadString(Global_instance, TXT_ERROR, error, sizeof(error));
  1298. MessageBox(g_PrimaryWindow,cantconn,error,MB_OK);
  1299. exit(-1);
  1300. }
  1301. return(S_OK);
  1302. }
  1303. STDMETHODIMP CChatEventSink::OnChannelList(HRESULT, Channel*)
  1304. {
  1305. return(S_OK);
  1306. }
  1307. STDMETHODIMP CChatEventSink::OnUserList(HRESULT, Channel*, User*)
  1308. {
  1309. return(S_OK);
  1310. }
  1311. //
  1312. // We got a list of updates to apply
  1313. //
  1314. STDMETHODIMP CChatEventSink::OnUpdateList(HRESULT r, Update * updates)
  1315. {
  1316. Update *tmp;
  1317. int numupdates=0;
  1318. int i=0;
  1319. int retval;
  1320. static int alreadyGotOne=0;
  1321. LogMsg("Update list");
  1322. // Close that contacting window
  1323. DestroyWindow(g_ContactWindow);
  1324. g_ContactWindow=NULL;
  1325. if( FAILED(r) )
  1326. {
  1327. LogMsg("Failed");
  1328. SetEvent(Events[ABORT_EVENT]); // An error occurred, bail out
  1329. }
  1330. if( updates == NULL ) // shouldn't happen
  1331. return S_OK;
  1332. if (alreadyGotOne) // Should only get one update list
  1333. return(S_OK);
  1334. alreadyGotOne=1;
  1335. // Count the updates;
  1336. tmp = updates;
  1337. while( tmp != NULL )
  1338. {
  1339. tmp = tmp->next;
  1340. numupdates++;
  1341. }
  1342. // Got a list of updates - If an update is required, the user must either
  1343. // patch or quit.
  1344. tmp = updates;
  1345. LogMsg("Found an update");
  1346. // We have a required update
  1347. char upreq[256];
  1348. char title[128];
  1349. LoadString(Global_instance, TXT_AN_UPGRADE_AVAILABLE, upreq, sizeof(upreq));
  1350. strcat(upreq,"\n");
  1351. LoadString(Global_instance, TXT_DOWNLOAD_NOW, upreq+strlen(upreq), sizeof(upreq));
  1352. LoadString(Global_instance, TXT_UPGRADE_AVAILABLE, title, sizeof(title));
  1353. if( MessageBox(g_PrimaryWindow,upreq,title, MB_YESNO ) == IDNO )
  1354. {
  1355. // If they don't want to patch now, just exit...
  1356. //DBGMSG("Must patch to continue, so exit");
  1357. exit(0);
  1358. }
  1359. // Do the downloads
  1360. while( tmp != NULL )
  1361. {
  1362. g_Update = tmp;
  1363. char dloading[256];
  1364. LoadString(Global_instance, TXT_DOWNLOADING_FILE, dloading, sizeof(dloading));
  1365. sprintf( g_UpdateString, dloading, ++i, numupdates );
  1366. LogMsg("Creating Download dialog box");
  1367. //if( (retval=DialogBox(Global_instance, MAKEINTRESOURCE(IDD_DOWNLOAD_DIALOG), g_PrimaryWindow,
  1368. // (DLGPROC)Download_Dialog_Proc)) != 1 )
  1369. retval=DialogBox(Global_instance, MAKEINTRESOURCE(IDD_DOWNLOAD_DIALOG), g_PrimaryWindow,(DLGPROC)Download_Dialog_Proc);
  1370. if (g_Finished != 1)
  1371. {
  1372. // Download failed
  1373. //DBGMSG("Download failed: "<<retval);
  1374. SetEvent(Events[ABORT_EVENT]);
  1375. return(E_FAIL);
  1376. }
  1377. tmp = tmp->next;
  1378. }
  1379. // Quit so the launcher can apply the patches
  1380. exit(0);
  1381. return(S_OK); // make silly compiler happy
  1382. }
  1383. STDMETHODIMP CChatEventSink::OnServerError(HRESULT, LPCSTR)
  1384. {
  1385. LogMsg("Server Error");
  1386. return(S_OK);
  1387. }
  1388. STDMETHODIMP CChatEventSink::OnMessageOfTheDay(HRESULT, LPCSTR)
  1389. {
  1390. return(S_OK);
  1391. }
  1392. STDMETHODIMP CChatEventSink::OnPrivateAction(HRESULT, User *, LPCSTR)
  1393. {
  1394. return(S_OK);
  1395. }
  1396. STDMETHODIMP CChatEventSink::OnPublicAction(HRESULT, Channel *, User *, LPCSTR)
  1397. {
  1398. return(S_OK);
  1399. }
  1400. STDMETHODIMP CChatEventSink::OnPrivateGameOptions(HRESULT, User *, LPCSTR)
  1401. {
  1402. return(S_OK);
  1403. }
  1404. STDMETHODIMP CChatEventSink::OnPublicGameOptions(HRESULT, Channel *, User *, LPCSTR)
  1405. {
  1406. return(S_OK);
  1407. }
  1408. STDMETHODIMP CChatEventSink::OnGameStart(HRESULT, Channel *, User *, int)
  1409. {
  1410. return(S_OK);
  1411. }
  1412. STDMETHODIMP CChatEventSink::OnUserKick(HRESULT, Channel *, User *, User *)
  1413. {
  1414. return(S_OK);
  1415. }
  1416. STDMETHODIMP CChatEventSink::OnUserIP(HRESULT, User *)
  1417. {
  1418. return(S_OK);
  1419. }
  1420. STDMETHODIMP CChatEventSink::OnSquadInfo(HRESULT, unsigned long, Squad *)
  1421. {
  1422. return(S_OK);
  1423. }
  1424. */