diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ccb0f2c61..d4a4f12ac 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,14 @@
+2011-05-11  Corinna Vinschen  <corinna@vinschen.de>
+
+	* autoload.cc (EnumProcessModules): Remove.
+	* dlfcn.cc (dlopen): Make sure errno is set if an error occurs.
+	(dlsym): Rewrite using RtlQueryProcessDebugInformation instead of
+	EnumProcessModules.
+	* ntdll.h (struct _DEBUG_MODULE_ARRAY): Define.
+	(RtlCreateQueryDebugBuffer): Declare.
+	(RtlDestroyQueryDebugBuffer): Declare.
+	(RtlQueryProcessDebugInformation): Declare.
+
 2011-05-11  Corinna Vinschen  <corinna@vinschen.de>
 
 	* autoload.cc (GetModuleFileNameExW): Remove.
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 5cf9cf36c..cb8c5bf35 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -414,8 +414,6 @@ LoadDLLfunc (RtlSetCurrentTransaction, 4, ntdll)
 
 LoadDLLfunc (CoTaskMemFree, 4, ole32)
 
-LoadDLLfunc (EnumProcessModules, 16, psapi)
-
 LoadDLLfunc (LsaDeregisterLogonProcess, 4, secur32)
 LoadDLLfunc (LsaFreeReturnBuffer, 4, secur32)
 LoadDLLfunc (LsaLogonUser, 56, secur32)
diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc
index fb3df2c5f..6d4580e9e 100644
--- a/winsup/cygwin/dlfcn.cc
+++ b/winsup/cygwin/dlfcn.cc
@@ -1,6 +1,7 @@
 /* dlfcn.cc
 
-   Copyright 1998, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010 Red Hat, Inc.
+   Copyright 1998, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010,
+   2011 Red Hat, Inc.
 
 This file is part of Cygwin.
 
@@ -17,6 +18,7 @@ details. */
 #include "dlfcn.h"
 #include "cygtls.h"
 #include "tls_pbuf.h"
+#include "ntdll.h"
 
 static void __stdcall
 set_dl_error (const char *str)
@@ -71,7 +73,11 @@ dlopen (const char *name, int)
   void *ret;
 
   if (name == NULL)
-    ret = (void *) GetModuleHandle (NULL); /* handle for the current module */
+    {
+      ret = (void *) GetModuleHandle (NULL); /* handle for the current module */
+      if (!ret)
+      	__seterrno ();
+    }
   else
     {
       /* handle for the named library */
@@ -112,7 +118,7 @@ dlopen (const char *name, int)
 	  /* Restore original cxx_malloc pointer. */
 	  __cygwin_user_data.cxx_malloc = tmp_malloc;
 
-	  if (ret == NULL)
+	  if (!ret)
 	    __seterrno ();
 	}
     }
@@ -128,26 +134,42 @@ void *
 dlsym (void *handle, const char *name)
 {
   void *ret = NULL;
+
   if (handle == RTLD_DEFAULT)
     { /* search all modules */
-      HANDLE cur_proc = GetCurrentProcess ();
-      HMODULE *modules;
-      DWORD needed, i;
-      if (!EnumProcessModules (cur_proc, NULL, 0, &needed))
+      PDEBUG_BUFFER buf;
+      NTSTATUS status;
+
+      buf = RtlCreateQueryDebugBuffer (0, FALSE);
+      if (!buf)
 	{
-	dlsym_fail:
+	  set_errno (ENOMEM);
 	  set_dl_error ("dlsym");
 	  return NULL;
 	}
-      modules = (HMODULE*) alloca (needed);
-      if (!EnumProcessModules (cur_proc, modules, needed, &needed))
-	goto dlsym_fail;
-      for (i = 0; i < needed / sizeof (HMODULE); i++)
-	if ((ret = (void *) GetProcAddress (modules[i], name)))
-	  break;
+      status = RtlQueryProcessDebugInformation (GetCurrentProcessId (),
+						PDI_MODULES, buf);
+      if (!NT_SUCCESS (status))
+	__seterrno_from_nt_status (status);
+      else
+	{
+	  PDEBUG_MODULE_ARRAY mods = (PDEBUG_MODULE_ARRAY)
+				     buf->ModuleInformation;
+	  for (ULONG i = 0; i < mods->Count; ++i)
+	    if ((ret = (void *)
+		       GetProcAddress ((HMODULE) mods->Modules[i].Base, name)))
+	      break;
+	  if (!ret)
+	    set_errno (ENOENT);
+	}
+      RtlDestroyQueryDebugBuffer (buf);
     }
   else
-    ret = (void *) GetProcAddress ((HMODULE)handle, name);
+    {
+      ret = (void *) GetProcAddress ((HMODULE) handle, name);
+      if (!ret)
+	__seterrno ();
+    }
   if (!ret)
     set_dl_error ("dlsym");
   debug_printf ("ret %p", ret);
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 090ec648f..df0ae29a3 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -538,6 +538,12 @@ typedef struct _DEBUG_MODULE_INFORMATION
   CHAR ImageName[256];
 } DEBUG_MODULE_INFORMATION, *PDEBUG_MODULE_INFORMATION;
 
+typedef struct _DEBUG_MODULE_ARRAY
+{
+  ULONG Count;
+  DEBUG_MODULE_INFORMATION Modules[1];
+} DEBUG_MODULE_ARRAY, *PDEBUG_MODULE_ARRAY;
+
 typedef struct _KERNEL_USER_TIMES
 {
   LARGE_INTEGER CreateTime;
@@ -1143,10 +1149,12 @@ extern "C"
   NTSTATUS NTAPI RtlCopySid (ULONG, PSID, PSID);
   VOID NTAPI RtlCopyUnicodeString (PUNICODE_STRING, PUNICODE_STRING);
   NTSTATUS NTAPI RtlCreateAcl (PACL, ULONG, ULONG);
+  PDEBUG_BUFFER NTAPI RtlCreateQueryDebugBuffer (ULONG, BOOLEAN);
   NTSTATUS NTAPI RtlCreateRegistryKey (ULONG, PCWSTR);
   NTSTATUS NTAPI RtlCreateSecurityDescriptor (PSECURITY_DESCRIPTOR, ULONG);
   BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz (PUNICODE_STRING, PCSTR);
   NTSTATUS NTAPI RtlDeleteSecurityObject (PSECURITY_DESCRIPTOR *);
+  NTSTATUS NTAPI RtlDestroyQueryDebugBuffer (PDEBUG_BUFFER);
   NTSTATUS NTAPI RtlDowncaseUnicodeString (PUNICODE_STRING, PUNICODE_STRING,
 					   BOOLEAN);
   NTSTATUS NTAPI RtlEnterCriticalSection (PRTL_CRITICAL_SECTION);
@@ -1184,6 +1192,7 @@ extern "C"
 					       BOOLEAN);
   BOOLEAN NTAPI RtlPrefixUnicodeString (PUNICODE_STRING, PUNICODE_STRING,
 					BOOLEAN);
+  NTSTATUS NTAPI RtlQueryProcessDebugInformation (ULONG, ULONG, PDEBUG_BUFFER);
   NTSTATUS NTAPI RtlQueryRegistryValues (ULONG, PCWSTR,
 					 PRTL_QUERY_REGISTRY_TABLE, PVOID,
 					 PVOID);