| 65 (LPWSTR) &err_msg, sizeof(err_msg) / sizeof(wchar_t), NULL); |
58 (LPWSTR) &err_msg, sizeof(err_msg) / sizeof(wchar_t), NULL); |
| 66 |
59 |
| 67 return err_msg; |
60 return err_msg; |
| 68 } |
61 } |
| 69 |
62 |
| 70 static BOOL reg_value_exists(HKEY key, wchar_t *sub_key, wchar_t *val_name) { |
|
| 71 HKEY hkey; |
|
| 72 LONG retv; |
|
| 73 DWORD index; |
|
| 74 wchar_t name_buffer[100]; |
|
| 75 BOOL exists = FALSE; |
|
| 76 |
|
| 77 if (sub_key == NULL || val_name == NULL) |
|
| 78 return FALSE; |
|
| 79 |
|
| 80 retv = RegOpenKeyExW(key, sub_key, 0, KEY_ENUMERATE_SUB_KEYS, &hkey); |
|
| 81 if (retv != ERROR_SUCCESS) |
|
| 82 return FALSE; |
|
| 83 |
|
| 84 if (val_name[0] == L'\0') { |
|
| 85 RegCloseKey(hkey); |
|
| 86 return TRUE; |
|
| 87 } |
|
| 88 |
|
| 89 index = 0; |
|
| 90 while (TRUE) |
|
| 91 { |
|
| 92 DWORD name_size = sizeof(name_buffer); |
|
| 93 retv = RegEnumValueW(hkey, index++, name_buffer, &name_size, |
|
| 94 NULL, NULL, NULL, NULL); |
|
| 95 if (retv != ERROR_SUCCESS) |
|
| 96 break; |
|
| 97 name_size /= sizeof(wchar_t); |
|
| 98 if (wcsncmp(name_buffer, val_name, name_size) == 0) { |
|
| 99 exists = TRUE; |
|
| 100 break; |
|
| 101 } |
|
| 102 } |
|
| 103 |
|
| 104 RegCloseKey(hkey); |
|
| 105 return exists; |
|
| 106 } |
|
| 107 |
|
| 108 static BOOL read_reg_string(HKEY key, wchar_t *sub_key, wchar_t *val_name, LPBYTE data, LPDWORD data_len) { |
|
| 109 HKEY hkey; |
|
| 110 BOOL ret = FALSE; |
|
| 111 LONG retv; |
|
| 112 |
|
| 113 if (ERROR_SUCCESS == (retv = RegOpenKeyExW(key, sub_key, 0, |
|
| 114 KEY_QUERY_VALUE, &hkey))) { |
|
| 115 if (ERROR_SUCCESS == (retv = RegQueryValueExW(hkey, val_name, |
|
| 116 NULL, NULL, data, data_len))) |
|
| 117 ret = TRUE; |
|
| 118 else { |
|
| 119 const wchar_t *err_msg = get_win32_error_message(retv); |
|
| 120 |
|
| 121 wprintf(L"Could not read reg key '%s' subkey '%s' value: '%s'.\nMessage: (%ld) %s\n", |
|
| 122 (key == HKEY_LOCAL_MACHINE) ? L"HKLM" |
|
| 123 : ((key == HKEY_CURRENT_USER) ? L"HKCU" : L"???"), |
|
| 124 sub_key, val_name, retv, err_msg); |
|
| 125 } |
|
| 126 RegCloseKey(hkey); |
|
| 127 } |
|
| 128 else { |
|
| 129 wchar_t szBuf[80]; |
|
| 130 |
|
| 131 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, retv, 0, |
|
| 132 (LPWSTR) &szBuf, sizeof(szBuf) / sizeof(wchar_t), NULL); |
|
| 133 wprintf(L"Could not open reg subkey: %s\nError: (%ld) %s\n", |
|
| 134 sub_key, retv, szBuf); |
|
| 135 } |
|
| 136 |
|
| 137 return ret; |
|
| 138 } |
|
| 139 |
|
| 140 static BOOL check_for_gtk(const wchar_t *path) { |
|
| 141 struct _stat stat_buf; |
|
| 142 wchar_t test_path[MAX_PATH + 1]; |
|
| 143 |
|
| 144 _snwprintf(test_path, sizeof(test_path) / sizeof(wchar_t), |
|
| 145 L"%s\\libgtk-win32-2.0-0.dll", path); |
|
| 146 test_path[sizeof(test_path) / sizeof(wchar_t) - 1] = L'\0'; |
|
| 147 |
|
| 148 return (_wstat(test_path, &stat_buf) == 0); |
|
| 149 } |
|
| 150 |
|
| 151 static void common_dll_prep(const wchar_t *path) { |
|
| 152 HMODULE hmod; |
|
| 153 HKEY hkey; |
|
| 154 wchar_t alt_path_buff[MAX_PATH + 1]; |
|
| 155 wchar_t tmp_path[MAX_PATH + 1]; |
|
| 156 /* Hold strlen("FS_PLUGIN_PATH=" or "GST_PLUGIN_SYSTEM_PATH") + |
|
| 157 * MAX_PATH + 1 |
|
| 158 */ |
|
| 159 wchar_t set_path[MAX_PATH + 24]; |
|
| 160 wchar_t *fslash, *bslash; |
|
| 161 |
|
| 162 if (!check_for_gtk(path)) { |
|
| 163 const wchar_t *winpath = _wgetenv(L"PATH"); |
|
| 164 wchar_t *delim; |
|
| 165 |
|
| 166 if (winpath == NULL) { |
|
| 167 printf("Unable to determine GTK+ path (and PATH is not set).\n"); |
|
| 168 exit(-1); |
|
| 169 } |
|
| 170 |
|
| 171 path = NULL; |
|
| 172 do |
|
| 173 { |
|
| 174 wcsncpy(alt_path_buff, winpath, MAX_PATH); |
|
| 175 alt_path_buff[MAX_PATH] = L'\0'; |
|
| 176 delim = wcschr(alt_path_buff, L';'); |
|
| 177 if (delim != NULL) { |
|
| 178 delim[0] = L'\0'; |
|
| 179 winpath = wcschr(winpath, L';') + 1; |
|
| 180 } |
|
| 181 if (check_for_gtk(alt_path_buff)) { |
|
| 182 path = alt_path_buff; |
|
| 183 break; |
|
| 184 } |
|
| 185 } |
|
| 186 while (delim != NULL); |
|
| 187 |
|
| 188 if (path == NULL) { |
|
| 189 printf("Unable to determine GTK+ path.\n"); |
|
| 190 exit(-1); |
|
| 191 } |
|
| 192 } |
|
| 193 |
|
| 194 wprintf(L"GTK+ path found: %s\n", path); |
|
| 195 |
|
| 196 wcsncpy(tmp_path, path, MAX_PATH); |
|
| 197 tmp_path[MAX_PATH] = L'\0'; |
|
| 198 bslash = wcsrchr(tmp_path, L'\\'); |
|
| 199 fslash = wcsrchr(tmp_path, L'/'); |
|
| 200 if (bslash && bslash > fslash) |
|
| 201 bslash[0] = L'\0'; |
|
| 202 else if (fslash && fslash > bslash) |
|
| 203 fslash[0] = L'\0'; |
|
| 204 /* tmp_path now contains \path\to\Pidgin\Gtk */ |
|
| 205 |
|
| 206 _snwprintf(set_path, sizeof(set_path) / sizeof(wchar_t), |
|
| 207 L"FS_PLUGIN_PATH=%s\\lib\\farstream-0.1", tmp_path); |
|
| 208 set_path[sizeof(set_path) / sizeof(wchar_t) - 1] = L'\0'; |
|
| 209 _wputenv(set_path); |
|
| 210 |
|
| 211 _snwprintf(set_path, sizeof(set_path) / sizeof(wchar_t), |
|
| 212 L"GST_PLUGIN_SYSTEM_PATH=%s\\lib\\gstreamer-0.10", tmp_path); |
|
| 213 set_path[sizeof(set_path) / sizeof(wchar_t) - 1] = L'\0'; |
|
| 214 _wputenv(set_path); |
|
| 215 |
|
| 216 _snwprintf(set_path, sizeof(set_path) / sizeof(wchar_t), |
|
| 217 L"GST_PLUGIN_PATH=%s\\lib\\gstreamer-0.10", tmp_path); |
|
| 218 set_path[sizeof(set_path) / sizeof(wchar_t) - 1] = L'\0'; |
|
| 219 _wputenv(set_path); |
|
| 220 |
|
| 221 if ((hmod = GetModuleHandleW(L"kernel32.dll"))) { |
|
| 222 MySetDllDirectory = (LPFNSETDLLDIRECTORY) GetProcAddress( |
|
| 223 hmod, "SetDllDirectoryW"); |
|
| 224 if (!MySetDllDirectory) |
|
| 225 printf("SetDllDirectory not supported\n"); |
|
| 226 } else |
|
| 227 printf("Error getting kernel32.dll module handle\n"); |
|
| 228 |
|
| 229 /* For Windows XP SP1+ / Server 2003 we use SetDllDirectory to avoid dll hell */ |
|
| 230 if (MySetDllDirectory) { |
|
| 231 MySetDllDirectory(path); |
|
| 232 } |
|
| 233 |
|
| 234 /* For the rest, we set the current directory and make sure |
|
| 235 * SafeDllSearch is set to 0 where needed. */ |
|
| 236 else { |
|
| 237 OSVERSIONINFOW osinfo; |
|
| 238 |
|
| 239 printf("Setting current directory to GTK+ dll directory\n"); |
|
| 240 SetCurrentDirectoryW(path); |
|
| 241 /* For Windows 2000 (SP3+) / WinXP (No SP): |
|
| 242 * If SafeDllSearchMode is set to 1, Windows system directories are |
|
| 243 * searched for dlls before the current directory. Therefore we set it |
|
| 244 * to 0. |
|
| 245 */ |
|
| 246 osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); |
|
| 247 GetVersionExW(&osinfo); |
|
| 248 if ((osinfo.dwMajorVersion == 5 |
|
| 249 && osinfo.dwMinorVersion == 0 |
|
| 250 && wcscmp(osinfo.szCSDVersion, L"Service Pack 3") >= 0) |
|
| 251 || |
|
| 252 (osinfo.dwMajorVersion == 5 |
|
| 253 && osinfo.dwMinorVersion == 1 |
|
| 254 && wcscmp(osinfo.szCSDVersion, L"") >= 0) |
|
| 255 ) { |
|
| 256 DWORD regval = 1; |
|
| 257 DWORD reglen = sizeof(DWORD); |
|
| 258 |
|
| 259 printf("Using Win2k (SP3+) / WinXP (No SP)... Checking SafeDllSearch\n"); |
|
| 260 read_reg_string(HKEY_LOCAL_MACHINE, |
|
| 261 L"System\\CurrentControlSet\\Control\\Session Manager", |
|
| 262 L"SafeDllSearchMode", |
|
| 263 (LPBYTE) ®val, |
|
| 264 ®len); |
|
| 265 |
|
| 266 if (regval != 0) { |
|
| 267 printf("Trying to set SafeDllSearchMode to 0\n"); |
|
| 268 regval = 0; |
|
| 269 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, |
|
| 270 L"System\\CurrentControlSet\\Control\\Session Manager", |
|
| 271 0, KEY_SET_VALUE, &hkey |
|
| 272 ) == ERROR_SUCCESS) { |
|
| 273 if (RegSetValueExW(hkey, |
|
| 274 L"SafeDllSearchMode", 0, |
|
| 275 REG_DWORD, (LPBYTE) ®val, |
|
| 276 sizeof(DWORD) |
|
| 277 ) != ERROR_SUCCESS) |
|
| 278 printf("Error writing SafeDllSearchMode. Error: %u\n", |
|
| 279 (UINT) GetLastError()); |
|
| 280 RegCloseKey(hkey); |
|
| 281 } else |
|
| 282 printf("Error opening Session Manager key for writing. Error: %u\n", |
|
| 283 (UINT) GetLastError()); |
|
| 284 } else |
|
| 285 printf("SafeDllSearchMode is set to 0\n"); |
|
| 286 }/*end else*/ |
|
| 287 } |
|
| 288 } |
|
| 289 |
|
| 290 #ifndef IS_WIN32_CROSS_COMPILED |
|
| 291 static void dll_prep(const wchar_t *pidgin_dir) { |
|
| 292 wchar_t path[MAX_PATH + 1]; |
|
| 293 path[0] = L'\0'; |
|
| 294 |
|
| 295 if (*pidgin_dir) { |
|
| 296 _snwprintf(path, sizeof(path) / sizeof(wchar_t), L"%s\\Gtk\\bin", pidgin_dir); |
|
| 297 path[sizeof(path) / sizeof(wchar_t) - 1] = L'\0'; |
|
| 298 } |
|
| 299 |
|
| 300 common_dll_prep(path); |
|
| 301 } |
|
| 302 #endif |
|
| 303 |
|
| 304 static void portable_mode_dll_prep(const wchar_t *pidgin_dir) { |
63 static void portable_mode_dll_prep(const wchar_t *pidgin_dir) { |
| 305 /* need to be able to fit MAX_PATH + "PURPLEHOME=" in path2 */ |
64 /* need to be able to fit MAX_PATH + "PURPLEHOME=" in path2 */ |
| 306 wchar_t path[MAX_PATH + 1]; |
65 wchar_t path[MAX_PATH + 1]; |
| 307 wchar_t path2[MAX_PATH + 12]; |
66 wchar_t path2[MAX_PATH + 12]; |
| 308 const wchar_t *prev = NULL; |
67 const wchar_t *prev = NULL; |
| 309 |
68 |
| 310 /* We assume that GTK+ is installed under \\path\to\Pidgin\..\GTK |
69 /* We want settings to go into \\path\to\Pidgin\'s parent directory |
| 311 * First we find \\path\to |
70 * First we find \\path\to |
| 312 */ |
71 */ |
| 313 if (*pidgin_dir) |
72 if (*pidgin_dir) |
| 314 /* pidgin_dir points to \\path\to\Pidgin */ |
73 /* pidgin_dir points to \\path\to\Pidgin */ |
| 315 prev = wcsrchr(pidgin_dir, L'\\'); |
74 prev = wcsrchr(pidgin_dir, L'\\'); |
| 597 } |
344 } |
| 598 |
345 |
| 599 /* Restore pidgin_dir to point to where the executable is */ |
346 /* Restore pidgin_dir to point to where the executable is */ |
| 600 pidgin_dir_start[0] = L'\0'; |
347 pidgin_dir_start[0] = L'\0'; |
| 601 } |
348 } |
| |
349 |
| |
350 #ifndef USE_WIN32_FHS |
| |
351 /* Add bin/ subdirectory to DLL path */ |
| |
352 if ((hmod = GetModuleHandleW(L"kernel32.dll"))) { |
| |
353 LPFNSETDLLDIRECTORY MySetDllDirectory = |
| |
354 (LPFNSETDLLDIRECTORY) |
| |
355 GetProcAddress(hmod, "SetDllDirectoryW"); |
| |
356 |
| |
357 if (MySetDllDirectory) { |
| |
358 wcscat(pidgin_dir, L"\\bin"); |
| |
359 if (MySetDllDirectory(pidgin_dir)) { |
| |
360 wprintf(L"Added DLL directory to search path: %s\n", |
| |
361 pidgin_dir); |
| |
362 } else { |
| |
363 DWORD dw = GetLastError(); |
| |
364 const wchar_t *err_msg = get_win32_error_message(dw); |
| |
365 wprintf(L"Error calling SetDllDirectory(): (%u) %s\n", dw, err_msg); |
| |
366 } |
| |
367 } else { |
| |
368 DWORD dw = GetLastError(); |
| |
369 const wchar_t *err_msg = get_win32_error_message(dw); |
| |
370 wprintf(L"Error loading SetDllDirectory(): (%u) %s\n", dw, err_msg); |
| |
371 } |
| |
372 |
| |
373 /* Restore pidgin_dir to point to where the executable is */ |
| |
374 pidgin_dir_start[0] = L'\0'; |
| |
375 } else { |
| |
376 printf("Error getting kernel32.dll handle\n"); |
| |
377 } |
| |
378 #endif |
| 602 } else { |
379 } else { |
| 603 DWORD dw = GetLastError(); |
380 DWORD dw = GetLastError(); |
| 604 const wchar_t *err_msg = get_win32_error_message(dw); |
381 const wchar_t *err_msg = get_win32_error_message(dw); |
| 605 _snwprintf(errbuf, 512, |
382 _snwprintf(errbuf, 512, |
| 606 L"Error getting module filename.\nError: (%u) %s", |
383 L"Error getting module filename.\nError: (%u) %s", |
| 617 portable_mode = TRUE; |
394 portable_mode = TRUE; |
| 618 } |
395 } |
| 619 |
396 |
| 620 if (portable_mode) |
397 if (portable_mode) |
| 621 portable_mode_dll_prep(pidgin_dir); |
398 portable_mode_dll_prep(pidgin_dir); |
| 622 #ifndef IS_WIN32_CROSS_COMPILED |
|
| 623 else if (!getenv("PIDGIN_NO_DLL_CHECK")) |
|
| 624 dll_prep(pidgin_dir); |
|
| 625 #endif |
|
| 626 |
399 |
| 627 /* If help, version or multiple flag used, do not check Mutex */ |
400 /* If help, version or multiple flag used, do not check Mutex */ |
| 628 if (!help && !version) |
401 if (!help && !version) |
| 629 if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && !multiple)) |
402 if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && !multiple)) |
| 630 return 0; |
403 return 0; |
| 631 |
404 |
| 632 #ifndef IS_WIN32_CROSS_COMPILED |
|
| 633 /* Now we are ready for Pidgin .. */ |
405 /* Now we are ready for Pidgin .. */ |
| 634 wcscat(pidgin_dir, L"\\pidgin.dll"); |
406 if ((hmod = LoadLibraryW(L"libpidgin-20.dll"))) |
| 635 if ((hmod = LoadLibraryW(pidgin_dir))) |
|
| 636 pidgin_main = (LPFNPIDGINMAIN) GetProcAddress(hmod, "pidgin_main"); |
407 pidgin_main = (LPFNPIDGINMAIN) GetProcAddress(hmod, "pidgin_main"); |
| 637 #endif |
408 |
| 638 |
|
| 639 /* Restore pidgin_dir to point to where the executable is */ |
|
| 640 if (pidgin_dir_start) |
|
| 641 pidgin_dir_start[0] = L'\0'; |
|
| 642 |
|
| 643 #ifndef IS_WIN32_CROSS_COMPILED |
|
| 644 if (!pidgin_main) { |
409 if (!pidgin_main) { |
| 645 DWORD dw = GetLastError(); |
410 DWORD dw = GetLastError(); |
| 646 BOOL mod_not_found = (dw == ERROR_MOD_NOT_FOUND || dw == ERROR_DLL_NOT_FOUND); |
|
| 647 const wchar_t *err_msg = get_win32_error_message(dw); |
411 const wchar_t *err_msg = get_win32_error_message(dw); |
| 648 |
412 |
| 649 _snwprintf(errbuf, 512, L"Error loading pidgin.dll.\nError: (%u) %s%s%s", |
413 _snwprintf(errbuf, 512, L"Error loading libpidgin-20.dll.\n" |
| 650 (UINT) dw, err_msg, |
414 "Error: (%u) %s", (UINT) dw, err_msg); |
| 651 mod_not_found ? L"\n" : L"", |
|
| 652 mod_not_found ? L"This probably means that GTK+ can't be found." : L""); |
|
| 653 wprintf(L"%s\n", errbuf); |
415 wprintf(L"%s\n", errbuf); |
| 654 MessageBoxW(NULL, errbuf, L"Error", MB_OK | MB_TOPMOST); |
416 MessageBoxW(NULL, errbuf, L"Error", MB_OK | MB_TOPMOST); |
| 655 |
417 |
| 656 return 0; |
418 return 0; |
| 657 } |
419 } |
| 658 #endif |
|
| 659 |
420 |
| 660 /* Convert argv to utf-8*/ |
421 /* Convert argv to utf-8*/ |
| 661 szArglist = CommandLineToArgvW(cmdLine, &j); |
422 szArglist = CommandLineToArgvW(cmdLine, &j); |
| 662 pidgin_argc = j; |
423 pidgin_argc = j; |
| 663 pidgin_argv = malloc(pidgin_argc* sizeof(char*)); |
424 pidgin_argv = malloc(pidgin_argc* sizeof(char*)); |