]>
Commit | Line | Data |
---|---|---|
d2e9e320 | 1 | /* |
fecb3aae | 2 | * Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved. |
aa8f3d76 | 3 | * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved |
19b8d06a | 4 | * |
0e9725bc | 5 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
d2e9e320 RS |
6 | * this file except in compliance with the License. You can obtain a copy |
7 | * in the file LICENSE in the source distribution or at | |
8 | * https://www.openssl.org/source/license.html | |
19b8d06a | 9 | */ |
d2e9e320 | 10 | |
d5f9166b | 11 | #include "internal/e_os.h" |
25f2138b | 12 | #include "crypto/cryptlib.h" |
c7922304 | 13 | #include <openssl/safestack.h> |
d02b48c6 | 14 | |
4d3c278c | 15 | #if defined(_WIN32) |
0f113f3e MC |
16 | # include <tchar.h> |
17 | # include <signal.h> | |
18 | # ifdef __WATCOMC__ | |
19 | # if defined(_UNICODE) || defined(__UNICODE__) | |
20 | # define _vsntprintf _vsnwprintf | |
21 | # else | |
22 | # define _vsntprintf _vsnprintf | |
23 | # endif | |
24 | # endif | |
25 | # ifdef _MSC_VER | |
26 | # define alloca _alloca | |
27 | # endif | |
28 | ||
29 | # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 | |
b2b4dfcc P |
30 | # ifdef OPENSSL_SYS_WIN_CORE |
31 | ||
32 | int OPENSSL_isservice(void) | |
33 | { | |
34 | /* OneCore API cannot interact with GUI */ | |
35 | return 1; | |
36 | } | |
37 | # else | |
e476f942 | 38 | int OPENSSL_isservice(void) |
0f113f3e MC |
39 | { |
40 | HWINSTA h; | |
41 | DWORD len; | |
42 | WCHAR *name; | |
43 | static union { | |
44 | void *p; | |
156561b0 | 45 | FARPROC f; |
0f113f3e MC |
46 | } _OPENSSL_isservice = { |
47 | NULL | |
48 | }; | |
471d0eb3 AP |
49 | |
50 | if (_OPENSSL_isservice.p == NULL) { | |
156561b0 | 51 | HANDLE mod = GetModuleHandle(NULL); |
af7d8d34 | 52 | FARPROC f = NULL; |
9e4a1c3f | 53 | |
156561b0 | 54 | if (mod != NULL) |
9e4a1c3f AP |
55 | f = GetProcAddress(mod, "_OPENSSL_isservice"); |
56 | if (f == NULL) | |
0f113f3e | 57 | _OPENSSL_isservice.p = (void *)-1; |
9e4a1c3f AP |
58 | else |
59 | _OPENSSL_isservice.f = f; | |
471d0eb3 AP |
60 | } |
61 | ||
62 | if (_OPENSSL_isservice.p != (void *)-1) | |
0f113f3e | 63 | return (*_OPENSSL_isservice.f) (); |
9f2027e5 | 64 | |
9f2027e5 | 65 | h = GetProcessWindowStation(); |
0f113f3e MC |
66 | if (h == NULL) |
67 | return -1; | |
68 | ||
69 | if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) || | |
70 | GetLastError() != ERROR_INSUFFICIENT_BUFFER) | |
71 | return -1; | |
72 | ||
73 | if (len > 512) | |
74 | return -1; /* paranoia */ | |
75 | len++, len &= ~1; /* paranoia */ | |
76 | name = (WCHAR *)alloca(len + sizeof(WCHAR)); | |
77 | if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len)) | |
78 | return -1; | |
79 | ||
80 | len++, len &= ~1; /* paranoia */ | |
81 | name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */ | |
b2b4dfcc | 82 | # if 1 |
0f113f3e MC |
83 | /* |
84 | * This doesn't cover "interactive" services [working with real | |
85 | * WinSta0's] nor programs started non-interactively by Task Scheduler | |
86 | * [those are working with SAWinSta]. | |
87 | */ | |
88 | if (wcsstr(name, L"Service-0x")) | |
89 | return 1; | |
b2b4dfcc | 90 | # else |
9f2027e5 | 91 | /* This covers all non-interactive programs such as services. */ |
0f113f3e MC |
92 | if (!wcsstr(name, L"WinSta0")) |
93 | return 1; | |
b2b4dfcc | 94 | # endif |
0f113f3e MC |
95 | else |
96 | return 0; | |
9f2027e5 | 97 | } |
b2b4dfcc | 98 | # endif |
0f113f3e MC |
99 | # else |
100 | int OPENSSL_isservice(void) | |
101 | { | |
102 | return 0; | |
103 | } | |
104 | # endif | |
105 | ||
106 | void OPENSSL_showfatal(const char *fmta, ...) | |
107 | { | |
108 | va_list ap; | |
109 | TCHAR buf[256]; | |
110 | const TCHAR *fmt; | |
2f0ca54c EK |
111 | /* |
112 | * First check if it's a console application, in which case the | |
113 | * error message would be printed to standard error. | |
114 | * Windows CE does not have a concept of a console application, | |
115 | * so we need to guard the check. | |
116 | */ | |
117 | # ifdef STD_ERROR_HANDLE | |
0f113f3e MC |
118 | HANDLE h; |
119 | ||
120 | if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL && | |
121 | GetFileType(h) != FILE_TYPE_UNKNOWN) { | |
122 | /* must be console application */ | |
123 | int len; | |
124 | DWORD out; | |
125 | ||
126 | va_start(ap, fmta); | |
127 | len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap); | |
128 | WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL); | |
129 | va_end(ap); | |
130 | return; | |
9f2027e5 | 131 | } |
0f113f3e | 132 | # endif |
9f2027e5 | 133 | |
0f113f3e MC |
134 | if (sizeof(TCHAR) == sizeof(char)) |
135 | fmt = (const TCHAR *)fmta; | |
9f2027e5 | 136 | else |
0f113f3e MC |
137 | do { |
138 | int keepgoing; | |
139 | size_t len_0 = strlen(fmta) + 1, i; | |
140 | WCHAR *fmtw; | |
141 | ||
142 | fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); | |
143 | if (fmtw == NULL) { | |
144 | fmt = (const TCHAR *)L"no stack?"; | |
145 | break; | |
146 | } | |
0f113f3e | 147 | if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0)) |
0f113f3e MC |
148 | for (i = 0; i < len_0; i++) |
149 | fmtw[i] = (WCHAR)fmta[i]; | |
0f113f3e MC |
150 | for (i = 0; i < len_0; i++) { |
151 | if (fmtw[i] == L'%') | |
152 | do { | |
153 | keepgoing = 0; | |
154 | switch (fmtw[i + 1]) { | |
155 | case L'0': | |
156 | case L'1': | |
157 | case L'2': | |
158 | case L'3': | |
159 | case L'4': | |
160 | case L'5': | |
161 | case L'6': | |
162 | case L'7': | |
163 | case L'8': | |
164 | case L'9': | |
165 | case L'.': | |
166 | case L'*': | |
167 | case L'-': | |
168 | i++; | |
169 | keepgoing = 1; | |
170 | break; | |
171 | case L's': | |
172 | fmtw[i + 1] = L'S'; | |
173 | break; | |
174 | case L'S': | |
175 | fmtw[i + 1] = L's'; | |
176 | break; | |
177 | case L'c': | |
178 | fmtw[i + 1] = L'C'; | |
179 | break; | |
180 | case L'C': | |
181 | fmtw[i + 1] = L'c'; | |
182 | break; | |
183 | } | |
184 | } while (keepgoing); | |
185 | } | |
186 | fmt = (const TCHAR *)fmtw; | |
187 | } while (0); | |
188 | ||
189 | va_start(ap, fmta); | |
bdcb1a2c DSH |
190 | _vsntprintf(buf, OSSL_NELEM(buf) - 1, fmt, ap); |
191 | buf[OSSL_NELEM(buf) - 1] = _T('\0'); | |
0f113f3e MC |
192 | va_end(ap); |
193 | ||
194 | # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 | |
b2b4dfcc P |
195 | # ifdef OPENSSL_SYS_WIN_CORE |
196 | /* ONECORE is always NONGUI and NT >= 0x0601 */ | |
b2b4dfcc P |
197 | # if !defined(NDEBUG) |
198 | /* | |
199 | * We are in a situation where we tried to report a critical | |
200 | * error and this failed for some reason. As a last resort, | |
201 | * in debug builds, send output to the debugger or any other | |
202 | * tool like DebugView which can monitor the output. | |
203 | */ | |
204 | OutputDebugString(buf); | |
205 | # endif | |
206 | # else | |
0f113f3e MC |
207 | /* this -------------v--- guards NT-specific calls */ |
208 | if (check_winnt() && OPENSSL_isservice() > 0) { | |
4cd94416 GK |
209 | HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL")); |
210 | ||
211 | if (hEventLog != NULL) { | |
212 | const TCHAR *pmsg = buf; | |
213 | ||
214 | if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL, | |
215 | 1, 0, &pmsg, NULL)) { | |
b2b4dfcc | 216 | # if !defined(NDEBUG) |
4cd94416 GK |
217 | /* |
218 | * We are in a situation where we tried to report a critical | |
219 | * error and this failed for some reason. As a last resort, | |
220 | * in debug builds, send output to the debugger or any other | |
221 | * tool like DebugView which can monitor the output. | |
222 | */ | |
223 | OutputDebugString(pmsg); | |
b2b4dfcc | 224 | # endif |
4cd94416 GK |
225 | } |
226 | ||
227 | (void)DeregisterEventSource(hEventLog); | |
228 | } | |
b2b4dfcc | 229 | } else { |
4cd94416 | 230 | MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); |
b2b4dfcc P |
231 | } |
232 | # endif | |
233 | # else | |
234 | MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); | |
df443918 | 235 | # endif |
9f2027e5 AP |
236 | } |
237 | #else | |
0f113f3e MC |
238 | void OPENSSL_showfatal(const char *fmta, ...) |
239 | { | |
984d6c60 | 240 | #ifndef OPENSSL_NO_STDIO |
0f113f3e MC |
241 | va_list ap; |
242 | ||
243 | va_start(ap, fmta); | |
244 | vfprintf(stderr, fmta, ap); | |
245 | va_end(ap); | |
984d6c60 | 246 | #endif |
0f113f3e | 247 | } |
9f2027e5 | 248 | |
0f113f3e MC |
249 | int OPENSSL_isservice(void) |
250 | { | |
251 | return 0; | |
9f2027e5 AP |
252 | } |
253 | #endif | |
254 | ||
040d43b3 | 255 | void OPENSSL_die(const char *message, const char *file, int line) |
0f113f3e | 256 | { |
040d43b3 RS |
257 | OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n", |
258 | file, line, message); | |
4d3c278c | 259 | #if !defined(_WIN32) |
0f113f3e | 260 | abort(); |
3b58c74c | 261 | #else |
0f113f3e MC |
262 | /* |
263 | * Win32 abort() customarily shows a dialog, but we just did that... | |
264 | */ | |
265 | # if !defined(_WIN32_WCE) | |
266 | raise(SIGABRT); | |
267 | # endif | |
268 | _exit(3); | |
3b58c74c | 269 | #endif |
0f113f3e | 270 | } |
9e88c827 | 271 | |
08073700 RB |
272 | #if defined(__TANDEM) && defined(OPENSSL_VPROC) |
273 | /* | |
274 | * Define a VPROC function for HP NonStop build crypto library. | |
275 | * This is used by platform version identification tools. | |
276 | * Do not inline this procedure or make it static. | |
277 | */ | |
278 | # define OPENSSL_VPROC_STRING_(x) x##_CRYPTO | |
279 | # define OPENSSL_VPROC_STRING(x) OPENSSL_VPROC_STRING_(x) | |
280 | # define OPENSSL_VPROC_FUNC OPENSSL_VPROC_STRING(OPENSSL_VPROC) | |
281 | void OPENSSL_VPROC_FUNC(void) {} | |
282 | #endif /* __TANDEM */ |