source: EcnlProtoTool/trunk/openssl-1.1.0e/crypto/dso/dso_win32.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 16.7 KB
Line 
1/*
2 * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
3 *
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
8 */
9
10#include "dso_locl.h"
11
12#if defined(DSO_WIN32)
13
14# ifdef _WIN32_WCE
15# if _WIN32_WCE < 300
16static FARPROC GetProcAddressA(HMODULE hModule, LPCSTR lpProcName)
17{
18 WCHAR lpProcNameW[64];
19 int i;
20
21 for (i = 0; lpProcName[i] && i < 64; i++)
22 lpProcNameW[i] = (WCHAR)lpProcName[i];
23 if (i == 64)
24 return NULL;
25 lpProcNameW[i] = 0;
26
27 return GetProcAddressW(hModule, lpProcNameW);
28}
29# endif
30# undef GetProcAddress
31# define GetProcAddress GetProcAddressA
32
33static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName)
34{
35 WCHAR *fnamw;
36 size_t len_0 = strlen(lpLibFileName) + 1, i;
37
38# ifdef _MSC_VER
39 fnamw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR));
40# else
41 fnamw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
42# endif
43 if (fnamw == NULL) {
44 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
45 return NULL;
46 }
47# if defined(_WIN32_WCE) && _WIN32_WCE>=101
48 if (!MultiByteToWideChar(CP_ACP, 0, lpLibFileName, len_0, fnamw, len_0))
49# endif
50 for (i = 0; i < len_0; i++)
51 fnamw[i] = (WCHAR)lpLibFileName[i];
52
53 return LoadLibraryW(fnamw);
54}
55# endif
56
57/* Part of the hack in "win32_load" ... */
58# define DSO_MAX_TRANSLATED_SIZE 256
59
60static int win32_load(DSO *dso);
61static int win32_unload(DSO *dso);
62static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname);
63static char *win32_name_converter(DSO *dso, const char *filename);
64static char *win32_merger(DSO *dso, const char *filespec1,
65 const char *filespec2);
66static void *win32_globallookup(const char *name);
67
68static const char *openssl_strnchr(const char *string, int c, size_t len);
69
70static DSO_METHOD dso_meth_win32 = {
71 "OpenSSL 'win32' shared library method",
72 win32_load,
73 win32_unload,
74 win32_bind_func,
75 NULL, /* ctrl */
76 win32_name_converter,
77 win32_merger,
78 NULL, /* init */
79 NULL, /* finish */
80 NULL, /* pathbyaddr */
81 win32_globallookup
82};
83
84DSO_METHOD *DSO_METHOD_openssl(void)
85{
86 return &dso_meth_win32;
87}
88
89/*
90 * For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to
91 * the handle (HINSTANCE) returned from LoadLibrary(), and copied.
92 */
93
94static int win32_load(DSO *dso)
95{
96 HINSTANCE h = NULL, *p = NULL;
97 /* See applicable comments from dso_dl.c */
98 char *filename = DSO_convert_filename(dso, NULL);
99
100 if (filename == NULL) {
101 DSOerr(DSO_F_WIN32_LOAD, DSO_R_NO_FILENAME);
102 goto err;
103 }
104 h = LoadLibraryA(filename);
105 if (h == NULL) {
106 DSOerr(DSO_F_WIN32_LOAD, DSO_R_LOAD_FAILED);
107 ERR_add_error_data(3, "filename(", filename, ")");
108 goto err;
109 }
110 p = OPENSSL_malloc(sizeof(*p));
111 if (p == NULL) {
112 DSOerr(DSO_F_WIN32_LOAD, ERR_R_MALLOC_FAILURE);
113 goto err;
114 }
115 *p = h;
116 if (!sk_void_push(dso->meth_data, p)) {
117 DSOerr(DSO_F_WIN32_LOAD, DSO_R_STACK_ERROR);
118 goto err;
119 }
120 /* Success */
121 dso->loaded_filename = filename;
122 return (1);
123 err:
124 /* Cleanup ! */
125 OPENSSL_free(filename);
126 OPENSSL_free(p);
127 if (h != NULL)
128 FreeLibrary(h);
129 return (0);
130}
131
132static int win32_unload(DSO *dso)
133{
134 HINSTANCE *p;
135 if (dso == NULL) {
136 DSOerr(DSO_F_WIN32_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
137 return (0);
138 }
139 if (sk_void_num(dso->meth_data) < 1)
140 return (1);
141 p = sk_void_pop(dso->meth_data);
142 if (p == NULL) {
143 DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_NULL_HANDLE);
144 return (0);
145 }
146 if (!FreeLibrary(*p)) {
147 DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_UNLOAD_FAILED);
148 /*
149 * We should push the value back onto the stack in case of a retry.
150 */
151 sk_void_push(dso->meth_data, p);
152 return (0);
153 }
154 /* Cleanup */
155 OPENSSL_free(p);
156 return (1);
157}
158
159static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname)
160{
161 HINSTANCE *ptr;
162 union {
163 void *p;
164 FARPROC f;
165 } sym;
166
167 if ((dso == NULL) || (symname == NULL)) {
168 DSOerr(DSO_F_WIN32_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
169 return (NULL);
170 }
171 if (sk_void_num(dso->meth_data) < 1) {
172 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_STACK_ERROR);
173 return (NULL);
174 }
175 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
176 if (ptr == NULL) {
177 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_NULL_HANDLE);
178 return (NULL);
179 }
180 sym.f = GetProcAddress(*ptr, symname);
181 if (sym.p == NULL) {
182 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_SYM_FAILURE);
183 ERR_add_error_data(3, "symname(", symname, ")");
184 return (NULL);
185 }
186 return ((DSO_FUNC_TYPE)sym.f);
187}
188
189struct file_st {
190 const char *node;
191 int nodelen;
192 const char *device;
193 int devicelen;
194 const char *predir;
195 int predirlen;
196 const char *dir;
197 int dirlen;
198 const char *file;
199 int filelen;
200};
201
202static struct file_st *win32_splitter(DSO *dso, const char *filename,
203 int assume_last_is_dir)
204{
205 struct file_st *result = NULL;
206 enum { IN_NODE, IN_DEVICE, IN_FILE } position;
207 const char *start = filename;
208 char last;
209
210 if (!filename) {
211 DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_NO_FILENAME);
212 /*
213 * goto err;
214 */
215 return (NULL);
216 }
217
218 result = OPENSSL_zalloc(sizeof(*result));
219 if (result == NULL) {
220 DSOerr(DSO_F_WIN32_SPLITTER, ERR_R_MALLOC_FAILURE);
221 return (NULL);
222 }
223
224 position = IN_DEVICE;
225
226 if ((filename[0] == '\\' && filename[1] == '\\')
227 || (filename[0] == '/' && filename[1] == '/')) {
228 position = IN_NODE;
229 filename += 2;
230 start = filename;
231 result->node = start;
232 }
233
234 do {
235 last = filename[0];
236 switch (last) {
237 case ':':
238 if (position != IN_DEVICE) {
239 DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_INCORRECT_FILE_SYNTAX);
240 /*
241 * goto err;
242 */
243 OPENSSL_free(result);
244 return (NULL);
245 }
246 result->device = start;
247 result->devicelen = (int)(filename - start);
248 position = IN_FILE;
249 start = ++filename;
250 result->dir = start;
251 break;
252 case '\\':
253 case '/':
254 if (position == IN_NODE) {
255 result->nodelen = (int)(filename - start);
256 position = IN_FILE;
257 start = ++filename;
258 result->dir = start;
259 } else if (position == IN_DEVICE) {
260 position = IN_FILE;
261 filename++;
262 result->dir = start;
263 result->dirlen = (int)(filename - start);
264 start = filename;
265 } else {
266 filename++;
267 result->dirlen += (int)(filename - start);
268 start = filename;
269 }
270 break;
271 case '\0':
272 if (position == IN_NODE) {
273 result->nodelen = (int)(filename - start);
274 } else {
275 if (filename - start > 0) {
276 if (assume_last_is_dir) {
277 if (position == IN_DEVICE) {
278 result->dir = start;
279 result->dirlen = 0;
280 }
281 result->dirlen += (int)(filename - start);
282 } else {
283 result->file = start;
284 result->filelen = (int)(filename - start);
285 }
286 }
287 }
288 break;
289 default:
290 filename++;
291 break;
292 }
293 }
294 while (last);
295
296 if (!result->nodelen)
297 result->node = NULL;
298 if (!result->devicelen)
299 result->device = NULL;
300 if (!result->dirlen)
301 result->dir = NULL;
302 if (!result->filelen)
303 result->file = NULL;
304
305 return (result);
306}
307
308static char *win32_joiner(DSO *dso, const struct file_st *file_split)
309{
310 int len = 0, offset = 0;
311 char *result = NULL;
312 const char *start;
313
314 if (!file_split) {
315 DSOerr(DSO_F_WIN32_JOINER, ERR_R_PASSED_NULL_PARAMETER);
316 return (NULL);
317 }
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 : */
324 }
325 len += file_split->predirlen;
326 if (file_split->predir && (file_split->dir || file_split->file)) {
327 len++; /* 1 for ending \ */
328 }
329 len += file_split->dirlen;
330 if (file_split->dir && file_split->file) {
331 len++; /* 1 for ending \ */
332 }
333 len += file_split->filelen;
334
335 if (!len) {
336 DSOerr(DSO_F_WIN32_JOINER, DSO_R_EMPTY_FILE_STRUCTURE);
337 return (NULL);
338 }
339
340 result = OPENSSL_malloc(len + 1);
341 if (result == NULL) {
342 DSOerr(DSO_F_WIN32_JOINER, ERR_R_MALLOC_FAILURE);
343 return (NULL);
344 }
345
346 if (file_split->node) {
347 strcpy(&result[offset], "\\\\");
348 offset += 2;
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] = '\\';
353 offset++;
354 }
355 } else if (file_split->device) {
356 strncpy(&result[offset], file_split->device, file_split->devicelen);
357 offset += file_split->devicelen;
358 result[offset] = ':';
359 offset++;
360 }
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));
366 if (!end)
367 end = start
368 + file_split->predirlen - (start - file_split->predir);
369 strncpy(&result[offset], start, end - start);
370 offset += (int)(end - start);
371 result[offset] = '\\';
372 offset++;
373 start = end + 1;
374 }
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 -
379 file_split->dir));
380 if (!end)
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] = '\\';
385 offset++;
386 start = end + 1;
387 }
388 strncpy(&result[offset], file_split->file, file_split->filelen);
389 offset += file_split->filelen;
390 result[offset] = '\0';
391 return (result);
392}
393
394static char *win32_merger(DSO *dso, const char *filespec1,
395 const char *filespec2)
396{
397 char *merged = NULL;
398 struct file_st *filespec1_split = NULL;
399 struct file_st *filespec2_split = NULL;
400
401 if (!filespec1 && !filespec2) {
402 DSOerr(DSO_F_WIN32_MERGER, ERR_R_PASSED_NULL_PARAMETER);
403 return (NULL);
404 }
405 if (!filespec2) {
406 merged = OPENSSL_malloc(strlen(filespec1) + 1);
407 if (merged == NULL) {
408 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
409 return (NULL);
410 }
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);
416 return (NULL);
417 }
418 strcpy(merged, filespec2);
419 } else {
420 filespec1_split = win32_splitter(dso, filespec1, 0);
421 if (!filespec1_split) {
422 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
423 return (NULL);
424 }
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);
429 return (NULL);
430 }
431
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;
438 }
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;
446 }
447 if (!filespec1_split->file) {
448 filespec1_split->file = filespec2_split->file;
449 filespec1_split->filelen = filespec2_split->filelen;
450 }
451
452 merged = win32_joiner(dso, filespec1_split);
453 }
454 OPENSSL_free(filespec1_split);
455 OPENSSL_free(filespec2_split);
456 return (merged);
457}
458
459static char *win32_name_converter(DSO *dso, const char *filename)
460{
461 char *translated;
462 int len, transform;
463
464 len = strlen(filename);
465 transform = ((strstr(filename, "/") == NULL) &&
466 (strstr(filename, "\\") == NULL) &&
467 (strstr(filename, ":") == NULL));
468 if (transform)
469 /* We will convert this to "%s.dll" */
470 translated = OPENSSL_malloc(len + 5);
471 else
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);
476 return (NULL);
477 }
478 if (transform)
479 sprintf(translated, "%s.dll", filename);
480 else
481 sprintf(translated, "%s", filename);
482 return (translated);
483}
484
485static const char *openssl_strnchr(const char *string, int c, size_t len)
486{
487 size_t i;
488 const char *p;
489 for (i = 0, p = string; i < len && *p; i++, p++) {
490 if (*p == c)
491 return p;
492 }
493 return NULL;
494}
495
496# include <tlhelp32.h>
497# ifdef _WIN32_WCE
498# define DLLNAME "TOOLHELP.DLL"
499# else
500# ifdef MODULEENTRY32
501# undef MODULEENTRY32 /* unmask the ASCII version! */
502# endif
503# define DLLNAME "KERNEL32.DLL"
504# endif
505
506typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
507typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE);
508typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *);
509
510static void *win32_globallookup(const char *name)
511{
512 HMODULE dll;
513 HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
514 MODULEENTRY32 me32;
515 CREATETOOLHELP32SNAPSHOT create_snap;
516 CLOSETOOLHELP32SNAPSHOT close_snap;
517 MODULE32 module_first, module_next;
518 union {
519 void *p;
520 FARPROC f;
521 } ret = { NULL };
522
523 dll = LoadLibrary(TEXT(DLLNAME));
524 if (dll == NULL) {
525 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
526 return NULL;
527 }
528
529 create_snap = (CREATETOOLHELP32SNAPSHOT)
530 GetProcAddress(dll, "CreateToolhelp32Snapshot");
531 if (create_snap == NULL) {
532 FreeLibrary(dll);
533 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
534 return NULL;
535 }
536 /* We take the rest for granted... */
537# ifdef _WIN32_WCE
538 close_snap = (CLOSETOOLHELP32SNAPSHOT)
539 GetProcAddress(dll, "CloseToolhelp32Snapshot");
540# else
541 close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
542# endif
543 module_first = (MODULE32) GetProcAddress(dll, "Module32First");
544 module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
545
546 hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
547 if (hModuleSnap == INVALID_HANDLE_VALUE) {
548 FreeLibrary(dll);
549 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
550 return NULL;
551 }
552
553 me32.dwSize = sizeof(me32);
554
555 if (!(*module_first) (hModuleSnap, &me32)) {
556 (*close_snap) (hModuleSnap);
557 FreeLibrary(dll);
558 return NULL;
559 }
560
561 do {
562 if ((ret.f = GetProcAddress(me32.hModule, name))) {
563 (*close_snap) (hModuleSnap);
564 FreeLibrary(dll);
565 return ret.p;
566 }
567 } while ((*module_next) (hModuleSnap, &me32));
568
569 (*close_snap) (hModuleSnap);
570 FreeLibrary(dll);
571 return NULL;
572}
573#endif /* DSO_WIN32 */
Note: See TracBrowser for help on using the repository browser.