diff options
author | Christopher Faylor <me@cgf.cx> | 2008-03-27 01:50:40 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2008-03-27 01:50:40 +0000 |
commit | 93d606f60aed779c555017828656c8a4e3c9c6a9 (patch) | |
tree | a1064ee801fa9606f9c06a4dc7f03f79db0314d9 /winsup/cygwin/hookapi.cc | |
parent | 73de02f44b83eeccdacf7b803cc37074660f75b2 (diff) | |
download | cygnal-93d606f60aed779c555017828656c8a4e3c9c6a9.tar.gz cygnal-93d606f60aed779c555017828656c8a4e3c9c6a9.tar.bz2 cygnal-93d606f60aed779c555017828656c8a4e3c9c6a9.zip |
* hookapi.cc (find_first_notloaded_dll): New function.
* pinfo.cc (status_exit): New function. Issue message when dll not found. Use
find_first_notloaded_dll to find a nonexistent dll.
(pinfo::maybe_set_exit_code_from_windows): Call status_exit when exit code >=
0xc0000000UL.
* sigproc.cc (child_info::proc_retry): Return exit code when
STATUS_DLL_NOT_FOUND.
* spawn.cc (spawn_guts): Minor cleanup.
* syscalls.cc (close_all_files): Don't actually close stderr filehandle. Just
make it noninheritable.
* winsup.h (find_first_notloaded_dll): Declare new function.
* ntdll.h: Add several missing NTSTATUS defines.
Diffstat (limited to 'winsup/cygwin/hookapi.cc')
-rw-r--r-- | winsup/cygwin/hookapi.cc | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/winsup/cygwin/hookapi.cc b/winsup/cygwin/hookapi.cc index 975879bf6..2e9ba0ece 100644 --- a/winsup/cygwin/hookapi.cc +++ b/winsup/cygwin/hookapi.cc @@ -1,6 +1,6 @@ /* hookapi.cc - Copyright 2005, 2006 Red Hat, Inc. + Copyright 2005, 2006, 2007, 2008 Red Hat, Inc. This file is part of Cygwin. @@ -9,15 +9,17 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ #include "winsup.h" +#include <imagehlp.h> +#include <stdlib.h> +#include <alloca.h> +#include "ntdll.h" #include "cygerrno.h" #include "security.h" #include "path.h" #include "fhandler.h" #include "dtable.h" #include "cygheap.h" -#include <stdlib.h> -#include <imagehlp.h> -#include <alloca.h> +#include "pinfo.h" #define rva(coerce, base, addr) (coerce) ((char *) (base) + (addr)) #define rvacyg(coerce, addr) rva (coerce, cygwin_hmodule, addr) @@ -158,7 +160,74 @@ makename (const char *name, char *&buf, int& i, int inc) return name; } -// Top level routine to find the EXE's imports, and redirect them +/* Find first missing dll in a given executable. + FIXME: This is not foolproof since it doesn't look for dlls in the + same directory as the given executable, like Windows. Instead it + searches for dlls in the context of the current executable. */ +const char * +find_first_notloaded_dll (path_conv& pc) +{ + const char *res = "?"; + HANDLE hc = NULL; + HMODULE hm = NULL; + OBJECT_ATTRIBUTES attr; + IO_STATUS_BLOCK io; + HANDLE h; + NTSTATUS status; + + status = NtOpenFile (&h, SYNCHRONIZE | GENERIC_READ, + pc.get_object_attr (attr, sec_none_nih), + &io, FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_FOR_BACKUP_INTENT + | FILE_NON_DIRECTORY_FILE); + if (!NT_SUCCESS (status)) + goto out; + + hc = CreateFileMapping (h, &sec_none_nih, PAGE_READONLY, 0, 0, NULL); + NtClose (h); + if (!hc) + goto out; + hm = (HMODULE) MapViewOfFile(hc, FILE_MAP_READ, 0, 0, 0); + CloseHandle (hc); + + PIMAGE_NT_HEADERS pExeNTHdr; + pExeNTHdr = PEHeaderFromHModule (hm); + + if (!pExeNTHdr) + goto out; + + DWORD importRVA; + importRVA = pExeNTHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; + if (!importRVA) + goto out; + + long delta = rvadelta (pExeNTHdr, importRVA); + + // Convert imports RVA to a usable pointer + PIMAGE_IMPORT_DESCRIPTOR pdfirst; + pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, hm, importRVA - delta); + + // Iterate through each import descriptor, and redirect if appropriate + for (PIMAGE_IMPORT_DESCRIPTOR pd = pdfirst; pd->FirstThunk; pd++) + { + const char *lib = rva (PSTR, hm, pd->Name - delta); + if (!LoadLibraryEx (lib, NULL, DONT_RESOLVE_DLL_REFERENCES + | LOAD_LIBRARY_AS_DATAFILE)) + { + static char buf[NT_MAX_PATH]; + res = strcpy (buf, lib); + } + } + +out: + if (hm) + UnmapViewOfFile (hm); + + return res; +} + +// Top level routine to find the EXE's imports and redirect them void * hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys) { |