xref: /onnv-gate/usr/src/common/openssl/crypto/dso/dso_win32.c (revision 2139:6243c3338933)
1*2139Sjp161948 /* dso_win32.c -*- mode:C; c-file-style: "eay" -*- */
20Sstevel@tonic-gate /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
30Sstevel@tonic-gate  * project 2000.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate /* ====================================================================
60Sstevel@tonic-gate  * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
90Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
100Sstevel@tonic-gate  * are met:
110Sstevel@tonic-gate  *
120Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
130Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
160Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
170Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
180Sstevel@tonic-gate  *    distribution.
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
210Sstevel@tonic-gate  *    software must display the following acknowledgment:
220Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
230Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
260Sstevel@tonic-gate  *    endorse or promote products derived from this software without
270Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
280Sstevel@tonic-gate  *    licensing@OpenSSL.org.
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
310Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
320Sstevel@tonic-gate  *    permission of the OpenSSL Project.
330Sstevel@tonic-gate  *
340Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
350Sstevel@tonic-gate  *    acknowledgment:
360Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
370Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
380Sstevel@tonic-gate  *
390Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
400Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
410Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
420Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
430Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
440Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
450Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
460Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
470Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
480Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
490Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
500Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
510Sstevel@tonic-gate  * ====================================================================
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
540Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
550Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #include <stdio.h>
600Sstevel@tonic-gate #include <string.h>
610Sstevel@tonic-gate #include "cryptlib.h"
620Sstevel@tonic-gate #include <openssl/dso.h>
630Sstevel@tonic-gate 
64*2139Sjp161948 #if !defined(DSO_WIN32)
DSO_METHOD_win32(void)650Sstevel@tonic-gate DSO_METHOD *DSO_METHOD_win32(void)
660Sstevel@tonic-gate 	{
670Sstevel@tonic-gate 	return NULL;
680Sstevel@tonic-gate 	}
690Sstevel@tonic-gate #else
700Sstevel@tonic-gate 
71*2139Sjp161948 #ifdef _WIN32_WCE
72*2139Sjp161948 # if _WIN32_WCE < 300
GetProcAddressA(HMODULE hModule,LPCSTR lpProcName)73*2139Sjp161948 static FARPROC GetProcAddressA(HMODULE hModule,LPCSTR lpProcName)
74*2139Sjp161948 	{
75*2139Sjp161948 	WCHAR lpProcNameW[64];
76*2139Sjp161948 	int i;
77*2139Sjp161948 
78*2139Sjp161948 	for (i=0;lpProcName[i] && i<64;i++)
79*2139Sjp161948 		lpProcNameW[i] = (WCHAR)lpProcName[i];
80*2139Sjp161948 	if (i==64) return NULL;
81*2139Sjp161948 	lpProcNameW[i] = 0;
82*2139Sjp161948 
83*2139Sjp161948 	return GetProcAddressW(hModule,lpProcNameW);
84*2139Sjp161948 	}
85*2139Sjp161948 # endif
86*2139Sjp161948 # undef GetProcAddress
87*2139Sjp161948 # define GetProcAddress GetProcAddressA
88*2139Sjp161948 
LoadLibraryA(LPCSTR lpLibFileName)89*2139Sjp161948 static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName)
90*2139Sjp161948 	{
91*2139Sjp161948 	WCHAR *fnamw;
92*2139Sjp161948 	size_t len_0=strlen(lpLibFileName)+1,i;
93*2139Sjp161948 
94*2139Sjp161948 #ifdef _MSC_VER
95*2139Sjp161948 	fnamw = (WCHAR *)_alloca (len_0*sizeof(WCHAR));
96*2139Sjp161948 #else
97*2139Sjp161948 	fnamw = (WCHAR *)alloca (len_0*sizeof(WCHAR));
98*2139Sjp161948 #endif
99*2139Sjp161948 	if (fnamw == NULL) return NULL;
100*2139Sjp161948 
101*2139Sjp161948 #if defined(_WIN32_WCE) && _WIN32_WCE>=101
102*2139Sjp161948 	if (!MultiByteToWideChar(CP_ACP,0,lpLibFileName,len_0,fnamw,len_0))
103*2139Sjp161948 #endif
104*2139Sjp161948 		for (i=0;i<len_0;i++) fnamw[i]=(WCHAR)lpLibFileName[i];
105*2139Sjp161948 
106*2139Sjp161948 	return LoadLibraryW(fnamw);
107*2139Sjp161948 	}
108*2139Sjp161948 #endif
109*2139Sjp161948 
1100Sstevel@tonic-gate /* Part of the hack in "win32_load" ... */
1110Sstevel@tonic-gate #define DSO_MAX_TRANSLATED_SIZE 256
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate static int win32_load(DSO *dso);
1140Sstevel@tonic-gate static int win32_unload(DSO *dso);
1150Sstevel@tonic-gate static void *win32_bind_var(DSO *dso, const char *symname);
1160Sstevel@tonic-gate static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname);
1170Sstevel@tonic-gate #if 0
1180Sstevel@tonic-gate static int win32_unbind_var(DSO *dso, char *symname, void *symptr);
1190Sstevel@tonic-gate static int win32_unbind_func(DSO *dso, char *symname, DSO_FUNC_TYPE symptr);
1200Sstevel@tonic-gate static int win32_init(DSO *dso);
1210Sstevel@tonic-gate static int win32_finish(DSO *dso);
1220Sstevel@tonic-gate static long win32_ctrl(DSO *dso, int cmd, long larg, void *parg);
1230Sstevel@tonic-gate #endif
1240Sstevel@tonic-gate static char *win32_name_converter(DSO *dso, const char *filename);
125*2139Sjp161948 static char *win32_merger(DSO *dso, const char *filespec1,
126*2139Sjp161948 	const char *filespec2);
127*2139Sjp161948 
128*2139Sjp161948 static const char *openssl_strnchr(const char *string, int c, size_t len);
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate static DSO_METHOD dso_meth_win32 = {
1310Sstevel@tonic-gate 	"OpenSSL 'win32' shared library method",
1320Sstevel@tonic-gate 	win32_load,
1330Sstevel@tonic-gate 	win32_unload,
1340Sstevel@tonic-gate 	win32_bind_var,
1350Sstevel@tonic-gate 	win32_bind_func,
1360Sstevel@tonic-gate /* For now, "unbind" doesn't exist */
1370Sstevel@tonic-gate #if 0
1380Sstevel@tonic-gate 	NULL, /* unbind_var */
1390Sstevel@tonic-gate 	NULL, /* unbind_func */
1400Sstevel@tonic-gate #endif
1410Sstevel@tonic-gate 	NULL, /* ctrl */
1420Sstevel@tonic-gate 	win32_name_converter,
143*2139Sjp161948 	win32_merger,
1440Sstevel@tonic-gate 	NULL, /* init */
1450Sstevel@tonic-gate 	NULL  /* finish */
1460Sstevel@tonic-gate 	};
1470Sstevel@tonic-gate 
DSO_METHOD_win32(void)1480Sstevel@tonic-gate DSO_METHOD *DSO_METHOD_win32(void)
1490Sstevel@tonic-gate 	{
1500Sstevel@tonic-gate 	return(&dso_meth_win32);
1510Sstevel@tonic-gate 	}
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate /* For this DSO_METHOD, our meth_data STACK will contain;
1540Sstevel@tonic-gate  * (i) a pointer to the handle (HINSTANCE) returned from
1550Sstevel@tonic-gate  *     LoadLibrary(), and copied.
1560Sstevel@tonic-gate  */
1570Sstevel@tonic-gate 
win32_load(DSO * dso)1580Sstevel@tonic-gate static int win32_load(DSO *dso)
1590Sstevel@tonic-gate 	{
1600Sstevel@tonic-gate 	HINSTANCE h = NULL, *p = NULL;
1610Sstevel@tonic-gate 	/* See applicable comments from dso_dl.c */
1620Sstevel@tonic-gate 	char *filename = DSO_convert_filename(dso, NULL);
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	if(filename == NULL)
1650Sstevel@tonic-gate 		{
1660Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_LOAD,DSO_R_NO_FILENAME);
1670Sstevel@tonic-gate 		goto err;
1680Sstevel@tonic-gate 		}
169*2139Sjp161948 	h = LoadLibraryA(filename);
1700Sstevel@tonic-gate 	if(h == NULL)
1710Sstevel@tonic-gate 		{
1720Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_LOAD,DSO_R_LOAD_FAILED);
1730Sstevel@tonic-gate 		ERR_add_error_data(3, "filename(", filename, ")");
1740Sstevel@tonic-gate 		goto err;
1750Sstevel@tonic-gate 		}
1760Sstevel@tonic-gate 	p = (HINSTANCE *)OPENSSL_malloc(sizeof(HINSTANCE));
1770Sstevel@tonic-gate 	if(p == NULL)
1780Sstevel@tonic-gate 		{
1790Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_LOAD,ERR_R_MALLOC_FAILURE);
1800Sstevel@tonic-gate 		goto err;
1810Sstevel@tonic-gate 		}
1820Sstevel@tonic-gate 	*p = h;
1830Sstevel@tonic-gate 	if(!sk_push(dso->meth_data, (char *)p))
1840Sstevel@tonic-gate 		{
1850Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_LOAD,DSO_R_STACK_ERROR);
1860Sstevel@tonic-gate 		goto err;
1870Sstevel@tonic-gate 		}
1880Sstevel@tonic-gate 	/* Success */
1890Sstevel@tonic-gate 	dso->loaded_filename = filename;
1900Sstevel@tonic-gate 	return(1);
1910Sstevel@tonic-gate err:
1920Sstevel@tonic-gate 	/* Cleanup !*/
1930Sstevel@tonic-gate 	if(filename != NULL)
1940Sstevel@tonic-gate 		OPENSSL_free(filename);
1950Sstevel@tonic-gate 	if(p != NULL)
1960Sstevel@tonic-gate 		OPENSSL_free(p);
1970Sstevel@tonic-gate 	if(h != NULL)
1980Sstevel@tonic-gate 		FreeLibrary(h);
1990Sstevel@tonic-gate 	return(0);
2000Sstevel@tonic-gate 	}
2010Sstevel@tonic-gate 
win32_unload(DSO * dso)2020Sstevel@tonic-gate static int win32_unload(DSO *dso)
2030Sstevel@tonic-gate 	{
2040Sstevel@tonic-gate 	HINSTANCE *p;
2050Sstevel@tonic-gate 	if(dso == NULL)
2060Sstevel@tonic-gate 		{
2070Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_UNLOAD,ERR_R_PASSED_NULL_PARAMETER);
2080Sstevel@tonic-gate 		return(0);
2090Sstevel@tonic-gate 		}
2100Sstevel@tonic-gate 	if(sk_num(dso->meth_data) < 1)
2110Sstevel@tonic-gate 		return(1);
2120Sstevel@tonic-gate 	p = (HINSTANCE *)sk_pop(dso->meth_data);
2130Sstevel@tonic-gate 	if(p == NULL)
2140Sstevel@tonic-gate 		{
2150Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_UNLOAD,DSO_R_NULL_HANDLE);
2160Sstevel@tonic-gate 		return(0);
2170Sstevel@tonic-gate 		}
2180Sstevel@tonic-gate 	if(!FreeLibrary(*p))
2190Sstevel@tonic-gate 		{
2200Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_UNLOAD,DSO_R_UNLOAD_FAILED);
2210Sstevel@tonic-gate 		/* We should push the value back onto the stack in
2220Sstevel@tonic-gate 		 * case of a retry. */
2230Sstevel@tonic-gate 		sk_push(dso->meth_data, (char *)p);
2240Sstevel@tonic-gate 		return(0);
2250Sstevel@tonic-gate 		}
2260Sstevel@tonic-gate 	/* Cleanup */
2270Sstevel@tonic-gate 	OPENSSL_free(p);
2280Sstevel@tonic-gate 	return(1);
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate /* Using GetProcAddress for variables? TODO: Check this out in
2320Sstevel@tonic-gate  * the Win32 API docs, there's probably a variant for variables. */
win32_bind_var(DSO * dso,const char * symname)2330Sstevel@tonic-gate static void *win32_bind_var(DSO *dso, const char *symname)
2340Sstevel@tonic-gate 	{
2350Sstevel@tonic-gate 	HINSTANCE *ptr;
2360Sstevel@tonic-gate 	void *sym;
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	if((dso == NULL) || (symname == NULL))
2390Sstevel@tonic-gate 		{
2400Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER);
2410Sstevel@tonic-gate 		return(NULL);
2420Sstevel@tonic-gate 		}
2430Sstevel@tonic-gate 	if(sk_num(dso->meth_data) < 1)
2440Sstevel@tonic-gate 		{
2450Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_BIND_VAR,DSO_R_STACK_ERROR);
2460Sstevel@tonic-gate 		return(NULL);
2470Sstevel@tonic-gate 		}
2480Sstevel@tonic-gate 	ptr = (HINSTANCE *)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
2490Sstevel@tonic-gate 	if(ptr == NULL)
2500Sstevel@tonic-gate 		{
2510Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_BIND_VAR,DSO_R_NULL_HANDLE);
2520Sstevel@tonic-gate 		return(NULL);
2530Sstevel@tonic-gate 		}
2540Sstevel@tonic-gate 	sym = GetProcAddress(*ptr, symname);
2550Sstevel@tonic-gate 	if(sym == NULL)
2560Sstevel@tonic-gate 		{
2570Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_BIND_VAR,DSO_R_SYM_FAILURE);
2580Sstevel@tonic-gate 		ERR_add_error_data(3, "symname(", symname, ")");
2590Sstevel@tonic-gate 		return(NULL);
2600Sstevel@tonic-gate 		}
2610Sstevel@tonic-gate 	return(sym);
2620Sstevel@tonic-gate 	}
2630Sstevel@tonic-gate 
win32_bind_func(DSO * dso,const char * symname)2640Sstevel@tonic-gate static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname)
2650Sstevel@tonic-gate 	{
2660Sstevel@tonic-gate 	HINSTANCE *ptr;
2670Sstevel@tonic-gate 	void *sym;
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	if((dso == NULL) || (symname == NULL))
2700Sstevel@tonic-gate 		{
2710Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER);
2720Sstevel@tonic-gate 		return(NULL);
2730Sstevel@tonic-gate 		}
2740Sstevel@tonic-gate 	if(sk_num(dso->meth_data) < 1)
2750Sstevel@tonic-gate 		{
2760Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_BIND_FUNC,DSO_R_STACK_ERROR);
2770Sstevel@tonic-gate 		return(NULL);
2780Sstevel@tonic-gate 		}
2790Sstevel@tonic-gate 	ptr = (HINSTANCE *)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
2800Sstevel@tonic-gate 	if(ptr == NULL)
2810Sstevel@tonic-gate 		{
2820Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_BIND_FUNC,DSO_R_NULL_HANDLE);
2830Sstevel@tonic-gate 		return(NULL);
2840Sstevel@tonic-gate 		}
2850Sstevel@tonic-gate 	sym = GetProcAddress(*ptr, symname);
2860Sstevel@tonic-gate 	if(sym == NULL)
2870Sstevel@tonic-gate 		{
2880Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_BIND_FUNC,DSO_R_SYM_FAILURE);
2890Sstevel@tonic-gate 		ERR_add_error_data(3, "symname(", symname, ")");
2900Sstevel@tonic-gate 		return(NULL);
2910Sstevel@tonic-gate 		}
2920Sstevel@tonic-gate 	return((DSO_FUNC_TYPE)sym);
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate 
295*2139Sjp161948 struct file_st
296*2139Sjp161948 	{
297*2139Sjp161948 	const char *node; int nodelen;
298*2139Sjp161948 	const char *device; int devicelen;
299*2139Sjp161948 	const char *predir; int predirlen;
300*2139Sjp161948 	const char *dir; int dirlen;
301*2139Sjp161948 	const char *file; int filelen;
302*2139Sjp161948 	};
303*2139Sjp161948 
win32_splitter(DSO * dso,const char * filename,int assume_last_is_dir)304*2139Sjp161948 static struct file_st *win32_splitter(DSO *dso, const char *filename,
305*2139Sjp161948 	int assume_last_is_dir)
306*2139Sjp161948 	{
307*2139Sjp161948 	struct file_st *result = NULL;
308*2139Sjp161948 	enum { IN_NODE, IN_DEVICE, IN_FILE } position;
309*2139Sjp161948 	const char *start = filename;
310*2139Sjp161948 
311*2139Sjp161948 	if (!filename)
312*2139Sjp161948 		{
313*2139Sjp161948 		DSOerr(DSO_F_WIN32_SPLITTER,DSO_R_NO_FILENAME);
314*2139Sjp161948 		/*goto err;*/
315*2139Sjp161948 		return(NULL);
316*2139Sjp161948 		}
317*2139Sjp161948 
318*2139Sjp161948 	result = OPENSSL_malloc(sizeof(struct file_st));
319*2139Sjp161948 	if(result == NULL)
320*2139Sjp161948 		{
321*2139Sjp161948 		DSOerr(DSO_F_WIN32_SPLITTER,
322*2139Sjp161948 			ERR_R_MALLOC_FAILURE);
323*2139Sjp161948 		return(NULL);
324*2139Sjp161948 		}
325*2139Sjp161948 
326*2139Sjp161948 	memset(result, 0, sizeof(struct file_st));
327*2139Sjp161948 	position = IN_DEVICE;
328*2139Sjp161948 
329*2139Sjp161948 	if(filename[0] == '\\' && filename[1] == '\\'
330*2139Sjp161948 		|| filename[0] == '/' && filename[1] == '/')
331*2139Sjp161948 		{
332*2139Sjp161948 		position = IN_NODE;
333*2139Sjp161948 		filename += 2;
334*2139Sjp161948 		start = filename;
335*2139Sjp161948 		result->node = start;
336*2139Sjp161948 		}
337*2139Sjp161948 
338*2139Sjp161948 	do
339*2139Sjp161948 		{
340*2139Sjp161948 		switch(filename[0])
341*2139Sjp161948 			{
342*2139Sjp161948 		case ':':
343*2139Sjp161948 			if(position != IN_DEVICE)
344*2139Sjp161948 				{
345*2139Sjp161948 				DSOerr(DSO_F_WIN32_SPLITTER,
346*2139Sjp161948 					DSO_R_INCORRECT_FILE_SYNTAX);
347*2139Sjp161948 				/*goto err;*/
348*2139Sjp161948 				return(NULL);
349*2139Sjp161948 				}
350*2139Sjp161948 			result->device = start;
351*2139Sjp161948 			result->devicelen = filename - start;
352*2139Sjp161948 			position = IN_FILE;
353*2139Sjp161948 			start = ++filename;
354*2139Sjp161948 			result->dir = start;
355*2139Sjp161948 			break;
356*2139Sjp161948 		case '\\':
357*2139Sjp161948 		case '/':
358*2139Sjp161948 			if(position == IN_NODE)
359*2139Sjp161948 				{
360*2139Sjp161948 				result->nodelen = filename - start;
361*2139Sjp161948 				position = IN_FILE;
362*2139Sjp161948 				start = ++filename;
363*2139Sjp161948 				result->dir = start;
364*2139Sjp161948 				}
365*2139Sjp161948 			else
366*2139Sjp161948 				{
367*2139Sjp161948 				filename++;
368*2139Sjp161948 				result->dirlen += filename - start;
369*2139Sjp161948 				}
370*2139Sjp161948 			break;
371*2139Sjp161948 		case '\0':
372*2139Sjp161948 			if(position == IN_NODE)
373*2139Sjp161948 				{
374*2139Sjp161948 				result->nodelen = filename - start;
375*2139Sjp161948 				}
376*2139Sjp161948 			else
377*2139Sjp161948 				{
378*2139Sjp161948 				if(filename - start > 0)
379*2139Sjp161948 					{
380*2139Sjp161948 					if (assume_last_is_dir)
381*2139Sjp161948 						{
382*2139Sjp161948 						result->devicelen += filename - start;
383*2139Sjp161948 						}
384*2139Sjp161948 					else
385*2139Sjp161948 						{
386*2139Sjp161948 						result->file = start;
387*2139Sjp161948 						result->filelen = filename - start;
388*2139Sjp161948 						}
389*2139Sjp161948 					}
390*2139Sjp161948 				}
391*2139Sjp161948 			break;
392*2139Sjp161948 		default:
393*2139Sjp161948 			filename++;
394*2139Sjp161948 			break;
395*2139Sjp161948 			}
396*2139Sjp161948 		}
397*2139Sjp161948 	while(*filename);
398*2139Sjp161948 
399*2139Sjp161948 	if(!result->nodelen) result->node = NULL;
400*2139Sjp161948 	if(!result->devicelen) result->device = NULL;
401*2139Sjp161948 	if(!result->dirlen) result->dir = NULL;
402*2139Sjp161948 	if(!result->filelen) result->file = NULL;
403*2139Sjp161948 
404*2139Sjp161948 	return(result);
405*2139Sjp161948 	}
406*2139Sjp161948 
win32_joiner(DSO * dso,const struct file_st * file_split)407*2139Sjp161948 static char *win32_joiner(DSO *dso, const struct file_st *file_split)
408*2139Sjp161948 	{
409*2139Sjp161948 	int len = 0, offset = 0;
410*2139Sjp161948 	char *result = NULL;
411*2139Sjp161948 	const char *start;
412*2139Sjp161948 
413*2139Sjp161948 	if(!file_split)
414*2139Sjp161948 		{
415*2139Sjp161948 		DSOerr(DSO_F_WIN32_JOINER,
416*2139Sjp161948 				ERR_R_PASSED_NULL_PARAMETER);
417*2139Sjp161948 		return(NULL);
418*2139Sjp161948 		}
419*2139Sjp161948 	if(file_split->node)
420*2139Sjp161948 		{
421*2139Sjp161948 		len += 2 + file_split->nodelen;	/* 2 for starting \\ */
422*2139Sjp161948 		if(file_split->predir || file_split->dir || file_split->file)
423*2139Sjp161948 			len++;	/* 1 for ending \ */
424*2139Sjp161948 		}
425*2139Sjp161948 	else if(file_split->device)
426*2139Sjp161948 		{
427*2139Sjp161948 		len += file_split->devicelen + 1; /* 1 for ending : */
428*2139Sjp161948 		}
429*2139Sjp161948 	len += file_split->predirlen;
430*2139Sjp161948 	if(file_split->predir && (file_split->dir || file_split->file))
431*2139Sjp161948 		{
432*2139Sjp161948 		len++;	/* 1 for ending \ */
433*2139Sjp161948 		}
434*2139Sjp161948 	len += file_split->dirlen;
435*2139Sjp161948 	if(file_split->dir && file_split->file)
436*2139Sjp161948 		{
437*2139Sjp161948 		len++;	/* 1 for ending \ */
438*2139Sjp161948 		}
439*2139Sjp161948 	len += file_split->filelen;
440*2139Sjp161948 
441*2139Sjp161948 	if(!len)
442*2139Sjp161948 		{
443*2139Sjp161948 		DSOerr(DSO_F_WIN32_JOINER, DSO_R_EMPTY_FILE_STRUCTURE);
444*2139Sjp161948 		return(NULL);
445*2139Sjp161948 		}
446*2139Sjp161948 
447*2139Sjp161948 	result = OPENSSL_malloc(len + 1);
448*2139Sjp161948 	if (!result)
449*2139Sjp161948 		{
450*2139Sjp161948 		DSOerr(DSO_F_WIN32_JOINER,
451*2139Sjp161948 			ERR_R_MALLOC_FAILURE);
452*2139Sjp161948 		return(NULL);
453*2139Sjp161948 		}
454*2139Sjp161948 
455*2139Sjp161948 	if(file_split->node)
456*2139Sjp161948 		{
457*2139Sjp161948 		strcpy(&result[offset], "\\\\"); offset += 2;
458*2139Sjp161948 		strncpy(&result[offset], file_split->node,
459*2139Sjp161948 			file_split->nodelen); offset += file_split->nodelen;
460*2139Sjp161948 		if(file_split->predir || file_split->dir || file_split->file)
461*2139Sjp161948 			{
462*2139Sjp161948 			result[offset] = '\\'; offset++;
463*2139Sjp161948 			}
464*2139Sjp161948 		}
465*2139Sjp161948 	else if(file_split->device)
466*2139Sjp161948 		{
467*2139Sjp161948 		strncpy(&result[offset], file_split->device,
468*2139Sjp161948 			file_split->devicelen); offset += file_split->devicelen;
469*2139Sjp161948 		result[offset] = ':'; offset++;
470*2139Sjp161948 		}
471*2139Sjp161948 	start = file_split->predir;
472*2139Sjp161948 	while(file_split->predirlen > (start - file_split->predir))
473*2139Sjp161948 		{
474*2139Sjp161948 		const char *end = openssl_strnchr(start, '/',
475*2139Sjp161948 			file_split->predirlen - (start - file_split->predir));
476*2139Sjp161948 		if(!end)
477*2139Sjp161948 			end = start
478*2139Sjp161948 				+ file_split->predirlen
479*2139Sjp161948 				- (start - file_split->predir);
480*2139Sjp161948 		strncpy(&result[offset], start,
481*2139Sjp161948 			end - start); offset += end - start;
482*2139Sjp161948 		result[offset] = '\\'; offset++;
483*2139Sjp161948 		start = end + 1;
484*2139Sjp161948 		}
485*2139Sjp161948 	if(file_split->predir && (file_split->dir || file_split->file))
486*2139Sjp161948 		{
487*2139Sjp161948 		result[offset] = '\\'; offset++;
488*2139Sjp161948 		}
489*2139Sjp161948 	start = file_split->dir;
490*2139Sjp161948 	while(file_split->dirlen > (start - file_split->dir))
491*2139Sjp161948 		{
492*2139Sjp161948 		const char *end = openssl_strnchr(start, '/',
493*2139Sjp161948 			file_split->dirlen - (start - file_split->dir));
494*2139Sjp161948 		if(!end)
495*2139Sjp161948 			end = start
496*2139Sjp161948 				+ file_split->dirlen
497*2139Sjp161948 				- (start - file_split->dir);
498*2139Sjp161948 		strncpy(&result[offset], start,
499*2139Sjp161948 			end - start); offset += end - start;
500*2139Sjp161948 		result[offset] = '\\'; offset++;
501*2139Sjp161948 		start = end + 1;
502*2139Sjp161948 		}
503*2139Sjp161948 	if(file_split->dir && file_split->file)
504*2139Sjp161948 		{
505*2139Sjp161948 		result[offset] = '\\'; offset++;
506*2139Sjp161948 		}
507*2139Sjp161948 	strncpy(&result[offset], file_split->file,
508*2139Sjp161948 		file_split->filelen); offset += file_split->filelen;
509*2139Sjp161948 	result[offset] = '\0';
510*2139Sjp161948 	return(result);
511*2139Sjp161948 	}
512*2139Sjp161948 
win32_merger(DSO * dso,const char * filespec1,const char * filespec2)513*2139Sjp161948 static char *win32_merger(DSO *dso, const char *filespec1, const char *filespec2)
514*2139Sjp161948 	{
515*2139Sjp161948 	char *merged = NULL;
516*2139Sjp161948 	struct file_st *filespec1_split = NULL;
517*2139Sjp161948 	struct file_st *filespec2_split = NULL;
518*2139Sjp161948 
519*2139Sjp161948 	if(!filespec1 && !filespec2)
520*2139Sjp161948 		{
521*2139Sjp161948 		DSOerr(DSO_F_WIN32_MERGER,
522*2139Sjp161948 				ERR_R_PASSED_NULL_PARAMETER);
523*2139Sjp161948 		return(NULL);
524*2139Sjp161948 		}
525*2139Sjp161948 	if (!filespec2)
526*2139Sjp161948 		{
527*2139Sjp161948 		merged = OPENSSL_malloc(strlen(filespec1) + 1);
528*2139Sjp161948 		if(!merged)
529*2139Sjp161948 			{
530*2139Sjp161948 			DSOerr(DSO_F_WIN32_MERGER,
531*2139Sjp161948 				ERR_R_MALLOC_FAILURE);
532*2139Sjp161948 			return(NULL);
533*2139Sjp161948 			}
534*2139Sjp161948 		strcpy(merged, filespec1);
535*2139Sjp161948 		}
536*2139Sjp161948 	else if (!filespec1)
537*2139Sjp161948 		{
538*2139Sjp161948 		merged = OPENSSL_malloc(strlen(filespec2) + 1);
539*2139Sjp161948 		if(!merged)
540*2139Sjp161948 			{
541*2139Sjp161948 			DSOerr(DSO_F_WIN32_MERGER,
542*2139Sjp161948 				ERR_R_MALLOC_FAILURE);
543*2139Sjp161948 			return(NULL);
544*2139Sjp161948 			}
545*2139Sjp161948 		strcpy(merged, filespec2);
546*2139Sjp161948 		}
547*2139Sjp161948 	else
548*2139Sjp161948 		{
549*2139Sjp161948 		filespec1_split = win32_splitter(dso, filespec1, 1);
550*2139Sjp161948 		if (!filespec1_split)
551*2139Sjp161948 			{
552*2139Sjp161948 			DSOerr(DSO_F_WIN32_MERGER,
553*2139Sjp161948 				ERR_R_MALLOC_FAILURE);
554*2139Sjp161948 			return(NULL);
555*2139Sjp161948 			}
556*2139Sjp161948 		filespec2_split = win32_splitter(dso, filespec2, 0);
557*2139Sjp161948 		if (!filespec1_split)
558*2139Sjp161948 			{
559*2139Sjp161948 			DSOerr(DSO_F_WIN32_MERGER,
560*2139Sjp161948 				ERR_R_MALLOC_FAILURE);
561*2139Sjp161948 			OPENSSL_free(filespec1_split);
562*2139Sjp161948 			return(NULL);
563*2139Sjp161948 			}
564*2139Sjp161948 
565*2139Sjp161948 		/* Fill in into filespec1_split */
566*2139Sjp161948 		if (!filespec1_split->node && !filespec1_split->device)
567*2139Sjp161948 			{
568*2139Sjp161948 			filespec1_split->node = filespec2_split->node;
569*2139Sjp161948 			filespec1_split->nodelen = filespec2_split->nodelen;
570*2139Sjp161948 			filespec1_split->device = filespec2_split->device;
571*2139Sjp161948 			filespec1_split->devicelen = filespec2_split->devicelen;
572*2139Sjp161948 			}
573*2139Sjp161948 		if (!filespec1_split->dir)
574*2139Sjp161948 			{
575*2139Sjp161948 			filespec1_split->dir = filespec2_split->dir;
576*2139Sjp161948 			filespec1_split->dirlen = filespec2_split->dirlen;
577*2139Sjp161948 			}
578*2139Sjp161948 		else if (filespec1_split->dir[0] != '\\'
579*2139Sjp161948 			&& filespec1_split->dir[0] != '/')
580*2139Sjp161948 			{
581*2139Sjp161948 			filespec1_split->predir = filespec2_split->dir;
582*2139Sjp161948 			filespec1_split->predirlen = filespec2_split->dirlen;
583*2139Sjp161948 			}
584*2139Sjp161948 		if (!filespec1_split->file)
585*2139Sjp161948 			{
586*2139Sjp161948 			filespec1_split->file = filespec2_split->file;
587*2139Sjp161948 			filespec1_split->filelen = filespec2_split->filelen;
588*2139Sjp161948 			}
589*2139Sjp161948 
590*2139Sjp161948 		merged = win32_joiner(dso, filespec1_split);
591*2139Sjp161948 		}
592*2139Sjp161948 	return(merged);
593*2139Sjp161948 	}
594*2139Sjp161948 
win32_name_converter(DSO * dso,const char * filename)5950Sstevel@tonic-gate static char *win32_name_converter(DSO *dso, const char *filename)
5960Sstevel@tonic-gate 	{
5970Sstevel@tonic-gate 	char *translated;
5980Sstevel@tonic-gate 	int len, transform;
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	len = strlen(filename);
6010Sstevel@tonic-gate 	transform = ((strstr(filename, "/") == NULL) &&
6020Sstevel@tonic-gate 			(strstr(filename, "\\") == NULL) &&
6030Sstevel@tonic-gate 			(strstr(filename, ":") == NULL));
6040Sstevel@tonic-gate 	if(transform)
6050Sstevel@tonic-gate 		/* We will convert this to "%s.dll" */
6060Sstevel@tonic-gate 		translated = OPENSSL_malloc(len + 5);
6070Sstevel@tonic-gate 	else
6080Sstevel@tonic-gate 		/* We will simply duplicate filename */
6090Sstevel@tonic-gate 		translated = OPENSSL_malloc(len + 1);
6100Sstevel@tonic-gate 	if(translated == NULL)
6110Sstevel@tonic-gate 		{
6120Sstevel@tonic-gate 		DSOerr(DSO_F_WIN32_NAME_CONVERTER,
6130Sstevel@tonic-gate 				DSO_R_NAME_TRANSLATION_FAILED);
6140Sstevel@tonic-gate 		return(NULL);
6150Sstevel@tonic-gate 		}
6160Sstevel@tonic-gate 	if(transform)
6170Sstevel@tonic-gate 		sprintf(translated, "%s.dll", filename);
6180Sstevel@tonic-gate 	else
6190Sstevel@tonic-gate 		sprintf(translated, "%s", filename);
6200Sstevel@tonic-gate 	return(translated);
6210Sstevel@tonic-gate 	}
6220Sstevel@tonic-gate 
openssl_strnchr(const char * string,int c,size_t len)623*2139Sjp161948 static const char *openssl_strnchr(const char *string, int c, size_t len)
624*2139Sjp161948 	{
625*2139Sjp161948 	size_t i;
626*2139Sjp161948 	const char *p;
627*2139Sjp161948 	for (i = 0, p = string; i < len && *p; i++, p++)
628*2139Sjp161948 		{
629*2139Sjp161948 		if (*p == c)
630*2139Sjp161948 			return p;
631*2139Sjp161948 		}
632*2139Sjp161948 	return NULL;
633*2139Sjp161948 	}
634*2139Sjp161948 
635*2139Sjp161948 
6360Sstevel@tonic-gate #endif /* OPENSSL_SYS_WIN32 */
637