diff options
-rw-r--r-- | winsup/cygwin/ChangeLog | 19 | ||||
-rw-r--r-- | winsup/cygwin/Makefile.in | 45 | ||||
-rw-r--r-- | winsup/cygwin/how-autoload-works.txt | 66 | ||||
-rw-r--r-- | winsup/cygwin/path.cc | 91 | ||||
-rw-r--r-- | winsup/cygwin/path.h | 3 | ||||
-rw-r--r-- | winsup/cygwin/shortcut.c | 170 | ||||
-rw-r--r-- | winsup/cygwin/shortcut.h | 28 | ||||
-rw-r--r-- | winsup/cygwin/winsup.h | 4 |
8 files changed, 199 insertions, 227 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 04bf33a76a4..42d55190969 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,20 @@ +2002-09-06 Christopher Faylor <cgf@redhat.com> + + * winsup.h (_WIN32_WINNT): Protect. + +2002-09-06 Christopher Faylor <cgf@redhat.com> + + * winsup.h (_WIN32_WINNT): Define. + +2002-09-03 Corinna Vinschen <corinna@vinschen.de> + + * Makefile.in (DLL_OFILES): Drop shortcut.o. + * path.cc: Move all shortcut functions from shortcut.c to here. + (check_shortcut): Implement without using COM interface. + * path.h: Move definition of SHORTCUT_HDR_SIZE to here. + * shortcut.c: Remove. + * shortcut.h: Ditto. + 2002-09-03 Conrad Scott <conrad.scott@dsl.pipex.com> * fhandler.h (fhandler_socket::read): Remove method. @@ -47,7 +64,7 @@ (fhandler_tty_slave::read): Don't do anything special with vtime when vmin == 0. -2002-07-25 Egor Duda <deo@logos-m.ru> +2002-08-30 Egor Duda <deo@logos-m.ru> * autoload.cc (GetConsoleWindow): Correct parameter count. diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 2bba7a71d37..86db505aae3 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -118,29 +118,28 @@ MALLOC_OFILES=@MALLOC_OFILES@ DLL_IMPORTS:=$(w32api_lib)/libuuid.a $(w32api_lib)/libshell32.a $(w32api_lib)/libkernel32.a # Please maintain this list in sorted order, with maximum files per 80 col line - -DLL_OFILES:=assert.o autoload.o cygheap.o cygserver_client.o \ - cygserver_transport.o cygserver_transport_pipes.o \ - cygserver_transport_sockets.o cygthread.o dcrt0.o debug.o \ - delqueue.o dir.o dlfcn.o dll_init.o dtable.o environ.o errno.o \ - exceptions.o exec.o external.o fcntl.o fhandler.o \ - fhandler_clipboard.o fhandler_console.o fhandler_disk_file.o \ - fhandler_dsp.o fhandler_floppy.o fhandler_mem.o \ - fhandler_proc.o fhandler_process.o fhandler_random.o \ - fhandler_raw.o fhandler_registry.o fhandler_serial.o \ - fhandler_socket.o fhandler_tape.o fhandler_termios.o \ - fhandler_tty.o fhandler_virtual.o fhandler_windows.o \ - fhandler_zero.o fnmatch.o fork.o glob.o grp.o heap.o init.o \ - ioctl.o ipc.o localtime.o malloc.o malloc_wrapper.o \ - miscfuncs.o mmap.o msg.o \ - net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o pthread.o \ - regcomp.o regerror.o regexec.o regfree.o registry.o resource.o \ - scandir.o sched.o sec_acl.o sec_helper.o security.o select.o \ - sem.o shared.o shm.o shortcut.o signal.o sigproc.o \ - smallprint.o spawn.o strace.o strsep.o sync.o syscalls.o \ - sysconf.o syslog.o termios.o thread.o times.o tty.o uinfo.o \ - uname.o v8_regexp.o v8_regerror.o v8_regsub.o wait.o wincap.o \ - window.o \ +DLL_OFILES:= \ + assert.o autoload.o cygheap.o cygserver_client.o \ + cygserver_transport.o cygserver_transport_pipes.o \ + cygserver_transport_sockets.o cygthread.o dcrt0.o debug.o \ + delqueue.o dir.o dlfcn.o dll_init.o dtable.o environ.o errno.o \ + exceptions.o exec.o external.o fcntl.o fhandler.o \ + fhandler_clipboard.o fhandler_console.o fhandler_disk_file.o \ + fhandler_dsp.o fhandler_floppy.o fhandler_mem.o \ + fhandler_proc.o fhandler_process.o fhandler_random.o \ + fhandler_raw.o fhandler_registry.o fhandler_serial.o \ + fhandler_socket.o fhandler_tape.o fhandler_termios.o \ + fhandler_tty.o fhandler_virtual.o fhandler_windows.o \ + fhandler_zero.o fnmatch.o fork.o glob.o grp.o heap.o init.o \ + ioctl.o ipc.o localtime.o malloc.o malloc_wrapper.o \ + miscfuncs.o mmap.o msg.o net.o ntea.o passwd.o path.o pinfo.o \ + pipe.o poll.o pthread.o regcomp.o regerror.o regexec.o \ + regfree.o registry.o resource.o scandir.o sched.o sec_acl.o \ + sec_helper.o security.o select.o sem.o shared.o shm.o signal.o \ + sigproc.o smallprint.o spawn.o strace.o strsep.o sync.o \ + syscalls.o sysconf.o syslog.o termios.o thread.o times.o tty.o \ + uinfo.o uname.o v8_regexp.o v8_regerror.o v8_regsub.o wait.o \ + wincap.o window.o \ $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS) GMON_OFILES:=gmon.o mcount.o profil.o diff --git a/winsup/cygwin/how-autoload-works.txt b/winsup/cygwin/how-autoload-works.txt new file mode 100644 index 00000000000..27c2426d877 --- /dev/null +++ b/winsup/cygwin/how-autoload-works.txt @@ -0,0 +1,66 @@ +Copyright 2002 Red Hat Inc., Egor Duda + +How does function autoloading work? + +Cygwin has the ability to handle win32 functions which are present on +some platforms and not present on others via autoload mechanism. It's +essentially a lazy binding of symbols. It works as following. For +(almost) every function from OS API which cygwin uses, a stub is created +in file autoload.cc. Each reference to the such function from win32 API +in cygwin dll source code is actually pointing to this stub. + +When the function, say GetConsoleWindow(), is called for the first time, +the control is passed to its stub. The stub tries to load the +appropriate system dll via LoadModule() and get the actual function +address via GetProcAddress(). If this operation succeeds, the stub is +"patched" to pass control to actual address of GetConsoleWindow() in +appropriate system dll, so that next time we won't have to load dll and +perform address lookup in it again. From this point on, the call to the +function is performed as if the dll/function were linked statically. + +If LoadModule() or GetProcAddress() fail, (and on nt4 the latter indeed +fails because GetConsoleWindow() is not available in kernel32.dll), then +the application, depending on what kind of stub is created in +autoload.cc, will either: + +1) Exit with fatal error. + +2) Or return a predefined value indicating an error; and set the windows +error code to 127 (ERROR_PROC_NOT_FOUND). + +Almost all w32api functions are linked into the cygwin dll in this +manner, dynamically, at runtime. + +The costs: +1) A tiny overhead in the initial call to a function call as each call +is performed, indirectly, via a stub. For the first lookup of a symbol +of an unloaded dll, there is also some overhead in loading the dll for +the first time. The dll is only loaded by the first call to a symbol +in the dll. After the first call to a function, subsequent calls are +as fast as a normal, statically loaded function. + +The benefits: +1) Speedup at startup time. Applications only load those dlls which are +actually needed. For example, if application never uses socket +functions, winsock dlls are never loaded. + +2) Greatly simplify wincap system -- we don't need to have a separate +capability for every win32 function which may or may not be present on +particular win32 platform. + +3) Allows a single cygwin1.dll for all win32 platforms. + +If you're changing in cygwin1.dll source code and if you use some +function that was not used there before, you should add a stub so it +will be autoloaded. To do so, add one of the LoadDllfunc* macros to +autoload.cc. All macros eventually resolve to the following form: + +LoadDLLfuncEx2 (function name, parameter block length, dll name, + non-fatality flag , value to return if function not available) + +Parameter block length is a sum of sizes (in bytes) of parameters which are +being passed to the function. If non-fatality flag is set to 0, then failure +to load dll and find a function will cause fatal error. If non fatality flag +is set to 1, then call to the function will return default value. +You can also use shorter versions -- LoadDLLfuncEx and LoadDLLfunc, if the +defaults they provide suit your needs. diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index f4527afd847..eea04ab1ba7 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -74,7 +74,6 @@ details. */ #include "shared_info.h" #include "registry.h" #include <assert.h> -#include "shortcut.h" #ifdef _MT_SAFE #define iteration _reent_winsup ()->_iteration @@ -105,6 +104,26 @@ struct symlink_info int pcheck_case = PCHECK_RELAXED; /* Determines the case check behaviour. */ +static char shortcut_header[SHORTCUT_HDR_SIZE]; +static BOOL shortcut_initalized; + +static void +create_shortcut_header (void) +{ + if (!shortcut_initalized) + { + shortcut_header[0] = 'L'; + shortcut_header[4] = '\001'; + shortcut_header[5] = '\024'; + shortcut_header[6] = '\002'; + shortcut_header[12] = '\300'; + shortcut_header[19] = 'F'; + shortcut_header[20] = '\f'; + shortcut_header[60] = '\001'; + shortcut_initalized = TRUE; + } +} + #define CYGWIN_REGNAME (cygheap->cygwin_regname ?: CYGWIN_INFO_CYGWIN_REGISTRY_NAME) /* Determine if path prefix matches current cygdrive */ @@ -387,7 +406,7 @@ path_conv::fillin (HANDLE h) fs.serial = local.dwVolumeSerialNumber; } fs.drive_type = DRIVE_UNKNOWN; -} +} /* Convert an arbitrary path SRC to a pure Win32 path, suitable for passing to Win32 API routines. @@ -2622,7 +2641,7 @@ symlink (const char *topath, const char *frompath) set_security_attribute (S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO, &sa, alloca (4096), 4096); - h = CreateFileA(win32_path, GENERIC_WRITE, 0, &sa, + h = CreateFile (win32_path, GENERIC_WRITE, 0, &sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); if (h == INVALID_HANDLE_VALUE) __seterrno (); @@ -2696,6 +2715,68 @@ done: return res; } +static BOOL +cmp_shortcut_header (const char *file_header) +{ + create_shortcut_header (); + return memcmp (shortcut_header, file_header, SHORTCUT_HDR_SIZE); +} + +static int +check_shortcut (const char *path, DWORD fileattr, HANDLE h, + char *contents, int *error, unsigned *pflags) +{ + char file_header[SHORTCUT_HDR_SIZE]; + unsigned short len; + int res = 0; + DWORD got = 0; + + /* Valid Cygwin & U/WIN shortcuts are R/O. */ + if (!(fileattr & FILE_ATTRIBUTE_READONLY)) + goto file_not_symlink; + /* Read the files header information. This is used to check for a + Cygwin or U/WIN shortcut or later to check for executable files. */ + if (!ReadFile (h, file_header, SHORTCUT_HDR_SIZE, &got, 0)) + { + *error = EIO; + goto close_it; + } + /* Check header if the shortcut is really created by Cygwin or U/WIN. */ + if (got != SHORTCUT_HDR_SIZE || cmp_shortcut_header (file_header)) + goto file_not_symlink; + /* Next 2 byte are USHORT, containing length of description entry. */ + if (!ReadFile (h, &len, sizeof len, &got, 0)) + { + *error = EIO; + goto close_it; + } + if (got != sizeof len || len == 0 || len > MAX_PATH) + goto file_not_symlink; + /* Now read description entry. */ + if (!ReadFile (h, contents, len, &got, 0)) + { + *error = EIO; + goto close_it; + } + if (got != len) + goto file_not_symlink; + contents[len] = '\0'; + res = len; + if (res) /* It's a symlink. */ + *pflags = PATH_SYMLINK; + goto close_it; + +file_not_symlink: + /* Not a symlink, see if executable. */ + if (!(*pflags & PATH_ALL_EXEC) && has_exec_chars (file_header, got)) + *pflags |= PATH_EXEC; + +close_it: + CloseHandle (h); + return res; +} + + static int check_sysfile (const char *path, DWORD fileattr, HANDLE h, char *contents, int *error, unsigned *pflags) @@ -2956,8 +3037,8 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt) /* Open the file. */ - h = CreateFileA (suffix.path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, 0); + h = CreateFile (suffix.path, GENERIC_READ, FILE_SHARE_READ, + &sec_none_nih, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); res = -1; if (h == INVALID_HANDLE_VALUE) goto file_not_symlink; diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index f9f55035e78..c8bb7ceadb9 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -170,6 +170,9 @@ class path_conv /* Socket marker */ #define SOCKET_COOKIE "!<socket >" +/* The sizeof header written to a shortcut by Cygwin or U/WIN. */ +#define SHORTCUT_HDR_SIZE 76 + /* Maximum depth of symlinks (after which ELOOP is issued). */ #define MAX_LINK_DEPTH 10 int __stdcall slash_unc_prefix_p (const char *path) __attribute__ ((regparm(1))); diff --git a/winsup/cygwin/shortcut.c b/winsup/cygwin/shortcut.c deleted file mode 100644 index 55710e86b22..00000000000 --- a/winsup/cygwin/shortcut.c +++ /dev/null @@ -1,170 +0,0 @@ -/* shortcut.c: Read shortcuts. This part of the code must be in C because - the C++ interface to COM doesn't work without -fvtable-thunk - which is too dangerous to use. - - Copyright 2001 Red Hat, Inc. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#define WIN32_LEAN_AND_MEAN -#include "winsup.h" -#include <shlobj.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/mount.h> -#include <errno.h> -#include "shortcut.h" - -/* TODO: - Currently duplicated from path.h. Later rearrangement of path.h - to allow including from plain C would be better. */ -/* This is needed to avoid including path.h which is a pure C++ header. */ -#define PATH_SYMLINK MOUNT_SYMLINK -#define PATH_EXEC MOUNT_EXEC -#define PATH_CYGWIN_EXEC MOUNT_CYGWIN_EXEC -#define PATH_ALL_EXEC (PATH_CYGWIN_EXEC | PATH_EXEC) - -/* TODO: Ditto. */ -static BOOL -has_exec_chars (const char *buf, int len) -{ - return len >= 2 && - ((buf[0] == '#' && buf[1] == '!') || - (buf[0] == ':' && buf[1] == '\n') || - (buf[0] == 'M' && buf[1] == 'Z')); -} - -char shortcut_header[SHORTCUT_HDR_SIZE]; -BOOL shortcut_initalized; - -void -create_shortcut_header (void) -{ - if (!shortcut_initalized) - { - shortcut_header[0] = 'L'; - shortcut_header[4] = '\001'; - shortcut_header[5] = '\024'; - shortcut_header[6] = '\002'; - shortcut_header[12] = '\300'; - shortcut_header[19] = 'F'; - shortcut_header[20] = '\f'; - shortcut_header[60] = '\001'; - shortcut_initalized = TRUE; - } -} - -static BOOL -cmp_shortcut_header (const char *file_header) -{ - create_shortcut_header (); - return memcmp (shortcut_header, file_header, SHORTCUT_HDR_SIZE); -} - -int -check_shortcut (const char *path, DWORD fileattr, HANDLE h, - char *contents, int *error, unsigned *pflags) -{ - HRESULT hres; - IShellLink *psl = NULL; - IPersistFile *ppf = NULL; - WCHAR wc_path[MAX_PATH]; - char file_header[SHORTCUT_HDR_SIZE]; - DWORD len = 0; - int res = 0; - DWORD got = 0; - - /* Initialize COM library. */ - CoInitialize (NULL); - - /* Get a pointer to the IShellLink interface. */ - hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - &IID_IShellLink, (void **)&psl); - if (FAILED (hres)) - goto close_it; - /* Get a pointer to the IPersistFile interface. */ - hres = psl->lpVtbl->QueryInterface (psl, &IID_IPersistFile, (void **)&ppf); - if (FAILED (hres)) - goto close_it; - /* Load the shortcut. */ - MultiByteToWideChar(CP_ACP, 0, path, -1, wc_path, MAX_PATH); - hres = ppf->lpVtbl->Load (ppf, wc_path, STGM_READ); - if (FAILED (hres)) - goto close_it; - /* Read the files header information. This is used to check for a - Cygwin or U/WIN shortcut or later to check for executable files. */ - if (!ReadFile (h, file_header, SHORTCUT_HDR_SIZE, &got, 0)) - { - *error = EIO; - goto close_it; - } - /* Try the description (containing a POSIX path) first. */ - if (fileattr & FILE_ATTRIBUTE_READONLY) - { - /* Check header if the shortcut is really created by Cygwin or U/WIN. */ - if (got == SHORTCUT_HDR_SIZE && !cmp_shortcut_header (file_header)) - { - hres = psl->lpVtbl->GetDescription (psl, contents, MAX_PATH); - if (FAILED (hres)) - goto file_not_symlink; - len = strlen (contents); - } - } -#if TREAT_NATIVE_SHORTCUTS_AS_SYMLINKS - /* No description or not R/O: Check the "official" path. */ - if (len == 0) - { - char full_path[MAX_PATH]; - WIN32_FIND_DATA wfd; - - /* Convert to full path (easy way) */ - if ((path[0] == '\\' && path[1] == '\\') - || (_toupper (path[0]) >= 'A' && _toupper (path[0]) <= 'Z' - && path[1] == ':')) - len = 0; - else - { - len = GetCurrentDirectory (MAX_PATH, full_path); - if (path[0] == '\\') - len = 2; - else if (full_path[len - 1] != '\\') - strcpy (full_path + len++, "\\"); - } - strcpy (full_path + len, path); - /* Set relative path inside of IShellLink interface. */ - hres = psl->lpVtbl->SetRelativePath (psl, full_path, 0); - if (FAILED (hres)) - goto file_not_symlink; - /* Get the path to the shortcut target. */ - hres = psl->lpVtbl->GetPath (psl, contents, MAX_PATH, &wfd, 0); - if (FAILED(hres)) - goto file_not_symlink; - } -#endif - res = strlen (contents); - if (res) /* It's a symlink. */ - *pflags = PATH_SYMLINK; - goto close_it; - -file_not_symlink: - /* Not a symlink, see if executable. */ - if (!(*pflags & PATH_ALL_EXEC) && has_exec_chars (file_header, got)) - *pflags |= PATH_EXEC; - -close_it: - /* Release the pointer to IPersistFile. */ - if (ppf) - ppf->lpVtbl->Release(ppf); - /* Release the pointer to IShellLink. */ - if (psl) - psl->lpVtbl->Release(psl); - /* Uninitialize COM library. */ - CoUninitialize (); - CloseHandle (h); - - return res; -} diff --git a/winsup/cygwin/shortcut.h b/winsup/cygwin/shortcut.h deleted file mode 100644 index 447e320b4a4..00000000000 --- a/winsup/cygwin/shortcut.h +++ /dev/null @@ -1,28 +0,0 @@ -/* shortcut.h: Header file for shortcut.c - - Copyright 2001 Red Hat, Inc. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* The header written to a shortcut by Cygwin or U/WIN. */ -#define SHORTCUT_HDR_SIZE 76 - -extern char shortcut_header[]; -extern BOOL shortcut_initalized; - -extern void create_shortcut_header (); - -int check_shortcut (const char *path, DWORD fileattr, HANDLE h, - char *contents, int *error, unsigned *pflags); - -#ifdef __cplusplus -}; -#endif diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 9e39728cca0..18aaf8a9e66 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -31,6 +31,10 @@ details. */ #define NEW_MACRO_VARARGS #endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + #include <sys/types.h> #include <sys/strace.h> |