summaryrefslogtreecommitdiff
path: root/updater/services.cpp
diff options
context:
space:
mode:
authorsje <sje@4f64403b-2f21-0410-a795-97e2b3489a10>2006-11-01 14:48:34 +0000
committersje <sje@4f64403b-2f21-0410-a795-97e2b3489a10>2006-11-01 14:48:34 +0000
commitd123e0ce94bf90b2adb0a4000930eb467e293226 (patch)
treed414dea59908105c4d2f256199a610e0a69c8690 /updater/services.cpp
parenta13e82647294da4add976a24335fec50d7bfe905 (diff)
git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@16 4f64403b-2f21-0410-a795-97e2b3489a10
Diffstat (limited to 'updater/services.cpp')
-rw-r--r--updater/services.cpp842
1 files changed, 842 insertions, 0 deletions
diff --git a/updater/services.cpp b/updater/services.cpp
new file mode 100644
index 0000000..8ba9de3
--- /dev/null
+++ b/updater/services.cpp
@@ -0,0 +1,842 @@
+#include "common.h"
+#include "services.h"
+
+UpdateList update_list;
+CRITICAL_SECTION list_cs;
+
+DWORD daily_timer_id = 0, startup_timer_id = 0;
+
+HANDLE hMainMenuItem, hGroupMenuItem;
+
+HANDLE hStartupDone = 0;
+
+bool checking = false;
+
+HANDLE hUpdateThread = 0;
+
+#define NUM_SERVICES 13
+HANDLE hService[NUM_SERVICES] = {0};
+
+VOID CALLBACK CheckTimerProcDaily(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
+ if(options.check_daily)
+ CallService(MS_UPDATE_CHECKFORUPDATES, (WPARAM)(is_idle && options.no_conf_idle), 0);
+}
+
+
+// returns true if any downloaded dll is active
+bool DownloadUpdates(UpdateList *todo, FilenameMap *map, bool dlls_only) {
+
+ bool dll_enabled_or_langpack = false;
+
+ bool use_popup = options.popup_notify && ArePopupsEnabled();
+
+ // iterate through the updates we need to check
+
+ if(use_popup) {
+ ShowPopup(0, TranslateT("Downloading Updates"), _T(""), POPFLAG_SAVEHWND, -1);
+ } else {
+ CreateProgressWindow();
+
+ PostMessage(hwndProgress, WM_SETTEXT, 0, (LPARAM)TranslateT("Progress - Downloading updates..."));
+ PostMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Downloading"), 0);
+
+ }
+
+ int count = todo->size(), index = 0;
+ TCHAR msg[512];
+ TCHAR *temp_str;
+ bool a_download_succeeded = false;
+
+ for(todo->reset(); todo->current(); todo->next(), index++) {
+ // remember if the user has decided not to install this version
+ char stored_setting[256];
+ mir_snprintf(stored_setting, 256, "DisabledVer%s", todo->current()->update.szComponentName);
+ DBVARIANT dbv;
+ bool download = todo->current()->update_options.enabled;
+ if(!DBGetContactSetting(0, "Updater", stored_setting, &dbv)) {
+ if(dbv.pszVal && strcmp(dbv.pszVal, todo->current()->newVersion) == 0)
+ download = false;
+ else
+ DBDeleteContactSetting(0, "Updater", stored_setting);
+ DBFreeVariant(&dbv);
+ }
+
+ if(download) {
+ _stprintf(msg, TranslateT("Downloading plugin: %s"), TranslateTS(temp_str = GetTString(todo->current()->update.szComponentName)));
+ free(temp_str);
+ } else {
+ _stprintf(msg, TranslateT("Skipping plugin: %s"), TranslateTS(temp_str = GetTString(todo->current()->update.szComponentName)));
+ free(temp_str);
+ }
+
+ if(!use_popup) {
+ PostMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)msg, 0);
+ PostMessage(hwndProgress, WMU_SETPROGRESS, (WPARAM)(int)(index * 100.0 / count), 0);
+ } //else if(hwndPop) // disabled - just annoying
+ //ChangePopupText(hwndPop, msg);
+
+
+ if(download) {
+ bool got_file = false;
+ if(todo->current()->update_options.use_beta) {
+ // download from i->update.szBetaUpdateURL to temp folder
+ got_file = GetFile(todo->current()->update.szBetaUpdateURL, options.temp_folder, todo->current()->update.szComponentName, todo->current()->newVersion, dlls_only);
+ } else {
+ got_file = GetFile(todo->current()->update.szUpdateURL, options.temp_folder, todo->current()->update.szComponentName, todo->current()->newVersion, dlls_only);
+ }
+
+ if(got_file) {
+ a_download_succeeded = true;
+ if(todo->current()->file_id != -1) {
+ if(todo->current()->cat == MC_PLUGINS)
+ dll_enabled_or_langpack |= RearrangeDlls(todo->current()->shortName, (*map)[todo->current()->file_id]);
+ else if(todo->current()->cat == MC_LOCALIZATION) {
+ RearrangeLangpacks(todo->current()->shortName, (*map)[todo->current()->file_id]);
+ dll_enabled_or_langpack = true;
+ }
+ } else {
+ dll_enabled_or_langpack = true;
+ }
+ }
+ }
+
+ if(use_popup == false && hwndProgress == 0) {
+ RemoveFolder(options.temp_folder);
+ break; // user closed progress window - cancel
+ }
+ }
+
+
+ if(!use_popup && hwndProgress) ProgressWindowDone();
+ // postmessage here causes a lockup on exit! bah popups!!
+ //if(hwndPop) PostMessage(hwndPop, WMU_CLOSEPOP, 0, 0);
+ if(hwndPop) SendMessage(hwndPop, WMU_CLOSEPOP, 0, 0);
+
+ if(!a_download_succeeded) {
+ for(todo->reset(); todo->current(); todo->next())
+ free(todo->current()->newVersion);
+ todo->clear();
+ }
+
+ return dll_enabled_or_langpack;
+}
+
+void __stdcall sttNotifyStartup( ULONG dwParam ) {
+ NotifyEventHooks(hStartupDone, 0, 0);
+}
+
+void RestoreStatus() {
+ //NotifyEventHooks(hStartupDone, 0, 0);
+ // do this in a seperate thread, in case we're called from an event hook to prevent double-lock on core hook critical section (csHooks)
+ QueueUserAPC(sttNotifyStartup, mainThread, 0);
+
+ if(options.start_offline) {
+ // restore global status - only works on startup since we remove the SavedGlobalStatus parameter
+ WORD clist_status = DBGetContactSettingWord(0, "CList", "Status", ID_STATUS_OFFLINE),
+ saved_global_status = DBGetContactSettingWord(0, MODULE, "SavedGlobalStatus", clist_status);
+ if(clist_status == ID_STATUS_OFFLINE && saved_global_status != clist_status) {
+#ifdef DEBUG_POPUPS
+ PUShowMessage("Updater: restoring status", SM_NOTIFY);
+#endif
+ CallService(MS_CLIST_SETSTATUSMODE, (WPARAM)saved_global_status, 0);
+ }
+ }
+ DBDeleteContactSetting(0, MODULE, "SavedGlobalStatus");
+}
+
+bool WriteLastCheckTime() {
+ SYSTEMTIME now;
+ GetSystemTime(&now);
+
+ DBWriteContactSettingWord(0, MODULE, "LastUpdateDay", now.wDay);
+ DBWriteContactSettingWord(0, MODULE, "LastUpdateMonth", now.wMonth);
+ DBWriteContactSettingWord(0, MODULE, "LastUpdateYear", now.wYear);
+
+ return true;
+}
+
+//DWORD CALLBACK CheckForUpdatesWorker(LPVOID param) {
+unsigned int CALLBACK CheckForUpdatesWorker(void *param) {
+
+ if(checking) return 1;
+ if(!(GetSystemMetrics(SM_NETWORK) & 1)) {
+ ShowError(TranslateT("No network - aborting update check"));
+ NLog("worker thread aborting - no network");
+ return 1; // no network
+ }
+
+ NLog("CheckForUpdatesWorker thread starting");
+
+ checking = true;
+
+ WriteLastCheckTime();
+
+ bool confirm = !(((DWORD)param & 1) == 1);
+ bool restart = !(((DWORD)param & 2) == 2); // if restart is false, then we're doing an 'update and shutdown'
+
+ if(hwndOptions) PostMessage(hwndOptions, WMU_CHECKING, 0, 0);
+
+ bool use_popup = options.popup_notify && ArePopupsEnabled();
+
+ FilenameMap fn_map;
+
+ if(use_popup) {
+ ShowPopup(0, TranslateT("Checking for Updates"), _T(""), POPFLAG_SAVEHWND, -1);
+ } else {
+ CreateProgressWindow();
+
+ PostMessage(hwndProgress, WM_SETTEXT, 0, (LPARAM)TranslateT("Progress - Checking for updates..."));
+ if(options.use_xml_backend) PostMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Downloading XML data"), 0);
+ else PostMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Checking for updates"), 0);
+
+ }
+
+ EnterCriticalSection(&list_cs);
+
+ if(options.use_xml_backend) {
+ if(UpdateXMLData(MC_PLUGINS)) {// prevent double error messages (in some cases)
+ // iterate through the registered plugins
+ if(!use_popup) PostMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Scanning plugins folder"), 0);
+ ScanPlugins(&fn_map, &update_list);
+
+ if(UpdateXMLData(MC_LOCALIZATION)) {
+ if(!use_popup) PostMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Scanning language packs"), 0);
+ ScanLangpacks(&fn_map, &update_list);
+ }
+
+ if(!use_popup) PostMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Updating component file listing ids"), 0);
+ UpdateFLIDs(update_list);
+ }
+
+ if(!use_popup) PostMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Checking for updates"), 0);
+ }
+
+ UpdateList update_list2(update_list);
+ LeaveCriticalSection(&list_cs);
+
+ int count = update_list2.size(), index = 0;
+ TCHAR msg[512];
+ TCHAR *temp_str;
+
+ UpdateList todo;
+
+ for(update_list2.reset(); update_list2.current(); update_list2.next(), index++) {
+ if(update_list2.current()->update_options.enabled) {
+ _stprintf(msg, TranslateT("Checking plugin: %s"), TranslateTS(temp_str = GetTString(update_list2.current()->update.szComponentName)));
+ free(temp_str);
+ } else {
+ _stprintf(msg, TranslateT("Skipping plugin: %s"), TranslateTS(temp_str = GetTString(update_list2.current()->update.szComponentName)));
+ free(temp_str);
+ }
+
+ if(!use_popup) {
+ PostMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)msg, 0);
+ PostMessage(hwndProgress, WMU_SETPROGRESS, (WPARAM)(int)(index * 100.0 / count), 0);
+ } //else if(hwndPop) // disabled - just annoying
+ //ChangePopupText(hwndPop, msg);
+
+ if(update_list2.current()->update_options.enabled) {
+ char *nv;
+ bool beta;
+ if(nv = UpdateRequired(update_list2.current(), &beta)) {
+ todo.push_back(*update_list2.current());
+ todo.back().newVersion = nv;
+ todo.back().update_options.use_beta = beta;
+ }
+ }
+ if(use_popup == false && hwndProgress == 0) {
+ RemoveFolder(options.temp_folder);
+ break; // user closed progress window - cancel
+ }
+ }
+
+ if(!use_popup && hwndProgress) ProgressWindowDone();
+ if(hwndPop) PostMessage(hwndPop, WMU_CLOSEPOP, 0, 0);
+
+ if(options.use_xml_backend) {
+ FreeXMLData(MC_PLUGINS);
+ FreeXMLData(MC_LOCALIZATION);
+ }
+
+ bool restore_status = true;
+
+ if(todo.size()) {
+ int cd_ret = CD_OK;
+ if(confirm) {
+ if(use_popup) {
+ ShowPopup(0, TranslateT("Updates Available"), TranslateT("Click here to install"), POPFLAG_SAVEHWND, -1);
+ DWORD ret;
+ while((ret = WaitForSingleObject(hEventPop, 200)) == WAIT_TIMEOUT && !Miranda_Terminated());
+ if(!pop_cancelled && ret == WAIT_OBJECT_0 && !Miranda_Terminated()) {
+ cd_ret = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CONFIRMUPDATES), GetDesktopWindow(), DlgProcConfirm, (LPARAM)&todo);
+ } else {
+ if(hwndOptions) PostMessage(hwndOptions, WMU_DONECHECKING, 0, 0);
+ RestoreStatus();
+ for(todo.reset(); todo.current(); todo.next())
+ free(todo.current()->newVersion);
+ checking = false;
+ return 1;
+ }
+ } else
+ cd_ret = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CONFIRMUPDATES), GetDesktopWindow(), DlgProcConfirm, (LPARAM)&todo);
+ }
+
+
+
+ if(!confirm || cd_ret == CD_CONFALL || cd_ret == CD_NOINSTALL || cd_ret == CD_OK) {
+
+ bool conf_all = (cd_ret == CD_CONFALL), no_install = (cd_ret == CD_NOINSTALL);
+
+ // ensure the backup folder exists (either create it or return non-zero signifying error)
+ if(options.backup && !CreatePath(options.backup_folder)) {
+ //MessageBox(0, Translate("Could not create backup folder"), Translate("Error"), MB_OK | MB_ICONERROR);
+ ShowError(TranslateT("Could not create backup folder"));
+ if(hwndOptions) PostMessage(hwndOptions, WMU_DONECHECKING, 0, 0);
+ RestoreStatus();
+ for(todo.reset(); todo.current(); todo.next())
+ free(todo.current()->newVersion);
+ checking = false;
+ return 1;
+ }
+
+ bool dll_enabled_or_langpack = DownloadUpdates(&todo, &fn_map, confirm ? false : options.auto_dll_only);
+ if(todo.size() && !no_install) {
+ if(!conf_all || DialogBox(hInst, MAKEINTRESOURCE(IDD_CONFIRMCOMPONENTS), GetDesktopWindow(), DlgProcConfirmComponents) == IDOK) {
+ if(!dll_enabled_or_langpack && restart) {
+ // we're not doing an 'update and shutdown', and we're not updating any active dlls...so just install
+
+ // get folders
+ TCHAR root_folder[MAX_PATH], plugins_folder[MAX_PATH], *p;
+
+ GetModuleFileName(0, root_folder, MAX_PATH);
+ _tcscpy(plugins_folder, root_folder);
+ p = _tcsrchr(plugins_folder, '\\');
+ if(p) *p = 0;
+ _tcscat(plugins_folder, _T("\\Plugins"));
+
+ p = _tcsrchr(root_folder, _T('\\'));
+ if(p) *p = 0;
+
+ // move files
+ MoveFiles(0, options.temp_folder, plugins_folder, options.backup_folder, root_folder);
+
+ // rescan to get correct version numbers
+ ScanPlugins(0, 0);
+ } else {
+ if(ExternProcess(restart) == 0) // if restarting, don't restore status
+ restore_status = false;
+ }
+ }
+ }
+ }
+
+ for(todo.reset(); todo.current(); todo.next())
+ free(todo.current()->newVersion);
+
+ } else if(!restart) {
+ HWND hWndMiranda = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
+ PostMessage(hWndMiranda, WM_COMMAND, ID_ICQ_EXIT, 0);
+ }
+
+ if(restore_status && restart) { // restore status if we're not doing an 'update and shutdown', and the update was unsuccessful (or there was nothing to update, or no need to shutdown)
+ checking = false;
+ if(hwndOptions) PostMessage(hwndOptions, WMU_DONECHECKING, 0, 0);
+ RestoreStatus();
+ }
+
+ return 0;
+}
+
+int Restart(WPARAM wParam, LPARAM lParam) {
+ ExternProcess(true);
+ return 0;
+}
+
+int UpdateAndExit(WPARAM wParam, LPARAM lParam) {
+ return CallService(MS_UPDATE_CHECKFORUPDATES, 0, 1);
+}
+
+// if wParam, don't confirm
+// if lParam, install and shutdown but don't restart
+int CheckForUpdates(WPARAM wParam, LPARAM lParam) {
+ if(daily_timer_id) KillTimer(0, daily_timer_id);
+ daily_timer_id = SetTimer(0, 0, 24 * 60 * 60 * 1000, CheckTimerProcDaily);
+
+ DWORD param = ((wParam ? 1 : 0) | (lParam ? 2 : 0));
+
+ if(hUpdateThread) CloseHandle(hUpdateThread);
+ //hUpdateThread = CreateThread(0, 0, CheckForUpdatesWorker, (void *)param, 0, 0);
+ hUpdateThread = (HANDLE)_beginthreadex(0, 0, CheckForUpdatesWorker, (void *)param, 0, 0);
+ NLog("CheckForUpdates service called");
+
+ return 0;
+}
+
+int EnumerateUpdates(WPARAM wParam, LPARAM lParam) {
+ UpdateEnumerateFunc func = (UpdateEnumerateFunc)wParam;
+
+ EnterCriticalSection(&list_cs);
+ for(update_list.reset(); update_list.current(); update_list.next()) {
+ func(update_list.current()->update.szComponentName, &(update_list.current()->update_options), lParam);
+ }
+ LeaveCriticalSection(&list_cs);
+
+ return 0;
+}
+
+void LoadUpdateOptions(char *szComponentName, UpdateOptions *update_options) {
+ char buff[256];
+ sprintf(buff, "Enable%s", szComponentName);
+ update_options->enabled = (DBGetContactSettingByte(0, MODULE, buff, 1) == 1);
+ if(!update_options->fixed) {
+ sprintf(buff, "UseBeta%s", szComponentName);
+ update_options->use_beta = (DBGetContactSettingByte(0, MODULE, buff, 0) == 1);
+ }
+}
+
+void SaveUpdateOptions(char *szComponentName, UpdateOptions *update_options) {
+ char buff[256];
+ sprintf(buff, "Enable%s", szComponentName);
+ DBWriteContactSettingByte(0, MODULE, buff, update_options->enabled ? 1 : 0);
+ if(!update_options->fixed) {
+ sprintf(buff, "UseBeta%s", szComponentName);
+ DBWriteContactSettingByte(0, MODULE, buff, update_options->use_beta ? 1 : 0);
+ }
+}
+
+int SetUpdateOptions(WPARAM wParam, LPARAM lParam) {
+ char *szComponentName = (char *)wParam;
+ UpdateOptions *uo = (UpdateOptions *)lParam;
+ TCHAR *temp1 = 0, *temp2 = 0;
+
+ bool found = false;
+ EnterCriticalSection(&list_cs);
+ for(update_list.reset(); update_list.current(); update_list.next()) {
+ if(strcmp(update_list.current()->update.szComponentName, szComponentName) == 0
+ || _tcscmp(TranslateTS(temp1 = GetTString(update_list.current()->update.szComponentName)), (TCHAR *)szComponentName) == 0) // when set via options, szComponentName is translated and potentially already converted to unicode
+ {
+ found = true;
+ update_list.current()->update_options = *uo;
+ SaveUpdateOptions(update_list.current()->update.szComponentName, &update_list.current()->update_options);
+ if(update_list.current()->file_id == -1 && !uo->use_beta) {
+ update_list.current()->file_id = CheckForFileID(update_list.current()->update.szUpdateURL, update_list.current()->update.szVersionURL, update_list.current()->update.szComponentName);
+ }
+ break;
+ }
+ }
+ LeaveCriticalSection(&list_cs);
+ if(temp1) free(temp1);
+ if(temp2) free(temp2);
+
+ return found ? 0 : 1;
+}
+
+int GetUpdateOptions(WPARAM wParam, LPARAM lParam) {
+ char *szComponentName = (char *)wParam;
+ UpdateOptions *uo = (UpdateOptions *)lParam;
+ TCHAR *temp1 = 0, *temp2 = 0;
+
+ bool found = false;
+ EnterCriticalSection(&list_cs);
+ for(update_list.reset(); update_list.current(); update_list.next()) {
+ if(strcmp(update_list.current()->update.szComponentName, szComponentName) == 0
+ || _tcscmp(TranslateTS(temp1 = GetTString(update_list.current()->update.szComponentName)), (TCHAR *)szComponentName) == 0) // when set via options, szComponentName is translated and potentially already converted to unicode
+ {
+ found = true;
+ *uo = update_list.current()->update_options;
+ break;
+ }
+ }
+ LeaveCriticalSection(&list_cs);
+ if(temp1) free(temp1);
+ if(temp2) free(temp2);
+
+ return found ? 0 : 1;
+}
+
+bool RegisterForFileListing(int file_id, PLUGININFO *pluginInfo, bool auto_register) {
+ return RegisterForFileListing(file_id, pluginInfo->shortName, pluginInfo->version, auto_register, MC_PLUGINS);
+}
+
+bool IsRegistered(int file_id) {
+ EnterCriticalSection(&list_cs);
+ for(update_list.reset(); update_list.current(); update_list.next()) {
+ if(update_list.current()->file_id == file_id) {
+ LeaveCriticalSection(&list_cs);
+ return true; // plugin already registered
+ }
+ }
+ LeaveCriticalSection(&list_cs);
+
+ return false;
+}
+
+bool RegisterForFileListing(int file_id, const char *fl_name, DWORD version, bool auto_register, const Category cat) {
+ // allow multiple registration of same plugin only if new plugin not automatically registered
+ // if multiple registration of an auto registered plugin occurs, use newest file id and version
+ EnterCriticalSection(&list_cs);
+ for(update_list.reset(); update_list.current(); update_list.next()) {
+ if(strcmp(update_list.current()->update.szComponentName, fl_name) == 0) {
+ if(!auto_register) {
+ update_list.erase();
+ break;
+ }
+ if(update_list.current()->auto_register) {
+ update_list.current()->file_id = file_id; // in case plugin file id changes (i.e. scan from xml data will overwrite settings read from db on startup)
+ char version_str[16];
+ update_list.current()->update.pbVersion = (BYTE *)safe_strdup(CreateVersionString(version, version_str));
+ update_list.current()->update.cpbVersion = strlen(version_str);
+ }
+ LeaveCriticalSection(&list_cs);
+
+ // plugin already registered - set file id if AUTOREGISTER
+ if(update_list.current()->update.szUpdateURL && strcmp(update_list.current()->update.szUpdateURL, UPDATER_AUTOREGISTER) == 0) {
+ update_list.current()->file_id = file_id;
+ char *buff = (char *)safe_alloc(strlen(MIM_DOWNLOAD_URL_PREFIX) + 9);
+ sprintf(buff, MIM_DOWNLOAD_URL_PREFIX "%d", file_id);
+ update_list.current()->update.szUpdateURL = buff;
+ update_list.current()->shortName = safe_strdup(update_list.current()->update.szComponentName);
+
+ if(update_list.current()->update.szBetaVersionURL) {
+ update_list.current()->update_options.fixed = false;
+ LoadUpdateOptions(update_list.current()->update.szComponentName, &update_list.current()->update_options);
+ }
+ }
+ return false;
+ }
+ }
+ LeaveCriticalSection(&list_cs);
+
+ UpdateInternal update_internal = {0};
+ char version_str[16];
+ char *buff;
+
+ update_internal.cat = cat;
+ update_internal.shortName = safe_strdup(fl_name);
+
+ update_internal.update.szComponentName = safe_strdup(fl_name);
+ update_internal.update.pbVersion = (BYTE *)safe_strdup(CreateVersionString(version, version_str));
+ update_internal.update.cpbVersion = strlen(version_str);
+
+ buff = (char *)safe_alloc(strlen(MIM_DOWNLOAD_URL_PREFIX) + 9);
+ sprintf(buff, MIM_DOWNLOAD_URL_PREFIX "%d", file_id);
+ update_internal.update.szUpdateURL = buff;
+
+ ///////// only used when not using the xml backend ////////////
+ buff = (char *)safe_alloc(strlen("class=\"fileNameHeader\">") + strlen(fl_name) + 2);
+ sprintf(buff, "class=\"fileNameHeader\">%s ", fl_name);
+ update_internal.update.pbVersionPrefix = (BYTE *)buff;
+ update_internal.update.cpbVersionPrefix = strlen(buff);
+
+ buff = (char *)safe_alloc(strlen(MIM_VIEW_URL_PREFIX) + 9);
+ sprintf(buff, MIM_VIEW_URL_PREFIX "%d", file_id);
+ update_internal.update.szVersionURL = buff;
+ ///////////////////////////////////////////////////////////////
+
+ // same as register, except for fileID
+ update_internal.file_id = file_id;
+ update_internal.auto_register = auto_register;
+ update_internal.update_options.fixed = true;
+ update_internal.update_options.use_beta = false;
+
+ LoadUpdateOptions(update_internal.update.szComponentName, &update_internal.update_options);
+
+ EnterCriticalSection(&list_cs);
+ update_list.push_back(update_internal);
+ LeaveCriticalSection(&list_cs);
+
+ return true;
+}
+
+void DoStartupProcess() {
+ if(checking) return;
+
+ if(OldXMLDataExists(MC_PLUGINS) && OldXMLDataExists(MC_LOCALIZATION)) {
+ if(options.check_on_startup) {
+ SYSTEMTIME now;
+ GetSystemTime(&now);
+
+ if(options.check_once) {
+ if(DBGetContactSettingWord(0, MODULE, "LastUpdateDay", 32) == 32) {
+ CallService(MS_UPDATE_CHECKFORUPDATES, 0, 0);
+ } else {
+ if(now.wDay != DBGetContactSettingWord(0, MODULE, "LastUpdateDay", now.wDay)
+ || now.wMonth != DBGetContactSettingWord(0, MODULE, "LastUpdateMonth", now.wMonth)
+ || now.wYear != DBGetContactSettingWord(0, MODULE, "LastUpdateYear", now.wYear))
+ {
+ CallService(MS_UPDATE_CHECKFORUPDATES, 0, 0);
+ } else {
+ if(LoadOldXMLData(MC_PLUGINS, false)) {
+ ScanPlugins(0, 0);
+ FreeXMLData(MC_PLUGINS);
+ }
+ if(LoadOldXMLData(MC_LOCALIZATION, false)) {
+ ScanLangpacks(0, 0);
+ FreeXMLData(MC_LOCALIZATION);
+ }
+
+ RestoreStatus();
+ }
+ }
+ } else {
+ CallService(MS_UPDATE_CHECKFORUPDATES, 0, 0);
+ }
+ } else {
+ if(LoadOldXMLData(MC_PLUGINS, false)) {
+ ScanPlugins(0, 0);
+ FreeXMLData(MC_PLUGINS);
+ }
+ if(LoadOldXMLData(MC_LOCALIZATION, false)) {
+ ScanLangpacks(0, 0);
+ FreeXMLData(MC_LOCALIZATION);
+ }
+
+ RestoreStatus();
+ }
+ } else {
+ if(options.check_on_startup) CallService(MS_UPDATE_CHECKFORUPDATES, 0, 0);
+ else RestoreStatus();
+ }
+
+}
+
+
+int Register(WPARAM wParam, LPARAM lParam) {
+
+ Update *update = (Update *)lParam;
+ UpdateInternal update_internal = {0};
+
+ // remove registered plugin if already there
+ EnterCriticalSection(&list_cs);
+ for(update_list.reset(); update_list.current(); update_list.next()) {
+ if(strcmp(update_list.current()->update.szComponentName, update->szComponentName) == 0) {
+ update_list.erase();
+ break;
+ }
+ }
+ LeaveCriticalSection(&list_cs);
+
+ if(update->szComponentName == 0 || update->pbVersion == 0)
+ return 1;
+ if(update->szVersionURL == 0 && (update->szUpdateURL == 0 || strcmp(update->szUpdateURL, UPDATER_AUTOREGISTER) != 0) && update->szBetaVersionURL == 0) // both betas and normal updates disabled - complain
+ return 1;
+
+ update_internal.cat = MC_UNKNOWN;
+
+ // duplicate all the data...sigh
+ update_internal.update.szComponentName = safe_strdup(update->szComponentName);
+
+ if(update->szVersionURL) update_internal.update.szVersionURL = safe_strdup(update->szVersionURL);
+ if(update->szUpdateURL) update_internal.update.szUpdateURL = safe_strdup(update->szUpdateURL);
+
+ // if revision update url is from the fl, and we can find the file_id, use xml data if available
+ // otherwise set this to -1 to check url's specified
+ if(update_internal.update.szUpdateURL)
+ update_internal.file_id = CheckForFileID(update_internal.update.szUpdateURL, update_internal.update.szVersionURL, update_internal.update.szComponentName);
+ else
+ update_internal.file_id = -1;
+
+ if(update_internal.file_id != -1) { // ensure correct format for file listing version string search data
+ char *buff = (char *)safe_alloc(strlen("class=\"fileNameHeader\">") + strlen(update->szComponentName) + 2);
+ sprintf(buff, "class=\"fileNameHeader\">%s ", update->szComponentName);
+ update_internal.update.pbVersionPrefix = (BYTE *)buff;
+ update_internal.update.cpbVersionPrefix = strlen(buff);
+
+ update_internal.shortName = safe_strdup(update->szComponentName);
+ } else {
+ if(update->pbVersionPrefix) update_internal.update.pbVersionPrefix = safe_bytedup(update->pbVersionPrefix, update->cpbVersionPrefix);
+ update_internal.update.cpbVersionPrefix = update->cpbVersionPrefix;
+ }
+
+ // leave beta alone
+ if(update->szBetaVersionURL) update_internal.update.szBetaVersionURL = safe_strdup(update->szBetaVersionURL);
+ if(update->pbBetaVersionPrefix) update_internal.update.pbBetaVersionPrefix = safe_bytedup(update->pbBetaVersionPrefix, update->cpbBetaVersionPrefix);
+ update_internal.update.cpbBetaVersionPrefix = update->cpbBetaVersionPrefix;
+ if(update->szBetaUpdateURL) update_internal.update.szBetaUpdateURL = safe_strdup(update->szBetaUpdateURL);
+
+ update_internal.update.pbVersion = safe_bytedup(update->pbVersion, update->cpbVersion);
+ update_internal.update.cpbVersion = update->cpbVersion;
+
+ if(update->cbSize > UPDATE_V1_SIZE && update->szBetaChangelogURL)
+ update_internal.update.szBetaChangelogURL = safe_strdup(update->szBetaChangelogURL);
+
+ update_internal.update_options.fixed = (update->szVersionURL == 0 || strcmp(update->szUpdateURL, UPDATER_AUTOREGISTER) == 0 || update->szBetaVersionURL == 0); // set 'fixed' flag
+ update_internal.update_options.use_beta = (update->szVersionURL == 0 || strcmp(update->szUpdateURL, UPDATER_AUTOREGISTER) == 0);
+ LoadUpdateOptions(update_internal.update.szComponentName, &update_internal.update_options);
+
+ EnterCriticalSection(&list_cs);
+ update_list.push_back(update_internal);
+ LeaveCriticalSection(&list_cs);
+
+ //if(strcmp(update_internal.update.szComponentName, "My Details") == 0) {
+ // MessageBox(0, "My Details registered", "msg", MB_OK);
+ //}
+
+ return 0;
+}
+
+int RegisterFL(WPARAM wParam, LPARAM lParam) {
+ int file_id = (int)wParam;
+ PLUGININFO *pluginInfo = (PLUGININFO *)lParam;
+
+ // remove registered plugin if already there
+ EnterCriticalSection(&list_cs);
+ for(update_list.reset(); update_list.current(); update_list.next()) {
+ if(strcmp(update_list.current()->update.szComponentName, pluginInfo->shortName) == 0) {
+ update_list.erase();
+ break;
+ }
+ }
+ LeaveCriticalSection(&list_cs);
+
+ RegisterForFileListing(file_id, pluginInfo, false);
+
+ return 0;
+}
+
+int Unregister(WPARAM wParam, LPARAM lParam) {
+ char *szComponentName = (char *)lParam;
+
+ // remove registered plugin if found
+ EnterCriticalSection(&list_cs);
+ for(update_list.reset(); update_list.current(); update_list.next()) {
+ if(strcmp(update_list.current()->update.szComponentName, szComponentName) == 0) {
+ update_list.erase();
+ break;
+ }
+ }
+ LeaveCriticalSection(&list_cs);
+
+ return 0;
+}
+
+int CheckForUpdatesTrgr(WPARAM wParam, LPARAM lParam) {
+ if(wParam & ACT_PERFORM) {
+#ifdef DEBUG_POPUPS
+ PUShowMessage("Updater: triggered check", SM_NOTIFY);
+#endif
+ CallService(MS_UPDATE_CHECKFORUPDATES, (WPARAM)(is_idle && options.no_conf_idle), 0);
+ }
+ return 0;
+}
+
+int ServicesModulesLoaded2(WPARAM wParam, LPARAM lParam) {
+ // do initial update etc. depending on options and time
+ KillTimer(0, startup_timer_id);
+ DoStartupProcess();
+ return 0;
+}
+
+VOID CALLBACK StartupTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
+ KillTimer(0, startup_timer_id);
+ ServicesModulesLoaded2(0, 0);
+}
+
+HANDLE hEventServicesModulesLoaded2;
+
+int ServicesModulesLoaded(WPARAM wParam, LPARAM lParam) {
+ // add main menu item
+
+ CLISTMENUITEM menu = {0};
+
+ menu.cbSize=sizeof(menu);
+ menu.flags = CMIM_ALL;
+ menu.hIcon = hIconCheck;
+
+ menu.pszName = Translate("Check for updates");
+ menu.pszService= MS_UPDATE_CHECKFORUPDATES;
+ menu.position = 500010000;
+#ifdef MS_CLIST_ADDGROUPMENUITEM
+ if (ServiceExists(MS_CLIST_ADDGROUPMENUITEM)) {
+ GroupMenuParam gmp = {0};
+ hGroupMenuItem = (HANDLE)CallService(MS_CLIST_ADDGROUPMENUITEM,(WPARAM)&gmp,(LPARAM)&menu);
+ }
+#endif
+ hMainMenuItem = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&menu);
+
+ hEventServicesModulesLoaded2 = HookEvent(ME_SYSTEM_MODULESLOADED, ServicesModulesLoaded2);
+ startup_timer_id = SetTimer(0, 0, 5000, StartupTimerProc);
+
+ return 0;
+}
+
+int EnableStatusControl(WPARAM wParam, LPARAM lParam) {
+ BOOL enable = (BOOL)wParam;
+
+ options.start_offline = (enable == TRUE);
+
+ return 0;
+}
+
+int IsUpdateSupported(WPARAM wParam, LPARAM lParam) {
+ char *szComponentName = (char *)lParam;
+ EnterCriticalSection(&list_cs);
+ for(update_list.reset(); update_list.current(); update_list.next()) {
+ if(strcmp(update_list.current()->update.szComponentName, szComponentName) == 0) {
+ return TRUE;
+ }
+ }
+ LeaveCriticalSection(&list_cs);
+
+ return FALSE;
+}
+
+int ServicesPreShutdown(WPARAM wParam, LPARAM lParam) {
+ KillProgressWindowThread();
+ return 0;
+}
+
+HANDLE hEventPreShutDown, hEventServicesModulesLoaded;
+void InitServices() {
+ InitAlternateShortNameMap();
+
+ InitializeCriticalSection(&list_cs);
+
+ int i = 0;
+ hService[i++] = CreateServiceFunction(MS_UPDATE_REGISTER, Register);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_REGISTERFL, RegisterFL);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_UNREGISTER, Unregister);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_CHECKFORUPDATESTRGR, CheckForUpdatesTrgr);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_CHECKFORUPDATES, CheckForUpdates);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_SETUPDATEOPTIONS, SetUpdateOptions);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_GETUPDATEOPTIONS, GetUpdateOptions);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_ENUMERATE, EnumerateUpdates);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_ENABLESTATUSCONTROL, EnableStatusControl);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_MENURESTART, Restart);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_MENUUPDATEANDEXIT, UpdateAndExit);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_MENUCHECKFORUPDATES, CheckForUpdates);
+ hService[i++] = CreateServiceFunction(MS_UPDATE_ISUPDATESUPPORTED, IsUpdateSupported);
+
+ hStartupDone = CreateHookableEvent(ME_UPDATE_STARTUPDONE);
+
+ hEventPreShutDown = HookEvent(ME_SYSTEM_PRESHUTDOWN, ServicesPreShutdown);
+
+ daily_timer_id = SetTimer(0, 0, 24 * 60 * 60 * 1000, CheckTimerProcDaily);
+
+ MakeProgressWindowThread();
+
+ hEventServicesModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ServicesModulesLoaded);
+}
+
+void DeinitServices() {
+ UnhookEvent(hEventPreShutDown);
+ UnhookEvent(hEventServicesModulesLoaded);
+ UnhookEvent(hEventServicesModulesLoaded2);
+
+ if(daily_timer_id) KillTimer(0, daily_timer_id);
+
+ if(hUpdateThread) {
+ WaitForSingleObject(hUpdateThread, INFINITE);
+ CloseHandle(hUpdateThread);
+ }
+
+ DestroyHookableEvent(hStartupDone);
+
+ for(int i = 0; i < NUM_SERVICES; i++)
+ if(hService[i])
+ DestroyServiceFunction(hService[i]);
+
+ DeleteCriticalSection(&list_cs);
+ update_list.clear();
+}
+