cryptlib.c revision 237998
11590Srgrimes/* crypto/cryptlib.c */
21590Srgrimes/* ====================================================================
31590Srgrimes * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes *
91590Srgrimes * 1. Redistributions of source code must retain the above copyright
101590Srgrimes *    notice, this list of conditions and the following disclaimer.
111590Srgrimes *
121590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
131590Srgrimes *    notice, this list of conditions and the following disclaimer in
141590Srgrimes *    the documentation and/or other materials provided with the
151590Srgrimes *    distribution.
161590Srgrimes *
171590Srgrimes * 3. All advertising materials mentioning features or use of this
181590Srgrimes *    software must display the following acknowledgment:
191590Srgrimes *    "This product includes software developed by the OpenSSL Project
201590Srgrimes *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
211590Srgrimes *
221590Srgrimes * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
231590Srgrimes *    endorse or promote products derived from this software without
241590Srgrimes *    prior written permission. For written permission, please contact
251590Srgrimes *    openssl-core@openssl.org.
261590Srgrimes *
271590Srgrimes * 5. Products derived from this software may not be called "OpenSSL"
281590Srgrimes *    nor may "OpenSSL" appear in their names without prior written
291590Srgrimes *    permission of the OpenSSL Project.
301590Srgrimes *
311590Srgrimes * 6. Redistributions of any form whatsoever must retain the following
321590Srgrimes *    acknowledgment:
331590Srgrimes *    "This product includes software developed by the OpenSSL Project
341590Srgrimes *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
3574769Smikeh *
361590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
3774769Smikeh * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
381590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3999112Sobrien * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4099112Sobrien * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
411590Srgrimes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
421590Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
431590Srgrimes * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
441590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
451590Srgrimes * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
461590Srgrimes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
471590Srgrimes * OF THE POSSIBILITY OF SUCH DAMAGE.
481590Srgrimes * ====================================================================
491590Srgrimes *
501590Srgrimes * This product includes cryptographic software written by Eric Young
511590Srgrimes * (eay@cryptsoft.com).  This product includes software written by Tim
521590Srgrimes * Hudson (tjh@cryptsoft.com).
531590Srgrimes *
541590Srgrimes */
551590Srgrimes/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
561590Srgrimes * All rights reserved.
571590Srgrimes *
581590Srgrimes * This package is an SSL implementation written
591590Srgrimes * by Eric Young (eay@cryptsoft.com).
601590Srgrimes * The implementation was written so as to conform with Netscapes SSL.
611590Srgrimes *
6277274Smikeh * This library is free for commercial and non-commercial use as long as
631590Srgrimes * the following conditions are aheared to.  The following conditions
6477274Smikeh * apply to all code found in this distribution, be it the RC4, RSA,
6577274Smikeh * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
6677274Smikeh * included with this distribution is covered by the same copyright terms
671590Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com).
681590Srgrimes *
6977274Smikeh * Copyright remains Eric Young's, and as such any Copyright notices in
701590Srgrimes * the code are not to be removed.
711590Srgrimes * If this package is used in a product, Eric Young should be given attribution
721590Srgrimes * as the author of the parts of the library used.
731590Srgrimes * This can be in the form of a textual message at program startup or
741590Srgrimes * in documentation (online or textual) provided with the package.
751590Srgrimes *
761590Srgrimes * Redistribution and use in source and binary forms, with or without
771590Srgrimes * modification, are permitted provided that the following conditions
781590Srgrimes * are met:
7977274Smikeh * 1. Redistributions of source code must retain the copyright
801590Srgrimes *    notice, this list of conditions and the following disclaimer.
811590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
8277274Smikeh *    notice, this list of conditions and the following disclaimer in the
8377274Smikeh *    documentation and/or other materials provided with the distribution.
8477274Smikeh * 3. All advertising materials mentioning features or use of this software
851590Srgrimes *    must display the following acknowledgement:
8677274Smikeh *    "This product includes cryptographic software written by
871590Srgrimes *     Eric Young (eay@cryptsoft.com)"
881590Srgrimes *    The word 'cryptographic' can be left out if the rouines from the library
891590Srgrimes *    being used are not cryptographic related :-).
901590Srgrimes * 4. If you include any Windows specific code (or a derivative thereof) from
911590Srgrimes *    the apps directory (application code) you must include an acknowledgement:
9277274Smikeh *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
931590Srgrimes *
941590Srgrimes * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
951590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
961590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
971590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
981590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9977274Smikeh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10077274Smikeh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1011590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10277274Smikeh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10377274Smikeh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10477274Smikeh * SUCH DAMAGE.
10574769Smikeh *
10677274Smikeh * The licence and distribution terms for any publically available version or
10777274Smikeh * derivative of this code cannot be changed.  i.e. this code cannot simply be
1081590Srgrimes * copied and put under another distribution licence
10977274Smikeh * [including the GNU Public Licence.]
1101590Srgrimes */
11177274Smikeh/* ====================================================================
1121590Srgrimes * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
1131590Srgrimes * ECDH support in OpenSSL originally developed by
1141590Srgrimes * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
1151590Srgrimes */
1161590Srgrimes
1171590Srgrimes#include "cryptlib.h"
11877274Smikeh#include <openssl/safestack.h>
11977274Smikeh
1201590Srgrimes#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16)
1211590Srgrimesstatic double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */
1221590Srgrimes#endif
1231590Srgrimes
1241590Srgrimesstatic void (MS_FAR *locking_callback)(int mode,int type,
1251590Srgrimes	const char *file,int line)=NULL;
1261590Srgrimesstatic int (MS_FAR *add_lock_callback)(int *pointer,int amount,
12777274Smikeh	int type,const char *file,int line)=NULL;
1281590Srgrimesstatic unsigned long (MS_FAR *id_callback)(void)=NULL;
1291590Srgrimes
13077274Smikehint CRYPTO_num_locks(void)
13177274Smikeh	{
13277274Smikeh	return CRYPTO_NUM_LOCKS;
1331590Srgrimes	}
1341590Srgrimes
13577274Smikehvoid (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file,
13677274Smikeh		int line)
1371590Srgrimes	{
1381590Srgrimes	return(locking_callback);
1391590Srgrimes	}
1401590Srgrimes
14177274Smikehint (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type,
1421590Srgrimes					  const char *file,int line)
1431590Srgrimes	{
1441590Srgrimes	return(add_lock_callback);
1451590Srgrimes	}
1461590Srgrimes
1471590Srgrimesvoid CRYPTO_set_locking_callback(void (*func)(int mode,int type,
1481590Srgrimes					      const char *file,int line))
14977274Smikeh	{
1501590Srgrimes	locking_callback=func;
1511590Srgrimes	}
1521590Srgrimes
15377274Smikehvoid CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type,
1541590Srgrimes					      const char *file,int line))
1551590Srgrimes	{
15674769Smikeh	add_lock_callback=func;
15777274Smikeh	}
1581590Srgrimes
1591590Srgrimesunsigned long (*CRYPTO_get_id_callback(void))(void)
1601590Srgrimes	{
16174769Smikeh	return(id_callback);
1621590Srgrimes	}
16374769Smikeh
16477274Smikehvoid CRYPTO_set_id_callback(unsigned long (*func)(void))
1651590Srgrimes	{
1661590Srgrimes	id_callback=func;
1671590Srgrimes	}
1681590Srgrimes
1691590Srgrimesunsigned long CRYPTO_thread_id(void)
1701590Srgrimes	{
1711590Srgrimes	unsigned long ret=0;
1721590Srgrimes
1731590Srgrimes	if (id_callback == NULL)
1741590Srgrimes		{
17577274Smikeh#ifdef OPENSSL_SYS_WIN16
1761590Srgrimes		ret=(unsigned long)GetCurrentTask();
1771590Srgrimes#elif defined(OPENSSL_SYS_WIN32)
1781590Srgrimes		ret=(unsigned long)GetCurrentThreadId();
1791590Srgrimes#elif defined(GETPID_IS_MEANINGLESS)
18077274Smikeh		ret=1L;
1811590Srgrimes#else
18277274Smikeh		ret=(unsigned long)getpid();
1831590Srgrimes#endif
1841590Srgrimes		}
1851590Srgrimes	else
1861590Srgrimes		ret=id_callback();
1871590Srgrimes	return(ret);
1881590Srgrimes	}
1891590Srgrimes
1901590Srgrimesstatic void (*do_dynlock_cb)(int mode, int type, const char *file, int line);
1911590Srgrimes
1921590Srgrimesvoid int_CRYPTO_set_do_dynlock_callback(
1931590Srgrimes	void (*dyn_cb)(int mode, int type, const char *file, int line))
1941590Srgrimes	{
1951590Srgrimes	do_dynlock_cb = dyn_cb;
1961590Srgrimes	}
1971590Srgrimes
1981590Srgrimesvoid CRYPTO_lock(int mode, int type, const char *file, int line)
1991590Srgrimes	{
2001590Srgrimes#ifdef LOCK_DEBUG
2011590Srgrimes		{
2021590Srgrimes		char *rw_text,*operation_text;
2031590Srgrimes
2041590Srgrimes		if (mode & CRYPTO_LOCK)
20577274Smikeh			operation_text="lock  ";
20677274Smikeh		else if (mode & CRYPTO_UNLOCK)
2071590Srgrimes			operation_text="unlock";
2081590Srgrimes		else
20977274Smikeh			operation_text="ERROR ";
2101590Srgrimes
2111590Srgrimes		if (mode & CRYPTO_READ)
2121590Srgrimes			rw_text="r";
213126415Smikeh		else if (mode & CRYPTO_WRITE)
214126415Smikeh			rw_text="w";
215126415Smikeh		else
216126415Smikeh			rw_text="ERROR";
217126415Smikeh
218126415Smikeh		fprintf(stderr,"lock:%08lx:(%s)%s %-18s %s:%d\n",
219126415Smikeh			CRYPTO_thread_id(), rw_text, operation_text,
220126415Smikeh			CRYPTO_get_lock_name(type), file, line);
221126415Smikeh		}
222126415Smikeh#endif
223126415Smikeh	if (type < 0)
224126415Smikeh		{
225126415Smikeh		if (do_dynlock_cb)
226126415Smikeh			do_dynlock_cb(mode, type, file, line);
227126415Smikeh		}
228126415Smikeh	else
229126415Smikeh		if (locking_callback != NULL)
230126415Smikeh			locking_callback(mode,type,file,line);
231126415Smikeh	}
232126415Smikeh
233126415Smikehint CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
234126415Smikeh	     int line)
235126415Smikeh	{
236126415Smikeh	int ret = 0;
237126415Smikeh
238126415Smikeh	if (add_lock_callback != NULL)
239126415Smikeh		{
240126415Smikeh#ifdef LOCK_DEBUG
241126415Smikeh		int before= *pointer;
242126415Smikeh#endif
243126415Smikeh
244126415Smikeh		ret=add_lock_callback(pointer,amount,type,file,line);
245126415Smikeh#ifdef LOCK_DEBUG
246126415Smikeh		fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
247126415Smikeh			CRYPTO_thread_id(),
248126415Smikeh			before,amount,ret,
249126415Smikeh			CRYPTO_get_lock_name(type),
250126415Smikeh			file,line);
251126415Smikeh#endif
252126415Smikeh		}
253126415Smikeh	else
254126415Smikeh		{
255126415Smikeh		CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,file,line);
256126415Smikeh
257126415Smikeh		ret= *pointer+amount;
258126415Smikeh#ifdef LOCK_DEBUG
259126415Smikeh		fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
260126415Smikeh			CRYPTO_thread_id(),
261126415Smikeh			*pointer,amount,ret,
262126415Smikeh			CRYPTO_get_lock_name(type),
263126415Smikeh			file,line);
264126415Smikeh#endif
265126415Smikeh		*pointer=ret;
266126415Smikeh		CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line);
267126415Smikeh		}
268126415Smikeh	return(ret);
269126415Smikeh	}
270126415Smikeh
271126415Smikeh#if	defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
272126415Smikeh	defined(__INTEL__) || \
273126415Smikeh	defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
274126415Smikeh
275126415Smikehunsigned long  OPENSSL_ia32cap_P=0;
276126415Smikehunsigned long *OPENSSL_ia32cap_loc(void) { return &OPENSSL_ia32cap_P; }
277126415Smikeh
278126415Smikeh#if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
279126415Smikeh#define OPENSSL_CPUID_SETUP
280126415Smikehvoid OPENSSL_cpuid_setup(void)
281126415Smikeh{ static int trigger=0;
282126415Smikeh  unsigned long OPENSSL_ia32_cpuid(void);
283126415Smikeh  char *env;
284126415Smikeh
285126415Smikeh    if (trigger)	return;
2861590Srgrimes
2871590Srgrimes    trigger=1;
2881590Srgrimes    if ((env=getenv("OPENSSL_ia32cap")))
2891590Srgrimes	OPENSSL_ia32cap_P = strtoul(env,NULL,0)|(1<<10);
2901590Srgrimes    else
2911590Srgrimes	OPENSSL_ia32cap_P = OPENSSL_ia32_cpuid()|(1<<10);
2921590Srgrimes    /*
2931590Srgrimes     * |(1<<10) sets a reserved bit to signal that variable
2941590Srgrimes     * was initialized already... This is to avoid interference
2951590Srgrimes     * with cpuid snippets in ELF .init segment.
2961590Srgrimes     */
2971590Srgrimes}
2981590Srgrimes#endif
29977274Smikeh
30077274Smikeh#else
30177274Smikehunsigned long *OPENSSL_ia32cap_loc(void) { return NULL; }
30277274Smikeh#endif
3031590Srgrimesint OPENSSL_NONPIC_relocated = 0;
3041590Srgrimes#if !defined(OPENSSL_CPUID_SETUP)
3051590Srgrimesvoid OPENSSL_cpuid_setup(void) {}
3061590Srgrimes#endif
30777274Smikeh
3081590Srgrimes#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL)
30977274Smikeh
3101590Srgrimes#ifdef OPENSSL_FIPS
3111590Srgrimes
3121590Srgrimes#include <tlhelp32.h>
3131590Srgrimes#if defined(__GNUC__) && __GNUC__>=2
3141590Srgrimesstatic int DllInit(void) __attribute__((constructor));
3151590Srgrimes#elif defined(_MSC_VER)
3161590Srgrimesstatic int DllInit(void);
3171590Srgrimes# ifdef _WIN64
3181590Srgrimes# pragma section(".CRT$XCU",read)
3191590Srgrimes  __declspec(allocate(".CRT$XCU"))
3201590Srgrimes# else
3211590Srgrimes# pragma data_seg(".CRT$XCU")
3221590Srgrimes# endif
3231590Srgrimes  static int (*p)(void) = DllInit;
3241590Srgrimes# pragma data_seg()
3251590Srgrimes#endif
32674769Smikeh
32774769Smikehstatic int DllInit(void)
32874769Smikeh{
32977274Smikeh#if defined(_WIN32_WINNT)
33077274Smikeh	union	{ int(*f)(void); BYTE *p; } t = { DllInit };
33174769Smikeh        HANDLE	hModuleSnap = INVALID_HANDLE_VALUE;
33274769Smikeh	IMAGE_DOS_HEADER *dos_header;
33374769Smikeh	IMAGE_NT_HEADERS *nt_headers;
3341590Srgrimes	MODULEENTRY32 me32 = {sizeof(me32)};
3351590Srgrimes
3361590Srgrimes	hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);
33774769Smikeh	if (hModuleSnap != INVALID_HANDLE_VALUE &&
33877274Smikeh	    Module32First(hModuleSnap,&me32)) do
3391590Srgrimes		{
34074769Smikeh		if (t.p >= me32.modBaseAddr &&
3411590Srgrimes		    t.p <  me32.modBaseAddr+me32.modBaseSize)
34277274Smikeh			{
3431590Srgrimes			dos_header=(IMAGE_DOS_HEADER *)me32.modBaseAddr;
3441590Srgrimes			if (dos_header->e_magic==IMAGE_DOS_SIGNATURE)
34577274Smikeh				{
3461590Srgrimes				nt_headers=(IMAGE_NT_HEADERS *)
34732189Sjoerg					((BYTE *)dos_header+dos_header->e_lfanew);
34877274Smikeh				if (nt_headers->Signature==IMAGE_NT_SIGNATURE &&
3491590Srgrimes				    me32.modBaseAddr!=(BYTE*)nt_headers->OptionalHeader.ImageBase)
35077274Smikeh					OPENSSL_NONPIC_relocated=1;
3511590Srgrimes				}
35277274Smikeh			break;
35377274Smikeh			}
35474769Smikeh		} while (Module32Next(hModuleSnap,&me32));
35574769Smikeh
35674769Smikeh	if (hModuleSnap != INVALID_HANDLE_VALUE)
35777274Smikeh		CloseHandle(hModuleSnap);
35874769Smikeh#endif
35974769Smikeh	OPENSSL_cpuid_setup();
36077274Smikeh	return 0;
3611590Srgrimes}
3621590Srgrimes
3631590Srgrimes#else
3641590Srgrimes
3651590Srgrimes#ifdef __CYGWIN__
3661590Srgrimes/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
3671590Srgrimes#include <windows.h>
3681590Srgrimes#endif
3691590Srgrimes
3701590Srgrimes/* All we really need to do is remove the 'error' state when a thread
37177274Smikeh * detaches */
37288150Smikeh
3731590SrgrimesBOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
3741590Srgrimes	     LPVOID lpvReserved)
3751590Srgrimes	{
3761590Srgrimes	switch(fdwReason)
3771590Srgrimes		{
3781590Srgrimes	case DLL_PROCESS_ATTACH:
3791590Srgrimes		OPENSSL_cpuid_setup();
3801590Srgrimes#if defined(_WIN32_WINNT)
38177274Smikeh		{
38277274Smikeh		IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *)hinstDLL;
38388150Smikeh		IMAGE_NT_HEADERS *nt_headers;
38488150Smikeh
38588150Smikeh		if (dos_header->e_magic==IMAGE_DOS_SIGNATURE)
38688150Smikeh			{
38788150Smikeh			nt_headers = (IMAGE_NT_HEADERS *)((char *)dos_header
38888150Smikeh						+ dos_header->e_lfanew);
3891590Srgrimes			if (nt_headers->Signature==IMAGE_NT_SIGNATURE &&
3901590Srgrimes			    hinstDLL!=(HINSTANCE)(nt_headers->OptionalHeader.ImageBase))
3911590Srgrimes				OPENSSL_NONPIC_relocated=1;
3921590Srgrimes			}
3931590Srgrimes		}
3941590Srgrimes#endif
3951590Srgrimes		break;
3961590Srgrimes	case DLL_THREAD_ATTACH:
39774769Smikeh		break;
3981590Srgrimes	case DLL_THREAD_DETACH:
3991590Srgrimes		break;
4001590Srgrimes	case DLL_PROCESS_DETACH:
4011590Srgrimes		break;
40274769Smikeh		}
4031590Srgrimes	return(TRUE);
4041590Srgrimes	}
4051590Srgrimes#endif
4061590Srgrimes
4071590Srgrimes#endif
40877274Smikeh
4091590Srgrimes#if defined(_WIN32) && !defined(__CYGWIN__)
4101590Srgrimes#include <tchar.h>
4111590Srgrimes
4121590Srgrimes#if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
4131590Srgrimesint OPENSSL_isservice(void)
41477274Smikeh{ HWINSTA h;
41574769Smikeh  DWORD len;
41674769Smikeh  WCHAR *name;
41774769Smikeh
41877274Smikeh    (void)GetDesktopWindow(); /* return value is ignored */
41977274Smikeh
42074769Smikeh    h = GetProcessWindowStation();
42174769Smikeh    if (h==NULL) return -1;
42277274Smikeh
42377274Smikeh    if (GetUserObjectInformationW (h,UOI_NAME,NULL,0,&len) ||
4241590Srgrimes	GetLastError() != ERROR_INSUFFICIENT_BUFFER)
4251590Srgrimes	return -1;
4261590Srgrimes
4271590Srgrimes    if (len>512) return -1;		/* paranoia */
4281590Srgrimes    len++,len&=~1;			/* paranoia */
4291590Srgrimes#ifdef _MSC_VER
4301590Srgrimes    name=(WCHAR *)_alloca(len+sizeof(WCHAR));
4311590Srgrimes#else
4321590Srgrimes    name=(WCHAR *)alloca(len+sizeof(WCHAR));
4331590Srgrimes#endif
4341590Srgrimes    if (!GetUserObjectInformationW (h,UOI_NAME,name,len,&len))
43577274Smikeh	return -1;
4361590Srgrimes
4371590Srgrimes    len++,len&=~1;			/* paranoia */
43877274Smikeh    name[len/sizeof(WCHAR)]=L'\0';	/* paranoia */
4391590Srgrimes#if 1
4401590Srgrimes    /* This doesn't cover "interactive" services [working with real
4411590Srgrimes     * WinSta0's] nor programs started non-interactively by Task
4421590Srgrimes     * Scheduler [those are working with SAWinSta]. */
4431590Srgrimes    if (wcsstr(name,L"Service-0x"))	return 1;
4441590Srgrimes#else
4451590Srgrimes    /* This covers all non-interactive programs such as services. */
4461590Srgrimes    if (!wcsstr(name,L"WinSta0"))	return 1;
4471590Srgrimes#endif
4481590Srgrimes    else				return 0;
4491590Srgrimes}
45077274Smikeh#else
4511590Srgrimesint OPENSSL_isservice(void) { return 0; }
4521590Srgrimes#endif
45377274Smikeh
45477274Smikehvoid OPENSSL_showfatal (const char *fmta,...)
4551590Srgrimes{ va_list ap;
45677274Smikeh  TCHAR buf[256];
4571590Srgrimes  const TCHAR *fmt;
45877274Smikeh#ifdef STD_ERROR_HANDLE	/* what a dirty trick! */
4591590Srgrimes  HANDLE h;
46077274Smikeh
4611590Srgrimes    if ((h=GetStdHandle(STD_ERROR_HANDLE)) != NULL &&
4621590Srgrimes	GetFileType(h)!=FILE_TYPE_UNKNOWN)
4631590Srgrimes    {	/* must be console application */
4641590Srgrimes	va_start (ap,fmta);
4651590Srgrimes	vfprintf (stderr,fmta,ap);
4661590Srgrimes	va_end (ap);
4671590Srgrimes	return;
4681590Srgrimes    }
4691590Srgrimes#endif
4701590Srgrimes
4711590Srgrimes    if (sizeof(TCHAR)==sizeof(char))
4721590Srgrimes	fmt=(const TCHAR *)fmta;
4731590Srgrimes    else do
47477274Smikeh    { int    keepgoing;
4751590Srgrimes      size_t len_0=strlen(fmta)+1,i;
47677274Smikeh      WCHAR *fmtw;
4771590Srgrimes
47877274Smikeh#ifdef _MSC_VER
4791590Srgrimes	fmtw = (WCHAR *)_alloca (len_0*sizeof(WCHAR));
48077274Smikeh#else
48177274Smikeh	fmtw = (WCHAR *)alloca (len_0*sizeof(WCHAR));
4821590Srgrimes#endif
4831590Srgrimes	if (fmtw == NULL) { fmt=(const TCHAR *)L"no stack?"; break; }
4841590Srgrimes
4851590Srgrimes#ifndef OPENSSL_NO_MULTIBYTE
4861590Srgrimes	if (!MultiByteToWideChar(CP_ACP,0,fmta,len_0,fmtw,len_0))
4871590Srgrimes#endif
4881590Srgrimes	    for (i=0;i<len_0;i++) fmtw[i]=(WCHAR)fmta[i];
4891590Srgrimes
49077274Smikeh	for (i=0;i<len_0;i++)
4911590Srgrimes	{   if (fmtw[i]==L'%') do
4921590Srgrimes	    {	keepgoing=0;
4931590Srgrimes		switch (fmtw[i+1])
4941590Srgrimes		{   case L'0': case L'1': case L'2': case L'3': case L'4':
4951590Srgrimes		    case L'5': case L'6': case L'7': case L'8': case L'9':
49677274Smikeh		    case L'.': case L'*':
4971590Srgrimes		    case L'-':	i++; keepgoing=1; break;
4981590Srgrimes		    case L's':	fmtw[i+1]=L'S';   break;
4991590Srgrimes		    case L'S':	fmtw[i+1]=L's';   break;
5001590Srgrimes		    case L'c':	fmtw[i+1]=L'C';   break;
5011590Srgrimes		    case L'C':	fmtw[i+1]=L'c';   break;
5021590Srgrimes		}
5031590Srgrimes	    } while (keepgoing);
5041590Srgrimes	}
5051590Srgrimes	fmt = (const TCHAR *)fmtw;
5061590Srgrimes    } while (0);
5071590Srgrimes
5081590Srgrimes    va_start (ap,fmta);
5091590Srgrimes    _vsntprintf (buf,sizeof(buf)/sizeof(TCHAR)-1,fmt,ap);
5101590Srgrimes    buf [sizeof(buf)/sizeof(TCHAR)-1] = _T('\0');
5111590Srgrimes    va_end (ap);
5121590Srgrimes
5131590Srgrimes#if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
5141590Srgrimes    /* this -------------v--- guards NT-specific calls */
5151590Srgrimes    if (GetVersion() < 0x80000000 && OPENSSL_isservice() > 0)
5161590Srgrimes    {	HANDLE h = RegisterEventSource(0,_T("OPENSSL"));
5171590Srgrimes	const TCHAR *pmsg=buf;
5181590Srgrimes	ReportEvent(h,EVENTLOG_ERROR_TYPE,0,0,0,1,0,&pmsg,0);
51977274Smikeh	DeregisterEventSource(h);
5201590Srgrimes    }
5211590Srgrimes    else
52277274Smikeh#endif
5231590Srgrimes	MessageBox (NULL,buf,_T("OpenSSL: FATAL"),MB_OK|MB_ICONSTOP);
5241590Srgrimes}
5251590Srgrimes#else
5261590Srgrimesvoid OPENSSL_showfatal (const char *fmta,...)
5271590Srgrimes{ va_list ap;
52877274Smikeh
5291590Srgrimes    va_start (ap,fmta);
5301590Srgrimes    vfprintf (stderr,fmta,ap);
5311590Srgrimes    va_end (ap);
5321590Srgrimes}
5331590Srgrimesint OPENSSL_isservice (void) { return 0; }
5341590Srgrimes#endif
5351590Srgrimes
5361590Srgrimesvoid OpenSSLDie(const char *file,int line,const char *assertion)
5371590Srgrimes	{
53877274Smikeh	OPENSSL_showfatal(
5391590Srgrimes		"%s(%d): OpenSSL internal error, assertion failed: %s\n",
5401590Srgrimes		file,line,assertion);
5411590Srgrimes	abort();
5421590Srgrimes	}
5431590Srgrimes
5441590Srgrimesvoid *OPENSSL_stderr(void)	{ return stderr; }
5451590Srgrimes