[RFC] widl: Add option to generate classfactory

Fabian Maurer dark.shadow4 at web.de
Sat Nov 10 16:20:48 CST 2018


Since the com simplification with the macros is probably not feasible,
here an approach that reuses an old idea - using widl to generate
a classfactory.

Feedback appreciated!
---
 dlls/uiribbon/main.c               | 141 ----------------
 dlls/uiribbon/uiribbon.c           |   8 +-
 dlls/uiribbon/uiribbon_classes.idl |   1 +
 tools/makedep.c                    |   9 +-
 tools/widl/Makefile.in             |   1 +
 tools/widl/factory.c               | 250 +++++++++++++++++++++++++++++
 tools/widl/parser.y                |   1 +
 tools/widl/widl.c                  |  23 ++-
 tools/widl/widl.h                  |   3 +
 9 files changed, 291 insertions(+), 146 deletions(-)
 create mode 100644 tools/widl/factory.c

diff --git a/dlls/uiribbon/main.c b/dlls/uiribbon/main.c
index a76c349ad9..b54644599f 100644
--- a/dlls/uiribbon/main.c
+++ b/dlls/uiribbon/main.c
@@ -56,147 +56,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
     return TRUE;
 }
 
-typedef struct {
-    IClassFactory IClassFactory_iface;
-
-    LONG ref;
-    HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, void **ppObj);
-} IClassFactoryImpl;
-
-static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
-{
-    return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
-}
-
-struct object_creation_info
-{
-    const CLSID *clsid;
-    HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, void **ppObj);
-};
-
-static const struct object_creation_info object_creation[] =
-{
-    { &CLSID_UIRibbonFramework, UIRibbonFrameworkImpl_Create },
-};
-
-static HRESULT WINAPI XFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, void **ppobj)
-{
-    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
-
-    if (IsEqualGUID(riid, &IID_IUnknown)
-        || IsEqualGUID(riid, &IID_IClassFactory))
-    {
-        IClassFactory_AddRef(iface);
-        *ppobj = &This->IClassFactory_iface;
-        return S_OK;
-    }
-
-    WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
-    return E_NOINTERFACE;
-}
-
-static ULONG WINAPI XFCF_AddRef(LPCLASSFACTORY iface)
-{
-    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
-    return InterlockedIncrement(&This->ref);
-}
-
-static ULONG WINAPI XFCF_Release(LPCLASSFACTORY iface)
-{
-    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
-
-    ULONG ref = InterlockedDecrement(&This->ref);
-
-    if (ref == 0)
-        HeapFree(GetProcessHeap(), 0, This);
-
-    return ref;
-}
-
-static HRESULT WINAPI XFCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, void **ppobj)
-{
-    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
-    HRESULT hres;
-    LPUNKNOWN punk;
-
-    TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
-
-    *ppobj = NULL;
-    hres = This->pfnCreateInstance(pOuter, (void **) &punk);
-    if (SUCCEEDED(hres)) {
-        hres = IUnknown_QueryInterface(punk, riid, ppobj);
-        IUnknown_Release(punk);
-    }
-    return hres;
-}
-
-static HRESULT WINAPI XFCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
-{
-    IClassFactoryImpl *This = impl_from_IClassFactory(iface);
-    FIXME("(%p)->(%d), stub!\n",This,dolock);
-    return S_OK;
-}
-
-static const IClassFactoryVtbl XFCF_Vtbl =
-{
-    XFCF_QueryInterface,
-    XFCF_AddRef,
-    XFCF_Release,
-    XFCF_CreateInstance,
-    XFCF_LockServer
-};
-
-/*******************************************************************************
- * Retrieves class object from a DLL object
- *
- * NOTES
- *    Docs say returns STDAPI
- *
- * PARAMS
- *    rclsid [I] CLSID for the class object
- *    riid   [I] Reference to identifier of interface for class object
- *    ppv    [O] Address of variable to receive interface pointer for riid
- *
- * RETURNS
- *    Success: S_OK
- *    Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
- *             E_UNEXPECTED
- */
-HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
-{
-    unsigned int i;
-    IClassFactoryImpl *factory;
-
-    TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
-
-    if ( !IsEqualGUID( &IID_IClassFactory, riid )
-         && ! IsEqualGUID( &IID_IUnknown, riid) )
-        return E_NOINTERFACE;
-
-    for (i = 0; i < ARRAY_SIZE(object_creation); i++)
-    {
-        if (IsEqualGUID(object_creation[i].clsid, rclsid))
-            break;
-    }
-
-    if (i == ARRAY_SIZE(object_creation))
-    {
-        FIXME("%s: no class found.\n", debugstr_guid(rclsid));
-        return CLASS_E_CLASSNOTAVAILABLE;
-    }
-
-    factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
-    if (factory == NULL) return E_OUTOFMEMORY;
-
-    factory->IClassFactory_iface.lpVtbl = &XFCF_Vtbl;
-    factory->ref = 1;
-
-    factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
-
-    *ppv = &(factory->IClassFactory_iface);
-    return S_OK;
-}
-
 HRESULT WINAPI DllCanUnloadNow(void)
 {
     return S_FALSE;
diff --git a/dlls/uiribbon/uiribbon.c b/dlls/uiribbon/uiribbon.c
index 58ac51aece..5385af5430 100644
--- a/dlls/uiribbon/uiribbon.c
+++ b/dlls/uiribbon/uiribbon.c
@@ -156,7 +156,7 @@ static const IUIFrameworkVtbl IUIFramework_Vtbl =
     UIRibbonFrameworkImpl_SetModes
 };
 
-HRESULT UIRibbonFrameworkImpl_Create(IUnknown *pUnkOuter, void **ppObj)
+HRESULT UIRibbonFramework_Create(IUnknown *pUnkOuter, void **ppObj)
 {
     UIRibbonFrameworkImpl *object;
 
@@ -173,3 +173,9 @@ HRESULT UIRibbonFrameworkImpl_Create(IUnknown *pUnkOuter, void **ppObj)
 
     return S_OK;
 }
+
+HRESULT UIRibbonImageFromBitmapFactory_Create(IUnknown *unk_outer, void **obj)
+{
+    FIXME("(%p, %p) - stub!\n", unk_outer, obj);
+    return E_FAIL;
+}
diff --git a/dlls/uiribbon/uiribbon_classes.idl b/dlls/uiribbon/uiribbon_classes.idl
index bd8bdde6b6..78d79a13fc 100644
--- a/dlls/uiribbon/uiribbon_classes.idl
+++ b/dlls/uiribbon/uiribbon_classes.idl
@@ -17,5 +17,6 @@
  */
 
 #pragma makedep register
+#pragma makedep factory
 
 #include "uiribbon.idl"
diff --git a/tools/makedep.c b/tools/makedep.c
index e3bb04ae82..755635f5dc 100644
--- a/tools/makedep.c
+++ b/tools/makedep.c
@@ -100,6 +100,7 @@ struct incl_file
 #define FLAG_RC_PO          0x010000  /* rc file contains translations */
 #define FLAG_C_IMPLIB       0x020000 /* file is part of an import library */
 #define FLAG_SFD_FONTS      0x040000 /* sfd file generated bitmap fonts */
+#define FLAG_IDL_FACTORY    0x080000  /* generates a factory (_f.c) file */
 
 static const struct
 {
@@ -114,7 +115,8 @@ static const struct
     { FLAG_IDL_PROXY,      "_p.c" },
     { FLAG_IDL_SERVER,     "_s.c" },
     { FLAG_IDL_REGISTER,   "_r.res" },
-    { FLAG_IDL_HEADER,     ".h" }
+    { FLAG_IDL_HEADER,     ".h" },
+    { FLAG_IDL_FACTORY,    "_f.c" }
 };
 
 #define HASH_SIZE 997
@@ -996,6 +998,7 @@ static void parse_pragma_directive( struct file *source, char *str )
             else if (!strcmp( flag, "typelib" )) source->flags |= FLAG_IDL_TYPELIB;
             else if (!strcmp( flag, "register" )) source->flags |= FLAG_IDL_REGISTER;
             else if (!strcmp( flag, "regtypelib" )) source->flags |= FLAG_IDL_REGTYPELIB;
+            else if (!strcmp( flag, "factory" )) source->flags |= FLAG_IDL_FACTORY;
         }
         else if (strendswith( source->name, ".rc" ))
         {
@@ -1821,6 +1824,10 @@ static void add_generated_sources( struct makefile *make )
             add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
             add_all_includes( make, file, file->file );
         }
+        if (source->file->flags & FLAG_IDL_FACTORY)
+        {
+            add_generated_source( make, replace_extension( source->name, ".idl", "_f.c" ), NULL );
+        }
         if (source->file->flags & FLAG_IDL_IDENT)
         {
             file = add_generated_source( make, replace_extension( source->name, ".idl", "_i.c" ), NULL );
diff --git a/tools/widl/Makefile.in b/tools/widl/Makefile.in
index e06d6cc5b3..3e725a1c69 100644
--- a/tools/widl/Makefile.in
+++ b/tools/widl/Makefile.in
@@ -4,6 +4,7 @@ MANPAGES = widl.man.in
 C_SRCS = \
 	client.c \
 	expr.c \
+	factory.c \
 	hash.c \
 	header.c \
 	proxy.c \
diff --git a/tools/widl/factory.c b/tools/widl/factory.c
new file mode 100644
index 0000000000..4ed0459b20
--- /dev/null
+++ b/tools/widl/factory.c
@@ -0,0 +1,250 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2018 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+
+#include "widl.h"
+#include "utils.h"
+#include "parser.h"
+#include "header.h"
+
+#include "widltypes.h"
+#include "typegen.h"
+#include "expr.h"
+
+static FILE* factory;
+static int indent = 0;
+
+static void print_factory( const char *format, ... ) __attribute__((format (printf, 1, 2)));
+static void print_factory( const char *format, ... )
+{
+    va_list va;
+    va_start(va, format);
+    print(factory, indent, format, va);
+    va_end(va);
+}
+
+static void init_factory(void)
+{
+    if (factory) return;
+    if (!(factory = fopen(factory_name, "w")))
+        error("Could not open %s for output\n", factory_name);
+
+    print_factory("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name);
+    print_factory("#define COBJMACROS\n");
+    print_factory("#include \"%s\"\n", header_name);
+    print_factory("#include \"wine/debug.h\"\n");
+    print_factory("\n");
+    print_factory("WINE_DEFAULT_DEBUG_CHANNEL(classfactory);\n");
+    print_factory("const char *source = \"%s\";", dup_basename(input_name, ".idl"));
+    print_factory("\n");
+    print_factory("\n");
+
+}
+
+static void write_class_array(const statement_list_t *stmts)
+{
+    const statement_t *stmt;
+
+    /* Declare all functions which need to be provided for the factory */
+    LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
+    {
+        if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_COCLASS)
+        {
+            type_t *object = stmt->u.type;
+            print_factory("HRESULT %s_Create(IUnknown *unk_outer, void **obj);\n", object->name);
+        }
+    }
+    print_factory("\n");
+
+
+    print_factory("struct object_creation_info\n");
+    print_factory("{\n");
+    print_factory("    const CLSID *clsid;\n");
+    print_factory("    HRESULT (*pfnCreateInstance)(IUnknown *unk_outer, void **obj);\n");
+    print_factory("};\n");
+    print_factory("\n");
+
+    print_factory("static const struct object_creation_info object_creation[] =\n");
+    print_factory("{\n");
+
+    LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
+    {
+        if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_COCLASS)
+        {
+            type_t *object = stmt->u.type;
+            print_factory("    {&CLSID_%s, &%s_Create },\n", object->name, object->name);
+        }
+    }
+    print_factory("};\n");
+}
+
+void write_factory_methods(void)
+{
+    print_factory("typedef struct {\n");
+    print_factory("    IClassFactory IClassFactory_iface;\n");
+    print_factory("    LONG ref;\n");
+    print_factory("    HRESULT (*pfnCreateInstance)(IUnknown *unk_outer, void **obj);\n");
+    print_factory("} IClassFactoryImpl;\n");
+    print_factory("\n");
+
+    print_factory("static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)\n");
+    print_factory("{\n");
+    print_factory("    return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);\n");
+    print_factory("}\n");
+    print_factory("\n");
+
+    print_factory("static HRESULT WINAPI classfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)\n");
+    print_factory("{\n");
+    print_factory("    IClassFactoryImpl *impl = impl_from_IClassFactory(iface);\n");
+    print_factory("\n");
+    print_factory("    if (IsEqualGUID(riid, &IID_IUnknown)\n");
+    print_factory("        || IsEqualGUID(riid, &IID_IClassFactory))\n");
+    print_factory("    {\n");
+    print_factory("        IClassFactory_AddRef(iface);\n");
+    print_factory("        *ppobj = &impl->IClassFactory_iface;\n");
+    print_factory("        return S_OK;\n");
+    print_factory("    }\n");
+    print_factory("\n");
+    print_factory("    WARN(\"%%s - (%%p)->(%%s,%%p),not found\\n\", source, impl, debugstr_guid(riid), ppobj);\n");
+    print_factory("    return E_NOINTERFACE;\n");
+    print_factory("}\n");
+    print_factory("\n");
+
+    print_factory("static ULONG WINAPI classfactory_AddRef(IClassFactory *iface)\n");
+    print_factory("{\n");
+    print_factory("    IClassFactoryImpl *This = impl_from_IClassFactory(iface);\n");
+    print_factory("    return InterlockedIncrement(&This->ref);\n");
+    print_factory("}\n");
+    print_factory("\n");
+
+    print_factory("static ULONG WINAPI classfactory_Release(IClassFactory *iface)\n");
+    print_factory("{\n");
+    print_factory("    IClassFactoryImpl *impl = impl_from_IClassFactory(iface);\n");
+    print_factory("    ULONG ref = InterlockedDecrement(&impl->ref);\n");
+    print_factory("\n");
+    print_factory("    if (ref == 0)\n");
+    print_factory("        HeapFree(GetProcessHeap(), 0, impl);\n");
+    print_factory("\n");
+    print_factory("    return ref;\n");
+    print_factory("}\n");
+    print_factory("\n");
+
+    print_factory("static HRESULT WINAPI classfactory_CreateInstance(IClassFactory *iface, IUnknown *outer_unk, REFIID riid, void **ppobj)\n");
+    print_factory("{\n");
+    print_factory("    IClassFactoryImpl *impl = impl_from_IClassFactory(iface);\n");
+    print_factory("    HRESULT hres;\n");
+    print_factory("    IUnknown *unk;\n");
+    print_factory("\n");
+    print_factory("    TRACE(\"%%s - (%%p)->(%%p,%%s,%%p)\\n\", source, impl, outer_unk, debugstr_guid(riid), ppobj);\n");
+    print_factory("\n");
+    print_factory("    *ppobj = NULL;\n");
+    print_factory("    hres = impl->pfnCreateInstance(outer_unk, (void **) &unk);\n");
+    print_factory("    if (SUCCEEDED(hres))\n");
+    print_factory("    {\n");
+    print_factory("        hres = IUnknown_QueryInterface(unk, riid, ppobj);\n");
+    print_factory("        IUnknown_Release(unk);\n");
+    print_factory("    }\n");
+    print_factory("    return hres;\n");
+    print_factory("}\n");
+    print_factory("\n");
+
+    print_factory("static HRESULT WINAPI classfactory_LockServer(IClassFactory *iface, BOOL dolock)\n");
+    print_factory("{\n");
+    print_factory("    IClassFactoryImpl *impl = impl_from_IClassFactory(iface);\n");
+    print_factory("    FIXME(\"%%s - (%%p)->(%%d), stub!\\n\", source, impl, dolock);\n");
+    print_factory("    return S_OK;\n");
+    print_factory("}\n");
+    print_factory("\n");
+
+    print_factory("static const IClassFactoryVtbl classfactory_Vtbl =\n");
+    print_factory("{\n");
+    print_factory("    classfactory_QueryInterface,\n");
+    print_factory("    classfactory_AddRef,\n");
+    print_factory("    classfactory_Release,\n");
+    print_factory("    classfactory_CreateInstance,\n");
+    print_factory("    classfactory_LockServer\n");
+    print_factory("};\n");
+    print_factory("\n");
+
+    print_factory("HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)\n");
+    print_factory("{\n");
+    print_factory("    unsigned int i;\n");
+    print_factory("    IClassFactoryImpl *factory;\n");
+    print_factory("\n");
+    print_factory("    TRACE(\"(%%s - %%s,%%s,%%p)\\n\", source, debugstr_guid(rclsid), debugstr_guid(riid), ppv);\n");
+    print_factory("\n");
+    print_factory("    if (!IsEqualGUID(&IID_IClassFactory, riid)\n");
+    print_factory("         && !IsEqualGUID( &IID_IUnknown, riid))\n");
+    print_factory("        return E_NOINTERFACE;\n");
+    print_factory("\n");
+    print_factory("    for (i = 0; i < ARRAY_SIZE(object_creation); i++)\n");
+    print_factory("    {\n");
+    print_factory("        if (IsEqualGUID(object_creation[i].clsid, rclsid))\n");
+    print_factory("            break;\n");
+    print_factory("    }\n");
+    print_factory("\n");
+    print_factory("    if (i == ARRAY_SIZE(object_creation))\n");
+    print_factory("    {\n");
+    print_factory("        FIXME(\"%%s - %%s: no class found.\\n\", source, debugstr_guid(rclsid));\n");
+    print_factory("        return CLASS_E_CLASSNOTAVAILABLE;\n");
+    print_factory("    }\n");
+    print_factory("\n");
+    print_factory("    factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));\n");
+    print_factory("    if (factory == NULL)\n");
+    print_factory("        return E_OUTOFMEMORY;\n");
+    print_factory("\n");
+    print_factory("    factory->IClassFactory_iface.lpVtbl = &classfactory_Vtbl;\n");
+    print_factory("    factory->ref = 1;\n");
+    print_factory("\n");
+    print_factory("    factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;\n");
+    print_factory("\n");
+    print_factory("    *ppv = &factory->IClassFactory_iface;\n");
+    print_factory("    return S_OK;\n");
+    print_factory("}\n");
+}
+
+void write_factory(const statement_list_t *stmts)
+{
+
+    if (!do_factory)
+        return;
+
+    if (!stmts)
+        return;
+
+    init_factory();
+    if (!factory)
+        return;
+
+    write_class_array(stmts);
+    write_factory_methods();
+
+    fclose(factory);
+}
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index d979394182..ed46b216d0 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -334,6 +334,7 @@ input: gbl_statements m_acf			{ fix_incomplete();
 						  write_typelib_regscript($1);
 						  write_dlldata($1);
 						  write_local_stubs($1);
+						  write_factory($1);
 						}
 	;
 
diff --git a/tools/widl/widl.c b/tools/widl/widl.c
index 410efb4c4c..6e10a5d092 100644
--- a/tools/widl/widl.c
+++ b/tools/widl/widl.c
@@ -58,6 +58,7 @@ static const char usage[] =
 "   -d n               Set debug level to 'n'\n"
 "   -D id[=val]        Define preprocessor identifier id=val\n"
 "   -E                 Preprocess only\n"
+"   -f                 Generate class factory\n"
 "   --help             Display this help and exit\n"
 "   -h                 Generate headers\n"
 "   -H file            Name of header file (default is infile.h)\n"
@@ -111,6 +112,7 @@ int do_server = 0;
 int do_regscript = 0;
 int do_idfile = 0;
 int do_dlldata = 0;
+int do_factory = 0;
 static int no_preprocess = 0;
 int old_names = 0;
 int do_win32 = 1;
@@ -137,6 +139,7 @@ char *server_name;
 char *server_token;
 char *regscript_name;
 char *regscript_token;
+char *factory_name;
 static char *idfile_name;
 char *temp_name;
 const char *prefix_client = "";
@@ -172,7 +175,7 @@ enum {
 };
 
 static const char short_options[] =
-    "b:cC:d:D:EhH:I:m:No:O:pP:rsS:tT:uU:VW";
+    "b:cC:d:D:EfhH:I:m:No:O:pP:rsS:tT:uU:VW";
 static const struct option long_options[] = {
     { "acf", 1, NULL, ACF_OPTION },
     { "app_config", 0, NULL, APP_CONFIG_OPTION },
@@ -319,6 +322,7 @@ static void set_everything(int x)
   do_regscript = x;
   do_idfile = x;
   do_dlldata = x;
+  do_factory = x;
 }
 
 void start_cplusplus_guard(FILE *fp)
@@ -647,6 +651,10 @@ int main(int argc,char *argv[])
       do_everything = 0;
       preprocess_only = 1;
       break;
+    case 'f':
+      do_everything = 0;
+      do_factory = 1;
+      break;
     case 'h':
       do_everything = 0;
       do_header = 1;
@@ -725,7 +733,7 @@ int main(int argc,char *argv[])
 
   /* if nothing specified, try to guess output type from the output file name */
   if (output_name && do_everything && !do_header && !do_typelib && !do_proxies &&
-      !do_client && !do_server && !do_regscript && !do_idfile && !do_dlldata)
+      !do_client && !do_server && !do_regscript && !do_idfile && !do_dlldata && !do_factory)
   {
       do_everything = 0;
       if (strendswith( output_name, ".h" )) do_header = 1;
@@ -737,6 +745,7 @@ int main(int argc,char *argv[])
       else if (strendswith( output_name, "_r.res" )) do_regscript = 1;
       else if (strendswith( output_name, "_t.res" )) do_typelib = 1;
       else if (strendswith( output_name, "dlldata.c" )) do_dlldata = 1;
+      else if (strendswith( output_name, "_f.c" )) do_factory = 1;
       else do_everything = 1;
   }
 
@@ -747,7 +756,7 @@ int main(int argc,char *argv[])
   if (!output_name) output_name = dup_basename(input_name, ".idl");
 
   if (do_header + do_typelib + do_proxies + do_client +
-      do_server + do_regscript + do_idfile + do_dlldata == 1)
+      do_server + do_regscript + do_idfile + do_dlldata + do_factory == 1)
   {
       if (do_header) header_name = output_name;
       else if (do_typelib) typelib_name = output_name;
@@ -757,6 +766,7 @@ int main(int argc,char *argv[])
       else if (do_regscript) regscript_name = output_name;
       else if (do_idfile) idfile_name = output_name;
       else if (do_dlldata) dlldata_name = output_name;
+      else if (do_factory) factory_name = output_name;
   }
 
   if (!dlldata_name && do_dlldata)
@@ -832,6 +842,11 @@ int main(int argc,char *argv[])
     strcat(idfile_name, "_i.c");
   }
 
+  if (!factory_name && do_factory) {
+    factory_name = dup_basename(input_name, ".idl");
+    strcat(factory_name, "_f.c");
+  }
+
   if (do_proxies) proxy_token = dup_basename_token(proxy_name,"_p.c");
   if (do_client) client_token = dup_basename_token(client_name,"_c.c");
   if (do_server) server_token = dup_basename_token(server_name,"_s.c");
@@ -922,4 +937,6 @@ static void rm_tempfile(void)
     unlink(proxy_name);
   if (do_typelib)
     unlink(typelib_name);
+  if (do_factory)
+    unlink(factory_name);
 }
diff --git a/tools/widl/widl.h b/tools/widl/widl.h
index 118e2245c2..759a7b818e 100644
--- a/tools/widl/widl.h
+++ b/tools/widl/widl.h
@@ -44,6 +44,7 @@ extern int do_server;
 extern int do_regscript;
 extern int do_idfile;
 extern int do_dlldata;
+extern int do_factory;
 extern int old_names;
 extern int do_win32;
 extern int do_win64;
@@ -66,6 +67,7 @@ extern char *client_name;
 extern char *client_token;
 extern char *server_name;
 extern char *server_token;
+extern char *factory_name;
 extern char *regscript_name;
 extern char *regscript_token;
 extern const char *prefix_client;
@@ -94,6 +96,7 @@ extern void write_typelib_regscript(const statement_list_t *stmts);
 extern void output_typelib_regscript( const typelib_t *typelib );
 extern void write_local_stubs(const statement_list_t *stmts);
 extern void write_dlldata(const statement_list_t *stmts);
+extern void write_factory(const statement_list_t *stmts);
 
 extern void start_cplusplus_guard(FILE *fp);
 extern void end_cplusplus_guard(FILE *fp);
-- 
2.19.1




More information about the wine-devel mailing list