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