|  | #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 |