| 24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
| 25 * |
25 * |
| 26 */ |
26 */ |
| 27 |
27 |
| 28 /* This is for ATTACH_PARENT_PROCESS */ |
28 /* This is for ATTACH_PARENT_PROCESS */ |
| |
29 #define UNICODE |
| |
30 #define _UNICODE |
| 29 #ifndef _WIN32_WINNT |
31 #ifndef _WIN32_WINNT |
| 30 #define _WIN32_WINNT 0x501 |
32 #define _WIN32_WINNT 0x501 |
| 31 #endif |
33 #endif |
| 32 #include <windows.h> |
34 #include <windows.h> |
| |
35 #include <tchar.h> |
| 33 #include <fcntl.h> |
36 #include <fcntl.h> |
| 34 #include <stdlib.h> |
37 #include <stdlib.h> |
| 35 #include <string.h> |
38 #include <string.h> |
| 36 #include <stdio.h> |
39 #include <stdio.h> |
| 37 |
40 #include <sys/types.h> |
| 38 /* These will hopefully be in the win32api next time it is updated - at which point, we'll remove them */ |
41 #include <sys/stat.h> |
| 39 #ifndef LANG_PERSIAN |
42 #include "config.h" |
| 40 #define LANG_PERSIAN 0x29 |
|
| 41 #endif |
|
| 42 #ifndef LANG_BOSNIAN |
|
| 43 #define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05 |
|
| 44 #define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08 |
|
| 45 #endif |
|
| 46 #ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN |
|
| 47 #define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04 |
|
| 48 #endif |
|
| 49 #ifndef LANG_XHOSA |
|
| 50 #define LANG_XHOSA 0x34 |
|
| 51 #endif |
|
| 52 |
|
| 53 |
43 |
| 54 typedef int (CALLBACK* LPFNPIDGINMAIN)(HINSTANCE, int, char**); |
44 typedef int (CALLBACK* LPFNPIDGINMAIN)(HINSTANCE, int, char**); |
| 55 typedef void (CALLBACK* LPFNSETDLLDIRECTORY)(LPCTSTR); |
45 typedef void (CALLBACK* LPFNSETDLLDIRECTORY)(LPCWSTR); |
| 56 typedef BOOL (CALLBACK* LPFNATTACHCONSOLE)(DWORD); |
46 typedef BOOL (CALLBACK* LPFNATTACHCONSOLE)(DWORD); |
| 57 |
47 |
| 58 static BOOL portable_mode = FALSE; |
48 static BOOL portable_mode = FALSE; |
| 59 |
49 |
| 60 /* |
50 /* |
| 61 * PROTOTYPES |
51 * PROTOTYPES |
| 62 */ |
52 */ |
| 63 static LPFNPIDGINMAIN pidgin_main = NULL; |
53 static LPFNPIDGINMAIN pidgin_main = NULL; |
| 64 static LPFNSETDLLDIRECTORY MySetDllDirectory = NULL; |
54 static LPFNSETDLLDIRECTORY MySetDllDirectory = NULL; |
| 65 |
55 |
| 66 static const char *get_win32_error_message(DWORD err) { |
56 static const TCHAR *get_win32_error_message(DWORD err) { |
| 67 static char err_msg[512]; |
57 static TCHAR err_msg[512]; |
| 68 |
58 |
| 69 FormatMessage( |
59 FormatMessage( |
| 70 FORMAT_MESSAGE_FROM_SYSTEM, |
60 FORMAT_MESSAGE_FROM_SYSTEM, |
| 71 NULL, err, |
61 NULL, err, |
| 72 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
62 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
| 73 (LPTSTR) &err_msg, sizeof(err_msg), NULL); |
63 (LPTSTR) &err_msg, sizeof(err_msg) / sizeof(TCHAR), NULL); |
| 74 |
64 |
| 75 return err_msg; |
65 return err_msg; |
| 76 } |
66 } |
| 77 |
67 |
| 78 static BOOL read_reg_string(HKEY key, char* sub_key, char* val_name, LPBYTE data, LPDWORD data_len) { |
68 static BOOL read_reg_string(HKEY key, TCHAR *sub_key, TCHAR *val_name, LPBYTE data, LPDWORD data_len) { |
| 79 HKEY hkey; |
69 HKEY hkey; |
| 80 BOOL ret = FALSE; |
70 BOOL ret = FALSE; |
| 81 LONG retv; |
71 LONG retv; |
| 82 |
72 |
| 83 if (ERROR_SUCCESS == (retv = RegOpenKeyEx(key, sub_key, 0, |
73 if (ERROR_SUCCESS == (retv = RegOpenKeyEx(key, sub_key, 0, |
| 84 KEY_QUERY_VALUE, &hkey))) { |
74 KEY_QUERY_VALUE, &hkey))) { |
| 85 if (ERROR_SUCCESS == (retv = RegQueryValueEx(hkey, val_name, |
75 if (ERROR_SUCCESS == (retv = RegQueryValueEx(hkey, val_name, |
| 86 NULL, NULL, data, data_len))) |
76 NULL, NULL, data, data_len))) |
| 87 ret = TRUE; |
77 ret = TRUE; |
| 88 else { |
78 else { |
| 89 const char *err_msg = get_win32_error_message(retv); |
79 const TCHAR *err_msg = get_win32_error_message(retv); |
| 90 |
80 |
| 91 printf("Could not read reg key '%s' subkey '%s' value: '%s'.\nMessage: (%ld) %s\n", |
81 _tprintf(_T("Could not read reg key '%s' subkey '%s' value: '%s'.\nMessage: (%ld) %s\n"), |
| 92 (key == HKEY_LOCAL_MACHINE) ? "HKLM" |
82 (key == HKEY_LOCAL_MACHINE) ? _T("HKLM") |
| 93 : ((key == HKEY_CURRENT_USER) ? "HKCU" : "???"), |
83 : ((key == HKEY_CURRENT_USER) ? _T("HKCU") : _T("???")), |
| 94 sub_key, val_name, retv, err_msg); |
84 sub_key, val_name, retv, err_msg); |
| 95 } |
85 } |
| 96 RegCloseKey(hkey); |
86 RegCloseKey(hkey); |
| 97 } |
87 } |
| 98 else { |
88 else { |
| 99 TCHAR szBuf[80]; |
89 TCHAR szBuf[80]; |
| 100 |
90 |
| 101 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, retv, 0, |
91 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, retv, 0, |
| 102 (LPTSTR) &szBuf, sizeof(szBuf), NULL); |
92 (LPTSTR) &szBuf, sizeof(szBuf) / sizeof(TCHAR), NULL); |
| 103 printf("Could not open reg subkey: %s\nError: (%ld) %s\n", |
93 _tprintf(_T("Could not open reg subkey: %s\nError: (%ld) %s\n"), |
| 104 sub_key, retv, szBuf); |
94 sub_key, retv, szBuf); |
| 105 } |
95 } |
| 106 |
96 |
| 107 return ret; |
97 return ret; |
| 108 } |
98 } |
| 109 |
99 |
| 110 static void common_dll_prep(const char *path) { |
100 static void common_dll_prep(const TCHAR *path) { |
| 111 HMODULE hmod; |
101 HMODULE hmod; |
| 112 HKEY hkey; |
102 HKEY hkey; |
| 113 |
103 struct _stat stat_buf; |
| 114 printf("GTK+ path found: %s\n", path); |
104 TCHAR test_path[MAX_PATH + 1]; |
| 115 |
105 |
| 116 if ((hmod = GetModuleHandle("kernel32.dll"))) { |
106 _sntprintf(test_path, sizeof(test_path) / sizeof(TCHAR), |
| |
107 _T("%s\\libgtk-win32-2.0-0.dll"), path); |
| |
108 test_path[sizeof(test_path) / sizeof(TCHAR) - 1] = _T('\0'); |
| |
109 |
| |
110 if (_tstat(test_path, &stat_buf) != 0) { |
| |
111 printf("Unable to determine GTK+ path. \n" |
| |
112 "Assuming GTK+ is in the PATH.\n"); |
| |
113 return; |
| |
114 } |
| |
115 |
| |
116 |
| |
117 _tprintf(_T("GTK+ path found: %s\n"), path); |
| |
118 |
| |
119 if ((hmod = GetModuleHandle(_T("kernel32.dll")))) { |
| 117 MySetDllDirectory = (LPFNSETDLLDIRECTORY) GetProcAddress( |
120 MySetDllDirectory = (LPFNSETDLLDIRECTORY) GetProcAddress( |
| 118 hmod, "SetDllDirectoryA"); |
121 hmod, "SetDllDirectoryW"); |
| 119 if (!MySetDllDirectory) |
122 if (!MySetDllDirectory) |
| 120 printf("SetDllDirectory not supported\n"); |
123 printf("SetDllDirectory not supported\n"); |
| 121 } else |
124 } else |
| 122 printf("Error getting kernel32.dll module handle\n"); |
125 printf("Error getting kernel32.dll module handle\n"); |
| 123 |
126 |
| 139 * searched for dlls before the current directory. Therefore we set it |
142 * searched for dlls before the current directory. Therefore we set it |
| 140 * to 0. |
143 * to 0. |
| 141 */ |
144 */ |
| 142 osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); |
145 osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); |
| 143 GetVersionEx(&osinfo); |
146 GetVersionEx(&osinfo); |
| 144 if ((osinfo.dwMajorVersion == 5 && |
147 if ((osinfo.dwMajorVersion == 5 |
| 145 osinfo.dwMinorVersion == 0 && |
148 && osinfo.dwMinorVersion == 0 |
| 146 strcmp(osinfo.szCSDVersion, "Service Pack 3") >= 0) || |
149 && _tcscmp(osinfo.szCSDVersion, _T("Service Pack 3")) >= 0) |
| 147 (osinfo.dwMajorVersion == 5 && |
150 || |
| 148 osinfo.dwMinorVersion == 1 && |
151 (osinfo.dwMajorVersion == 5 |
| 149 strcmp(osinfo.szCSDVersion, "") >= 0) |
152 && osinfo.dwMinorVersion == 1 |
| |
153 && _tcscmp(osinfo.szCSDVersion, _T("")) >= 0) |
| 150 ) { |
154 ) { |
| 151 DWORD regval = 1; |
155 DWORD regval = 1; |
| 152 DWORD reglen = sizeof(DWORD); |
156 DWORD reglen = sizeof(DWORD); |
| 153 |
157 |
| 154 printf("Using Win2k (SP3+) / WinXP (No SP)... Checking SafeDllSearch\n"); |
158 printf("Using Win2k (SP3+) / WinXP (No SP)... Checking SafeDllSearch\n"); |
| 155 read_reg_string(HKEY_LOCAL_MACHINE, |
159 read_reg_string(HKEY_LOCAL_MACHINE, |
| 156 "System\\CurrentControlSet\\Control\\Session Manager", |
160 _T("System\\CurrentControlSet\\Control\\Session Manager"), |
| 157 "SafeDllSearchMode", |
161 _T("SafeDllSearchMode"), |
| 158 (LPBYTE) ®val, |
162 (LPBYTE) ®val, |
| 159 ®len); |
163 ®len); |
| 160 |
164 |
| 161 if (regval != 0) { |
165 if (regval != 0) { |
| 162 printf("Trying to set SafeDllSearchMode to 0\n"); |
166 printf("Trying to set SafeDllSearchMode to 0\n"); |
| 163 regval = 0; |
167 regval = 0; |
| 164 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, |
168 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, |
| 165 "System\\CurrentControlSet\\Control\\Session Manager", |
169 _T("System\\CurrentControlSet\\Control\\Session Manager"), |
| 166 0, KEY_SET_VALUE, &hkey |
170 0, KEY_SET_VALUE, &hkey |
| 167 ) == ERROR_SUCCESS) { |
171 ) == ERROR_SUCCESS) { |
| 168 if (RegSetValueEx(hkey, |
172 if (RegSetValueEx(hkey, |
| 169 "SafeDllSearchMode", 0, |
173 _T("SafeDllSearchMode"), 0, |
| 170 REG_DWORD, (LPBYTE) ®val, |
174 REG_DWORD, (LPBYTE) ®val, |
| 171 sizeof(DWORD) |
175 sizeof(DWORD) |
| 172 ) != ERROR_SUCCESS) |
176 ) != ERROR_SUCCESS) |
| 173 printf("Error writing SafeDllSearchMode. Error: %u\n", |
177 printf("Error writing SafeDllSearchMode. Error: %u\n", |
| 174 (UINT) GetLastError()); |
178 (UINT) GetLastError()); |
| 175 RegCloseKey(hkey); |
179 RegCloseKey(hkey); |
| 176 } else |
180 } else |
| 177 printf("Error opening Session Manager key for writing. Error: %u\n", |
181 printf("Error opening Session Manager key for writing. Error: %u\n", |
| 178 (UINT) GetLastError()); |
182 (UINT) GetLastError()); |
| 179 } else |
183 } else |
| 180 printf("SafeDllSearchMode is set to 0\n"); |
184 printf("SafeDllSearchMode is set to 0\n"); |
| 181 }/*end else*/ |
185 }/*end else*/ |
| 182 } |
186 } |
| 183 } |
187 } |
| 184 |
188 |
| 185 static void portable_mode_dll_prep(const char *pidgin_dir) { |
189 static void portable_mode_dll_prep(const TCHAR *pidgin_dir) { |
| 186 /* need to be able to fit MAX_PATH + "PIDGIN_ASPELL_DIR=\\Aspell\\bin" in path2 */ |
190 /* need to be able to fit MAX_PATH + "PIDGIN_ASPELL_DIR=\\Aspell\\bin" in path2 */ |
| 187 char path[MAX_PATH + 1]; |
191 TCHAR path[MAX_PATH + 1]; |
| 188 char path2[MAX_PATH + 33]; |
192 TCHAR path2[MAX_PATH + 33]; |
| 189 const char *prev = NULL; |
193 const TCHAR *prev = NULL; |
| 190 |
194 |
| 191 /* We assume that GTK+ is installed under \\path\to\Pidgin\..\GTK |
195 /* We assume that GTK+ is installed under \\path\to\Pidgin\..\GTK |
| 192 * First we find \\path\to |
196 * First we find \\path\to |
| 193 */ |
197 */ |
| 194 if (*pidgin_dir) { |
198 if (*pidgin_dir) |
| 195 /* pidgin_dir points to \\path\to\Pidgin */ |
199 /* pidgin_dir points to \\path\to\Pidgin */ |
| 196 const char *tmp = pidgin_dir; |
200 prev = _tcsrchr(pidgin_dir, _T('\\')); |
| 197 |
|
| 198 while ((tmp = strchr(tmp, '\\'))) { |
|
| 199 prev = tmp; |
|
| 200 tmp++; |
|
| 201 } |
|
| 202 } |
|
| 203 |
201 |
| 204 if (prev) { |
202 if (prev) { |
| 205 int cnt = (prev - pidgin_dir); |
203 int cnt = (prev - pidgin_dir); |
| 206 strncpy(path, pidgin_dir, cnt); |
204 _tcsncpy(path, pidgin_dir, cnt); |
| 207 path[cnt] = '\0'; |
205 path[cnt] = _T('\0'); |
| 208 } else { |
206 } else { |
| 209 printf("Unable to determine current executable path. \n" |
207 printf("Unable to determine current executable path. \n" |
| 210 "This will prevent the settings dir from being set.\n" |
208 "This will prevent the settings dir from being set.\n" |
| 211 "Assuming GTK+ is in the PATH.\n"); |
209 "Assuming GTK+ is in the PATH.\n"); |
| 212 return; |
210 return; |
| 213 } |
211 } |
| 214 |
212 |
| 215 /* Set $HOME so that the GTK+ settings get stored in the right place */ |
213 /* Set $HOME so that the GTK+ settings get stored in the right place */ |
| 216 _snprintf(path2, sizeof(path2), "HOME=%s", path); |
214 _sntprintf(path2, sizeof(path2) / sizeof(TCHAR), _T("HOME=%s"), path); |
| 217 _putenv(path2); |
215 _tputenv(path2); |
| 218 |
216 |
| 219 /* Set up the settings dir base to be \\path\to |
217 /* Set up the settings dir base to be \\path\to |
| 220 * The actual settings dir will be \\path\to\.purple */ |
218 * The actual settings dir will be \\path\to\.purple */ |
| 221 _snprintf(path2, sizeof(path2), "PURPLEHOME=%s", path); |
219 _sntprintf(path2, sizeof(path2) / sizeof(TCHAR), _T("PURPLEHOME=%s"), path); |
| 222 printf("Setting settings dir: %s\n", path2); |
220 _tprintf(_T("Setting settings dir: %s\n"), path2); |
| 223 _putenv(path2); |
221 _tputenv(path2); |
| 224 |
222 |
| 225 _snprintf(path2, sizeof(path2), "PIDGIN_ASPELL_DIR=%s\\Aspell\\bin", path); |
223 _sntprintf(path2, sizeof(path2) / sizeof(TCHAR), _T("PIDGIN_ASPELL_DIR=%s\\Aspell\\bin"), path); |
| 226 printf("%s\n", path2); |
224 _tprintf(_T("%s\n"), path2); |
| 227 _putenv(path2); |
225 _tputenv(path2); |
| 228 |
226 |
| 229 /* set the GTK+ path to be \\path\to\GTK\bin */ |
227 /* set the GTK+ path to be \\path\to\GTK\bin */ |
| 230 strcat(path, "\\GTK\\bin"); |
228 _tcscat(path, _T("\\GTK\\bin")); |
| 231 |
229 |
| 232 common_dll_prep(path); |
230 common_dll_prep(path); |
| 233 } |
231 } |
| 234 |
232 |
| 235 static void dll_prep() { |
233 static void dll_prep(const TCHAR *pidgin_dir) { |
| 236 char path[MAX_PATH + 1]; |
234 TCHAR gtk_path[MAX_PATH + 1]; |
| 237 HKEY hkey; |
235 gtk_path[0] = _T('\0'); |
| 238 char gtkpath[MAX_PATH + 1]; |
236 |
| 239 DWORD plen; |
237 if (*pidgin_dir) { |
| 240 |
238 _sntprintf(gtk_path, sizeof(gtk_path) / sizeof(TCHAR), _T("%s\\Gtk\\bin"), pidgin_dir); |
| 241 plen = sizeof(gtkpath); |
239 gtk_path[sizeof(gtk_path) / sizeof(TCHAR)] = _T('\0'); |
| 242 hkey = HKEY_CURRENT_USER; |
240 } |
| 243 if (!read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "Path", |
241 |
| 244 (LPBYTE) >kpath, &plen)) { |
242 common_dll_prep(gtk_path); |
| 245 hkey = HKEY_LOCAL_MACHINE; |
243 } |
| 246 if (!read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "Path", |
244 |
| 247 (LPBYTE) >kpath, &plen)) { |
245 static TCHAR* winpidgin_lcid_to_posix(LCID lcid) { |
| 248 printf("GTK+ Path Registry Key not found. " |
246 TCHAR *posix = NULL; |
| 249 "Assuming GTK+ is in the PATH.\n"); |
|
| 250 return; |
|
| 251 } |
|
| 252 } |
|
| 253 |
|
| 254 /* this value is replaced during a successful RegQueryValueEx() */ |
|
| 255 plen = sizeof(path); |
|
| 256 /* Determine GTK+ dll path .. */ |
|
| 257 if (!read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "DllPath", |
|
| 258 (LPBYTE) &path, &plen)) { |
|
| 259 strcpy(path, gtkpath); |
|
| 260 strcat(path, "\\bin"); |
|
| 261 } |
|
| 262 |
|
| 263 common_dll_prep(path); |
|
| 264 } |
|
| 265 |
|
| 266 static char* winpidgin_lcid_to_posix(LCID lcid) { |
|
| 267 char *posix = NULL; |
|
| 268 int lang_id = PRIMARYLANGID(lcid); |
247 int lang_id = PRIMARYLANGID(lcid); |
| 269 int sub_id = SUBLANGID(lcid); |
248 int sub_id = SUBLANGID(lcid); |
| 270 |
249 |
| 271 switch (lang_id) { |
250 switch (lang_id) { |
| 272 case LANG_AFRIKAANS: posix = "af"; break; |
251 case LANG_AFRIKAANS: posix = _T("af"); break; |
| 273 case LANG_ARABIC: posix = "ar"; break; |
252 case LANG_ARABIC: posix = _T("ar"); break; |
| 274 case LANG_AZERI: posix = "az"; break; |
253 case LANG_AZERI: posix = _T("az"); break; |
| 275 case LANG_BENGALI: posix = "bn"; break; |
254 case LANG_BENGALI: posix = _T("bn"); break; |
| 276 case LANG_BULGARIAN: posix = "bg"; break; |
255 case LANG_BULGARIAN: posix = _T("bg"); break; |
| 277 case LANG_CATALAN: posix = "ca"; break; |
256 case LANG_CATALAN: posix = _T("ca"); break; |
| 278 case LANG_CZECH: posix = "cs"; break; |
257 case LANG_CZECH: posix = _T("cs"); break; |
| 279 case LANG_DANISH: posix = "da"; break; |
258 case LANG_DANISH: posix = _T("da"); break; |
| 280 case LANG_ESTONIAN: posix = "et"; break; |
259 case LANG_ESTONIAN: posix = _T("et"); break; |
| 281 case LANG_PERSIAN: posix = "fa"; break; |
260 case LANG_PERSIAN: posix = _T("fa"); break; |
| 282 case LANG_GERMAN: posix = "de"; break; |
261 case LANG_GERMAN: posix = _T("de"); break; |
| 283 case LANG_GREEK: posix = "el"; break; |
262 case LANG_GREEK: posix = _T("el"); break; |
| 284 case LANG_ENGLISH: |
263 case LANG_ENGLISH: |
| 285 switch (sub_id) { |
264 switch (sub_id) { |
| 286 case SUBLANG_ENGLISH_UK: |
265 case SUBLANG_ENGLISH_UK: |
| 287 posix = "en_GB"; break; |
266 posix = _T("en_GB"); break; |
| 288 case SUBLANG_ENGLISH_AUS: |
267 case SUBLANG_ENGLISH_AUS: |
| 289 posix = "en_AU"; break; |
268 posix = _T("en_AU"); break; |
| 290 case SUBLANG_ENGLISH_CAN: |
269 case SUBLANG_ENGLISH_CAN: |
| 291 posix = "en_CA"; break; |
270 posix = _T("en_CA"); break; |
| 292 default: |
271 default: |
| 293 posix = "en"; break; |
272 posix = _T("en"); break; |
| 294 } |
273 } |
| 295 break; |
274 break; |
| 296 case LANG_SPANISH: posix = "es"; break; |
275 case LANG_SPANISH: posix = _T("es"); break; |
| 297 case LANG_BASQUE: posix = "eu"; break; |
276 case LANG_BASQUE: posix = _T("eu"); break; |
| 298 case LANG_FINNISH: posix = "fi"; break; |
277 case LANG_FINNISH: posix = _T("fi"); break; |
| 299 case LANG_FRENCH: posix = "fr"; break; |
278 case LANG_FRENCH: posix = _T("fr"); break; |
| 300 case LANG_GALICIAN: posix = "gl"; break; |
279 case LANG_GALICIAN: posix = _T("gl"); break; |
| 301 case LANG_GUJARATI: posix = "gu"; break; |
280 case LANG_GUJARATI: posix = _T("gu"); break; |
| 302 case LANG_HEBREW: posix = "he"; break; |
281 case LANG_HEBREW: posix = _T("he"); break; |
| 303 case LANG_HINDI: posix = "hi"; break; |
282 case LANG_HINDI: posix = _T("hi"); break; |
| 304 case LANG_HUNGARIAN: posix = "hu"; break; |
283 case LANG_HUNGARIAN: posix = _T("hu"); break; |
| 305 case LANG_ICELANDIC: break; |
284 case LANG_ICELANDIC: break; |
| 306 case LANG_INDONESIAN: posix = "id"; break; |
285 case LANG_INDONESIAN: posix = _T("id"); break; |
| 307 case LANG_ITALIAN: posix = "it"; break; |
286 case LANG_ITALIAN: posix = _T("it"); break; |
| 308 case LANG_JAPANESE: posix = "ja"; break; |
287 case LANG_JAPANESE: posix = _T("ja"); break; |
| 309 case LANG_GEORGIAN: posix = "ka"; break; |
288 case LANG_GEORGIAN: posix = _T("ka"); break; |
| 310 case LANG_KANNADA: posix = "kn"; break; |
289 case LANG_KANNADA: posix = _T("kn"); break; |
| 311 case LANG_KOREAN: posix = "ko"; break; |
290 case LANG_KOREAN: posix = _T("ko"); break; |
| 312 case LANG_LITHUANIAN: posix = "lt"; break; |
291 case LANG_LITHUANIAN: posix = _T("lt"); break; |
| 313 case LANG_MACEDONIAN: posix = "mk"; break; |
292 case LANG_MACEDONIAN: posix = _T("mk"); break; |
| 314 case LANG_DUTCH: posix = "nl"; break; |
293 case LANG_DUTCH: posix = _T("nl"); break; |
| 315 case LANG_NEPALI: posix = "ne"; break; |
294 case LANG_NEPALI: posix = _T("ne"); break; |
| 316 case LANG_NORWEGIAN: |
295 case LANG_NORWEGIAN: |
| 317 switch (sub_id) { |
296 switch (sub_id) { |
| 318 case SUBLANG_NORWEGIAN_BOKMAL: |
297 case SUBLANG_NORWEGIAN_BOKMAL: |
| 319 posix = "nb"; break; |
298 posix = _T("nb"); break; |
| 320 case SUBLANG_NORWEGIAN_NYNORSK: |
299 case SUBLANG_NORWEGIAN_NYNORSK: |
| 321 posix = "nn"; break; |
300 posix = _T("nn"); break; |
| 322 } |
301 } |
| 323 break; |
302 break; |
| 324 case LANG_PUNJABI: posix = "pa"; break; |
303 case LANG_PUNJABI: posix = _T("pa"); break; |
| 325 case LANG_POLISH: posix = "pl"; break; |
304 case LANG_POLISH: posix = _T("pl"); break; |
| 326 case LANG_PASHTO: posix = "ps"; break; |
305 case LANG_PASHTO: posix = _T("ps"); break; |
| 327 case LANG_PORTUGUESE: |
306 case LANG_PORTUGUESE: |
| 328 switch (sub_id) { |
307 switch (sub_id) { |
| 329 case SUBLANG_PORTUGUESE_BRAZILIAN: |
308 case SUBLANG_PORTUGUESE_BRAZILIAN: |
| 330 posix = "pt_BR"; break; |
309 posix = _T("pt_BR"); break; |
| 331 default: |
310 default: |
| 332 posix = "pt"; break; |
311 posix = _T("pt"); break; |
| 333 } |
312 } |
| 334 break; |
313 break; |
| 335 case LANG_ROMANIAN: posix = "ro"; break; |
314 case LANG_ROMANIAN: posix = _T("ro"); break; |
| 336 case LANG_RUSSIAN: posix = "ru"; break; |
315 case LANG_RUSSIAN: posix = _T("ru"); break; |
| 337 case LANG_SLOVAK: posix = "sk"; break; |
316 case LANG_SLOVAK: posix = _T("sk"); break; |
| 338 case LANG_SLOVENIAN: posix = "sl"; break; |
317 case LANG_SLOVENIAN: posix = _T("sl"); break; |
| 339 case LANG_ALBANIAN: posix = "sq"; break; |
318 case LANG_ALBANIAN: posix = _T("sq"); break; |
| 340 /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN */ |
319 /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN */ |
| 341 case LANG_SERBIAN: |
320 case LANG_SERBIAN: |
| 342 switch (sub_id) { |
321 switch (sub_id) { |
| 343 case SUBLANG_SERBIAN_LATIN: |
322 case SUBLANG_SERBIAN_LATIN: |
| 344 posix = "sr@Latn"; break; |
323 posix = _T("sr@Latn"); break; |
| 345 case SUBLANG_SERBIAN_CYRILLIC: |
324 case SUBLANG_SERBIAN_CYRILLIC: |
| 346 posix = "sr"; break; |
325 posix = _T("sr"); break; |
| 347 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: |
326 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: |
| 348 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: |
327 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: |
| 349 posix = "bs"; break; |
328 posix = _T("bs"); break; |
| 350 case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: |
329 case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: |
| 351 posix = "hr"; break; |
330 posix = _T("hr"); break; |
| 352 } |
331 } |
| 353 break; |
332 break; |
| 354 case LANG_SWEDISH: posix = "sv"; break; |
333 case LANG_SWEDISH: posix = _T("sv"); break; |
| 355 case LANG_TAMIL: posix = "ta"; break; |
334 case LANG_TAMIL: posix = _T("ta"); break; |
| 356 case LANG_TELUGU: posix = "te"; break; |
335 case LANG_TELUGU: posix = _T("te"); break; |
| 357 case LANG_THAI: posix = "th"; break; |
336 case LANG_THAI: posix = _T("th"); break; |
| 358 case LANG_TURKISH: posix = "tr"; break; |
337 case LANG_TURKISH: posix = _T("tr"); break; |
| 359 case LANG_UKRAINIAN: posix = "uk"; break; |
338 case LANG_UKRAINIAN: posix = _T("uk"); break; |
| 360 case LANG_VIETNAMESE: posix = "vi"; break; |
339 case LANG_VIETNAMESE: posix = _T("vi"); break; |
| 361 case LANG_XHOSA: posix = "xh"; break; |
340 case LANG_XHOSA: posix = _T("xh"); break; |
| 362 case LANG_CHINESE: |
341 case LANG_CHINESE: |
| 363 switch (sub_id) { |
342 switch (sub_id) { |
| 364 case SUBLANG_CHINESE_SIMPLIFIED: |
343 case SUBLANG_CHINESE_SIMPLIFIED: |
| 365 posix = "zh_CN"; break; |
344 posix = _T("zh_CN"); break; |
| 366 case SUBLANG_CHINESE_TRADITIONAL: |
345 case SUBLANG_CHINESE_TRADITIONAL: |
| 367 posix = "zh_TW"; break; |
346 posix = _T("zh_TW"); break; |
| 368 default: |
347 default: |
| 369 posix = "zh"; break; |
348 posix = _T("zh"); break; |
| 370 } |
349 } |
| 371 break; |
350 break; |
| 372 case LANG_URDU: break; |
351 case LANG_URDU: break; |
| 373 case LANG_BELARUSIAN: break; |
352 case LANG_BELARUSIAN: break; |
| 374 case LANG_LATVIAN: break; |
353 case LANG_LATVIAN: break; |
| 408 /* Determine and set Pidgin locale as follows (in order of priority): |
387 /* Determine and set Pidgin locale as follows (in order of priority): |
| 409 - Check PIDGINLANG env var |
388 - Check PIDGINLANG env var |
| 410 - Check NSIS Installer Language reg value |
389 - Check NSIS Installer Language reg value |
| 411 - Use default user locale |
390 - Use default user locale |
| 412 */ |
391 */ |
| 413 static const char *winpidgin_get_locale() { |
392 static const TCHAR *winpidgin_get_locale() { |
| 414 const char *locale = NULL; |
393 const TCHAR *locale = NULL; |
| 415 LCID lcid; |
394 LCID lcid; |
| 416 char data[10]; |
395 TCHAR data[10]; |
| 417 DWORD datalen = 10; |
396 DWORD datalen = sizeof(data) / sizeof(TCHAR); |
| 418 |
397 |
| 419 /* Check if user set PIDGINLANG env var */ |
398 /* Check if user set PIDGINLANG env var */ |
| 420 if ((locale = getenv("PIDGINLANG"))) |
399 if ((locale = _tgetenv(_T("PIDGINLANG")))) |
| 421 return locale; |
400 return locale; |
| 422 |
401 |
| 423 if (!portable_mode && read_reg_string(HKEY_CURRENT_USER, "SOFTWARE\\pidgin", |
402 if (!portable_mode && read_reg_string(HKEY_CURRENT_USER, _T("SOFTWARE\\pidgin"), |
| 424 "Installer Language", (LPBYTE) &data, &datalen)) { |
403 _T("Installer Language"), (LPBYTE) &data, &datalen)) { |
| 425 if ((locale = winpidgin_lcid_to_posix(atoi(data)))) |
404 if ((locale = winpidgin_lcid_to_posix(_ttoi(data)))) |
| 426 return locale; |
405 return locale; |
| 427 } |
406 } |
| 428 |
407 |
| 429 lcid = GetUserDefaultLCID(); |
408 lcid = GetUserDefaultLCID(); |
| 430 if ((locale = winpidgin_lcid_to_posix(lcid))) |
409 if ((locale = winpidgin_lcid_to_posix(lcid))) |
| 431 return locale; |
410 return locale; |
| 432 |
411 |
| 433 return "en"; |
412 return _T("en"); |
| 434 } |
413 } |
| 435 |
414 |
| 436 static void winpidgin_set_locale() { |
415 static void winpidgin_set_locale() { |
| 437 const char *locale = NULL; |
416 const TCHAR *locale; |
| 438 char envstr[25]; |
417 TCHAR envstr[25]; |
| 439 |
418 |
| 440 locale = winpidgin_get_locale(); |
419 locale = winpidgin_get_locale(); |
| 441 |
420 |
| 442 _snprintf(envstr, 25, "LANG=%s", locale); |
421 _sntprintf(envstr, sizeof(envstr) / sizeof(TCHAR), _T("LANG=%s"), locale); |
| 443 printf("Setting locale: %s\n", envstr); |
422 _tprintf(_T("Setting locale: %s\n"), envstr); |
| 444 _putenv(envstr); |
423 _tputenv(envstr); |
| 445 } |
424 } |
| 446 |
425 |
| 447 |
426 |
| 448 static void winpidgin_add_stuff_to_path() { |
427 static void winpidgin_add_stuff_to_path() { |
| 449 char perl_path[MAX_PATH + 1]; |
428 TCHAR perl_path[MAX_PATH + 1]; |
| 450 char *ppath = NULL; |
429 TCHAR *ppath = NULL; |
| 451 char mit_kerberos_path[MAX_PATH + 1]; |
430 TCHAR mit_kerberos_path[MAX_PATH + 1]; |
| 452 char *mpath = NULL; |
431 TCHAR *mpath = NULL; |
| 453 DWORD plen; |
432 DWORD plen; |
| 454 |
433 |
| 455 printf("%s", "Looking for Perl... "); |
434 printf("%s", "Looking for Perl... "); |
| 456 |
435 |
| 457 plen = sizeof(perl_path); |
436 plen = sizeof(perl_path) / sizeof(TCHAR); |
| 458 if (read_reg_string(HKEY_LOCAL_MACHINE, "SOFTWARE\\Perl", "", |
437 if (read_reg_string(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Perl"), _T(""), |
| 459 (LPBYTE) &perl_path, &plen)) { |
438 (LPBYTE) &perl_path, &plen)) { |
| 460 /* We *could* check for perl510.dll, but it seems unnecessary. */ |
439 /* We *could* check for perl510.dll, but it seems unnecessary. */ |
| 461 printf("found in '%s'.\n", perl_path); |
440 _tprintf(_T("found in '%s'.\n"), perl_path); |
| 462 |
441 |
| 463 if (perl_path[strlen(perl_path) - 1] != '\\') |
442 if (perl_path[_tcslen(perl_path) - 1] != _T('\\')) |
| 464 strcat(perl_path, "\\"); |
443 _tcscat(perl_path, _T("\\")); |
| 465 strcat(perl_path, "bin"); |
444 _tcscat(perl_path, _T("bin")); |
| 466 |
445 |
| 467 ppath = perl_path; |
446 ppath = perl_path; |
| 468 } else |
447 } else |
| 469 printf("%s", "not found.\n"); |
448 printf("%s", "not found.\n"); |
| 470 |
449 |
| 471 printf("%s", "Looking for MIT Kerberos... "); |
450 printf("%s", "Looking for MIT Kerberos... "); |
| 472 |
451 |
| 473 plen = sizeof(mit_kerberos_path); |
452 plen = sizeof(mit_kerberos_path) / sizeof(TCHAR); |
| 474 if (read_reg_string(HKEY_LOCAL_MACHINE, "SOFTWARE\\MIT\\Kerberos", "InstallDir", |
453 if (read_reg_string(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\MIT\\Kerberos"), _T("InstallDir"), |
| 475 (LPBYTE) &mit_kerberos_path, &plen)) { |
454 (LPBYTE) &mit_kerberos_path, &plen)) { |
| 476 /* We *could* check for gssapi32.dll */ |
455 /* We *could* check for gssapi32.dll */ |
| 477 printf("found in '%s'.\n", mit_kerberos_path); |
456 _tprintf(_T("found in '%s'.\n"), mit_kerberos_path); |
| 478 |
457 |
| 479 if (mit_kerberos_path[strlen(mit_kerberos_path) - 1] != '\\') |
458 if (mit_kerberos_path[_tcslen(mit_kerberos_path) - 1] != _T('\\')) |
| 480 strcat(mit_kerberos_path, "\\"); |
459 _tcscat(mit_kerberos_path, _T("\\")); |
| 481 strcat(mit_kerberos_path, "bin"); |
460 _tcscat(mit_kerberos_path, _T("bin")); |
| 482 |
461 |
| 483 mpath = mit_kerberos_path; |
462 mpath = mit_kerberos_path; |
| 484 } else |
463 } else |
| 485 printf("%s", "not found.\n"); |
464 printf("%s", "not found.\n"); |
| 486 |
465 |
| 487 if (ppath != NULL || mpath != NULL) { |
466 if (ppath != NULL || mpath != NULL) { |
| 488 const char *path = getenv("PATH"); |
467 const TCHAR *path = _tgetenv(_T("PATH")); |
| 489 BOOL add_ppath = ppath != NULL && (path == NULL || !strstr(path, ppath)); |
468 BOOL add_ppath = ppath != NULL && (path == NULL || !_tcsstr(path, ppath)); |
| 490 BOOL add_mpath = mpath != NULL && (path == NULL || !strstr(path, mpath)); |
469 BOOL add_mpath = mpath != NULL && (path == NULL || !_tcsstr(path, mpath)); |
| 491 char *newpath; |
470 TCHAR *newpath; |
| 492 int newlen; |
471 int newlen; |
| 493 |
472 |
| 494 if (add_ppath || add_mpath) { |
473 if (add_ppath || add_mpath) { |
| 495 /* Enough to add "PATH=" + path + ";" + ppath + ";" + mpath + \0 */ |
474 /* Enough to add "PATH=" + path + ";" + ppath + ";" + mpath + \0 */ |
| 496 newlen = 6 + (path ? strlen(path) + 1 : 0); |
475 newlen = 6 + (path ? _tcslen(path) + 1 : 0); |
| 497 if (add_ppath) |
476 if (add_ppath) |
| 498 newlen += strlen(ppath) + 1; |
477 newlen += _tcslen(ppath) + 1; |
| 499 if (add_mpath) |
478 if (add_mpath) |
| 500 newlen += strlen(mpath) + 1; |
479 newlen += _tcslen(mpath) + 1; |
| 501 newpath = malloc(newlen); |
480 newpath = malloc(newlen * sizeof(TCHAR)); |
| 502 *newpath = '\0'; |
481 |
| 503 |
482 _sntprintf(newpath, newlen, _T("PATH=%s%s%s%s%s%s"), |
| 504 _snprintf(newpath, newlen, "PATH=%s%s%s%s%s%s", |
483 path ? path : _T(""), |
| 505 path ? path : "", |
484 path ? _T(";") : _T(""), |
| 506 path ? ";" : "", |
485 add_ppath ? ppath : _T(""), |
| 507 add_ppath ? ppath : "", |
486 add_ppath ? _T(";") : _T(""), |
| 508 add_ppath ? ";" : "", |
487 add_mpath ? mpath : _T(""), |
| 509 add_mpath ? mpath : "", |
488 add_mpath ? _T(";") : _T("")); |
| 510 add_mpath ? ";" : ""); |
489 |
| 511 |
490 _tprintf(_T("New PATH: %s\n"), newpath); |
| 512 printf("New PATH: %s\n", newpath); |
491 |
| 513 |
492 _tputenv(newpath); |
| 514 _putenv(newpath); |
|
| 515 free(newpath); |
493 free(newpath); |
| 516 } |
494 } |
| 517 } |
495 } |
| 518 } |
496 } |
| 519 |
497 |
| 521 #define PIDGIN_WM_PROTOCOL_HANDLE (WM_APP + 14) |
499 #define PIDGIN_WM_PROTOCOL_HANDLE (WM_APP + 14) |
| 522 |
500 |
| 523 static BOOL winpidgin_set_running(BOOL fail_if_running) { |
501 static BOOL winpidgin_set_running(BOOL fail_if_running) { |
| 524 HANDLE h; |
502 HANDLE h; |
| 525 |
503 |
| 526 if ((h = CreateMutex(NULL, FALSE, "pidgin_is_running"))) { |
504 if ((h = CreateMutex(NULL, FALSE, _T("pidgin_is_running")))) { |
| 527 DWORD err = GetLastError(); |
505 DWORD err = GetLastError(); |
| 528 if (err == ERROR_ALREADY_EXISTS) { |
506 if (err == ERROR_ALREADY_EXISTS) { |
| 529 if (fail_if_running) { |
507 if (fail_if_running) { |
| 530 HWND msg_win; |
508 HWND msg_win; |
| 531 |
509 |
| 532 printf("An instance of Pidgin is already running.\n"); |
510 printf("An instance of Pidgin is already running.\n"); |
| 533 |
511 |
| 534 if((msg_win = FindWindowEx(NULL, NULL, TEXT("WinpidginMsgWinCls"), NULL))) |
512 if((msg_win = FindWindowEx(NULL, NULL, _T("WinpidginMsgWinCls"), NULL))) |
| 535 if(SendMessage(msg_win, PIDGIN_WM_FOCUS_REQUEST, (WPARAM) NULL, (LPARAM) NULL)) |
513 if(SendMessage(msg_win, PIDGIN_WM_FOCUS_REQUEST, (WPARAM) NULL, (LPARAM) NULL)) |
| 536 return FALSE; |
514 return FALSE; |
| 537 |
515 |
| 538 /* If we get here, the focus request wasn't successful */ |
516 /* If we get here, the focus request wasn't successful */ |
| 539 |
517 |
| 540 MessageBox(NULL, |
518 MessageBox(NULL, |
| 541 "An instance of Pidgin is already running", |
519 _T("An instance of Pidgin is already running"), |
| 542 NULL, MB_OK | MB_TOPMOST); |
520 NULL, MB_OK | MB_TOPMOST); |
| 543 |
521 |
| 544 return FALSE; |
522 return FALSE; |
| 545 } |
523 } |
| 546 } else if (err != ERROR_SUCCESS) |
524 } else if (err != ERROR_SUCCESS) |
| 547 printf("Error (%u) accessing \"pidgin_is_running\" mutex.\n", (UINT) err); |
525 printf("Error (%u) accessing \"pidgin_is_running\" mutex.\n", (UINT) err); |
| 548 } |
526 } |
| 549 return TRUE; |
527 return TRUE; |
| 550 } |
528 } |
| 551 |
529 |
| 552 #define PROTO_HANDLER_SWITCH "--protocolhandler=" |
530 #define PROTO_HANDLER_SWITCH L"--protocolhandler=" |
| 553 |
531 |
| 554 static void handle_protocol(char *cmd) { |
532 static void handle_protocol(wchar_t *cmd) { |
| 555 char *remote_msg, *tmp1, *tmp2; |
533 char *remote_msg, *utf8msg; |
| 556 int len; |
534 wchar_t *tmp1, *tmp2; |
| |
535 int len, wlen; |
| 557 SIZE_T len_written; |
536 SIZE_T len_written; |
| 558 HWND msg_win; |
537 HWND msg_win; |
| 559 DWORD pid; |
538 DWORD pid; |
| 560 HANDLE process; |
539 HANDLE process; |
| 561 |
540 |
| 562 /* The start of the message */ |
541 /* The start of the message */ |
| 563 tmp1 = cmd + strlen(PROTO_HANDLER_SWITCH); |
542 tmp1 = cmd + wcslen(PROTO_HANDLER_SWITCH); |
| 564 |
543 |
| 565 /* The end of the message */ |
544 /* The end of the message */ |
| 566 if ((tmp2 = strchr(tmp1, ' '))) |
545 if ((tmp2 = wcschr(tmp1, L' '))) |
| 567 len = (tmp2 - tmp1); |
546 wlen = (tmp2 - tmp1); |
| 568 else |
547 else |
| 569 len = strlen(tmp1); |
548 wlen = wcslen(tmp1); |
| |
549 |
| |
550 if (wlen == 0) { |
| |
551 printf("No protocol message specified.\n"); |
| |
552 return; |
| |
553 } |
| |
554 |
| |
555 if (!(msg_win = FindWindowEx(NULL, NULL, _T("WinpidginMsgWinCls"), NULL))) { |
| |
556 printf("Unable to find an instance of Pidgin to handle protocol message.\n"); |
| |
557 return; |
| |
558 } |
| |
559 |
| |
560 len = WideCharToMultiByte(CP_UTF8, 0, tmp1, |
| |
561 wlen, NULL, 0, NULL, NULL); |
| |
562 if (len) { |
| |
563 utf8msg = malloc(len * sizeof(char)); |
| |
564 len = WideCharToMultiByte(CP_UTF8, 0, tmp1, |
| |
565 wlen, utf8msg, len, NULL, NULL); |
| |
566 } |
| 570 |
567 |
| 571 if (len == 0) { |
568 if (len == 0) { |
| 572 printf("No protocol message specified.\n"); |
569 printf("No protocol message specified.\n"); |
| 573 return; |
570 return; |
| 574 } |
571 } |
| 575 |
572 |
| 576 if (!(msg_win = FindWindowEx(NULL, NULL, TEXT("WinpidginMsgWinCls"), NULL))) { |
|
| 577 printf("Unable to find an instance of Pidgin to handle protocol message.\n"); |
|
| 578 return; |
|
| 579 } |
|
| 580 |
|
| 581 GetWindowThreadProcessId(msg_win, &pid); |
573 GetWindowThreadProcessId(msg_win, &pid); |
| 582 if (!(process = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, pid))) { |
574 if (!(process = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, pid))) { |
| 583 DWORD dw = GetLastError(); |
575 DWORD dw = GetLastError(); |
| 584 const char *err_msg = get_win32_error_message(dw); |
576 const TCHAR *err_msg = get_win32_error_message(dw); |
| 585 printf("Unable to open Pidgin process. (%u) %s\n", (UINT) dw, err_msg); |
577 _tprintf(_T("Unable to open Pidgin process. (%u) %s\n"), (UINT) dw, err_msg); |
| 586 return; |
578 return; |
| 587 } |
579 } |
| 588 |
580 |
| 589 printf("Trying to handle protocol message:\n'%.*s'\n", len, tmp1); |
581 wprintf(L"Trying to handle protocol message:\n'%.*s'\n", wlen, tmp1); |
| 590 |
582 |
| 591 /* MEM_COMMIT initializes the memory to zero, |
583 /* MEM_COMMIT initializes the memory to zero |
| 592 * so we don't need to worry that our section of tmp1 isn't nul-terminated */ |
584 * so we don't need to worry that our section of utf8msg isn't nul-terminated */ |
| 593 if ((remote_msg = (char*) VirtualAllocEx(process, NULL, len + 1, MEM_COMMIT, PAGE_READWRITE))) { |
585 if ((remote_msg = (char*) VirtualAllocEx(process, NULL, len + 1, MEM_COMMIT, PAGE_READWRITE))) { |
| 594 if (WriteProcessMemory(process, remote_msg, tmp1, len, &len_written)) { |
586 if (WriteProcessMemory(process, remote_msg, utf8msg, len, &len_written)) { |
| 595 if (!SendMessage(msg_win, PIDGIN_WM_PROTOCOL_HANDLE, len_written, (LPARAM) remote_msg)) |
587 if (!SendMessageA(msg_win, PIDGIN_WM_PROTOCOL_HANDLE, len_written, (LPARAM) remote_msg)) |
| 596 printf("Unable to send protocol message to Pidgin instance.\n"); |
588 printf("Unable to send protocol message to Pidgin instance.\n"); |
| 597 } else { |
589 } else { |
| 598 DWORD dw = GetLastError(); |
590 DWORD dw = GetLastError(); |
| 599 const char *err_msg = get_win32_error_message(dw); |
591 const TCHAR *err_msg = get_win32_error_message(dw); |
| 600 printf("Unable to write to remote memory. (%u) %s\n", (UINT) dw, err_msg); |
592 _tprintf(_T("Unable to write to remote memory. (%u) %s\n"), (UINT) dw, err_msg); |
| 601 } |
593 } |
| 602 |
594 |
| 603 VirtualFreeEx(process, remote_msg, 0, MEM_RELEASE); |
595 VirtualFreeEx(process, remote_msg, 0, MEM_RELEASE); |
| 604 } else { |
596 } else { |
| 605 DWORD dw = GetLastError(); |
597 DWORD dw = GetLastError(); |
| 606 const char *err_msg = get_win32_error_message(dw); |
598 const TCHAR *err_msg = get_win32_error_message(dw); |
| 607 printf("Unable to allocate remote memory. (%u) %s\n", (UINT) dw, err_msg); |
599 _tprintf(_T("Unable to allocate remote memory. (%u) %s\n"), (UINT) dw, err_msg); |
| 608 } |
600 } |
| 609 |
601 |
| 610 CloseHandle(process); |
602 CloseHandle(process); |
| |
603 free(utf8msg); |
| 611 } |
604 } |
| 612 |
605 |
| 613 |
606 |
| 614 int _stdcall |
607 int _stdcall |
| 615 WinMain (struct HINSTANCE__ *hInstance, struct HINSTANCE__ *hPrevInstance, |
608 WinMain (struct HINSTANCE__ *hInstance, struct HINSTANCE__ *hPrevInstance, |
| 616 char *lpszCmdLine, int nCmdShow) { |
609 char *lpszCmdLine, int nCmdShow) { |
| 617 char errbuf[512]; |
610 TCHAR errbuf[512]; |
| 618 char pidgin_dir[MAX_PATH]; |
611 TCHAR pidgin_dir[MAX_PATH]; |
| 619 char exe_name[MAX_PATH]; |
612 TCHAR exe_name[MAX_PATH]; |
| 620 HMODULE hmod; |
613 HMODULE hmod; |
| 621 char *tmp; |
614 TCHAR *tmp; |
| 622 int pidgin_argc = __argc; |
615 wchar_t *wtmp; |
| 623 char **pidgin_argv = __argv; |
616 int pidgin_argc; |
| 624 int i; |
617 char **pidgin_argv; /* This is in utf-8 */ |
| 625 BOOL debug = FALSE, help = FALSE, version = FALSE, multiple = FALSE; |
618 int i, j, k; |
| |
619 BOOL debug = FALSE, help = FALSE, version = FALSE, multiple = FALSE, success; |
| |
620 LPWSTR *szArglist; |
| |
621 LPWSTR cmdLine; |
| 626 |
622 |
| 627 /* If debug or help or version flag used, create console for output */ |
623 /* If debug or help or version flag used, create console for output */ |
| 628 for (i = 1; i < __argc; i++) { |
624 for (i = 1; i < __argc; i++) { |
| 629 if (strlen(__argv[i]) > 1 && __argv[i][0] == '-') { |
625 if (strlen(__argv[i]) > 1 && __argv[i][0] == '-') { |
| 630 /* check if we're looking at -- or - option */ |
626 /* check if we're looking at -- or - option */ |
| 666 freopen("CONOUT$", "w", stderr); |
662 freopen("CONOUT$", "w", stderr); |
| 667 } |
663 } |
| 668 } |
664 } |
| 669 } |
665 } |
| 670 |
666 |
| |
667 cmdLine = GetCommandLineW(); |
| |
668 |
| 671 /* If this is a protocol handler invocation, deal with it accordingly */ |
669 /* If this is a protocol handler invocation, deal with it accordingly */ |
| 672 if ((tmp = strstr(lpszCmdLine, PROTO_HANDLER_SWITCH)) != NULL) { |
670 if ((wtmp = wcsstr(cmdLine, PROTO_HANDLER_SWITCH)) != NULL) { |
| 673 handle_protocol(tmp); |
671 handle_protocol(wtmp); |
| 674 return 0; |
672 return 0; |
| 675 } |
673 } |
| 676 |
674 |
| 677 /* Load exception handler if we have it */ |
675 /* Load exception handler if we have it */ |
| 678 if (GetModuleFileName(NULL, pidgin_dir, MAX_PATH) != 0) { |
676 if (GetModuleFileName(NULL, pidgin_dir, MAX_PATH) != 0) { |
| 679 char *prev = NULL; |
|
| 680 tmp = pidgin_dir; |
|
| 681 |
677 |
| 682 /* primitive dirname() */ |
678 /* primitive dirname() */ |
| 683 while ((tmp = strchr(tmp, '\\'))) { |
679 tmp = _tcsrchr(pidgin_dir, _T('\\')); |
| 684 prev = tmp; |
680 |
| 685 tmp++; |
681 if (tmp) { |
| 686 } |
682 HMODULE hmod; |
| 687 |
683 tmp[0] = _T('\0'); |
| 688 if (prev) { |
684 |
| 689 prev[0] = '\0'; |
685 /* tmp++ will now point to the executable file name */ |
| 690 |
686 _tcscpy(exe_name, tmp + 1); |
| 691 /* prev++ will now point to the executable file name */ |
687 |
| 692 strcpy(exe_name, prev + 1); |
688 _tcscat(pidgin_dir, _T("\\exchndl.dll")); |
| 693 |
689 if ((hmod = LoadLibrary(pidgin_dir))) { |
| 694 strcat(pidgin_dir, "\\exchndl.dll"); |
690 FARPROC proc; |
| 695 if (LoadLibrary(pidgin_dir)) |
691 /* exchndl.dll is built without UNICODE */ |
| |
692 char debug_dir[MAX_PATH]; |
| 696 printf("Loaded exchndl.dll\n"); |
693 printf("Loaded exchndl.dll\n"); |
| 697 |
694 /* Temporarily override exchndl.dll's logfile |
| 698 prev[0] = '\0'; |
695 * to something sane (Pidgin will override it |
| |
696 * again when it initializes) */ |
| |
697 proc = GetProcAddress(hmod, "SetLogFile"); |
| |
698 if (proc) { |
| |
699 if (GetTempPathA(sizeof(debug_dir) * sizeof(char), debug_dir) != 0) { |
| |
700 strcat(debug_dir, "pidgin.RPT"); |
| |
701 printf(" Setting exchndl.dll LogFile to %s\n", |
| |
702 debug_dir); |
| |
703 (proc)(debug_dir); |
| |
704 } |
| |
705 } |
| |
706 proc = GetProcAddress(hmod, "SetDebugInfoDir"); |
| |
707 if (proc) { |
| |
708 char *pidgin_dir_ansi = NULL; |
| |
709 tmp[0] = _T('\0'); |
| |
710 #ifdef _UNICODE |
| |
711 i = WideCharToMultiByte(CP_ACP, 0, pidgin_dir, |
| |
712 -1, NULL, 0, NULL, NULL); |
| |
713 if (i != 0) { |
| |
714 pidgin_dir_ansi = malloc(i * sizeof(char)); |
| |
715 i = WideCharToMultiByte(CP_ACP, 0, pidgin_dir, |
| |
716 -1, pidgin_dir_ansi, i, NULL, NULL); |
| |
717 if (i == 0) { |
| |
718 free(pidgin_dir_ansi); |
| |
719 pidgin_dir_ansi = NULL; |
| |
720 } |
| |
721 } |
| |
722 #else |
| |
723 pidgin_dir_ansi = pidgin_dir; |
| |
724 #endif |
| |
725 if (pidgin_dir_ansi != NULL) { |
| |
726 _snprintf(debug_dir, sizeof(debug_dir) / sizeof(char), |
| |
727 "%s\\pidgin-%s-dbgsym", |
| |
728 pidgin_dir_ansi, VERSION); |
| |
729 debug_dir[sizeof(debug_dir) / sizeof(char) - 1] = '\0'; |
| |
730 printf(" Setting exchndl.dll DebugInfoDir to %s\n", |
| |
731 debug_dir); |
| |
732 (proc)(debug_dir); |
| |
733 #ifdef _UNICODE |
| |
734 free(pidgin_dir_ansi); |
| |
735 #endif |
| |
736 } |
| |
737 } |
| |
738 |
| |
739 } |
| |
740 |
| |
741 tmp[0] = _T('\0'); |
| 699 } |
742 } |
| 700 } else { |
743 } else { |
| 701 DWORD dw = GetLastError(); |
744 DWORD dw = GetLastError(); |
| 702 const char *err_msg = get_win32_error_message(dw); |
745 const TCHAR *err_msg = get_win32_error_message(dw); |
| 703 _snprintf(errbuf, 512, |
746 _sntprintf(errbuf, 512, |
| 704 "Error getting module filename.\nError: (%u) %s", |
747 _T("Error getting module filename.\nError: (%u) %s"), |
| 705 (UINT) dw, err_msg); |
748 (UINT) dw, err_msg); |
| 706 printf("%s\n", errbuf); |
749 _tprintf(_T("%s\n"), errbuf); |
| 707 MessageBox(NULL, errbuf, NULL, MB_OK | MB_TOPMOST); |
750 MessageBox(NULL, errbuf, NULL, MB_OK | MB_TOPMOST); |
| 708 pidgin_dir[0] = '\0'; |
751 pidgin_dir[0] = _T('\0'); |
| 709 } |
752 } |
| 710 |
753 |
| 711 /* Determine if we're running in portable mode */ |
754 /* Determine if we're running in portable mode */ |
| 712 if (strstr(lpszCmdLine, "--portable-mode") |
755 if (wcsstr(cmdLine, L"--portable-mode") |
| 713 || (exe_name != NULL && strstr(exe_name, "-portable.exe"))) { |
756 || (exe_name != NULL && _tcsstr(exe_name, _T("-portable.exe")))) { |
| 714 int i = 0, c = 0; |
|
| 715 |
|
| 716 printf("Running in PORTABLE mode.\n"); |
757 printf("Running in PORTABLE mode.\n"); |
| 717 portable_mode = TRUE; |
758 portable_mode = TRUE; |
| 718 |
|
| 719 /* Remove the --portable-mode arg from the args passed to pidgin so it doesn't choke */ |
|
| 720 pidgin_argv = malloc(sizeof(char*) * pidgin_argc); |
|
| 721 for (; i < __argc; i++) { |
|
| 722 if (strstr(__argv[i], "--portable-mode") == NULL) |
|
| 723 pidgin_argv[c++] = __argv[i]; |
|
| 724 else |
|
| 725 pidgin_argc--; |
|
| 726 } |
|
| 727 } |
759 } |
| 728 |
760 |
| 729 if (portable_mode) |
761 if (portable_mode) |
| 730 portable_mode_dll_prep(pidgin_dir); |
762 portable_mode_dll_prep(pidgin_dir); |
| 731 else if (!getenv("PIDGIN_NO_DLL_CHECK")) |
763 else if (!getenv("PIDGIN_NO_DLL_CHECK")) |
| 732 dll_prep(); |
764 dll_prep(pidgin_dir); |
| 733 |
765 |
| 734 winpidgin_set_locale(); |
766 winpidgin_set_locale(); |
| 735 |
767 |
| 736 winpidgin_add_stuff_to_path(); |
768 winpidgin_add_stuff_to_path(); |
| 737 |
769 |