2 * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 #include "dso_local.h"
13 #if defined(DSO_WIN32)
17 static FARPROC
GetProcAddressA(HMODULE hModule
, LPCSTR lpProcName
)
19 WCHAR lpProcNameW
[64];
22 for (i
= 0; lpProcName
[i
] && i
< 64; i
++)
23 lpProcNameW
[i
] = (WCHAR
)lpProcName
[i
];
28 return GetProcAddressW(hModule
, lpProcNameW
);
31 # undef GetProcAddress
32 # define GetProcAddress GetProcAddressA
34 static HINSTANCE
LoadLibraryA(LPCSTR lpLibFileName
)
37 size_t len_0
= strlen(lpLibFileName
) + 1, i
;
40 fnamw
= (WCHAR
*)_alloca(len_0
* sizeof(WCHAR
));
42 fnamw
= (WCHAR
*)alloca(len_0
* sizeof(WCHAR
));
45 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
48 # if defined(_WIN32_WCE) && _WIN32_WCE>=101
49 if (!MultiByteToWideChar(CP_ACP
, 0, lpLibFileName
, len_0
, fnamw
, len_0
))
51 for (i
= 0; i
< len_0
; i
++)
52 fnamw
[i
] = (WCHAR
)lpLibFileName
[i
];
54 return LoadLibraryW(fnamw
);
58 /* Part of the hack in "win32_load" ... */
59 # define DSO_MAX_TRANSLATED_SIZE 256
61 static int win32_load(DSO
*dso
);
62 static int win32_unload(DSO
*dso
);
63 static DSO_FUNC_TYPE
win32_bind_func(DSO
*dso
, const char *symname
);
64 static char *win32_name_converter(DSO
*dso
, const char *filename
);
65 static char *win32_merger(DSO
*dso
, const char *filespec1
,
66 const char *filespec2
);
67 static int win32_pathbyaddr(void *addr
, char *path
, int sz
);
68 static void *win32_globallookup(const char *name
);
70 static const char *openssl_strnchr(const char *string
, int c
, size_t len
);
72 static DSO_METHOD dso_meth_win32
= {
73 "OpenSSL 'win32' shared library method",
82 win32_pathbyaddr
, /* pathbyaddr */
86 DSO_METHOD
*DSO_METHOD_openssl(void)
88 return &dso_meth_win32
;
92 * For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to
93 * the handle (HINSTANCE) returned from LoadLibrary(), and copied.
96 static int win32_load(DSO
*dso
)
98 HINSTANCE h
= NULL
, *p
= NULL
;
99 /* See applicable comments from dso_dl.c */
100 char *filename
= DSO_convert_filename(dso
, NULL
);
102 if (filename
== NULL
) {
103 DSOerr(DSO_F_WIN32_LOAD
, DSO_R_NO_FILENAME
);
106 h
= LoadLibraryA(filename
);
108 DSOerr(DSO_F_WIN32_LOAD
, DSO_R_LOAD_FAILED
);
109 ERR_add_error_data(3, "filename(", filename
, ")");
112 p
= OPENSSL_malloc(sizeof(*p
));
114 DSOerr(DSO_F_WIN32_LOAD
, ERR_R_MALLOC_FAILURE
);
118 if (!sk_void_push(dso
->meth_data
, p
)) {
119 DSOerr(DSO_F_WIN32_LOAD
, DSO_R_STACK_ERROR
);
123 dso
->loaded_filename
= filename
;
127 OPENSSL_free(filename
);
134 static int win32_unload(DSO
*dso
)
138 DSOerr(DSO_F_WIN32_UNLOAD
, ERR_R_PASSED_NULL_PARAMETER
);
141 if (sk_void_num(dso
->meth_data
) < 1)
143 p
= sk_void_pop(dso
->meth_data
);
145 DSOerr(DSO_F_WIN32_UNLOAD
, DSO_R_NULL_HANDLE
);
148 if (!FreeLibrary(*p
)) {
149 DSOerr(DSO_F_WIN32_UNLOAD
, DSO_R_UNLOAD_FAILED
);
151 * We should push the value back onto the stack in case of a retry.
153 sk_void_push(dso
->meth_data
, p
);
161 static DSO_FUNC_TYPE
win32_bind_func(DSO
*dso
, const char *symname
)
169 if ((dso
== NULL
) || (symname
== NULL
)) {
170 DSOerr(DSO_F_WIN32_BIND_FUNC
, ERR_R_PASSED_NULL_PARAMETER
);
173 if (sk_void_num(dso
->meth_data
) < 1) {
174 DSOerr(DSO_F_WIN32_BIND_FUNC
, DSO_R_STACK_ERROR
);
177 ptr
= sk_void_value(dso
->meth_data
, sk_void_num(dso
->meth_data
) - 1);
179 DSOerr(DSO_F_WIN32_BIND_FUNC
, DSO_R_NULL_HANDLE
);
182 sym
.f
= GetProcAddress(*ptr
, symname
);
184 DSOerr(DSO_F_WIN32_BIND_FUNC
, DSO_R_SYM_FAILURE
);
185 ERR_add_error_data(3, "symname(", symname
, ")");
188 return (DSO_FUNC_TYPE
)sym
.f
;
204 static struct file_st
*win32_splitter(DSO
*dso
, const char *filename
,
205 int assume_last_is_dir
)
207 struct file_st
*result
= NULL
;
208 enum { IN_NODE
, IN_DEVICE
, IN_FILE
} position
;
209 const char *start
= filename
;
213 DSOerr(DSO_F_WIN32_SPLITTER
, DSO_R_NO_FILENAME
);
217 result
= OPENSSL_zalloc(sizeof(*result
));
218 if (result
== NULL
) {
219 DSOerr(DSO_F_WIN32_SPLITTER
, ERR_R_MALLOC_FAILURE
);
223 position
= IN_DEVICE
;
225 if ((filename
[0] == '\\' && filename
[1] == '\\')
226 || (filename
[0] == '/' && filename
[1] == '/')) {
230 result
->node
= start
;
237 if (position
!= IN_DEVICE
) {
238 DSOerr(DSO_F_WIN32_SPLITTER
, DSO_R_INCORRECT_FILE_SYNTAX
);
239 OPENSSL_free(result
);
242 result
->device
= start
;
243 result
->devicelen
= (int)(filename
- start
);
250 if (position
== IN_NODE
) {
251 result
->nodelen
= (int)(filename
- start
);
255 } else if (position
== IN_DEVICE
) {
259 result
->dirlen
= (int)(filename
- start
);
263 result
->dirlen
+= (int)(filename
- start
);
268 if (position
== IN_NODE
) {
269 result
->nodelen
= (int)(filename
- start
);
271 if (filename
- start
> 0) {
272 if (assume_last_is_dir
) {
273 if (position
== IN_DEVICE
) {
277 result
->dirlen
+= (int)(filename
- start
);
279 result
->file
= start
;
280 result
->filelen
= (int)(filename
- start
);
292 if (!result
->nodelen
)
294 if (!result
->devicelen
)
295 result
->device
= NULL
;
298 if (!result
->filelen
)
304 static char *win32_joiner(DSO
*dso
, const struct file_st
*file_split
)
306 int len
= 0, offset
= 0;
311 DSOerr(DSO_F_WIN32_JOINER
, ERR_R_PASSED_NULL_PARAMETER
);
314 if (file_split
->node
) {
315 len
+= 2 + file_split
->nodelen
; /* 2 for starting \\ */
316 if (file_split
->predir
|| file_split
->dir
|| file_split
->file
)
317 len
++; /* 1 for ending \ */
318 } else if (file_split
->device
) {
319 len
+= file_split
->devicelen
+ 1; /* 1 for ending : */
321 len
+= file_split
->predirlen
;
322 if (file_split
->predir
&& (file_split
->dir
|| file_split
->file
)) {
323 len
++; /* 1 for ending \ */
325 len
+= file_split
->dirlen
;
326 if (file_split
->dir
&& file_split
->file
) {
327 len
++; /* 1 for ending \ */
329 len
+= file_split
->filelen
;
332 DSOerr(DSO_F_WIN32_JOINER
, DSO_R_EMPTY_FILE_STRUCTURE
);
336 result
= OPENSSL_malloc(len
+ 1);
337 if (result
== NULL
) {
338 DSOerr(DSO_F_WIN32_JOINER
, ERR_R_MALLOC_FAILURE
);
342 if (file_split
->node
) {
343 strcpy(&result
[offset
], "\\\\");
345 strncpy(&result
[offset
], file_split
->node
, file_split
->nodelen
);
346 offset
+= file_split
->nodelen
;
347 if (file_split
->predir
|| file_split
->dir
|| file_split
->file
) {
348 result
[offset
] = '\\';
351 } else if (file_split
->device
) {
352 strncpy(&result
[offset
], file_split
->device
, file_split
->devicelen
);
353 offset
+= file_split
->devicelen
;
354 result
[offset
] = ':';
357 start
= file_split
->predir
;
358 while (file_split
->predirlen
> (start
- file_split
->predir
)) {
359 const char *end
= openssl_strnchr(start
, '/',
360 file_split
->predirlen
- (start
-
361 file_split
->predir
));
364 + file_split
->predirlen
- (start
- file_split
->predir
);
365 strncpy(&result
[offset
], start
, end
- start
);
366 offset
+= (int)(end
- start
);
367 result
[offset
] = '\\';
371 start
= file_split
->dir
;
372 while (file_split
->dirlen
> (start
- file_split
->dir
)) {
373 const char *end
= openssl_strnchr(start
, '/',
374 file_split
->dirlen
- (start
-
377 end
= start
+ file_split
->dirlen
- (start
- file_split
->dir
);
378 strncpy(&result
[offset
], start
, end
- start
);
379 offset
+= (int)(end
- start
);
380 result
[offset
] = '\\';
384 strncpy(&result
[offset
], file_split
->file
, file_split
->filelen
);
385 offset
+= file_split
->filelen
;
386 result
[offset
] = '\0';
390 static char *win32_merger(DSO
*dso
, const char *filespec1
,
391 const char *filespec2
)
394 struct file_st
*filespec1_split
= NULL
;
395 struct file_st
*filespec2_split
= NULL
;
397 if (!filespec1
&& !filespec2
) {
398 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_PASSED_NULL_PARAMETER
);
402 merged
= OPENSSL_strdup(filespec1
);
403 if (merged
== NULL
) {
404 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
407 } else if (!filespec1
) {
408 merged
= OPENSSL_strdup(filespec2
);
409 if (merged
== NULL
) {
410 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
414 filespec1_split
= win32_splitter(dso
, filespec1
, 0);
415 if (!filespec1_split
) {
416 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
419 filespec2_split
= win32_splitter(dso
, filespec2
, 1);
420 if (!filespec2_split
) {
421 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
422 OPENSSL_free(filespec1_split
);
426 /* Fill in into filespec1_split */
427 if (!filespec1_split
->node
&& !filespec1_split
->device
) {
428 filespec1_split
->node
= filespec2_split
->node
;
429 filespec1_split
->nodelen
= filespec2_split
->nodelen
;
430 filespec1_split
->device
= filespec2_split
->device
;
431 filespec1_split
->devicelen
= filespec2_split
->devicelen
;
433 if (!filespec1_split
->dir
) {
434 filespec1_split
->dir
= filespec2_split
->dir
;
435 filespec1_split
->dirlen
= filespec2_split
->dirlen
;
436 } else if (filespec1_split
->dir
[0] != '\\'
437 && filespec1_split
->dir
[0] != '/') {
438 filespec1_split
->predir
= filespec2_split
->dir
;
439 filespec1_split
->predirlen
= filespec2_split
->dirlen
;
441 if (!filespec1_split
->file
) {
442 filespec1_split
->file
= filespec2_split
->file
;
443 filespec1_split
->filelen
= filespec2_split
->filelen
;
446 merged
= win32_joiner(dso
, filespec1_split
);
448 OPENSSL_free(filespec1_split
);
449 OPENSSL_free(filespec2_split
);
453 static char *win32_name_converter(DSO
*dso
, const char *filename
)
458 len
= strlen(filename
);
459 transform
= ((strstr(filename
, "/") == NULL
) &&
460 (strstr(filename
, "\\") == NULL
) &&
461 (strstr(filename
, ":") == NULL
));
463 /* We will convert this to "%s.dll" */
464 translated
= OPENSSL_malloc(len
+ 5);
466 /* We will simply duplicate filename */
467 translated
= OPENSSL_malloc(len
+ 1);
468 if (translated
== NULL
) {
469 DSOerr(DSO_F_WIN32_NAME_CONVERTER
, DSO_R_NAME_TRANSLATION_FAILED
);
473 sprintf(translated
, "%s.dll", filename
);
475 sprintf(translated
, "%s", filename
);
479 static const char *openssl_strnchr(const char *string
, int c
, size_t len
)
483 for (i
= 0, p
= string
; i
< len
&& *p
; i
++, p
++) {
490 # include <tlhelp32.h>
492 # define DLLNAME "TOOLHELP.DLL"
494 # ifdef MODULEENTRY32
495 # undef MODULEENTRY32 /* unmask the ASCII version! */
497 # define DLLNAME "KERNEL32.DLL"
500 typedef HANDLE(WINAPI
*CREATETOOLHELP32SNAPSHOT
) (DWORD
, DWORD
);
501 typedef BOOL(WINAPI
*CLOSETOOLHELP32SNAPSHOT
) (HANDLE
);
502 typedef BOOL(WINAPI
*MODULE32
) (HANDLE
, MODULEENTRY32
*);
504 static int win32_pathbyaddr(void *addr
, char *path
, int sz
)
507 HANDLE hModuleSnap
= INVALID_HANDLE_VALUE
;
509 CREATETOOLHELP32SNAPSHOT create_snap
;
510 CLOSETOOLHELP32SNAPSHOT close_snap
;
511 MODULE32 module_first
, module_next
;
515 int (*f
) (void *, char *, int);
523 dll
= LoadLibrary(TEXT(DLLNAME
));
525 DSOerr(DSO_F_WIN32_PATHBYADDR
, DSO_R_UNSUPPORTED
);
529 create_snap
= (CREATETOOLHELP32SNAPSHOT
)
530 GetProcAddress(dll
, "CreateToolhelp32Snapshot");
531 if (create_snap
== NULL
) {
533 DSOerr(DSO_F_WIN32_PATHBYADDR
, DSO_R_UNSUPPORTED
);
536 /* We take the rest for granted... */
538 close_snap
= (CLOSETOOLHELP32SNAPSHOT
)
539 GetProcAddress(dll
, "CloseToolhelp32Snapshot");
541 close_snap
= (CLOSETOOLHELP32SNAPSHOT
) CloseHandle
;
543 module_first
= (MODULE32
) GetProcAddress(dll
, "Module32First");
544 module_next
= (MODULE32
) GetProcAddress(dll
, "Module32Next");
547 * Take a snapshot of current process which includes
548 * list of all involved modules.
550 hModuleSnap
= (*create_snap
) (TH32CS_SNAPMODULE
, 0);
551 if (hModuleSnap
== INVALID_HANDLE_VALUE
) {
553 DSOerr(DSO_F_WIN32_PATHBYADDR
, DSO_R_UNSUPPORTED
);
557 me32
.dwSize
= sizeof(me32
);
559 if (!(*module_first
) (hModuleSnap
, &me32
)) {
560 (*close_snap
) (hModuleSnap
);
562 DSOerr(DSO_F_WIN32_PATHBYADDR
, DSO_R_FAILURE
);
566 /* Enumerate the modules to find one which includes me. */
568 if ((uintptr_t) addr
>= (uintptr_t) me32
.modBaseAddr
&&
569 (uintptr_t) addr
< (uintptr_t) (me32
.modBaseAddr
+ me32
.modBaseSize
)) {
570 (*close_snap
) (hModuleSnap
);
573 # if _WIN32_WCE >= 101
574 return WideCharToMultiByte(CP_ACP
, 0, me32
.szExePath
, -1,
575 path
, sz
, NULL
, NULL
);
578 int i
, len
= (int)wcslen(me32
.szExePath
);
583 for (i
= 0; i
< len
; i
++)
584 path
[i
] = (char)me32
.szExePath
[i
];
591 int len
= (int)strlen(me32
.szExePath
);
596 memcpy(path
, me32
.szExePath
, len
);
602 } while ((*module_next
) (hModuleSnap
, &me32
));
604 (*close_snap
) (hModuleSnap
);
609 static void *win32_globallookup(const char *name
)
612 HANDLE hModuleSnap
= INVALID_HANDLE_VALUE
;
614 CREATETOOLHELP32SNAPSHOT create_snap
;
615 CLOSETOOLHELP32SNAPSHOT close_snap
;
616 MODULE32 module_first
, module_next
;
622 dll
= LoadLibrary(TEXT(DLLNAME
));
624 DSOerr(DSO_F_WIN32_GLOBALLOOKUP
, DSO_R_UNSUPPORTED
);
628 create_snap
= (CREATETOOLHELP32SNAPSHOT
)
629 GetProcAddress(dll
, "CreateToolhelp32Snapshot");
630 if (create_snap
== NULL
) {
632 DSOerr(DSO_F_WIN32_GLOBALLOOKUP
, DSO_R_UNSUPPORTED
);
635 /* We take the rest for granted... */
637 close_snap
= (CLOSETOOLHELP32SNAPSHOT
)
638 GetProcAddress(dll
, "CloseToolhelp32Snapshot");
640 close_snap
= (CLOSETOOLHELP32SNAPSHOT
) CloseHandle
;
642 module_first
= (MODULE32
) GetProcAddress(dll
, "Module32First");
643 module_next
= (MODULE32
) GetProcAddress(dll
, "Module32Next");
645 hModuleSnap
= (*create_snap
) (TH32CS_SNAPMODULE
, 0);
646 if (hModuleSnap
== INVALID_HANDLE_VALUE
) {
648 DSOerr(DSO_F_WIN32_GLOBALLOOKUP
, DSO_R_UNSUPPORTED
);
652 me32
.dwSize
= sizeof(me32
);
654 if (!(*module_first
) (hModuleSnap
, &me32
)) {
655 (*close_snap
) (hModuleSnap
);
661 if ((ret
.f
= GetProcAddress(me32
.hModule
, name
))) {
662 (*close_snap
) (hModuleSnap
);
666 } while ((*module_next
) (hModuleSnap
, &me32
));
668 (*close_snap
) (hModuleSnap
);
672 #endif /* DSO_WIN32 */