From 93d606f60aed779c555017828656c8a4e3c9c6a9 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Thu, 27 Mar 2008 01:50:40 +0000 Subject: * 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. --- winsup/cygwin/hookapi.cc | 79 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 5 deletions(-) (limited to 'winsup/cygwin/hookapi.cc') 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 +#include +#include +#include "ntdll.h" #include "cygerrno.h" #include "security.h" #include "path.h" #include "fhandler.h" #include "dtable.h" #include "cygheap.h" -#include -#include -#include +#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) { -- cgit v1.2.3