Mercurial > pidgin.yaz
comparison src/win_gaim.c @ 7350:e28728795a45
[gaim-migrate @ 7941]
Fix for bug #808562 - LANG needs to be set before gtk_init,
when setting text widgets to RTL or LTR. New dll hell avoidance policies..
hopefully this time as many bases are covered as can be.
committer: Tailor Script <tailor@pidgin.im>
author | Herman Bloggs <hermanator12002@yahoo.com> |
---|---|
date | Mon, 27 Oct 2003 16:11:54 +0000 |
parents | 4eee806af511 |
children | be11a6f2fe00 |
comparison
equal
deleted
inserted
replaced
7349:345f3b22ebd6 | 7350:e28728795a45 |
---|---|
1 /* | 1 /* |
2 * win_aim.c | 2 * win_gaim.c |
3 * | 3 * |
4 * Author: Herman Bloggs <hermanator12002@yahoo.com> | |
5 * Date: June, 2002 | 4 * Date: June, 2002 |
6 * Description: Entry point for win32 gaim, and various win32 dependant | 5 * Description: Entry point for win32 gaim, and various win32 dependant |
7 * routines. | 6 * routines. |
7 * | |
8 * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com> | |
9 * | |
10 * This program is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program; if not, write to the Free Software | |
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
23 * | |
8 */ | 24 */ |
9 #include <windows.h> | 25 #include <windows.h> |
10 #include <stdlib.h> | 26 #include <stdlib.h> |
11 #include <string.h> | 27 #include <string.h> |
12 #include <stdio.h> | 28 #include <stdio.h> |
13 | 29 |
14 /* | 30 /* |
15 * GLOBALS | |
16 */ | |
17 __declspec(dllimport) HINSTANCE gaimexe_hInstance; | |
18 | |
19 /* | |
20 * LOCALS | |
21 */ | |
22 static char msg1[] = "The following duplicate of "; | |
23 static char msg2[] = " has been found in your dll search path and will likely\x0d\x0a" | |
24 "cause Gaim to malfunction:\x0d\x0a\x0d\x0a"; | |
25 | |
26 static char msg3[] = "\x0d\x0a\x0d\x0aWould you like to rename this dll to "; | |
27 static char msg4[] = ".prob in order to avoid any possible conflicts?\x0d\x0a" | |
28 "\x0d\x0a" | |
29 "Note: Doing so will likely cause the application that installed this dll to stop functioning.\x0d\x0a" | |
30 "You may wish to inform the author of the responsible application so that future versions\x0d\x0a" | |
31 "do not cause 'Dll Hell'."; | |
32 | |
33 /* | |
34 * PROTOTYPES | 31 * PROTOTYPES |
35 */ | 32 */ |
36 int (*gaim_main)( HINSTANCE, int, char** ) = NULL; | 33 static int (*gaim_main)( HINSTANCE, int, char** ) = NULL; |
37 | 34 static void (*MySetDllDirectory)(LPCTSTR lpPathName) = NULL; |
38 static void check_dll(char* dll, char* orig) { | 35 |
39 char tmp[MAX_PATH]; | 36 |
40 char *last; | 37 static BOOL read_reg_string(HKEY key, char* sub_key, char* val_name, LPBYTE data, LPDWORD data_len) { |
41 | |
42 if(SearchPath(NULL, dll, NULL, MAX_PATH, tmp, &last)) { | |
43 char* patha = (char*)malloc(strlen(orig) + strlen(dll) + 4); | |
44 strcpy(patha, orig); | |
45 strcat(patha, "\\"); | |
46 strcat(patha, dll); | |
47 /* Make sure that 2 paths are not the same */ | |
48 if(strcasecmp(patha, tmp) != 0) { | |
49 char *warning = (char*)malloc(strlen(msg1)+ | |
50 strlen(msg2)+ | |
51 strlen(msg3)+ | |
52 strlen(msg4)+ | |
53 strlen(tmp)+ | |
54 (strlen(dll)*2)+4); | |
55 sprintf(warning, "%s%s%s%s%s%s%s", msg1, dll, msg2, tmp, msg3, dll, msg4); | |
56 if(MessageBox(NULL, warning, "Gaim Warning", MB_YESNO | MB_TOPMOST)==IDYES) { | |
57 char *newname = (char*)malloc(strlen(tmp)+6); | |
58 /* Rename offending dll */ | |
59 sprintf(newname, "%s%s", tmp, ".prob"); | |
60 if(rename(tmp, newname) != 0) { | |
61 MessageBox(NULL, "Error renaming file.", NULL, MB_OK | MB_TOPMOST); | |
62 } | |
63 else | |
64 check_dll(dll, orig); | |
65 free(newname); | |
66 } | |
67 free(warning); | |
68 } | |
69 free(patha); | |
70 } | |
71 } | |
72 | |
73 static void dll_hell_check(char* gtkpath) { | |
74 HANDLE myHandle; | |
75 WIN32_FIND_DATA fd; | |
76 char* srchstr = (char*)malloc(strlen(gtkpath) + 8); | |
77 | |
78 sprintf(srchstr, "%s%s", gtkpath, "\\*.dll"); | |
79 myHandle = FindFirstFile(srchstr, &fd ); | |
80 if(myHandle != INVALID_HANDLE_VALUE) { | |
81 check_dll(fd.cFileName, gtkpath); | |
82 while(FindNextFile(myHandle, &fd)) { | |
83 check_dll(fd.cFileName, gtkpath); | |
84 } | |
85 } | |
86 free(srchstr); | |
87 } | |
88 | |
89 BOOL read_reg_string(HKEY key, char* sub_key, char* val_name, LPBYTE data, LPDWORD data_len) { | |
90 HKEY hkey; | 38 HKEY hkey; |
91 BOOL ret = FALSE; | 39 BOOL ret = FALSE; |
92 int retv; | 40 int retv; |
93 | 41 |
94 if(ERROR_SUCCESS == RegOpenKeyEx(key, | 42 if(ERROR_SUCCESS == RegOpenKeyEx(key, |
95 sub_key, | 43 sub_key, |
96 0, KEY_QUERY_VALUE, &hkey)) { | 44 0, KEY_QUERY_VALUE, &hkey)) { |
97 if(ERROR_SUCCESS == (retv=RegQueryValueEx(hkey, val_name, 0, NULL, data, data_len))) | 45 if(ERROR_SUCCESS == (retv=RegQueryValueEx(hkey, val_name, 0, NULL, data, data_len))) |
98 ret = TRUE; | 46 ret = TRUE; |
99 else { | 47 else |
100 printf("Error reading registry string value: %d\n", retv); | 48 ret = FALSE; |
101 } | |
102 RegCloseKey(key); | 49 RegCloseKey(key); |
103 } | 50 } |
104 return ret; | 51 return ret; |
105 } | 52 } |
106 | 53 |
107 void run_dll_check() { | 54 static void run_dll_prep() { |
55 char gtkpath[MAX_PATH]; | |
108 char path[MAX_PATH]; | 56 char path[MAX_PATH]; |
109 DWORD plen = MAX_PATH; | 57 DWORD plen = MAX_PATH; |
110 int gotreg=FALSE; | 58 int gotreg=FALSE; |
111 | 59 HKEY hkey; |
112 /* Dll Hell Check.. Only run check if we are the same gaim as found in the | 60 HMODULE hmod; |
113 gaim registry key */ | 61 |
114 if(!(gotreg = read_reg_string(HKEY_LOCAL_MACHINE, "SOFTWARE\\gaim", "", (LPBYTE)&path, &plen))) | 62 if(!(gotreg = read_reg_string((hkey=HKEY_LOCAL_MACHINE), "SOFTWARE\\GTK\\2.0", "Path", (LPBYTE)>kpath, &plen))) |
115 gotreg = read_reg_string(HKEY_CURRENT_USER, "SOFTWARE\\gaim", "", (LPBYTE)&path, &plen); | 63 gotreg = read_reg_string((hkey=HKEY_CURRENT_USER), "SOFTWARE\\GTK\\2.0", "Path", (LPBYTE)>kpath, &plen); |
116 | 64 |
117 if(gotreg) { | 65 if(!gotreg) |
118 char modpath[MAX_PATH]; | 66 return; |
119 | 67 |
120 strcat(path, "\\gaim.exe"); | 68 /* Determine GTK+ dll path .. */ |
121 GetModuleFileName(NULL, modpath, MAX_PATH); | 69 if(!read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "DllPath", (LPBYTE)&path, &plen)) { |
122 if(strcasecmp(path, modpath) == 0) { | 70 char version[10]; |
123 plen = MAX_PATH; | 71 char inst[10]; |
124 if(!(gotreg = read_reg_string(HKEY_LOCAL_MACHINE, "SOFTWARE\\GTK\\2.0", "Path", (LPBYTE)&path, &plen))) | 72 DWORD len = 10; |
125 gotreg = read_reg_string(HKEY_CURRENT_USER, "SOFTWARE\\GTK\\2.0", "Path", (LPBYTE)&path, &plen); | 73 |
126 if(gotreg) { | 74 strcpy(path, gtkpath); |
75 if(read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "Version", (LPBYTE)&version, &len) && | |
76 read_reg_string(hkey, "SOFTWARE\\GTK\\2.0", "Installer", (LPBYTE)&inst, &len)) { | |
77 if(strcmp(version, "2.2.2") >= 0 && | |
78 strcmp(inst, "NSIS") == 0) { | |
127 strcat(path, "\\bin"); | 79 strcat(path, "\\bin"); |
128 dll_hell_check(path); | 80 } |
81 else | |
82 strcat(path, "\\lib"); | |
83 } | |
84 else | |
85 strcat(path, "\\lib"); | |
86 } | |
87 | |
88 if((hmod=LoadLibrary("kernel32.dll"))) { | |
89 MySetDllDirectory = (void*)GetProcAddress(hmod, "SetDllDirectory"); | |
90 } | |
91 | |
92 /* For Windows XP SP1 / Server 2003 we use SetDllDirectory to avoid dll hell */ | |
93 if(MySetDllDirectory) | |
94 MySetDllDirectory(path); | |
95 /* For the rest, we set the current directory */ | |
96 else { | |
97 OSVERSIONINFO osinfo; | |
98 | |
99 SetCurrentDirectory(path); | |
100 /* For Windows 2000 SP3 and higher: | |
101 * If SafeDllSearchMode is set to 1, Windows system directories are | |
102 * searched for dlls before the current directory. Therefore we set it | |
103 * to 0. | |
104 */ | |
105 osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); | |
106 GetVersionEx(&osinfo); | |
107 if(osinfo.dwMajorVersion == 5 && | |
108 osinfo.dwMinorVersion == 0 && | |
109 strcmp(osinfo.szCSDVersion, "Service Pack 3") >= 0) { | |
110 if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, | |
111 "System\\CurrentControlSet\\Control\\Session Manager", | |
112 0, KEY_SET_VALUE, &hkey)) { | |
113 DWORD regval = 0; | |
114 RegSetValueEx(hkey, | |
115 "SafeDllSearchMode", | |
116 0, | |
117 REG_DWORD, | |
118 (LPBYTE) ®val, | |
119 sizeof(regval)); | |
120 RegCloseKey(hkey); | |
129 } | 121 } |
130 } | 122 } |
131 } | 123 } |
132 } | 124 } |
125 | |
126 static char* wgaim_lcid_to_posix(LCID lcid) { | |
127 switch(lcid) { | |
128 case 1026: return "bg"; /* bulgarian */ | |
129 case 1027: return "ca"; /* catalan */ | |
130 case 1050: return "hr"; /* croation */ | |
131 case 1029: return "cs"; /* czech */ | |
132 case 1030: return "da"; /* danaish */ | |
133 case 1043: return "nl"; /* dutch - netherlands */ | |
134 case 1033: return "en"; /* english - us */ | |
135 case 1035: return "fi"; /* finish */ | |
136 case 1036: return "fr"; /* french - france */ | |
137 case 1031: return "de"; /* german - germany */ | |
138 case 1032: return "el"; /* greek */ | |
139 case 1037: return "he"; /* hebrew */ | |
140 case 1038: return "hu"; /* hungarian */ | |
141 case 1040: return "it"; /* italian - italy */ | |
142 case 1041: return "ja"; /* japanese */ | |
143 case 1042: return "ko"; /* korean */ | |
144 case 1063: return "lt"; /* lithuanian */ | |
145 case 1071: return "mk"; /* macedonian */ | |
146 case 1045: return "pl"; /* polish */ | |
147 case 2070: return "pt"; /* portuguese - portugal */ | |
148 case 1046: return "pt_BR"; /* portuguese - brazil */ | |
149 case 1048: return "ro"; /* romanian - romania */ | |
150 case 1049: return "ru"; /* russian - russia */ | |
151 case 2074: return "sr@Latn"; /* serbian - latin */ | |
152 case 3098: return "sr"; /* serbian - cyrillic */ | |
153 case 2052: return "zh_CN"; /* chinese - china (simple) */ | |
154 case 1051: return "sk"; /* slovak */ | |
155 case 1060: return "sl"; /* slovenian */ | |
156 case 1034: return "es"; /* spanish */ | |
157 case 1053: return "sv"; /* swedish */ | |
158 case 1054: return "th"; /* thai */ | |
159 case 1028: return "zh_TW"; /* chinese - taiwan (traditional) */ | |
160 case 1055: return "tr"; /* turkish */ | |
161 case 1058: return "uk"; /* ukrainian */ | |
162 default: | |
163 return NULL; | |
164 } | |
165 } | |
166 | |
167 /* Determine and set Gaim locale as follows (in order of priority): | |
168 - Check LANG env var | |
169 - Check NSIS Installer Language reg value | |
170 - Use default user locale | |
171 */ | |
172 static void wgaim_set_locale() { | |
173 HKEY hkey; | |
174 char* locale=NULL; | |
175 char envstr[25]; | |
176 LCID lcid; | |
177 | |
178 /* Check if user set LANG env var */ | |
179 if((locale = (char*)getenv("LANG"))) { | |
180 goto finish; | |
181 } | |
182 | |
183 /* Check reg key set at install time */ | |
184 if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, | |
185 "SOFTWARE\\gaim", | |
186 0, KEY_QUERY_VALUE, &hkey)) { | |
187 BYTE data[10]; | |
188 DWORD ds = 10; | |
189 if(ERROR_SUCCESS == RegQueryValueEx(hkey, "Installer Language", 0, NULL, (LPBYTE)&data, &ds)) { | |
190 if((locale = wgaim_lcid_to_posix(atoi(data)))) | |
191 goto finish; | |
192 } | |
193 } | |
194 | |
195 lcid = GetUserDefaultLCID(); | |
196 if((locale = wgaim_lcid_to_posix(lcid))) | |
197 goto finish; | |
198 | |
199 finish: | |
200 if(!locale) | |
201 locale = "en"; | |
202 | |
203 sprintf(envstr, "LANG=%s", locale); | |
204 putenv(envstr); | |
205 } | |
206 | |
133 | 207 |
134 #ifdef __GNUC__ | 208 #ifdef __GNUC__ |
135 # ifndef _stdcall | 209 # ifndef _stdcall |
136 # define _stdcall __attribute__((stdcall)) | 210 # define _stdcall __attribute__((stdcall)) |
137 # endif | 211 # endif |
147 char *point; | 221 char *point; |
148 HMODULE hmod; | 222 HMODULE hmod; |
149 | 223 |
150 /* If GAIM_NO_DLL_CHECK is set, don't run the dll check */ | 224 /* If GAIM_NO_DLL_CHECK is set, don't run the dll check */ |
151 if(!getenv("GAIM_NO_DLL_CHECK")) | 225 if(!getenv("GAIM_NO_DLL_CHECK")) |
152 run_dll_check(); | 226 run_dll_prep(); |
153 | 227 |
154 /* Load exception handler if we have it */ | 228 /* Load exception handler if we have it */ |
155 GetModuleFileName(NULL, gaimdir, MAX_PATH); | 229 GetModuleFileName(NULL, gaimdir, MAX_PATH); |
156 if((point=strstr(gaimdir, "gaim.exe"))) { | 230 if((point=strstr(gaimdir, "gaim.exe"))) { |
157 point[0] = '\0'; | 231 point[0] = '\0'; |
158 strcat(gaimdir, "exchndl.dll"); | 232 strcat(gaimdir, "exchndl.dll"); |
159 LoadLibrary(gaimdir); | 233 LoadLibrary(gaimdir); |
160 } | 234 } |
235 | |
236 /* Set Gaim locale */ | |
237 wgaim_set_locale(); | |
161 | 238 |
162 /* Now we are ready for Gaim .. */ | 239 /* Now we are ready for Gaim .. */ |
163 if((hmod=LoadLibrary("gaim.dll"))) { | 240 if((hmod=LoadLibrary("gaim.dll"))) { |
164 gaim_main = (void*)GetProcAddress(hmod, "gaim_main"); | 241 gaim_main = (void*)GetProcAddress(hmod, "gaim_main"); |
165 } | 242 } |