diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6067303..a8cc21d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -209,7 +209,7 @@ if (ENABLE_OBJCXX)
 			message(STATUS "Forcing build of stand-alone libobjcxx")
 			add_library(objcxx SHARED ${libobjcxx_CXX_SRCS})
 			set_target_properties(objcxx PROPERTIES
-				LINKER_LANGUAGE C
+				LINKER_LANGUAGE CXX
 				SOVERSION ${libobjc_VERSION}
 				)
 			target_link_libraries(objcxx ${CXX_RUNTIME})
@@ -225,7 +225,7 @@ if (ENABLE_OBJCXX)
 		message(STATUS "No C++ runtime library found")
 		add_library(objcxx SHARED ${libobjcxx_CXX_SRCS})
 		set_target_properties(objcxx PROPERTIES
-			LINKER_LANGUAGE C
+			LINKER_LANGUAGE CXX
 			SOVERSION ${libobjc_VERSION}
 			)
 		set(CXX_RUNTIME "")
@@ -286,6 +286,23 @@ if (APPLE)
 	set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -Wl,-undefined,dynamic_lookup")
 endif ()
 
+if (MINGW)
+	# Ordering of libs matters on Windows/MinGW
+	target_link_libraries(objc ${CMAKE_THREAD_LIBS_INIT})
+	target_link_libraries(objc "psapi")
+	target_link_libraries(objcxx ${CMAKE_BINARY_DIR}/libobjc.dll.a)
+
+	# OS_BUILD comes from the environment or the command line, i.e. 
+	# cmake .. -DOS_BUILD=64 <...>
+	# TODO: make sure the toolchain is 64-bit in this case
+	if (OS_BUILD STREQUAL 64)
+		message(STATUS "MinGW 64-bit build")
+		set(CMAKE_C_FLAGS "-m64 ${CMAKE_C_FLAGS}")
+		set(CMAKE_CXX_FLAGS "-m64 ${CMAKE_CXX_FLAGS}")
+		set(CMAKE_ASM_FLAGS "-m64 ${CMAKE_ASM_FLAGS}")
+	endif ()
+endif (MINGW)
+
 #
 # Installation
 #
diff --git a/Test/CMakeLists.txt b/Test/CMakeLists.txt
index e8db645..53e5fdc 100644
--- a/Test/CMakeLists.txt
+++ b/Test/CMakeLists.txt
@@ -43,11 +43,20 @@ function(addtest_flags TEST FLAGS TEST_SOURCE)
 	set_target_properties(${TEST} PROPERTIES
 		INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}"
 		COMPILE_FLAGS "-fobjc-runtime=gnustep-1.7 -fblocks ${FLAGS}"
-		LINKER_LANGUAGE C
-	)
-	set_property(TEST ${TEST} PROPERTY
-		ENVIRONMENT "LD_LIBRARY_PATH="
+		LINKER_LANGUAGE CXX
 	)
+	if (MINGW)
+		# For newly built DLLs:
+		set(path_value "$ENV{PATH};${CMAKE_BINARY_DIR}")
+		string(REPLACE ";" "\\;" path_value "${path_value}")
+		set_property(TEST ${TEST} PROPERTY
+			ENVIRONMENT "PATH=${path_value}"
+		)
+	else (MINGW)
+		set_property(TEST ${TEST} PROPERTY
+			ENVIRONMENT "LD_LIBRARY_PATH="
+		)
+	endif (MINGW)
 	target_link_libraries(${TEST} objc)
 endfunction(addtest_flags)
 
diff --git a/Test/ManyManySelectors.m b/Test/ManyManySelectors.m
index 2e6f7d0..ada93e5 100644
--- a/Test/ManyManySelectors.m
+++ b/Test/ManyManySelectors.m
@@ -5,7 +5,10 @@
 
 #include <sys/types.h>
 #include <sys/time.h>
+
+#ifndef _WIN32
 #include <sys/resource.h>
+#endif
 
 
 static BOOL methodCalled = NO;
diff --git a/Test/RuntimeTest.m b/Test/RuntimeTest.m
index 327a23f..b4517c8 100644
--- a/Test/RuntimeTest.m
+++ b/Test/RuntimeTest.m
@@ -3,6 +3,11 @@
 #include <string.h>
 #include <unistd.h>
 
+#ifdef _WIN32
+#include <windows.h>
+#define sleep(n) (void)(Sleep((n) * 1000))
+#endif
+
 static int exitStatus = 0;
 
 static void _test(BOOL X, char *expr, int line)
@@ -86,7 +91,7 @@ __attribute__((objc_root_class))
 - (id) aBool: (BOOL)d andAnInt: (int) w;
 @end
 
-id exceptionObj = @"Exception";
+id exceptionObj;
 
 @implementation Foo
 - (void) aMethod
@@ -143,11 +148,11 @@ id exceptionObj = @"Exception";
 }
 - (id) manyTypes
 {
-  return @"Hello";
+  return nil;
 }
 - (id) aBool: (BOOL)d andAnInt: (int) w
 {
-  return @"Hello";
+  return nil;
 }
 @end
 
@@ -322,6 +327,8 @@ static int initCount;
 
 int main (int argc, const char * argv[])
 {
+  exceptionObj = [Foo new];
+
   testInvalidArguments();
   testGetMethod();
   testProtocols();
diff --git a/Test/objc_msgSend.m b/Test/objc_msgSend.m
index 6d6803c..cc94f5f 100644
--- a/Test/objc_msgSend.m
+++ b/Test/objc_msgSend.m
@@ -54,11 +54,11 @@ __attribute__((objc_root_class))
 + (void)printf: (const char*)str, ...
 {
 	va_list ap;
-	char *s;
+	char s[256];
 
 	va_start(ap, str);
 
-	vasprintf(&s, str, ap);
+	vsnprintf(s, sizeof(s), str, ap);
 	va_end(ap);
 	//fprintf(stderr, "String: '%s'\n", s);
 	assert(strcmp(s, "Format string 42 42.000000\n") ==0);
diff --git a/block_to_imp.c b/block_to_imp.c
index 9fadea2..bf2aaa0 100644
--- a/block_to_imp.c
+++ b/block_to_imp.c
@@ -10,13 +10,18 @@
 #include <ctype.h>
 #include <unistd.h>
 #include <sys/types.h>
-#include <sys/mman.h>
 #include "objc/runtime.h"
 #include "objc/blocks_runtime.h"
 #include "blocks_runtime.h"
 #include "lock.h"
 #include "visibility.h"
 
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/mman.h>
+#endif
+
 #ifndef __has_builtin
 #define __has_builtin(x) 0
 #endif
@@ -39,6 +44,14 @@ static void *executeBuffer;
 static void *writeBuffer;
 static ptrdiff_t offset;
 static mutex_t trampoline_lock;
+
+
+#ifdef _WIN32
+
+static void initTmpFile(void) {}
+
+#else
+
 #ifndef SHM_ANON
 static char *tmpPattern;
 static void initTmpFile(void)
@@ -69,6 +82,9 @@ static int getAnonMemFd(void)
 }
 #endif
 
+#endif // _WIN32
+
+
 struct wx_buffer
 {
 	void *w;
@@ -86,10 +102,17 @@ static struct wx_buffer alloc_buffer(size_t size)
 	LOCK_FOR_SCOPE(&trampoline_lock);
 	if ((0 == offset) || (offset + size >= PAGE_SIZE))
 	{
+#ifdef _WIN32
+		void* w = VirtualAllocEx(GetCurrentProcess(), 0, PAGE_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+		if (w == NULL)
+			abort();
+		executeBuffer = w;
+#else
 		int fd = getAnonMemFd();
 		ftruncate(fd, PAGE_SIZE);
 		void *w = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED, fd, 0);
 		executeBuffer = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0);
+#endif
 		*((void**)w) = writeBuffer;
 		writeBuffer = w;
 		offset = sizeof(void*);
diff --git a/eh_personality.c b/eh_personality.c
index 5308862..a8daa0e 100644
--- a/eh_personality.c
+++ b/eh_personality.c
@@ -11,6 +11,12 @@
 #include <pthread.h>
 #endif
 
+#ifdef _WIN32
+#define __OBJC__ // MinGW32 hack to fix the BOOL conflict
+#include "windows.h"
+#include "psapi.h"
+#endif
+
 #ifndef DEBUG_EXCEPTIONS
 #define DEBUG_LOG(...)
 #else
@@ -506,12 +512,50 @@ BEGIN_PERSONALITY_FUNCTION(__gnustep_objcxx_personality_v0)
 }
 #endif
 
+
+#ifdef _WIN32
+
+// Weak refs don't work on Windows the same way as with ELF, so:
+
+void *(*weak__cxa_begin_catch)(void *e);
+void (*weak__cxa_end_catch)(void);
+void (*weak__cxa_rethrow)(void);
+
+static void resolve_cxa_syms()
+{
+	HMODULE hmods[256 * sizeof(HMODULE)];
+	DWORD hmodCount;
+	if(!EnumProcessModules(GetCurrentProcess(), hmods, sizeof(hmods), &hmodCount))
+		abort();
+	for (int i = 0; i < (hmodCount / sizeof(HMODULE)); i++)
+	{
+		weak__cxa_begin_catch = (void*)GetProcAddress(hmods[i], TEXT("__cxa_begin_catch"));
+		if (weak__cxa_begin_catch)
+		{
+#ifdef DEBUG_EXCEPTIONS
+			TCHAR name[MAX_PATH];
+			GetModuleFileName(hmods[i], name, sizeof(name));
+			printf("Resolving __cxa_* from module %s\n", name);
+#endif
+			weak__cxa_end_catch = (void*)GetProcAddress(hmods[i], TEXT("__cxa_end_catch"));
+			weak__cxa_rethrow = (void*)GetProcAddress(hmods[i], TEXT("__cxa_rethrow"));
+		}
+	}
+}
+
+#else // _WIN32
+
 // Weak references to C++ runtime functions.  We don't bother testing that
 // these are 0 before calling them, because if they are not resolved then we
 // should not be in a code path that involves a C++ exception.
 __attribute__((weak)) void *__cxa_begin_catch(void *e);
 __attribute__((weak)) void __cxa_end_catch(void);
 __attribute__((weak)) void __cxa_rethrow(void);
+#define weak__cxa_begin_catch __cxa_begin_catch
+#define weak__cxa_end_catch __cxa_end_catch
+#define weak__cxa_rethrow __cxa_rethrow
+
+#endif // _WIN32
 
 enum exception_type
 {
@@ -619,7 +663,11 @@ id objc_begin_catch(struct _Unwind_Exception *exceptionObject)
 	{
 		DEBUG_LOG("c++ catch\n");
 		td->current_exception_type = CXX;
-		return __cxa_begin_catch(exceptionObject);
+#ifdef _WIN32
+		if (!weak__cxa_begin_catch)
+			resolve_cxa_syms();
+#endif
+		return weak__cxa_begin_catch(exceptionObject);
 	}
 	DEBUG_LOG("foreign exception catch\n");
 	// Box if we have a boxing function.
@@ -659,7 +707,7 @@ void objc_end_catch(void)
 	// If this is a C++ exception, then just let the C++ runtime handle it.
 	if (td->current_exception_type == CXX)
 	{
-		__cxa_end_catch();
+		weak__cxa_end_catch();
 		td->current_exception_type = OBJC;
 		return;
 	}
@@ -714,7 +762,7 @@ void objc_exception_rethrow(struct _Unwind_Exception *e)
 	else if (td->current_exception_type == CXX)
 	{
 		assert(e->exception_class == cxx_exception_class);
-		__cxa_rethrow();
+		weak__cxa_rethrow();
 	}
 	if (td->current_exception_type == BOXED_FOREIGN)
 	{
diff --git a/lock.h b/lock.h
index d39f07b..3a93641 100644
--- a/lock.h
+++ b/lock.h
@@ -6,7 +6,7 @@
 
 #ifndef __LIBOBJC_LOCK_H_INCLUDED__
 #define __LIBOBJC_LOCK_H_INCLUDED__
-#ifdef WIN32
+#ifdef _WIN32
 #define BOOL _WINBOOL
 #	include <windows.h>
 #undef BOOL
diff --git a/objc_msgSend.x86-32.S b/objc_msgSend.x86-32.S
index 2b5406f..a53d9c4 100644
--- a/objc_msgSend.x86-32.S
+++ b/objc_msgSend.x86-32.S
@@ -3,6 +3,10 @@
 #define SHIFT_OFFSET   4
 #define DATA_OFFSET    12
 #define SLOT_OFFSET    16
+
+#define slowMsgLookup CDECL(slowMsgLookup)
+#define SmallObjectClasses CDECL(SmallObjectClasses)
+
 .macro MSGSEND receiver, sel, fpret
 	.cfi_startproc                        
 	movl  \receiver(%esp), %eax
@@ -66,15 +70,25 @@
 	mov   \sel(%esp), %ecx
 	lea   \receiver(%esp), %eax
 
+#ifdef __APPLE__
+	subl  $4, %esp                       # stack alignment: ret, pad, cmd, self
+#endif
 	push  %ecx                           # _cmd
 	push  %eax                           # &self
 	.cfi_def_cfa_offset 12
 	call  slowMsgLookup@PLT
+#ifdef __APPLE__
+	add   $12, %esp                      # restore the stack
+#else
 	add   $8, %esp                       # restore the stack
+#endif
 
 
 	jmp   *%eax
 6:                                       # smallObject:
+#if defined(WIN32) || defined(__APPLE__)
+	mov   SmallObjectClasses, %eax       # On 32-bit systems there is only one entry
+#else
 	push  %ebx                           # Save old %ebx
 	calll 7f
 7:
@@ -84,6 +98,7 @@
 	leal  SmallObjectClasses@GOTOFF(%ebx), %eax
 	mov   (%eax), %eax
 	popl  %ebx
+#endif
 	jmp   1b 
 	.cfi_endproc
 .endm
diff --git a/objcxx_eh.cc b/objcxx_eh.cc
index 1837ae6..c9055ef 100644
--- a/objcxx_eh.cc
+++ b/objcxx_eh.cc
@@ -8,6 +8,11 @@ extern "C"
 {
 #include "objc/runtime.h"
 };
+
+#if defined (_WIN32) || defined(__APPLE__)
+#include <typeinfo>
+#else
+
 namespace __cxxabiv1
 {
 	struct __class_type_info;
@@ -48,6 +53,7 @@ namespace std
 				                void **thrown_object) const;
 	};
 }
+#endif
 
 using namespace std;
 
diff --git a/selector_table.c b/selector_table.c
index 13b6ca5..1754446 100644
--- a/selector_table.c
+++ b/selector_table.c
@@ -4,6 +4,11 @@
  * When building, you may define TYPE_DEPENDENT_DISPATCH to enable message
  * sends to depend on their types.
  */
+
+#ifdef _WIN32
+#define _NO_BOOL_TYPEDEF // MinGW64 hack
+#endif
+
 #include <string.h>
 #include <stdio.h>
 #include <assert.h>
diff --git a/spinlock.h b/spinlock.h
index e65e608..452f155 100644
--- a/spinlock.h
+++ b/spinlock.h
@@ -1,10 +1,7 @@
-#ifdef __MINGW32__
+
+#ifdef _WIN32
 #include <windows.h>
-static unsigned sleep(unsigned seconds)
-{
-	Sleep(seconds*1000);
-	return 0;
-}
+#define sleep(n) (void)(Sleep((n) * 1000))
 #else
 #include <unistd.h>
 #endif
