Update FAQ.
[openssl.git] / ms / uplink.c
1 #if (defined(_WIN64) || defined(_WIN32_WCE)) && !defined(UNICODE)
2 #define UNICODE
3 #endif
4 #if defined(UNICODE) && !defined(_UNICODE)
5 #define _UNICODE
6 #endif
7 #if defined(_UNICODE) && !defined(UNICODE)
8 #define UNICODE
9 #endif
10
11 #include <windows.h>
12 #include <tchar.h>
13 #include <stdio.h>
14 #include "uplink.h"
15 void OPENSSL_showfatal(const char *,...);
16
17 static TCHAR msg[128];
18
19 static void unimplemented (void)
20 {   OPENSSL_showfatal (sizeof(TCHAR)==sizeof(char)?"%s\n":"%S\n",msg);
21     ExitProcess (1);
22 }
23
24 void OPENSSL_Uplink (volatile void **table, int index)
25 { static HMODULE volatile apphandle=NULL;
26   static void ** volatile applinktable=NULL;
27   int len;
28   void (*func)(void)=unimplemented;
29   HANDLE h;
30   void **p;
31
32     /* Note that the below code is not MT-safe in respect to msg
33      * buffer, but what's the worst thing that can happen? Error
34      * message might be misleading or corrupted. As error condition
35      * is fatal and should never be risen, I accept the risk... */
36     /* One can argue that I should have used InterlockedExchangePointer
37      * or something to update static variables and table[]. Well,
38      * store instructions are as atomic as they can get and assigned
39      * values are effectively constant... So that volatile qualifier
40      * should be sufficient [it prohibits compiler to reorder memory
41      * access instructions]. */
42     do {
43         len = _sntprintf (msg,sizeof(msg)/sizeof(TCHAR),
44                           _T("OPENSSL_Uplink(%p,%02X): "),table,index);
45         _tcscpy (msg+len,_T("unimplemented function"));
46
47         if ((h=apphandle)==NULL)
48         {   if  ((h=GetModuleHandle(NULL))==NULL)
49             {   apphandle=(HMODULE)-1;
50                 _tcscpy (msg+len,_T("no host application"));
51                 break;
52             }
53             apphandle = h;
54         }
55         if ((h=apphandle)==(HMODULE)-1) /* revalidate */
56             break;
57
58         if (applinktable==NULL)
59         { void**(*applink)();
60
61             applink=(void**(*)())GetProcAddress(h,"OPENSSL_Applink");
62             if (applink==NULL)
63             {   apphandle=(HMODULE)-1;
64                 _tcscpy (msg+len,_T("no OPENSSL_Applink"));
65                 break;
66             }
67             p = (*applink)();
68             if (p==NULL)
69             {   apphandle=(HMODULE)-1;
70                 _tcscpy (msg+len,_T("no ApplinkTable"));
71                 break;
72             }
73             applinktable = p;
74         }
75         else
76             p = applinktable;
77
78         if (index > (int)p[0])
79             break;
80
81         if (p[index]) func = p[index];
82     } while (0);
83
84     table[index] = func;
85 }    
86
87 #if defined(_MSC_VER) && defined(_M_IX86) && !defined(OPENSSL_NO_INLINE_ASM)
88 #define LAZY(i)         \
89 __declspec(naked) static void lazy##i (void) {  \
90         _asm    push i                          \
91         _asm    push OFFSET OPENSSL_UplinkTable \
92         _asm    call OPENSSL_Uplink             \
93         _asm    add  esp,8                      \
94         _asm    jmp  OPENSSL_UplinkTable+4*i    }
95
96 #if APPLINK_MAX>25
97 #error "Add more stubs..."
98 #endif
99 /* make some in advance... */
100 LAZY(1)  LAZY(2)  LAZY(3)  LAZY(4)  LAZY(5)
101 LAZY(6)  LAZY(7)  LAZY(8)  LAZY(9)  LAZY(10)
102 LAZY(11) LAZY(12) LAZY(13) LAZY(14) LAZY(15)
103 LAZY(16) LAZY(17) LAZY(18) LAZY(19) LAZY(20)
104 LAZY(21) LAZY(22) LAZY(23) LAZY(24) LAZY(25)
105 void *OPENSSL_UplinkTable[] = {
106         (void *)APPLINK_MAX,
107         lazy1, lazy2, lazy3, lazy4, lazy5,
108         lazy6, lazy7, lazy8, lazy9, lazy10,
109         lazy11,lazy12,lazy13,lazy14,lazy15,
110         lazy16,lazy17,lazy18,lazy19,lazy20,
111         lazy21,lazy22,lazy23,lazy24,lazy25,
112 };
113 #endif
114
115 #ifdef SELFTEST
116 main() {  UP_fprintf(UP_stdout,"hello, world!\n"); }
117 #endif