summaryrefslogtreecommitdiffstats
path: root/ms/uplink.c
blob: 8c61a7ed1d70b7b069c71140f92f1fed5f870adb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#if (defined(_WIN64) || defined(_WIN32_WCE)) && !defined(UNICODE)
# define UNICODE
#endif
#if defined(UNICODE) && !defined(_UNICODE)
# define _UNICODE
#endif
#if defined(_UNICODE) && !defined(UNICODE)
# define UNICODE
#endif

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include "uplink.h"
void OPENSSL_showfatal(const char *, ...);

static TCHAR msg[128];

static void unimplemented(void)
{
    OPENSSL_showfatal(sizeof(TCHAR) == sizeof(char) ? "%s\n" : "%S\n", msg);
    TerminateProcess(GetCurrentProcess(), 1);
}

void OPENSSL_Uplink(volatile void **table, int index)
{
    static HMODULE volatile apphandle = NULL;
    static void **volatile applinktable = NULL;
    int len;
    void (*func) (void) = unimplemented;
    HANDLE h;
    void **p;

    /*
     * Note that the below code is not MT-safe in respect to msg buffer, but
     * what's the worst thing that can happen? Error message might be
     * misleading or corrupted. As error condition is fatal and should never
     * be risen, I accept the risk...
     */
    /*
     * One can argue that I should have used InterlockedExchangePointer or
     * something to update static variables and table[]. Well, store
     * instructions are as atomic as they can get and assigned values are
     * effectively constant... So that volatile qualifier should be
     * sufficient [it prohibits compiler to reorder memory access
     * instructions].
     */
    do {
        len = _sntprintf(msg, sizeof(msg) / sizeof(TCHAR),
                         _T("OPENSSL_Uplink(%p,%02X): "), table, index);
        _tcscpy(msg + len, _T("unimplemented function"));

        if ((h = apphandle) == NULL) {
            if ((h = GetModuleHandle(NULL)) == NULL) {
                apphandle = (HMODULE) - 1;
                _tcscpy(msg + len, _T("no host application"));
                break;
            }
            apphandle = h;
        }
        if ((h = apphandle) == (HMODULE) - 1) /* revalidate */
            break;

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

            applink = (void **(*)())GetProcAddress(h, "OPENSSL_Applink");
            if (applink == NULL) {
                apphandle = (HMODULE) - 1;
                _tcscpy(msg + len, _T("no OPENSSL_Applink"));
                break;
            }
            p = (*applink) ();
            if (p == NULL) {
                apphandle = (HMODULE) - 1;
                _tcscpy(msg + len, _T("no ApplinkTable"));
                break;
            }
            applinktable = p;
        } else
            p = applinktable;

        if (index > (int)p[0])
            break;

        if (p[index])
            func = p[index];
    } while (0);

    table[index] = func;
}

#if defined(_MSC_VER) && defined(_M_IX86)
# define LAZY(i)         \
__declspec(naked) static void lazy##i (void) {  \
        _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>25
#  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)
    LAZY(21) LAZY(22) LAZY(23) LAZY(24) LAZY(25)
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,
    lazy21, lazy22, lazy23, lazy24, lazy25,
};
#endif

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