Blame ms/uplink.c

Packit c4476c
/*
Packit c4476c
 * Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
 *
Packit c4476c
 * Licensed under the OpenSSL license (the "License").  You may not use
Packit c4476c
 * this file except in compliance with the License.  You can obtain a copy
Packit c4476c
 * in the file LICENSE in the source distribution or at
Packit c4476c
 * https://www.openssl.org/source/license.html
Packit c4476c
 */
Packit c4476c
Packit c4476c
#if (defined(_WIN64) || defined(_WIN32_WCE)) && !defined(UNICODE)
Packit c4476c
# define UNICODE
Packit c4476c
#endif
Packit c4476c
#if defined(UNICODE) && !defined(_UNICODE)
Packit c4476c
# define _UNICODE
Packit c4476c
#endif
Packit c4476c
#if defined(_UNICODE) && !defined(UNICODE)
Packit c4476c
# define UNICODE
Packit c4476c
#endif
Packit c4476c
Packit c4476c
#include <windows.h>
Packit c4476c
#include <tchar.h>
Packit c4476c
#include <stdio.h>
Packit c4476c
#include "uplink.h"
Packit c4476c
void OPENSSL_showfatal(const char *, ...);
Packit c4476c
Packit c4476c
static TCHAR msg[128];
Packit c4476c
Packit c4476c
static void unimplemented(void)
Packit c4476c
{
Packit c4476c
    OPENSSL_showfatal(sizeof(TCHAR) == sizeof(char) ? "%s\n" : "%S\n", msg);
Packit c4476c
    TerminateProcess(GetCurrentProcess(), 1);
Packit c4476c
}
Packit c4476c
Packit c4476c
void OPENSSL_Uplink(volatile void **table, int index)
Packit c4476c
{
Packit c4476c
    static HMODULE volatile apphandle = NULL;
Packit c4476c
    static void **volatile applinktable = NULL;
Packit c4476c
    int len;
Packit c4476c
    void (*func) (void) = unimplemented;
Packit c4476c
    HANDLE h;
Packit c4476c
    void **p;
Packit c4476c
Packit c4476c
    /*
Packit c4476c
     * Note that the below code is not MT-safe in respect to msg buffer, but
Packit c4476c
     * what's the worst thing that can happen? Error message might be
Packit c4476c
     * misleading or corrupted. As error condition is fatal and should never
Packit c4476c
     * be risen, I accept the risk...
Packit c4476c
     */
Packit c4476c
    /*
Packit c4476c
     * One can argue that I should have used InterlockedExchangePointer or
Packit c4476c
     * something to update static variables and table[]. Well, store
Packit c4476c
     * instructions are as atomic as they can get and assigned values are
Packit c4476c
     * effectively constant... So that volatile qualifier should be
Packit c4476c
     * sufficient [it prohibits compiler to reorder memory access
Packit c4476c
     * instructions].
Packit c4476c
     */
Packit c4476c
    do {
Packit c4476c
        len = _sntprintf(msg, sizeof(msg) / sizeof(TCHAR),
Packit c4476c
                         _T("OPENSSL_Uplink(%p,%02X): "), table, index);
Packit c4476c
        _tcscpy(msg + len, _T("unimplemented function"));
Packit c4476c
Packit c4476c
        if ((h = apphandle) == NULL) {
Packit c4476c
            if ((h = GetModuleHandle(NULL)) == NULL) {
Packit c4476c
                apphandle = (HMODULE) - 1;
Packit c4476c
                _tcscpy(msg + len, _T("no host application"));
Packit c4476c
                break;
Packit c4476c
            }
Packit c4476c
            apphandle = h;
Packit c4476c
        }
Packit c4476c
        if ((h = apphandle) == (HMODULE) - 1) /* revalidate */
Packit c4476c
            break;
Packit c4476c
Packit c4476c
        if (applinktable == NULL) {
Packit c4476c
            void **(*applink) ();
Packit c4476c
Packit c4476c
            applink = (void **(*)())GetProcAddress(h, "OPENSSL_Applink");
Packit c4476c
            if (applink == NULL) {
Packit c4476c
                apphandle = (HMODULE) - 1;
Packit c4476c
                _tcscpy(msg + len, _T("no OPENSSL_Applink"));
Packit c4476c
                break;
Packit c4476c
            }
Packit c4476c
            p = (*applink) ();
Packit c4476c
            if (p == NULL) {
Packit c4476c
                apphandle = (HMODULE) - 1;
Packit c4476c
                _tcscpy(msg + len, _T("no ApplinkTable"));
Packit c4476c
                break;
Packit c4476c
            }
Packit c4476c
            applinktable = p;
Packit c4476c
        } else
Packit c4476c
            p = applinktable;
Packit c4476c
Packit c4476c
        if (index > (int)p[0])
Packit c4476c
            break;
Packit c4476c
Packit c4476c
        if (p[index])
Packit c4476c
            func = p[index];
Packit c4476c
    } while (0);
Packit c4476c
Packit c4476c
    table[index] = func;
Packit c4476c
}
Packit c4476c
Packit c4476c
#if defined(_MSC_VER) && defined(_M_IX86)
Packit c4476c
# define LAZY(i)         \
Packit c4476c
__declspec(naked) static void lazy##i (void) {  \
Packit c4476c
        _asm    push i                          \
Packit c4476c
        _asm    push OFFSET OPENSSL_UplinkTable \
Packit c4476c
        _asm    call OPENSSL_Uplink             \
Packit c4476c
        _asm    add  esp,8                      \
Packit c4476c
        _asm    jmp  OPENSSL_UplinkTable+4*i    }
Packit c4476c
Packit c4476c
# if APPLINK_MAX>25
Packit c4476c
#  error "Add more stubs..."
Packit c4476c
# endif
Packit c4476c
/* make some in advance... */
Packit c4476c
LAZY(1) LAZY(2) LAZY(3) LAZY(4) LAZY(5)
Packit c4476c
    LAZY(6) LAZY(7) LAZY(8) LAZY(9) LAZY(10)
Packit c4476c
    LAZY(11) LAZY(12) LAZY(13) LAZY(14) LAZY(15)
Packit c4476c
    LAZY(16) LAZY(17) LAZY(18) LAZY(19) LAZY(20)
Packit c4476c
    LAZY(21) LAZY(22) LAZY(23) LAZY(24) LAZY(25)
Packit c4476c
void *OPENSSL_UplinkTable[] = {
Packit c4476c
    (void *)APPLINK_MAX,
Packit c4476c
    lazy1, lazy2, lazy3, lazy4, lazy5,
Packit c4476c
    lazy6, lazy7, lazy8, lazy9, lazy10,
Packit c4476c
    lazy11, lazy12, lazy13, lazy14, lazy15,
Packit c4476c
    lazy16, lazy17, lazy18, lazy19, lazy20,
Packit c4476c
    lazy21, lazy22, lazy23, lazy24, lazy25,
Packit c4476c
};
Packit c4476c
#endif
Packit c4476c
Packit c4476c
#ifdef SELFTEST
Packit c4476c
main()
Packit c4476c
{
Packit c4476c
    UP_fprintf(UP_stdout, "hello, world!\n");
Packit c4476c
}
Packit c4476c
#endif