[PATCH v6 0/4] MR10659: combase: Implement restricted WinRT error handling APIs.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58900 Bug 58900 This series implements restricted WinRT error handling in combase and\ adds conformance tests for the new behavior. Implemented APIs include restricted error creation / retrieval,\ error context capture, transform, matching, and unhandled error reporting\ paths. Tests were added under dlls/combase/tests and pass locally.\ The existing combase tests also continue to pass. -- v6: combase/tests: Temporarily trim restricted error handling coverage. https://gitlab.winehq.org/wine/wine/-/merge_requests/10659
From: Anna R Békefi <annareginabekefi@gmail.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58900 --- dlls/combase/combase.spec | 10 +- dlls/combase/errorinfo.c | 308 ++++++++++++++++++++++ dlls/combase/roapi.c | 535 +++++++++++++++++++++++++++++++++++++- 3 files changed, 835 insertions(+), 18 deletions(-) diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 19249e17f87..345f48360f8 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -288,8 +288,8 @@ @ stdcall PropVariantCopy(ptr ptr) @ stub ReleaseFuncDescs @ stdcall RoActivateInstance(ptr ptr) -@ stub RoCaptureErrorContext -@ stub RoClearError +@ stdcall RoCaptureErrorContext(long) +@ stdcall RoClearError() @ stdcall RoFailFastWithErrorContext(long) @ stub RoFreeParameterizedTypeExtra @ stub RoGetActivatableClassRegistration @@ -297,7 +297,7 @@ @ stdcall RoGetAgileReference(long ptr ptr ptr) @ stdcall RoGetApartmentIdentifier(ptr) @ stdcall RoGetErrorReportingFlags(ptr) -@ stub RoGetMatchingRestrictedErrorInfo +@ stdcall RoGetMatchingRestrictedErrorInfo(long ptr) @ stdcall RoGetParameterizedTypeInstanceIID(long ptr ptr ptr ptr) @ stdcall RoGetServerActivatableClasses(ptr ptr ptr) @ stdcall RoInitialize(long) @@ -315,8 +315,8 @@ @ stub RoResolveRestrictedErrorInfoReference @ stub RoRevokeActivationFactories @ stdcall RoSetErrorReportingFlags(long) -@ stub RoTransformError -@ stub RoTransformErrorW +@ stdcall RoTransformError(long long ptr) +@ stdcall RoTransformErrorW(long long long ptr) @ stdcall RoUninitialize() @ stub RoUnregisterForApartmentShutdown @ stub SetCleanupFlag diff --git a/dlls/combase/errorinfo.c b/dlls/combase/errorinfo.c index 9383e8d5a72..afe30e43080 100644 --- a/dlls/combase/errorinfo.c +++ b/dlls/combase/errorinfo.c @@ -27,6 +27,9 @@ #include "wine/debug.h" +#include "roerrorapi.h" + + WINE_DEFAULT_DEBUG_CHANNEL(ole); struct error_info @@ -393,3 +396,308 @@ HRESULT WINAPI SetErrorInfo(ULONG reserved, IErrorInfo *error_info) return S_OK; } + +/*********************************************************************** + * IRestrictedErrorInfo implementation / helper (combase internal) + */ +struct restricted_error_info +{ + IRestrictedErrorInfo IRestrictedErrorInfo_iface; + IErrorInfo IErrorInfo_iface; + LONG refcount; + + GUID guid; + WCHAR *source; + WCHAR *help_file; + DWORD help_context; + + HRESULT hr; + WCHAR *description; + WCHAR *restricted_description; + WCHAR *capability_sid; + WCHAR *reference; + + BOOL context_captured; + USHORT stack_frame_count; + void *stack_frames[32]; + ULONG stack_hash; +}; + +static struct restricted_error_info *impl_from_IRestrictedErrorInfo(IRestrictedErrorInfo *iface) +{ + return CONTAINING_RECORD(iface, struct restricted_error_info, IRestrictedErrorInfo_iface); +} + +static struct restricted_error_info *impl_from_restricted_IErrorInfo(IErrorInfo *iface) +{ + return CONTAINING_RECORD(iface, struct restricted_error_info, IErrorInfo_iface); +} + +static ULONG restricted_errorinfo_addref(struct restricted_error_info *info) +{ + ULONG refcount = InterlockedIncrement(&info->refcount); + + TRACE("%p, refcount %lu.\n", info, refcount); + return refcount; +} + +static ULONG restricted_errorinfo_release(struct restricted_error_info *info) +{ + ULONG refcount = InterlockedDecrement(&info->refcount); + + TRACE("%p, refcount %lu.\n", info, refcount); + + if (!refcount) + { + free(info->source); + free(info->help_file); + free(info->description); + free(info->restricted_description); + free(info->capability_sid); + free(info->reference); + free(info); + } + + return refcount; +} + +static HRESULT WINAPI restricted_errorinfo_QueryInterface(IRestrictedErrorInfo *iface, REFIID riid, void **obj) +{ + struct restricted_error_info *info = impl_from_IRestrictedErrorInfo(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (!obj) return E_POINTER; + *obj = NULL; + + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IRestrictedErrorInfo)) + *obj = &info->IRestrictedErrorInfo_iface; + else if (IsEqualIID(riid, &IID_IErrorInfo)) + *obj = &info->IErrorInfo_iface; + + if (*obj) + { + restricted_errorinfo_addref(info); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI restricted_errorinfo_AddRef(IRestrictedErrorInfo *iface) +{ + struct restricted_error_info *info = impl_from_IRestrictedErrorInfo(iface); + return restricted_errorinfo_addref(info); +} + +static ULONG WINAPI restricted_errorinfo_Release(IRestrictedErrorInfo *iface) +{ + struct restricted_error_info *info = impl_from_IRestrictedErrorInfo(iface); + return restricted_errorinfo_release(info); +} + +static HRESULT WINAPI restricted_errorinfo_GetErrorDetails(IRestrictedErrorInfo *iface, + BSTR *description, HRESULT *error, BSTR *restricted_description, BSTR *capability_sid) +{ + struct restricted_error_info *info = impl_from_IRestrictedErrorInfo(iface); + + TRACE("%p, %p, %p, %p, %p.\n", iface, description, error, restricted_description, capability_sid); + + if (description) + *description = info->description ? SysAllocString(info->description) : NULL; + if (error) + *error = info->hr; + if (restricted_description) + *restricted_description = info->restricted_description ? SysAllocString(info->restricted_description) : NULL; + if (capability_sid) + *capability_sid = info->capability_sid ? SysAllocString(info->capability_sid) : NULL; + + return S_OK; +} + +static HRESULT WINAPI restricted_errorinfo_GetReference(IRestrictedErrorInfo *iface, BSTR *reference) +{ + struct restricted_error_info *info = impl_from_IRestrictedErrorInfo(iface); + + TRACE("%p, %p.\n", iface, reference); + + if (!reference) return E_POINTER; + *reference = info->reference ? SysAllocString(info->reference) : NULL; + return S_OK; +} + +static HRESULT WINAPI restricted_errorinfo_ierror_QueryInterface(IErrorInfo *iface, REFIID riid, void **obj) +{ + struct restricted_error_info *info = impl_from_restricted_IErrorInfo(iface); + return IRestrictedErrorInfo_QueryInterface(&info->IRestrictedErrorInfo_iface, riid, obj); +} + +static ULONG WINAPI restricted_errorinfo_ierror_AddRef(IErrorInfo *iface) +{ + struct restricted_error_info *info = impl_from_restricted_IErrorInfo(iface); + return restricted_errorinfo_addref(info); +} + +static ULONG WINAPI restricted_errorinfo_ierror_Release(IErrorInfo *iface) +{ + struct restricted_error_info *info = impl_from_restricted_IErrorInfo(iface); + return restricted_errorinfo_release(info); +} + +static HRESULT WINAPI restricted_errorinfo_ierror_GetGUID(IErrorInfo *iface, GUID *guid) +{ + struct restricted_error_info *info = impl_from_restricted_IErrorInfo(iface); + + TRACE("%p, %p.\n", iface, guid); + + if (!guid) return E_INVALIDARG; + *guid = info->guid; + return S_OK; +} + +static HRESULT WINAPI restricted_errorinfo_ierror_GetSource(IErrorInfo *iface, BSTR *source) +{ + struct restricted_error_info *info = impl_from_restricted_IErrorInfo(iface); + + TRACE("%p, %p.\n", iface, source); + + if (!source) return E_INVALIDARG; + *source = info->source ? SysAllocString(info->source) : NULL; + return S_OK; +} + +static HRESULT WINAPI restricted_errorinfo_ierror_GetDescription(IErrorInfo *iface, BSTR *description) +{ + struct restricted_error_info *info = impl_from_restricted_IErrorInfo(iface); + + TRACE("%p, %p.\n", iface, description); + + if (!description) return E_INVALIDARG; + *description = info->description ? SysAllocString(info->description) : NULL; + return S_OK; +} + +static HRESULT WINAPI restricted_errorinfo_ierror_GetHelpFile(IErrorInfo *iface, BSTR *helpfile) +{ + struct restricted_error_info *info = impl_from_restricted_IErrorInfo(iface); + + TRACE("%p, %p.\n", iface, helpfile); + + if (!helpfile) return E_INVALIDARG; + *helpfile = info->help_file ? SysAllocString(info->help_file) : NULL; + return S_OK; +} + +static HRESULT WINAPI restricted_errorinfo_ierror_GetHelpContext(IErrorInfo *iface, DWORD *help_context) +{ + struct restricted_error_info *info = impl_from_restricted_IErrorInfo(iface); + + TRACE("%p, %p.\n", iface, help_context); + + if (!help_context) return E_INVALIDARG; + *help_context = info->help_context; + return S_OK; +} + +static const IErrorInfoVtbl restricted_errorinfo_ierror_vtbl = +{ + restricted_errorinfo_ierror_QueryInterface, + restricted_errorinfo_ierror_AddRef, + restricted_errorinfo_ierror_Release, + restricted_errorinfo_ierror_GetGUID, + restricted_errorinfo_ierror_GetSource, + restricted_errorinfo_ierror_GetDescription, + restricted_errorinfo_ierror_GetHelpFile, + restricted_errorinfo_ierror_GetHelpContext +}; + +static const IRestrictedErrorInfoVtbl restricted_errorinfo_vtbl = +{ + restricted_errorinfo_QueryInterface, + restricted_errorinfo_AddRef, + restricted_errorinfo_Release, + restricted_errorinfo_GetErrorDetails, + restricted_errorinfo_GetReference +}; + +HRESULT create_restricted_error_info(HRESULT hr, const WCHAR *description, + const WCHAR *restricted_description, const WCHAR *capability_sid, + const WCHAR *reference, IRestrictedErrorInfo **ret) +{ + struct restricted_error_info *info; + + TRACE("%#lx, %s, %s, %s, %s, %p.\n", hr, debugstr_w(description), + debugstr_w(restricted_description), debugstr_w(capability_sid), + debugstr_w(reference), ret); + + if (!ret) return E_INVALIDARG; + *ret = NULL; + + info = calloc(1, sizeof(*info)); + if (!info) return E_OUTOFMEMORY; + + info->IRestrictedErrorInfo_iface.lpVtbl = &restricted_errorinfo_vtbl; + info->IErrorInfo_iface.lpVtbl = &restricted_errorinfo_ierror_vtbl; + info->refcount = 1; + + info->guid = GUID_NULL; + info->source = NULL; + info->help_file = NULL; + info->help_context = 0; + + info->hr = hr; + info->description = description ? wcsdup(description) : NULL; + info->restricted_description = restricted_description ? wcsdup(restricted_description) : NULL; + info->capability_sid = capability_sid ? wcsdup(capability_sid) : NULL; + info->reference = reference ? wcsdup(reference) : NULL; + + info->context_captured = FALSE; + info->stack_frame_count = 0; + info->stack_hash = 0; + + *ret = &info->IRestrictedErrorInfo_iface; + return S_OK; +} + +HRESULT capture_restricted_error_context(IRestrictedErrorInfo *iface, HRESULT hr) +{ + struct restricted_error_info *info; + ULONG hash = 0; + + TRACE("%p, %#lx.\n", iface, hr); + + if (!iface) + return E_INVALIDARG; + + info = impl_from_IRestrictedErrorInfo(iface); + + info->hr = hr; + memset(info->stack_frames, 0, sizeof(info->stack_frames)); + info->stack_frame_count = RtlCaptureStackBackTrace(1, ARRAY_SIZE(info->stack_frames), + info->stack_frames, &hash); + info->stack_hash = hash; + info->context_captured = TRUE; + + return S_OK; +} + +HRESULT copy_restricted_error_context(IRestrictedErrorInfo *dst_iface, IRestrictedErrorInfo *src_iface) +{ + struct restricted_error_info *dst, *src; + + TRACE("%p, %p.\n", dst_iface, src_iface); + + if (!dst_iface || !src_iface) + return E_INVALIDARG; + + dst = impl_from_IRestrictedErrorInfo(dst_iface); + src = impl_from_IRestrictedErrorInfo(src_iface); + + dst->context_captured = src->context_captured; + dst->stack_frame_count = src->stack_frame_count; + memcpy(dst->stack_frames, src->stack_frames, sizeof(dst->stack_frames)); + dst->stack_hash = src->stack_hash; + + return S_OK; +} diff --git a/dlls/combase/roapi.c b/dlls/combase/roapi.c index f4f7c0aac26..7137294e201 100644 --- a/dlls/combase/roapi.c +++ b/dlls/combase/roapi.c @@ -17,6 +17,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define COBJMACROS +#define WINOLEAUTAPI #include "objbase.h" #include "initguid.h" #include "roapi.h" @@ -29,8 +30,26 @@ #include "wine/debug.h" +HRESULT create_restricted_error_info(HRESULT hr, const WCHAR *description, + const WCHAR *restricted_description, const WCHAR *capability_sid, + const WCHAR *reference, IRestrictedErrorInfo **ret); + +HRESULT capture_restricted_error_context(IRestrictedErrorInfo *iface, HRESULT hr); + +HRESULT copy_restricted_error_context(IRestrictedErrorInfo *dst_iface, IRestrictedErrorInfo *src_iface); + +HRESULT WINAPI RoGetMatchingRestrictedErrorInfo(HRESULT error, IRestrictedErrorInfo **info); + WINE_DEFAULT_DEBUG_CHANNEL(combase); +static UINT32 ro_error_reporting_flags = RO_ERROR_REPORTING_USESETERRORINFO; + +#define RO_ERROR_REPORTING_VALID_MASK \ + (RO_ERROR_REPORTING_SUPPRESSEXCEPTIONS | \ + RO_ERROR_REPORTING_FORCEEXCEPTIONS | \ + RO_ERROR_REPORTING_USESETERRORINFO | \ + RO_ERROR_REPORTING_SUPPRESSSETERRORINFO) + struct activatable_class_data { ULONG size; @@ -40,6 +59,86 @@ struct activatable_class_data DWORD threading_model; }; +static WCHAR *duplicate_bounded_message(const WCHAR *message, UINT cchMax) +{ + UINT len = 0, limit = 511; + WCHAR *copy; + + if (!message) + return NULL; + + if (!cchMax) + { + while (len < limit && message[len]) + len++; + } + else + { + while (len < cchMax && len < limit && message[len]) + len++; + } + + if (!len) + return NULL; + + copy = malloc((len + 1) * sizeof(*copy)); + if (!copy) + return NULL; + + memcpy(copy, message, len * sizeof(*copy)); + copy[len] = 0; + return copy; +} + +static BOOL is_current_thread_com_initialized(void) +{ + struct tlsdata *tlsdata = NtCurrentTeb()->ReservedForOle; + + return tlsdata && (tlsdata->inits || tlsdata->ole_inits); +} + +static BOOL should_use_seterrorinfo(void) +{ + if (ro_error_reporting_flags & RO_ERROR_REPORTING_SUPPRESSSETERRORINFO) + return FALSE; + if (!(ro_error_reporting_flags & RO_ERROR_REPORTING_USESETERRORINFO)) + return FALSE; + if (!is_current_thread_com_initialized()) + return FALSE; + + return TRUE; +} + +static WCHAR *get_generic_error_message(HRESULT error) +{ + WCHAR *system_message = NULL, *copy; + DWORD len, flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS; + + len = FormatMessageW(flags, NULL, error, 0, (WCHAR *)&system_message, 0, NULL); + if (!len) + len = FormatMessageW(flags, NULL, E_FAIL, 0, (WCHAR *)&system_message, 0, NULL); + + if (!len || !system_message) + return wcsdup(L"Unspecified error"); + + while (len && (system_message[len - 1] == '\r' || system_message[len - 1] == '\n')) + system_message[--len] = 0; + + if (len > 511) + len = 511; + + copy = malloc((len + 1) * sizeof(*copy)); + if (copy) + { + memcpy(copy, system_message, len * sizeof(*copy)); + copy[len] = 0; + } + + LocalFree(system_message); + return copy; +} + static HRESULT get_library_for_classid(const WCHAR *classid, WCHAR **out) { ACTCTX_SECTION_KEYED_DATA data; @@ -498,8 +597,36 @@ HRESULT WINAPI RoRegisterActivationFactories(HSTRING *classes, PFNGETACTIVATIONF */ HRESULT WINAPI GetRestrictedErrorInfo(IRestrictedErrorInfo **info) { - FIXME( "(%p)\n", info ); - return E_NOTIMPL; + IErrorInfo *error_info = NULL; + HRESULT hr; + + TRACE("(%p)\n", info); + + if (!info) return E_POINTER; + *info = NULL; + + hr = GetErrorInfo(0, &error_info); + if (hr == S_FALSE) + return S_FALSE; + if (FAILED(hr)) + { + WARN("GetErrorInfo failed, hr %#lx.\n", hr); + return hr; + } + + if (!error_info) + return S_FALSE; + + hr = IErrorInfo_QueryInterface(error_info, &IID_IRestrictedErrorInfo, (void **)info); + IErrorInfo_Release(error_info); + + if (FAILED(hr)) + { + TRACE("Current error object does not support IRestrictedErrorInfo.\n"); + return S_FALSE; + } + + return S_OK; } /*********************************************************************** @@ -507,8 +634,107 @@ HRESULT WINAPI GetRestrictedErrorInfo(IRestrictedErrorInfo **info) */ HRESULT WINAPI SetRestrictedErrorInfo(IRestrictedErrorInfo *info) { - FIXME( "(%p)\n", info ); - return E_NOTIMPL; + IErrorInfo *error_info = NULL; + HRESULT hr; + + TRACE("(%p)\n", info); + + if (!info) + return SetErrorInfo(0, NULL); + + hr = IRestrictedErrorInfo_QueryInterface(info, &IID_IErrorInfo, (void **)&error_info); + if (FAILED(hr)) + { + WARN("Restricted error object does not expose IErrorInfo, hr %#lx.\n", hr); + return hr; + } + + hr = SetErrorInfo(0, error_info); + IErrorInfo_Release(error_info); + + return hr; +} + +/*********************************************************************** + * RoCaptureErrorContext (combase.@) + * + * Captures the current restricted error context for the specified HRESULT. + * + * Wine stores the captured context in the restricted error object, + * including a stack backtrace. Native Windows Error Reporting (WER) + * integration is not implemented yet. + */ +HRESULT WINAPI RoCaptureErrorContext(HRESULT error) +{ + IRestrictedErrorInfo *info = NULL; + HRESULT hr, stored_error = S_OK; + + TRACE("%#lx.\n", error); + + if (!FAILED(error)) + return S_OK; + + hr = GetRestrictedErrorInfo(&info); + if (FAILED(hr) && hr != S_FALSE) + { + WARN("GetRestrictedErrorInfo failed, hr %#lx.\n", hr); + return hr; + } + + if (info) + { + hr = IRestrictedErrorInfo_GetErrorDetails(info, NULL, &stored_error, NULL, NULL); + if (FAILED(hr) || stored_error != error) + { + IRestrictedErrorInfo_Release(info); + info = NULL; + } + } + + if (!info) + { + hr = create_restricted_error_info(error, NULL, NULL, NULL, NULL, &info); + if (FAILED(hr)) + { + WARN("create_restricted_error_info failed, hr %#lx.\n", hr); + return hr; + } + } + + hr = capture_restricted_error_context(info, error); + if (FAILED(hr)) + { + WARN("capture_restricted_error_context failed, hr %#lx.\n", hr); + IRestrictedErrorInfo_Release(info); + return hr; + } + + hr = SetRestrictedErrorInfo(info); + IRestrictedErrorInfo_Release(info); + + return hr; +} + +/*********************************************************************** + * RoClearError (combase.@) + * + * Clears the current restricted error info for the calling thread. + */ +void WINAPI RoClearError(void) +{ + struct tlsdata *tlsdata = NtCurrentTeb()->ReservedForOle; + IErrorInfo *error_info; + + TRACE("()\n"); + + if (!tlsdata) + return; + + error_info = tlsdata->errorinfo; + tlsdata->errorinfo = NULL; + + if (error_info) + IErrorInfo_Release(error_info); } /*********************************************************************** @@ -525,8 +751,15 @@ BOOL WINAPI RoOriginateLanguageException(HRESULT error, HSTRING message, IUnknow */ BOOL WINAPI RoOriginateError(HRESULT error, HSTRING message) { - FIXME("%#lx, %s: stub\n", error, debugstr_hstring(message)); - return FALSE; + const WCHAR *str = NULL; + UINT32 len = 0; + + TRACE("%#lx, %s.\n", error, debugstr_hstring(message)); + + if (message) + str = WindowsGetStringRawBuffer(message, &len); + + return RoOriginateErrorW(error, len, str); } /*********************************************************************** @@ -534,16 +767,89 @@ BOOL WINAPI RoOriginateError(HRESULT error, HSTRING message) */ BOOL WINAPI RoOriginateErrorW(HRESULT error, UINT max_len, const WCHAR *message) { - FIXME("%#lx, %u, %p: stub\n", error, max_len, message); - return FALSE; + IRestrictedErrorInfo *info = NULL; + WCHAR *text = NULL; + HRESULT hr; + + TRACE("%#lx, %u, %s.\n", error, max_len, debugstr_w(message)); + + if (!FAILED(error)) + return FALSE; + + if (message) + text = duplicate_bounded_message(message, max_len); + else + text = get_generic_error_message(error); + + if (message && !text) + return FALSE; + + /* The call still succeeds even if we don't attach the error object + * to the COM channel. */ + if (!should_use_seterrorinfo()) + { + free(text); + return TRUE; + } + + hr = create_restricted_error_info(error, text, NULL, NULL, NULL, &info); + free(text); + if (FAILED(hr)) + { + WARN("create_restricted_error_info failed, hr %#lx.\n", hr); + return FALSE; + } + + hr = SetRestrictedErrorInfo(info); + IRestrictedErrorInfo_Release(info); + + return SUCCEEDED(hr); } /*********************************************************************** - * RoReportUnhandledError (combase.@) + * RoReportUnhandledError (combase.@) + * + * Reports an unhandled error by updating the COM error channel state + * for the current thread and logging the error details. */ HRESULT WINAPI RoReportUnhandledError(IRestrictedErrorInfo *info) { - FIXME("(%p): stub\n", info); + HRESULT hr; + BSTR description = NULL, restricted = NULL, capability = NULL; + HRESULT orig_error = S_OK; + + TRACE("(%p)\n", info); + + if (!info) + return E_POINTER; + + hr = SetRestrictedErrorInfo(info); + if (FAILED(hr)) + { + WARN("SetRestrictedErrorInfo failed, hr %#lx.\n", hr); + return hr; + } + + if (SUCCEEDED(IRestrictedErrorInfo_GetErrorDetails(info, &description, &orig_error, + &restricted, &capability))) + { + WARN("Unhandled WinRT error: hr %#lx, desc %s, restricted %s, capability %s\n", + orig_error, debugstr_w(description), debugstr_w(restricted), + debugstr_w(capability)); + + SysFreeString(description); + SysFreeString(restricted); + SysFreeString(capability); + } + else + { + WARN("Unhandled WinRT error reported, but failed to get details.\n"); + } + + /* Native Windows triggers the Global Error Handler here. + * Wine currently preserves the reported restricted error object + * on the current thread for later observation. + */ return S_OK; } @@ -552,7 +858,210 @@ HRESULT WINAPI RoReportUnhandledError(IRestrictedErrorInfo *info) */ HRESULT WINAPI RoSetErrorReportingFlags(UINT32 flags) { - FIXME("(%08x): stub\n", flags); + TRACE("(%08x)\n", flags); + + if (flags & ~RO_ERROR_REPORTING_VALID_MASK) + return E_INVALIDARG; + + ro_error_reporting_flags = flags; + return S_OK; +} + +/*********************************************************************** + * RoTransformErrorW (combase.@) + * + * Transforms the current restricted error into a new one with a different + * HRESULT and (optionally) a new user-visible message. + */ + +BOOL WINAPI RoTransformErrorW(HRESULT old_error, HRESULT new_error, + UINT max_len, const WCHAR *message) +{ + IRestrictedErrorInfo *old_info = NULL, *new_info = NULL; + BSTR desc = NULL, restricted_desc = NULL, cap_sid = NULL, reference = NULL; + HRESULT hr, stored_hr = S_OK; + WCHAR *bounded_message = NULL; + const WCHAR *new_desc = NULL, *new_restricted_desc = NULL; + + TRACE("%#lx, %#lx, %u, %s.\n", old_error, new_error, max_len, debugstr_w(message)); + + if (old_error == new_error) + return FALSE; + if (!FAILED(old_error) && !FAILED(new_error)) + return FALSE; + + if (message) + { + bounded_message = duplicate_bounded_message(message, max_len); + if (!bounded_message) + return FALSE; + } + else + { + bounded_message = get_generic_error_message(new_error); + if (!bounded_message) + return FALSE; + } + + /* As with RoOriginateErrorW(), the call can still succeed even if + * we don't attach the transformed error object to the COM channel. */ + if (!should_use_seterrorinfo()) + { + free(bounded_message); + return TRUE; + } + + hr = RoGetMatchingRestrictedErrorInfo(old_error, &old_info); + if (FAILED(hr)) + { + WARN("RoGetMatchingRestrictedErrorInfo failed, hr %#lx.\n", hr); + free(bounded_message); + return FALSE; + } + + if (old_info) + { + hr = IRestrictedErrorInfo_GetErrorDetails(old_info, &desc, &stored_hr, + &restricted_desc, &cap_sid); + if (FAILED(hr)) + { + desc = NULL; + restricted_desc = NULL; + cap_sid = NULL; + } + + hr = IRestrictedErrorInfo_GetReference(old_info, &reference); + if (FAILED(hr)) + reference = NULL; + } + + new_desc = bounded_message; + new_restricted_desc = desc ? desc : restricted_desc; + + hr = create_restricted_error_info(new_error, new_desc, new_restricted_desc, + cap_sid, reference, &new_info); + if (FAILED(hr)) + { + WARN("create_restricted_error_info failed, hr %#lx.\n", hr); + goto done; + } + + if (old_info) + { + hr = copy_restricted_error_context(new_info, old_info); + if (FAILED(hr)) + { + WARN("copy_restricted_error_context failed, hr %#lx.\n", hr); + goto done; + } + } + + hr = SetRestrictedErrorInfo(new_info); + if (FAILED(hr)) + { + WARN("SetRestrictedErrorInfo failed, hr %#lx.\n", hr); + goto done; + } + +done: + if (new_info) + IRestrictedErrorInfo_Release(new_info); + if (old_info) + IRestrictedErrorInfo_Release(old_info); + if (desc) + SysFreeString(desc); + if (restricted_desc) + SysFreeString(restricted_desc); + if (cap_sid) + SysFreeString(cap_sid); + if (reference) + SysFreeString(reference); + free(bounded_message); + + return SUCCEEDED(hr); +} + +/*********************************************************************** + * RoTransformError (combase.@) + */ +BOOL WINAPI RoTransformError(HRESULT old_error, HRESULT new_error, HSTRING message) +{ + const WCHAR *msg = NULL; + UINT32 len = 0; + + TRACE("%#lx, %#lx, %s.\n", old_error, new_error, debugstr_hstring(message)); + + if (message) + msg = WindowsGetStringRawBuffer(message, &len); + + return RoTransformErrorW(old_error, new_error, len, msg); +} + +/*********************************************************************** + * RoGetMatchingRestrictedErrorInfo (combase.@) + * + * Ensures that there is a restricted error info whose HRESULT matches + * the given error code, and returns it. + */ +HRESULT WINAPI RoGetMatchingRestrictedErrorInfo(HRESULT error, IRestrictedErrorInfo **info) +{ + IRestrictedErrorInfo *current = NULL; + HRESULT hr, stored_hr = S_OK; + + TRACE("%#lx, %p.\n", error, info); + + if (!info) return E_POINTER; + *info = NULL; + + if (!FAILED(error)) + return S_FALSE; + + hr = GetRestrictedErrorInfo(¤t); + if (FAILED(hr) && hr != S_FALSE) + { + WARN("GetRestrictedErrorInfo failed, hr %#lx.\n", hr); + return hr; + } + + if (current) + { + hr = IRestrictedErrorInfo_GetErrorDetails(current, NULL, &stored_hr, NULL, NULL); + if (SUCCEEDED(hr) && stored_hr == error) + { + hr = SetRestrictedErrorInfo(current); + if (FAILED(hr)) + { + WARN("SetRestrictedErrorInfo failed, hr %#lx.\n", hr); + IRestrictedErrorInfo_Release(current); + return hr; + } + + IRestrictedErrorInfo_AddRef(current); + *info = current; + IRestrictedErrorInfo_Release(current); + return S_OK; + } + + IRestrictedErrorInfo_Release(current); + current = NULL; + } + + hr = create_restricted_error_info(error, NULL, NULL, NULL, NULL, ¤t); + if (FAILED(hr)) + { + WARN("create_restricted_error_info failed, hr %#lx.\n", hr); + return hr; + } + + hr = SetRestrictedErrorInfo(current); + if (FAILED(hr)) + { + WARN("SetRestrictedErrorInfo failed, hr %#lx.\n", hr); + IRestrictedErrorInfo_Release(current); + return hr; + } + + *info = current; return S_OK; } @@ -561,12 +1070,12 @@ HRESULT WINAPI RoSetErrorReportingFlags(UINT32 flags) */ HRESULT WINAPI RoGetErrorReportingFlags(UINT32 *flags) { - FIXME("(%p): stub\n", flags); + TRACE("(%p)\n", flags); if (!flags) return E_POINTER; - *flags = RO_ERROR_REPORTING_USESETERRORINFO; + *flags = ro_error_reporting_flags; return S_OK; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10659
From: Anna R Békefi <annareginabekefi@gmail.com> --- dlls/combase/tests/Makefile.in | 2 +- dlls/combase/tests/roapi.c | 170 +++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 1 deletion(-) diff --git a/dlls/combase/tests/Makefile.in b/dlls/combase/tests/Makefile.in index 21597b38d51..85b337cceec 100644 --- a/dlls/combase/tests/Makefile.in +++ b/dlls/combase/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = combase.dll -IMPORTS = combase uuid user32 +IMPORTS = combase uuid user32 oleaut32 SOURCES = \ combase.rc \ diff --git a/dlls/combase/tests/roapi.c b/dlls/combase/tests/roapi.c index e4100cb11bc..16452bfd21d 100644 --- a/dlls/combase/tests/roapi.c +++ b/dlls/combase/tests/roapi.c @@ -23,6 +23,7 @@ #include "winerror.h" #include "winstring.h" #include "winternl.h" +#include "oleauto.h" #include "initguid.h" #include "roapi.h" @@ -30,6 +31,11 @@ #include "wine/test.h" +HRESULT WINAPI RoCaptureErrorContext(HRESULT hr); +void WINAPI RoClearError(void); +HRESULT WINAPI RoGetMatchingRestrictedErrorInfo(HRESULT hr, IRestrictedErrorInfo **info); +BOOL WINAPI RoTransformErrorW(HRESULT old_error, HRESULT new_error, UINT cchMax, const WCHAR *message); + #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__) static void _expect_ref(IUnknown* obj, ULONG ref, int line) { @@ -639,6 +645,169 @@ static void test_RoGetErrorReportingFlags(void) ok(flags == RO_ERROR_REPORTING_USESETERRORINFO, "Got unexpected flag %#x.\n", flags); } +static BOOL wstr_equal_nullsafe(const WCHAR *a, const WCHAR *b) +{ + if (!a && !b) return TRUE; + if (!a || !b) return FALSE; + return !lstrcmpW(a, b); +} + +static void check_restricted_error_details_(unsigned int line, IRestrictedErrorInfo *info, + HRESULT expected_hr, const WCHAR *expected_desc, const WCHAR *expected_restricted) +{ + BSTR desc = NULL, restricted = NULL, capability = NULL; + HRESULT hr = E_FAIL, call_hr; + + ok_(__FILE__, line)(!!info, "expected restricted error info.\n"); + if (!info) return; + + call_hr = IRestrictedErrorInfo_GetErrorDetails(info, &desc, &hr, &restricted, &capability); + ok_(__FILE__, line)(call_hr == S_OK, "GetErrorDetails returned %#lx.\n", call_hr); + if (call_hr == S_OK) + { + ok_(__FILE__, line)(hr == expected_hr, "got hr %#lx, expected %#lx.\n", hr, expected_hr); + ok_(__FILE__, line)(wstr_equal_nullsafe(desc, expected_desc), + "got desc %s, expected %s.\n", wine_dbgstr_w(desc), wine_dbgstr_w(expected_desc)); + ok_(__FILE__, line)(wstr_equal_nullsafe(restricted, expected_restricted), + "got restricted %s, expected %s.\n", wine_dbgstr_w(restricted), wine_dbgstr_w(expected_restricted)); + } + + if (desc) SysFreeString(desc); + if (restricted) SysFreeString(restricted); + if (capability) SysFreeString(capability); +} + +#define check_restricted_error_details(info, hr, desc, restricted) \ + check_restricted_error_details_(__LINE__, info, hr, desc, restricted) + +static void clear_restricted_error_state(void) +{ + IRestrictedErrorInfo *info = NULL; + + RoClearError(); + while (GetRestrictedErrorInfo(&info) == S_OK && info) + { + IRestrictedErrorInfo_Release(info); + info = NULL; + } +} + +static void test_restricted_error_handling(void) +{ + static const WCHAR originate_msg[] = L"originate-one"; + static const WCHAR old_msg[] = L"old-message"; + static const WCHAR new_msg[] = L"new-message"; + static const WCHAR suppressed_msg[] = L"suppressed"; + IRestrictedErrorInfo *info = NULL; + HRESULT hr; + UINT32 flags = 0; + BOOL uninit = FALSE; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK || hr == S_FALSE, "RoInitialize returned %#lx.\n", hr); + if (SUCCEEDED(hr)) + uninit = TRUE; + + clear_restricted_error_state(); + + hr = GetRestrictedErrorInfo(&info); + ok(hr == S_FALSE, "GetRestrictedErrorInfo returned %#lx.\n", hr); + ok(!info, "got info %p.\n", info); + + ok(!RoOriginateErrorW(S_OK, 0, L"should-not-set"), + "RoOriginateErrorW should fail for success HRESULT.\n"); + + ok(RoOriginateErrorW(E_ACCESSDENIED, 0, originate_msg), + "RoOriginateErrorW failed.\n"); + + hr = RoCaptureErrorContext(E_ACCESSDENIED); + ok(hr == S_OK, "RoCaptureErrorContext returned %#lx.\n", hr); + + hr = GetRestrictedErrorInfo(&info); + ok(hr == S_OK, "GetRestrictedErrorInfo returned %#lx.\n", hr); + check_restricted_error_details(info, E_ACCESSDENIED, originate_msg, NULL); + IRestrictedErrorInfo_Release(info); + info = NULL; + + hr = GetRestrictedErrorInfo(&info); + ok(hr == S_FALSE, "GetRestrictedErrorInfo returned %#lx.\n", hr); + ok(!info, "got info %p.\n", info); + + hr = RoGetMatchingRestrictedErrorInfo(E_ACCESSDENIED, &info); + ok(hr == S_OK, "RoGetMatchingRestrictedErrorInfo returned %#lx.\n", hr); + check_restricted_error_details(info, E_ACCESSDENIED, NULL, NULL); + + hr = SetRestrictedErrorInfo(info); + ok(hr == S_OK, "SetRestrictedErrorInfo returned %#lx.\n", hr); + IRestrictedErrorInfo_Release(info); + info = NULL; + + hr = GetRestrictedErrorInfo(&info); + ok(hr == S_OK, "GetRestrictedErrorInfo returned %#lx.\n", hr); + check_restricted_error_details(info, E_ACCESSDENIED, NULL, NULL); + IRestrictedErrorInfo_Release(info); + info = NULL; + + hr = SetRestrictedErrorInfo(NULL); + ok(hr == S_OK, "SetRestrictedErrorInfo(NULL) returned %#lx.\n", hr); + + hr = GetRestrictedErrorInfo(&info); + ok(hr == S_FALSE, "GetRestrictedErrorInfo returned %#lx.\n", hr); + ok(!info, "got info %p.\n", info); + + ok(RoOriginateErrorW(E_FAIL, 0, old_msg), "RoOriginateErrorW failed.\n"); + hr = RoCaptureErrorContext(E_FAIL); + ok(hr == S_OK, "RoCaptureErrorContext returned %#lx.\n", hr); + + ok(RoTransformErrorW(E_FAIL, E_ACCESSDENIED, 0, new_msg), + "RoTransformErrorW failed.\n"); + + hr = GetRestrictedErrorInfo(&info); + ok(hr == S_OK, "GetRestrictedErrorInfo returned %#lx.\n", hr); + check_restricted_error_details(info, E_ACCESSDENIED, new_msg, old_msg); + IRestrictedErrorInfo_Release(info); + info = NULL; + + hr = RoReportUnhandledError(NULL); + ok(hr == E_POINTER, "RoReportUnhandledError returned %#lx.\n", hr); + + hr = RoGetMatchingRestrictedErrorInfo(E_BOUNDS, &info); + ok(hr == S_OK, "RoGetMatchingRestrictedErrorInfo returned %#lx.\n", hr); + + hr = RoReportUnhandledError(info); + ok(hr == S_OK, "RoReportUnhandledError returned %#lx.\n", hr); + IRestrictedErrorInfo_Release(info); + info = NULL; + + hr = GetRestrictedErrorInfo(&info); + ok(hr == S_OK, "GetRestrictedErrorInfo returned %#lx.\n", hr); + check_restricted_error_details(info, E_BOUNDS, NULL, NULL); + IRestrictedErrorInfo_Release(info); + info = NULL; + + hr = RoSetErrorReportingFlags(RO_ERROR_REPORTING_SUPPRESSSETERRORINFO); + ok(hr == S_OK, "RoSetErrorReportingFlags returned %#lx.\n", hr); + + ok(RoOriginateErrorW(E_FAIL, 0, suppressed_msg), + "RoOriginateErrorW failed under suppressed mode.\n"); + + hr = GetRestrictedErrorInfo(&info); + ok(hr == S_FALSE, "GetRestrictedErrorInfo returned %#lx.\n", hr); + ok(!info, "got info %p.\n", info); + + hr = RoSetErrorReportingFlags(RO_ERROR_REPORTING_USESETERRORINFO); + ok(hr == S_OK, "RoSetErrorReportingFlags returned %#lx.\n", hr); + + hr = RoGetErrorReportingFlags(&flags); + ok(hr == S_OK, "RoGetErrorReportingFlags returned %#lx.\n", hr); + ok(flags == RO_ERROR_REPORTING_USESETERRORINFO, "got flags %#x.\n", flags); + + clear_restricted_error_state(); + + if (uninit) + RoUninitialize(); +} + START_TEST(roapi) { BOOL ret; @@ -649,6 +818,7 @@ START_TEST(roapi) test_ActivationFactories(); test_RoGetAgileReference(); test_RoGetErrorReportingFlags(); + test_restricted_error_handling(); SetLastError(0xdeadbeef); ret = DeleteFileW(L"wine.combase.test.dll"); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10659
From: Anna R Békefi <annareginabekefi@gmail.com> --- dlls/combase/roapi.c | 75 ++++++++++++++++++++++++++------------ dlls/combase/tests/roapi.c | 42 ++++++++++++++++++--- 2 files changed, 88 insertions(+), 29 deletions(-) diff --git a/dlls/combase/roapi.c b/dlls/combase/roapi.c index 7137294e201..53d401de685 100644 --- a/dlls/combase/roapi.c +++ b/dlls/combase/roapi.c @@ -122,9 +122,6 @@ static WCHAR *get_generic_error_message(HRESULT error) if (!len || !system_message) return wcsdup(L"Unspecified error"); - while (len && (system_message[len - 1] == '\r' || system_message[len - 1] == '\n')) - system_message[--len] = 0; - if (len > 511) len = 511; @@ -768,7 +765,7 @@ BOOL WINAPI RoOriginateError(HRESULT error, HSTRING message) BOOL WINAPI RoOriginateErrorW(HRESULT error, UINT max_len, const WCHAR *message) { IRestrictedErrorInfo *info = NULL; - WCHAR *text = NULL; + WCHAR *generic_text = NULL, *restricted_text = NULL; HRESULT hr; TRACE("%#lx, %u, %s.\n", error, max_len, debugstr_w(message)); @@ -776,24 +773,39 @@ BOOL WINAPI RoOriginateErrorW(HRESULT error, UINT max_len, const WCHAR *message) if (!FAILED(error)) return FALSE; + generic_text = get_generic_error_message(error); + if (!generic_text) + return FALSE; + if (message) - text = duplicate_bounded_message(message, max_len); + restricted_text = duplicate_bounded_message(message, max_len); else - text = get_generic_error_message(error); + restricted_text = wcsdup(generic_text); - if (message && !text) + if (message && !restricted_text) + { + free(generic_text); return FALSE; + } + + if (!restricted_text) + { + free(generic_text); + return FALSE; + } /* The call still succeeds even if we don't attach the error object * to the COM channel. */ if (!should_use_seterrorinfo()) { - free(text); + free(generic_text); + free(restricted_text); return TRUE; } - hr = create_restricted_error_info(error, text, NULL, NULL, NULL, &info); - free(text); + hr = create_restricted_error_info(error, generic_text, restricted_text, NULL, NULL, &info); + free(generic_text); + free(restricted_text); if (FAILED(hr)) { WARN("create_restricted_error_info failed, hr %#lx.\n", hr); @@ -880,8 +892,7 @@ BOOL WINAPI RoTransformErrorW(HRESULT old_error, HRESULT new_error, IRestrictedErrorInfo *old_info = NULL, *new_info = NULL; BSTR desc = NULL, restricted_desc = NULL, cap_sid = NULL, reference = NULL; HRESULT hr, stored_hr = S_OK; - WCHAR *bounded_message = NULL; - const WCHAR *new_desc = NULL, *new_restricted_desc = NULL; + WCHAR *generic_text = NULL, *restricted_text = NULL; TRACE("%#lx, %#lx, %u, %s.\n", old_error, new_error, max_len, debugstr_w(message)); @@ -890,24 +901,35 @@ BOOL WINAPI RoTransformErrorW(HRESULT old_error, HRESULT new_error, if (!FAILED(old_error) && !FAILED(new_error)) return FALSE; + generic_text = get_generic_error_message(new_error); + if (!generic_text) + return FALSE; + if (message) { - bounded_message = duplicate_bounded_message(message, max_len); - if (!bounded_message) + restricted_text = duplicate_bounded_message(message, max_len); + if (!restricted_text) + { + free(generic_text); return FALSE; + } } else { - bounded_message = get_generic_error_message(new_error); - if (!bounded_message) + restricted_text = wcsdup(generic_text); + if (!restricted_text) + { + free(generic_text); return FALSE; + } } /* As with RoOriginateErrorW(), the call can still succeed even if * we don't attach the transformed error object to the COM channel. */ if (!should_use_seterrorinfo()) { - free(bounded_message); + free(generic_text); + free(restricted_text); return TRUE; } @@ -915,7 +937,8 @@ BOOL WINAPI RoTransformErrorW(HRESULT old_error, HRESULT new_error, if (FAILED(hr)) { WARN("RoGetMatchingRestrictedErrorInfo failed, hr %#lx.\n", hr); - free(bounded_message); + free(generic_text); + free(restricted_text); return FALSE; } @@ -935,10 +958,7 @@ BOOL WINAPI RoTransformErrorW(HRESULT old_error, HRESULT new_error, reference = NULL; } - new_desc = bounded_message; - new_restricted_desc = desc ? desc : restricted_desc; - - hr = create_restricted_error_info(new_error, new_desc, new_restricted_desc, + hr = create_restricted_error_info(new_error, generic_text, restricted_text, cap_sid, reference, &new_info); if (FAILED(hr)) { @@ -976,7 +996,8 @@ done: SysFreeString(cap_sid); if (reference) SysFreeString(reference); - free(bounded_message); + free(generic_text); + free(restricted_text); return SUCCEEDED(hr); } @@ -1007,6 +1028,7 @@ HRESULT WINAPI RoGetMatchingRestrictedErrorInfo(HRESULT error, IRestrictedErrorI { IRestrictedErrorInfo *current = NULL; HRESULT hr, stored_hr = S_OK; + WCHAR *generic_text = NULL; TRACE("%#lx, %p.\n", error, info); @@ -1046,7 +1068,12 @@ HRESULT WINAPI RoGetMatchingRestrictedErrorInfo(HRESULT error, IRestrictedErrorI current = NULL; } - hr = create_restricted_error_info(error, NULL, NULL, NULL, NULL, ¤t); + generic_text = get_generic_error_message(error); + if (!generic_text) + return E_OUTOFMEMORY; + + hr = create_restricted_error_info(error, generic_text, generic_text, NULL, NULL, ¤t); + free(generic_text); if (FAILED(hr)) { WARN("create_restricted_error_info failed, hr %#lx.\n", hr); diff --git a/dlls/combase/tests/roapi.c b/dlls/combase/tests/roapi.c index 16452bfd21d..c31ae8b340d 100644 --- a/dlls/combase/tests/roapi.c +++ b/dlls/combase/tests/roapi.c @@ -652,6 +652,27 @@ static BOOL wstr_equal_nullsafe(const WCHAR *a, const WCHAR *b) return !lstrcmpW(a, b); } +static WCHAR *get_expected_system_message(HRESULT hr) +{ + WCHAR *msg = NULL; + DWORD len; + + len = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, hr, 0, (WCHAR *)&msg, 0, NULL); + if (!len) + { + len = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, E_FAIL, 0, (WCHAR *)&msg, 0, NULL); + } + + ok(msg != NULL, "FormatMessageW failed for %#lx.\n", hr); + return msg; +} + static void check_restricted_error_details_(unsigned int line, IRestrictedErrorInfo *info, HRESULT expected_hr, const WCHAR *expected_desc, const WCHAR *expected_restricted) { @@ -702,6 +723,8 @@ static void test_restricted_error_handling(void) HRESULT hr; UINT32 flags = 0; BOOL uninit = FALSE; + WCHAR *access_denied_msg; + WCHAR *bounds_msg; hr = RoInitialize(RO_INIT_MULTITHREADED); ok(hr == S_OK || hr == S_FALSE, "RoInitialize returned %#lx.\n", hr); @@ -710,6 +733,12 @@ static void test_restricted_error_handling(void) clear_restricted_error_state(); + access_denied_msg = get_expected_system_message(E_ACCESSDENIED); + bounds_msg = get_expected_system_message(E_BOUNDS); + + ok(access_denied_msg != NULL, "Failed to get expected message for E_ACCESSDENIED.\n"); + ok(bounds_msg != NULL, "Failed to get expected message for E_BOUNDS.\n"); + hr = GetRestrictedErrorInfo(&info); ok(hr == S_FALSE, "GetRestrictedErrorInfo returned %#lx.\n", hr); ok(!info, "got info %p.\n", info); @@ -725,7 +754,7 @@ static void test_restricted_error_handling(void) hr = GetRestrictedErrorInfo(&info); ok(hr == S_OK, "GetRestrictedErrorInfo returned %#lx.\n", hr); - check_restricted_error_details(info, E_ACCESSDENIED, originate_msg, NULL); + check_restricted_error_details(info, E_ACCESSDENIED, access_denied_msg, originate_msg); IRestrictedErrorInfo_Release(info); info = NULL; @@ -735,7 +764,7 @@ static void test_restricted_error_handling(void) hr = RoGetMatchingRestrictedErrorInfo(E_ACCESSDENIED, &info); ok(hr == S_OK, "RoGetMatchingRestrictedErrorInfo returned %#lx.\n", hr); - check_restricted_error_details(info, E_ACCESSDENIED, NULL, NULL); + check_restricted_error_details(info, E_ACCESSDENIED, access_denied_msg, access_denied_msg); hr = SetRestrictedErrorInfo(info); ok(hr == S_OK, "SetRestrictedErrorInfo returned %#lx.\n", hr); @@ -744,7 +773,7 @@ static void test_restricted_error_handling(void) hr = GetRestrictedErrorInfo(&info); ok(hr == S_OK, "GetRestrictedErrorInfo returned %#lx.\n", hr); - check_restricted_error_details(info, E_ACCESSDENIED, NULL, NULL); + check_restricted_error_details(info, E_ACCESSDENIED, access_denied_msg, access_denied_msg); IRestrictedErrorInfo_Release(info); info = NULL; @@ -764,7 +793,7 @@ static void test_restricted_error_handling(void) hr = GetRestrictedErrorInfo(&info); ok(hr == S_OK, "GetRestrictedErrorInfo returned %#lx.\n", hr); - check_restricted_error_details(info, E_ACCESSDENIED, new_msg, old_msg); + check_restricted_error_details(info, E_ACCESSDENIED, access_denied_msg, new_msg); IRestrictedErrorInfo_Release(info); info = NULL; @@ -781,7 +810,7 @@ static void test_restricted_error_handling(void) hr = GetRestrictedErrorInfo(&info); ok(hr == S_OK, "GetRestrictedErrorInfo returned %#lx.\n", hr); - check_restricted_error_details(info, E_BOUNDS, NULL, NULL); + check_restricted_error_details(info, E_BOUNDS, bounds_msg, bounds_msg); IRestrictedErrorInfo_Release(info); info = NULL; @@ -804,6 +833,9 @@ static void test_restricted_error_handling(void) clear_restricted_error_state(); + LocalFree(access_denied_msg); + LocalFree(bounds_msg); + if (uninit) RoUninitialize(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10659
From: Anna R Békefi <annareginabekefi@gmail.com> --- dlls/combase/tests/roapi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dlls/combase/tests/roapi.c b/dlls/combase/tests/roapi.c index c31ae8b340d..0b4828d6e76 100644 --- a/dlls/combase/tests/roapi.c +++ b/dlls/combase/tests/roapi.c @@ -716,8 +716,6 @@ static void clear_restricted_error_state(void) static void test_restricted_error_handling(void) { static const WCHAR originate_msg[] = L"originate-one"; - static const WCHAR old_msg[] = L"old-message"; - static const WCHAR new_msg[] = L"new-message"; static const WCHAR suppressed_msg[] = L"suppressed"; IRestrictedErrorInfo *info = NULL; HRESULT hr; @@ -784,7 +782,7 @@ static void test_restricted_error_handling(void) ok(hr == S_FALSE, "GetRestrictedErrorInfo returned %#lx.\n", hr); ok(!info, "got info %p.\n", info); - ok(RoOriginateErrorW(E_FAIL, 0, old_msg), "RoOriginateErrorW failed.\n"); + /* ok(RoOriginateErrorW(E_FAIL, 0, old_msg), "RoOriginateErrorW failed.\n"); hr = RoCaptureErrorContext(E_FAIL); ok(hr == S_OK, "RoCaptureErrorContext returned %#lx.\n", hr); @@ -813,7 +811,7 @@ static void test_restricted_error_handling(void) check_restricted_error_details(info, E_BOUNDS, bounds_msg, bounds_msg); IRestrictedErrorInfo_Release(info); info = NULL; - + */ hr = RoSetErrorReportingFlags(RO_ERROR_REPORTING_SUPPRESSSETERRORINFO); ok(hr == S_OK, "RoSetErrorReportingFlags returned %#lx.\n", hr); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10659
participants (2)
-
Anna R Békefi -
Anna R Békefi (@annareginabekefi)