/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ // // This module takes care of all the Chat API stuff // #include #include "GameSpy/ghttp/ghttp.h" #include "downloadManager.h" #include "chatapi.h" //#include "api/wolapi_i.c" // This should only be in one .cpp file #include #include #include #include #include #include "resource.h" #include "winblows.h" #include #include "process.h" #include "WWDownload/registry.h" #include "WWDownload/urlBuilder.h" #include "debug.h" enum EVENT_TYPES { NOUPDATE_EVENT=0, // don't need to update ABORT_EVENT, NUM_EVENTS // keep last }; #define GAME_NAME "Command & Conquer" HANDLE Events[NUM_EVENTS]; char g_UpdateString[256]; // for the filename char g_DLTimeRem[80]; char g_DLBytesLeft[80]; char g_DLBPS[80]; int g_Finished=0; HWND g_DownloadWindow; HWND g_ContactWindow; HWND g_PrimaryWindow; static bool checkingForPatch = false; static int checksLeft = 0; static bool cantConnect = false; static std::list queuedDownloads; BOOL CALLBACK downloadDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); /////////////////////////////////////////////////////////////////////////////////////// static void startOnline( void ); /////////////////////////////////////////////////////////////////////////////////////// QueuedDownload TheDownload; class DownloadManagerMunkee : public DownloadManager { public: DownloadManagerMunkee() { } virtual HRESULT OnError( int error ); virtual HRESULT OnEnd(); virtual HRESULT OnProgressUpdate( int bytesread, int totalsize, int timetaken, int timeleft ); virtual HRESULT OnStatusUpdate( int status ); virtual HRESULT downloadFile( std::string server, std::string username, std::string password, std::string file, std::string localfile, std::string regkey, bool tryResume ); }; /////////////////////////////////////////////////////////////////////////////////////// HRESULT DownloadManagerMunkee::downloadFile( std::string server, std::string username, std::string password, std::string file, std::string localfile, std::string regkey, bool tryResume ) { /* if (staticTextFile) { UnicodeString fileString; fileString.translate(file); GadgetStaticTextSetText(staticTextFile, fileString); } */ return DownloadManager::downloadFile( server, username, password, file, localfile, regkey, tryResume ); } HRESULT DownloadManagerMunkee::OnError( int error ) { HRESULT ret = DownloadManager::OnError( error ); g_Finished = -1; return ret; } HRESULT DownloadManagerMunkee::OnEnd() { HRESULT ret = DownloadManager::OnEnd(); g_Finished = 1; return ret; } HRESULT DownloadManagerMunkee::OnProgressUpdate( int bytesread, int totalsize, int timetaken, int timeleft ) { HRESULT ret = DownloadManager::OnProgressUpdate( bytesread, totalsize, timetaken, timeleft ); SendDlgItemMessage( g_DownloadWindow, IDC_PROGRESS, PBM_SETPOS, (WPARAM)(bytesread * 100) / totalsize, 0 ); char temp[256]; if( timeleft > 0 ) { //DBGMSG("Bytes read: "<=0 && i start) { int len = end - start; char* tmp = new char[len+1]; memcpy(tmp, start, len); tmp[len] = 0; tok = tmp; delete[] tmp; base = end; return true; } else { base = tok = ""; return false; } } /////////////////////////////////////////////////////////////////////////////////////// static void queuePatch(bool mandatory, std::string downloadURL) { // downloadURL is of the form "ftp://ftp.ea.com:user@pass/pub/munkee/bananna.rtp" QueuedDownload q; bool success = true; std::string connectionType; success = success && nextToken(downloadURL, connectionType, ":"); std::string server; success = success && nextToken(downloadURL, server, ":/"); std::string user; success = success && nextToken(downloadURL, user, ":@"); std::string pass; success = success && nextToken(downloadURL, pass, "@/"); std::string filePath; success = success && nextToken(downloadURL, filePath, ""); if (!success && !user.empty()) { // no user/pass combo - move the file into it's proper place filePath = user; user = ""; // LFeenanEA - Credentials removed as per Security requirements pass = ""; success = true; } std::string fileStr = filePath; unsigned int slashPos = filePath.find_last_of('/'); std::string fileDir = "patches\\"; std::string fileName = ""; if (slashPos == filePath.npos) { fileName = filePath; } else { fileName = filePath.substr(slashPos+1); } fileDir.append(fileName); DEBUG_LOG(("download URL split: %d [%s] [%s] [%s] [%s] [%s] [%s] [%s]\n", success, connectionType.c_str(), server.c_str(), user.c_str(), pass.c_str(), filePath.c_str(), fileName.c_str(), fileDir.c_str())); if (!success) return; q.file = filePath; q.localFile = fileDir; q.password = pass; q.regKey = ""; q.server = server; q.tryResume = true; q.userName = user; std::list::iterator it = queuedDownloads.begin(); while (it != queuedDownloads.end()) { if (it->localFile == q.localFile) return; // don't add it if it exists already (because we can check multiple times) ++it; } queuedDownloads.push_back(q); } /////////////////////////////////////////////////////////////////////////////////////// static GHTTPBool patchCheckCallback( GHTTPRequest request, GHTTPResult result, char * buffer, int bufferLen, void * param ) { --checksLeft; DEBUG_ASSERTCRASH(checksLeft>=0, ("Too many callbacks")); DEBUG_LOG(("Result=%d, buffer=[%s], len=%d\n", result, buffer, bufferLen)); if (result != GHTTPSuccess) { cantConnect = true; if (!checksLeft) { startOnline(); } return GHTTPTrue; } std::string message = buffer; std::string line; while (nextToken(message, line, "\r\n")) { std::string type, req, url; bool ok = true; ok = ok && nextToken(line, type, " "); ok = ok && nextToken(line, req, " "); ok = ok && nextToken(line, url, " "); if (ok && type == "patch") { DEBUG_LOG(("Saw a patch: %d/[%s]\n", atoi(req.c_str()), url.c_str())); queuePatch( atoi(req.c_str()), url ); } else if (ok && type == "server") { } } if (!checksLeft) { startOnline(); } return GHTTPTrue; } /////////////////////////////////////////////////////////////////////////////////////// static void StartPatchCheck( void ) { checkingForPatch = true; std::string gameURL, mapURL; std::string configURL, motdURL; FormatURLFromRegistry(gameURL, mapURL, configURL, motdURL); std::string proxy; if (GetStringFromRegistry("", "Proxy", proxy)) { if (!proxy.empty()) { ghttpSetProxy(proxy.c_str()); } } // check for a patch first checksLeft = 2; cantConnect = false; ghttpGet(gameURL.c_str(), GHTTPFalse, patchCheckCallback, NULL); ghttpGet(mapURL.c_str(), GHTTPFalse, patchCheckCallback, NULL); DEBUG_LOG(("Started looking for patches at '%s' && '%s'\n", gameURL.c_str(), mapURL.c_str())); } /////////////////////////////////////////////////////////////////////////////////////// BOOL CALLBACK downloadDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { // HRESULT res; int cmd = LOWORD(wParam); switch( uMsg ) { case WM_COMMAND: if ( cmd == IDC_DLABORT ) { char abort[128]; char abortdload[256]; LoadString(Global_instance, TXT_ABORT_DOWNLOAD, abortdload, sizeof(abortdload)); LoadString(Global_instance, TXT_ABORT, abort, sizeof(abort)); if (MessageBox(g_PrimaryWindow,abortdload,abort,MB_YESNO)==IDYES) { TheDownloadManager->reset(); EndDialog( hwndDlg, g_Finished ); DestroyWindow(hwndDlg); } } else { return FALSE; } break; case WM_INITDIALOG: //SetupDownload(); SendMessage(hwndDlg, WM_SETICON,(WPARAM)ICON_SMALL, (LPARAM)LoadIcon(Global_instance, MAKEINTRESOURCE(IDI_ICON1))); g_DLTimeRem[0]=0; g_DLBytesLeft[0]=0; g_DLBPS[0]=0; //SetDlgItemText( hwndDlg, IDC_DOWNLOADTITLE, g_UpdateString); //SetWindowText(hwndDlg, g_UpdateString); SetDlgItemText( hwndDlg, IDC_TIMEREM, g_DLTimeRem); SetDlgItemText( hwndDlg, IDC_BYTESLEFT, g_DLBytesLeft); // SetDlgItemText( hwndDlg, IDC_BPS, g_DLBPS ); // Work out the full file name //char fullpath[_MAX_PATH]; //char localfile[_MAX_PATH]; //sprintf( fullpath, "%s/%s", g_Update->patchpath,g_Update->patchfile); //sprintf(localfile,"%s\\%s",g_Update->localpath,g_Update->patchfile); // Create the directory //CreateDirectory((char *)g_Update->localpath, NULL ); TheDownloadManager->downloadFile(TheDownload.server, TheDownload.userName, TheDownload.password, TheDownload.file, TheDownload.localFile, TheDownload.regKey, TheDownload.tryResume); /* res=pDownload->DownloadFile((char *)g_Update->server, (char *)g_Update->login, (char *)g_Update->password, fullpath, localfile, APP_REG_KEY); */ g_DownloadWindow = hwndDlg; g_Finished = 0; SetTimer( hwndDlg, 1, 200, NULL ); // was 50 break; case WM_TIMER: DEBUG_LOG(("TIMER\n")); if( g_Finished == 0 ) { DEBUG_LOG(("Entering PumpMsgs\n")); TheDownloadManager->update(); /* pDownload->PumpMessages(); */ DEBUG_LOG(("Done with PumpMsgs\n")); if (strlen(g_DLTimeRem)) SetDlgItemText( hwndDlg, IDC_TIMEREM, g_DLTimeRem ); if (strlen(g_DLBytesLeft)) SetDlgItemText( hwndDlg, IDC_BYTESLEFT, g_DLBytesLeft ); //if (strlen(g_DLBPS)) // SetDlgItemText( hwndDlg, IDC_BPS, g_DLBPS ); } else { DEBUG_LOG(("TIMER: Finished\n")); EndDialog( hwndDlg, g_Finished ); DestroyWindow( hwndDlg ); } break; case WM_DESTROY: KillTimer( hwndDlg, 1 ); //ClosedownDownload(); //DBGMSG("WM_DESTROY"); break; case WM_SETFONT: return TRUE; default: return FALSE; } return TRUE; } DWORD dwChatAdvise; DWORD dwDownloadAdvise; //Update *g_Update; uint32 g_AppVer=-1; BOOL CALLBACK Download_Dialog_Proc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); BOOL CALLBACK Simple_Dialog_Proc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); HWND CreatePrimaryWin(void); char const * Fetch_String(int id); // // Create a primary window // HWND CreatePrimaryWin(void) { HWND hwnd; WNDCLASS wc; char name[256]; sprintf(name,Fetch_String(TXT_TITLE)); //DBGMSG("CreatePrimary: "< 8)) { // Launch the process SHELLEXECUTEINFO info; memset(&info,0,sizeof(info)); info.cbSize=sizeof(info); info.fMask=SEE_MASK_NOCLOSEPROCESS; info.hwnd=g_PrimaryWindow; info.lpVerb=NULL; info.lpFile=regapp; info.lpParameters=NULL; info.lpDirectory="."; info.nShow=SW_SHOW; ShellExecuteEx(&info); // Can't wait infinite or the other process will never create its window // Only Bill himself knows why this is happening while(1) // Wait for completion { DispatchEvents(); if (WaitForSingleObject(info.hProcess,500)!=WAIT_TIMEOUT) break; } } RegCloseKey(rKey); } } // OK, done with that crap go on to the task at hand now.... */ // Find the game version g_AppVer = -1; if (!GetUnsignedIntFromRegistry("", "Version", g_AppVer)) { MessageBox(g_PrimaryWindow,Fetch_String(TXT_INSTALL_PROBLEM),Fetch_String(TXT_ERROR),MB_OK); exit(0); } // OK, have the current game version now g_PrimaryWindow=CreatePrimaryWin(); // Create the main window DispatchEvents(); // process some win messages // Popup the "contacting" window g_ContactWindow=CreateDialog(Global_instance,MAKEINTRESOURCE(IDD_CONNECTING),g_PrimaryWindow,Simple_Dialog_Proc); ShowWindow(g_ContactWindow,SW_SHOWNORMAL); SetForegroundWindow(g_ContactWindow); DispatchEvents(); // process some win messages // Setup the Westwood Online stuff Startup_Chat(); Update_If_Required(); Shutdown_Chat(); return(0); } typedef struct SRecord { int ID; // ID number of the string resource. int TimeStamp; // 'Time' that this string was last requested. char String[2048]; // Copy of string resource. SRecord(void) : ID(-1), TimeStamp(-1) {} } SRecord; /*********************************************************************************************** * Fetch_String -- Fetches a string resource. * * * * Fetches a string resource and returns a pointer to its text. * * * * INPUT: id -- The ID number of the string resource to fetch. * * * * OUTPUT: Returns with a pointer to the actual text of the string resource. * * * * WARNINGS: none * * * * HISTORY: * * 12/25/1996 JLB : Created. * *=============================================================================================*/ char const * Fetch_String(int id) { static SRecord _buffers[64]; static int _time = 0; /* ** Determine if the string ID requested is valid. If not then return an empty string pointer. */ if (id == -1 || id == TXT_NONE) return(""); /* ** Adjust the 'time stamp' tracking value. This is an artificial value used merely to track ** the relative age of the strings requested. */ _time = _time+1; /* ** Check to see if the requested string has already been fetched into a buffer. If so, then ** return a pointer to that string (update the time stamp as well). */ for (int index = 0; index < ARRAY_SIZE(_buffers); index++) { if (_buffers[index].ID == id) { _buffers[index].TimeStamp = _time; return(_buffers[index].String); } } /* ** Find a suitable buffer to hold the string to be fetched. The buffer should either be ** empty or have the oldest fetched string. */ int oldest = -1; int oldtime = -1; for (int text = 0; text < ARRAY_SIZE(_buffers); text++) { if (oldest == -1 || oldtime > _buffers[text].TimeStamp) { oldest = text; oldtime = _buffers[text].TimeStamp; if (oldtime == -1 || _buffers[text].ID == -1) break; } } /* ** A suitable buffer has been found so fetch the string resource and then return a pointer ** to the string. */ char * stringptr = _buffers[oldest].String; _buffers[oldest].ID = id; _buffers[oldest].TimeStamp = _time; if (LoadString(Global_instance, id, stringptr, sizeof(_buffers[oldest].String)) == 0) { return(""); } /****** char resname[32]; sprintf(resname,"#%d",id); HMODULE hmod=GetModuleHandle(NULL); HRSRC hrsrc=FindResourceEx(hmod, RT_STRING, MAKEINTRESOURCE(id), LANGID); if (hrsrc==0) { char message_buffer[256]; FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &message_buffer[0], 256, NULL ); } HGLOBAL resdata=LoadResource(NULL,hrsrc); LPVOID vdata=LockResource(resdata); strcpy(stringptr,(char *)vdata); *********/ stringptr[sizeof(_buffers[oldest].String)-1] = '\0'; return(stringptr); } void LogMsg(char *msg) { #ifdef _DEBUG FILE *out=fopen("register.log","a"); fprintf(out,"%s\n",msg); fflush(out); fclose(out); #endif } void Startup_Chat(void) { /* //////CComObject* g_pChatSink; HRESULT hRes; g_pChatSink=NULL; CoCreateInstance(CLSID_Chat, NULL, CLSCTX_INPROC_SERVER, IID_IChat, (void**)&pChat); if (pChat==NULL) { char error[128]; char apimissing[256]; LoadString(Global_instance, TXT_API_MISSING, apimissing, sizeof(apimissing)); LoadString(Global_instance, TXT_ERROR, error, sizeof(error)); MessageBox(g_PrimaryWindow,apimissing,error,MB_OK); exit(-5); } g_pChatSink=new CChatEventSink; // Get a connection point from the chat class IConnectionPoint *pConnectionPoint=NULL; IConnectionPointContainer *pContainer=NULL; dwChatAdvise=0; hRes=pChat->QueryInterface(IID_IConnectionPointContainer,(void**)&pContainer); _ASSERTE(SUCCEEDED(hRes)); hRes=pContainer->FindConnectionPoint(IID_IChatEvent,&pConnectionPoint); _ASSERTE(SUCCEEDED(hRes)); hRes=pConnectionPoint->Advise((IChatEvent *)g_pChatSink,&dwChatAdvise); _ASSERTE(SUCCEEDED(hRes)); pChat->SetAttributeValue("RegPath",APP_REG_KEY); // ADD pConnectionPoint->Release(); */ } void Shutdown_Chat(void) { /* /////AtlUnadvise(pChat, IID_IChatEvent, dwChatAdvise); IConnectionPoint *pConnectionPoint=NULL; IConnectionPointContainer *pContainer=NULL; HRESULT hRes; hRes=pChat->QueryInterface(IID_IConnectionPointContainer,(void**)&pContainer); _ASSERTE(SUCCEEDED(hRes)); hRes=pContainer->FindConnectionPoint(IID_IChatEvent,&pConnectionPoint); _ASSERTE(SUCCEEDED(hRes)); pConnectionPoint->Unadvise(dwChatAdvise); pChat->Release(); /////delete(g_pChatSink); This appears to be bad.... // ADD g_pChatSink->Release(); // ADD pConnectionPoint->Release(); // ADD pContainer->Release(); */ } // // Download a patch for the registration client if required // This uses the chat API for ver checking and FTP. // void Update_If_Required(void) { int retval; int i; // Create the events for (i=0; iRequestServerList(1000,262364,"register","regpas98",15); ///pChat->RequestServerList(1000,300,"register","regpas98",15); pChat->RequestServerList(g_AppSku,g_AppVer,"register","regpas98",40); while(1) { pChat->PumpMessages(); MSG msg; while(PeekMessage(&msg,NULL,0,0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } retval=WaitForMultipleObjectsEx(NUM_EVENTS,Events,FALSE,50,FALSE); if (retval==WAIT_TIMEOUT) continue; //DBGMSG("An event was set"); retval-=WAIT_OBJECT_0; break; } //DBGMSG("Out of the loop") if (retval==ABORT_EVENT) { exit(0); } else { //DBGMSG("NO update required"); } //DBGMSG("Shutting down"); // close all the event objects for (i=0; i(this) ; } else { *ppv = NULL; return E_NOINTERFACE; } (reinterpret_cast(*ppv))->AddRef() ; return S_OK ; } /////////////////////////////////////////////////////////// // // AddRef // ULONG __stdcall CChatEventSink::AddRef() { return InterlockedIncrement(&m_cRef) ; } /////////////////////////////////////////////////////////// // // Release // ULONG __stdcall CChatEventSink::Release() { if (InterlockedDecrement(&m_cRef) == 0) { delete this ; return 0 ; } return m_cRef; } ///// DOWNLOAD CDownloadEventSink::CDownloadEventSink() { m_cRef=0; // Ref counter } /////////////////////////////////////////////////////////// // // Interface IUnknown Methods // /////////////////////////////////////////////////////////// // // QueryInterface // HRESULT __stdcall CDownloadEventSink::QueryInterface(const IID& iid, void** ppv) { if ((iid == IID_IUnknown) ||(iid == IID_IDownloadEvent)) { *ppv = static_cast(this) ; } else { *ppv = NULL; return E_NOINTERFACE; } (reinterpret_cast(*ppv))->AddRef() ; return S_OK ; } /////////////////////////////////////////////////////////// // // AddRef // ULONG __stdcall CDownloadEventSink::AddRef() { return InterlockedIncrement(&m_cRef) ; } /////////////////////////////////////////////////////////// // // Release // ULONG __stdcall CDownloadEventSink::Release() { if (InterlockedDecrement(&m_cRef) == 0) { delete this ; return 0 ; } return m_cRef; } */ //// FTP Download stuff void SetupDownload( void ) { /* HRESULT hRes; g_pDownloadSink=NULL; CoCreateInstance(CLSID_Download, NULL, CLSCTX_INPROC_SERVER, IID_IDownload, (void**)&pDownload); _ASSERTE(pDownload); g_pDownloadSink=new CDownloadEventSink; // Get a connection point from the chat class IConnectionPoint *pConnectionPoint=NULL; IConnectionPointContainer *pContainer=NULL; dwDownloadAdvise = 0; hRes=pDownload->QueryInterface(IID_IConnectionPointContainer,(void**)&pContainer); _ASSERTE(SUCCEEDED(hRes)); hRes=pContainer->FindConnectionPoint(IID_IDownloadEvent,&pConnectionPoint); _ASSERTE(SUCCEEDED(hRes)); hRes=pConnectionPoint->Advise((IDownloadEvent *)g_pDownloadSink,&dwDownloadAdvise); _ASSERTE(SUCCEEDED(hRes)); */ } void ClosedownDownload( void ) { /* // AtlUnadvise(pDownload, IID_IDownloadEvent, dwDownloadAdvise); IConnectionPoint *pConnectionPoint=NULL; IConnectionPointContainer *pContainer=NULL; HRESULT hRes; hRes=pDownload->QueryInterface(IID_IConnectionPointContainer,(void**)&pContainer); _ASSERTE(SUCCEEDED(hRes)); hRes=pContainer->FindConnectionPoint(IID_IDownloadEvent,&pConnectionPoint); _ASSERTE(SUCCEEDED(hRes)); pConnectionPoint->Unadvise(dwDownloadAdvise); pDownload->Release(); //////delete(g_pDownloadSink); This appears to be bad.... */ } BOOL CALLBACK Download_Dialog_Proc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { // char fullpath[ 256 ]; // char localfile[ 256]; // HRESULT res; switch( uMsg ) { case WM_COMMAND: switch( LOWORD( wParam ) ) { case IDC_DLABORT: { char abort[128]; char abortdload[256]; LoadString(Global_instance, TXT_ABORT_DOWNLOAD, abortdload, sizeof(abortdload)); LoadString(Global_instance, TXT_ABORT, abort, sizeof(abort)); if (MessageBox(g_PrimaryWindow,abortdload,abort,MB_YESNO)==IDYES) { /* pDownload->Abort(); */ EndDialog( hwndDlg, g_Finished ); DestroyWindow(hwndDlg); } } break; default: return FALSE; } break; case WM_INITDIALOG: SetupDownload(); SendMessage(hwndDlg, WM_SETICON,(WPARAM)ICON_SMALL, (LPARAM)LoadIcon(Global_instance, MAKEINTRESOURCE(IDI_ICON1))); g_DLTimeRem[0]=0; g_DLBytesLeft[0]=0; g_DLBPS[0]=0; //SetDlgItemText( hwndDlg, IDC_DOWNLOADTITLE, g_UpdateString); //SetWindowText(hwndDlg, g_UpdateString); SetDlgItemText( hwndDlg, IDC_TIMEREM, g_DLTimeRem); SetDlgItemText( hwndDlg, IDC_BYTESLEFT, g_DLBytesLeft); // SetDlgItemText( hwndDlg, IDC_BPS, g_DLBPS ); /* // Work out the full file name sprintf( fullpath, "%s/%s", g_Update->patchpath,g_Update->patchfile); sprintf(localfile,"%s\\%s",g_Update->localpath,g_Update->patchfile); // Create the directory CreateDirectory((char *)g_Update->localpath, NULL ); res=pDownload->DownloadFile((char *)g_Update->server, (char *)g_Update->login, (char *)g_Update->password, fullpath, localfile, APP_REG_KEY); */ g_DownloadWindow = hwndDlg; g_Finished = 0; SetTimer( hwndDlg, 1, 200, NULL ); // was 50 break; case WM_TIMER: LogMsg("TIMER"); if( g_Finished == 0 ) { LogMsg("Entering PumpMsgs"); /* pDownload->PumpMessages(); */ LogMsg("Done with PumpMsgs"); if (strlen(g_DLTimeRem)) SetDlgItemText( hwndDlg, IDC_TIMEREM, g_DLTimeRem ); if (strlen(g_DLBytesLeft)) SetDlgItemText( hwndDlg, IDC_BYTESLEFT, g_DLBytesLeft ); //if (strlen(g_DLBPS)) // SetDlgItemText( hwndDlg, IDC_BPS, g_DLBPS ); } else { LogMsg("TIMER: Finished"); EndDialog( hwndDlg, g_Finished ); DestroyWindow( hwndDlg ); } break; case WM_DESTROY: KillTimer( hwndDlg, 1 ); ClosedownDownload(); //DBGMSG("WM_DESTROY"); break; case WM_SETFONT: return TRUE; default: return FALSE; } return TRUE; } // Whoeee this is an exciting one... BOOL CALLBACK Simple_Dialog_Proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch( uMsg ) { case WM_INITDIALOG: return(TRUE); break; case WM_CLOSE: DestroyWindow(hwnd); PostQuitMessage(0); exit(0); break; } return(FALSE); } ///////////////////////////////////////////////////////////////////////////// // CDownloadEventSink ////////////////////////////////////////////////////////////////////////////// /* STDMETHODIMP CDownloadEventSink::OnEnd(void) { LogMsg("Finished!"); g_Finished = 1; return(S_OK); } STDMETHODIMP CDownloadEventSink::OnError(int error) { LogMsg("ERROR"); g_Finished = -1; return(S_OK); } STDMETHODIMP CDownloadEventSink::OnProgressUpdate(int bytesread, int totalsize, int timetaken, int timeleft) { SendDlgItemMessage( g_DownloadWindow, IDC_PROGRESS, PBM_SETPOS, (WPARAM)(bytesread * 100) / totalsize, 0 ); char temp[256]; if( timeleft > 0 ) { //DBGMSG("Bytes read: "<next; numupdates++; } // Got a list of updates - If an update is required, the user must either // patch or quit. tmp = updates; LogMsg("Found an update"); // We have a required update char upreq[256]; char title[128]; LoadString(Global_instance, TXT_AN_UPGRADE_AVAILABLE, upreq, sizeof(upreq)); strcat(upreq,"\n"); LoadString(Global_instance, TXT_DOWNLOAD_NOW, upreq+strlen(upreq), sizeof(upreq)); LoadString(Global_instance, TXT_UPGRADE_AVAILABLE, title, sizeof(title)); if( MessageBox(g_PrimaryWindow,upreq,title, MB_YESNO ) == IDNO ) { // If they don't want to patch now, just exit... //DBGMSG("Must patch to continue, so exit"); exit(0); } // Do the downloads while( tmp != NULL ) { g_Update = tmp; char dloading[256]; LoadString(Global_instance, TXT_DOWNLOADING_FILE, dloading, sizeof(dloading)); sprintf( g_UpdateString, dloading, ++i, numupdates ); LogMsg("Creating Download dialog box"); //if( (retval=DialogBox(Global_instance, MAKEINTRESOURCE(IDD_DOWNLOAD_DIALOG), g_PrimaryWindow, // (DLGPROC)Download_Dialog_Proc)) != 1 ) retval=DialogBox(Global_instance, MAKEINTRESOURCE(IDD_DOWNLOAD_DIALOG), g_PrimaryWindow,(DLGPROC)Download_Dialog_Proc); if (g_Finished != 1) { // Download failed //DBGMSG("Download failed: "<next; } // Quit so the launcher can apply the patches exit(0); return(S_OK); // make silly compiler happy } STDMETHODIMP CChatEventSink::OnServerError(HRESULT, LPCSTR) { LogMsg("Server Error"); return(S_OK); } STDMETHODIMP CChatEventSink::OnMessageOfTheDay(HRESULT, LPCSTR) { return(S_OK); } STDMETHODIMP CChatEventSink::OnPrivateAction(HRESULT, User *, LPCSTR) { return(S_OK); } STDMETHODIMP CChatEventSink::OnPublicAction(HRESULT, Channel *, User *, LPCSTR) { return(S_OK); } STDMETHODIMP CChatEventSink::OnPrivateGameOptions(HRESULT, User *, LPCSTR) { return(S_OK); } STDMETHODIMP CChatEventSink::OnPublicGameOptions(HRESULT, Channel *, User *, LPCSTR) { return(S_OK); } STDMETHODIMP CChatEventSink::OnGameStart(HRESULT, Channel *, User *, int) { return(S_OK); } STDMETHODIMP CChatEventSink::OnUserKick(HRESULT, Channel *, User *, User *) { return(S_OK); } STDMETHODIMP CChatEventSink::OnUserIP(HRESULT, User *) { return(S_OK); } STDMETHODIMP CChatEventSink::OnSquadInfo(HRESULT, unsigned long, Squad *) { return(S_OK); } */