Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2008-03-27 04:50:40 +0300
committerChristopher Faylor <me@cgf.cx>2008-03-27 04:50:40 +0300
commit93d606f60aed779c555017828656c8a4e3c9c6a9 (patch)
treea1064ee801fa9606f9c06a4dc7f03f79db0314d9 /winsup/cygwin/hookapi.cc
parent73de02f44b83eeccdacf7b803cc37074660f75b2 (diff)
* 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.cc79
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)
{