Mercurial > hg > xemacs-beta
comparison src/nt.c @ 814:a634e3b7acc8
[xemacs-hg @ 2002-04-14 12:41:59 by ben]
latest changes
TODO.ben-mule-21-5: Update.
make-docfile.c: Add basic support for handling ISO 2022 doc strings -- we parse
the basic charset designation sequences so we know whether we're
in ASCII and have to pay attention to end quotes and such.
Reformat code according to coding standards.
abbrev.el: Add `global-abbrev-mode', which turns on or off abbrev-mode in all
buffers. Added `defining-abbrev-turns-on-abbrev-mode' -- if
non-nil, defining an abbrev through an interactive function will
automatically turn on abbrev-mode, either globally or locally
depending on the command. This is the "what you'd expect"
behavior.
indent.el: general function for indenting a balanced expression in a
mode-correct way. Works similar to indent-region in that a mode
can specify a specific command to do the whole operation; if not,
figure out the region using forward-sexp and indent each line
using indent-according-to-mode.
keydefs.el: Removed.
Modify M-C-backslash to do indent-region-or-balanced-expression.
Make S-Tab just insert a TAB char, like it's meant to do.
make-docfile.el: Now that we're using the call-process-in-lisp, we need to load
an extra file win32-native.el because we're running a bare temacs.
menubar-items.el: Totally redo the Cmds menu so that most used commands appear
directly on the menu and less used commands appear in submenus.
The old way may have been very pretty, but rather impractical.
process.el: Under Windows, don't ever use old-call-process-internal, even
in batch mode. We can do processes in batch mode.
subr.el: Someone recoded truncate-string-to-width, saying "the FSF version
is too complicated and does lots of hard-to-understand stuff" but
the resulting recoded version was *totally* wrong! it
misunderstood the basic point of this function, which is work in
*columns* not chars. i dumped ours and copied the version from
FSF 21.1. Also added truncate-string-with-continuation-dots,
since this idiom is used often.
config.inc.samp, xemacs.mak: Separate out debug and optimize flags.
Remove all vestiges of USE_MINIMAL_TAGBITS,
USE_INDEXED_LRECORD_IMPLEMENTATION, and GUNG_HO, since those
ifdefs have long been removed.
Make error-checking support actually work.
Some rearrangement of config.inc.samp to make it more logical.
Remove callproc.c and ntproc.c from xemacs.mak, no longer used.
Make pdump the default.
lisp.h: Add support for strong type-checking of Bytecount, Bytebpos,
Charcount, Charbpos, and others, by making them classes,
overloading the operators to provide integer-like operation and
carefully controlling what operations are allowed. Not currently
enabled in C++ builds because there are still a number of compile
errors, and it won't really work till we merge in my "8-bit-Mule"
workspace, in which I make use of the new types Charxpos,
Bytexpos, Memxpos, representing a "position" either in a buffer or
a string. (This is especially important in the extent code.)
abbrev.c, alloc.c, eval.c, buffer.c, buffer.h, editfns.c, fns.c, text.h: Warning fixes, some of them related to new C++ strict type
checking of Bytecount, Charbpos, etc.
dired.c: Caught an actual error due to strong type checking -- char len
being passed when should be byte len.
alloc.c, backtrace.h, bytecode.c, bytecode.h, eval.c, sysdep.c: Further optimize Ffuncall:
-- process arg list at compiled-function creation time, converting
into an array for extra-quick access at funcall time.
-- rewrite funcall_compiled_function to use it, and inline this
function.
-- change the order of check for magic stuff in
SPECBIND_FAST_UNSAFE to be faster.
-- move the check for need to garbage collect into the allocation
code, so only a single flag needs to be checked in funcall.
buffer.c, symbols.c: add debug funs to check on mule optimization info in buffers and
strings.
eval.c, emacs.c, text.c, regex.c, scrollbar-msw.c, search.c: Fix evil crashes due to eistrings not properly reinitialized under
pdump. Redo a bit some of the init routines; convert some
complex_vars_of() into simple vars_of(), because they didn't need
complex processing.
callproc.c, emacs.c, event-stream.c, nt.c, process.c, process.h, sysdep.c, sysdep.h, syssignal.h, syswindows.h, ntproc.c: Delete. Hallelujah, praise the Lord, there is no god
but Allah!!!
fix so that processes can be invoked in bare temacs -- thereby
eliminating any need for callproc.c. (currently only eliminated
under NT.) remove all crufty and unnecessary old process code in
ntproc.c and elsewhere. move non-callproc-specific stuff (mostly
environment) into process.c, so callproc.c can be left out under
NT.
console-tty.c, doc.c, file-coding.c, file-coding.h, lstream.c, lstream.h: fix doc string handling so it works with Japanese, etc docs.
change handling of "character mode" so callers don't have to
manually set it (quite error-prone).
event-msw.c: spacing fixes.
lread.c: eliminate unused crufty vintage-19 "FSF defun hack" code.
lrecord.h: improve pdump description docs.
buffer.c, ntheap.c, unexnt.c, win32.c, emacs.c: Mule-ize some unexec and startup code. It was pseudo-Mule-ized
before by simply always calling the ...A versions of functions,
but that won't cut it -- eventually we want to be able to run
properly even if XEmacs has been installed in a Japanese
directory. (The current problem is the timing of the loading of
the Unicode tables; this will eventually be fixed.) Go through and
fix various other places where the code was not Mule-clean.
Provide a function mswindows_get_module_file_name() to get our own
name without resort to PATH_MAX and such. Add a big comment in
main() about the problem with Unicode table load timing that I
just alluded to.
emacs.c: When error-checking is enabled (interpreted as "user is developing
XEmacs"), don't ask user to "pause to read messages" when a fatal
error has occurred, because it will wedge if we are in an inner
modal loop (typically when a menu is popped up) and make us unable
to get a useful stack trace in the debugger.
text.c: Correct update_entirely_ascii_p_flag to actually work.
lisp.h, symsinit.h: declarations for above changes.
author | ben |
---|---|
date | Sun, 14 Apr 2002 12:43:31 +0000 |
parents | 2b676dc88c66 |
children | 6504113e7c2d |
comparison
equal
deleted
inserted
replaced
813:9541922fb765 | 814:a634e3b7acc8 |
---|---|
417 | 417 |
418 return (NULL); | 418 return (NULL); |
419 } | 419 } |
420 | 420 |
421 void | 421 void |
422 init_environment (void) | 422 init_mswindows_environment (void) |
423 { | 423 { |
424 /* Check for environment variables and use registry if they don't exist */ | 424 /* Check for environment variables and use registry if they don't exist */ |
425 /* Emacs 20.6 sets default values for these; not necessary here because | 425 /* Emacs 20.6 sets default values for these; not necessary here because |
426 we already supply them. (except SHELL, which is set in init_user_info().) | 426 we already supply them. (except SHELL, which is set in init_user_info().) |
427 Emacs 20.6 messes with TMPDIR; not necessary here. */ | 427 Emacs 20.6 messes with TMPDIR; not necessary here. */ |
1745 TSTR_TO_C_STRING_MALLOC (cwdext, cwd); | 1745 TSTR_TO_C_STRING_MALLOC (cwdext, cwd); |
1746 xfree (cwdext); | 1746 xfree (cwdext); |
1747 return cwd; | 1747 return cwd; |
1748 } | 1748 } |
1749 | 1749 |
1750 | |
1751 /*--------------------------------------------------------------------*/ | |
1752 /* Memory-mapped files */ | |
1753 /*--------------------------------------------------------------------*/ | |
1754 | |
1755 int | |
1756 open_input_file (file_data *p_file, const Intbyte *filename) | |
1757 { | |
1758 /* Synched with FSF 20.6. We fixed some warnings. */ | |
1759 HANDLE file; | |
1760 HANDLE file_mapping; | |
1761 void *file_base; | |
1762 DWORD size, upper_size; | |
1763 Extbyte *fileext; | |
1764 | |
1765 C_STRING_TO_TSTR (filename, fileext); | |
1766 | |
1767 file = qxeCreateFile (fileext, GENERIC_READ, FILE_SHARE_READ, NULL, | |
1768 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |
1769 if (file == INVALID_HANDLE_VALUE) | |
1770 return FALSE; | |
1771 | |
1772 size = GetFileSize (file, &upper_size); | |
1773 file_mapping = qxeCreateFileMapping (file, NULL, PAGE_READONLY, | |
1774 0, size, NULL); | |
1775 if (!file_mapping) | |
1776 return FALSE; | |
1777 | |
1778 file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size); | |
1779 if (file_base == 0) | |
1780 return FALSE; | |
1781 | |
1782 p_file->name = filename; | |
1783 p_file->size = size; | |
1784 p_file->file = file; | |
1785 p_file->file_mapping = file_mapping; | |
1786 p_file->file_base = file_base; | |
1787 | |
1788 return TRUE; | |
1789 } | |
1790 | |
1791 int | |
1792 open_output_file (file_data *p_file, const Intbyte *filename, | |
1793 unsigned long size) | |
1794 { | |
1795 /* Synched with FSF 20.6. We fixed some warnings. */ | |
1796 HANDLE file; | |
1797 HANDLE file_mapping; | |
1798 void *file_base; | |
1799 Extbyte *fileext; | |
1800 | |
1801 C_STRING_TO_TSTR (filename, fileext); | |
1802 | |
1803 file = qxeCreateFile (fileext, GENERIC_READ | GENERIC_WRITE, 0, NULL, | |
1804 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); | |
1805 if (file == INVALID_HANDLE_VALUE) | |
1806 return FALSE; | |
1807 | |
1808 file_mapping = qxeCreateFileMapping (file, NULL, PAGE_READWRITE, | |
1809 0, size, NULL); | |
1810 if (!file_mapping) | |
1811 return FALSE; | |
1812 | |
1813 file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size); | |
1814 if (file_base == NULL) | |
1815 return FALSE; | |
1816 | |
1817 p_file->name = filename; | |
1818 p_file->size = size; | |
1819 p_file->file = file; | |
1820 p_file->file_mapping = file_mapping; | |
1821 p_file->file_base = file_base; | |
1822 | |
1823 return TRUE; | |
1824 } | |
1825 | |
1826 #if 1 /* !defined(MINGW) */ | |
1827 /* Return pointer to section header for section containing the given | |
1828 relative virtual address. */ | |
1829 static IMAGE_SECTION_HEADER * | |
1830 rva_to_section (DWORD rva, IMAGE_NT_HEADERS *nt_header) | |
1831 { | |
1832 /* Synched with FSF 20.6. We added MINGW stuff. */ | |
1833 PIMAGE_SECTION_HEADER section; | |
1834 int i; | |
1835 | |
1836 section = IMAGE_FIRST_SECTION (nt_header); | |
1837 | |
1838 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) | |
1839 { | |
1840 /* Some linkers (eg. the NT SDK linker I believe) swapped the | |
1841 meaning of these two values - or rather, they ignored | |
1842 VirtualSize entirely and always set it to zero. This affects | |
1843 some very old exes (eg. gzip dated Dec 1993). Since | |
1844 mswindows_executable_type relies on this function to work reliably, | |
1845 we need to cope with this. */ | |
1846 DWORD real_size = max (section->SizeOfRawData, | |
1847 section->Misc.VirtualSize); | |
1848 if (rva >= section->VirtualAddress | |
1849 && rva < section->VirtualAddress + real_size) | |
1850 return section; | |
1851 section++; | |
1852 } | |
1853 return NULL; | |
1854 } | |
1855 #endif | |
1856 | |
1750 void | 1857 void |
1751 init_ntproc (void) | 1858 mswindows_executable_type (const Intbyte *filename, int *is_dos_app, |
1859 int *is_cygnus_app) | |
1860 { | |
1861 /* Synched with FSF 20.6. We added MINGW stuff and casts. */ | |
1862 file_data executable; | |
1863 Intbyte *p; | |
1864 | |
1865 /* Default values in case we can't tell for sure. */ | |
1866 *is_dos_app = FALSE; | |
1867 *is_cygnus_app = FALSE; | |
1868 | |
1869 if (!open_input_file (&executable, filename)) | |
1870 return; | |
1871 | |
1872 p = qxestrrchr (filename, '.'); | |
1873 | |
1874 /* We can only identify DOS .com programs from the extension. */ | |
1875 if (p && qxestrcasecmp (p, ".com") == 0) | |
1876 *is_dos_app = TRUE; | |
1877 else if (p && (qxestrcasecmp (p, ".bat") == 0 || | |
1878 qxestrcasecmp (p, ".cmd") == 0)) | |
1879 { | |
1880 /* A DOS shell script - it appears that CreateProcess is happy to | |
1881 accept this (somewhat surprisingly); presumably it looks at | |
1882 COMSPEC to determine what executable to actually invoke. | |
1883 Therefore, we have to do the same here as well. */ | |
1884 /* Actually, I think it uses the program association for that | |
1885 extension, which is defined in the registry. */ | |
1886 p = egetenv ("COMSPEC"); | |
1887 if (p) | |
1888 mswindows_executable_type (p, is_dos_app, is_cygnus_app); | |
1889 } | |
1890 else | |
1891 { | |
1892 /* Look for DOS .exe signature - if found, we must also check that | |
1893 it isn't really a 16- or 32-bit Windows exe, since both formats | |
1894 start with a DOS program stub. Note that 16-bit Windows | |
1895 executables use the OS/2 1.x format. */ | |
1896 | |
1897 #if 0 /* defined( MINGW ) */ | |
1898 /* mingw doesn't have enough headers to detect cygwin | |
1899 apps, just do what we can. */ | |
1900 FILHDR *exe_header; | |
1901 | |
1902 exe_header = (FILHDR *) executable.file_base; | |
1903 if (exe_header->e_magic != DOSMAGIC) | |
1904 goto unwind; | |
1905 | |
1906 if ((char *) exe_header->e_lfanew > (char *) executable.size) | |
1907 { | |
1908 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
1909 *is_dos_app = TRUE; | |
1910 } | |
1911 else if (exe_header->nt_signature != NT_SIGNATURE) | |
1912 { | |
1913 *is_dos_app = TRUE; | |
1914 } | |
1915 #else | |
1916 IMAGE_DOS_HEADER *dos_header; | |
1917 IMAGE_NT_HEADERS *nt_header; | |
1918 | |
1919 dos_header = (PIMAGE_DOS_HEADER) executable.file_base; | |
1920 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) | |
1921 goto unwind; | |
1922 | |
1923 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + | |
1924 dos_header->e_lfanew); | |
1925 | |
1926 if ((char *) nt_header > (char *) dos_header + executable.size) | |
1927 { | |
1928 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
1929 *is_dos_app = TRUE; | |
1930 } | |
1931 else if (nt_header->Signature != IMAGE_NT_SIGNATURE && | |
1932 LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE) | |
1933 { | |
1934 *is_dos_app = TRUE; | |
1935 } | |
1936 else if (nt_header->Signature == IMAGE_NT_SIGNATURE) | |
1937 { | |
1938 /* Look for cygwin.dll in DLL import list. */ | |
1939 IMAGE_DATA_DIRECTORY import_dir = | |
1940 nt_header->OptionalHeader. | |
1941 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; | |
1942 IMAGE_IMPORT_DESCRIPTOR *imports; | |
1943 IMAGE_SECTION_HEADER *section; | |
1944 | |
1945 section = rva_to_section (import_dir.VirtualAddress, nt_header); | |
1946 imports = | |
1947 (IMAGE_IMPORT_DESCRIPTOR *) RVA_TO_PTR (import_dir.VirtualAddress, | |
1948 section, executable); | |
1949 | |
1950 for ( ; imports->Name; imports++) | |
1951 { | |
1952 Extbyte *dllname_ext = | |
1953 (Extbyte *) RVA_TO_PTR (imports->Name, section, executable); | |
1954 Intbyte *dllname; | |
1955 | |
1956 EXTERNAL_TO_C_STRING (dllname_ext, dllname, Qbinary); | |
1957 | |
1958 /* The exact name of the cygwin dll has changed with | |
1959 various releases, but hopefully this will be reasonably | |
1960 future proof. */ | |
1961 if (qxestrncasecmp (dllname, (Intbyte *) "cygwin", 6) == 0) | |
1962 { | |
1963 *is_cygnus_app = TRUE; | |
1964 break; | |
1965 } | |
1966 } | |
1967 } | |
1968 #endif | |
1969 } | |
1970 | |
1971 unwind: | |
1972 close_file_data (&executable); | |
1973 } | |
1974 | |
1975 /* Close the system structures associated with the given file. */ | |
1976 void | |
1977 close_file_data (file_data *p_file) | |
1978 { | |
1979 UnmapViewOfFile (p_file->file_base); | |
1980 CloseHandle (p_file->file_mapping); | |
1981 CloseHandle (p_file->file); | |
1982 } | |
1983 | |
1984 | |
1985 /* Some miscellaneous functions that are Windows specific, but not GUI | |
1986 specific (ie. are applicable in terminal or batch mode as well). */ | |
1987 | |
1988 DEFUN ("mswindows-short-file-name", Fmswindows_short_file_name, 1, 1, "", /* | |
1989 Return the short file name version (8.3) of the full path of FILENAME. | |
1990 If FILENAME does not exist, return nil. | |
1991 All path elements in FILENAME are converted to their short names. | |
1992 */ | |
1993 (filename)) | |
1994 { | |
1995 Extbyte shortname[MAX_PATH * MAX_XETCHAR_SIZE]; | |
1996 Extbyte *fileext; | |
1997 Intbyte *shortint; | |
1998 | |
1999 CHECK_STRING (filename); | |
2000 | |
2001 /* first expand it. */ | |
2002 filename = Fexpand_file_name (filename, Qnil); | |
2003 | |
2004 LISP_STRING_TO_TSTR (filename, fileext); | |
2005 /* luckily, this returns the short version of each element in the path. */ | |
2006 if (qxeGetShortPathName (fileext, shortname, | |
2007 sizeof (shortname) / XETCHAR_SIZE) == 0) | |
2008 return Qnil; | |
2009 | |
2010 TSTR_TO_C_STRING (shortname, shortint); | |
2011 MSWINDOWS_NORMALIZE_FILENAME (shortint); | |
2012 | |
2013 return build_string (shortint); | |
2014 } | |
2015 | |
2016 | |
2017 DEFUN ("mswindows-long-file-name", Fmswindows_long_file_name, 1, 1, "", /* | |
2018 Return the long file name version of the full path of FILENAME. | |
2019 If FILENAME does not exist, return nil. | |
2020 All path elements in FILENAME are converted to their long names. | |
2021 */ | |
2022 (filename)) | |
2023 { | |
2024 Intbyte *longname, *canon; | |
2025 Lisp_Object ret; | |
2026 | |
2027 CHECK_STRING (filename); | |
2028 | |
2029 /* first expand it. */ | |
2030 filename = Fexpand_file_name (filename, Qnil); | |
2031 | |
2032 if (!(longname = mswindows_get_long_filename (XSTRING_DATA (filename)))) | |
2033 return Qnil; | |
2034 | |
2035 canon = mswindows_canonicalize_filename (longname); | |
2036 ret = build_string (canon); | |
2037 xfree (canon); | |
2038 xfree (longname); | |
2039 return ret; | |
2040 } | |
2041 | |
2042 | |
2043 void | |
2044 init_nt (void) | |
1752 { | 2045 { |
1753 /* Initial preparation for subprocess support: replace our standard | 2046 /* Initial preparation for subprocess support: replace our standard |
1754 handles with non-inheritable versions. */ | 2047 handles with non-inheritable versions. |
2048 | |
2049 #### Do we still need this? This is left over from the old process | |
2050 support. */ | |
1755 { | 2051 { |
1756 HANDLE parent; | 2052 HANDLE parent; |
1757 HANDLE stdin_save = INVALID_HANDLE_VALUE; | 2053 HANDLE stdin_save = INVALID_HANDLE_VALUE; |
1758 HANDLE stdout_save = INVALID_HANDLE_VALUE; | 2054 HANDLE stdout_save = INVALID_HANDLE_VALUE; |
1759 HANDLE stderr_save = INVALID_HANDLE_VALUE; | 2055 HANDLE stderr_save = INVALID_HANDLE_VALUE; |
1831 /* Reset the volume info cache. */ | 2127 /* Reset the volume info cache. */ |
1832 volume_cache = NULL; | 2128 volume_cache = NULL; |
1833 } | 2129 } |
1834 } | 2130 } |
1835 | 2131 |
1836 | |
1837 /*--------------------------------------------------------------------*/ | |
1838 /* Memory-mapped files */ | |
1839 /*--------------------------------------------------------------------*/ | |
1840 | |
1841 int | |
1842 open_input_file (file_data *p_file, const Intbyte *filename) | |
1843 { | |
1844 /* Synched with FSF 20.6. We fixed some warnings. */ | |
1845 HANDLE file; | |
1846 HANDLE file_mapping; | |
1847 void *file_base; | |
1848 DWORD size, upper_size; | |
1849 Extbyte *fileext; | |
1850 | |
1851 C_STRING_TO_TSTR (filename, fileext); | |
1852 | |
1853 file = qxeCreateFile (fileext, GENERIC_READ, FILE_SHARE_READ, NULL, | |
1854 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |
1855 if (file == INVALID_HANDLE_VALUE) | |
1856 return FALSE; | |
1857 | |
1858 size = GetFileSize (file, &upper_size); | |
1859 file_mapping = qxeCreateFileMapping (file, NULL, PAGE_READONLY, | |
1860 0, size, NULL); | |
1861 if (!file_mapping) | |
1862 return FALSE; | |
1863 | |
1864 file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size); | |
1865 if (file_base == 0) | |
1866 return FALSE; | |
1867 | |
1868 p_file->name = filename; | |
1869 p_file->size = size; | |
1870 p_file->file = file; | |
1871 p_file->file_mapping = file_mapping; | |
1872 p_file->file_base = file_base; | |
1873 | |
1874 return TRUE; | |
1875 } | |
1876 | |
1877 int | |
1878 open_output_file (file_data *p_file, const Intbyte *filename, | |
1879 unsigned long size) | |
1880 { | |
1881 /* Synched with FSF 20.6. We fixed some warnings. */ | |
1882 HANDLE file; | |
1883 HANDLE file_mapping; | |
1884 void *file_base; | |
1885 Extbyte *fileext; | |
1886 | |
1887 C_STRING_TO_TSTR (filename, fileext); | |
1888 | |
1889 file = qxeCreateFile (fileext, GENERIC_READ | GENERIC_WRITE, 0, NULL, | |
1890 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); | |
1891 if (file == INVALID_HANDLE_VALUE) | |
1892 return FALSE; | |
1893 | |
1894 file_mapping = qxeCreateFileMapping (file, NULL, PAGE_READWRITE, | |
1895 0, size, NULL); | |
1896 if (!file_mapping) | |
1897 return FALSE; | |
1898 | |
1899 file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size); | |
1900 if (file_base == NULL) | |
1901 return FALSE; | |
1902 | |
1903 p_file->name = filename; | |
1904 p_file->size = size; | |
1905 p_file->file = file; | |
1906 p_file->file_mapping = file_mapping; | |
1907 p_file->file_base = file_base; | |
1908 | |
1909 return TRUE; | |
1910 } | |
1911 | |
1912 #if 1 /* !defined(MINGW) */ | |
1913 /* Return pointer to section header for section containing the given | |
1914 relative virtual address. */ | |
1915 static IMAGE_SECTION_HEADER * | |
1916 rva_to_section (DWORD rva, IMAGE_NT_HEADERS *nt_header) | |
1917 { | |
1918 /* Synched with FSF 20.6. We added MINGW stuff. */ | |
1919 PIMAGE_SECTION_HEADER section; | |
1920 int i; | |
1921 | |
1922 section = IMAGE_FIRST_SECTION (nt_header); | |
1923 | |
1924 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) | |
1925 { | |
1926 /* Some linkers (eg. the NT SDK linker I believe) swapped the | |
1927 meaning of these two values - or rather, they ignored | |
1928 VirtualSize entirely and always set it to zero. This affects | |
1929 some very old exes (eg. gzip dated Dec 1993). Since | |
1930 mswindows_executable_type relies on this function to work reliably, | |
1931 we need to cope with this. */ | |
1932 DWORD real_size = max (section->SizeOfRawData, | |
1933 section->Misc.VirtualSize); | |
1934 if (rva >= section->VirtualAddress | |
1935 && rva < section->VirtualAddress + real_size) | |
1936 return section; | |
1937 section++; | |
1938 } | |
1939 return NULL; | |
1940 } | |
1941 #endif | |
1942 | |
1943 void | |
1944 mswindows_executable_type (const Intbyte *filename, int *is_dos_app, | |
1945 int *is_cygnus_app) | |
1946 { | |
1947 /* Synched with FSF 20.6. We added MINGW stuff and casts. */ | |
1948 file_data executable; | |
1949 Intbyte *p; | |
1950 | |
1951 /* Default values in case we can't tell for sure. */ | |
1952 *is_dos_app = FALSE; | |
1953 *is_cygnus_app = FALSE; | |
1954 | |
1955 if (!open_input_file (&executable, filename)) | |
1956 return; | |
1957 | |
1958 p = qxestrrchr (filename, '.'); | |
1959 | |
1960 /* We can only identify DOS .com programs from the extension. */ | |
1961 if (p && qxestrcasecmp (p, ".com") == 0) | |
1962 *is_dos_app = TRUE; | |
1963 else if (p && (qxestrcasecmp (p, ".bat") == 0 || | |
1964 qxestrcasecmp (p, ".cmd") == 0)) | |
1965 { | |
1966 /* A DOS shell script - it appears that CreateProcess is happy to | |
1967 accept this (somewhat surprisingly); presumably it looks at | |
1968 COMSPEC to determine what executable to actually invoke. | |
1969 Therefore, we have to do the same here as well. */ | |
1970 /* Actually, I think it uses the program association for that | |
1971 extension, which is defined in the registry. */ | |
1972 p = egetenv ("COMSPEC"); | |
1973 if (p) | |
1974 mswindows_executable_type (p, is_dos_app, is_cygnus_app); | |
1975 } | |
1976 else | |
1977 { | |
1978 /* Look for DOS .exe signature - if found, we must also check that | |
1979 it isn't really a 16- or 32-bit Windows exe, since both formats | |
1980 start with a DOS program stub. Note that 16-bit Windows | |
1981 executables use the OS/2 1.x format. */ | |
1982 | |
1983 #if 0 /* defined( MINGW ) */ | |
1984 /* mingw doesn't have enough headers to detect cygwin | |
1985 apps, just do what we can. */ | |
1986 FILHDR *exe_header; | |
1987 | |
1988 exe_header = (FILHDR *) executable.file_base; | |
1989 if (exe_header->e_magic != DOSMAGIC) | |
1990 goto unwind; | |
1991 | |
1992 if ((char *) exe_header->e_lfanew > (char *) executable.size) | |
1993 { | |
1994 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
1995 *is_dos_app = TRUE; | |
1996 } | |
1997 else if (exe_header->nt_signature != NT_SIGNATURE) | |
1998 { | |
1999 *is_dos_app = TRUE; | |
2000 } | |
2001 #else | |
2002 IMAGE_DOS_HEADER *dos_header; | |
2003 IMAGE_NT_HEADERS *nt_header; | |
2004 | |
2005 dos_header = (PIMAGE_DOS_HEADER) executable.file_base; | |
2006 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) | |
2007 goto unwind; | |
2008 | |
2009 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + | |
2010 dos_header->e_lfanew); | |
2011 | |
2012 if ((char *) nt_header > (char *) dos_header + executable.size) | |
2013 { | |
2014 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
2015 *is_dos_app = TRUE; | |
2016 } | |
2017 else if (nt_header->Signature != IMAGE_NT_SIGNATURE && | |
2018 LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE) | |
2019 { | |
2020 *is_dos_app = TRUE; | |
2021 } | |
2022 else if (nt_header->Signature == IMAGE_NT_SIGNATURE) | |
2023 { | |
2024 /* Look for cygwin.dll in DLL import list. */ | |
2025 IMAGE_DATA_DIRECTORY import_dir = | |
2026 nt_header->OptionalHeader. | |
2027 DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; | |
2028 IMAGE_IMPORT_DESCRIPTOR *imports; | |
2029 IMAGE_SECTION_HEADER *section; | |
2030 | |
2031 section = rva_to_section (import_dir.VirtualAddress, nt_header); | |
2032 imports = | |
2033 (IMAGE_IMPORT_DESCRIPTOR *) RVA_TO_PTR (import_dir.VirtualAddress, | |
2034 section, executable); | |
2035 | |
2036 for ( ; imports->Name; imports++) | |
2037 { | |
2038 Extbyte *dllname_ext = | |
2039 (Extbyte *) RVA_TO_PTR (imports->Name, section, executable); | |
2040 Intbyte *dllname; | |
2041 | |
2042 EXTERNAL_TO_C_STRING (dllname_ext, dllname, Qbinary); | |
2043 | |
2044 /* The exact name of the cygwin dll has changed with | |
2045 various releases, but hopefully this will be reasonably | |
2046 future proof. */ | |
2047 if (qxestrncasecmp (dllname, (Intbyte *) "cygwin", 6) == 0) | |
2048 { | |
2049 *is_cygnus_app = TRUE; | |
2050 break; | |
2051 } | |
2052 } | |
2053 } | |
2054 #endif | |
2055 } | |
2056 | |
2057 unwind: | |
2058 close_file_data (&executable); | |
2059 } | |
2060 | |
2061 /* Close the system structures associated with the given file. */ | |
2062 void | |
2063 close_file_data (file_data *p_file) | |
2064 { | |
2065 UnmapViewOfFile (p_file->file_base); | |
2066 CloseHandle (p_file->file_mapping); | |
2067 CloseHandle (p_file->file); | |
2068 } | |
2069 | |
2070 | |
2071 /* Some miscellaneous functions that are Windows specific, but not GUI | |
2072 specific (ie. are applicable in terminal or batch mode as well). */ | |
2073 | |
2074 DEFUN ("mswindows-short-file-name", Fmswindows_short_file_name, 1, 1, "", /* | |
2075 Return the short file name version (8.3) of the full path of FILENAME. | |
2076 If FILENAME does not exist, return nil. | |
2077 All path elements in FILENAME are converted to their short names. | |
2078 */ | |
2079 (filename)) | |
2080 { | |
2081 Extbyte shortname[MAX_PATH * MAX_XETCHAR_SIZE]; | |
2082 Extbyte *fileext; | |
2083 Intbyte *shortint; | |
2084 | |
2085 CHECK_STRING (filename); | |
2086 | |
2087 /* first expand it. */ | |
2088 filename = Fexpand_file_name (filename, Qnil); | |
2089 | |
2090 LISP_STRING_TO_TSTR (filename, fileext); | |
2091 /* luckily, this returns the short version of each element in the path. */ | |
2092 if (qxeGetShortPathName (fileext, shortname, | |
2093 sizeof (shortname) / XETCHAR_SIZE) == 0) | |
2094 return Qnil; | |
2095 | |
2096 TSTR_TO_C_STRING (shortname, shortint); | |
2097 MSWINDOWS_NORMALIZE_FILENAME (shortint); | |
2098 | |
2099 return build_string (shortint); | |
2100 } | |
2101 | |
2102 | |
2103 DEFUN ("mswindows-long-file-name", Fmswindows_long_file_name, 1, 1, "", /* | |
2104 Return the long file name version of the full path of FILENAME. | |
2105 If FILENAME does not exist, return nil. | |
2106 All path elements in FILENAME are converted to their long names. | |
2107 */ | |
2108 (filename)) | |
2109 { | |
2110 Intbyte *longname, *canon; | |
2111 Lisp_Object ret; | |
2112 | |
2113 CHECK_STRING (filename); | |
2114 | |
2115 /* first expand it. */ | |
2116 filename = Fexpand_file_name (filename, Qnil); | |
2117 | |
2118 if (!(longname = mswindows_get_long_filename (XSTRING_DATA (filename)))) | |
2119 return Qnil; | |
2120 | |
2121 canon = mswindows_canonicalize_filename (longname); | |
2122 ret = build_string (canon); | |
2123 xfree (canon); | |
2124 xfree (longname); | |
2125 return ret; | |
2126 } | |
2127 | |
2128 void | 2132 void |
2129 syms_of_nt (void) | 2133 syms_of_nt (void) |
2130 { | 2134 { |
2131 DEFSUBR (Fmswindows_short_file_name); | 2135 DEFSUBR (Fmswindows_short_file_name); |
2132 DEFSUBR (Fmswindows_long_file_name); | 2136 DEFSUBR (Fmswindows_long_file_name); |