From c7013ba1fcad7fcc84d7e6e93d7a0306c13bce47 Mon Sep 17 00:00:00 2001
From: Philipp Brueschweiler <bruphili@student.ethz.ch>
Date: Sat, 15 Jun 2013 10:10:49 +0200
Subject: [PATCH] std::dynamic_lib: start fixing windows implementation

The code compiles and runs under windows now, but I couldn't look up any
symbol from the current executable (dlopen(NULL)), and calling looked
up external function handles doesn't seem to work correctly under windows.
---
 src/libstd/unstable/dynamic_lib.rs | 49 ++++++++++++++++++++----------
 src/libstd/unstable/mod.rs         |  5 ---
 2 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs
index 96aba1d2971..f5f88f2bb88 100644
--- a/src/libstd/unstable/dynamic_lib.rs
+++ b/src/libstd/unstable/dynamic_lib.rs
@@ -42,19 +42,15 @@ impl DynamicLibrary {
     /// Lazily open a dynamic library. When passed None it gives a
     /// handle to the calling process
     pub fn open(filename: Option<&path::Path>) -> Result<DynamicLibrary, ~str> {
-        let open_wrapper = |raw_ptr| {
-            do dl::check_for_errors_in {
-                unsafe {
-                    DynamicLibrary { handle: dl::open(raw_ptr) }
+        do dl::check_for_errors_in {
+            unsafe {
+                DynamicLibrary { handle:
+                    match filename {
+                        Some(name) => dl::open_external(name),
+                        None => dl::open_internal()
+                    }
                 }
             }
-        };
-
-        match filename {
-            Some(name) => do name.to_str().as_c_str |raw_name| {
-                open_wrapper(raw_name)
-            },
-            None => open_wrapper(ptr::null())
         }
     }
 
@@ -74,6 +70,7 @@ impl DynamicLibrary {
 }
 
 #[test]
+#[ignore(cfg(windows))]
 priv fn test_loading_cosine () {
     // The math library does not need to be loaded since it is already
     // statically linked in
@@ -106,13 +103,20 @@ priv fn test_loading_cosine () {
 #[cfg(target_os = "freebsd")]
 mod dl {
     use libc;
+    use path;
     use ptr;
     use str;
     use task;
     use result::*;
 
-    pub unsafe fn open(filename: *libc::c_char) -> *libc::c_void {
-        dlopen(filename, Lazy as libc::c_int)
+    pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
+        do filename.to_str().as_c_str |raw_name| {
+            dlopen(raw_name, Lazy as libc::c_int)
+        }
+    }
+
+    pub unsafe fn open_internal() -> *libc::c_void {
+        dlopen(ptr::null(), Lazy as libc::c_int)
     }
 
     pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
@@ -159,11 +163,22 @@ mod dl {
 mod dl {
     use os;
     use libc;
+    use path;
+    use ptr;
+    use str;
     use task;
     use result::*;
 
-    pub unsafe fn open(filename: *libc::c_char) -> *libc::c_void {
-        LoadLibrary(filename)
+    pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
+        do os::win32::as_utf16_p(filename.to_str()) |raw_name| {
+            LoadLibraryW(raw_name)
+        }
+    }
+
+    pub unsafe fn open_internal() -> *libc::c_void {
+        let mut handle = ptr::null();
+        GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
+        handle
     }
 
     pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
@@ -192,7 +207,9 @@ mod dl {
     #[link_name = "kernel32"]
     extern "stdcall" {
         fn SetLastError(error: u32);
-        fn LoadLibrary(name: *libc::c_char) -> *libc::c_void;
+        fn LoadLibraryW(name: *u16) -> *libc::c_void;
+        fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
+                              handle: **libc::c_void) -> *libc::c_void;
         fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
         fn FreeLibrary(handle: *libc::c_void);
     }
diff --git a/src/libstd/unstable/mod.rs b/src/libstd/unstable/mod.rs
index ae878050142..0a46ef619af 100644
--- a/src/libstd/unstable/mod.rs
+++ b/src/libstd/unstable/mod.rs
@@ -18,11 +18,6 @@ use task;
 
 pub mod at_exit;
 
-// Currently only works for *NIXes
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "android")]
-#[cfg(target_os = "macos")]
-#[cfg(target_os = "freebsd")]
 pub mod dynamic_lib;
 
 pub mod global;