comparison src/ntproc.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children ed498ef2108b
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
22 Adapted from alarm.c by Tim Fleehart */ 22 Adapted from alarm.c by Tim Fleehart */
23 23
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ 24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */
25 /* Synced with FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ 25 /* Synced with FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */
26 26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <io.h>
31 #include <fcntl.h>
32 #include <signal.h>
33
34 /* must include CRT headers *before* config.h */
35 /* #### I don't believe it - martin */
36 #include <config.h> 27 #include <config.h>
37 #undef signal 28 #undef signal
38 #undef wait 29 #undef wait
39 #undef spawnve 30 #undef spawnve
40 #undef select 31 #undef select
41 #undef kill 32 #undef kill
42 33
43 #include <windows.h> 34 #include <windows.h>
44 #include <sys/socket.h>
45 #ifdef HAVE_A_OUT_H 35 #ifdef HAVE_A_OUT_H
46 #include <a.out.h> 36 #include <a.out.h>
47 #endif 37 #endif
48 #include "lisp.h" 38 #include "lisp.h"
49 #include "sysproc.h" 39 #include "sysproc.h"
53 #include "syssignal.h" 43 #include "syssignal.h"
54 #include "sysfile.h" 44 #include "sysfile.h"
55 #include "syswait.h" 45 #include "syswait.h"
56 #include "buffer.h" 46 #include "buffer.h"
57 #include "process.h" 47 #include "process.h"
48
49 #include "console-msw.h"
50
58 /*#include "w32term.h"*/ /* From 19.34.6: sync in ? --marcpa */ 51 /*#include "w32term.h"*/ /* From 19.34.6: sync in ? --marcpa */
59 52
60 /* #### I'm not going to play with shit. */ 53 /* #### I'm not going to play with shit. */
61 #pragma warning (disable:4013 4024 4090) 54 #pragma warning (disable:4013 4024 4090)
62 55
80 avoids the inefficiency of frequently reading small amounts of data. 73 avoids the inefficiency of frequently reading small amounts of data.
81 This is primarily necessary for handling DOS processes on Windows 95, 74 This is primarily necessary for handling DOS processes on Windows 95,
82 but is useful for Win32 processes on both Win95 and NT as well. */ 75 but is useful for Win32 processes on both Win95 and NT as well. */
83 Lisp_Object Vwin32_pipe_read_delay; 76 Lisp_Object Vwin32_pipe_read_delay;
84 77
85 /* Control whether stat() attempts to generate fake but hopefully 78 /* Control whether xemacs_stat() attempts to generate fake but hopefully
86 "accurate" inode values, by hashing the absolute truenames of files. 79 "accurate" inode values, by hashing the absolute truenames of files.
87 This should detect aliasing between long and short names, but still 80 This should detect aliasing between long and short names, but still
88 allows the possibility of hash collisions. */ 81 allows the possibility of hash collisions. */
89 Lisp_Object Vwin32_generate_fake_inodes; 82 Lisp_Object Vwin32_generate_fake_inodes;
90 83
106 va_end (args); 99 va_end (args);
107 OutputDebugString (buf); 100 OutputDebugString (buf);
108 #endif 101 #endif
109 } 102 }
110 103
111 /* sys_signal moved to nt.c. It's now called msw_signal... */ 104 /* sys_signal moved to nt.c. It's now called mswindows_signal... */
112 105
113 /* Defined in <process.h> which conflicts with the local copy */ 106 /* Defined in <process.h> which conflicts with the local copy */
114 #define _P_NOWAIT 1 107 #define _P_NOWAIT 1
115 108
116 /* Child process management list. */ 109 /* Child process management list. */
117 int child_proc_count = 0; 110 int child_proc_count = 0;
118 child_process child_procs[ MAX_CHILDREN ]; 111 child_process child_procs[ MAX_CHILDREN ];
119 child_process *dead_child = NULL; 112 child_process *dead_child = NULL;
120 113
121 DWORD WINAPI reader_thread (void *arg); 114 DWORD WINAPI reader_thread (void *arg);
122
123 /* Determine if running on Windows 9x and not NT */
124 static int
125 windows9x_p (void)
126 {
127 return GetVersion () & 0x80000000;
128 }
129 115
130 /* Find an unused process slot. */ 116 /* Find an unused process slot. */
131 child_process * 117 child_process *
132 new_child (void) 118 new_child (void)
133 { 119 {
398 the new process should start in. This is set just before calling 384 the new process should start in. This is set just before calling
399 sys_spawnve, and is not generally valid at any other time. */ 385 sys_spawnve, and is not generally valid at any other time. */
400 static const char * process_dir; 386 static const char * process_dir;
401 387
402 static BOOL 388 static BOOL
403 create_child (CONST char *exe, char *cmdline, char *env, 389 create_child (const char *exe, char *cmdline, char *env,
404 int * pPid, child_process *cp) 390 int * pPid, child_process *cp)
405 { 391 {
406 STARTUPINFO start; 392 STARTUPINFO start;
407 SECURITY_ATTRIBUTES sec_attrs; 393 SECURITY_ATTRIBUTES sec_attrs;
408 SECURITY_DESCRIPTOR sec_desc; 394 SECURITY_DESCRIPTOR sec_desc;
411 if (cp == NULL) abort (); 397 if (cp == NULL) abort ();
412 398
413 xzero (start); 399 xzero (start);
414 start.cb = sizeof (start); 400 start.cb = sizeof (start);
415 401
416 #ifdef HAVE_NTGUI
417 if (NILP (Vwin32_start_process_show_window)) 402 if (NILP (Vwin32_start_process_show_window))
418 start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; 403 start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
419 else 404 else
420 start.dwFlags = STARTF_USESTDHANDLES; 405 start.dwFlags = STARTF_USESTDHANDLES;
421 start.wShowWindow = SW_HIDE; 406 start.wShowWindow = SW_HIDE;
422 407
423 start.hStdInput = GetStdHandle (STD_INPUT_HANDLE); 408 start.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
424 start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); 409 start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
425 start.hStdError = GetStdHandle (STD_ERROR_HANDLE); 410 start.hStdError = GetStdHandle (STD_ERROR_HANDLE);
426 #endif /* HAVE_NTGUI */
427 411
428 /* Explicitly specify no security */ 412 /* Explicitly specify no security */
413 /* #### not supported under win98, but will go away */
429 if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION)) 414 if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION))
430 goto EH_Fail; 415 goto EH_Fail;
416 /* #### not supported under win98, but will go away */
431 if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE)) 417 if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE))
432 goto EH_Fail; 418 goto EH_Fail;
433 sec_attrs.nLength = sizeof (sec_attrs); 419 sec_attrs.nLength = sizeof (sec_attrs);
434 sec_attrs.lpSecurityDescriptor = &sec_desc; 420 sec_attrs.lpSecurityDescriptor = &sec_desc;
435 sec_attrs.bInheritHandle = FALSE; 421 sec_attrs.bInheritHandle = FALSE;
462 EH_Fail: 448 EH_Fail:
463 DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError());); 449 DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError()););
464 return FALSE; 450 return FALSE;
465 } 451 }
466 452
467 #ifndef __MINGW32__
468 /* Return pointer to section header for section containing the given
469 relative virtual address. */
470 static IMAGE_SECTION_HEADER *
471 rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header)
472 {
473 PIMAGE_SECTION_HEADER section;
474 int i;
475
476 section = IMAGE_FIRST_SECTION (nt_header);
477
478 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
479 {
480 if (rva >= section->VirtualAddress
481 && rva < section->VirtualAddress + section->SizeOfRawData)
482 return section;
483 section++;
484 }
485 return NULL;
486 }
487 #endif
488
489 void
490 win32_executable_type (CONST char * filename, int * is_dos_app, int * is_cygnus_app)
491 {
492 file_data executable;
493 char * p;
494
495 /* Default values in case we can't tell for sure. */
496 *is_dos_app = FALSE;
497 *is_cygnus_app = FALSE;
498
499 if (!open_input_file (&executable, filename))
500 return;
501
502 p = strrchr (filename, '.');
503
504 /* We can only identify DOS .com programs from the extension. */
505 if (p && stricmp (p, ".com") == 0)
506 *is_dos_app = TRUE;
507 else if (p && (stricmp (p, ".bat") == 0 ||
508 stricmp (p, ".cmd") == 0))
509 {
510 /* A DOS shell script - it appears that CreateProcess is happy to
511 accept this (somewhat surprisingly); presumably it looks at
512 COMSPEC to determine what executable to actually invoke.
513 Therefore, we have to do the same here as well. */
514 /* Actually, I think it uses the program association for that
515 extension, which is defined in the registry. */
516 p = egetenv ("COMSPEC");
517 if (p)
518 win32_executable_type (p, is_dos_app, is_cygnus_app);
519 }
520 else
521 {
522 /* Look for DOS .exe signature - if found, we must also check that
523 it isn't really a 16- or 32-bit Windows exe, since both formats
524 start with a DOS program stub. Note that 16-bit Windows
525 executables use the OS/2 1.x format. */
526
527 #ifdef __MINGW32__
528 /* mingw32 doesn't have enough headers to detect cygwin
529 apps, just do what we can. */
530 FILHDR * exe_header;
531
532 exe_header = (FILHDR*) executable.file_base;
533 if (exe_header->e_magic != DOSMAGIC)
534 goto unwind;
535
536 if ((char *) exe_header->e_lfanew > (char *) executable.size)
537 {
538 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */
539 *is_dos_app = TRUE;
540 }
541 else if (exe_header->nt_signature != NT_SIGNATURE)
542 {
543 *is_dos_app = TRUE;
544 }
545 #else
546 IMAGE_DOS_HEADER * dos_header;
547 IMAGE_NT_HEADERS * nt_header;
548
549 dos_header = (PIMAGE_DOS_HEADER) executable.file_base;
550 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
551 goto unwind;
552
553 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
554
555 if ((char *) nt_header > (char *) dos_header + executable.size)
556 {
557 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */
558 *is_dos_app = TRUE;
559 }
560 else if (nt_header->Signature != IMAGE_NT_SIGNATURE &&
561 LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
562 {
563 *is_dos_app = TRUE;
564 }
565 else if (nt_header->Signature == IMAGE_NT_SIGNATURE)
566 {
567 /* Look for cygwin.dll in DLL import list. */
568 IMAGE_DATA_DIRECTORY import_dir =
569 nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
570 IMAGE_IMPORT_DESCRIPTOR * imports;
571 IMAGE_SECTION_HEADER * section;
572
573 section = rva_to_section (import_dir.VirtualAddress, nt_header);
574 imports = RVA_TO_PTR (import_dir.VirtualAddress, section, executable);
575
576 for ( ; imports->Name; imports++)
577 {
578 char * dllname = RVA_TO_PTR (imports->Name, section, executable);
579
580 if (strcmp (dllname, "cygwin.dll") == 0)
581 {
582 *is_cygnus_app = TRUE;
583 break;
584 }
585 }
586 }
587 #endif
588 }
589
590 unwind:
591 close_file_data (&executable);
592 }
593
594 int
595 compare_env (const void *strp1, const void *strp2)
596 {
597 const char *str1 = *(const char**)strp1, *str2 = *(const char**)strp2;
598
599 while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
600 {
601 if ((*str1) > (*str2))
602 return 1;
603 else if ((*str1) < (*str2))
604 return -1;
605 str1++, str2++;
606 }
607
608 if (*str1 == '=' && *str2 == '=')
609 return 0;
610 else if (*str1 == '=')
611 return -1;
612 else
613 return 1;
614 }
615
616 void 453 void
617 merge_and_sort_env (char **envp1, char **envp2, char **new_envp) 454 merge_and_sort_env (char **envp1, char **envp2, char **new_envp)
618 { 455 {
619 char **optr, **nptr; 456 char **optr, **nptr;
620 int num; 457 int num;
628 optr = envp2; 465 optr = envp2;
629 while (*optr) 466 while (*optr)
630 *nptr++ = *optr++; 467 *nptr++ = *optr++;
631 num += optr - envp2; 468 num += optr - envp2;
632 469
633 qsort (new_envp, num, sizeof (char *), compare_env); 470 qsort (new_envp, num, sizeof (char*), compare_env);
634 471
635 *nptr = NULL; 472 *nptr = NULL;
636 } 473 }
637 474
638 /* When a new child process is created we need to register it in our list, 475 /* When a new child process is created we need to register it in our list,
639 so intercept spawn requests. */ 476 so intercept spawn requests. */
640 int 477 int
641 sys_spawnve (int mode, CONST char *cmdname, 478 sys_spawnve (int mode, const char *cmdname,
642 CONST char * CONST *argv, CONST char *CONST *envp) 479 const char * const *argv, const char *const *envp)
643 { 480 {
644 Lisp_Object program, full; 481 Lisp_Object program, full;
645 char *cmdline, *env, *parg, **targ; 482 char *cmdline, *env, *parg, **targ;
646 int arglen, numenv; 483 int arglen, numenv;
647 int pid; 484 int pid;
661 errno = EINVAL; 498 errno = EINVAL;
662 return -1; 499 return -1;
663 } 500 }
664 501
665 /* Handle executable names without an executable suffix. */ 502 /* Handle executable names without an executable suffix. */
666 program = make_string (cmdname, strlen (cmdname)); 503 program = build_string (cmdname);
667 GCPRO1 (program); 504 GCPRO1 (program);
668 if (NILP (Ffile_executable_p (program))) 505 if (NILP (Ffile_executable_p (program)))
669 { 506 {
670 full = Qnil; 507 full = Qnil;
671 locate_file (Vexec_path, program, Vlisp_EXEC_SUFFIXES, &full, 1); 508 locate_file (Vexec_path, program, Vlisp_EXEC_SUFFIXES, &full, 1);
679 C_STRING_ALLOCA, cmdname, 516 C_STRING_ALLOCA, cmdname,
680 Qfile_name); 517 Qfile_name);
681 } 518 }
682 else 519 else
683 { 520 {
684 (char*)cmdname = alloca (strlen (argv[0]) + 1); 521 cmdname = (char*)alloca (strlen (argv[0]) + 1);
685 strcpy ((char*)cmdname, argv[0]); 522 strcpy ((char*)cmdname, argv[0]);
686 } 523 }
687 UNGCPRO; 524 UNGCPRO;
688 525
689 /* make sure argv[0] and cmdname are both in DOS format */ 526 /* make sure argv[0] and cmdname are both in DOS format */
690 unixtodos_filename ((char*)cmdname); 527 unixtodos_filename ((char*)cmdname);
691 /* #### KLUDGE */ 528 /* #### KLUDGE */
692 ((CONST char**)argv)[0] = cmdname; 529 ((const char**)argv)[0] = cmdname;
693 530
694 /* Determine whether program is a 16-bit DOS executable, or a Win32 531 /* Determine whether program is a 16-bit DOS executable, or a Win32
695 executable that is implicitly linked to the Cygnus dll (implying it 532 executable that is implicitly linked to the Cygnus dll (implying it
696 was compiled with the Cygnus GNU toolchain and hence relies on 533 was compiled with the Cygnus GNU toolchain and hence relies on
697 cygwin.dll to parse the command line - we use this to decide how to 534 cygwin.dll to parse the command line - we use this to decide how to
698 escape quote chars in command line args that must be quoted). */ 535 escape quote chars in command line args that must be quoted). */
699 win32_executable_type (cmdname, &is_dos_app, &is_cygnus_app); 536 mswindows_executable_type (cmdname, &is_dos_app, &is_cygnus_app);
700 537
701 /* On Windows 95, if cmdname is a DOS app, we invoke a helper 538 /* On Windows 95, if cmdname is a DOS app, we invoke a helper
702 application to start it by specifying the helper app as cmdname, 539 application to start it by specifying the helper app as cmdname,
703 while leaving the real app name as argv[0]. */ 540 while leaving the real app name as argv[0]. */
704 if (is_dos_app) 541 if (is_dos_app)
705 { 542 {
706 cmdname = alloca (MAXPATHLEN); 543 cmdname = (char*) alloca (MAXPATHLEN);
707 if (egetenv ("CMDPROXY")) 544 if (egetenv ("CMDPROXY"))
708 strcpy ((char*)cmdname, egetenv ("CMDPROXY")); 545 strcpy ((char*)cmdname, egetenv ("CMDPROXY"));
709 else 546 else
710 { 547 {
711 strcpy ((char*)cmdname, XSTRING_DATA (Vinvocation_directory)); 548 strcpy ((char*)cmdname, XSTRING_DATA (Vinvocation_directory));
748 { 585 {
749 do_quoting = 1; 586 do_quoting = 1;
750 /* Override escape char by binding win32-quote-process-args to 587 /* Override escape char by binding win32-quote-process-args to
751 desired character, or use t for auto-selection. */ 588 desired character, or use t for auto-selection. */
752 if (INTP (Vwin32_quote_process_args)) 589 if (INTP (Vwin32_quote_process_args))
753 escape_char = XINT (Vwin32_quote_process_args); 590 escape_char = (char) XINT (Vwin32_quote_process_args);
754 else 591 else
755 escape_char = is_cygnus_app ? '"' : '\\'; 592 escape_char = is_cygnus_app ? '"' : '\\';
756 } 593 }
757 594
758 /* do argv... */ 595 /* do argv... */
800 if (escape_char_run > 0) 637 if (escape_char_run > 0)
801 arglen += escape_char_run; 638 arglen += escape_char_run;
802 } 639 }
803 arglen += strlen (*targ++) + 1; 640 arglen += strlen (*targ++) + 1;
804 } 641 }
805 cmdline = alloca (arglen); 642 cmdline = (char*) alloca (arglen);
806 targ = (char**)argv; 643 targ = (char**)argv;
807 parg = cmdline; 644 parg = cmdline;
808 while (*targ) 645 while (*targ)
809 { 646 {
810 char * p = *targ; 647 char * p = *targ;
882 } 719 }
883 *--parg = '\0'; 720 *--parg = '\0';
884 721
885 /* and envp... */ 722 /* and envp... */
886 arglen = 1; 723 arglen = 1;
887 targ = (char**)envp; 724 targ = (char**) envp;
888 numenv = 1; /* for end null */ 725 numenv = 1; /* for end null */
889 while (*targ) 726 while (*targ)
890 { 727 {
891 arglen += strlen (*targ++) + 1; 728 arglen += strlen (*targ++) + 1;
892 numenv++; 729 numenv++;
896 GetCurrentProcessId ()); 733 GetCurrentProcessId ());
897 arglen += strlen (ppid_env_var_buffer) + 1; 734 arglen += strlen (ppid_env_var_buffer) + 1;
898 numenv++; 735 numenv++;
899 736
900 /* merge env passed in and extra env into one, and sort it. */ 737 /* merge env passed in and extra env into one, and sort it. */
901 targ = (char **) alloca (numenv * sizeof (char *)); 738 targ = (char **) alloca (numenv * sizeof (char*));
902 merge_and_sort_env ((char**)envp, extra_env, targ); 739 merge_and_sort_env ((char**) envp, extra_env, targ);
903 740
904 /* concatenate env entries. */ 741 /* concatenate env entries. */
905 env = alloca (arglen); 742 env = (char*) alloca (arglen);
906 parg = env; 743 parg = env;
907 while (*targ) 744 while (*targ)
908 { 745 {
909 strcpy (parg, *targ); 746 strcpy (parg, *targ);
910 parg += strlen (*targ++); 747 parg += strlen (*targ++);
944 { 781 {
945 char window_class[32]; 782 char window_class[32];
946 783
947 GetClassName (hwnd, window_class, sizeof (window_class)); 784 GetClassName (hwnd, window_class, sizeof (window_class));
948 if (strcmp (window_class, 785 if (strcmp (window_class,
949 windows9x_p() 786 mswindows_windows9x_p()
950 ? "tty" 787 ? "tty"
951 : "ConsoleWindowClass") == 0) 788 : "ConsoleWindowClass") == 0)
952 { 789 {
953 cp->hwnd = hwnd; 790 cp->hwnd = hwnd;
954 return FALSE; 791 return FALSE;
1037 else 874 else
1038 { 875 {
1039 if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd) 876 if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd)
1040 { 877 {
1041 #if 1 878 #if 1
1042 if (windows9x_p()) 879 if (mswindows_windows9x_p())
1043 { 880 {
1044 /* 881 /*
1045 Another possibility is to try terminating the VDM out-right by 882 Another possibility is to try terminating the VDM out-right by
1046 calling the Shell VxD (id 0x17) V86 interface, function #4 883 calling the Shell VxD (id 0x17) V86 interface, function #4
1047 "SHELL_Destroy_VM", ie. 884 "SHELL_Destroy_VM", ie.
1098 return rc; 935 return rc;
1099 } 936 }
1100 937
1101 #if 0 938 #if 0
1102 /* Sync with FSF Emacs 19.34.6 note: ifdef'ed out in XEmacs */ 939 /* Sync with FSF Emacs 19.34.6 note: ifdef'ed out in XEmacs */
1103 extern int report_file_error (CONST char *, Lisp_Object); 940 extern int report_file_error (const char *, Lisp_Object);
1104 #endif 941 #endif
1105 /* The following two routines are used to manipulate stdin, stdout, and 942 /* The following two routines are used to manipulate stdin, stdout, and
1106 stderr of our child processes. 943 stderr of our child processes.
1107 944
1108 Assuming that in, out, and err are *not* inheritable, we make them 945 Assuming that in, out, and err are *not* inheritable, we make them
1191 } 1028 }
1192 1029
1193 /* Some miscellaneous functions that are Windows specific, but not GUI 1030 /* Some miscellaneous functions that are Windows specific, but not GUI
1194 specific (ie. are applicable in terminal or batch mode as well). */ 1031 specific (ie. are applicable in terminal or batch mode as well). */
1195 1032
1196 /* lifted from fileio.c */
1197 #define CORRECT_DIR_SEPS(s) \
1198 do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
1199 else unixtodos_filename (s); \
1200 } while (0)
1201
1202 DEFUN ("win32-short-file-name", Fwin32_short_file_name, 1, 1, "", /* 1033 DEFUN ("win32-short-file-name", Fwin32_short_file_name, 1, 1, "", /*
1203 Return the short file name version (8.3) of the full path of FILENAME. 1034 Return the short file name version (8.3) of the full path of FILENAME.
1204 If FILENAME does not exist, return nil. 1035 If FILENAME does not exist, return nil.
1205 All path elements in FILENAME are converted to their short names. 1036 All path elements in FILENAME are converted to their short names.
1206 */ 1037 */
1421 CHECK_INT (lcid); 1252 CHECK_INT (lcid);
1422 1253
1423 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED)) 1254 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED))
1424 return Qnil; 1255 return Qnil;
1425 1256
1257 /* #### not supported under win98, but will go away */
1426 if (!SetThreadLocale (XINT (lcid))) 1258 if (!SetThreadLocale (XINT (lcid)))
1427 return Qnil; 1259 return Qnil;
1428 1260
1429 /* Sync with FSF Emacs 19.34.6 note: dwWinThreadId declared in 1261 /* Sync with FSF Emacs 19.34.6 note: dwWinThreadId declared in
1430 w32term.h and defined in w32fns.c, both of which are not in current 1262 w32term.h and defined in w32fns.c, both of which are not in current
1439 return make_int (GetThreadLocale ()); 1271 return make_int (GetThreadLocale ());
1440 } 1272 }
1441 1273
1442 1274
1443 void 1275 void
1444 syms_of_ntproc () 1276 syms_of_ntproc (void)
1445 { 1277 {
1446 DEFSUBR (Fwin32_short_file_name); 1278 DEFSUBR (Fwin32_short_file_name);
1447 DEFSUBR (Fwin32_long_file_name); 1279 DEFSUBR (Fwin32_long_file_name);
1448 DEFSUBR (Fwin32_set_process_priority); 1280 DEFSUBR (Fwin32_set_process_priority);
1449 DEFSUBR (Fwin32_get_locale_info); 1281 DEFSUBR (Fwin32_get_locale_info);