# HG changeset patch # User Daniel Atallah # Date 1184349825 0 # Node ID c36b62c6e0b34bfdeb9ced262e7a0d412bf5b5ec # Parent 850cccc126adc608d527df20df031c5c6e96dcf2 Convert portable winpidgin launcher executable to be the same binary as pidgin.exe and determine which behavior to use at runtime. Running "pidgin.exe --portable-mode" or renaming "pidgin.exe" to "pidgin-portable.exe" will cause the portable mode to be used. diff -r 850cccc126ad -r c36b62c6e0b3 pidgin/Makefile.mingw --- a/pidgin/Makefile.mingw Fri Jul 13 13:57:59 2007 +0000 +++ b/pidgin/Makefile.mingw Fri Jul 13 18:03:45 2007 +0000 @@ -129,7 +129,7 @@ ## ## TARGET DEFINITIONS ## -.PHONY: all install install_shallow clean clean_exe +.PHONY: all install install_shallow clean all: $(EXE_TARGET).exe $(PIDGIN_TARGET).dll $(MAKE) -C $(PIDGIN_PLUGINS_TOP) -f $(MINGW_MAKEFILE) @@ -161,12 +161,6 @@ $(EXE_TARGET).exe: $(PIDGIN_CONFIG_H) $(PIDGIN_DLL).a $(PIDGIN_IDLETRACK_DLL).a $(EXE_OBJECTS) $(CC) $(LDFLAGS) $(EXE_OBJECTS) -o $(EXE_TARGET).exe -$(EXE_TARGET)-portable.exe: DEFINES += -DPORTABLE -$(EXE_TARGET)-portable.exe: EXE_NAME := $(EXE_TARGET)-portable.exe -$(EXE_TARGET)-portable.exe: clean_exe $(PIDGIN_CONFIG_H) $(PIDGIN_DLL).a $(PIDGIN_IDLETRACK_DLL).a $(EXE_OBJECTS) - $(CC) $(LDFLAGS) $(EXE_OBJECTS) -o $(EXE_TARGET)-portable.exe - $(MAKE) -f $(MINGW_MAKEFILE) clean_exe - ## ## CLEAN RULES ## @@ -175,9 +169,6 @@ $(MAKE) -C $(PIDGIN_PLUGINS_TOP) -f $(MINGW_MAKEFILE) clean rm -f $(PIDGIN_OBJECTS) $(PIDGIN_RC_SRC) $(EXE_OBJECTS) $(EXE_RC_SRC) rm -f $(PIDGIN_TARGET).dll $(PIDGIN_TARGET).dll.a - rm -f $(EXE_TARGET).exe $(EXE_TARGET)-portable.exe - -clean_exe: - rm -f $(EXE_OBJECTS) $(EXE_RC_SRC) + rm -f $(EXE_TARGET).exe include $(PIDGIN_COMMON_TARGETS) diff -r 850cccc126ad -r c36b62c6e0b3 pidgin/win32/winpidgin.c --- a/pidgin/win32/winpidgin.c Fri Jul 13 13:57:59 2007 +0000 +++ b/pidgin/win32/winpidgin.c Fri Jul 13 18:03:45 2007 +0000 @@ -55,6 +55,8 @@ typedef void (CALLBACK* LPFNSETDLLDIRECTORY)(LPCTSTR); typedef BOOL (CALLBACK* LPFNATTACHCONSOLE)(DWORD); +static BOOL portable_mode = FALSE; + /* * PROTOTYPES */ @@ -106,78 +108,10 @@ return ret; } -static void dll_prep() { - char path[MAX_PATH + 1]; +static void common_dll_prep(const char *path) { HMODULE hmod; HKEY hkey; -#ifdef PORTABLE - /* We assume that GTK+ is installed under \\path\to\Pidgin\..\GTK - * First we find \\path\to - */ - if (GetModuleFileName(NULL, path, MAX_PATH) != 0) { - char *tmp = path; - char *prev = NULL; - char *prev2 = NULL; - while ((tmp = strchr(tmp, '\\'))) { - prev2 = prev; - prev = tmp; - tmp++; - } - - if (prev2) { - prev2[0] = '\0'; - } - } else { - printf("Unable to determine current executable path. \n" - "This will prevent the settings dir from being set.\n" - "Assuming GTK+ is in the PATH.\n"); - } - - if (path) { - /* Set up the settings dir base to be \\path\to - * The actual settings dir will be \\path\to\.purple */ - char settingsdir[strlen(path) + strlen("PURPLEHOME=") + 1]; - char aspelldir[strlen(path) + strlen("PIDGIN_ASPELL_DIR=\\Aspell\\bin") + 1]; - - snprintf(settingsdir, sizeof(settingsdir), "PURPLEHOME=%s", path); - printf("Setting settings dir: %s\n", settingsdir); - putenv(settingsdir); - - snprintf(aspelldir, sizeof(aspelldir), "PIDGIN_ASPELL_DIR=%s\\Aspell\\bin", path); - printf("%s\n", aspelldir); - putenv(aspelldir); - - /* set the GTK+ path to be \\path\to\GTK\bin */ - strcat(path, "\\GTK\\bin"); - } else - return; -#else /* PORTABLE */ - char gtkpath[MAX_PATH + 1]; - DWORD plen; - - plen = sizeof(gtkpath); - hkey = HKEY_CURRENT_USER; - if (!read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "Path", - (LPBYTE) >kpath, &plen)) { - hkey = HKEY_LOCAL_MACHINE; - if (!read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "Path", - (LPBYTE) >kpath, &plen)) { - printf("GTK+ Path Registry Key not found. " - "Assuming GTK+ is in the PATH.\n"); - return; - } - } - - /* this value is replaced during a successful RegQueryValueEx() */ - plen = sizeof(path); - /* Determine GTK+ dll path .. */ - if (!read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "DllPath", - (LPBYTE) &path, &plen)) { - strcpy(path, gtkpath); - strcat(path, "\\bin"); - } -#endif printf("GTK+ path found: %s\n", path); if ((hmod = GetModuleHandle("kernel32.dll"))) { @@ -249,6 +183,84 @@ } } +static void portable_mode_dll_prep(const char *pidgin_dir) { + /* need to be able to fit MAX_PATH + "PIDGIN_ASPELL_DIR=\\Aspell\\bin" in path2 */ + char path[MAX_PATH + 1]; + char path2[MAX_PATH + 33]; + const char *prev = NULL; + + /* We assume that GTK+ is installed under \\path\to\Pidgin\..\GTK + * First we find \\path\to + */ + if (*pidgin_dir) { + /* pidgin_dir points to \\path\to\Pidgin */ + const char *tmp = pidgin_dir; + + while ((tmp = strchr(tmp, '\\'))) { + prev = tmp; + tmp++; + } + } + + if (prev) { + int cnt = (prev - pidgin_dir); + strncpy(path, pidgin_dir, cnt); + path[cnt] = '\0'; + } else { + printf("Unable to determine current executable path. \n" + "This will prevent the settings dir from being set.\n" + "Assuming GTK+ is in the PATH.\n"); + return; + } + + + /* Set up the settings dir base to be \\path\to + * The actual settings dir will be \\path\to\.purple */ + snprintf(path2, sizeof(path2), "PURPLEHOME=%s", path); + printf("Setting settings dir: %s\n", path2); + putenv(path2); + + snprintf(path2, sizeof(path2), "PIDGIN_ASPELL_DIR=%s\\Aspell\\bin", path); + printf("%s\n", path2); + putenv(path2); + + /* set the GTK+ path to be \\path\to\GTK\bin */ + strcat(path, "\\GTK\\bin"); + + common_dll_prep(path); +} + +static void dll_prep() { + char path[MAX_PATH + 1]; + HKEY hkey; + char gtkpath[MAX_PATH + 1]; + DWORD plen; + + plen = sizeof(gtkpath); + hkey = HKEY_CURRENT_USER; + if (!read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "Path", + (LPBYTE) >kpath, &plen)) { + hkey = HKEY_LOCAL_MACHINE; + if (!read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "Path", + (LPBYTE) >kpath, &plen)) { + printf("GTK+ Path Registry Key not found. " + "Assuming GTK+ is in the PATH.\n"); + return; + } + } + + /* this value is replaced during a successful RegQueryValueEx() */ + plen = sizeof(path); + /* Determine GTK+ dll path .. */ + if (!read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "DllPath", + (LPBYTE) &path, &plen)) { + strcpy(path, gtkpath); + strcat(path, "\\bin"); + } + + common_dll_prep(path); +} + static char* winpidgin_lcid_to_posix(LCID lcid) { char *posix = NULL; int lang_id = PRIMARYLANGID(lcid); @@ -398,22 +410,18 @@ static const char *winpidgin_get_locale() { const char *locale = NULL; LCID lcid; -#ifndef PORTABLE char data[10]; DWORD datalen = 10; -#endif /* Check if user set PIDGINLANG env var */ if ((locale = getenv("PIDGINLANG"))) return locale; -#ifndef PORTABLE - if (read_reg_string(HKEY_CURRENT_USER, "SOFTWARE\\pidgin", + if (!portable_mode && read_reg_string(HKEY_CURRENT_USER, "SOFTWARE\\pidgin", "Installer Language", (LPBYTE) &data, &datalen)) { if ((locale = winpidgin_lcid_to_posix(atoi(data)))) return locale; } -#endif lcid = GetUserDefaultLCID(); if ((locale = winpidgin_lcid_to_posix(lcid))) @@ -525,7 +533,8 @@ WinMain (struct HINSTANCE__ *hInstance, struct HINSTANCE__ *hPrevInstance, char *lpszCmdLine, int nCmdShow) { char errbuf[512]; - char pidgindir[MAX_PATH]; + char pidgin_dir[MAX_PATH]; + char exe_name[MAX_PATH]; HMODULE hmod; char *tmp; @@ -555,10 +564,11 @@ } /* Load exception handler if we have it */ - if (GetModuleFileName(NULL, pidgindir, MAX_PATH) != 0) { + if (GetModuleFileName(NULL, pidgin_dir, MAX_PATH) != 0) { char *prev = NULL; - tmp = pidgindir; + tmp = pidgin_dir; + /* primitive dirname() */ while ((tmp = strchr(tmp, '\\'))) { prev = tmp; tmp++; @@ -566,9 +576,15 @@ if (prev) { prev[0] = '\0'; - strcat(pidgindir, "\\exchndl.dll"); - if (LoadLibrary(pidgindir)) + + /* prev++ will now point to the executable file name */ + strcpy(exe_name, prev + 1); + + strcat(pidgin_dir, "\\exchndl.dll"); + if (LoadLibrary(pidgin_dir)) printf("Loaded exchndl.dll\n"); + + prev[0] = '\0'; } } else { DWORD dw = GetLastError(); @@ -578,11 +594,19 @@ (UINT) dw, err_msg); printf("%s", errbuf); MessageBox(NULL, errbuf, NULL, MB_OK | MB_TOPMOST); + pidgin_dir[0] = '\0'; } -#ifndef PORTABLE - if (!getenv("PIDGIN_NO_DLL_CHECK")) -#endif + /* Determine if we're running in portable mode */ + if (strstr(lpszCmdLine, "--portable-mode") + || (exe_name != NULL && strstr(exe_name, "-portable.exe"))) { + printf("Running in PORTABLE mode.\n"); + portable_mode = TRUE; + } + + if (portable_mode) + portable_mode_dll_prep(pidgin_dir); + else if (!getenv("PIDGIN_NO_DLL_CHECK")) dll_prep(); winpidgin_set_locale(); @@ -592,9 +616,8 @@ return 0; /* Now we are ready for Pidgin .. */ - if ((hmod = LoadLibrary("pidgin.dll"))) { + if ((hmod = LoadLibrary("pidgin.dll"))) pidgin_main = (LPFNPIDGINMAIN) GetProcAddress(hmod, "pidgin_main"); - } if (!pidgin_main) { DWORD dw = GetLastError();