1 /* NetHack 3.7 winnt.c $NHDT-Date: 1596498321 2020/08/03 23:45:21 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.64 $ */
2 /* Copyright (c) NetHack PC Development Team 1993, 1994 */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 /*
6 * WIN32 system functions.
7 *
8 * Included in both console and window based clients on the windows platform.
9 *
10 * Initial Creation: Michael Allison - January 31/93
11 *
12 */
13
14 #include "win10.h"
15 #include "winos.h"
16
17 #define NEED_VARARGS
18 #include "hack.h"
19 #include <dos.h>
20 #ifndef __BORLANDC__
21 #include <direct.h>
22 #endif
23 #include <ctype.h>
24 #ifdef TTY_GRAPHICS
25 #include "wintty.h"
26 #endif
27 #ifdef WIN32
28
29 /*
30 * The following WIN32 API routines are used in this file.
31 *
32 * GetDiskFreeSpace
33 * GetVolumeInformation
34 * GetUserName
35 * FindFirstFile
36 * FindNextFile
37 * FindClose
38 *
39 */
40
41 /* runtime cursor display control switch */
42 boolean win32_cursorblink;
43
44 /* globals required within here */
45 HANDLE ffhandle = (HANDLE) 0;
46 WIN32_FIND_DATA ffd;
47 extern int GUILaunched;
48 boolean getreturn_enabled;
49 int redirect_stdout;
50
51 typedef HWND(WINAPI *GETCONSOLEWINDOW)();
52 static HWND GetConsoleHandle(void);
53 static HWND GetConsoleHwnd(void);
54 #if !defined(TTY_GRAPHICS)
55 extern void backsp(void);
56 #endif
57 int windows_console_custom_nhgetch(void);
58 extern void safe_routines(void);
59
60 /* The function pointer nt_kbhit contains a kbhit() equivalent
61 * which varies depending on which window port is active.
62 * For the tty port it is tty_kbhit() [from nttty.c]
63 * For the win32 port it is win32_kbhit() [from winmain.c]
64 * It is initialized to point to def_kbhit [in here] for safety.
65 */
66
67 int def_kbhit(void);
68 int (*nt_kbhit)() = def_kbhit;
69
70 char
switchar(void)71 switchar(void)
72 {
73 /* Could not locate a WIN32 API call for this- MJA */
74 return '-';
75 }
76
77 long
freediskspace(char * path)78 freediskspace(char* path)
79 {
80 char tmppath[4];
81 DWORD SectorsPerCluster = 0;
82 DWORD BytesPerSector = 0;
83 DWORD FreeClusters = 0;
84 DWORD TotalClusters = 0;
85
86 tmppath[0] = *path;
87 tmppath[1] = ':';
88 tmppath[2] = '\\';
89 tmppath[3] = '\0';
90 GetDiskFreeSpace(tmppath, &SectorsPerCluster, &BytesPerSector,
91 &FreeClusters, &TotalClusters);
92 return (long) (SectorsPerCluster * BytesPerSector * FreeClusters);
93 }
94
95 /*
96 * Functions to get filenames using wildcards
97 */
98 int
findfirst(char * path)99 findfirst(char* path)
100 {
101 if (ffhandle) {
102 FindClose(ffhandle);
103 ffhandle = (HANDLE) 0;
104 }
105 ffhandle = FindFirstFile(path, &ffd);
106 return (ffhandle == INVALID_HANDLE_VALUE) ? 0 : 1;
107 }
108
109 int
findnext(void)110 findnext(void)
111 {
112 return FindNextFile(ffhandle, &ffd) ? 1 : 0;
113 }
114
115 char *
foundfile_buffer(void)116 foundfile_buffer(void)
117 {
118 return &ffd.cFileName[0];
119 }
120
121 long
filesize(char * file)122 filesize(char* file)
123 {
124 if (findfirst(file)) {
125 return ((long) ffd.nFileSizeLow);
126 } else
127 return -1L;
128 }
129
130 /*
131 * Chdrive() changes the default drive.
132 */
133 void
chdrive(char * str)134 chdrive(char* str)
135 {
136 char *ptr;
137 char drive;
138 if ((ptr = index(str, ':')) != (char *) 0) {
139 drive = toupper((uchar) *(ptr - 1));
140 _chdrive((drive - 'A') + 1);
141 }
142 }
143
144 static int
max_filename(void)145 max_filename(void)
146 {
147 DWORD maxflen;
148 int status = 0;
149
150 status = GetVolumeInformation((LPTSTR) 0, (LPTSTR) 0, 0, (LPDWORD) 0,
151 &maxflen, (LPDWORD) 0, (LPTSTR) 0, 0);
152 if (status)
153 return maxflen;
154 else
155 return 0;
156 }
157
158 int
def_kbhit(void)159 def_kbhit(void)
160 {
161 return 0;
162 }
163
164 /*
165 * Strip out troublesome file system characters.
166 */
167
nt_regularize(char * s)168 void nt_regularize(char* s) /* normalize file name */
169 {
170 unsigned char *lp;
171
172 for (lp = (unsigned char *) s; *lp; lp++)
173 if (*lp == '?' || *lp == '"' || *lp == '\\' || *lp == '/'
174 || *lp == '>' || *lp == '<' || *lp == '*' || *lp == '|'
175 || *lp == ':' || (*lp > 127))
176 *lp = '_';
177 }
178
179 /*
180 * This is used in nhlan.c to implement some of the LAN_FEATURES.
181 */
182 char *
get_username(int * lan_username_size)183 get_username(int *lan_username_size)
184 {
185 static TCHAR username_buffer[BUFSZ];
186 DWORD i = BUFSZ - 1;
187 BOOL allowUserName = TRUE;
188
189 Strcpy(username_buffer, "NetHack");
190
191 #ifndef WIN32CON
192 /* Our privacy policy for the windows store version of nethack makes
193 * a promise about not collecting any personally identifiable information.
194 * Do not allow getting user name if we being run from windows store
195 * version of nethack. In 3.7, we should remove use of username.
196 */
197 allowUserName = !win10_is_desktop_bridge_application();
198 #endif
199
200 if (allowUserName) {
201 /* i gets updated with actual size */
202 if (GetUserName(username_buffer, &i))
203 username_buffer[i] = '\0';
204 }
205
206 if (lan_username_size)
207 *lan_username_size = strlen(username_buffer);
208 return username_buffer;
209 }
210
211 #if 0
212 char *getxxx(void)
213 {
214 char szFullPath[MAX_PATH] = "";
215 HMODULE hInst = NULL; /* NULL gets the filename of this module */
216
217 GetModuleFileName(hInst, szFullPath, sizeof(szFullPath));
218 return &szFullPath[0];
219 }
220 #endif
221
222 extern void mswin_raw_print_flush(void);
223 extern void mswin_raw_print(const char *);
224
225 /* fatal error */
226 /*VARARGS1*/
227 void error
VA_DECL(const char *,s)228 VA_DECL(const char *, s)
229 {
230 char buf[BUFSZ];
231 VA_START(s);
232 VA_INIT(s, const char *);
233 /* error() may get called before tty is initialized */
234 if (iflags.window_inited)
235 end_screen();
236 if (WINDOWPORT("tty")) {
237 buf[0] = '\n';
238 (void) vsnprintf(&buf[1], sizeof buf - (1 + sizeof "\n"), s, VA_ARGS);
239 Strcat(buf, "\n");
240 msmsg(buf);
241 } else {
242 (void) vsnprintf(buf, sizeof buf - sizeof "\n", s, VA_ARGS);
243 Strcat(buf, "\n");
244 raw_printf(buf);
245 }
246 if (windowprocs.win_raw_print == mswin_raw_print)
247 mswin_raw_print_flush();
248 VA_END();
249 exit(EXIT_FAILURE);
250 }
251
252 void
Delay(int ms)253 Delay(int ms)
254 {
255 (void) Sleep(ms);
256 }
257
258 void
win32_abort(void)259 win32_abort(void)
260 {
261 int c;
262
263 if (WINDOWPORT("mswin") || WINDOWPORT("tty")) {
264 if (iflags.window_inited)
265 exit_nhwindows((char *) 0);
266 iflags.window_inited = FALSE;
267 }
268 if (!WINDOWPORT("mswin") && !WINDOWPORT("safe-startup"))
269 safe_routines();
270 if (wizard) {
271 raw_print("Execute debug breakpoint wizard?");
272 if ((c = nhgetch()) == 'y' || c == 'Y')
273 DebugBreak();
274 }
275 abort();
276 }
277
278 static char interjection_buf[INTERJECTION_TYPES][1024];
279 static int interjection[INTERJECTION_TYPES];
280
281 void
interject_assistance(int num,int interjection_type,genericptr_t ptr1,genericptr_t ptr2)282 interject_assistance(int num, int interjection_type, genericptr_t ptr1, genericptr_t ptr2)
283 {
284 switch (num) {
285 case 1: {
286 char *panicmsg = (char *) ptr1;
287 char *datadir = (char *) ptr2;
288 char *tempdir = nh_getenv("TEMP");
289 interjection_type = INTERJECT_PANIC;
290 interjection[INTERJECT_PANIC] = 1;
291 /*
292 * ptr1 = the panic message about to be delivered.
293 * ptr2 = the directory prefix of the dungeon file
294 * that failed to open.
295 * Check to see if datadir matches tempdir or a
296 * common windows temp location. If it does, inform
297 * the user that they are probably trying to run the
298 * game from within their unzip utility, so the required
299 * files really don't exist at the location. Instruct
300 * them to unpack them first.
301 */
302 if (panicmsg && datadir) {
303 if (!strncmpi(datadir, "C:\\WINDOWS\\TEMP", 15)
304 || strstri(datadir, "TEMP")
305 || (tempdir && strstri(datadir, tempdir))) {
306 (void) strncpy(
307 interjection_buf[INTERJECT_PANIC],
308 "\nOne common cause of this error is attempting to "
309 "execute\n"
310 "the game by double-clicking on it while it is "
311 "displayed\n"
312 "inside an unzip utility.\n\n"
313 "You have to unzip the contents of the zip file into a\n"
314 "folder on your system, and then run \"NetHack.exe\" or "
315 "\n"
316 "\"xNetHackW.exe\" from there.\n\n"
317 "If that is not the situation, you are encouraged to\n"
318 "report the error as shown above.\n\n",
319 1023);
320 }
321 }
322 } break;
323 }
324 }
325
326 void
interject(int interjection_type)327 interject(int interjection_type)
328 {
329 if (interjection_type >= 0 && interjection_type < INTERJECTION_TYPES)
330 msmsg(interjection_buf[interjection_type]);
331 }
332
333 #ifdef RUNTIME_PASTEBUF_SUPPORT
334
port_insert_pastebuf(char * buf)335 void port_insert_pastebuf(char *buf)
336 {
337 /* This implementation will utilize the windows clipboard
338 * to accomplish this.
339 */
340
341 HGLOBAL hglbCopy;
342 WCHAR *w, w2[2];
343 int cc, rc, abytes;
344 LPWSTR lpwstrCopy;
345 HANDLE hresult;
346
347 if (!buf)
348 return;
349
350 cc = strlen(buf);
351 /* last arg=0 means "tell me the size of the buffer that I need" */
352 rc = MultiByteToWideChar(GetConsoleOutputCP(), 0, buf, -1, w2, 0);
353 if (!rc) return;
354
355 abytes = rc * sizeof(WCHAR);
356 w = (WCHAR *)alloc(abytes);
357 /* Housekeeping need: +free(w) */
358
359 rc = MultiByteToWideChar(GetConsoleOutputCP(), 0, buf, -1, w, rc);
360 if (!rc) {
361 free(w);
362 return;
363 }
364 if (!OpenClipboard(NULL)) {
365 free(w);
366 return;
367 }
368 /* Housekeeping need: +CloseClipboard(), free(w) */
369
370 EmptyClipboard();
371
372 /* allocate global mem obj to hold the text */
373
374 hglbCopy = GlobalAlloc(GMEM_MOVEABLE, abytes);
375 if (hglbCopy == NULL) {
376 CloseClipboard();
377 free(w);
378 return;
379 }
380 /* Housekeeping need: +GlobalFree(hglbCopy), CloseClipboard(), free(w) */
381
382 lpwstrCopy = (LPWSTR)GlobalLock(hglbCopy);
383 /* Housekeeping need: +GlobalUnlock(hglbCopy), GlobalFree(hglbCopy),
384 CloseClipboard(), free(w) */
385
386 memcpy(lpwstrCopy, w, abytes);
387 GlobalUnlock(hglbCopy);
388 /* Housekeeping need: GlobalFree(hglbCopy), CloseClipboard(), free(w) */
389
390 /* put it on the clipboard */
391 hresult = SetClipboardData(CF_UNICODETEXT, hglbCopy);
392 if (!hresult) {
393 raw_printf("Error copying to clipboard.\n");
394 GlobalFree(hglbCopy); /* only needed if clipboard didn't accept data */
395 }
396 /* Housekeeping need: CloseClipboard(), free(w) */
397
398 CloseClipboard();
399 free(w);
400 return;
401 }
402
403 static HWND
GetConsoleHandle(void)404 GetConsoleHandle(void)
405 {
406 HMODULE hMod = GetModuleHandle("kernel32.dll");
407 GETCONSOLEWINDOW pfnGetConsoleWindow =
408 (GETCONSOLEWINDOW) GetProcAddress(hMod, "GetConsoleWindow");
409 if (pfnGetConsoleWindow)
410 return pfnGetConsoleWindow();
411 else
412 return GetConsoleHwnd();
413 }
414
415 static HWND
GetConsoleHwnd(void)416 GetConsoleHwnd(void)
417 {
418 int iterations = 0;
419 HWND hwndFound = 0;
420 char OldTitle[1024], NewTitle[1024], TestTitle[1024];
421
422 /* Get current window title */
423 GetConsoleTitle(OldTitle, sizeof OldTitle);
424
425 (void) sprintf(NewTitle, "NETHACK%ld/%ld", GetTickCount(),
426 GetCurrentProcessId());
427 SetConsoleTitle(NewTitle);
428
429 GetConsoleTitle(TestTitle, sizeof TestTitle);
430 while (strcmp(TestTitle, NewTitle) != 0) {
431 iterations++;
432 /* sleep(0); */
433 GetConsoleTitle(TestTitle, sizeof TestTitle);
434 }
435 hwndFound = FindWindow(NULL, NewTitle);
436 SetConsoleTitle(OldTitle);
437 /* printf("%d iterations\n", iterations); */
438 return hwndFound;
439 }
440
441 #endif
442
443 #ifdef RUNTIME_PORT_ID
444 /*
445 * _M_IX86 is Defined for x86 processors. This is not defined for x64
446 * processors.
447 * _M_X64 is Defined for x64 processors.
448 * _M_IA64 is Defined for Itanium Processor Family 64-bit processors.
449 * _WIN64 is Defined for applications for Win64.
450 */
451 #ifndef _M_IX86
452 #ifdef _M_X64
453 #define TARGET_PORT "x64"
454 #endif
455 #ifdef _M_IA64
456 #define TARGET_PORT "IA64"
457 #endif
458 #endif
459
460 #ifndef TARGET_PORT
461 #define TARGET_PORT "x86"
462 #endif
463
464 char *
get_port_id(char * buf)465 get_port_id(char *buf)
466 {
467 Strcpy(buf, TARGET_PORT);
468 return buf;
469 }
470 #endif /* RUNTIME_PORT_ID */
471
472 void
nethack_exit(int code)473 nethack_exit(int code)
474 {
475 /* Only if we started from the GUI, not the command prompt,
476 * we need to get one last return, so the score board does
477 * not vanish instantly after being created.
478 * GUILaunched is defined and set in nttty.c.
479 */
480
481
482 if (!GUILaunched) {
483 windowprocs = *get_safe_procs(1);
484 /* use our custom version which works
485 a little cleaner than the stdio one */
486 windowprocs.win_nhgetch = windows_console_custom_nhgetch;
487 }
488 if (getreturn_enabled) {
489 raw_print("\n");
490 wait_synch();
491 }
492 exit(code);
493 }
494
495 #undef kbhit
496 #include <conio.h>
497
498 int
windows_console_custom_nhgetch(void)499 windows_console_custom_nhgetch(void)
500 {
501 return _getch();
502 }
503
504
505 void
getreturn(const char * str)506 getreturn(const char *str)
507 {
508 static boolean in_getreturn = FALSE;
509 char buf[BUFSZ];
510
511 if (in_getreturn || !getreturn_enabled)
512 return;
513 in_getreturn = TRUE;
514 Sprintf(buf,"Hit <Enter> %s.", str);
515 raw_print(buf);
516 wait_synch();
517 in_getreturn = FALSE;
518 return;
519 }
520
521 /* nethack_enter_winnt() is called from main immediately after
522 initializing the window port */
nethack_enter_winnt(void)523 void nethack_enter_winnt(void)
524 {
525 if (WINDOWPORT("tty"))
526 nethack_enter_nttty();
527 }
528
529 /* CP437 to Unicode mapping according to the Unicode Consortium */
530 const WCHAR cp437[256] = {
531 0x0020, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
532 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
533 0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8,
534 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC,
535 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
536 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
537 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
538 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
539 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
540 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
541 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
542 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
543 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
544 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
545 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
546 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
547 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
548 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
549 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
550 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
551 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
552 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
553 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
554 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
555 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
556 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
557 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
558 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
559 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
560 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
561 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
562 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
563 };
564
565 WCHAR *
winos_ascii_to_wide_str(const unsigned char * src,WCHAR * dst,size_t dstLength)566 winos_ascii_to_wide_str(const unsigned char * src, WCHAR * dst, size_t dstLength)
567 {
568 size_t i = 0;
569 while(i < dstLength - 1 && src[i] != 0)
570 dst[i++] = cp437[src[i]];
571 dst[i] = 0;
572 return dst;
573 }
574
575 WCHAR
winos_ascii_to_wide(const unsigned char c)576 winos_ascii_to_wide(const unsigned char c)
577 {
578 return cp437[c];
579 }
580
winos_font_support_cp437(HFONT hFont)581 BOOL winos_font_support_cp437(HFONT hFont)
582 {
583 BOOL allFound = FALSE;
584 HDC hdc = GetDC(NULL);
585 HFONT oldFont = SelectObject(hdc, hFont);
586
587 DWORD size = GetFontUnicodeRanges(hdc, NULL);
588 GLYPHSET *glyphSet = (GLYPHSET *) malloc(size);
589
590 if (glyphSet != NULL) {
591 GetFontUnicodeRanges(hdc, glyphSet);
592
593 allFound = TRUE;
594 for (int i = 0; i < 256 && allFound; i++) {
595 WCHAR wc = cp437[i];
596 BOOL found = FALSE;
597 for (DWORD j = 0; j < glyphSet->cRanges && !found; j++) {
598 WCHAR first = glyphSet->ranges[j].wcLow;
599 WCHAR last = first + glyphSet->ranges[j].cGlyphs - 1;
600
601 if (wc >= first && wc <= last)
602 found = TRUE;
603 }
604 if (!found)
605 allFound = FALSE;
606 }
607
608 free(glyphSet);
609 }
610
611 SelectObject(hdc, oldFont);
612 ReleaseDC(NULL, hdc);
613
614 return allFound;
615 }
616
617 int
windows_early_options(const char * window_opt)618 windows_early_options(const char *window_opt)
619 {
620 /*
621 * If you return 2, the game will exit before it begins.
622 * Return 1, to say the option parsed okay.
623 * Return 0, to say the option was bad.
624 */
625
626 if (match_optname(window_opt, "cursorblink", 5, FALSE)) {
627 win32_cursorblink = TRUE;
628 return 1;
629 } else {
630 raw_printf(
631 "-%swindows:cursorblink is the only supported option.\n");
632 }
633 return 0;
634 }
635
636 /*
637 * Add a backslash to any name not ending in /, \ or : There must
638 * be room for the \
639 */
640 void
append_slash(char * name)641 append_slash(char *name)
642 {
643 char *ptr;
644
645 if (!*name)
646 return;
647 ptr = name + (strlen(name) - 1);
648 if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
649 *++ptr = '\\';
650 *++ptr = '\0';
651 }
652 return;
653 }
654
655 #include <bcrypt.h> /* Windows Crypto Next Gen (CNG) */
656
657 #ifndef STATUS_SUCCESS
658 #define STATUS_SUCCESS 0
659 #endif
660 #ifndef STATUS_NOT_FOUND
661 #define STATUS_NOT_FOUND 0xC0000225
662 #endif
663 #ifndef STATUS_UNSUCCESSFUL
664 #define STATUS_UNSUCCESSFUL 0xC0000001
665 #endif
666
667 unsigned long
sys_random_seed(void)668 sys_random_seed(void)
669 {
670 unsigned long ourseed = 0UL;
671 BCRYPT_ALG_HANDLE hRa = (BCRYPT_ALG_HANDLE) 0;
672 NTSTATUS status = STATUS_UNSUCCESSFUL;
673 boolean Plan_B = TRUE;
674
675 status = BCryptOpenAlgorithmProvider(&hRa, BCRYPT_RNG_ALGORITHM,
676 (LPCWSTR) 0, 0);
677 if (hRa && status == STATUS_SUCCESS) {
678 status = BCryptGenRandom(hRa, (PUCHAR) &ourseed,
679 (ULONG) sizeof ourseed, 0);
680 if (status == STATUS_SUCCESS) {
681 BCryptCloseAlgorithmProvider(hRa,0);
682 has_strong_rngseed = TRUE;
683 Plan_B = FALSE;
684 }
685 }
686
687 if (Plan_B) {
688 time_t datetime = 0;
689 const char *emsg;
690
691 if (status == STATUS_NOT_FOUND)
692 emsg = "BCRYPT_RNG_ALGORITHM not avail, falling back";
693 else
694 emsg = "Other failure than algorithm not avail";
695 paniclog("sys_random_seed", emsg); /* leaves clue, doesn't exit */
696 (void) time(&datetime);
697 ourseed = (unsigned long) datetime;
698 }
699 return ourseed;
700 }
701
702 /* nt_assert_failed is called when an nhassert's condition is false */
703 void
nt_assert_failed(const char * expression,const char * filepath,int line)704 nt_assert_failed(const char *expression, const char *filepath, int line)
705 {
706 const char * filename;
707
708 filename = strrchr(filepath, '\\');
709 filename = (filename == NULL ? filepath : filename + 1);
710
711 if (IsDebuggerPresent()) {
712 char message[BUFSIZ];
713 snprintf(message, sizeof(message),
714 "nhassert(%s) failed in file '%s' at line %d",
715 expression, filename, line);
716 OutputDebugStringA(message);
717 DebugBreak();
718 }
719
720 /* get file name from path */
721 impossible("nhassert(%s) failed in file '%s' at line %d",
722 expression, filename, line);
723 }
724
725 #endif /* WIN32 */
726
727 /*winnt.c*/
728