* 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.
This commit is contained in:
Christopher Faylor
2008-03-27 01:50:40 +00:00
parent 73de02f44b
commit 93d606f60a
11 changed files with 143 additions and 16 deletions

View File

@ -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)
{