2 * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (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
12 #if defined(DSO_WIN32)
16 static FARPROC
GetProcAddressA(HMODULE hModule
, LPCSTR lpProcName
)
18 WCHAR lpProcNameW
[64];
21 for (i
= 0; lpProcName
[i
] && i
< 64; i
++)
22 lpProcNameW
[i
] = (WCHAR
)lpProcName
[i
];
27 return GetProcAddressW(hModule
, lpProcNameW
);
30 # undef GetProcAddress
31 # define GetProcAddress GetProcAddressA
33 static HINSTANCE
LoadLibraryA(LPCSTR lpLibFileName
)
36 size_t len_0
= strlen(lpLibFileName
) + 1, i
;
39 fnamw
= (WCHAR
*)_alloca(len_0
* sizeof(WCHAR
));
41 fnamw
= (WCHAR
*)alloca(len_0
* sizeof(WCHAR
));
44 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
47 # if defined(_WIN32_WCE) && _WIN32_WCE>=101
48 if (!MultiByteToWideChar(CP_ACP
, 0, lpLibFileName
, len_0
, fnamw
, len_0
))
50 for (i
= 0; i
< len_0
; i
++)
51 fnamw
[i
] = (WCHAR
)lpLibFileName
[i
];
53 return LoadLibraryW(fnamw
);
57 /* Part of the hack in "win32_load" ... */
58 # define DSO_MAX_TRANSLATED_SIZE 256
60 static int win32_load(DSO
*dso
);
61 static int win32_unload(DSO
*dso
);
62 static DSO_FUNC_TYPE
win32_bind_func(DSO
*dso
, const char *symname
);
63 static char *win32_name_converter(DSO
*dso
, const char *filename
);
64 static char *win32_merger(DSO
*dso
, const char *filespec1
,
65 const char *filespec2
);
66 static void *win32_globallookup(const char *name
);
68 static const char *openssl_strnchr(const char *string
, int c
, size_t len
);
70 static DSO_METHOD dso_meth_win32
= {
71 "OpenSSL 'win32' shared library method",
80 NULL
, /* pathbyaddr */
84 DSO_METHOD
*DSO_METHOD_openssl(void)
86 return &dso_meth_win32
;
90 * For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to
91 * the handle (HINSTANCE) returned from LoadLibrary(), and copied.
94 static int win32_load(DSO
*dso
)
96 HINSTANCE h
= NULL
, *p
= NULL
;
97 /* See applicable comments from dso_dl.c */
98 char *filename
= DSO_convert_filename(dso
, NULL
);
100 if (filename
== NULL
) {
101 DSOerr(DSO_F_WIN32_LOAD
, DSO_R_NO_FILENAME
);
104 h
= LoadLibraryA(filename
);
106 DSOerr(DSO_F_WIN32_LOAD
, DSO_R_LOAD_FAILED
);
107 ERR_add_error_data(3, "filename(", filename
, ")");
110 p
= OPENSSL_malloc(sizeof(*p
));
112 DSOerr(DSO_F_WIN32_LOAD
, ERR_R_MALLOC_FAILURE
);
116 if (!sk_void_push(dso
->meth_data
, p
)) {
117 DSOerr(DSO_F_WIN32_LOAD
, DSO_R_STACK_ERROR
);
121 dso
->loaded_filename
= filename
;
125 OPENSSL_free(filename
);
132 static int win32_unload(DSO
*dso
)
136 DSOerr(DSO_F_WIN32_UNLOAD
, ERR_R_PASSED_NULL_PARAMETER
);
139 if (sk_void_num(dso
->meth_data
) < 1)
141 p
= sk_void_pop(dso
->meth_data
);
143 DSOerr(DSO_F_WIN32_UNLOAD
, DSO_R_NULL_HANDLE
);
146 if (!FreeLibrary(*p
)) {
147 DSOerr(DSO_F_WIN32_UNLOAD
, DSO_R_UNLOAD_FAILED
);
149 * We should push the value back onto the stack in case of a retry.
151 sk_void_push(dso
->meth_data
, p
);
159 static DSO_FUNC_TYPE
win32_bind_func(DSO
*dso
, const char *symname
)
167 if ((dso
== NULL
) || (symname
== NULL
)) {
168 DSOerr(DSO_F_WIN32_BIND_FUNC
, ERR_R_PASSED_NULL_PARAMETER
);
171 if (sk_void_num(dso
->meth_data
) < 1) {
172 DSOerr(DSO_F_WIN32_BIND_FUNC
, DSO_R_STACK_ERROR
);
175 ptr
= sk_void_value(dso
->meth_data
, sk_void_num(dso
->meth_data
) - 1);
177 DSOerr(DSO_F_WIN32_BIND_FUNC
, DSO_R_NULL_HANDLE
);
180 sym
.f
= GetProcAddress(*ptr
, symname
);
182 DSOerr(DSO_F_WIN32_BIND_FUNC
, DSO_R_SYM_FAILURE
);
183 ERR_add_error_data(3, "symname(", symname
, ")");
186 return ((DSO_FUNC_TYPE
)sym
.f
);
202 static struct file_st
*win32_splitter(DSO
*dso
, const char *filename
,
203 int assume_last_is_dir
)
205 struct file_st
*result
= NULL
;
206 enum { IN_NODE
, IN_DEVICE
, IN_FILE
} position
;
207 const char *start
= filename
;
211 DSOerr(DSO_F_WIN32_SPLITTER
, DSO_R_NO_FILENAME
);
218 result
= OPENSSL_zalloc(sizeof(*result
));
219 if (result
== NULL
) {
220 DSOerr(DSO_F_WIN32_SPLITTER
, ERR_R_MALLOC_FAILURE
);
224 position
= IN_DEVICE
;
226 if ((filename
[0] == '\\' && filename
[1] == '\\')
227 || (filename
[0] == '/' && filename
[1] == '/')) {
231 result
->node
= start
;
238 if (position
!= IN_DEVICE
) {
239 DSOerr(DSO_F_WIN32_SPLITTER
, DSO_R_INCORRECT_FILE_SYNTAX
);
243 OPENSSL_free(result
);
246 result
->device
= start
;
247 result
->devicelen
= (int)(filename
- start
);
254 if (position
== IN_NODE
) {
255 result
->nodelen
= (int)(filename
- start
);
259 } else if (position
== IN_DEVICE
) {
263 result
->dirlen
= (int)(filename
- start
);
267 result
->dirlen
+= (int)(filename
- start
);
272 if (position
== IN_NODE
) {
273 result
->nodelen
= (int)(filename
- start
);
275 if (filename
- start
> 0) {
276 if (assume_last_is_dir
) {
277 if (position
== IN_DEVICE
) {
281 result
->dirlen
+= (int)(filename
- start
);
283 result
->file
= start
;
284 result
->filelen
= (int)(filename
- start
);
296 if (!result
->nodelen
)
298 if (!result
->devicelen
)
299 result
->device
= NULL
;
302 if (!result
->filelen
)
308 static char *win32_joiner(DSO
*dso
, const struct file_st
*file_split
)
310 int len
= 0, offset
= 0;
315 DSOerr(DSO_F_WIN32_JOINER
, ERR_R_PASSED_NULL_PARAMETER
);
318 if (file_split
->node
) {
319 len
+= 2 + file_split
->nodelen
; /* 2 for starting \\ */
320 if (file_split
->predir
|| file_split
->dir
|| file_split
->file
)
321 len
++; /* 1 for ending \ */
322 } else if (file_split
->device
) {
323 len
+= file_split
->devicelen
+ 1; /* 1 for ending : */
325 len
+= file_split
->predirlen
;
326 if (file_split
->predir
&& (file_split
->dir
|| file_split
->file
)) {
327 len
++; /* 1 for ending \ */
329 len
+= file_split
->dirlen
;
330 if (file_split
->dir
&& file_split
->file
) {
331 len
++; /* 1 for ending \ */
333 len
+= file_split
->filelen
;
336 DSOerr(DSO_F_WIN32_JOINER
, DSO_R_EMPTY_FILE_STRUCTURE
);
340 result
= OPENSSL_malloc(len
+ 1);
341 if (result
== NULL
) {
342 DSOerr(DSO_F_WIN32_JOINER
, ERR_R_MALLOC_FAILURE
);
346 if (file_split
->node
) {
347 strcpy(&result
[offset
], "\\\\");
349 strncpy(&result
[offset
], file_split
->node
, file_split
->nodelen
);
350 offset
+= file_split
->nodelen
;
351 if (file_split
->predir
|| file_split
->dir
|| file_split
->file
) {
352 result
[offset
] = '\\';
355 } else if (file_split
->device
) {
356 strncpy(&result
[offset
], file_split
->device
, file_split
->devicelen
);
357 offset
+= file_split
->devicelen
;
358 result
[offset
] = ':';
361 start
= file_split
->predir
;
362 while (file_split
->predirlen
> (start
- file_split
->predir
)) {
363 const char *end
= openssl_strnchr(start
, '/',
364 file_split
->predirlen
- (start
-
365 file_split
->predir
));
368 + file_split
->predirlen
- (start
- file_split
->predir
);
369 strncpy(&result
[offset
], start
, end
- start
);
370 offset
+= (int)(end
- start
);
371 result
[offset
] = '\\';
375 start
= file_split
->dir
;
376 while (file_split
->dirlen
> (start
- file_split
->dir
)) {
377 const char *end
= openssl_strnchr(start
, '/',
378 file_split
->dirlen
- (start
-
381 end
= start
+ file_split
->dirlen
- (start
- file_split
->dir
);
382 strncpy(&result
[offset
], start
, end
- start
);
383 offset
+= (int)(end
- start
);
384 result
[offset
] = '\\';
388 strncpy(&result
[offset
], file_split
->file
, file_split
->filelen
);
389 offset
+= file_split
->filelen
;
390 result
[offset
] = '\0';
394 static char *win32_merger(DSO
*dso
, const char *filespec1
,
395 const char *filespec2
)
398 struct file_st
*filespec1_split
= NULL
;
399 struct file_st
*filespec2_split
= NULL
;
401 if (!filespec1
&& !filespec2
) {
402 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_PASSED_NULL_PARAMETER
);
406 merged
= OPENSSL_malloc(strlen(filespec1
) + 1);
407 if (merged
== NULL
) {
408 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
411 strcpy(merged
, filespec1
);
412 } else if (!filespec1
) {
413 merged
= OPENSSL_malloc(strlen(filespec2
) + 1);
414 if (merged
== NULL
) {
415 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
418 strcpy(merged
, filespec2
);
420 filespec1_split
= win32_splitter(dso
, filespec1
, 0);
421 if (!filespec1_split
) {
422 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
425 filespec2_split
= win32_splitter(dso
, filespec2
, 1);
426 if (!filespec2_split
) {
427 DSOerr(DSO_F_WIN32_MERGER
, ERR_R_MALLOC_FAILURE
);
428 OPENSSL_free(filespec1_split
);
432 /* Fill in into filespec1_split */
433 if (!filespec1_split
->node
&& !filespec1_split
->device
) {
434 filespec1_split
->node
= filespec2_split
->node
;
435 filespec1_split
->nodelen
= filespec2_split
->nodelen
;
436 filespec1_split
->device
= filespec2_split
->device
;
437 filespec1_split
->devicelen
= filespec2_split
->devicelen
;
439 if (!filespec1_split
->dir
) {
440 filespec1_split
->dir
= filespec2_split
->dir
;
441 filespec1_split
->dirlen
= filespec2_split
->dirlen
;
442 } else if (filespec1_split
->dir
[0] != '\\'
443 && filespec1_split
->dir
[0] != '/') {
444 filespec1_split
->predir
= filespec2_split
->dir
;
445 filespec1_split
->predirlen
= filespec2_split
->dirlen
;
447 if (!filespec1_split
->file
) {
448 filespec1_split
->file
= filespec2_split
->file
;
449 filespec1_split
->filelen
= filespec2_split
->filelen
;
452 merged
= win32_joiner(dso
, filespec1_split
);
454 OPENSSL_free(filespec1_split
);
455 OPENSSL_free(filespec2_split
);
459 static char *win32_name_converter(DSO
*dso
, const char *filename
)
464 len
= strlen(filename
);
465 transform
= ((strstr(filename
, "/") == NULL
) &&
466 (strstr(filename
, "\\") == NULL
) &&
467 (strstr(filename
, ":") == NULL
));
469 /* We will convert this to "%s.dll" */
470 translated
= OPENSSL_malloc(len
+ 5);
472 /* We will simply duplicate filename */
473 translated
= OPENSSL_malloc(len
+ 1);
474 if (translated
== NULL
) {
475 DSOerr(DSO_F_WIN32_NAME_CONVERTER
, DSO_R_NAME_TRANSLATION_FAILED
);
479 sprintf(translated
, "%s.dll", filename
);
481 sprintf(translated
, "%s", filename
);
485 static const char *openssl_strnchr(const char *string
, int c
, size_t len
)
489 for (i
= 0, p
= string
; i
< len
&& *p
; i
++, p
++) {
496 # include <tlhelp32.h>
498 # define DLLNAME "TOOLHELP.DLL"
500 # ifdef MODULEENTRY32
501 # undef MODULEENTRY32 /* unmask the ASCII version! */
503 # define DLLNAME "KERNEL32.DLL"
506 typedef HANDLE(WINAPI
*CREATETOOLHELP32SNAPSHOT
) (DWORD
, DWORD
);
507 typedef BOOL(WINAPI
*CLOSETOOLHELP32SNAPSHOT
) (HANDLE
);
508 typedef BOOL(WINAPI
*MODULE32
) (HANDLE
, MODULEENTRY32
*);
510 static void *win32_globallookup(const char *name
)
513 HANDLE hModuleSnap
= INVALID_HANDLE_VALUE
;
515 CREATETOOLHELP32SNAPSHOT create_snap
;
516 CLOSETOOLHELP32SNAPSHOT close_snap
;
517 MODULE32 module_first
, module_next
;
523 dll
= LoadLibrary(TEXT(DLLNAME
));
525 DSOerr(DSO_F_WIN32_GLOBALLOOKUP
, DSO_R_UNSUPPORTED
);
529 create_snap
= (CREATETOOLHELP32SNAPSHOT
)
530 GetProcAddress(dll
, "CreateToolhelp32Snapshot");
531 if (create_snap
== NULL
) {
533 DSOerr(DSO_F_WIN32_GLOBALLOOKUP
, 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");
546 hModuleSnap
= (*create_snap
) (TH32CS_SNAPMODULE
, 0);
547 if (hModuleSnap
== INVALID_HANDLE_VALUE
) {
549 DSOerr(DSO_F_WIN32_GLOBALLOOKUP
, DSO_R_UNSUPPORTED
);
553 me32
.dwSize
= sizeof(me32
);
555 if (!(*module_first
) (hModuleSnap
, &me32
)) {
556 (*close_snap
) (hModuleSnap
);
562 if ((ret
.f
= GetProcAddress(me32
.hModule
, name
))) {
563 (*close_snap
) (hModuleSnap
);
567 } while ((*module_next
) (hModuleSnap
, &me32
));
569 (*close_snap
) (hModuleSnap
);
573 #endif /* DSO_WIN32 */