Home | History | Annotate | Download | only in dso
      1 /* dso_win32.c -*- mode:C; c-file-style: "eay" -*- */
      2 /* Written by Geoff Thorpe (geoff (at) geoffthorpe.net) for the OpenSSL
      3  * project 2000.
      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
     13  *    notice, this list of conditions and the following disclaimer.
     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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     55  * Hudson (tjh (at) cryptsoft.com).
     56  *
     57  */
     58 
     59 #include <stdio.h>
     60 #include <string.h>
     61 #include "cryptlib.h"
     62 #include <openssl/dso.h>
     63 
     64 #if !defined(DSO_WIN32)
     65 DSO_METHOD *DSO_METHOD_win32(void)
     66 	{
     67 	return NULL;
     68 	}
     69 #else
     70 
     71 #ifdef _WIN32_WCE
     72 # if _WIN32_WCE < 300
     73 static FARPROC GetProcAddressA(HMODULE hModule,LPCSTR lpProcName)
     74 	{
     75 	WCHAR lpProcNameW[64];
     76 	int i;
     77 
     78 	for (i=0;lpProcName[i] && i<64;i++)
     79 		lpProcNameW[i] = (WCHAR)lpProcName[i];
     80 	if (i==64) return NULL;
     81 	lpProcNameW[i] = 0;
     82 
     83 	return GetProcAddressW(hModule,lpProcNameW);
     84 	}
     85 # endif
     86 # undef GetProcAddress
     87 # define GetProcAddress GetProcAddressA
     88 
     89 static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName)
     90 	{
     91 	WCHAR *fnamw;
     92 	size_t len_0=strlen(lpLibFileName)+1,i;
     93 
     94 #ifdef _MSC_VER
     95 	fnamw = (WCHAR *)_alloca (len_0*sizeof(WCHAR));
     96 #else
     97 	fnamw = (WCHAR *)alloca (len_0*sizeof(WCHAR));
     98 #endif
     99 	if (fnamw == NULL)
    100 		{
    101 		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
    102 		return NULL;
    103 		}
    104 
    105 #if defined(_WIN32_WCE) && _WIN32_WCE>=101
    106 	if (!MultiByteToWideChar(CP_ACP,0,lpLibFileName,len_0,fnamw,len_0))
    107 #endif
    108 		for (i=0;i<len_0;i++) fnamw[i]=(WCHAR)lpLibFileName[i];
    109 
    110 	return LoadLibraryW(fnamw);
    111 	}
    112 #endif
    113 
    114 /* Part of the hack in "win32_load" ... */
    115 #define DSO_MAX_TRANSLATED_SIZE 256
    116 
    117 static int win32_load(DSO *dso);
    118 static int win32_unload(DSO *dso);
    119 static void *win32_bind_var(DSO *dso, const char *symname);
    120 static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname);
    121 #if 0
    122 static int win32_unbind_var(DSO *dso, char *symname, void *symptr);
    123 static int win32_unbind_func(DSO *dso, char *symname, DSO_FUNC_TYPE symptr);
    124 static int win32_init(DSO *dso);
    125 static int win32_finish(DSO *dso);
    126 static long win32_ctrl(DSO *dso, int cmd, long larg, void *parg);
    127 #endif
    128 static char *win32_name_converter(DSO *dso, const char *filename);
    129 static char *win32_merger(DSO *dso, const char *filespec1,
    130 	const char *filespec2);
    131 static int win32_pathbyaddr(void *addr,char *path,int sz);
    132 static void *win32_globallookup(const char *name);
    133 
    134 static const char *openssl_strnchr(const char *string, int c, size_t len);
    135 
    136 static DSO_METHOD dso_meth_win32 = {
    137 	"OpenSSL 'win32' shared library method",
    138 	win32_load,
    139 	win32_unload,
    140 	win32_bind_var,
    141 	win32_bind_func,
    142 /* For now, "unbind" doesn't exist */
    143 #if 0
    144 	NULL, /* unbind_var */
    145 	NULL, /* unbind_func */
    146 #endif
    147 	NULL, /* ctrl */
    148 	win32_name_converter,
    149 	win32_merger,
    150 	NULL, /* init */
    151 	NULL, /* finish */
    152 	win32_pathbyaddr,
    153 	win32_globallookup
    154 	};
    155 
    156 DSO_METHOD *DSO_METHOD_win32(void)
    157 	{
    158 	return(&dso_meth_win32);
    159 	}
    160 
    161 /* For this DSO_METHOD, our meth_data STACK will contain;
    162  * (i) a pointer to the handle (HINSTANCE) returned from
    163  *     LoadLibrary(), and copied.
    164  */
    165 
    166 static int win32_load(DSO *dso)
    167 	{
    168 	HINSTANCE h = NULL, *p = NULL;
    169 	/* See applicable comments from dso_dl.c */
    170 	char *filename = DSO_convert_filename(dso, NULL);
    171 
    172 	if(filename == NULL)
    173 		{
    174 		DSOerr(DSO_F_WIN32_LOAD,DSO_R_NO_FILENAME);
    175 		goto err;
    176 		}
    177 	h = LoadLibraryA(filename);
    178 	if(h == NULL)
    179 		{
    180 		DSOerr(DSO_F_WIN32_LOAD,DSO_R_LOAD_FAILED);
    181 		ERR_add_error_data(3, "filename(", filename, ")");
    182 		goto err;
    183 		}
    184 	p = (HINSTANCE *)OPENSSL_malloc(sizeof(HINSTANCE));
    185 	if(p == NULL)
    186 		{
    187 		DSOerr(DSO_F_WIN32_LOAD,ERR_R_MALLOC_FAILURE);
    188 		goto err;
    189 		}
    190 	*p = h;
    191 	if(!sk_void_push(dso->meth_data, p))
    192 		{
    193 		DSOerr(DSO_F_WIN32_LOAD,DSO_R_STACK_ERROR);
    194 		goto err;
    195 		}
    196 	/* Success */
    197 	dso->loaded_filename = filename;
    198 	return(1);
    199 err:
    200 	/* Cleanup !*/
    201 	if(filename != NULL)
    202 		OPENSSL_free(filename);
    203 	if(p != NULL)
    204 		OPENSSL_free(p);
    205 	if(h != NULL)
    206 		FreeLibrary(h);
    207 	return(0);
    208 	}
    209 
    210 static int win32_unload(DSO *dso)
    211 	{
    212 	HINSTANCE *p;
    213 	if(dso == NULL)
    214 		{
    215 		DSOerr(DSO_F_WIN32_UNLOAD,ERR_R_PASSED_NULL_PARAMETER);
    216 		return(0);
    217 		}
    218 	if(sk_void_num(dso->meth_data) < 1)
    219 		return(1);
    220 	p = sk_void_pop(dso->meth_data);
    221 	if(p == NULL)
    222 		{
    223 		DSOerr(DSO_F_WIN32_UNLOAD,DSO_R_NULL_HANDLE);
    224 		return(0);
    225 		}
    226 	if(!FreeLibrary(*p))
    227 		{
    228 		DSOerr(DSO_F_WIN32_UNLOAD,DSO_R_UNLOAD_FAILED);
    229 		/* We should push the value back onto the stack in
    230 		 * case of a retry. */
    231 		sk_void_push(dso->meth_data, p);
    232 		return(0);
    233 		}
    234 	/* Cleanup */
    235 	OPENSSL_free(p);
    236 	return(1);
    237 	}
    238 
    239 /* Using GetProcAddress for variables? TODO: Check this out in
    240  * the Win32 API docs, there's probably a variant for variables. */
    241 static void *win32_bind_var(DSO *dso, const char *symname)
    242 	{
    243 	HINSTANCE *ptr;
    244 	void *sym;
    245 
    246 	if((dso == NULL) || (symname == NULL))
    247 		{
    248 		DSOerr(DSO_F_WIN32_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER);
    249 		return(NULL);
    250 		}
    251 	if(sk_void_num(dso->meth_data) < 1)
    252 		{
    253 		DSOerr(DSO_F_WIN32_BIND_VAR,DSO_R_STACK_ERROR);
    254 		return(NULL);
    255 		}
    256 	ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
    257 	if(ptr == NULL)
    258 		{
    259 		DSOerr(DSO_F_WIN32_BIND_VAR,DSO_R_NULL_HANDLE);
    260 		return(NULL);
    261 		}
    262 	sym = GetProcAddress(*ptr, symname);
    263 	if(sym == NULL)
    264 		{
    265 		DSOerr(DSO_F_WIN32_BIND_VAR,DSO_R_SYM_FAILURE);
    266 		ERR_add_error_data(3, "symname(", symname, ")");
    267 		return(NULL);
    268 		}
    269 	return(sym);
    270 	}
    271 
    272 static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname)
    273 	{
    274 	HINSTANCE *ptr;
    275 	void *sym;
    276 
    277 	if((dso == NULL) || (symname == NULL))
    278 		{
    279 		DSOerr(DSO_F_WIN32_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER);
    280 		return(NULL);
    281 		}
    282 	if(sk_void_num(dso->meth_data) < 1)
    283 		{
    284 		DSOerr(DSO_F_WIN32_BIND_FUNC,DSO_R_STACK_ERROR);
    285 		return(NULL);
    286 		}
    287 	ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
    288 	if(ptr == NULL)
    289 		{
    290 		DSOerr(DSO_F_WIN32_BIND_FUNC,DSO_R_NULL_HANDLE);
    291 		return(NULL);
    292 		}
    293 	sym = GetProcAddress(*ptr, symname);
    294 	if(sym == NULL)
    295 		{
    296 		DSOerr(DSO_F_WIN32_BIND_FUNC,DSO_R_SYM_FAILURE);
    297 		ERR_add_error_data(3, "symname(", symname, ")");
    298 		return(NULL);
    299 		}
    300 	return((DSO_FUNC_TYPE)sym);
    301 	}
    302 
    303 struct file_st
    304 	{
    305 	const char *node; int nodelen;
    306 	const char *device; int devicelen;
    307 	const char *predir; int predirlen;
    308 	const char *dir; int dirlen;
    309 	const char *file; int filelen;
    310 	};
    311 
    312 static struct file_st *win32_splitter(DSO *dso, const char *filename,
    313 	int assume_last_is_dir)
    314 	{
    315 	struct file_st *result = NULL;
    316 	enum { IN_NODE, IN_DEVICE, IN_FILE } position;
    317 	const char *start = filename;
    318 	char last;
    319 
    320 	if (!filename)
    321 		{
    322 		DSOerr(DSO_F_WIN32_SPLITTER,DSO_R_NO_FILENAME);
    323 		/*goto err;*/
    324 		return(NULL);
    325 		}
    326 
    327 	result = OPENSSL_malloc(sizeof(struct file_st));
    328 	if(result == NULL)
    329 		{
    330 		DSOerr(DSO_F_WIN32_SPLITTER,
    331 			ERR_R_MALLOC_FAILURE);
    332 		return(NULL);
    333 		}
    334 
    335 	memset(result, 0, sizeof(struct file_st));
    336 	position = IN_DEVICE;
    337 
    338 	if((filename[0] == '\\' && filename[1] == '\\')
    339 		|| (filename[0] == '/' && filename[1] == '/'))
    340 		{
    341 		position = IN_NODE;
    342 		filename += 2;
    343 		start = filename;
    344 		result->node = start;
    345 		}
    346 
    347 	do
    348 		{
    349 		last = filename[0];
    350 		switch(last)
    351 			{
    352 		case ':':
    353 			if(position != IN_DEVICE)
    354 				{
    355 				DSOerr(DSO_F_WIN32_SPLITTER,
    356 					DSO_R_INCORRECT_FILE_SYNTAX);
    357 				/*goto err;*/
    358 				OPENSSL_free(result);
    359 				return(NULL);
    360 				}
    361 			result->device = start;
    362 			result->devicelen = (int)(filename - start);
    363 			position = IN_FILE;
    364 			start = ++filename;
    365 			result->dir = start;
    366 			break;
    367 		case '\\':
    368 		case '/':
    369 			if(position == IN_NODE)
    370 				{
    371 				result->nodelen = (int)(filename - start);
    372 				position = IN_FILE;
    373 				start = ++filename;
    374 				result->dir = start;
    375 				}
    376 			else if(position == IN_DEVICE)
    377 				{
    378 				position = IN_FILE;
    379 				filename++;
    380 				result->dir = start;
    381 				result->dirlen = (int)(filename - start);
    382 				start = filename;
    383 				}
    384 			else
    385 				{
    386 				filename++;
    387 				result->dirlen += (int)(filename - start);
    388 				start = filename;
    389 				}
    390 			break;
    391 		case '\0':
    392 			if(position == IN_NODE)
    393 				{
    394 				result->nodelen = (int)(filename - start);
    395 				}
    396 			else
    397 				{
    398 				if(filename - start > 0)
    399 					{
    400 					if (assume_last_is_dir)
    401 						{
    402 						if (position == IN_DEVICE)
    403 							{
    404 							result->dir = start;
    405 							result->dirlen = 0;
    406 							}
    407 						result->dirlen +=
    408 							(int)(filename - start);
    409 						}
    410 					else
    411 						{
    412 						result->file = start;
    413 						result->filelen =
    414 							(int)(filename - start);
    415 						}
    416 					}
    417 				}
    418 			break;
    419 		default:
    420 			filename++;
    421 			break;
    422 			}
    423 		}
    424 	while(last);
    425 
    426 	if(!result->nodelen) result->node = NULL;
    427 	if(!result->devicelen) result->device = NULL;
    428 	if(!result->dirlen) result->dir = NULL;
    429 	if(!result->filelen) result->file = NULL;
    430 
    431 	return(result);
    432 	}
    433 
    434 static char *win32_joiner(DSO *dso, const struct file_st *file_split)
    435 	{
    436 	int len = 0, offset = 0;
    437 	char *result = NULL;
    438 	const char *start;
    439 
    440 	if(!file_split)
    441 		{
    442 		DSOerr(DSO_F_WIN32_JOINER,
    443 				ERR_R_PASSED_NULL_PARAMETER);
    444 		return(NULL);
    445 		}
    446 	if(file_split->node)
    447 		{
    448 		len += 2 + file_split->nodelen;	/* 2 for starting \\ */
    449 		if(file_split->predir || file_split->dir || file_split->file)
    450 			len++;	/* 1 for ending \ */
    451 		}
    452 	else if(file_split->device)
    453 		{
    454 		len += file_split->devicelen + 1; /* 1 for ending : */
    455 		}
    456 	len += file_split->predirlen;
    457 	if(file_split->predir && (file_split->dir || file_split->file))
    458 		{
    459 		len++;	/* 1 for ending \ */
    460 		}
    461 	len += file_split->dirlen;
    462 	if(file_split->dir && file_split->file)
    463 		{
    464 		len++;	/* 1 for ending \ */
    465 		}
    466 	len += file_split->filelen;
    467 
    468 	if(!len)
    469 		{
    470 		DSOerr(DSO_F_WIN32_JOINER, DSO_R_EMPTY_FILE_STRUCTURE);
    471 		return(NULL);
    472 		}
    473 
    474 	result = OPENSSL_malloc(len + 1);
    475 	if (!result)
    476 		{
    477 		DSOerr(DSO_F_WIN32_JOINER,
    478 			ERR_R_MALLOC_FAILURE);
    479 		return(NULL);
    480 		}
    481 
    482 	if(file_split->node)
    483 		{
    484 		strcpy(&result[offset], "\\\\"); offset += 2;
    485 		strncpy(&result[offset], file_split->node,
    486 			file_split->nodelen); offset += file_split->nodelen;
    487 		if(file_split->predir || file_split->dir || file_split->file)
    488 			{
    489 			result[offset] = '\\'; offset++;
    490 			}
    491 		}
    492 	else if(file_split->device)
    493 		{
    494 		strncpy(&result[offset], file_split->device,
    495 			file_split->devicelen); offset += file_split->devicelen;
    496 		result[offset] = ':'; offset++;
    497 		}
    498 	start = file_split->predir;
    499 	while(file_split->predirlen > (start - file_split->predir))
    500 		{
    501 		const char *end = openssl_strnchr(start, '/',
    502 			file_split->predirlen - (start - file_split->predir));
    503 		if(!end)
    504 			end = start
    505 				+ file_split->predirlen
    506 				- (start - file_split->predir);
    507 		strncpy(&result[offset], start,
    508 			end - start); offset += (int)(end - start);
    509 		result[offset] = '\\'; offset++;
    510 		start = end + 1;
    511 		}
    512 #if 0 /* Not needed, since the directory converter above already appeneded
    513 	 a backslash */
    514 	if(file_split->predir && (file_split->dir || file_split->file))
    515 		{
    516 		result[offset] = '\\'; offset++;
    517 		}
    518 #endif
    519 	start = file_split->dir;
    520 	while(file_split->dirlen > (start - file_split->dir))
    521 		{
    522 		const char *end = openssl_strnchr(start, '/',
    523 			file_split->dirlen - (start - file_split->dir));
    524 		if(!end)
    525 			end = start
    526 				+ file_split->dirlen
    527 				- (start - file_split->dir);
    528 		strncpy(&result[offset], start,
    529 			end - start); offset += (int)(end - start);
    530 		result[offset] = '\\'; offset++;
    531 		start = end + 1;
    532 		}
    533 #if 0 /* Not needed, since the directory converter above already appeneded
    534 	 a backslash */
    535 	if(file_split->dir && file_split->file)
    536 		{
    537 		result[offset] = '\\'; offset++;
    538 		}
    539 #endif
    540 	strncpy(&result[offset], file_split->file,
    541 		file_split->filelen); offset += file_split->filelen;
    542 	result[offset] = '\0';
    543 	return(result);
    544 	}
    545 
    546 static char *win32_merger(DSO *dso, const char *filespec1, const char *filespec2)
    547 	{
    548 	char *merged = NULL;
    549 	struct file_st *filespec1_split = NULL;
    550 	struct file_st *filespec2_split = NULL;
    551 
    552 	if(!filespec1 && !filespec2)
    553 		{
    554 		DSOerr(DSO_F_WIN32_MERGER,
    555 				ERR_R_PASSED_NULL_PARAMETER);
    556 		return(NULL);
    557 		}
    558 	if (!filespec2)
    559 		{
    560 		merged = OPENSSL_malloc(strlen(filespec1) + 1);
    561 		if(!merged)
    562 			{
    563 			DSOerr(DSO_F_WIN32_MERGER,
    564 				ERR_R_MALLOC_FAILURE);
    565 			return(NULL);
    566 			}
    567 		strcpy(merged, filespec1);
    568 		}
    569 	else if (!filespec1)
    570 		{
    571 		merged = OPENSSL_malloc(strlen(filespec2) + 1);
    572 		if(!merged)
    573 			{
    574 			DSOerr(DSO_F_WIN32_MERGER,
    575 				ERR_R_MALLOC_FAILURE);
    576 			return(NULL);
    577 			}
    578 		strcpy(merged, filespec2);
    579 		}
    580 	else
    581 		{
    582 		filespec1_split = win32_splitter(dso, filespec1, 0);
    583 		if (!filespec1_split)
    584 			{
    585 			DSOerr(DSO_F_WIN32_MERGER,
    586 				ERR_R_MALLOC_FAILURE);
    587 			return(NULL);
    588 			}
    589 		filespec2_split = win32_splitter(dso, filespec2, 1);
    590 		if (!filespec2_split)
    591 			{
    592 			DSOerr(DSO_F_WIN32_MERGER,
    593 				ERR_R_MALLOC_FAILURE);
    594 			OPENSSL_free(filespec1_split);
    595 			return(NULL);
    596 			}
    597 
    598 		/* Fill in into filespec1_split */
    599 		if (!filespec1_split->node && !filespec1_split->device)
    600 			{
    601 			filespec1_split->node = filespec2_split->node;
    602 			filespec1_split->nodelen = filespec2_split->nodelen;
    603 			filespec1_split->device = filespec2_split->device;
    604 			filespec1_split->devicelen = filespec2_split->devicelen;
    605 			}
    606 		if (!filespec1_split->dir)
    607 			{
    608 			filespec1_split->dir = filespec2_split->dir;
    609 			filespec1_split->dirlen = filespec2_split->dirlen;
    610 			}
    611 		else if (filespec1_split->dir[0] != '\\'
    612 			&& filespec1_split->dir[0] != '/')
    613 			{
    614 			filespec1_split->predir = filespec2_split->dir;
    615 			filespec1_split->predirlen = filespec2_split->dirlen;
    616 			}
    617 		if (!filespec1_split->file)
    618 			{
    619 			filespec1_split->file = filespec2_split->file;
    620 			filespec1_split->filelen = filespec2_split->filelen;
    621 			}
    622 
    623 		merged = win32_joiner(dso, filespec1_split);
    624 		}
    625 	OPENSSL_free(filespec1_split);
    626 	OPENSSL_free(filespec2_split);
    627 	return(merged);
    628 	}
    629 
    630 static char *win32_name_converter(DSO *dso, const char *filename)
    631 	{
    632 	char *translated;
    633 	int len, transform;
    634 
    635 	len = strlen(filename);
    636 	transform = ((strstr(filename, "/") == NULL) &&
    637 			(strstr(filename, "\\") == NULL) &&
    638 			(strstr(filename, ":") == NULL));
    639 	if(transform)
    640 		/* We will convert this to "%s.dll" */
    641 		translated = OPENSSL_malloc(len + 5);
    642 	else
    643 		/* We will simply duplicate filename */
    644 		translated = OPENSSL_malloc(len + 1);
    645 	if(translated == NULL)
    646 		{
    647 		DSOerr(DSO_F_WIN32_NAME_CONVERTER,
    648 				DSO_R_NAME_TRANSLATION_FAILED);
    649 		return(NULL);
    650 		}
    651 	if(transform)
    652 		sprintf(translated, "%s.dll", filename);
    653 	else
    654 		sprintf(translated, "%s", filename);
    655 	return(translated);
    656 	}
    657 
    658 static const char *openssl_strnchr(const char *string, int c, size_t len)
    659 	{
    660 	size_t i;
    661 	const char *p;
    662 	for (i = 0, p = string; i < len && *p; i++, p++)
    663 		{
    664 		if (*p == c)
    665 			return p;
    666 		}
    667 	return NULL;
    668 	}
    669 
    670 #include <tlhelp32.h>
    671 #ifdef _WIN32_WCE
    672 # define DLLNAME "TOOLHELP.DLL"
    673 #else
    674 # ifdef MODULEENTRY32
    675 # undef MODULEENTRY32	/* unmask the ASCII version! */
    676 # endif
    677 # define DLLNAME "KERNEL32.DLL"
    678 #endif
    679 
    680 typedef HANDLE (WINAPI *CREATETOOLHELP32SNAPSHOT)(DWORD, DWORD);
    681 typedef BOOL (WINAPI *CLOSETOOLHELP32SNAPSHOT)(HANDLE);
    682 typedef BOOL (WINAPI *MODULE32)(HANDLE, MODULEENTRY32 *);
    683 
    684 static int win32_pathbyaddr(void *addr,char *path,int sz)
    685 	{
    686 	HMODULE dll;
    687 	HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    688 	MODULEENTRY32 me32;
    689 	CREATETOOLHELP32SNAPSHOT create_snap;
    690 	CLOSETOOLHELP32SNAPSHOT  close_snap;
    691 	MODULE32 module_first, module_next;
    692 	int len;
    693 
    694 	if (addr == NULL)
    695 		{
    696 		union	{ int(*f)(void*,char*,int); void *p; } t =
    697 			{ win32_pathbyaddr };
    698 		addr = t.p;
    699 		}
    700 
    701 	dll = LoadLibrary(TEXT(DLLNAME));
    702 	if (dll == NULL)
    703 		{
    704 		DSOerr(DSO_F_WIN32_PATHBYADDR,DSO_R_UNSUPPORTED);
    705 		return -1;
    706 		}
    707 
    708 	create_snap = (CREATETOOLHELP32SNAPSHOT)
    709 		GetProcAddress(dll,"CreateToolhelp32Snapshot");
    710 	if (create_snap == NULL)
    711 		{
    712 		FreeLibrary(dll);
    713 		DSOerr(DSO_F_WIN32_PATHBYADDR,DSO_R_UNSUPPORTED);
    714 		return -1;
    715 		}
    716 	/* We take the rest for granted... */
    717 #ifdef _WIN32_WCE
    718 	close_snap = (CLOSETOOLHELP32SNAPSHOT)
    719 		GetProcAddress(dll,"CloseToolhelp32Snapshot");
    720 #else
    721 	close_snap = (CLOSETOOLHELP32SNAPSHOT)CloseHandle;
    722 #endif
    723 	module_first = (MODULE32)GetProcAddress(dll,"Module32First");
    724 	module_next  = (MODULE32)GetProcAddress(dll,"Module32Next");
    725 
    726 	hModuleSnap = (*create_snap)(TH32CS_SNAPMODULE,0);
    727 	if( hModuleSnap == INVALID_HANDLE_VALUE )
    728 		{
    729 		FreeLibrary(dll);
    730 		DSOerr(DSO_F_WIN32_PATHBYADDR,DSO_R_UNSUPPORTED);
    731 		return -1;
    732 		}
    733 
    734 	me32.dwSize = sizeof(me32);
    735 
    736 	if(!(*module_first)(hModuleSnap,&me32))
    737 		{
    738 		(*close_snap)(hModuleSnap);
    739 		FreeLibrary(dll);
    740 		DSOerr(DSO_F_WIN32_PATHBYADDR,DSO_R_FAILURE);
    741 		return -1;
    742 		}
    743 
    744 	do	{
    745 		if ((BYTE *)addr >= me32.modBaseAddr &&
    746 		    (BYTE *)addr <  me32.modBaseAddr+me32.modBaseSize)
    747 			{
    748 			(*close_snap)(hModuleSnap);
    749 			FreeLibrary(dll);
    750 #ifdef _WIN32_WCE
    751 # if _WIN32_WCE >= 101
    752 			return WideCharToMultiByte(CP_ACP,0,me32.szExePath,-1,
    753 							path,sz,NULL,NULL);
    754 # else
    755 			len = (int)wcslen(me32.szExePath);
    756 			if (sz <= 0) return len+1;
    757 			if (len >= sz) len=sz-1;
    758 			for(i=0;i<len;i++)
    759 				path[i] = (char)me32.szExePath[i];
    760 			path[len++] = 0;
    761 			return len;
    762 # endif
    763 #else
    764 			len = (int)strlen(me32.szExePath);
    765 			if (sz <= 0) return len+1;
    766 			if (len >= sz) len=sz-1;
    767 			memcpy(path,me32.szExePath,len);
    768 			path[len++] = 0;
    769 			return len;
    770 #endif
    771 			}
    772 		} while((*module_next)(hModuleSnap, &me32));
    773 
    774 	(*close_snap)(hModuleSnap);
    775 	FreeLibrary(dll);
    776 	return 0;
    777 	}
    778 
    779 static void *win32_globallookup(const char *name)
    780 	{
    781 	HMODULE dll;
    782 	HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    783 	MODULEENTRY32 me32;
    784 	CREATETOOLHELP32SNAPSHOT create_snap;
    785 	CLOSETOOLHELP32SNAPSHOT  close_snap;
    786 	MODULE32 module_first, module_next;
    787 	FARPROC ret=NULL;
    788 
    789 	dll = LoadLibrary(TEXT(DLLNAME));
    790 	if (dll == NULL)
    791 		{
    792 		DSOerr(DSO_F_WIN32_GLOBALLOOKUP,DSO_R_UNSUPPORTED);
    793 		return NULL;
    794 		}
    795 
    796 	create_snap = (CREATETOOLHELP32SNAPSHOT)
    797 		GetProcAddress(dll,"CreateToolhelp32Snapshot");
    798 	if (create_snap == NULL)
    799 		{
    800 		FreeLibrary(dll);
    801 		DSOerr(DSO_F_WIN32_GLOBALLOOKUP,DSO_R_UNSUPPORTED);
    802 		return NULL;
    803 		}
    804 	/* We take the rest for granted... */
    805 #ifdef _WIN32_WCE
    806 	close_snap = (CLOSETOOLHELP32SNAPSHOT)
    807 		GetProcAddress(dll,"CloseToolhelp32Snapshot");
    808 #else
    809 	close_snap = (CLOSETOOLHELP32SNAPSHOT)CloseHandle;
    810 #endif
    811 	module_first = (MODULE32)GetProcAddress(dll,"Module32First");
    812 	module_next  = (MODULE32)GetProcAddress(dll,"Module32Next");
    813 
    814 	hModuleSnap = (*create_snap)(TH32CS_SNAPMODULE,0);
    815 	if( hModuleSnap == INVALID_HANDLE_VALUE )
    816 		{
    817 		FreeLibrary(dll);
    818 		DSOerr(DSO_F_WIN32_GLOBALLOOKUP,DSO_R_UNSUPPORTED);
    819 		return NULL;
    820 		}
    821 
    822 	me32.dwSize = sizeof(me32);
    823 
    824 	if (!(*module_first)(hModuleSnap,&me32))
    825 		{
    826 		(*close_snap)(hModuleSnap);
    827 		FreeLibrary(dll);
    828 		return NULL;
    829 		}
    830 
    831 	do	{
    832 		if ((ret = GetProcAddress(me32.hModule,name)))
    833 			{
    834 			(*close_snap)(hModuleSnap);
    835 			FreeLibrary(dll);
    836 			return ret;
    837 			}
    838 		} while((*module_next)(hModuleSnap,&me32));
    839 
    840 	(*close_snap)(hModuleSnap);
    841 	FreeLibrary(dll);
    842 	return NULL;
    843 	}
    844 #endif /* DSO_WIN32 */
    845