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.
This commit is contained in:
parent
f2bfbcef76
commit
3fc378aa0b
45
ms/applink.c
Normal file
45
ms/applink.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#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
|
168
ms/uplink.c
Normal file
168
ms/uplink.c
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#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
|
14
ms/uplink.h
Normal file
14
ms/uplink.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#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])
|
177
ms/uplink.pl
Executable file
177
ms/uplink.pl
Executable file
@ -0,0 +1,177 @@
|
|||||||
|
#!/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
|
||||||
|
___
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user