| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 | /* * Copyright 1998-2023 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. 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 */#include "internal/e_os.h"#include "crypto/cryptlib.h"#include <openssl/safestack.h>#if defined(_WIN32) && !defined(OPENSSL_SYS_UEFI)# include <tchar.h># include <signal.h># ifdef __WATCOMC__#  if defined(_UNICODE) || defined(__UNICODE__)#   define _vsntprintf _vsnwprintf#  else#   define _vsntprintf _vsnprintf#  endif# endif# ifdef _MSC_VER#  define alloca _alloca# endif# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333#  ifdef OPENSSL_SYS_WIN_COREint OPENSSL_isservice(void){    /* OneCore API cannot interact with GUI */    return 1;}#  elseint OPENSSL_isservice(void){    HWINSTA h;    DWORD len;    WCHAR *name;    static union {        void *p;        int (*f) (void);    } _OPENSSL_isservice = {        NULL    };    if (_OPENSSL_isservice.p == NULL) {        HANDLE mod = GetModuleHandle(NULL);        FARPROC f = NULL;        if (mod != NULL)            f = GetProcAddress(mod, "_OPENSSL_isservice");        if (f == NULL)            _OPENSSL_isservice.p = (void *)-1;        else            _OPENSSL_isservice.f = f;    }    if (_OPENSSL_isservice.p != (void *)-1)        return (*_OPENSSL_isservice.f) ();    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 */    name = (WCHAR *)alloca(len + sizeof(WCHAR));    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# elseint OPENSSL_isservice(void){    return 0;}# endifvoid OPENSSL_showfatal(const char *fmta, ...){    va_list ap;    TCHAR buf[256];    const TCHAR *fmt;    /*     * First check if it's a console application, in which case the     * error message would be printed to standard error.     * Windows CE does not have a concept of a console application,     * so we need to guard the check.     */# ifdef STD_ERROR_HANDLE    HANDLE h;    if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL &&        GetFileType(h) != FILE_TYPE_UNKNOWN) {        /* must be console application */        int len;        DWORD out;        va_start(ap, fmta);        len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap);        WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL);        va_end(ap);        return;    }# endif    if (sizeof(TCHAR) == sizeof(char))        fmt = (const TCHAR *)fmta;    else        do {            int keepgoing;            size_t len_0 = strlen(fmta) + 1, i;            WCHAR *fmtw;            fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));            if (fmtw == NULL) {                fmt = (const TCHAR *)L"no stack?";                break;            }            if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0))                for (i = 0; i < len_0; i++)                    fmtw[i] = (WCHAR)fmta[i];            for (i = 0; i < len_0; i++) {                if (fmtw[i] == L'%')                    do {                        keepgoing = 0;                        switch (fmtw[i + 1]) {                        case L'0':                        case L'1':                        case L'2':                        case L'3':                        case L'4':                        case L'5':                        case L'6':                        case L'7':                        case L'8':                        case L'9':                        case L'.':                        case L'*':                        case L'-':                            i++;                            keepgoing = 1;                            break;                        case L's':                            fmtw[i + 1] = L'S';                            break;                        case L'S':                            fmtw[i + 1] = L's';                            break;                        case L'c':                            fmtw[i + 1] = L'C';                            break;                        case L'C':                            fmtw[i + 1] = L'c';                            break;                        }                    } while (keepgoing);            }            fmt = (const TCHAR *)fmtw;        } while (0);    va_start(ap, fmta);    _vsntprintf(buf, OSSL_NELEM(buf) - 1, fmt, ap);    buf[OSSL_NELEM(buf) - 1] = _T('\0');    va_end(ap);# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333#  ifdef OPENSSL_SYS_WIN_CORE    /* ONECORE is always NONGUI and NT >= 0x0601 */#   if !defined(NDEBUG)        /*        * We are in a situation where we tried to report a critical        * error and this failed for some reason. As a last resort,        * in debug builds, send output to the debugger or any other        * tool like DebugView which can monitor the output.        */        OutputDebugString(buf);#   endif#  else    /* this -------------v--- guards NT-specific calls */    if (check_winnt() && OPENSSL_isservice() > 0) {        HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL"));        if (hEventLog != NULL) {            const TCHAR *pmsg = buf;            if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL,                             1, 0, &pmsg, NULL)) {#   if !defined(NDEBUG)                /*                 * We are in a situation where we tried to report a critical                 * error and this failed for some reason. As a last resort,                 * in debug builds, send output to the debugger or any other                 * tool like DebugView which can monitor the output.                 */                OutputDebugString(pmsg);#   endif            }            (void)DeregisterEventSource(hEventLog);        }    } else {        MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR);    }#  endif# else    MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR);# endif}#elsevoid OPENSSL_showfatal(const char *fmta, ...){#ifndef OPENSSL_NO_STDIO    va_list ap;    va_start(ap, fmta);    vfprintf(stderr, fmta, ap);    va_end(ap);#endif}int OPENSSL_isservice(void){    return 0;}#endifvoid OPENSSL_die(const char *message, const char *file, int line){    OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n",                      file, line, message);#if !defined(_WIN32) || defined(OPENSSL_SYS_UEFI)    abort();#else    /*     * Win32 abort() customarily shows a dialog, but we just did that...     */# if !defined(_WIN32_WCE)    raise(SIGABRT);# endif    _exit(3);#endif}#if defined(__TANDEM) && defined(OPENSSL_VPROC)/* * Define a VPROC function for HP NonStop build crypto library. * This is used by platform version identification tools. * Do not inline this procedure or make it static. */# define OPENSSL_VPROC_STRING_(x)    x##_CRYPTO# define OPENSSL_VPROC_STRING(x)     OPENSSL_VPROC_STRING_(x)# define OPENSSL_VPROC_FUNC          OPENSSL_VPROC_STRING(OPENSSL_VPROC)void OPENSSL_VPROC_FUNC(void) {}#endif /* __TANDEM */
 |