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)&gtkpath, &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)&gtkpath, &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) &regval,
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 }