comparison pidgin/win32/winpidgin.c @ 29775:e446b56c01e4

propagate from branch 'im.pidgin.pidgin' (head be77df4826034ac2521177bb6af6b60be3d1b4c4) to branch 'im.pidgin.pidgin.next.minor' (head c0803026336ad6c803c2982ec7b0153378d71860)
author Paul Aurich <paul@darkrain42.org>
date Tue, 16 Feb 2010 15:16:44 +0000
parents 380d38f07f58
children d4c887b0cb43
comparison
equal deleted inserted replaced
29454:5c9c4557fec2 29775:e446b56c01e4
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) &regval, 162 (LPBYTE) &regval,
159 &reglen); 163 &reglen);
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) &regval, 174 REG_DWORD, (LPBYTE) &regval,
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) &gtkpath, &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) &gtkpath, &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;
395 } 374 }
396 375
397 /* Deal with exceptions */ 376 /* Deal with exceptions */
398 if (posix == NULL) { 377 if (posix == NULL) {
399 switch (lcid) { 378 switch (lcid) {
400 case 0x0455: posix = "my_MM"; break; /* Myanmar (Burmese) */ 379 case 0x0455: posix = _T("my_MM"); break; /* Myanmar (Burmese) */
401 case 9999: posix = "ku"; break; /* Kurdish (from NSIS) */ 380 case 9999: posix = _T("ku"); break; /* Kurdish (from NSIS) */
402 } 381 }
403 } 382 }
404 383
405 return posix; 384 return posix;
406 } 385 }
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 */
653 if (debug || help || version) { 649 if (debug || help || version) {
654 /* If stdout hasn't been redirected to a file, alloc a console 650 /* If stdout hasn't been redirected to a file, alloc a console
655 * (_istty() doesn't work for stuff using the GUI subsystem) */ 651 * (_istty() doesn't work for stuff using the GUI subsystem) */
656 if (_fileno(stdout) == -1 || _fileno(stdout) == -2) { 652 if (_fileno(stdout) == -1 || _fileno(stdout) == -2) {
657 LPFNATTACHCONSOLE MyAttachConsole = NULL; 653 LPFNATTACHCONSOLE MyAttachConsole = NULL;
658 if ((hmod = GetModuleHandle("kernel32.dll"))) { 654 if ((hmod = GetModuleHandle(_T("kernel32.dll")))) {
659 MyAttachConsole = 655 MyAttachConsole =
660 (LPFNATTACHCONSOLE) 656 (LPFNATTACHCONSOLE)
661 GetProcAddress(hmod, "AttachConsole"); 657 GetProcAddress(hmod, "AttachConsole");
662 } 658 }
663 if ((MyAttachConsole && MyAttachConsole(ATTACH_PARENT_PROCESS)) 659 if ((MyAttachConsole && MyAttachConsole(ATTACH_PARENT_PROCESS))
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
739 if (!help && !version) 771 if (!help && !version)
740 if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && !multiple)) 772 if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && !multiple))
741 return 0; 773 return 0;
742 774
743 /* Now we are ready for Pidgin .. */ 775 /* Now we are ready for Pidgin .. */
744 if ((hmod = LoadLibrary("pidgin.dll"))) 776 if ((hmod = LoadLibrary(_T("pidgin.dll"))))
745 pidgin_main = (LPFNPIDGINMAIN) GetProcAddress(hmod, "pidgin_main"); 777 pidgin_main = (LPFNPIDGINMAIN) GetProcAddress(hmod, "pidgin_main");
746 778
747 if (!pidgin_main) { 779 if (!pidgin_main) {
748 DWORD dw = GetLastError(); 780 DWORD dw = GetLastError();
749 BOOL mod_not_found = (dw == ERROR_MOD_NOT_FOUND || dw == ERROR_DLL_NOT_FOUND); 781 BOOL mod_not_found = (dw == ERROR_MOD_NOT_FOUND || dw == ERROR_DLL_NOT_FOUND);
750 const char *err_msg = get_win32_error_message(dw); 782 const TCHAR *err_msg = get_win32_error_message(dw);
751 783
752 _snprintf(errbuf, 512, "Error loading pidgin.dll.\nError: (%u) %s%s%s", 784 _sntprintf(errbuf, 512, _T("Error loading pidgin.dll.\nError: (%u) %s%s%s"),
753 (UINT) dw, err_msg, 785 (UINT) dw, err_msg,
754 mod_not_found ? "\n" : "", 786 mod_not_found ? _T("\n") : _T(""),
755 mod_not_found ? "This probably means that GTK+ can't be found." : ""); 787 mod_not_found ? _T("This probably means that GTK+ can't be found.") : _T(""));
756 printf("%s\n", errbuf); 788 _tprintf(_T("%s\n"), errbuf);
757 MessageBox(NULL, errbuf, TEXT("Error"), MB_OK | MB_TOPMOST); 789 MessageBox(NULL, errbuf, _T("Error"), MB_OK | MB_TOPMOST);
758 790
759 return 0; 791 return 0;
760 } 792 }
761 793
794 /* Convert argv to utf-8*/
795 szArglist = CommandLineToArgvW(cmdLine, &j);
796 pidgin_argc = j;
797 pidgin_argv = malloc(pidgin_argc* sizeof(char*));
798 k = 0;
799 for (i = 0; i < j; i++) {
800 success = FALSE;
801 /* Remove the --portable-mode arg from the args passed to pidgin so it doesn't choke */
802 if (wcsstr(szArglist[i], L"--portable-mode") == NULL) {
803 int len = WideCharToMultiByte(CP_UTF8, 0, szArglist[i],
804 -1, NULL, 0, NULL, NULL);
805 if (len != 0) {
806 char *arg = malloc(len * sizeof(char));
807 len = WideCharToMultiByte(CP_UTF8, 0, szArglist[i],
808 -1, arg, len, NULL, NULL);
809 if (len != 0) {
810 pidgin_argv[k++] = arg;
811 success = TRUE;
812 }
813 }
814 if (!success)
815 wprintf(L"Error converting argument '%s' to UTF-8\n",
816 szArglist[i]);
817 }
818 if (!success)
819 pidgin_argc--;
820 }
821 LocalFree(szArglist);
822
823
762 return pidgin_main(hInstance, pidgin_argc, pidgin_argv); 824 return pidgin_main(hInstance, pidgin_argc, pidgin_argv);
763 } 825 }