comparison gtk/win32/win32dep.c @ 14191:009db0b357b5

This is a hand-crafted commit to migrate across subversion revisions 16854:16861, due to some vagaries of the way the original renames were done. Witness that monotone can do in one revision what svn had to spread across several.
author Ethan Blanton <elb@pidgin.im>
date Sat, 16 Dec 2006 04:59:55 +0000
parents
children
comparison
equal deleted inserted replaced
14190:366be2ce35a7 14191:009db0b357b5
1 /*
2 * gaim
3 *
4 * File: win32dep.c
5 * Date: June, 2002
6 * Description: Windows dependant code for Gaim
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 *
24 */
25 #define _WIN32_IE 0x500
26 #include <windows.h>
27 #include <io.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <winuser.h>
31
32 #include <glib.h>
33 #include <glib/gstdio.h>
34
35 #include "gaim.h"
36 #include "debug.h"
37 #include "notify.h"
38
39 #include "resource.h"
40 #include "idletrack.h"
41 #include "zlib.h"
42 #include "untar.h"
43
44 #include <libintl.h>
45
46 #include "win32dep.h"
47
48 /*
49 * DEFINES & MACROS
50 */
51 #define _(x) gettext(x)
52
53 /*
54 * DATA STRUCTS
55 */
56
57 /* For shfolder.dll */
58 typedef HRESULT (CALLBACK* LPFNSHGETFOLDERPATHA)(HWND, int, HANDLE, DWORD, LPSTR);
59 typedef HRESULT (CALLBACK* LPFNSHGETFOLDERPATHW)(HWND, int, HANDLE, DWORD, LPWSTR);
60
61 /*
62 * LOCALS
63 */
64 static char *app_data_dir, *install_dir, *lib_dir, *locale_dir;
65
66 /*
67 * GLOBALS
68 */
69 HINSTANCE gaimexe_hInstance = 0;
70 HINSTANCE gaimdll_hInstance = 0;
71
72 /*
73 * PROTOS
74 */
75
76 FARPROC wgaim_find_and_loadproc(char*, char*);
77 char* wgaim_data_dir(void);
78
79 /*
80 * STATIC CODE
81 */
82
83 static void wgaim_debug_print(GaimDebugLevel level, const char *category, const char *format, va_list args) {
84 char *str = NULL;
85 if (args != NULL) {
86 str = g_strdup_vprintf(format, args);
87 } else {
88 str = g_strdup(format);
89 }
90 printf("%s%s%s", category ? category : "", category ? ": " : "", str);
91 g_free(str);
92 }
93
94 static GaimDebugUiOps ops = {
95 wgaim_debug_print
96 };
97
98 /*
99 * PUBLIC CODE
100 */
101
102 HINSTANCE wgaim_hinstance(void) {
103 return gaimexe_hInstance;
104 }
105
106 /* Escape windows dir separators. This is needed when paths are saved,
107 and on being read back have their '\' chars used as an escape char.
108 Returns an allocated string which needs to be freed.
109 */
110 char* wgaim_escape_dirsep(char* filename) {
111 int sepcount = 0;
112 char* ret = NULL;
113 int cnt = 0;
114
115 ret = filename;
116 while(*ret) {
117 if(*ret == '\\')
118 sepcount++;
119 ret++;
120 }
121 ret = g_malloc0(strlen(filename) + sepcount + 1);
122 while(*filename) {
123 ret[cnt] = *filename;
124 if(*filename == '\\')
125 ret[++cnt] = '\\';
126 filename++;
127 cnt++;
128 }
129 ret[cnt] = '\0';
130 return ret;
131 }
132
133 /* Determine whether the specified dll contains the specified procedure.
134 If so, load it (if not already loaded). */
135 FARPROC wgaim_find_and_loadproc(char* dllname, char* procedure) {
136 HMODULE hmod;
137 BOOL did_load = FALSE;
138 FARPROC proc = 0;
139
140 if(!(hmod = GetModuleHandle(dllname))) {
141 gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "%s not already loaded; loading it...\n", dllname);
142 if(!(hmod = LoadLibrary(dllname))) {
143 gaim_debug(GAIM_DEBUG_ERROR, "wgaim", "Could not load: %s\n", dllname);
144 return NULL;
145 }
146 else
147 did_load = TRUE;
148 }
149
150 if((proc = GetProcAddress(hmod, procedure))) {
151 gaim_debug(GAIM_DEBUG_INFO, "wgaim", "This version of %s contains %s\n",
152 dllname, procedure);
153 return proc;
154 }
155 else {
156 gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "Function %s not found in dll %s\n",
157 procedure, dllname);
158 if(did_load) {
159 /* unload dll */
160 FreeLibrary(hmod);
161 }
162 return NULL;
163 }
164 }
165
166 /* Determine Gaim Paths during Runtime */
167
168 /* Get paths to special Windows folders. */
169 char *wgaim_get_special_folder(int folder_type) {
170 static LPFNSHGETFOLDERPATHA MySHGetFolderPathA = NULL;
171 static LPFNSHGETFOLDERPATHW MySHGetFolderPathW = NULL;
172 char *retval = NULL;
173
174 if (!MySHGetFolderPathW) {
175 MySHGetFolderPathW = (LPFNSHGETFOLDERPATHW)
176 wgaim_find_and_loadproc("shfolder.dll", "SHGetFolderPathW");
177 }
178
179 if (MySHGetFolderPathW) {
180 wchar_t utf_16_dir[MAX_PATH + 1];
181
182 if (SUCCEEDED(MySHGetFolderPathW(NULL, folder_type, NULL,
183 SHGFP_TYPE_CURRENT, utf_16_dir))) {
184 retval = g_utf16_to_utf8(utf_16_dir, -1, NULL, NULL, NULL);
185 }
186 }
187
188 if (!retval) {
189 if (!MySHGetFolderPathA) {
190 MySHGetFolderPathA = (LPFNSHGETFOLDERPATHA)
191 wgaim_find_and_loadproc("shfolder.dll", "SHGetFolderPathA");
192 }
193 if (MySHGetFolderPathA) {
194 char locale_dir[MAX_PATH + 1];
195
196 if (SUCCEEDED(MySHGetFolderPathA(NULL, folder_type, NULL,
197 SHGFP_TYPE_CURRENT, locale_dir))) {
198 retval = g_locale_to_utf8(locale_dir, -1, NULL, NULL, NULL);
199 }
200 }
201 }
202
203 return retval;
204 }
205
206 char* wgaim_install_dir(void) {
207 static gboolean initialized = FALSE;
208
209 if (!initialized) {
210 char *tmp = NULL;
211 if (G_WIN32_HAVE_WIDECHAR_API()) {
212 wchar_t winstall_dir[MAXPATHLEN];
213 if (GetModuleFileNameW(NULL, winstall_dir,
214 MAXPATHLEN) > 0) {
215 tmp = g_utf16_to_utf8(winstall_dir, -1,
216 NULL, NULL, NULL);
217 }
218 } else {
219 gchar cpinstall_dir[MAXPATHLEN];
220 if (GetModuleFileNameA(NULL, cpinstall_dir,
221 MAXPATHLEN) > 0) {
222 tmp = g_locale_to_utf8(cpinstall_dir,
223 -1, NULL, NULL, NULL);
224 }
225 }
226
227 if (tmp == NULL) {
228 tmp = g_win32_error_message(GetLastError());
229 gaim_debug(GAIM_DEBUG_ERROR, "wgaim",
230 "GetModuleFileName error: %s\n", tmp);
231 g_free(tmp);
232 return NULL;
233 } else {
234 install_dir = g_path_get_dirname(tmp);
235 g_free(tmp);
236 initialized = TRUE;
237 }
238 }
239
240 return install_dir;
241 }
242
243 char* wgaim_lib_dir(void) {
244 static gboolean initialized = FALSE;
245
246 if (!initialized) {
247 char *inst_dir = wgaim_install_dir();
248 if (inst_dir != NULL) {
249 lib_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "plugins", inst_dir);
250 initialized = TRUE;
251 } else {
252 return NULL;
253 }
254 }
255
256 return lib_dir;
257 }
258
259 char* wgaim_locale_dir(void) {
260 static gboolean initialized = FALSE;
261
262 if (!initialized) {
263 char *inst_dir = wgaim_install_dir();
264 if (inst_dir != NULL) {
265 locale_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "locale", inst_dir);
266 initialized = TRUE;
267 } else {
268 return NULL;
269 }
270 }
271
272 return locale_dir;
273 }
274
275 char* wgaim_data_dir(void) {
276 return app_data_dir;
277 }
278
279 /* Miscellaneous */
280
281 gboolean wgaim_read_reg_string(HKEY key, char* sub_key, char* val_name, LPBYTE data, LPDWORD data_len) {
282 HKEY hkey;
283 gboolean ret = FALSE;
284
285 if(ERROR_SUCCESS == RegOpenKeyEx(key, sub_key, 0, KEY_QUERY_VALUE,
286 &hkey)) {
287 if(ERROR_SUCCESS == RegQueryValueEx(hkey, val_name, 0, NULL,
288 data, data_len))
289 ret = TRUE;
290 RegCloseKey(key);
291 }
292 return ret;
293 }
294
295 int wgaim_gz_decompress(const char* in, const char* out) {
296 gzFile fin;
297 FILE *fout;
298 char buf[1024];
299 int ret;
300
301 if((fin = gzopen(in, "rb"))) {
302 if(!(fout = g_fopen(out, "wb"))) {
303 gaim_debug(GAIM_DEBUG_ERROR, "wgaim_gz_decompress", "Error opening file: %s\n", out);
304 gzclose(fin);
305 return 0;
306 }
307 }
308 else {
309 gaim_debug(GAIM_DEBUG_ERROR, "wgaim_gz_decompress", "gzopen failed to open: %s\n", in);
310 return 0;
311 }
312
313 while((ret = gzread(fin, buf, 1024))) {
314 if(fwrite(buf, 1, ret, fout) < ret) {
315 gaim_debug(GAIM_DEBUG_ERROR, "wgaim_gz_decompress", "Error writing %d bytes to file\n", ret);
316 gzclose(fin);
317 fclose(fout);
318 return 0;
319 }
320 }
321 fclose(fout);
322 gzclose(fin);
323
324 if(ret < 0) {
325 gaim_debug(GAIM_DEBUG_ERROR, "wgaim_gz_decompress", "gzread failed while reading: %s\n", in);
326 return 0;
327 }
328
329 return 1;
330 }
331
332 int wgaim_gz_untar(const char* filename, const char* destdir) {
333 char tmpfile[_MAX_PATH];
334 char template[]="wgaimXXXXXX";
335
336 sprintf(tmpfile, "%s%s%s", g_get_tmp_dir(), G_DIR_SEPARATOR_S, _mktemp(template));
337 if(wgaim_gz_decompress(filename, tmpfile)) {
338 int ret;
339 if(untar(tmpfile, destdir, UNTAR_FORCE | UNTAR_QUIET))
340 ret = 1;
341 else {
342 gaim_debug(GAIM_DEBUG_ERROR, "wgaim_gz_untar", "Failure untaring %s\n", tmpfile);
343 ret = 0;
344 }
345 g_unlink(tmpfile);
346 return ret;
347 }
348 else {
349 gaim_debug(GAIM_DEBUG_ERROR, "wgaim_gz_untar", "Failed to gz decompress %s\n", filename);
350 return 0;
351 }
352 }
353
354 void wgaim_notify_uri(const char *uri) {
355
356 /* We'll allow whatever URI schemes are supported by the
357 * default http browser.
358 */
359
360 if (G_WIN32_HAVE_WIDECHAR_API()) {
361 SHELLEXECUTEINFOW wsinfo;
362 wchar_t *w_uri;
363
364 w_uri = g_utf8_to_utf16(uri, -1, NULL, NULL, NULL);
365
366 memset(&wsinfo, 0, sizeof(wsinfo));
367 wsinfo.cbSize = sizeof(wsinfo);
368 wsinfo.fMask = SEE_MASK_CLASSNAME;
369 wsinfo.lpVerb = L"open";
370 wsinfo.lpFile = w_uri;
371 wsinfo.nShow = SW_SHOWNORMAL;
372 wsinfo.lpClass = L"http";
373
374 gaim_debug(GAIM_DEBUG_INFO, "wgaim_notify_uri", "The wide uri is %s\n", uri);
375 if(!ShellExecuteExW(&wsinfo))
376 gaim_debug_error("wgaim", "Error opening URI: %s error: %d\n",
377 uri, (int) wsinfo.hInstApp);
378
379 g_free(w_uri);
380 } else {
381 SHELLEXECUTEINFOA sinfo;
382 gchar *locale_uri;
383
384 locale_uri = g_locale_from_utf8(uri, -1, NULL, NULL, NULL);
385
386 memset(&sinfo, 0, sizeof(sinfo));
387 sinfo.cbSize = sizeof(sinfo);
388 sinfo.fMask = SEE_MASK_CLASSNAME;
389 sinfo.lpVerb = "open";
390 sinfo.lpFile = locale_uri;
391 sinfo.nShow = SW_SHOWNORMAL;
392 sinfo.lpClass = "http";
393
394 if(!ShellExecuteExA(&sinfo))
395 gaim_debug_error("wgaim", "Error opening URI: %s error: %d\n",
396 uri, (int) sinfo.hInstApp);
397
398 g_free(locale_uri);
399 }
400 }
401
402 void wgaim_init(HINSTANCE hint) {
403 WORD wVersionRequested;
404 WSADATA wsaData;
405 const char *perlenv;
406 char *newenv;
407
408 gaim_debug_set_ui_ops(&ops);
409 gaim_debug_info("wgaim", "wgaim_init start\n");
410
411 gaim_debug_info("wgaim", "Glib:%u.%u.%u\n",
412 glib_major_version, glib_minor_version, glib_micro_version);
413
414 gaimexe_hInstance = hint;
415
416 /* Winsock init */
417 wVersionRequested = MAKEWORD(2, 2);
418 WSAStartup(wVersionRequested, &wsaData);
419
420 /* Confirm that the winsock DLL supports 2.2 */
421 /* Note that if the DLL supports versions greater than
422 2.2 in addition to 2.2, it will still return 2.2 in
423 wVersion since that is the version we requested. */
424 if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
425 gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "Could not find a usable WinSock DLL. Oh well.\n");
426 WSACleanup();
427 }
428
429 /* Set Environmental Variables */
430 /* Tell perl where to find Gaim's perl modules */
431 perlenv = g_getenv("PERL5LIB");
432 newenv = g_strdup_printf("PERL5LIB=%s%s%s" G_DIR_SEPARATOR_S "perlmod;",
433 perlenv ? perlenv : "",
434 perlenv ? ";" : "",
435 wgaim_install_dir());
436 if (putenv(newenv) < 0)
437 gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "putenv failed\n");
438 g_free(newenv);
439
440 /* Set app data dir, used by gaim_home_dir */
441 newenv = (char*) g_getenv("GAIMHOME");
442 if (newenv) {
443 app_data_dir = g_strdup(newenv);
444 } else {
445 app_data_dir = wgaim_get_special_folder(CSIDL_APPDATA);
446 if (!app_data_dir) {
447 app_data_dir = g_strdup("C:");
448 }
449 }
450
451 gaim_debug(GAIM_DEBUG_INFO, "wgaim", "Gaim settings dir: %s\n", app_data_dir);
452
453 /* IdleTracker Initialization */
454 if(!wgaim_set_idlehooks())
455 gaim_debug(GAIM_DEBUG_ERROR, "wgaim", "Failed to initialize idle tracker\n");
456
457 gaim_debug(GAIM_DEBUG_INFO, "wgaim", "wgaim_init end\n");
458 }
459
460 /* Windows Cleanup */
461
462 void wgaim_cleanup(void) {
463 gaim_debug(GAIM_DEBUG_INFO, "wgaim", "wgaim_cleanup\n");
464
465 /* winsock cleanup */
466 WSACleanup();
467
468 /* Idle tracker cleanup */
469 wgaim_remove_idlehooks();
470
471 g_free(app_data_dir);
472 }
473
474 /* DLL initializer */
475 BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) {
476 gaimdll_hInstance = hinstDLL;
477 return TRUE;
478 }