Rob Shearman : widl: Add support for generic binding handles.

Alexandre Julliard julliard at winehq.org
Thu Mar 27 15:43:23 CDT 2008


Module: wine
Branch: master
Commit: 59556de0c1b7acb5f62a695b7256debb54c5de8c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=59556de0c1b7acb5f62a695b7256debb54c5de8c

Author: Rob Shearman <rob at codeweavers.com>
Date:   Thu Mar 27 14:03:17 2008 +0000

widl: Add support for generic binding handles.

---

 tools/widl/client.c    |   32 +++++++++++++++++++++---
 tools/widl/header.c    |   62 ++++++++++++++++++++++++++++++++++++++++++++++-
 tools/widl/header.h    |    3 ++
 tools/widl/parser.y    |    2 +-
 tools/widl/widl.c      |    1 +
 tools/widl/widltypes.h |    2 +-
 6 files changed, 94 insertions(+), 8 deletions(-)

diff --git a/tools/widl/client.c b/tools/widl/client.c
index eb65d83..47fb25d 100644
--- a/tools/widl/client.c
+++ b/tools/widl/client.c
@@ -99,16 +99,21 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
     {
         const var_t *def = func->def;
         const var_t* explicit_handle_var;
+        const var_t* explicit_generic_handle_var = NULL;
         const var_t* context_handle_var = NULL;
         int has_full_pointer = is_full_pointer_function(func);
 
         /* check for a defined binding handle */
         explicit_handle_var = get_explicit_handle_var(func);
         if (!explicit_handle_var)
-            context_handle_var = get_context_handle_var(func);
+        {
+            explicit_generic_handle_var = get_explicit_generic_handle_var(func);
+            if (!explicit_generic_handle_var)
+                context_handle_var = get_context_handle_var(func);
+        }
         if (explicit_handle)
         {
-            if (!explicit_handle_var || !context_handle_var)
+            if (!explicit_handle_var || !explicit_generic_handle_var || !context_handle_var)
             {
                 error("%s() does not define an explicit binding handle!\n", def->name);
                 return;
@@ -148,7 +153,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
             fprintf(client, " _RetVal;\n");
         }
 
-        if (implicit_handle || explicit_handle_var || context_handle_var)
+        if (implicit_handle || explicit_handle_var || explicit_generic_handle_var || context_handle_var)
             print_client("RPC_BINDING_HANDLE _Handle = 0;\n");
 
         print_client("RPC_MESSAGE _RpcMessage;\n");
@@ -189,12 +194,20 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
             print_client("_Handle = %s;\n", explicit_handle_var->name);
             fprintf(client, "\n");
         }
+        else if (explicit_generic_handle_var)
+        {
+            print_client("_Handle = %s_bind(%s);\n",
+                get_explicit_generic_handle_type(explicit_generic_handle_var)->name,
+                explicit_generic_handle_var->name);
+            fprintf(client, "\n");
+        }
         else if (context_handle_var)
         {
             print_client("if (%s%s != 0)\n", is_ptr(context_handle_var->type) ? "*" : "", context_handle_var->name);
             indent++;
             print_client("_Handle = NDRCContextBinding(%s%s);\n", is_ptr(context_handle_var->type) ? "*" : "", context_handle_var->name);
             indent--;
+            fprintf(client, "\n");
         }
 
         write_remoting_arguments(client, indent, func, PASS_IN, PHASE_BUFFERSIZE);
@@ -203,7 +216,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
         indent++;
         print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
         print_client("_StubMsg.BufferLength,\n");
-        if (implicit_handle || explicit_handle_var || context_handle_var)
+        if (implicit_handle || explicit_handle_var || explicit_generic_handle_var || context_handle_var)
             print_client("_Handle);\n");
         else
             print_client("%s__MIDL_AutoBindHandle);\n", iface->name);
@@ -278,6 +291,17 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
 
         print_client("NdrFreeBuffer((PMIDL_STUB_MESSAGE)&_StubMsg);\n");
 
+        if (!implicit_handle && explicit_generic_handle_var)
+        {
+            fprintf(client, "\n");
+            print_client("if (_Handle)\n");
+            indent++;
+            print_client("%s_unbind(%s, _Handle);\n",
+                get_explicit_generic_handle_type(explicit_generic_handle_var)->name,
+                explicit_generic_handle_var->name);
+            indent--;
+        }
+
         indent--;
         print_client("}\n");
         print_client("RpcEndFinally\n");
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 5ffa549..f1e5a03 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -34,9 +34,12 @@
 #include "parser.h"
 #include "header.h"
 
+typedef struct _user_type_t generic_handle_t;
+
 static int indentation = 0;
 user_type_list_t user_type_list = LIST_INIT(user_type_list);
 static context_handle_list_t context_handle_list = LIST_INIT(context_handle_list);
+static struct list generic_handle_list = LIST_INIT(generic_handle_list);
 
 static void indent(FILE *h, int delta)
 {
@@ -343,7 +346,18 @@ static int context_handle_registered(const char *name)
   return 0;
 }
 
-void check_for_user_types_and_context_handles(const var_list_t *list)
+static int generic_handle_registered(const char *name)
+{
+  generic_handle_t *gh;
+  LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry)
+    if (!strcmp(name, gh->name))
+      return 1;
+  return 0;
+}
+
+/* check for types which require additional prototypes to be generated in the
+ * header */
+void check_for_additional_prototype_types(const var_list_t *list)
 {
   const var_t *v;
 
@@ -365,6 +379,16 @@ void check_for_user_types_and_context_handles(const var_list_t *list)
         /* don't carry on parsing fields within this type */
         break;
       }
+      if (type->type != RPC_FC_BIND_PRIMITIVE && is_attr(type->attrs, ATTR_HANDLE)) {
+        if (!generic_handle_registered(name))
+        {
+          generic_handle_t *gh = xmalloc(sizeof(*gh));
+          gh->name = xstrdup(name);
+          list_add_tail(&generic_handle_list, &gh->entry);
+        }
+        /* don't carry on parsing fields within this type */
+        break;
+      }
       if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
         if (!user_type_registered(name))
         {
@@ -378,7 +402,7 @@ void check_for_user_types_and_context_handles(const var_list_t *list)
       }
       else
       {
-        check_for_user_types_and_context_handles(type->fields);
+        check_for_additional_prototype_types(type->fields);
       }
     }
   }
@@ -407,6 +431,17 @@ void write_context_handle_rundowns(void)
   }
 }
 
+void write_generic_handle_routines(void)
+{
+  generic_handle_t *gh;
+  LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry)
+  {
+    const char *name = gh->name;
+    fprintf(header, "handle_t __RPC_USER %s_bind(%s);\n", name, name);
+    fprintf(header, "void __RPC_USER %s_unbind(%s, handle_t);\n", name, name);
+  }
+}
+
 void write_typedef(type_t *type)
 {
   fprintf(header, "typedef ");
@@ -537,6 +572,29 @@ const var_t* get_explicit_handle_var(const func_t* func)
     return NULL;
 }
 
+const type_t* get_explicit_generic_handle_type(const var_t* var)
+{
+    const type_t *t;
+    for (t = var->type; is_ptr(t); t = t->ref)
+        if (t->type != RPC_FC_BIND_PRIMITIVE && is_attr(t->attrs, ATTR_HANDLE))
+            return t;
+    return NULL;
+}
+
+const var_t* get_explicit_generic_handle_var(const func_t* func)
+{
+    const var_t* var;
+
+    if (!func->args)
+        return NULL;
+
+    LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
+        if (get_explicit_generic_handle_type(var))
+            return var;
+
+    return NULL;
+}
+
 int has_out_arg_or_return(const func_t *func)
 {
     const var_t *var;
diff --git a/tools/widl/header.h b/tools/widl/header.h
index 173bd03..3f4fee2 100644
--- a/tools/widl/header.h
+++ b/tools/widl/header.h
@@ -62,7 +62,10 @@ extern void write_externdef(const var_t *v);
 extern void write_library(const char *name, const attr_list_t *attr);
 extern void write_user_types(void);
 extern void write_context_handle_rundowns(void);
+extern void write_generic_handle_routines(void);
 extern const var_t* get_explicit_handle_var(const func_t* func);
+extern const type_t* get_explicit_generic_handle_type(const var_t* var);
+extern const var_t* get_explicit_generic_handle_var(const func_t* func);
 extern int has_out_arg_or_return(const func_t *func);
 extern void write_guid(FILE *f, const char *guid_prefix, const char *name,
                        const UUID *uuid);
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 3a89723..a4f383f 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -2072,7 +2072,7 @@ static void check_all_user_types(ifref_list_t *ifrefs)
   {
     const func_list_t *fs = ifref->iface->funcs;
     if (fs) LIST_FOR_EACH_ENTRY(f, fs, const func_t, entry)
-      check_for_user_types_and_context_handles(f->args);
+      check_for_additional_prototype_types(f->args);
   }
 }
 
diff --git a/tools/widl/widl.c b/tools/widl/widl.c
index bb3f651..13daf7e 100644
--- a/tools/widl/widl.c
+++ b/tools/widl/widl.c
@@ -601,6 +601,7 @@ int main(int argc,char *argv[])
     fprintf(header, "/* Begin additional prototypes for all interfaces */\n");
     fprintf(header, "\n");
     write_user_types();
+    write_generic_handle_routines();
     write_context_handle_rundowns();
     fprintf(header, "\n");
     fprintf(header, "/* End additional prototypes */\n");
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index acdc3f1..7eaacd1 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -312,7 +312,7 @@ struct _user_type_t {
 extern unsigned char pointer_default;
 
 extern user_type_list_t user_type_list;
-void check_for_user_types_and_context_handles(const var_list_t *list);
+void check_for_additional_prototype_types(const var_list_t *list);
 
 void init_types(void);
 type_t *alloc_type(void);




More information about the wine-cvs mailing list