diff options
author | LRN <lrn1986@gmail.com> | 2012-10-30 21:08:47 +0000 |
---|---|---|
committer | LRN <lrn1986@gmail.com> | 2012-10-30 21:08:47 +0000 |
commit | 60e1efa23b8590f4579bb2aa4937b494f40ac5cc (patch) | |
tree | da5fa74788af12f1d5e47cc910c9c1337077b0d3 | |
parent | f74b67b30e97b871ae37575b64179668b15abab0 (diff) | |
download | gnunet-60e1efa23b8590f4579bb2aa4937b494f40ac5cc.tar.gz gnunet-60e1efa23b8590f4579bb2aa4937b494f40ac5cc.zip |
W32: Fix get_path_from_module_filename()
-rw-r--r-- | src/util/os_installation.c | 104 |
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 | |||
116 | static 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 | */ | ||
123 | BOOL WINAPI | ||
124 | DllMain (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 () | |||
119 | static char * | 146 | static char * |
120 | get_path_from_module_filename () | 147 | get_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 | ||