Commit 3fc378aa authored by Andy Polyakov's avatar Andy Polyakov
Browse files

Framework for glueing BIO layer and Win32 compiler run-time. Goal is to

make it possible to produce for a unified binary build, which can be
used with a variety of Win32 compilers.
parent f2bfbcef
Loading
Loading
Loading
Loading

ms/applink.c

0 → 100644
+45 −0
Original line number Diff line number Diff line
#define APPLINK_STDIN	1
#define APPLINK_STDOUT	2
#define APPLINK_STDERR	3
#define APPLINK_FPRINTF	4
#define APPLINK_FGETS	5
#define APPLINK_FREAD	6
#define APPLINK_FWRITE	7
#define APPLINK_FSETMOD	8
#define APPLINK_FEOF	9
#define APPLINK_FCLOSE 	10	/* should not be used */
#define APPLINK_MAX	10	/* always same as last macro */

#ifndef APPMACROS_ONLY
#include <stdio.h>
#include <io.h>
#include <fcntl.h>

static void *app_stdin()	{ return stdin;  }
static void *app_stdout()	{ return stdout; }
static void *app_stderr()	{ return stderr; }
static int   app_feof(FILE *fp)	{ return feof(fp); }
static int   app_fsetmod(FILE *fp,char mod)
{ return _setmode (_fileno(fp),mod=='b'?_O_BINARY:_O_TEXT); }

__declspec(dllexport) void **OPENSSL_Applink()
{ static int once=1;
  static void *OPENSSL_ApplinkTable[APPLINK_MAX+1]={(void *)APPLINK_MAX};

    if (once)
    {	OPENSSL_ApplinkTable[APPLINK_STDIN]	= app_stdin;
	OPENSSL_ApplinkTable[APPLINK_STDOUT]	= app_stdout;
	OPENSSL_ApplinkTable[APPLINK_STDERR]	= app_stderr;
	OPENSSL_ApplinkTable[APPLINK_FPRINTF]	= fprintf;
	OPENSSL_ApplinkTable[APPLINK_FGETS]	= fgets;
	OPENSSL_ApplinkTable[APPLINK_FREAD]	= fread;
	OPENSSL_ApplinkTable[APPLINK_FWRITE]	= fwrite;
	OPENSSL_ApplinkTable[APPLINK_FSETMOD]	= app_fsetmod;
	OPENSSL_ApplinkTable[APPLINK_FEOF]	= app_feof;
	OPENSSL_ApplinkTable[APPLINK_FCLOSE]	= fclose;
	once = 0;
    }

  return OPENSSL_ApplinkTable;
}
#endif

ms/uplink.c

0 → 100644
+168 −0
Original line number Diff line number Diff line
#if defined(_WIN64) && !defined(UNICODE)
#define UNICODE
#endif
#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#endif
#if defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#if defined(_MSC_VER) && !defined(_WIN32_WINNT)
#define _WIN32_WINNT 0x0333	/* 3.51 */
#endif

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <malloc.h>
#include "uplink.h"

#ifdef _MSC_VER
#pragma comment(lib,"delayimp")
/*
 * CL command line should also be complemented with following:
 *
 *	/link /delayload:advapi32.dll /delayload:user32.dll
 *
 * This is required if/as we want to support Win9x. With delayloaded
 * DLLs in question all we have to do is to make sure NT-specific
 * functions are not actually called under Win9x.
 */
#endif

#if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
int IsService()
{ HWINSTA h;
  DWORD len;
  WCHAR *name;

    GetDesktopWindow(); /* return value is ignored */

    h = GetProcessWindowStation();
    if (h==NULL) return -1;

    if (GetUserObjectInformationW (h,UOI_NAME,NULL,0,&len) ||
	GetLastError() != ERROR_INSUFFICIENT_BUFFER)
	return -1;

    if (len>512) return -1;		/* paranoia */
    len++,len&=~1;			/* paranoia */
#ifdef _MSC_VER
    name=(WCHAR *)_alloca(len+sizeof(WCHAR));
#else
    name=(WCHAR *)alloca(len+sizeof(WCHAR));
#endif
    if (!GetUserObjectInformationW (h,UOI_NAME,name,len,&len))
	return -1;

    len++,len&=~1;			/* paranoia */
    name[len/sizeof(WCHAR)]=L'\0';	/* paranoia */
#if 1
    /* This doesn't cover "interactive" services [working with real
     * WinSta0's] nor programs started non-interactively by Task
     * Scheduler [those are working with SAWinSta]. */
    if (wcsstr(name,L"Service-0x"))	return 1;
#else
    /* This covers all non-interactive programs such as services. */
    if (!wcsstr(name,L"WinSta0"))	return 1;
#endif
    else				return 0;
}
#endif

static TCHAR msg[128];

static void unimplemented ()
{
#if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
    /* this -------------v--- guards NT-specific calls */
    if (GetVersion() < 0x80000000 && IsService())
    {	HANDLE h = RegisterEventSource(0,_T("OPENSSL"));
	TCHAR *pmsg=msg;
	ReportEvent(h,EVENTLOG_ERROR_TYPE,0,0,0,1,0,&pmsg,0);
	DeregisterEventSource(h);
    }
    else
#endif
    {	MSGBOXPARAMS         m;

	m.cbSize             = sizeof(m);
	m.hwndOwner          = NULL;
	m.lpszCaption        = _T("OpenSSL: FATAL");
	m.dwStyle            = MB_OK;
	m.hInstance          = NULL;
	m.lpszIcon           = IDI_ERROR;
	m.dwContextHelpId    = 0;
	m.lpfnMsgBoxCallback = NULL;
	m.dwLanguageId       = MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US);
	m.lpszText           = msg;

	MessageBoxIndirect (&m);
    }
    ExitProcess (1);
}

void OPENSSL_Uplink (void **table, int index)
{ static HMODULE app=NULL;
  static void **applinktable=NULL;
  int len;

    len = _stprintf (msg,_T("OPENSSL_Uplink(%p,%02X): "),table,index);
    _tcscpy (msg+len,_T("unimplemented function"));
    table [index] = unimplemented;

    if (app==NULL && (app=GetModuleHandle(NULL))==NULL)
    {	app=(HMODULE)-1; _tcscpy (msg+len,_T("no host application"));
	return;
    }
    else if (app==(HMODULE)-1)	{ return; }

    if (applinktable==NULL)
    { void**(*applink)();

	applink=(void**(*)())GetProcAddress(app,"OPENSSL_Applink");
	if (applink==NULL)
	{   app=(HMODULE)-1; _tcscpy (msg+len,_T("no OPENSSL_Applink"));
	    return;
	}
	applinktable = (*applink)();
	if (applinktable==NULL)
	{   app=(HMODULE)-1; _tcscpy (msg+len,_T("no ApplinkTable"));
	    return;
	}
    }

    if (index > (int)applinktable[0])	{ return; }

    if (applinktable[index]) table[index] = applinktable[index];
}    

#if defined(_MSC_VER) && defined(_M_IX86)
#define LAZY(i)		\
__declspec(naked) static void lazy##i () { 	\
	_asm	push i				\
	_asm	push OFFSET OPENSSL_UplinkTable	\
	_asm	call OPENSSL_Uplink		\
	_asm	add  esp,8			\
	_asm	jmp  OPENSSL_UplinkTable+4*i	}

#if APPLINK_MAX>20
#error "Add more stubs..."
#endif
/* make some in advance... */
LAZY(1)  LAZY(2)  LAZY(3)  LAZY(4)  LAZY(5)
LAZY(6)  LAZY(7)  LAZY(8)  LAZY(9)  LAZY(10)
LAZY(11) LAZY(12) LAZY(13) LAZY(14) LAZY(15)
LAZY(16) LAZY(17) LAZY(18) LAZY(19) LAZY(20)
void *OPENSSL_UplinkTable[] = {
	(void *)APPLINK_MAX,
	lazy1, lazy2, lazy3, lazy4, lazy5,
	lazy6, lazy7, lazy8, lazy9, lazy10,
	lazy11,lazy12,lazy13,lazy14,lazy15,
	lazy16,lazy17,lazy18,lazy19,lazy20,
};
#endif

#ifdef SELFTEST
main() {  UP_fprintf(UP_stdout,"hello, world!\n"); }
#endif

ms/uplink.h

0 → 100644
+14 −0
Original line number Diff line number Diff line
#define APPMACROS_ONLY
#include "applink.c"

extern void *OPENSSL_UplinkTable[];
#define UP_stdin  (*(void *(*)())OPENSSL_UplinkTable[APPLINK_STDIN])()
#define UP_stdout (*(void *(*)())OPENSSL_UplinkTable[APPLINK_STDOUT])()
#define UP_stderr (*(void *(*)())OPENSSL_UplinkTable[APPLINK_STDERR])()
#define UP_fprintf (*(int (*)(void *,const char *,...))OPENSSL_UplinkTable[APPLINK_FPRINTF])
#define UP_fgets  (*(char *(*)(char *,int,void *))OPENSSL_UplinkTable[APPLINK_FGETS])
#define UP_fread  (*(size_t (*)(void *,size_t,size_t,void *))OPENSSL_UplinkTable[APPLINK_FREAD])
#define UP_fwrite (*(size_t (*)(void *,size_t,size_t,void *))OPENSSL_UplinkTable[APPLINK_FWRITE])
#define UP_fsetmod (*(int (*)(void *,char))OPENSSL_UplinkTable[APPLINK_FSETMOD])
#define UP_feof   (*(int (*)(void *))OPENSSL_UplinkTable[APPLINK_FEOF])
#define UP_fclose (*(int (*)(void *))OPENSSL_Uplink[APPLINK_FCLOSE])

ms/uplink.pl

0 → 100755
+177 −0
Original line number Diff line number Diff line
#!/usr/bin/env perl
#
# For Microsoft CL this is implemented as inline assembler. So that
# even though this script can generate even Win32 code, we'll be
# using it primarily to generate Win64 modules. Both IA-64 and AMD64
# are supported...

# pull APPLINK_MAX value from applink.c...
$applink_c=$0;
$applink_c=~s|[^/\\]+$||g;
$applink_c.="applink.c";
open(INPUT,$applink_c) || die "can't open $applink_c: $!";
@max=grep {/APPLINK_MAX\s+(\d+)/} <INPUT>;
close(INPUT);
($#max==0) or die "can't find APPLINK_MAX in $applink_c";

$max[0]=~/APPLINK_MAX\s+(\d+)/;
$N=$1;	# number of entries in OPENSSL_UplinkTable not including
	# OPENSSL_UplinkTable[0], which contains this value...

# Idea is to fill the OPENSSL_UplinkTable with pointers to stubs
# which invoke 'void OPENSSL_Uplink (ULONG_PTR *table,int index)';
# and then dereference themselves. Latter shall result in endless
# loop *unless* OPENSSL_Uplink does not replace 'table[index]' with
# something else, e.g. as 'table[index]=unimplemented;'...

$arg = shift;
#( defined shift || open STDOUT,">$arg" ) || die "can't open $arg: $!";

if ($arg =~ /win32n/)	{ ia32nasm();  }
elsif ($arg =~ /win32/)	{ ia32masm();  }
elsif ($arg =~ /ia64/)	{ ia64ias();   }
elsif ($arg =~ /amd64/)	{ amd64masm(); }
else	{ die "nonsense $arg"; }

sub ia32masm() {
print <<___;
.386P
.model	FLAT

_DATA	SEGMENT
PUBLIC	_OPENSSL_UplinkTable
_OPENSSL_UplinkTable	DD	$N	; amount of following entries
___
for ($i=1;$i<=$N;$i++) {   print "	DD	FLAT:\$lazy$i\n";   }
print <<___;
_DATA	ENDS

_TEXT	SEGMENT
EXTRN	_OPENSSL_Uplink:NEAR
___
for ($i=1;$i<=$N;$i++) {
print <<___;
ALIGN	4
\$lazy$i	PROC NEAR
	push	$i
	push	OFFSET FLAT:_OPENSSL_UplinkTable
	call	_OPENSSL_Uplink
	add	esp,8
	jmp	DWORD PTR _OPENSSL_UplinkTable+4*$i
\$lazy$i	ENDP
___
}
print <<___;
ALIGN	4
_TEXT	ENDS
END
___
}

sub ia32nasm() {
print <<___;
SEGMENT	.data
GLOBAL	_OPENSSL_UplinkTable
_OPENSSL_UplinkTable	DD	$N	; amount of following entries
___
for ($i=1;$i<=$N;$i++) {   print "	DD	\$lazy$i\n";   }
print <<___;

SEGMENT	.text
EXTERN	_OPENSSL_Uplink
___
for ($i=1;$i<=$N;$i++) {
print <<___;
ALIGN	4
\$lazy$i:
	push	$i
	push	_OPENSSL_UplinkTable
	call	_OPENSSL_Uplink
	add	esp,8
	jmp	[_OPENSSL_UplinkTable+4*$i]
___
}
print <<___;
ALIGN	4
END
___
}

sub ia64ias () {
local $V=8;	# max number of args uplink functions may accept...
print <<___;
.data
.global	OPENSSL_UplinkTable#
OPENSSL_UplinkTable:	data8	$N	// amount of following entries
___
for ($i=1;$i<=$N;$i++) {   print "	data8	\@fptr(lazy$i#)\n";   }
print <<___;
.size	OPENSSL_UplinkTable,.-OPENSSL_UplinkTable#

.text
.global	OPENSSL_Uplink#
.type	OPENSSL_Uplink#,\@function
___
for ($i=1;$i<=$N;$i++) {
print <<___;
.proc	lazy$i
lazy$i:
{ .mii;	alloc	loc0=ar.pfs,$V,3,2,0
	mov	loc1=b0
	addl	loc2=\@ltoff(OPENSSL_UplinkTable#),gp	};;
{ .mmi;	ld8	out0=[loc2]
	mov	out1=$i					};;
{ .mib;	adds	loc2=8*$i,out0
	br.call.sptk.many	b0=OPENSSL_Uplink#	};;
{ .mmi;	ld8	r31=[loc2];;
	ld8	r30=[r31],8				};;
{ .mii;	ld8	gp=[r31]
	mov	b6=r30
	mov	b0=loc1					};;
{ .mib; mov	ar.pfs=loc0
	br.many	b6					};;
.endp	lazy$i#
___
}
}

sub amd64masm() {
print <<___;
_DATA	SEGMENT
PUBLIC	OPENSSL_UplinkTable
OPENSSL_UplinkTable	DQ	$N
___
for ($i=1;$i<=$N;$i++) {   print "	DQ	FLAT:\$lazy$i\n";   }
print <<___;
_DATA	ENDS

TEXT	SEGMENT
EXTERN	OPENSSL_Uplink:NEAR
___
for ($i=1;$i<=$N;$i++) {
print <<___;
ALIGN	4
\$lazy$i	PROC NEAR
	push	r9
	push	r8
	push	rdx
	push	rcx
	sub	rsp,40
	mov	rcx,OFFSET FLAT:OPENSSL_UplinkTable
	mov	rdx,$i
	call	OPENSSL_Uplink
	add	rsp,40
	pop	rcx
	pop	rdx
	pop	r8
	pop	r9
	jmp	QWORD PTR OPENSSL_UplinkTable+8*$i
\$lazy$i	ENDP
___
}
print <<___;
TEXT	ENDS
END
___
}