widl [1/7]: Output working exception handling macros. [take 2]

Dan Hipschman dsh at linux.ucla.edu
Wed Nov 21 19:17:53 CST 2007


This is essentially the same as the last attempt but doesn't add a wine-
internal function to kernel32.  It just puts the code directly in the
widl-generated exception handler.  An alternative is to handle these access-
based page faults for which we can continue in the signal handler (signal_i386,
etc., in ntdll) so they never actually result in an exception being raised.
I'm not sure if anything depends on the current behavior and didn't want to
mess much more with the exception handling code than I had to.  Here's what
the output looks like:


#ifdef __WINESRC__
#include <winternl.h>
#include "wine/exception.h"

#undef RpcExceptionCode
#undef RpcTryExcept
#undef RpcExcept
#undef RpcEndExcept
#undef RpcTryFinally
#undef RpcFinally
#undef RpcEndFinally

#if !defined(__GNUC__) && !defined(__attribute__)
#define __attribute__(x)
#endif

typedef struct
{
    EXCEPTION_REGISTRATION_RECORD frame;
    EXCEPTION_RECORD rec;
    sigjmp_buf jmp;
    DWORD mask;
} __widl_except_frame_t;

static DWORD __widl_exception_handler(
    EXCEPTION_RECORD *rec,
    EXCEPTION_REGISTRATION_RECORD *frame,
    CONTEXT *context __attribute__((unused)),
    EXCEPTION_REGISTRATION_RECORD **pdispatcher __attribute__((unused)))
{
    __widl_except_frame_t *wef = (__widl_except_frame_t *) frame;
    if (rec->ExceptionFlags & wef->mask)
        return ExceptionContinueSearch;
    if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
        && 2 <= rec->NumberParameters
        && rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
    {
        MEMORY_BASIC_INFORMATION meminfo;
        void *addr = (void *) rec->ExceptionInformation[1];
        if (VirtualQuery(addr, &meminfo, sizeof meminfo)
            && meminfo.State != MEM_FREE
            && (meminfo.Protect == PAGE_READONLY
                || meminfo.Protect == PAGE_READWRITE
                || meminfo.Protect == PAGE_WRITECOPY))
            if (VirtualProtect(addr, 1, meminfo.Protect << 4, NULL))
                return ExceptionContinueExecution;
    }
    wef->rec = *rec;
    RtlUnwind(frame, 0, rec, 0);
    siglongjmp(wef->jmp, 1);
}

#define RpcExceptionCode() (__f.rec.ExceptionCode)

#define RpcTryExcept \
    { \
        int __need_pop = 1; \
        __widl_except_frame_t __f; \
        __f.frame.Handler = __widl_exception_handler; \
        __f.mask = EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL; \
        __wine_push_frame(&__f.frame); \
        if (!sigsetjmp(__f.jmp, 1)) \
        {
#define RpcExcept(cond) \
        } \
        else \
        { \
            __wine_pop_frame(&__f.frame); \
            __need_pop = 0; \
            if (cond) \
            {
#define RpcEndExcept \
            } \
            else \
                RtlRaiseException(&__f.rec); \
        } \
        if (__need_pop) \
            __wine_pop_frame(&__f.frame); \
    }

#define RpcTryFinally \
    { \
        int __ok = 0; \
        __widl_except_frame_t __f; \
        __f.frame.Handler = __widl_exception_handler; \
        __f.mask = EH_UNWINDING | EH_EXIT_UNWIND; \
        __wine_push_frame(&__f.frame); \
        if (!sigsetjmp(__f.jmp, 1)) \
        {
#define RpcFinally \
            __ok = 1; \
        } \
        __wine_pop_frame(&__f.frame); \
        {
#define RpcEndFinally \
        } \
        if (!__ok) \
            RtlRaiseException(&__f.rec); \
    }

#endif  /* __WINESRC__ */

---
 tools/widl/client.c  |    7 +++
 tools/widl/proxy.c   |    3 +
 tools/widl/server.c  |    1 +
 tools/widl/typegen.c |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/widl/typegen.h |    1 +
 5 files changed, 115 insertions(+), 0 deletions(-)

diff --git a/tools/widl/client.c b/tools/widl/client.c
index 696dd83..d944ab0 100644
--- a/tools/widl/client.c
+++ b/tools/widl/client.c
@@ -141,6 +141,12 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
         print_client("MIDL_STUB_MESSAGE _StubMsg;\n");
         fprintf(client, "\n");
 
+        if (!is_void(def->type))
+        {
+            print_client("/* Silence warnings about being used uninitialized.  */\n");
+            print_client("memset(&_RetVal, 0, sizeof _RetVal);\n\n");
+        }
+
         /* check pointers */
         check_pointers(func);
 
@@ -380,6 +386,7 @@ static void init_client(void)
     fprintf(client, "\n");
     print_client("#include \"%s\"\n", header_name);
     fprintf(client, "\n");
+    write_exception_macros(client);
 }
 
 
diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c
index 8a81885..45f312a 100644
--- a/tools/widl/proxy.c
+++ b/tools/widl/proxy.c
@@ -110,6 +110,7 @@ static void init_proxy(ifref_list_t *ifaces)
   print_proxy( "\n");
   print_proxy( "#include \"%s\"\n", header_name);
   print_proxy( "\n");
+  write_exception_macros(proxy);
   write_formatstringsdecl(proxy, indent, ifaces, need_proxy);
   write_stubdescproto();
 }
@@ -271,6 +272,8 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx,
   print_proxy( "\n");
 
   /* FIXME: trace */
+  print_proxy( "/* Silence warnings about being used uninitialized.  */\n" );
+  print_proxy( "memset(&_RetVal, 0, sizeof _RetVal);\n\n" );
   clear_output_vars( cur->args );
 
   print_proxy( "RpcTryExcept\n" );
diff --git a/tools/widl/server.c b/tools/widl/server.c
index c915662..3ae3f6a 100644
--- a/tools/widl/server.c
+++ b/tools/widl/server.c
@@ -392,6 +392,7 @@ static void init_server(void)
     fprintf(server, "\n");
     print_server("#include \"%s\"\n", header_name);
     fprintf(server, "\n");
+    write_exception_macros(server);
 }
 
 
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 1078ede..d0a8e36 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -54,6 +54,7 @@ struct expr_eval_routine
     const expr_t *expr;
 };
 
+static inline int is_base_type(unsigned char type);
 static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
 static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
@@ -339,6 +340,11 @@ void write_parameters_init(FILE *file, int indent, const func_t *func)
             print_file(file, indent, "MIDL_memset(&%s, 0, sizeof %s);\n", n, n);
         else if (is_ptr(t) || is_array(t))
             print_file(file, indent, "%s = 0;\n", n);
+        else
+        {
+            assert(is_base_type(t->type));
+            print_file(file, indent, "%s = 0;  /* Avoid initialization warnings.  */\n", n);
+        }
     }
 
     fprintf(file, "\n");
@@ -3235,3 +3241,100 @@ void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
 error:
     error("Invalid endpoint syntax '%s'\n", endpoint->str);
 }
+
+void write_exception_macros(FILE *file)
+{
+    print_file(file, 0, "#ifdef __WINESRC__\n");
+    print_file(file, 0, "#include <winternl.h>\n");
+    print_file(file, 0, "#include \"wine/exception.h\"\n\n");
+    print_file(file, 0, "#undef RpcExceptionCode\n");
+    print_file(file, 0, "#undef RpcTryExcept\n");
+    print_file(file, 0, "#undef RpcExcept\n");
+    print_file(file, 0, "#undef RpcEndExcept\n");
+    print_file(file, 0, "#undef RpcTryFinally\n");
+    print_file(file, 0, "#undef RpcFinally\n");
+    print_file(file, 0, "#undef RpcEndFinally\n\n");
+    print_file(file, 0, "#if !defined(__GNUC__) && !defined(__attribute__)\n");
+    print_file(file, 0, "#define __attribute__(x)\n");
+    print_file(file, 0, "#endif\n\n");
+    print_file(file, 0, "typedef struct\n");
+    print_file(file, 0, "{\n");
+    print_file(file, 1, "EXCEPTION_REGISTRATION_RECORD frame;\n");
+    print_file(file, 1, "EXCEPTION_RECORD rec;\n");
+    print_file(file, 1, "sigjmp_buf jmp;\n");
+    print_file(file, 1, "DWORD mask;\n");
+    print_file(file, 0, "} __widl_except_frame_t;\n\n");
+    print_file(file, 0, "static DWORD __widl_exception_handler(\n");
+    print_file(file, 1, "EXCEPTION_RECORD *rec,\n");
+    print_file(file, 1, "EXCEPTION_REGISTRATION_RECORD *frame,\n");
+    print_file(file, 1, "CONTEXT *context __attribute__((unused)),\n");
+    print_file(file, 1, "EXCEPTION_REGISTRATION_RECORD **pdispatcher __attribute__((unused)))\n");
+    print_file(file, 0, "{\n");
+    print_file(file, 1, "__widl_except_frame_t *wef = (__widl_except_frame_t *) frame;\n");
+    print_file(file, 1, "if (rec->ExceptionFlags & wef->mask)\n");
+    print_file(file, 2, "return ExceptionContinueSearch;\n");
+    print_file(file, 1, "if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION\n");
+    print_file(file, 1, "    && 2 <= rec->NumberParameters\n");
+    print_file(file, 1, "    && rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)\n");
+    print_file(file, 1, "{\n");
+    print_file(file, 2, "MEMORY_BASIC_INFORMATION meminfo;\n");
+    print_file(file, 2, "void *addr = (void *) rec->ExceptionInformation[1];\n");
+    print_file(file, 2, "if (VirtualQuery(addr, &meminfo, sizeof meminfo)\n");
+    print_file(file, 2, "    && meminfo.State != MEM_FREE\n");
+    print_file(file, 2, "    && (meminfo.Protect == PAGE_READONLY\n");
+    print_file(file, 2, "        || meminfo.Protect == PAGE_READWRITE\n");
+    print_file(file, 2, "        || meminfo.Protect == PAGE_WRITECOPY))\n");
+    print_file(file, 3, "if (VirtualProtect(addr, 1, meminfo.Protect << 4, NULL))\n");
+    print_file(file, 4, "return ExceptionContinueExecution;\n");
+    print_file(file, 1, "}\n");
+    print_file(file, 1, "wef->rec = *rec;\n");
+    print_file(file, 1, "RtlUnwind(frame, 0, rec, 0);\n");
+    print_file(file, 1, "siglongjmp(wef->jmp, 1);\n");
+    print_file(file, 0, "}\n\n");
+    print_file(file, 0, "#define RpcExceptionCode() (__f.rec.ExceptionCode)\n\n");
+    print_file(file, 0, "#define RpcTryExcept \\\n");
+    print_file(file, 1, "{ \\\n");
+    print_file(file, 2, "int __need_pop = 1; \\\n");
+    print_file(file, 2, "__widl_except_frame_t __f; \\\n");
+    print_file(file, 2, "__f.frame.Handler = __widl_exception_handler; \\\n");
+    print_file(file, 2, "__f.mask = EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL; \\\n");
+    print_file(file, 2, "__wine_push_frame(&__f.frame); \\\n");
+    print_file(file, 2, "if (!sigsetjmp(__f.jmp, 1)) \\\n");
+    print_file(file, 2, "{\n");
+    print_file(file, 0, "#define RpcExcept(cond) \\\n");
+    print_file(file, 2, "} \\\n");
+    print_file(file, 2, "else \\\n");
+    print_file(file, 2, "{ \\\n");
+    print_file(file, 3, "__wine_pop_frame(&__f.frame); \\\n");
+    print_file(file, 3, "__need_pop = 0; \\\n");
+    print_file(file, 3, "if (cond) \\\n");
+    print_file(file, 3, "{\n");
+    print_file(file, 0, "#define RpcEndExcept \\\n");
+    print_file(file, 3, "} \\\n");
+    print_file(file, 3, "else \\\n");
+    print_file(file, 4, "RtlRaiseException(&__f.rec); \\\n");
+    print_file(file, 2, "} \\\n");
+    print_file(file, 2, "if (__need_pop) \\\n");
+    print_file(file, 3, "__wine_pop_frame(&__f.frame); \\\n");
+    print_file(file, 1, "}\n\n");
+    print_file(file, 0, "#define RpcTryFinally \\\n");
+    print_file(file, 1, "{ \\\n");
+    print_file(file, 2, "int __ok = 0; \\\n");
+    print_file(file, 2, "__widl_except_frame_t __f; \\\n");
+    print_file(file, 2, "__f.frame.Handler = __widl_exception_handler; \\\n");
+    print_file(file, 2, "__f.mask = EH_UNWINDING | EH_EXIT_UNWIND; \\\n");
+    print_file(file, 2, "__wine_push_frame(&__f.frame); \\\n");
+    print_file(file, 2, "if (!sigsetjmp(__f.jmp, 1)) \\\n");
+    print_file(file, 2, "{\n");
+    print_file(file, 0, "#define RpcFinally \\\n");
+    print_file(file, 3, "__ok = 1; \\\n");
+    print_file(file, 2, "} \\\n");
+    print_file(file, 2, "__wine_pop_frame(&__f.frame); \\\n");
+    print_file(file, 2, "{\n");
+    print_file(file, 0, "#define RpcEndFinally \\\n");
+    print_file(file, 2, "} \\\n");
+    print_file(file, 2, "if (!__ok) \\\n");
+    print_file(file, 3, "RtlRaiseException(&__f.rec); \\\n");
+    print_file(file, 1, "}\n\n");
+    print_file(file, 0, "#endif  /* __WINESRC__ */\n\n");
+}
diff --git a/tools/widl/typegen.h b/tools/widl/typegen.h
index c9a5148..4e44663 100644
--- a/tools/widl/typegen.h
+++ b/tools/widl/typegen.h
@@ -60,3 +60,4 @@ void print(FILE *file, int indent, const char *format, va_list ap);
 int get_padding(const var_list_t *fields);
 int is_user_type(const type_t *t);
 expr_t *get_size_is_expr(const type_t *t, const char *name);
+void write_exception_macros(FILE *file);



More information about the wine-patches mailing list