+}
+
+/*
+ * A good explanation of the exception handling semantics is
+ * http://win32assembly.online.fr/Exceptionhandling.html .
+ */
+
+EXCEPTION_DISPOSITION
+handle_exception(EXCEPTION_RECORD *exception_record,
+ struct lisp_exception_frame *exception_frame,
+ CONTEXT *ctx,
+ void *dispatcher_context)
+{
+ if (exception_record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) {
+ /* If we're being unwound, be graceful about it. */
+
+ /* Undo any dynamic bindings. */
+ unbind_to_here(exception_frame->bindstack_pointer,
+ arch_os_get_current_thread());
+
+ return ExceptionContinueSearch;
+ }
+
+ DWORD code = exception_record->ExceptionCode;
+
+ /* For EXCEPTION_ACCESS_VIOLATION only. */
+ void *fault_address = (void *)exception_record->ExceptionInformation[1];
+
+ /* This function will become unwieldy. Let's cut it down into
+ * pieces based on the different exception codes. Each exception
+ * code handler gets the chance to decline by returning non-zero if it
+ * isn't happy: */
+
+ int rc;
+ switch (code) {
+ case EXCEPTION_ACCESS_VIOLATION:
+ rc = handle_access_violation(
+ ctx, exception_record, fault_address);
+ break;
+
+ case SBCL_EXCEPTION_BREAKPOINT:
+ rc = handle_breakpoint_trap(ctx);
+ break;
+
+#if defined(LISP_FEATURE_X86)
+ case EXCEPTION_SINGLE_STEP:
+ rc = handle_single_step(ctx);
+ break;
+#endif
+
+ default:
+ rc = -1;
+ }
+
+ if (rc)
+ /* All else failed, drop through to the lisp-side exception handler. */
+ signal_internal_error_or_lose(ctx, exception_record, fault_address);