NdrClientCall() should only be used in 32-bit mode when Oi or Oic stub optimizations are used. Currently our interpreted mode targets Oicf mode and other levels are not supported.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
From: Nikolay Sivov nsivov@codeweavers.com
NdrClientCall() should only be used in 32-bit mode when Oi or Oic stub optimizations are used. Currently our interpreted mode targets Oicf mode and other levels are not supported.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- tools/widl/typegen.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 9567b2d5e4e..1db6ee5093b 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -5239,9 +5239,7 @@ void write_client_call_routine( FILE *file, const type_t *iface, const var_t *fu } else if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n\n" );
- len = fprintf( file, " %s%s( ", - has_ret ? "_RetVal = " : "", - interpreted_mode ? "NdrClientCall2" : "NdrClientCall" ); + len = fprintf( file, " %sNdrClientCall2( ", has_ret ? "_RetVal = " : "" ); fprintf( file, "&%s_StubDesc,", prefix ); fprintf( file, "\n%*s&__MIDL_ProcFormatString.Format[%u]", len, "", proc_offset ); if (needs_params)
From: Nikolay Sivov nsivov@codeweavers.com
The issue comes from per-field structure copy that we generate on 32-bit. For non-pointer fields like "const int" this breaks compilation when assigning to a const field. The best solution would be to remove local struct variable completely and pass first argument address as a stack address. This is what midl does. My understanding is that doing it midl way used to break on some compilers, and we have to keep the copy. Once we encounter pointer type that needs such copy, we'll have to patch it more to cast the const away for example.
Such type modification matches what midl does for structures in _Thunk's, so the fix itself is correct.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- tools/widl/header.c | 21 +++++++++++---------- tools/widl/header.h | 3 ++- tools/widl/typegen.c | 8 ++++---- 3 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c index 31b476df677..e14194bb62a 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -279,7 +279,8 @@ static void write_pointer_left(FILE *h, type_t *ref) fprintf(h, "*"); }
-void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, bool define, int write_callconv) +void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, bool define, + int write_callconv, bool noconst) { type_t *t = ds->type; const char *decl_name, *name; @@ -293,7 +294,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, b if (ds->func_specifier & FUNCTION_SPECIFIER_INLINE) fprintf(h, "inline ");
- if ((ds->qualifier & TYPE_QUALIFIER_CONST) && (type_is_alias(t) || !is_ptr(t))) + if ((ds->qualifier & TYPE_QUALIFIER_CONST) && (!noconst && (type_is_alias(t) || !is_ptr(t)))) fprintf(h, "const ");
if (type_is_alias(t)) fprintf(h, "%s", name); @@ -350,7 +351,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, b break; case TYPE_POINTER: { - write_type_left(h, type_pointer_get_ref(t), name_type, define, FALSE); + write_type_left(h, type_pointer_get_ref(t), name_type, define, FALSE, false); write_pointer_left(h, type_pointer_get_ref_type(t)); if (ds->qualifier & TYPE_QUALIFIER_CONST) fprintf(h, "const "); break; @@ -360,14 +361,14 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, b fprintf(h, "%s", t->name); else { - write_type_left(h, type_array_get_element(t), name_type, define, !type_array_is_decl_as_ptr(t)); + write_type_left(h, type_array_get_element(t), name_type, define, !type_array_is_decl_as_ptr(t), false); if (type_array_is_decl_as_ptr(t)) write_pointer_left(h, type_array_get_element_type(t)); } break; case TYPE_FUNCTION: { - write_type_left(h, type_function_get_ret(t), name_type, define, TRUE); + write_type_left(h, type_function_get_ret(t), name_type, define, TRUE, false);
/* A pointer to a function has to write the calling convention inside * the parentheses. There's no way to handle that here, so we have to @@ -446,7 +447,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, b case TYPE_BITFIELD: { const decl_spec_t ds = {.type = type_bitfield_get_field(t)}; - write_type_left(h, &ds, name_type, define, TRUE); + write_type_left(h, &ds, name_type, define, TRUE, false); break; } case TYPE_ALIAS: @@ -548,7 +549,7 @@ static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, bool defi
if (!h) return;
- if (t) write_type_left(h, ds, name_type, define, TRUE); + if (t) write_type_left(h, ds, name_type, define, TRUE, false);
if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name );
@@ -570,14 +571,14 @@ static void write_type_definition(FILE *f, type_t *t, bool define) write_namespace_start(f, t->namespace); } indent(f, 0); - write_type_left(f, &ds, NAME_DEFAULT, define, TRUE); + write_type_left(f, &ds, NAME_DEFAULT, define, TRUE, false); fprintf(f, ";\n"); if(in_namespace) { t->written = save_written; write_namespace_end(f, t->namespace); fprintf(f, "extern "C" {\n"); fprintf(f, "#else\n"); - write_type_left(f, &ds, NAME_C, define, TRUE); + write_type_left(f, &ds, NAME_C, define, TRUE, false); fprintf(f, ";\n"); if (winrt_mode) write_widl_using_macros(f, t); fprintf(f, "#endif\n\n"); @@ -592,7 +593,7 @@ void write_type_decl(FILE *f, const decl_spec_t *t, const char *name)
void write_type_decl_left(FILE *f, const decl_spec_t *ds) { - write_type_left(f, ds, NAME_DEFAULT, false, TRUE); + write_type_left(f, ds, NAME_DEFAULT, false, TRUE, false); }
static int user_type_registered(const char *name) diff --git a/tools/widl/header.h b/tools/widl/header.h index 45066898a66..da5a3d1075c 100644 --- a/tools/widl/header.h +++ b/tools/widl/header.h @@ -24,7 +24,8 @@ #include "typetree.h"
extern const char* get_name(const var_t *v); -extern void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, bool define, int write_callconv); +extern void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, + bool define, int write_callconv, bool noconst); extern void write_type_right(FILE *h, type_t *t, int is_field); extern void write_type_decl(FILE *f, const decl_spec_t *t, const char *name); extern void write_type_decl_left(FILE *f, const decl_spec_t *ds); diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 1db6ee5093b..d3c7749d216 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -5055,7 +5055,7 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { print_file(file, 2, "%s", ""); - write_type_left( file, &arg->declspec, NAME_DEFAULT, false, TRUE ); + write_type_left( file, &arg->declspec, NAME_DEFAULT, false, TRUE, true ); if (needs_space_after( arg->declspec.type )) fputc( ' ', file ); if (is_array( arg->declspec.type ) && !type_array_is_decl_as_ptr( arg->declspec.type )) fputc( '*', file );
@@ -5071,7 +5071,7 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun if (add_retval && !is_void( retval->declspec.type )) { print_file(file, 2, "%s", ""); - write_type_left( file, &retval->declspec, NAME_DEFAULT, false, TRUE ); + write_type_left( file, &retval->declspec, NAME_DEFAULT, false, TRUE, true ); if (needs_space_after( retval->declspec.type )) fputc( ' ', file ); if (!is_array( retval->declspec.type ) && !is_ptr( retval->declspec.type ) && type_memsize( retval->declspec.type ) != pointer_size) @@ -5122,9 +5122,9 @@ int write_expr_eval_routines(FILE *file, const char *iface) { decl_spec_t ds = {.type = (type_t *)eval->cont_type}; print_file(file, 1, "%s", ""); - write_type_left(file, &ds, NAME_DEFAULT, false, TRUE); + write_type_left(file, &ds, NAME_DEFAULT, false, TRUE, false); fprintf(file, " *%s = (", var_name); - write_type_left(file, &ds, NAME_DEFAULT, false, TRUE); + write_type_left(file, &ds, NAME_DEFAULT, false, TRUE, false); fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff); } print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
From: Piotr Caban piotr@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/msdaps/usrmarshal.c | 45 ++++++++++++++++++++++++ include/Makefile.in | 1 + include/errlup.idl | 74 ++++++++++++++++++++++++++++++++++++++++ include/oledb.idl | 1 + 4 files changed, 121 insertions(+) create mode 100644 include/errlup.idl
diff --git a/dlls/msdaps/usrmarshal.c b/dlls/msdaps/usrmarshal.c index 476008b53f9..80ae1305872 100644 --- a/dlls/msdaps/usrmarshal.c +++ b/dlls/msdaps/usrmarshal.c @@ -1856,3 +1856,48 @@ HRESULT __RPC_STUB IDBSchemaRowset_GetSchemas_Stub(IDBSchemaRowset* This, ULONG FIXME("(%p)->(%p, %p, %p, %p): stub\n", This, pcSchemas, prgSchemas, prgRestrictionSupport, ppErrorInfoRem); return E_NOTIMPL; } + +HRESULT CALLBACK IErrorLookup_GetErrorDescription_Proxy(IErrorLookup* This, HRESULT hrError, DWORD dwLookupID, + DISPPARAMS *pdispparams, LCID lcid, BSTR *pbstrSource, BSTR *pbstrDescription) +{ + FIXME("(%p)->(%#lx, %#lx, %p, %#lx, %p, %p): stub\n", This, hrError, dwLookupID, pdispparams, lcid, + pbstrSource, pbstrDescription); + return E_NOTIMPL; +} + +HRESULT __RPC_STUB IErrorLookup_GetErrorDescription_Stub(IErrorLookup* This, HRESULT hrError, DWORD dwLookupID, + DISPPARAMS *pdispparams, LCID lcid, BSTR *pbstrSource, BSTR *pbstrDescription, IErrorInfo **ppErrorInfoRem) +{ + FIXME("(%p)->(%#lx, %#lx, %p, %#lx, %p, %p, %p): stub\n", This, hrError, dwLookupID, pdispparams, lcid, + pbstrSource, pbstrDescription, ppErrorInfoRem); + return E_NOTIMPL; +} + +HRESULT CALLBACK IErrorLookup_GetHelpInfo_Proxy(IErrorLookup* This, HRESULT hrError, + DWORD dwLookupID, LCID lcid, BSTR *pbstrHelpFile, DWORD *pdwHelpContext) +{ + FIXME("(%p)->(%#lx, %#lx, %#lx, %p, %p): stub\n", This, hrError, dwLookupID, lcid, + pbstrHelpFile, pdwHelpContext); + return E_NOTIMPL; +} + +HRESULT __RPC_STUB IErrorLookup_GetHelpInfo_Stub(IErrorLookup* This, HRESULT hrError, DWORD dwLookupID, + LCID lcid, BSTR *pbstrHelpFile, DWORD *pdwHelpContext, IErrorInfo **ppErrorInfoRem) +{ + FIXME("(%p)->(%#lx, %#lx, %#lx, %p, %p, %p): stub\n", This, hrError, dwLookupID, lcid, + pbstrHelpFile, pdwHelpContext, ppErrorInfoRem); + return E_NOTIMPL; +} + +HRESULT CALLBACK IErrorLookup_ReleaseErrors_Proxy(IErrorLookup* This, const DWORD dwDynamicErrorID) +{ + FIXME("(%p)->(%#lx): stub\n", This, dwDynamicErrorID); + return E_NOTIMPL; +} + +HRESULT __RPC_STUB IErrorLookup_ReleaseErrors_Stub(IErrorLookup* This, + const DWORD dwDynamicErrorID, IErrorInfo **ppErrorInfoRem) +{ + FIXME("(%p)->(%#lx, %p): stub\n", This, dwDynamicErrorID, ppErrorInfoRem); + return E_NOTIMPL; +} diff --git a/include/Makefile.in b/include/Makefile.in index ab4957969d3..d40654f1936 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -311,6 +311,7 @@ SOURCES = \ dxvahd.idl \ dyngraph.idl \ endpointvolume.idl \ + errlup.idl \ errorrep.h \ errors.h \ errrec.idl \ diff --git a/include/errlup.idl b/include/errlup.idl new file mode 100644 index 00000000000..f1fca5b27bc --- /dev/null +++ b/include/errlup.idl @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2025 Piotr Caban + * + * 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 + */ + +#if 0 +#pragma makedep install +#endif + +[ + object, + uuid(0c733a66-2a1c-11ce-ade5-00aa0044773d), + pointer_default(unique) +] +interface IErrorLookup : IUnknown { + [local] + HRESULT GetErrorDescription( + [in] HRESULT hrError, + [in] DWORD dwLookupID, + [in] DISPPARAMS *pdispparams, + [in] LCID lcid, + [out] BSTR *pbstrSource, + [out] BSTR *pbstrDescription); + + [call_as(GetErrorDescription)] + HRESULT RemoteGetErrorDescription( + [in] HRESULT hrError, + [in] DWORD dwLookupID, + [in] DISPPARAMS *pdispparams, + [in] LCID lcid, + [out] BSTR *pbstrSource, + [out] BSTR *pbstrDescription, + [out] IErrorInfo **ppErrorInfoRem); + + [local] + HRESULT GetHelpInfo( + [in] HRESULT hrError, + [in] DWORD dwLookupID, + [in] LCID lcid, + [out] BSTR *pbstrHelpFile, + [out] DWORD *pdwHelpContext); + + [call_as(GetHelpInfo)] + HRESULT RemoteGetHelpInfo( + [in] HRESULT hrError, + [in] DWORD dwLookupID, + [in] LCID lcid, + [out] BSTR *pbstrHelpFile, + [out] DWORD *pdwHelpContext, + [out] IErrorInfo **ppErrorInfoRem); + + [local] + HRESULT ReleaseErrors( + [in] const DWORD dwDynamicErrorID); + + [call_as(ReleaseErrors)] + HRESULT RemoteReleaseErrors( + [in] const DWORD dwDynamicErrorID, + [out] IErrorInfo **ppErrorInfoRem); + +} diff --git a/include/oledb.idl b/include/oledb.idl index 4677e3055a8..54fe572f2dc 100644 --- a/include/oledb.idl +++ b/include/oledb.idl @@ -75,6 +75,7 @@ typedef LONG_PTR DB_LRESERVE; #include "binres.idl" #include "crtrow.idl" #include "errrec.idl" +#include "errlup.idl" #include "getdts.idl" #include "cmdstrm.idl" #include "cmdprp.idl"
Rémi Bernon (@rbernon) commented about tools/widl/typegen.c:
if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { print_file(file, 2, "%s", "");
write_type_left( file, &arg->declspec, NAME_DEFAULT, false, TRUE );
write_type_left( file, &arg->declspec, NAME_DEFAULT, false, TRUE, true );
Can we rather make a local copy of the declspec to clear the const spec than add yet another parameter to this horrible function?