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