Mercurial > pidgin.yaz
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) ®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; |
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 } |