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
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 void *win32_globallookup(const char *name
);
69 static const char *openssl_strnchr(const char *string
, int c
, size_t len
);
71 static DSO_METHOD dso_meth_win32
= {
72 "OpenSSL 'win32' shared library method",
81 NULL
, /* pathbyaddr */
85 DSO_METHOD
*DSO_METHOD_openssl(void)
87 return &dso_meth_win32
;
91 * For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to
92 * the handle (HINSTANCE) returned from LoadLibrary(), and copied.
95 static int win32_load(DSO
*dso
)
97 HINSTANCE h
= NULL
, *p
= NULL
;
98 /* See applicable comments from dso_dl.c */
99 char *filename
= DSO_convert_filename(dso
, NULL
);
101 if (filename
== NULL
) {
102 DSOerr(DSO_F_WIN32_LOAD
, DSO_R_NO_FILENAME
);
105 h
= LoadLibraryA(filename
);
107 DSOerr(DSO_F_WIN32_LOAD
, DSO_R_LOAD_FAILED
);
108 ERR_add_error_data(3, "filename(", filename
, ")");
111 p
= OPENSSL_malloc(sizeof(*p
));
113 DSOerr(DSO_F_WIN32_LOAD
, ERR_R_MALLOC_FAILURE
);
117 if (!sk_void_push(dso
->meth_data
, p
)) {
118 DSOerr(DSO_F_WIN32_LOAD
, DSO_R_STACK_ERROR
);
122 dso
->loaded_filename
= filename
;
126 OPENSSL_free(filename
);
133 static int win32_unload(DSO
*dso
)
137 DSOerr(DSO_F_WIN32_UNLOAD
, ERR_R_PASSED_NULL_PARAMETER
);
140 if (sk_void_num(dso
->meth_data
) < 1)
142 p
= sk_void_pop(dso
->meth_data
);
144 DSOerr(DSO_F_WIN32_UNLOAD
, DSO_R_NULL_HANDLE
);
147 if (!FreeLibrary(*p
)) {
148 DSOerr(DSO_F_WIN32_UNLOAD
, DSO_R_UNLOAD_FAILED
);
150 * We should push the value back onto the stack in case of a retry.
152 sk_void_push(dso
->meth_data
, p
);
160 static DSO_FUNC_TYPE
win32_bind_func(DSO
*dso
, const char *symname
)
168 if ((dso
== NULL
) || (symname
== NULL
)) {
169 DSOerr(DSO_F_WIN32_BIND_FUNC
, ERR_R_PASSED_NULL_PARAMETER
);
172 if (sk_void_num(dso
->meth_data
) < 1) {
173 DSOerr(DSO_F_WIN32_BIND_FUNC
, DSO_R_STACK_ERROR
);
176 ptr
= sk_void_value(dso
->meth_data
, sk_void_num(dso
->meth_data
) - 1);
178 DSOerr(DSO_F_WIN32_BIND_FUNC
, DSO_R_NULL_HANDLE
);
181 sym
.f
= GetProcAddress(*ptr
, symname
);
183 DSOerr(DSO_F_WIN32_BIND_FUNC
, DSO_R_SYM_FAILURE
);
184 ERR_add_error_data(3, "symname(", symname
, ")");
187 return (DSO_FUNC_TYPE
)sym
.f
;
203 static struct file_st
*win32_splitter(DSO
*dso
, const char *filename
,
204 int assume_last_is_dir
)
206 struct file_st
*result
= NULL
;
207 enum { IN_NODE
, IN_DEVICE
, IN_FILE
} position
;
208 const char *start
= filename
;
212 DSOerr(DSO_F_WIN32_SPLITTER
, DSO_R_NO_FILENAME
);
216 result
= OPENSSL_zalloc(sizeof(*result
));
217 if (result
== NULL
) {
218 DSOerr(DSO_F_WIN32_SPLITTER
, ERR_R_MALLOC_FAILURE
);
222 position
= IN_DEVICE
;
224 if ((filename
[0] == '\\' && filename
[1] == '\\')
225 || (filename
[0] == '/' && filename
[1] == '/')) {
229 result
->node
= start
;
236 if (position
!= IN_DEVICE
) {
237 DSOerr(DSO_F_WIN32_SPLITTER
, DSO_R_INCORRECT_FILE_SYNTAX
);
238 OPENSSL_free(result
);
241 result
->device
= start
;
242 result
->devicelen
= (int)(filename
- start
);
249 if (position
== IN_NODE
) {
250 result
->nodelen
= (int)(filename
- start
);
254 } else if (position
== IN_DEVICE
) {
258 result
->dirlen
= (int)(filename
- start
);
262 result
->dirlen
+= (int)(filename
- start
);
267 if (position
== IN_NODE
) {
268 result
->nodelen
= (int)(filename
- start
);
270 if (filename
- start
> 0) {
271 if (assume_last_is_dir
) {
272 if (position
== IN_DEVICE
) {
276 result
->dirlen
+= (int)(filename
- start
);
278 result
->file
= start
;
279 result
->filelen
= (int)(filename
- start
);
291 if (!result
->nodelen
)
293 if (!result
->devicelen
)
294 result
->device
= NULL
;
297 if (!result
->filelen
)
303 static char *win32_joiner(DSO
*dso
, const struct file_st
*file_split
)
305 int len
= 0, offset
= 0;
310 DSOerr(DSO_F_WIN32_JOINER
, ERR_R_PASSED_NULL_PARAMETER
);
313 if (file_split
->node
) {
314 len
+= 2 + file_split
->nodelen
; /* 2 for starting \\ */
315 if (file_split
->predir
|| file_split
->dir
|| file_split
->file
)
316 len
++; /* 1 for ending \ */
317 } else if (file_split
->device
) {
318 len
+= file_split
->devicelen
+ 1; /* 1 for ending : */
320 len
+= file_split
->predirlen
;
321 if (file_split
->predir
&& (file_split
->dir
|| file_split
->file
)) {
322 len
++; /* 1 for ending \ */
324 len
+= file_split
->dirlen
;
325 if (file_split
->dir
&& file_split
->file
) {
326 len
++; /* 1 for ending \ */
328 len
+= file_split
->filelen
;
331 DSOerr(DSO_F_WIN32_JOINER
, DSO_R_EMPTY_FILE_STRUCTURE
);
335 result
= OPENSSL_malloc(len
+ 1);
336 if (result
== NULL
) {
337 DSOerr(DSO_F_WIN32_JOINER
, ERR_R_MALLOC_FAILURE
);
341 if (file_split
->node
) {
342 strcpy(&result
[offset
], "\\\\");
344 strncpy(&result
[offset
], file_split
->node
, file_split
->nodelen
);
345 offset
+= file_split
->nodelen
;
346 if (file_split
->predir
|| file_split
->dir
|| file_split
->file
) {
347 result
[offset
] = '\\';
350 } else if (file_split
->device
) {
351 strncpy(&result
[offset
], file_split
->device
, file_split
->devicelen
);
352 offset
+= file_split
->devicelen
;
353 result
[offset
] = ':';
356 start
= file_split
->predir
;
357 while (file_split
->predirlen
> (start
- file_split
->predir
)) {
358 const char *end
= openssl_strnchr(start
, '/',
359 file_split
->predirlen
- (start
-
360 file_split
->predir
));
363 + file_split
->predirlen
- (start
- file_split
->predir
);
364 strncpy(&result
[offset
], start
, end
- start
);
365 offset
+= (int)(end
- start
);
366 result
[offset
] = '\\';
370 start
= file_split
->dir
;
371 while (file_split
->dirlen
> (start
- file_split
->dir
)) {
372 const char *end
= openssl_strnchr(start
, '/',
373 file_split
->dirlen
- (start
-
376 end
= start
+ file_split
->dirlen
- (start
- file_split
->dir
);
377 strncpy(&result
[offset
], start
, end
- start
);
378 offset
+= (int)(end
- start
);
379 result
[offset
] = '\\';
383 strncpy(&result
[offset
], file_split
->file
, file_split
->filelen
);
384 offset
+= file_split
->filelen
;
385 result
[offset
] = '\0';
389 static char *win32_merger(DSO
*dso
, const char *filespec1
,
390 const char *filespec2
)
393 struct file_st
*filespec1_split
= NULL
;
394 struct file_st
*filespec2_split
= NULL
;
396 if (!filespec1
&& !filespec2
) {
397 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_PASSED_NULL_PARAMETER
);
401 merged
= OPENSSL_strdup(filespec1
);
402 if (merged
== NULL
) {
403 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
406 } else if (!filespec1
) {
407 merged
= OPENSSL_strdup(filespec2
);
408 if (merged
== NULL
) {
409 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
413 filespec1_split
= win32_splitter(dso
, filespec1
, 0);
414 if (!filespec1_split
) {
415 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
418 filespec2_split
= win32_splitter(dso
, filespec2
, 1);
419 if (!filespec2_split
) {
420 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
421 OPENSSL_free(filespec1_split
);
425 /* Fill in into filespec1_split */
426 if (!filespec1_split
->node
&& !filespec1_split
->device
) {
427 filespec1_split
->node
= filespec2_split
->node
;
428 filespec1_split
->nodelen
= filespec2_split
->nodelen
;
429 filespec1_split
->device
= filespec2_split
->device
;
430 filespec1_split
->devicelen
= filespec2_split
->devicelen
;
432 if (!filespec1_split
->dir
) {
433 filespec1_split
->dir
= filespec2_split
->dir
;
434 filespec1_split
->dirlen
= filespec2_split
->dirlen
;
435 } else if (filespec1_split
->dir
[0] != '\\'
436 && filespec1_split
->dir
[0] != '/') {
437 filespec1_split
->predir
= filespec2_split
->dir
;
438 filespec1_split
->predirlen
= filespec2_split
->dirlen
;
440 if (!filespec1_split
->file
) {
441 filespec1_split
->file
= filespec2_split
->file
;
442 filespec1_split
->filelen
= filespec2_split
->filelen
;
445 merged
= win32_joiner(dso
, filespec1_split
);
447 OPENSSL_free(filespec1_split
);
448 OPENSSL_free(filespec2_split
);
452 static char *win32_name_converter(DSO
*dso
, const char *filename
)
457 len
= strlen(filename
);
458 transform
= ((strstr(filename
, "/") == NULL
) &&
459 (strstr(filename
, "\\") == NULL
) &&
460 (strstr(filename
, ":") == NULL
));
462 /* We will convert this to "%s.dll" */
463 translated
= OPENSSL_malloc(len
+ 5);
465 /* We will simply duplicate filename */
466 translated
= OPENSSL_malloc(len
+ 1);
467 if (translated
== NULL
) {
468 DSOerr(DSO_F_WIN32_NAME_CONVERTER
, DSO_R_NAME_TRANSLATION_FAILED
);
472 sprintf(translated
, "%s.dll", filename
);
474 sprintf(translated
, "%s", filename
);
478 static const char *openssl_strnchr(const char *string
, int c
, size_t len
)
482 for (i
= 0, p
= string
; i
< len
&& *p
; i
++, p
++) {
489 # include <tlhelp32.h>
491 # define DLLNAME "TOOLHELP.DLL"
493 # ifdef MODULEENTRY32
494 # undef MODULEENTRY32 /* unmask the ASCII version! */
496 # define DLLNAME "KERNEL32.DLL"
499 typedef HANDLE(WINAPI
*CREATETOOLHELP32SNAPSHOT
) (DWORD
, DWORD
);
500 typedef BOOL(WINAPI
*CLOSETOOLHELP32SNAPSHOT
) (HANDLE
);
501 typedef BOOL(WINAPI
*MODULE32
) (HANDLE
, MODULEENTRY32
*);
503 static void *win32_globallookup(const char *name
)
506 HANDLE hModuleSnap
= INVALID_HANDLE_VALUE
;
508 CREATETOOLHELP32SNAPSHOT create_snap
;
509 CLOSETOOLHELP32SNAPSHOT close_snap
;
510 MODULE32 module_first
, module_next
;
516 dll
= LoadLibrary(TEXT(DLLNAME
));
518 DSOerr(DSO_F_WIN32_GLOBALLOOKUP
, DSO_R_UNSUPPORTED
);
522 create_snap
= (CREATETOOLHELP32SNAPSHOT
)
523 GetProcAddress(dll
, "CreateToolhelp32Snapshot");
524 if (create_snap
== NULL
) {
526 DSOerr(DSO_F_WIN32_GLOBALLOOKUP
, DSO_R_UNSUPPORTED
);
529 /* We take the rest for granted... */
531 close_snap
= (CLOSETOOLHELP32SNAPSHOT
)
532 GetProcAddress(dll
, "CloseToolhelp32Snapshot");
534 close_snap
= (CLOSETOOLHELP32SNAPSHOT
) CloseHandle
;
536 module_first
= (MODULE32
) GetProcAddress(dll
, "Module32First");
537 module_next
= (MODULE32
) GetProcAddress(dll
, "Module32Next");
539 hModuleSnap
= (*create_snap
) (TH32CS_SNAPMODULE
, 0);
540 if (hModuleSnap
== INVALID_HANDLE_VALUE
) {
542 DSOerr(DSO_F_WIN32_GLOBALLOOKUP
, DSO_R_UNSUPPORTED
);
546 me32
.dwSize
= sizeof(me32
);
548 if (!(*module_first
) (hModuleSnap
, &me32
)) {
549 (*close_snap
) (hModuleSnap
);
555 if ((ret
.f
= GetProcAddress(me32
.hModule
, name
))) {
556 (*close_snap
) (hModuleSnap
);
560 } while ((*module_next
) (hModuleSnap
, &me32
));
562 (*close_snap
) (hModuleSnap
);
566 #endif /* DSO_WIN32 */