]>
Commit | Line | Data |
---|---|---|
0f113f3e MC |
1 | /* |
2 | * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project | |
3 | * 2000. | |
8f4fac7f GT |
4 | */ |
5 | /* ==================================================================== | |
6 | * Copyright (c) 2000 The OpenSSL Project. All rights reserved. | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * | |
12 | * 1. Redistributions of source code must retain the above copyright | |
0f113f3e | 13 | * notice, this list of conditions and the following disclaimer. |
8f4fac7f GT |
14 | * |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in | |
17 | * the documentation and/or other materials provided with the | |
18 | * distribution. | |
19 | * | |
20 | * 3. All advertising materials mentioning features or use of this | |
21 | * software must display the following acknowledgment: | |
22 | * "This product includes software developed by the OpenSSL Project | |
23 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
24 | * | |
25 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
26 | * endorse or promote products derived from this software without | |
27 | * prior written permission. For written permission, please contact | |
28 | * licensing@OpenSSL.org. | |
29 | * | |
30 | * 5. Products derived from this software may not be called "OpenSSL" | |
31 | * nor may "OpenSSL" appear in their names without prior written | |
32 | * permission of the OpenSSL Project. | |
33 | * | |
34 | * 6. Redistributions of any form whatsoever must retain the following | |
35 | * acknowledgment: | |
36 | * "This product includes software developed by the OpenSSL Project | |
37 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
38 | * | |
39 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
40 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
41 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
42 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
43 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
44 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
45 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
46 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
48 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
49 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
50 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
51 | * ==================================================================== | |
52 | * | |
53 | * This product includes cryptographic software written by Eric Young | |
54 | * (eay@cryptsoft.com). This product includes software written by Tim | |
55 | * Hudson (tjh@cryptsoft.com). | |
56 | * | |
57 | */ | |
58 | ||
73decf59 | 59 | #include "dso_locl.h" |
8f4fac7f | 60 | |
38186bfd | 61 | #if defined(DSO_WIN32) |
8f4fac7f | 62 | |
0f113f3e MC |
63 | # ifdef _WIN32_WCE |
64 | # if _WIN32_WCE < 300 | |
65 | static FARPROC GetProcAddressA(HMODULE hModule, LPCSTR lpProcName) | |
66 | { | |
67 | WCHAR lpProcNameW[64]; | |
68 | int i; | |
69 | ||
70 | for (i = 0; lpProcName[i] && i < 64; i++) | |
71 | lpProcNameW[i] = (WCHAR)lpProcName[i]; | |
72 | if (i == 64) | |
73 | return NULL; | |
74 | lpProcNameW[i] = 0; | |
75 | ||
76 | return GetProcAddressW(hModule, lpProcNameW); | |
77 | } | |
78 | # endif | |
79 | # undef GetProcAddress | |
80 | # define GetProcAddress GetProcAddressA | |
b37fb16d | 81 | |
19bd66fe | 82 | static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName) |
0f113f3e MC |
83 | { |
84 | WCHAR *fnamw; | |
85 | size_t len_0 = strlen(lpLibFileName) + 1, i; | |
86 | ||
87 | # ifdef _MSC_VER | |
88 | fnamw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR)); | |
89 | # else | |
90 | fnamw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); | |
91 | # endif | |
92 | if (fnamw == NULL) { | |
93 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); | |
94 | return NULL; | |
95 | } | |
96 | # if defined(_WIN32_WCE) && _WIN32_WCE>=101 | |
97 | if (!MultiByteToWideChar(CP_ACP, 0, lpLibFileName, len_0, fnamw, len_0)) | |
98 | # endif | |
99 | for (i = 0; i < len_0; i++) | |
100 | fnamw[i] = (WCHAR)lpLibFileName[i]; | |
101 | ||
102 | return LoadLibraryW(fnamw); | |
103 | } | |
104 | # endif | |
83e68987 | 105 | |
b9e63915 | 106 | /* Part of the hack in "win32_load" ... */ |
0f113f3e | 107 | # define DSO_MAX_TRANSLATED_SIZE 256 |
b9e63915 | 108 | |
51c8dc37 | 109 | static int win32_load(DSO *dso); |
8f4fac7f | 110 | static int win32_unload(DSO *dso); |
e9a68cfb GT |
111 | static void *win32_bind_var(DSO *dso, const char *symname); |
112 | static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname); | |
51c8dc37 | 113 | static char *win32_name_converter(DSO *dso, const char *filename); |
cbecb3ac | 114 | static char *win32_merger(DSO *dso, const char *filespec1, |
0f113f3e MC |
115 | const char *filespec2); |
116 | static int win32_pathbyaddr(void *addr, char *path, int sz); | |
c6cb42e4 | 117 | static void *win32_globallookup(const char *name); |
8f4fac7f | 118 | |
74e3931f DSH |
119 | static const char *openssl_strnchr(const char *string, int c, size_t len); |
120 | ||
8f4fac7f | 121 | static DSO_METHOD dso_meth_win32 = { |
0f113f3e MC |
122 | "OpenSSL 'win32' shared library method", |
123 | win32_load, | |
124 | win32_unload, | |
125 | win32_bind_var, | |
126 | win32_bind_func, | |
0f113f3e MC |
127 | NULL, /* ctrl */ |
128 | win32_name_converter, | |
129 | win32_merger, | |
130 | NULL, /* init */ | |
131 | NULL, /* finish */ | |
132 | win32_pathbyaddr, | |
133 | win32_globallookup | |
134 | }; | |
8f4fac7f | 135 | |
38186bfd | 136 | DSO_METHOD *DSO_METHOD_openssl(void) |
0f113f3e | 137 | { |
38186bfd | 138 | return &dso_meth_win32; |
0f113f3e | 139 | } |
8f4fac7f | 140 | |
0f113f3e MC |
141 | /* |
142 | * For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to | |
143 | * the handle (HINSTANCE) returned from LoadLibrary(), and copied. | |
8f4fac7f GT |
144 | */ |
145 | ||
51c8dc37 | 146 | static int win32_load(DSO *dso) |
0f113f3e MC |
147 | { |
148 | HINSTANCE h = NULL, *p = NULL; | |
149 | /* See applicable comments from dso_dl.c */ | |
150 | char *filename = DSO_convert_filename(dso, NULL); | |
151 | ||
152 | if (filename == NULL) { | |
153 | DSOerr(DSO_F_WIN32_LOAD, DSO_R_NO_FILENAME); | |
154 | goto err; | |
155 | } | |
156 | h = LoadLibraryA(filename); | |
157 | if (h == NULL) { | |
158 | DSOerr(DSO_F_WIN32_LOAD, DSO_R_LOAD_FAILED); | |
159 | ERR_add_error_data(3, "filename(", filename, ")"); | |
160 | goto err; | |
161 | } | |
b4faea50 | 162 | p = OPENSSL_malloc(sizeof(*p)); |
0f113f3e MC |
163 | if (p == NULL) { |
164 | DSOerr(DSO_F_WIN32_LOAD, ERR_R_MALLOC_FAILURE); | |
165 | goto err; | |
166 | } | |
167 | *p = h; | |
168 | if (!sk_void_push(dso->meth_data, p)) { | |
169 | DSOerr(DSO_F_WIN32_LOAD, DSO_R_STACK_ERROR); | |
170 | goto err; | |
171 | } | |
172 | /* Success */ | |
173 | dso->loaded_filename = filename; | |
174 | return (1); | |
175 | err: | |
176 | /* Cleanup ! */ | |
b548a1f1 RS |
177 | OPENSSL_free(filename); |
178 | OPENSSL_free(p); | |
0f113f3e MC |
179 | if (h != NULL) |
180 | FreeLibrary(h); | |
181 | return (0); | |
182 | } | |
8f4fac7f GT |
183 | |
184 | static int win32_unload(DSO *dso) | |
0f113f3e MC |
185 | { |
186 | HINSTANCE *p; | |
187 | if (dso == NULL) { | |
188 | DSOerr(DSO_F_WIN32_UNLOAD, ERR_R_PASSED_NULL_PARAMETER); | |
189 | return (0); | |
190 | } | |
191 | if (sk_void_num(dso->meth_data) < 1) | |
192 | return (1); | |
193 | p = sk_void_pop(dso->meth_data); | |
194 | if (p == NULL) { | |
195 | DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_NULL_HANDLE); | |
196 | return (0); | |
197 | } | |
198 | if (!FreeLibrary(*p)) { | |
199 | DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_UNLOAD_FAILED); | |
200 | /* | |
201 | * We should push the value back onto the stack in case of a retry. | |
202 | */ | |
203 | sk_void_push(dso->meth_data, p); | |
204 | return (0); | |
205 | } | |
206 | /* Cleanup */ | |
207 | OPENSSL_free(p); | |
208 | return (1); | |
209 | } | |
210 | ||
211 | /* | |
212 | * Using GetProcAddress for variables? TODO: Check this out in the Win32 API | |
213 | * docs, there's probably a variant for variables. | |
214 | */ | |
e9a68cfb | 215 | static void *win32_bind_var(DSO *dso, const char *symname) |
0f113f3e MC |
216 | { |
217 | HINSTANCE *ptr; | |
156561b0 AP |
218 | union { |
219 | void *p; | |
220 | FARPROC f; | |
221 | } sym; | |
0f113f3e MC |
222 | |
223 | if ((dso == NULL) || (symname == NULL)) { | |
224 | DSOerr(DSO_F_WIN32_BIND_VAR, ERR_R_PASSED_NULL_PARAMETER); | |
225 | return (NULL); | |
226 | } | |
227 | if (sk_void_num(dso->meth_data) < 1) { | |
228 | DSOerr(DSO_F_WIN32_BIND_VAR, DSO_R_STACK_ERROR); | |
229 | return (NULL); | |
230 | } | |
231 | ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1); | |
232 | if (ptr == NULL) { | |
233 | DSOerr(DSO_F_WIN32_BIND_VAR, DSO_R_NULL_HANDLE); | |
234 | return (NULL); | |
235 | } | |
156561b0 AP |
236 | sym.f = GetProcAddress(*ptr, symname); |
237 | if (sym.p == NULL) { | |
0f113f3e MC |
238 | DSOerr(DSO_F_WIN32_BIND_VAR, DSO_R_SYM_FAILURE); |
239 | ERR_add_error_data(3, "symname(", symname, ")"); | |
240 | return (NULL); | |
241 | } | |
156561b0 | 242 | return (sym.p); |
0f113f3e | 243 | } |
e9a68cfb GT |
244 | |
245 | static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname) | |
0f113f3e MC |
246 | { |
247 | HINSTANCE *ptr; | |
156561b0 AP |
248 | union { |
249 | void *p; | |
250 | FARPROC f; | |
251 | } sym; | |
0f113f3e MC |
252 | |
253 | if ((dso == NULL) || (symname == NULL)) { | |
254 | DSOerr(DSO_F_WIN32_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER); | |
255 | return (NULL); | |
256 | } | |
257 | if (sk_void_num(dso->meth_data) < 1) { | |
258 | DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_STACK_ERROR); | |
259 | return (NULL); | |
260 | } | |
261 | ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1); | |
262 | if (ptr == NULL) { | |
263 | DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_NULL_HANDLE); | |
264 | return (NULL); | |
265 | } | |
156561b0 AP |
266 | sym.f = GetProcAddress(*ptr, symname); |
267 | if (sym.p == NULL) { | |
0f113f3e MC |
268 | DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_SYM_FAILURE); |
269 | ERR_add_error_data(3, "symname(", symname, ")"); | |
270 | return (NULL); | |
271 | } | |
156561b0 | 272 | return ((DSO_FUNC_TYPE)sym.f); |
0f113f3e MC |
273 | } |
274 | ||
275 | struct file_st { | |
276 | const char *node; | |
277 | int nodelen; | |
278 | const char *device; | |
279 | int devicelen; | |
280 | const char *predir; | |
281 | int predirlen; | |
282 | const char *dir; | |
283 | int dirlen; | |
284 | const char *file; | |
285 | int filelen; | |
286 | }; | |
cbecb3ac RL |
287 | |
288 | static struct file_st *win32_splitter(DSO *dso, const char *filename, | |
0f113f3e MC |
289 | int assume_last_is_dir) |
290 | { | |
291 | struct file_st *result = NULL; | |
292 | enum { IN_NODE, IN_DEVICE, IN_FILE } position; | |
293 | const char *start = filename; | |
294 | char last; | |
295 | ||
296 | if (!filename) { | |
297 | DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_NO_FILENAME); | |
298 | /* | |
299 | * goto err; | |
300 | */ | |
301 | return (NULL); | |
302 | } | |
303 | ||
b51bce94 | 304 | result = OPENSSL_zalloc(sizeof(*result)); |
0f113f3e MC |
305 | if (result == NULL) { |
306 | DSOerr(DSO_F_WIN32_SPLITTER, ERR_R_MALLOC_FAILURE); | |
307 | return (NULL); | |
308 | } | |
309 | ||
0f113f3e MC |
310 | position = IN_DEVICE; |
311 | ||
312 | if ((filename[0] == '\\' && filename[1] == '\\') | |
313 | || (filename[0] == '/' && filename[1] == '/')) { | |
314 | position = IN_NODE; | |
315 | filename += 2; | |
316 | start = filename; | |
317 | result->node = start; | |
318 | } | |
319 | ||
320 | do { | |
321 | last = filename[0]; | |
322 | switch (last) { | |
323 | case ':': | |
324 | if (position != IN_DEVICE) { | |
325 | DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_INCORRECT_FILE_SYNTAX); | |
326 | /* | |
327 | * goto err; | |
328 | */ | |
329 | OPENSSL_free(result); | |
330 | return (NULL); | |
331 | } | |
332 | result->device = start; | |
333 | result->devicelen = (int)(filename - start); | |
334 | position = IN_FILE; | |
335 | start = ++filename; | |
336 | result->dir = start; | |
337 | break; | |
338 | case '\\': | |
339 | case '/': | |
340 | if (position == IN_NODE) { | |
341 | result->nodelen = (int)(filename - start); | |
342 | position = IN_FILE; | |
343 | start = ++filename; | |
344 | result->dir = start; | |
345 | } else if (position == IN_DEVICE) { | |
346 | position = IN_FILE; | |
347 | filename++; | |
348 | result->dir = start; | |
349 | result->dirlen = (int)(filename - start); | |
350 | start = filename; | |
351 | } else { | |
352 | filename++; | |
353 | result->dirlen += (int)(filename - start); | |
354 | start = filename; | |
355 | } | |
356 | break; | |
357 | case '\0': | |
358 | if (position == IN_NODE) { | |
359 | result->nodelen = (int)(filename - start); | |
360 | } else { | |
361 | if (filename - start > 0) { | |
362 | if (assume_last_is_dir) { | |
363 | if (position == IN_DEVICE) { | |
364 | result->dir = start; | |
365 | result->dirlen = 0; | |
366 | } | |
367 | result->dirlen += (int)(filename - start); | |
368 | } else { | |
369 | result->file = start; | |
370 | result->filelen = (int)(filename - start); | |
371 | } | |
372 | } | |
373 | } | |
374 | break; | |
375 | default: | |
376 | filename++; | |
377 | break; | |
378 | } | |
379 | } | |
380 | while (last); | |
381 | ||
382 | if (!result->nodelen) | |
383 | result->node = NULL; | |
384 | if (!result->devicelen) | |
385 | result->device = NULL; | |
386 | if (!result->dirlen) | |
387 | result->dir = NULL; | |
388 | if (!result->filelen) | |
389 | result->file = NULL; | |
390 | ||
391 | return (result); | |
392 | } | |
cbecb3ac | 393 | |
74e3931f | 394 | static char *win32_joiner(DSO *dso, const struct file_st *file_split) |
0f113f3e MC |
395 | { |
396 | int len = 0, offset = 0; | |
397 | char *result = NULL; | |
398 | const char *start; | |
399 | ||
400 | if (!file_split) { | |
401 | DSOerr(DSO_F_WIN32_JOINER, ERR_R_PASSED_NULL_PARAMETER); | |
402 | return (NULL); | |
403 | } | |
404 | if (file_split->node) { | |
405 | len += 2 + file_split->nodelen; /* 2 for starting \\ */ | |
406 | if (file_split->predir || file_split->dir || file_split->file) | |
407 | len++; /* 1 for ending \ */ | |
408 | } else if (file_split->device) { | |
409 | len += file_split->devicelen + 1; /* 1 for ending : */ | |
410 | } | |
411 | len += file_split->predirlen; | |
412 | if (file_split->predir && (file_split->dir || file_split->file)) { | |
413 | len++; /* 1 for ending \ */ | |
414 | } | |
415 | len += file_split->dirlen; | |
416 | if (file_split->dir && file_split->file) { | |
417 | len++; /* 1 for ending \ */ | |
418 | } | |
419 | len += file_split->filelen; | |
420 | ||
421 | if (!len) { | |
422 | DSOerr(DSO_F_WIN32_JOINER, DSO_R_EMPTY_FILE_STRUCTURE); | |
423 | return (NULL); | |
424 | } | |
425 | ||
426 | result = OPENSSL_malloc(len + 1); | |
90945fa3 | 427 | if (result == NULL) { |
0f113f3e MC |
428 | DSOerr(DSO_F_WIN32_JOINER, ERR_R_MALLOC_FAILURE); |
429 | return (NULL); | |
430 | } | |
431 | ||
432 | if (file_split->node) { | |
433 | strcpy(&result[offset], "\\\\"); | |
434 | offset += 2; | |
435 | strncpy(&result[offset], file_split->node, file_split->nodelen); | |
436 | offset += file_split->nodelen; | |
437 | if (file_split->predir || file_split->dir || file_split->file) { | |
438 | result[offset] = '\\'; | |
439 | offset++; | |
440 | } | |
441 | } else if (file_split->device) { | |
442 | strncpy(&result[offset], file_split->device, file_split->devicelen); | |
443 | offset += file_split->devicelen; | |
444 | result[offset] = ':'; | |
445 | offset++; | |
446 | } | |
447 | start = file_split->predir; | |
448 | while (file_split->predirlen > (start - file_split->predir)) { | |
449 | const char *end = openssl_strnchr(start, '/', | |
450 | file_split->predirlen - (start - | |
451 | file_split->predir)); | |
452 | if (!end) | |
453 | end = start | |
454 | + file_split->predirlen - (start - file_split->predir); | |
455 | strncpy(&result[offset], start, end - start); | |
456 | offset += (int)(end - start); | |
457 | result[offset] = '\\'; | |
458 | offset++; | |
459 | start = end + 1; | |
460 | } | |
0f113f3e MC |
461 | start = file_split->dir; |
462 | while (file_split->dirlen > (start - file_split->dir)) { | |
463 | const char *end = openssl_strnchr(start, '/', | |
464 | file_split->dirlen - (start - | |
465 | file_split->dir)); | |
466 | if (!end) | |
467 | end = start + file_split->dirlen - (start - file_split->dir); | |
468 | strncpy(&result[offset], start, end - start); | |
469 | offset += (int)(end - start); | |
470 | result[offset] = '\\'; | |
471 | offset++; | |
472 | start = end + 1; | |
473 | } | |
0f113f3e MC |
474 | strncpy(&result[offset], file_split->file, file_split->filelen); |
475 | offset += file_split->filelen; | |
476 | result[offset] = '\0'; | |
477 | return (result); | |
478 | } | |
479 | ||
480 | static char *win32_merger(DSO *dso, const char *filespec1, | |
481 | const char *filespec2) | |
482 | { | |
483 | char *merged = NULL; | |
484 | struct file_st *filespec1_split = NULL; | |
485 | struct file_st *filespec2_split = NULL; | |
486 | ||
487 | if (!filespec1 && !filespec2) { | |
488 | DSOerr(DSO_F_WIN32_MERGER, ERR_R_PASSED_NULL_PARAMETER); | |
489 | return (NULL); | |
490 | } | |
491 | if (!filespec2) { | |
492 | merged = OPENSSL_malloc(strlen(filespec1) + 1); | |
90945fa3 | 493 | if (merged == NULL) { |
0f113f3e MC |
494 | DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); |
495 | return (NULL); | |
496 | } | |
497 | strcpy(merged, filespec1); | |
498 | } else if (!filespec1) { | |
499 | merged = OPENSSL_malloc(strlen(filespec2) + 1); | |
90945fa3 | 500 | if (merged == NULL) { |
0f113f3e MC |
501 | DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); |
502 | return (NULL); | |
503 | } | |
504 | strcpy(merged, filespec2); | |
505 | } else { | |
506 | filespec1_split = win32_splitter(dso, filespec1, 0); | |
507 | if (!filespec1_split) { | |
508 | DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); | |
509 | return (NULL); | |
510 | } | |
511 | filespec2_split = win32_splitter(dso, filespec2, 1); | |
512 | if (!filespec2_split) { | |
513 | DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE); | |
514 | OPENSSL_free(filespec1_split); | |
515 | return (NULL); | |
516 | } | |
517 | ||
518 | /* Fill in into filespec1_split */ | |
519 | if (!filespec1_split->node && !filespec1_split->device) { | |
520 | filespec1_split->node = filespec2_split->node; | |
521 | filespec1_split->nodelen = filespec2_split->nodelen; | |
522 | filespec1_split->device = filespec2_split->device; | |
523 | filespec1_split->devicelen = filespec2_split->devicelen; | |
524 | } | |
525 | if (!filespec1_split->dir) { | |
526 | filespec1_split->dir = filespec2_split->dir; | |
527 | filespec1_split->dirlen = filespec2_split->dirlen; | |
528 | } else if (filespec1_split->dir[0] != '\\' | |
529 | && filespec1_split->dir[0] != '/') { | |
530 | filespec1_split->predir = filespec2_split->dir; | |
531 | filespec1_split->predirlen = filespec2_split->dirlen; | |
532 | } | |
533 | if (!filespec1_split->file) { | |
534 | filespec1_split->file = filespec2_split->file; | |
535 | filespec1_split->filelen = filespec2_split->filelen; | |
536 | } | |
537 | ||
538 | merged = win32_joiner(dso, filespec1_split); | |
539 | } | |
540 | OPENSSL_free(filespec1_split); | |
541 | OPENSSL_free(filespec2_split); | |
542 | return (merged); | |
543 | } | |
cbecb3ac | 544 | |
51c8dc37 | 545 | static char *win32_name_converter(DSO *dso, const char *filename) |
0f113f3e MC |
546 | { |
547 | char *translated; | |
548 | int len, transform; | |
549 | ||
550 | len = strlen(filename); | |
551 | transform = ((strstr(filename, "/") == NULL) && | |
552 | (strstr(filename, "\\") == NULL) && | |
553 | (strstr(filename, ":") == NULL)); | |
554 | if (transform) | |
555 | /* We will convert this to "%s.dll" */ | |
556 | translated = OPENSSL_malloc(len + 5); | |
557 | else | |
558 | /* We will simply duplicate filename */ | |
559 | translated = OPENSSL_malloc(len + 1); | |
560 | if (translated == NULL) { | |
561 | DSOerr(DSO_F_WIN32_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED); | |
562 | return (NULL); | |
563 | } | |
564 | if (transform) | |
565 | sprintf(translated, "%s.dll", filename); | |
566 | else | |
567 | sprintf(translated, "%s", filename); | |
568 | return (translated); | |
569 | } | |
51c8dc37 | 570 | |
74e3931f | 571 | static const char *openssl_strnchr(const char *string, int c, size_t len) |
0f113f3e MC |
572 | { |
573 | size_t i; | |
574 | const char *p; | |
575 | for (i = 0, p = string; i < len && *p; i++, p++) { | |
576 | if (*p == c) | |
577 | return p; | |
578 | } | |
579 | return NULL; | |
580 | } | |
581 | ||
582 | # include <tlhelp32.h> | |
583 | # ifdef _WIN32_WCE | |
584 | # define DLLNAME "TOOLHELP.DLL" | |
585 | # else | |
586 | # ifdef MODULEENTRY32 | |
587 | # undef MODULEENTRY32 /* unmask the ASCII version! */ | |
588 | # endif | |
589 | # define DLLNAME "KERNEL32.DLL" | |
7ed87653 | 590 | # endif |
0f113f3e MC |
591 | |
592 | typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD); | |
593 | typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE); | |
594 | typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *); | |
595 | ||
596 | static int win32_pathbyaddr(void *addr, char *path, int sz) | |
597 | { | |
598 | HMODULE dll; | |
599 | HANDLE hModuleSnap = INVALID_HANDLE_VALUE; | |
600 | MODULEENTRY32 me32; | |
601 | CREATETOOLHELP32SNAPSHOT create_snap; | |
602 | CLOSETOOLHELP32SNAPSHOT close_snap; | |
603 | MODULE32 module_first, module_next; | |
604 | ||
605 | if (addr == NULL) { | |
606 | union { | |
607 | int (*f) (void *, char *, int); | |
608 | void *p; | |
609 | } t = { | |
610 | win32_pathbyaddr | |
611 | }; | |
612 | addr = t.p; | |
613 | } | |
614 | ||
615 | dll = LoadLibrary(TEXT(DLLNAME)); | |
616 | if (dll == NULL) { | |
617 | DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED); | |
618 | return -1; | |
619 | } | |
620 | ||
621 | create_snap = (CREATETOOLHELP32SNAPSHOT) | |
622 | GetProcAddress(dll, "CreateToolhelp32Snapshot"); | |
623 | if (create_snap == NULL) { | |
624 | FreeLibrary(dll); | |
625 | DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED); | |
626 | return -1; | |
627 | } | |
628 | /* We take the rest for granted... */ | |
629 | # ifdef _WIN32_WCE | |
630 | close_snap = (CLOSETOOLHELP32SNAPSHOT) | |
631 | GetProcAddress(dll, "CloseToolhelp32Snapshot"); | |
7ed87653 | 632 | # else |
0f113f3e | 633 | close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle; |
7ed87653 | 634 | # endif |
0f113f3e MC |
635 | module_first = (MODULE32) GetProcAddress(dll, "Module32First"); |
636 | module_next = (MODULE32) GetProcAddress(dll, "Module32Next"); | |
637 | ||
638 | hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0); | |
639 | if (hModuleSnap == INVALID_HANDLE_VALUE) { | |
640 | FreeLibrary(dll); | |
641 | DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED); | |
642 | return -1; | |
643 | } | |
644 | ||
645 | me32.dwSize = sizeof(me32); | |
646 | ||
647 | if (!(*module_first) (hModuleSnap, &me32)) { | |
648 | (*close_snap) (hModuleSnap); | |
649 | FreeLibrary(dll); | |
650 | DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_FAILURE); | |
651 | return -1; | |
652 | } | |
653 | ||
654 | do { | |
655 | if ((BYTE *) addr >= me32.modBaseAddr && | |
656 | (BYTE *) addr < me32.modBaseAddr + me32.modBaseSize) { | |
657 | (*close_snap) (hModuleSnap); | |
658 | FreeLibrary(dll); | |
659 | # ifdef _WIN32_WCE | |
660 | # if _WIN32_WCE >= 101 | |
661 | return WideCharToMultiByte(CP_ACP, 0, me32.szExePath, -1, | |
662 | path, sz, NULL, NULL); | |
663 | # else | |
664 | { | |
665 | int i, len = (int)wcslen(me32.szExePath); | |
666 | if (sz <= 0) | |
667 | return len + 1; | |
668 | if (len >= sz) | |
669 | len = sz - 1; | |
670 | for (i = 0; i < len; i++) | |
671 | path[i] = (char)me32.szExePath[i]; | |
672 | path[len++] = 0; | |
673 | return len; | |
674 | } | |
675 | # endif | |
676 | # else | |
677 | { | |
678 | int len = (int)strlen(me32.szExePath); | |
679 | if (sz <= 0) | |
680 | return len + 1; | |
681 | if (len >= sz) | |
682 | len = sz - 1; | |
683 | memcpy(path, me32.szExePath, len); | |
684 | path[len++] = 0; | |
685 | return len; | |
686 | } | |
687 | # endif | |
688 | } | |
689 | } while ((*module_next) (hModuleSnap, &me32)); | |
690 | ||
691 | (*close_snap) (hModuleSnap); | |
692 | FreeLibrary(dll); | |
693 | return 0; | |
694 | } | |
68b64fb6 | 695 | |
c6cb42e4 | 696 | static void *win32_globallookup(const char *name) |
0f113f3e MC |
697 | { |
698 | HMODULE dll; | |
699 | HANDLE hModuleSnap = INVALID_HANDLE_VALUE; | |
700 | MODULEENTRY32 me32; | |
701 | CREATETOOLHELP32SNAPSHOT create_snap; | |
702 | CLOSETOOLHELP32SNAPSHOT close_snap; | |
703 | MODULE32 module_first, module_next; | |
156561b0 AP |
704 | union { |
705 | void *p; | |
706 | FARPROC f; | |
707 | } ret = { NULL }; | |
0f113f3e MC |
708 | |
709 | dll = LoadLibrary(TEXT(DLLNAME)); | |
710 | if (dll == NULL) { | |
711 | DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED); | |
712 | return NULL; | |
713 | } | |
714 | ||
715 | create_snap = (CREATETOOLHELP32SNAPSHOT) | |
716 | GetProcAddress(dll, "CreateToolhelp32Snapshot"); | |
717 | if (create_snap == NULL) { | |
718 | FreeLibrary(dll); | |
719 | DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED); | |
720 | return NULL; | |
721 | } | |
722 | /* We take the rest for granted... */ | |
723 | # ifdef _WIN32_WCE | |
724 | close_snap = (CLOSETOOLHELP32SNAPSHOT) | |
725 | GetProcAddress(dll, "CloseToolhelp32Snapshot"); | |
726 | # else | |
727 | close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle; | |
728 | # endif | |
729 | module_first = (MODULE32) GetProcAddress(dll, "Module32First"); | |
730 | module_next = (MODULE32) GetProcAddress(dll, "Module32Next"); | |
731 | ||
732 | hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0); | |
733 | if (hModuleSnap == INVALID_HANDLE_VALUE) { | |
734 | FreeLibrary(dll); | |
735 | DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED); | |
736 | return NULL; | |
737 | } | |
738 | ||
739 | me32.dwSize = sizeof(me32); | |
740 | ||
741 | if (!(*module_first) (hModuleSnap, &me32)) { | |
742 | (*close_snap) (hModuleSnap); | |
743 | FreeLibrary(dll); | |
744 | return NULL; | |
745 | } | |
746 | ||
747 | do { | |
156561b0 | 748 | if ((ret.f = GetProcAddress(me32.hModule, name))) { |
0f113f3e MC |
749 | (*close_snap) (hModuleSnap); |
750 | FreeLibrary(dll); | |
156561b0 | 751 | return ret.p; |
0f113f3e MC |
752 | } |
753 | } while ((*module_next) (hModuleSnap, &me32)); | |
754 | ||
755 | (*close_snap) (hModuleSnap); | |
756 | FreeLibrary(dll); | |
757 | return NULL; | |
758 | } | |
759 | #endif /* DSO_WIN32 */ |