Msvcrt patch 2/2

François Gouget fgouget at codeweavers.com
Thu Dec 20 01:48:48 CST 2001


   And here is part two. This one deals with setjmp/setjmp3 and longjmp.
I also worked with Alexandre to convert it to use register functions
(hence the recent patches if anyone was wondering).

   (note there's one new file: include/msvcrt/setjmp.h)


Changelog:

   Jon Griffiths <jon_p_griffiths at yahoo.com>
   François Gouget <fgouget at codeweavers.com>
   Alexandre Julliard <julliard at codeweavers.com>

 * include/msvcrt/setjmp.h,
   dlls/msvcrt/except.c

   Implement setjmp/setjmp3 and longjmp


-- 
François Gouget
fgouget at codeweavers.com
-------------- next part --------------
--- /dev/null	Thu Dec 13 01:07:23 2001
+++ include/msvcrt/setjmp.h	Wed Dec 19 23:18:16 2001
@@ -0,0 +1,58 @@
+/*
+ * Setjmp/Longjmp definitions
+ *
+ * Copyright 2001 Francois Gouget.
+ */
+#ifndef __WINE_SETJMP_H
+#define __WINE_SETJMP_H
+#define __WINE_USE_MSVCRT
+
+#ifdef USE_MSVCRT_PREFIX
+#define MSVCRT(x)    MSVCRT_##x
+#else
+#define MSVCRT(x)    x
+#endif
+
+
+#ifdef __i386__
+
+#define _JBLEN                     16
+#define _JBTYPE                    int
+
+typedef struct __JUMP_BUFFER
+{
+    unsigned long Ebp;
+    unsigned long Ebx;
+    unsigned long Edi;
+    unsigned long Esi;
+    unsigned long Esp;
+    unsigned long Eip;
+    unsigned long Registration;
+    unsigned long TryLevel;
+    /* Start of new struct members */
+    unsigned long Cookie;
+    unsigned long UnwindFunc;
+    unsigned long UnwindData[6];
+} _JUMP_BUFFER;
+
+#endif /* __i386__ */
+
+typedef _JBTYPE MSVCRT(jmp_buf)[_JBLEN];
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int         MSVCRT(_setjmp)( MSVCRT(jmp_buf));
+int         MSVCRT(longjmp)( MSVCRT(jmp_buf),int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifndef USE_MSVCRT_PREFIX
+#define setjmp _setjmp
+#endif
+
+#endif /* __WINE_SETJMP_H */
Index: dlls/msvcrt/except.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/except.c,v
retrieving revision 1.7
diff -u -r1.7 except.c
--- dlls/msvcrt/except.c	2001/09/20 19:33:37	1.7
+++ dlls/msvcrt/except.c	2001/12/20 05:48:23
@@ -15,6 +15,9 @@
 #include "thread.h"
 #include "msvcrt.h"
 
+#include "msvcrt/setjmp.h"
+
+
 DEFAULT_DEBUG_CHANNEL(msvcrt);
 
 typedef void (*MSVCRT_sig_handler_func)(void);
@@ -227,32 +230,120 @@
   return 0;
 }
 
+/*
+ * setjmp/longjmp implementation
+ */
+
+#ifdef __i386__
+#define MSVCRT_JMP_MAGIC 0x56433230 /* ID value for new jump structure */
+typedef void (*MSVCRT_unwind_function)(const void*);
+
+/*
+ * The signatures of the setjmp/longjmp functions do not match that 
+ * declared in the setjmp header so they don't follow the regular naming 
+ * convention to avoid conflicts.
+ */
+
 /*******************************************************************
  *		_setjmp (MSVCRT.@)
  */
-int MSVCRT__setjmp(LPDWORD* jmpbuf)
+void _MSVCRT__setjmp(_JUMP_BUFFER *jmp, CONTEXT86* context)
 {
-  FIXME(":(%p): stub\n",jmpbuf);
-  return 0;
+    TRACE("(%p)\n",jmp);
+    jmp->Ebp = context->Ebp;
+    jmp->Ebx = context->Ebx;
+    jmp->Edi = context->Edi;
+    jmp->Esi = context->Esi;
+    jmp->Esp = context->Esp;
+    jmp->Eip = context->Eip;
+    jmp->Registration = (unsigned long)NtCurrentTeb()->except;
+    if (jmp->Registration == TRYLEVEL_END)
+        jmp->TryLevel = TRYLEVEL_END;
+    else
+        jmp->TryLevel = ((MSVCRT_EXCEPTION_FRAME*)jmp->Registration)->trylevel;
+    TRACE("returning 0\n");
+    context->Eax=0;
 }
 
 /*******************************************************************
  *		_setjmp3 (MSVCRT.@)
  */
-int __cdecl MSVCRT__setjmp3(LPDWORD *jmpbuf, int x)
+void _MSVCRT__setjmp3(_JUMP_BUFFER *jmp, int nb_args, CONTEXT86* context)
 {
-  FIXME(":(%p %x): stub\n",jmpbuf,x);
-  return 0;
+    TRACE("(%p,%d)\n",jmp,nb_args);
+    jmp->Ebp = context->Ebp;
+    jmp->Ebx = context->Ebx;
+    jmp->Edi = context->Edi;
+    jmp->Esi = context->Esi;
+    jmp->Esp = context->Esp;
+    jmp->Eip = context->Eip;
+    jmp->Cookie = MSVCRT_JMP_MAGIC;
+    jmp->UnwindFunc = 0;
+    jmp->Registration = (unsigned long)NtCurrentTeb()->except;
+    if (jmp->Registration == TRYLEVEL_END)
+    {
+        jmp->TryLevel = TRYLEVEL_END;
+    }
+    else
+    {
+        void **args = ((void**)context->Esp)+2;
+
+        if (nb_args > 0) jmp->UnwindFunc = (unsigned long)*args++;
+        if (nb_args > 1) jmp->TryLevel = (unsigned long)*args++;
+        else jmp->TryLevel = ((MSVCRT_EXCEPTION_FRAME*)jmp->Registration)->trylevel;
+        if (nb_args > 2)
+        {
+            size_t size = (nb_args - 2) * sizeof(DWORD);
+            memcpy( jmp->UnwindData, args, min( size, sizeof(jmp->UnwindData) ));
+        }
+    }
+    TRACE("returning 0\n");
+    context->Eax = 0;
 }
 
 /*********************************************************************
  *		longjmp (MSVCRT.@)
  */
-void MSVCRT_longjmp(jmp_buf env, int val)
+void _MSVCRT_longjmp(_JUMP_BUFFER *jmp, int retval, CONTEXT86* context)
 {
-  FIXME("MSVCRT_longjmp semistub, expect crash\n");
-  longjmp(env, val);
+    unsigned long cur_frame = 0;
+
+    TRACE("(%p,%d)\n", jmp, retval);
+
+    cur_frame=(unsigned long)NtCurrentTeb()->except;
+    TRACE("cur_frame=%lx\n",cur_frame);
+
+    if (cur_frame != jmp->Registration)
+        _global_unwind2((PEXCEPTION_FRAME)jmp->Registration);
+
+    if (jmp->Registration)
+    {
+        if (!IsBadReadPtr(&jmp->Cookie, sizeof(long)) &&
+            jmp->Cookie == MSVCRT_JMP_MAGIC && jmp->UnwindFunc)
+        {
+            MSVCRT_unwind_function unwind_func;
+
+            unwind_func=(MSVCRT_unwind_function)jmp->UnwindFunc;
+            unwind_func(jmp);
+        }
+        else
+            _local_unwind2((MSVCRT_EXCEPTION_FRAME*)jmp->Registration,
+                           jmp->TryLevel);
+    }
+
+    if (!retval)
+        retval = 1;
+
+    TRACE("Jump to %lx returning %d\n",jmp->Eip,retval);
+    context->Ebp = jmp->Ebp;
+    context->Ebx = jmp->Ebx;
+    context->Edi = jmp->Edi;
+    context->Esi = jmp->Esi;
+    context->Esp = jmp->Esp;
+    context->Eip = jmp->Eip;
+    context->Eax = retval;
 }
+#endif /* i386 */
 
 /*********************************************************************
  *		signal (MSVCRT.@)
Index: dlls/msvcrt/msvcrt.spec
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/msvcrt.spec,v
retrieving revision 1.26
diff -u -r1.26 msvcrt.spec
--- dlls/msvcrt/msvcrt.spec	2001/12/05 22:11:35	1.26
+++ dlls/msvcrt/msvcrt.spec	2001/12/20 05:48:24
@@ -432,8 +432,8 @@
 @ stub _set_error_mode #(long)
 @ stub _set_sbh_threshold #(long)
 @ stub _seterrormode #(long)
-@ cdecl _setjmp(ptr) MSVCRT__setjmp
-@ cdecl _setjmp3(ptr long) MSVCRT__setjmp3
+@ cdecl -register -noimport -i386 _setjmp(ptr) _MSVCRT__setjmp
+@ cdecl -register -noimport -i386 _setjmp3(ptr long) _MSVCRT__setjmp3
 @ stub _setmaxstdio #(long)
 @ cdecl _setmbcp(long) _setmbcp
 @ cdecl _setmode(long long) _setmode
@@ -665,7 +665,7 @@
 @ cdecl localtime(ptr) localtime
 @ forward -noimport log ntdll.log
 @ cdecl log10(double) log10
-@ cdecl longjmp(long long) MSVCRT_longjmp
+@ cdecl -register -noimport -i386 longjmp(ptr long) _MSVCRT_longjmp
 @ cdecl malloc(long) MSVCRT_malloc
 @ cdecl mblen(ptr long) MSVCRT_mblen
 @ forward -noimport mbstowcs ntdll.mbstowcs


More information about the wine-patches mailing list