aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLRN <lrn1986@gmail.com>2012-10-30 21:08:47 +0000
committerLRN <lrn1986@gmail.com>2012-10-30 21:08:47 +0000
commit60e1efa23b8590f4579bb2aa4937b494f40ac5cc (patch)
treeda5fa74788af12f1d5e47cc910c9c1337077b0d3
parentf74b67b30e97b871ae37575b64179668b15abab0 (diff)
downloadgnunet-60e1efa23b8590f4579bb2aa4937b494f40ac5cc.tar.gz
gnunet-60e1efa23b8590f4579bb2aa4937b494f40ac5cc.zip
W32: Fix get_path_from_module_filename()
-rw-r--r--src/util/os_installation.c104
1 files changed, 95 insertions, 9 deletions
diff --git a/src/util/os_installation.c b/src/util/os_installation.c
index 43feba87b..c520c6f79 100644
--- a/src/util/os_installation.c
+++ b/src/util/os_installation.c
@@ -27,6 +27,7 @@
27#include <stdlib.h> 27#include <stdlib.h>
28#include <string.h> 28#include <string.h>
29#include <unistd.h> 29#include <unistd.h>
30#include <unistr.h> /* for u16_to_u8 */
30 31
31#include "platform.h" 32#include "platform.h"
32#include "gnunet_common.h" 33#include "gnunet_common.h"
@@ -111,6 +112,32 @@ get_path_from_proc_exe ()
111#endif 112#endif
112 113
113#if WINDOWS 114#if WINDOWS
115
116static HINSTANCE dll_instance;
117
118
119/* GNUNET_util_cl_init() in common_logging.c is preferred.
120 * This function is only for thread-local storage (not used in GNUnet)
121 * and hInstance saving.
122 */
123BOOL WINAPI
124DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
125{
126 switch (fdwReason)
127 {
128 case DLL_PROCESS_ATTACH:
129 dll_instance = hinstDLL;
130 break;
131 case DLL_THREAD_ATTACH:
132 break;
133 case DLL_THREAD_DETACH:
134 break;
135 case DLL_PROCESS_DETACH:
136 break;
137 }
138 return TRUE;
139}
140
114/** 141/**
115 * Try to determine path with win32-specific function 142 * Try to determine path with win32-specific function
116 * 143 *
@@ -119,19 +146,78 @@ get_path_from_proc_exe ()
119static char * 146static char *
120get_path_from_module_filename () 147get_path_from_module_filename ()
121{ 148{
122 wchar_t path[4097]; 149 size_t pathlen = 512;
123 char upath[4097]; 150 DWORD real_pathlen;
124 wchar_t *idx; 151 wchar_t *idx;
125 152 wchar_t *modulepath = NULL;
126 GetModuleFileNameW (NULL, path, sizeof (path) - 1); 153 char *upath;
127 idx = path + wcslen (path); 154 uint8_t *u8_string;
128 while ((idx > path) && (*idx != L'\\') && (*idx != L'/')) 155 size_t u8_string_length;
156
157 /* This braindead function won't tell us how much space it needs, so
158 * we start at 1024 and double the space up if it doesn't fit, until
159 * it fits, or we exceed the threshold.
160 */
161 do
162 {
163 pathlen = pathlen * 2;
164 modulepath = GNUNET_realloc (modulepath, pathlen * sizeof (wchar_t));
165 SetLastError (0);
166 real_pathlen = GetModuleFileNameW (dll_instance, modulepath, pathlen * sizeof (wchar_t));
167 } while (real_pathlen >= pathlen && pathlen < 16*1024);
168 if (real_pathlen >= pathlen)
169 GNUNET_abort ();
170 /* To be safe */
171 modulepath[real_pathlen] = '\0';
172
173 idx = modulepath + real_pathlen;
174 while ((idx > modulepath) && (*idx != L'\\') && (*idx != L'/'))
129 idx--; 175 idx--;
130 *idx = L'\0'; 176 *idx = L'\0';
131 upath[0] = '\0';
132 WideCharToMultiByte (CP_UTF8, 0, path, -1, upath, 4097, NULL, NULL);
133 177
134 return GNUNET_strdup (upath); 178 /* Now modulepath holds full path to the directory where libgnunetutil is.
179 * This directory should look like <GNUNET_PREFIX>/bin or <GNUNET_PREFIX>.
180 */
181 if (wcschr (modulepath, L'/') || wcschr (modulepath, L'\\'))
182 {
183 /* At least one directory component (i.e. we're not in a root directory) */
184 wchar_t *dirname = idx;
185 while ((dirname > modulepath) && (*dirname != L'\\') && (*dirname != L'/'))
186 dirname--;
187 *dirname = L'\0';
188 if (dirname > modulepath)
189 {
190 dirname++;
191 /* Now modulepath holds full path to the parent directory of the directory
192 * where libgnunetutil is.
193 * dirname holds the name of the directory where libgnunetutil is.
194 */
195 if (wcsicmp (dirname, L"bin") == 0)
196 {
197 /* pass */
198 }
199 else
200 {
201 /* Roll back our changes to modulepath */
202 dirname--;
203 *dirname = L'/';
204 }
205 }
206 }
207
208 /* modulepath is GNUNET_PREFIX */
209 u8_string = u16_to_u8 (modulepath, wcslen (modulepath), NULL, &u8_string_length);
210 if (NULL == u8_string)
211 GNUNET_abort ();
212
213 upath = GNUNET_malloc (u8_string_length + 1);
214 memcpy (upath, u8_string, u8_string_length);
215 upath[u8_string_length] = '\0';
216
217 free (u8_string);
218 GNUNET_free (modulepath);
219
220 return upath;
135} 221}
136#endif 222#endif
137 223