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 | 11 +- 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, 293 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..8aa4d9e2fc 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,12 @@ 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) + { + file = add_generated_source( make, replace_extension( source->name, ".idl", "_f.c" ), NULL ); + 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_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);
Hi Fabian,
On 10/11/2018 23:57, Fabian Maurer wrote:
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.
Since the code that you generate seems very similar to what you sent in header, comments that I sent you to that patch apply here as well.
Other than that, you introduce wine/debug.h dependency in widl generated sources, which makes it usable only for Wine internals. Introducing something only for Wine internals in widl could be fine if justified, but I'm not sure that's the case.
This implementation does not allow DLLs to mix custom class factories and generated ones in the same DLL. Some class factories need for example additional interfaces. Those will have to be implemented from scratch, which is fine. But if other class factories from the same DLL could use generic implementation, they can't because of how DllGetClassObject is generated.
On the first look I liked the idea of using widl for class factories. But after having closer look, I'm no longer convinced it's the right tool. Class factories are really simple things, and having widl extension might be more complexity than it's worth. A simple header with default implementation and a single macro just for vtbl (not for the actual code) is all that's really needed.
Thanks, Jacek