comparison src/nt.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 3078fd1074e8
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
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 /* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ 25 /* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */
26 26
27 #include <config.h> 27 #include <config.h>
28
29 #undef signal
30 #define getwd _getwd 28 #define getwd _getwd
31 #include "lisp.h" 29 #include "lisp.h"
32 #undef getwd 30 #undef getwd
33 31
34 #include "systime.h" 32 #include "systime.h"
35 #include "syssignal.h" 33 #include "syssignal.h"
36 #include "sysproc.h" 34 #include "sysproc.h"
37 #include "sysfile.h" 35 #include "sysfile.h"
38 36 #include "syspwd.h"
39 #include <ctype.h> 37 #include "sysdir.h"
40 #include <direct.h> 38
41 #include <errno.h> 39 #include "syswindows.h"
42 #include <fcntl.h>
43 #include <io.h>
44 #include <pwd.h>
45 #include <signal.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49
50 #include <windows.h>
51 #ifndef __MINGW32__
52 #include <mmsystem.h>
53 #else
54 typedef void (CALLBACK TIMECALLBACK)(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
55
56 typedef TIMECALLBACK FAR *LPTIMECALLBACK;
57 DWORD WINAPI timeGetTime(void);
58 MMRESULT WINAPI timeSetEvent(UINT uDelay, UINT uResolution,
59 LPTIMECALLBACK fptc, DWORD dwUser, UINT fuEvent);
60 MMRESULT WINAPI timeKillEvent(UINT uTimerID);
61 MMRESULT WINAPI timeGetDevCaps(TIMECAPS* ptc, UINT cbtc);
62 MMRESULT WINAPI timeBeginPeriod(UINT uPeriod);
63 MMRESULT WINAPI timeEndPeriod(UINT uPeriod);
64 #endif
65 40
66 #include "nt.h" 41 #include "nt.h"
67 #include <sys/dir.h>
68 #include "ntheap.h" 42 #include "ntheap.h"
69 43
70 44
71 extern Lisp_Object Vmswindows_downcase_file_names; 45 extern Lisp_Object Vmswindows_downcase_file_names;
72 #if 0 46 #if 0
93 strcpy (dir, startup_dir); 67 strcpy (dir, startup_dir);
94 return dir; 68 return dir;
95 #endif 69 #endif
96 } 70 }
97 71
98 /* Emulate getloadavg. */
99 int
100 getloadavg (double loadavg[], int nelem)
101 {
102 int i;
103
104 /* A faithful emulation is going to have to be saved for a rainy day. */
105 for (i = 0; i < nelem; i++)
106 {
107 loadavg[i] = 0.0;
108 }
109 return i;
110 }
111
112 /* Emulate getpwuid, getpwnam and others. */ 72 /* Emulate getpwuid, getpwnam and others. */
113 73
114 #define PASSWD_FIELD_SIZE 256 74 #define PASSWD_FIELD_SIZE 256
115 75
116 static char the_passwd_name[PASSWD_FIELD_SIZE]; 76 static char the_passwd_name[PASSWD_FIELD_SIZE];
130 the_passwd_dir, 90 the_passwd_dir,
131 the_passwd_shell, 91 the_passwd_shell,
132 }; 92 };
133 93
134 uid_t 94 uid_t
135 getuid () 95 getuid (void)
136 { 96 {
137 return nt_fake_unix_uid; 97 return nt_fake_unix_uid;
138 } 98 }
139 99
140 uid_t 100 uid_t
141 geteuid () 101 geteuid (void)
142 { 102 {
143 return nt_fake_unix_uid; 103 return nt_fake_unix_uid;
144 } 104 }
145 105
146 gid_t 106 gid_t
147 getgid () 107 getgid (void)
148 { 108 {
149 return the_passwd.pw_gid; 109 return the_passwd.pw_gid;
150 } 110 }
151 111
152 gid_t 112 gid_t
153 getegid () 113 getegid (void)
154 { 114 {
155 return getgid (); 115 return getgid ();
156 } 116 }
157 117
158 struct passwd * 118 struct passwd *
181 141
182 return pw; 142 return pw;
183 } 143 }
184 144
185 void 145 void
186 init_user_info () 146 init_user_info (void)
187 { 147 {
188 /* This code is pretty much of ad hoc nature. There is no unix-like 148 /* This code is pretty much of ad hoc nature. There is no unix-like
189 UIDs under Windows NT. There is no concept of root user, because 149 UIDs under Windows NT. There is no concept of root user, because
190 all security is ACL-based. Instead, let's use a simple variable, 150 all security is ACL-based. Instead, let's use a simple variable,
191 nt-fake-unix-uid, which would allow the user to have a uid of 151 nt-fake-unix-uid, which would allow the user to have a uid of
288 #endif 248 #endif
289 if (getenv ("SHELL") == NULL) 249 if (getenv ("SHELL") == NULL)
290 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd"); 250 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
291 251
292 /* Set dir and shell from environment variables. */ 252 /* Set dir and shell from environment variables. */
293 strcpy (the_passwd.pw_dir, get_home_directory()); 253 strcpy (the_passwd.pw_dir, (char *)get_home_directory());
294 strcpy (the_passwd.pw_shell, getenv ("SHELL")); 254 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
295 } 255 }
296 256
297 /* Normalize filename by converting all path separators to 257 /* Normalize filename by converting all path separators to
298 the specified separator. Also conditionally convert upper 258 the specified separator. Also conditionally convert upper
299 case path name components to lower case. */ 259 case path name components to lower case. */
300 260
301 static void 261 static void
302 normalize_filename (fp, path_sep) 262 normalize_filename (char *fp, char path_sep)
303 REGISTER char *fp;
304 char path_sep;
305 { 263 {
306 char sep; 264 char sep;
307 char *elem; 265 char *elem;
308 266
309 /* Always lower-case drive letters a-z, even if the filesystem 267 /* Always lower-case drive letters a-z, even if the filesystem
355 } while (*fp++); 313 } while (*fp++);
356 } 314 }
357 315
358 /* Destructively turn backslashes into slashes. */ 316 /* Destructively turn backslashes into slashes. */
359 void 317 void
360 dostounix_filename (p) 318 dostounix_filename (char *p)
361 REGISTER char *p;
362 { 319 {
363 normalize_filename (p, '/'); 320 normalize_filename (p, '/');
364 } 321 }
365 322
366 /* Destructively turn slashes into backslashes. */ 323 /* Destructively turn slashes into backslashes. */
367 void 324 void
368 unixtodos_filename (p) 325 unixtodos_filename (char *p)
369 REGISTER char *p;
370 { 326 {
371 normalize_filename (p, '\\'); 327 normalize_filename (p, '\\');
372 } 328 }
373 329
374 /* Remove all CR's that are followed by a LF. 330 /* Remove all CR's that are followed by a LF.
375 (From msdos.c...probably should figure out a way to share it, 331 (From msdos.c...probably should figure out a way to share it,
376 although this code isn't going to ever change.) */ 332 although this code isn't going to ever change.) */
377 int 333 int
378 crlf_to_lf (n, buf, lf_count) 334 crlf_to_lf (int n, unsigned char *buf, unsigned *lf_count)
379 REGISTER int n;
380 REGISTER unsigned char *buf;
381 REGISTER unsigned *lf_count;
382 { 335 {
383 unsigned char *np = buf; 336 unsigned char *np = buf;
384 unsigned char *startp = buf; 337 unsigned char *startp = buf;
385 unsigned char *endp = buf + n; 338 unsigned char *endp = buf + n;
386 339
553 #endif /* 0 */ 506 #endif /* 0 */
554 507
555 #define REG_ROOT "SOFTWARE\\GNU\\XEmacs" 508 #define REG_ROOT "SOFTWARE\\GNU\\XEmacs"
556 509
557 LPBYTE 510 LPBYTE
558 nt_get_resource (key, lpdwtype) 511 nt_get_resource (char *key, LPDWORD lpdwtype)
559 char *key;
560 LPDWORD lpdwtype;
561 { 512 {
562 LPBYTE lpvalue; 513 LPBYTE lpvalue;
563 HKEY hrootkey = NULL; 514 HKEY hrootkey = NULL;
564 DWORD cbData; 515 DWORD cbData;
565 516
600 551
601 return (NULL); 552 return (NULL);
602 } 553 }
603 554
604 void 555 void
605 init_environment () 556 init_environment (void)
606 { 557 {
607 /* Check for environment variables and use registry if they don't exist */ 558 /* Check for environment variables and use registry if they don't exist */
608 { 559 {
609 int i; 560 int i;
610 LPBYTE lpval; 561 LPBYTE lpval;
622 "EMACSPATH", 573 "EMACSPATH",
623 "EMACSPACKAGEPATH", 574 "EMACSPACKAGEPATH",
624 "EMACSLOCKDIR", 575 "EMACSLOCKDIR",
625 "INFOPATH" 576 "INFOPATH"
626 }; 577 };
627 #ifdef HEAP_IN_DATA 578 #if defined (HEAP_IN_DATA) && !defined(PDUMP)
628 cache_system_info (); 579 cache_system_info ();
629 #endif 580 #endif
630 for (i = 0; i < countof (env_vars); i++) 581 for (i = 0; i < countof (env_vars); i++)
631 { 582 {
632 if (!getenv (env_vars[i]) && 583 if (!getenv (env_vars[i]) &&
1096 dir_is_fat = is_fat_volume (filename, NULL); 1047 dir_is_fat = is_fat_volume (filename, NULL);
1097 1048
1098 return dirp; 1049 return dirp;
1099 } 1050 }
1100 1051
1101 void 1052 int
1102 closedir (DIR *dirp) 1053 closedir (DIR *dirp)
1103 { 1054 {
1055 BOOL retval;
1056
1104 /* If we have a find-handle open, close it. */ 1057 /* If we have a find-handle open, close it. */
1105 if (dir_find_handle != INVALID_HANDLE_VALUE) 1058 if (dir_find_handle != INVALID_HANDLE_VALUE)
1106 { 1059 {
1107 FindClose (dir_find_handle); 1060 retval = FindClose (dir_find_handle);
1108 dir_find_handle = INVALID_HANDLE_VALUE; 1061 dir_find_handle = INVALID_HANDLE_VALUE;
1109 } 1062 }
1110 xfree (dirp); 1063 xfree (dirp);
1064 if (retval)
1065 return 0;
1066 else
1067 return -1;
1111 } 1068 }
1112 1069
1113 struct direct * 1070 struct direct *
1114 readdir (DIR *dirp) 1071 readdir (DIR *dirp)
1115 { 1072 {
1135 if (!FindNextFile (dir_find_handle, &dir_find_data)) 1092 if (!FindNextFile (dir_find_handle, &dir_find_data))
1136 return NULL; 1093 return NULL;
1137 } 1094 }
1138 1095
1139 /* Emacs never uses this value, so don't bother making it match 1096 /* Emacs never uses this value, so don't bother making it match
1140 value returned by stat(). */ 1097 value returned by xemacs_stat(). */
1141 dir_static.d_ino = 1; 1098 dir_static.d_ino = 1;
1142 1099
1143 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 + 1100 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
1144 dir_static.d_namlen - dir_static.d_namlen % 4; 1101 dir_static.d_namlen - dir_static.d_namlen % 4;
1145 1102
1256 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime; 1213 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
1257 ret -= utc_base; 1214 ret -= utc_base;
1258 return (time_t) (ret * 1e-7); 1215 return (time_t) (ret * 1e-7);
1259 } 1216 }
1260 #else 1217 #else
1218
1219 #if defined(MINGW) && CYGWIN_VERSION_DLL_MAJOR <= 21
1220 #define LowPart u.LowPart
1221 #define HighPart u.HighPart
1222 #endif
1261 1223
1262 static LARGE_INTEGER utc_base_li; 1224 static LARGE_INTEGER utc_base_li;
1263 1225
1264 time_t 1226 time_t
1265 convert_time (FILETIME uft) 1227 convert_time (FILETIME uft)
1326 #endif 1288 #endif
1327 1289
1328 return ret; 1290 return ret;
1329 } 1291 }
1330 #endif 1292 #endif
1293 #if defined(MINGW) && CYGWIN_VERSION_DLL_MAJOR <= 21
1294 #undef LowPart
1295 #undef HighPart
1296 #endif
1331 1297
1332 #if 0 1298 #if 0
1333 /* in case we ever have need of this */ 1299 /* in case we ever have need of this */
1334 void 1300 void
1335 convert_from_time_t (time_t time, FILETIME * pft) 1301 convert_from_time_t (time_t time, FILETIME * pft)
1403 return hashval (p); 1369 return hashval (p);
1404 } 1370 }
1405 1371
1406 #endif 1372 #endif
1407 1373
1408 /* stat has been fixed since MSVC 5.0. 1374 /* #### aichner@ecf.teradyne.com reported that with the library
1409 Oh, and do not encapsulater stat for non-MS compilers, too */ 1375 provided stat/fstat, (file-exist "d:\\tmp\\") =>> nil,
1410 /* #### popineau@ese-metz.fr says they still might be broken. 1376 (file-exist "d:\\tmp") =>> t, when d:\tmp exists. Whenever
1411 Oh well... Let's add that `1 ||' condition.... --kkm */ 1377 we opt to use non-encapsulated stat(), this should serve as
1412 #if 1 || defined(_MSC_VER) && _MSC_VER < 1100 1378 a compatibility test. --kkm */
1413 1379
1414 /* Since stat is encapsulated on Windows NT, we need to encapsulate 1380 /* Since stat is encapsulated on Windows NT, we need to encapsulate
1415 the equally broken fstat as well. */ 1381 the equally broken fstat as well. */
1416 int _cdecl 1382 int
1417 fstat (int handle, struct stat *buffer) 1383 mswindows_fstat (int handle, struct stat *buffer)
1418 { 1384 {
1419 int ret; 1385 int ret;
1420 BY_HANDLE_FILE_INFORMATION lpFileInfo; 1386 BY_HANDLE_FILE_INFORMATION lpFileInfo;
1421 /* Initialize values */ 1387 /* Initialize values */
1422 buffer->st_mode = 0; 1388 buffer->st_mode = 0;
1447 1413
1448 /* MSVC stat function can't cope with UNC names and has other bugs, so 1414 /* MSVC stat function can't cope with UNC names and has other bugs, so
1449 replace it with our own. This also allows us to calculate consistent 1415 replace it with our own. This also allows us to calculate consistent
1450 inode values without hacks in the main Emacs code. */ 1416 inode values without hacks in the main Emacs code. */
1451 int 1417 int
1452 stat (const char * path, struct stat * buf) 1418 mswindows_stat (const char * path, struct stat * buf)
1453 { 1419 {
1454 char * name; 1420 char * name;
1455 WIN32_FIND_DATA wfd; 1421 WIN32_FIND_DATA wfd;
1456 HANDLE fh; 1422 HANDLE fh;
1457 DWORD fake_inode; 1423 DWORD fake_inode;
1477 directory of a drive or UNC volume in which case ensure there 1443 directory of a drive or UNC volume in which case ensure there
1478 is a trailing separator. */ 1444 is a trailing separator. */
1479 len = strlen (name); 1445 len = strlen (name);
1480 rootdir = (path >= name + len - 1 1446 rootdir = (path >= name + len - 1
1481 && (IS_DIRECTORY_SEP (*path) || *path == 0)); 1447 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1482 name = strcpy (alloca (len + 2), name); 1448 name = strcpy ((char *)alloca (len + 2), name);
1483 1449
1484 if (rootdir) 1450 if (rootdir)
1485 { 1451 {
1486 if (!IS_DIRECTORY_SEP (name[len-1])) 1452 if (!IS_DIRECTORY_SEP (name[len-1]))
1487 strcat (name, "\\"); 1453 strcat (name, "\\");
1633 1599
1634 buf->st_mode |= permission | (permission >> 3) | (permission >> 6); 1600 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1635 1601
1636 return 0; 1602 return 0;
1637 } 1603 }
1638 #endif /* defined(_MSC_VER) && _MSC_VER < 1100 */
1639 1604
1640 /* From callproc.c */ 1605 /* From callproc.c */
1641 extern Lisp_Object Vbinary_process_input; 1606 extern Lisp_Object Vbinary_process_input;
1642 extern Lisp_Object Vbinary_process_output; 1607 extern Lisp_Object Vbinary_process_output;
1643 1608
1674 term_ntproc (int unused) 1639 term_ntproc (int unused)
1675 { 1640 {
1676 } 1641 }
1677 1642
1678 void 1643 void
1679 init_ntproc () 1644 init_ntproc (void)
1680 { 1645 {
1681 /* Initial preparation for subprocess support: replace our standard 1646 /* Initial preparation for subprocess support: replace our standard
1682 handles with non-inheritable versions. */ 1647 handles with non-inheritable versions. */
1683 { 1648 {
1684 HANDLE parent; 1649 HANDLE parent;
1807 unsigned signal_block_mask = 0; 1772 unsigned signal_block_mask = 0;
1808 1773
1809 /* Signal pending mask: bit set to 1 means sig is pending */ 1774 /* Signal pending mask: bit set to 1 means sig is pending */
1810 unsigned signal_pending_mask = 0; 1775 unsigned signal_pending_mask = 0;
1811 1776
1812 msw_sighandler msw_sigset (int nsig, msw_sighandler handler) 1777 mswindows_sighandler mswindows_sigset (int nsig, mswindows_sighandler handler)
1813 { 1778 {
1814 /* We delegate some signals to the system function */ 1779 /* We delegate some signals to the system function */
1815 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT) 1780 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT)
1816 return signal (nsig, handler); 1781 return signal (nsig, handler);
1817 1782
1821 return NULL; 1786 return NULL;
1822 } 1787 }
1823 1788
1824 /* Store handler ptr */ 1789 /* Store handler ptr */
1825 { 1790 {
1826 msw_sighandler old_handler = signal_handlers[nsig]; 1791 mswindows_sighandler old_handler = signal_handlers[nsig];
1827 signal_handlers[nsig] = handler; 1792 signal_handlers[nsig] = handler;
1828 return old_handler; 1793 return old_handler;
1829 } 1794 }
1830 } 1795 }
1831 1796
1832 int msw_sighold (int nsig) 1797 int mswindows_sighold (int nsig)
1833 { 1798 {
1834 if (nsig < 0 || nsig > SIG_MAX) 1799 if (nsig < 0 || nsig > SIG_MAX)
1835 return errno = EINVAL; 1800 return errno = EINVAL;
1836 1801
1837 signal_block_mask |= sigmask(nsig); 1802 signal_block_mask |= sigmask(nsig);
1838 return 0; 1803 return 0;
1839 } 1804 }
1840 1805
1841 int msw_sigrelse (int nsig) 1806 int mswindows_sigrelse (int nsig)
1842 { 1807 {
1843 if (nsig < 0 || nsig > SIG_MAX) 1808 if (nsig < 0 || nsig > SIG_MAX)
1844 return errno = EINVAL; 1809 return errno = EINVAL;
1845 1810
1846 signal_block_mask &= ~sigmask(nsig); 1811 signal_block_mask &= ~sigmask(nsig);
1847 1812
1848 if (signal_pending_mask & sigmask(nsig)) 1813 if (signal_pending_mask & sigmask(nsig))
1849 msw_raise (nsig); 1814 mswindows_raise (nsig);
1850 1815
1851 return 0; 1816 return 0;
1852 } 1817 }
1853 1818
1854 int msw_sigpause (int nsig) 1819 int mswindows_sigpause (int nsig)
1855 { 1820 {
1856 /* This is currently not called, because the only 1821 /* This is currently not called, because the only
1857 call to sigpause inside XEmacs is with SIGCHLD 1822 call to sigpause inside XEmacs is with SIGCHLD
1858 parameter. Just in case, we put an assert here, 1823 parameter. Just in case, we put an assert here,
1859 so anyone who will add a call to sigpause will 1824 so anyone who will add a call to sigpause will
1860 be surprised (or surprise someone else...) */ 1825 be surprised (or surprise someone else...) */
1861 assert (0); 1826 assert (0);
1862 return 0; 1827 return 0;
1863 } 1828 }
1864 1829
1865 int msw_raise (int nsig) 1830 int mswindows_raise (int nsig)
1866 { 1831 {
1867 /* We delegate some raises to the system routine */ 1832 /* We delegate some raises to the system routine */
1868 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT) 1833 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT)
1869 return raise (nsig); 1834 return raise (nsig);
1870 1835
1926 1891
1927 static void CALLBACK timer_proc (UINT uID, UINT uMsg, DWORD dwUser, 1892 static void CALLBACK timer_proc (UINT uID, UINT uMsg, DWORD dwUser,
1928 DWORD dw1, DWORD dw2) 1893 DWORD dw1, DWORD dw2)
1929 { 1894 {
1930 /* Just raise a signal indicated by dwUser parameter */ 1895 /* Just raise a signal indicated by dwUser parameter */
1931 msw_raise (dwUser); 1896 mswindows_raise (dwUser);
1932 } 1897 }
1933 1898
1934 /* Divide time in ms specified by IT by DENOM. Return 1 ms 1899 /* Divide time in ms specified by IT by DENOM. Return 1 ms
1935 if division results in zero */ 1900 if division results in zero */
1936 static UINT period (const struct itimerval* it, UINT denom) 1901 static UINT period (const struct itimerval* it, UINT denom)
2009 return setitimer_helper (itnew, itold, &it_prof, &tid_prof, SIGPROF); 1974 return setitimer_helper (itnew, itold, &it_prof, &tid_prof, SIGPROF);
2010 else 1975 else
2011 return errno = EINVAL; 1976 return errno = EINVAL;
2012 } 1977 }
2013 1978
1979
1980 /*--------------------------------------------------------------------*/
1981 /* Memory-mapped files */
1982 /*--------------------------------------------------------------------*/
1983
2014 int 1984 int
2015 open_input_file (file_data *p_file, CONST char *filename) 1985 open_input_file (file_data *p_file, const char *filename)
2016 { 1986 {
1987 /* Synched with FSF 20.6. We fixed some warnings. */
2017 HANDLE file; 1988 HANDLE file;
2018 HANDLE file_mapping; 1989 HANDLE file_mapping;
2019 void *file_base; 1990 void *file_base;
2020 DWORD size, upper_size; 1991 DWORD size, upper_size;
2021 1992
2032 2003
2033 file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size); 2004 file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size);
2034 if (file_base == 0) 2005 if (file_base == 0)
2035 return FALSE; 2006 return FALSE;
2036 2007
2037 p_file->name = (char*)filename; 2008 p_file->name = (char *)filename;
2038 p_file->size = size; 2009 p_file->size = size;
2039 p_file->file = file; 2010 p_file->file = file;
2040 p_file->file_mapping = file_mapping; 2011 p_file->file_mapping = file_mapping;
2041 p_file->file_base = file_base; 2012 p_file->file_base = (char *)file_base;
2042 2013
2043 return TRUE; 2014 return TRUE;
2015 }
2016
2017 int
2018 open_output_file (file_data *p_file, const char *filename, unsigned long size)
2019 {
2020 /* Synched with FSF 20.6. We fixed some warnings. */
2021 HANDLE file;
2022 HANDLE file_mapping;
2023 void *file_base;
2024
2025 file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2026 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
2027 if (file == INVALID_HANDLE_VALUE)
2028 return FALSE;
2029
2030 file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE,
2031 0, size, NULL);
2032 if (!file_mapping)
2033 return FALSE;
2034
2035 file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
2036 if (file_base == NULL)
2037 return FALSE;
2038
2039 p_file->name = filename;
2040 p_file->size = size;
2041 p_file->file = file;
2042 p_file->file_mapping = file_mapping;
2043 p_file->file_base = (char*) file_base;
2044
2045 return TRUE;
2046 }
2047
2048 #if 1 /* !defined(MINGW) */
2049 /* Return pointer to section header for section containing the given
2050 relative virtual address. */
2051 static IMAGE_SECTION_HEADER *
2052 rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header)
2053 {
2054 /* Synched with FSF 20.6. We added MINGW stuff. */
2055 PIMAGE_SECTION_HEADER section;
2056 int i;
2057
2058 section = IMAGE_FIRST_SECTION (nt_header);
2059
2060 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
2061 {
2062 /* Some linkers (eg. the NT SDK linker I believe) swapped the
2063 meaning of these two values - or rather, they ignored
2064 VirtualSize entirely and always set it to zero. This affects
2065 some very old exes (eg. gzip dated Dec 1993). Since
2066 mswindows_executable_type relies on this function to work reliably,
2067 we need to cope with this. */
2068 DWORD real_size = max (section->SizeOfRawData,
2069 section->Misc.VirtualSize);
2070 if (rva >= section->VirtualAddress
2071 && rva < section->VirtualAddress + real_size)
2072 return section;
2073 section++;
2074 }
2075 return NULL;
2076 }
2077 #endif
2078
2079 void
2080 mswindows_executable_type (const char * filename, int * is_dos_app,
2081 int * is_cygnus_app)
2082 {
2083 /* Synched with FSF 20.6. We added MINGW stuff and casts. */
2084 file_data executable;
2085 char * p;
2086
2087 /* Default values in case we can't tell for sure. */
2088 *is_dos_app = FALSE;
2089 *is_cygnus_app = FALSE;
2090
2091 if (!open_input_file (&executable, filename))
2092 return;
2093
2094 p = strrchr (filename, '.');
2095
2096 /* We can only identify DOS .com programs from the extension. */
2097 if (p && stricmp (p, ".com") == 0)
2098 *is_dos_app = TRUE;
2099 else if (p && (stricmp (p, ".bat") == 0 ||
2100 stricmp (p, ".cmd") == 0))
2101 {
2102 /* A DOS shell script - it appears that CreateProcess is happy to
2103 accept this (somewhat surprisingly); presumably it looks at
2104 COMSPEC to determine what executable to actually invoke.
2105 Therefore, we have to do the same here as well. */
2106 /* Actually, I think it uses the program association for that
2107 extension, which is defined in the registry. */
2108 p = egetenv ("COMSPEC");
2109 if (p)
2110 mswindows_executable_type (p, is_dos_app, is_cygnus_app);
2111 }
2112 else
2113 {
2114 /* Look for DOS .exe signature - if found, we must also check that
2115 it isn't really a 16- or 32-bit Windows exe, since both formats
2116 start with a DOS program stub. Note that 16-bit Windows
2117 executables use the OS/2 1.x format. */
2118
2119 #if 0 /* defined( MINGW ) */
2120 /* mingw32 doesn't have enough headers to detect cygwin
2121 apps, just do what we can. */
2122 FILHDR * exe_header;
2123
2124 exe_header = (FILHDR*) executable.file_base;
2125 if (exe_header->e_magic != DOSMAGIC)
2126 goto unwind;
2127
2128 if ((char*) exe_header->e_lfanew > (char*) executable.size)
2129 {
2130 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */
2131 *is_dos_app = TRUE;
2132 }
2133 else if (exe_header->nt_signature != NT_SIGNATURE)
2134 {
2135 *is_dos_app = TRUE;
2136 }
2137 #else
2138 IMAGE_DOS_HEADER * dos_header;
2139 IMAGE_NT_HEADERS * nt_header;
2140
2141 dos_header = (PIMAGE_DOS_HEADER) executable.file_base;
2142 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
2143 goto unwind;
2144
2145 nt_header = (PIMAGE_NT_HEADERS) ((char*) dos_header + dos_header->e_lfanew);
2146
2147 if ((char*) nt_header > (char*) dos_header + executable.size)
2148 {
2149 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */
2150 *is_dos_app = TRUE;
2151 }
2152 else if (nt_header->Signature != IMAGE_NT_SIGNATURE &&
2153 LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
2154 {
2155 *is_dos_app = TRUE;
2156 }
2157 else if (nt_header->Signature == IMAGE_NT_SIGNATURE)
2158 {
2159 /* Look for cygwin.dll in DLL import list. */
2160 IMAGE_DATA_DIRECTORY import_dir =
2161 nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
2162 IMAGE_IMPORT_DESCRIPTOR * imports;
2163 IMAGE_SECTION_HEADER * section;
2164
2165 section = rva_to_section (import_dir.VirtualAddress, nt_header);
2166 imports = (IMAGE_IMPORT_DESCRIPTOR *) RVA_TO_PTR (import_dir.VirtualAddress,
2167 section, executable);
2168
2169 for ( ; imports->Name; imports++)
2170 {
2171 char *dllname = (char*) RVA_TO_PTR (imports->Name, section, executable);
2172
2173 /* The exact name of the cygwin dll has changed with
2174 various releases, but hopefully this will be reasonably
2175 future proof. */
2176 if (strncmp (dllname, "cygwin", 6) == 0)
2177 {
2178 *is_cygnus_app = TRUE;
2179 break;
2180 }
2181 }
2182 }
2183 #endif
2184 }
2185
2186 unwind:
2187 close_file_data (&executable);
2044 } 2188 }
2045 2189
2046 /* Close the system structures associated with the given file. */ 2190 /* Close the system structures associated with the given file. */
2047 void 2191 void
2048 close_file_data (file_data *p_file) 2192 close_file_data (file_data *p_file)