Index: /trunk/xcache.c
===================================================================
--- /trunk/xcache.c	(revision 913)
+++ /trunk/xcache.c	(revision 914)
@@ -3336,4 +3336,104 @@
 /* }}} */
 
+#ifdef ZEND_WIN32
+#include "dbghelp.h"
+typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
+		CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+		CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+		CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
+		);
+
+static PTOP_LEVEL_EXCEPTION_FILTER oldFilter;
+static HMODULE dbghelpModule = NULL;
+static char crash_dumpPath[_MAX_PATH];
+static MINIDUMPWRITEDUMP dbghelp_MiniDumpWriteDump;
+
+static LONG WINAPI miniDumperFilter(struct _EXCEPTION_POINTERS *pExceptionInfo) /* {{{ */
+{
+	HANDLE fileHandle;
+
+	SetUnhandledExceptionFilter(oldFilter);
+
+	/* create the file */
+	fileHandle = CreateFile(crash_dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+	if (fileHandle != INVALID_HANDLE_VALUE) {
+		MINIDUMP_EXCEPTION_INFORMATION exceptionInformation;
+		BOOL ok;
+
+		exceptionInformation.ThreadId = GetCurrentThreadId();
+		exceptionInformation.ExceptionPointers = pExceptionInfo;
+		exceptionInformation.ClientPointers = FALSE;
+
+		/* write the dump */
+		ok = dbghelp_MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), fileHandle, MiniDumpNormal, &exceptionInformation, NULL, NULL);
+		CloseHandle(fileHandle);
+		if (ok) {
+			zend_error(E_ERROR, "Saved dump file to '%s'", crash_dumpPath);
+			return EXCEPTION_EXECUTE_HANDLER;
+		}
+		else {
+			zend_error(E_ERROR, "Failed to save dump file to '%s' (error %d)", crash_dumpPath, GetLastError());
+		}
+	}
+	else {
+		zend_error(E_ERROR, "Failed to create dump file '%s' (error %d)", crash_dumpPath, GetLastError());
+	}
+
+	return EXCEPTION_CONTINUE_SEARCH;
+}
+/* }}} */
+
+static void xcache_restore_crash_handler() /* {{{ */
+{
+	if (oldFilter) {
+		SetUnhandledExceptionFilter(oldFilter);
+		oldFilter = NULL;
+	}
+}
+/* }}} */
+static void xcache_init_crash_handler() /* {{{ */
+{
+	/* firstly see if dbghelp.dll is around and has the function we need
+	   look next to the EXE first, as the one in System32 might be old
+	   (e.g. Windows 2000) */
+	char dbghelpPath[_MAX_PATH];
+
+	if (GetModuleFileName(NULL, dbghelpPath, _MAX_PATH)) {
+		char *slash = strchr(dbghelpPath, '\\');
+		if (slash) {
+			strcpy(slash + 1, "DBGHELP.DLL");
+			dbghelpModule = LoadLibrary(dbghelpPath);
+		}
+	}
+
+	if (!dbghelpModule) {
+		/* load any version we can */
+		dbghelpModule = LoadLibrary("DBGHELP.DLL");
+		if (!dbghelpModule) {
+			zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL not found");
+			return;
+		}
+	}
+
+	dbghelp_MiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress(dbghelpModule, "MiniDumpWriteDump");
+	if (dbghelp_MiniDumpWriteDump) {
+		zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL too old");
+		return;
+	}
+
+	/* work out a good place for the dump file */
+	{
+		char tmpPath[_MAX_PATH];
+		if (!GetTempPath(_MAX_PATH, tmpPath)) {
+			strcpy(tmpPath, "c:\\temp");
+		}
+		sprintf(crash_dumpPath, "%s\\php-%s-xcache-%s-%lu.dmp", PHP_VERSION, XCACHE_VERSION, (unsigned long) GetCurrentProcessId());
+	}
+
+	oldFilter = SetUnhandledExceptionFilter(&miniDumperFilter);
+}
+/* }}} */
+#else
 /* old signal handlers {{{ */
 typedef void (*xc_sighandler_t)(int);
@@ -3343,5 +3443,5 @@
 /* }}} */
 static void xcache_signal_handler(int sig);
-static void xcache_restore_signal_handler() /* {{{ */
+static void xcache_restore_crash_handler() /* {{{ */
 {
 #define FOREACH_SIG(sig) do { \
@@ -3357,5 +3457,5 @@
 }
 /* }}} */
-static void xcache_init_signal_handler() /* {{{ */
+static void xcache_init_crash_handler() /* {{{ */
 {
 #define FOREACH_SIG(sig) \
@@ -3367,5 +3467,5 @@
 static void xcache_signal_handler(int sig) /* {{{ */
 {
-	xcache_restore_signal_handler();
+	xcache_restore_crash_handler();
 	if (xc_coredump_dir && xc_coredump_dir[0]) {
 		if (chdir(xc_coredump_dir) != 0) {
@@ -3377,4 +3477,5 @@
 }
 /* }}} */
+#endif
 
 /* {{{ PHP_INI */
@@ -3712,5 +3813,5 @@
 
 	if (xc_coredump_dir && xc_coredump_dir[0]) {
-		xcache_init_signal_handler();
+		xcache_init_crash_handler();
 	}
 
@@ -3767,5 +3868,5 @@
 
 	if (xc_coredump_dir && xc_coredump_dir[0]) {
-		xcache_restore_signal_handler();
+		xcache_restore_crash_handler();
 	}
 	if (xc_coredump_dir) {
