[PATCH 0/1] MR11208: dnsapi: Add DNS-SD service API stubs to prevent abort on unimplemented entry points
iRacing crashes during UI and/or background service initialisation under Wine when `DNSAPI.dll` entry points are called and not found. The crash manifests as an unimplemented function abort in the Steam Proton log: `wine: Call from ... to unimplemented function DNSAPI.dll.DnsServiceConstructInstance, aborting` My research suggests iRacing uses this api to discover local network devices or services, likely searching for Apple Vision Pro hardware on the local network based upon recent updates to the game. This patch adds the `DNS_SERVICE_INSTANCE` structure and `PDNS_SERVICE_INSTANCE` typedef to `windns.h`, which were missing entirely, along with the associated callback typedefs `DNS_SERVICE_REGISTER_COMPLETE` and `DNS_SERVICE_RESOLVE_COMPLETE` that depend on them. `DnsServiceConstructInstance` has been given a functional implementation that allocates and populates a `DNS_SERVICE_INSTANCE` structure and `DnsServiceFreeInstance` has been implemented to free it. The remaining DNS-SD entry points (`DnsServiceRegister`, `DnsServiceDeRegister`, `DnsServiceRegisterCancel`, `DnsServiceResolve`, `DnsServiceResolveCancel`, and `DnsServiceBrowseCancel`) are implemented as stubs returning appropriate values with `FIXME` traces, replacing the hard aborts that previously prevented iRacing from reaching its UI. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11208
From: DanFraser <11152006+DanFraserUK@users.noreply.github.com> --- dlls/dnsapi/dnsapi.spec | 8 ++ dlls/dnsapi/main.c | 181 ++++++++++++++++++++++++++++++++++++++++ include/windns.h | 46 ++++++++++ 3 files changed, 235 insertions(+) diff --git a/dlls/dnsapi/dnsapi.spec b/dlls/dnsapi/dnsapi.spec index a8ffa40a0ae..3bfc4bc5451 100644 --- a/dlls/dnsapi/dnsapi.spec +++ b/dlls/dnsapi/dnsapi.spec @@ -104,6 +104,14 @@ @ stdcall DnsReplaceRecordSetW(ptr long ptr ptr ptr) @ stub DnsReplaceRecordSet_W @ stdcall DnsServiceBrowse(ptr ptr) +@ stdcall DnsServiceBrowseCancel(ptr) +@ stdcall DnsServiceConstructInstance(wstr wstr ptr ptr long long long long ptr ptr) +@ stdcall DnsServiceDeRegister(ptr ptr) +@ stdcall DnsServiceFreeInstance(ptr) +@ stdcall DnsServiceRegister(ptr ptr) +@ stdcall DnsServiceRegisterCancel(ptr) +@ stdcall DnsServiceResolve(ptr ptr) +@ stdcall DnsServiceResolveCancel(ptr) @ stub DnsServiceNotificationDeregister_A @ stub DnsServiceNotificationDeregister_UTF8 @ stub DnsServiceNotificationDeregister_W diff --git a/dlls/dnsapi/main.c b/dlls/dnsapi/main.c index 9b057a09a05..500876c467b 100644 --- a/dlls/dnsapi/main.c +++ b/dlls/dnsapi/main.c @@ -20,6 +20,7 @@ */ #include <stdarg.h> +#include <stdlib.h> #include "windef.h" #include "winternl.h" @@ -243,3 +244,183 @@ DNS_STATUS WINAPI DnsServiceBrowse( PDNS_SERVICE_BROWSE_REQUEST request, PDNS_SE FIXME( "(%p, %p) stub\n", request, cancel ); return ERROR_SUCCESS; } + +/****************************************************************************** + * DnsServiceConstructInstance [DNSAPI.@] + * + */ +PDNS_SERVICE_INSTANCE WINAPI DnsServiceConstructInstance( PCWSTR service_name, PCWSTR host_name, + PIP4_ADDRESS ip4, PIP6_ADDRESS ip6, + WORD port, WORD priority, WORD weight, + DWORD property_count, PWSTR *keys, + PWSTR *values ) +{ + DNS_SERVICE_INSTANCE *instance; + DWORD i; + + FIXME( "(%s, %s, %p, %p, %u, %u, %u, %lu, %p, %p) stub\n", + debugstr_w(service_name), debugstr_w(host_name), ip4, ip6, + port, priority, weight, property_count, keys, values ); + + if (!(instance = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*instance) ))) + return NULL; + + if (service_name && !(instance->pszInstanceName = wcsdup( service_name ))) + goto fail; + if (host_name && !(instance->pszHostName = wcsdup( host_name ))) + goto fail; + + if (ip4) + { + if (!(instance->ip4Address = HeapAlloc( GetProcessHeap(), 0, sizeof(*instance->ip4Address) ))) + goto fail; + *instance->ip4Address = *ip4; + } + if (ip6) + { + if (!(instance->ip6Address = HeapAlloc( GetProcessHeap(), 0, sizeof(*instance->ip6Address) ))) + goto fail; + *instance->ip6Address = *ip6; + } + + instance->wPort = port; + instance->wPriority = priority; + instance->wWeight = weight; + + if (property_count && keys && values) + { + instance->dwPropertyCount = property_count; + if (!(instance->keys = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + property_count * sizeof(*instance->keys) ))) + goto fail; + if (!(instance->values = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + property_count * sizeof(*instance->values) ))) + goto fail; + for (i = 0; i < property_count; i++) + { + if (keys[i] && !(instance->keys[i] = wcsdup( keys[i] ))) + goto fail; + if (values[i] && !(instance->values[i] = wcsdup( values[i] ))) + goto fail; + } + } + + return instance; + +fail: + DnsServiceFreeInstance( instance ); + return NULL; +} + +/****************************************************************************** + * DnsServiceFreeInstance [DNSAPI.@] + * + */ +VOID WINAPI DnsServiceFreeInstance( PDNS_SERVICE_INSTANCE instance ) +{ + DWORD i; + + FIXME( "(%p) stub\n", instance ); + + if (!instance) return; + + free( instance->pszInstanceName ); + free( instance->pszHostName ); + HeapFree( GetProcessHeap(), 0, instance->ip4Address ); + HeapFree( GetProcessHeap(), 0, instance->ip6Address ); + + if (instance->keys && instance->values) + { + for (i = 0; i < instance->dwPropertyCount; i++) + { + free( instance->keys[i] ); + free( instance->values[i] ); + } + } + HeapFree( GetProcessHeap(), 0, instance->keys ); + HeapFree( GetProcessHeap(), 0, instance->values ); + HeapFree( GetProcessHeap(), 0, instance ); +} + +/****************************************************************************** + * DnsServiceRegister [DNSAPI.@] + * + */ +DNS_STATUS WINAPI DnsServiceRegister( PDNS_SERVICE_REGISTER_REQUEST request, PDNS_SERVICE_CANCEL cancel ) +{ + FIXME( "(%p, %p) stub\n", request, cancel ); + + if (!request) return ERROR_INVALID_PARAMETER; + + /* Invoke completion callback immediately with a not-implemented status so + * callers do not block waiting for an async result that will never arrive. */ + if (request->pRegisterCompletionCallback) + request->pRegisterCompletionCallback( ERROR_CALL_NOT_IMPLEMENTED, + request->pQueryContext, + request->pServiceInstance ); + return DNS_REQUEST_PENDING; +} + +/****************************************************************************** + * DnsServiceDeRegister [DNSAPI.@] + * + */ +DNS_STATUS WINAPI DnsServiceDeRegister( PDNS_SERVICE_REGISTER_REQUEST request, PDNS_SERVICE_CANCEL cancel ) +{ + FIXME( "(%p, %p) stub\n", request, cancel ); + + if (!request) return ERROR_INVALID_PARAMETER; + + if (request->pRegisterCompletionCallback) + request->pRegisterCompletionCallback( ERROR_CALL_NOT_IMPLEMENTED, + request->pQueryContext, + request->pServiceInstance ); + return DNS_REQUEST_PENDING; +} + +/****************************************************************************** + * DnsServiceRegisterCancel [DNSAPI.@] + * + */ +DNS_STATUS WINAPI DnsServiceRegisterCancel( PDNS_SERVICE_CANCEL cancel ) +{ + FIXME( "(%p) stub\n", cancel ); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +/****************************************************************************** + * DnsServiceResolve [DNSAPI.@] + * + */ +DNS_STATUS WINAPI DnsServiceResolve( PDNS_SERVICE_RESOLVE_REQUEST request, PDNS_SERVICE_CANCEL cancel ) +{ + FIXME( "(%p, %p) stub\n", request, cancel ); + + if (!request) return ERROR_INVALID_PARAMETER; + + if (request->pResolveCompletionCallback) + request->pResolveCompletionCallback( ERROR_CALL_NOT_IMPLEMENTED, + request->pQueryContext, + NULL ); + return DNS_REQUEST_PENDING; +} + +/****************************************************************************** + * DnsServiceResolveCancel [DNSAPI.@] + * + */ +DNS_STATUS WINAPI DnsServiceResolveCancel( PDNS_SERVICE_CANCEL cancel ) +{ + FIXME( "(%p) stub\n", cancel ); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +/****************************************************************************** + * DnsServiceBrowseCancel [DNSAPI.@] + * + */ +DNS_STATUS WINAPI DnsServiceBrowseCancel( PDNS_SERVICE_CANCEL cancel ) +{ + FIXME( "(%p) stub\n", cancel ); + return ERROR_CALL_NOT_IMPLEMENTED; +} diff --git a/include/windns.h b/include/windns.h index 87e8dad37da..cf7ac27001f 100644 --- a/include/windns.h +++ b/include/windns.h @@ -781,6 +781,44 @@ typedef struct _DNS_SERVICE_CANCEL void *reserved; } DNS_SERVICE_CANCEL, *PDNS_SERVICE_CANCEL; +typedef struct _DNS_SERVICE_INSTANCE +{ + LPWSTR pszInstanceName; + LPWSTR pszHostName; + PIP4_ADDRESS ip4Address; + PIP6_ADDRESS ip6Address; + WORD wPort; + WORD wPriority; + WORD wWeight; + DWORD dwPropertyCount; + PWSTR *keys; + PWSTR *values; +} DNS_SERVICE_INSTANCE, *PDNS_SERVICE_INSTANCE; + +typedef void WINAPI DNS_SERVICE_REGISTER_COMPLETE(DWORD, void *, PDNS_SERVICE_INSTANCE); +typedef DNS_SERVICE_REGISTER_COMPLETE *PDNS_SERVICE_REGISTER_COMPLETE; + +typedef struct _DNS_SERVICE_REGISTER_REQUEST { + ULONG Version; + ULONG InterfaceIndex; + PDNS_SERVICE_INSTANCE pServiceInstance; + PDNS_SERVICE_REGISTER_COMPLETE pRegisterCompletionCallback; + PVOID pQueryContext; + HANDLE hCredentials; + BOOL unicastEnabled; +} DNS_SERVICE_REGISTER_REQUEST, *PDNS_SERVICE_REGISTER_REQUEST; + +typedef void WINAPI DNS_SERVICE_RESOLVE_COMPLETE(DWORD, void *, PDNS_SERVICE_INSTANCE); +typedef DNS_SERVICE_RESOLVE_COMPLETE *PDNS_SERVICE_RESOLVE_COMPLETE; + +typedef struct _DNS_SERVICE_RESOLVE_REQUEST { + ULONG Version; + ULONG InterfaceIndex; + LPWSTR QueryName; + PDNS_SERVICE_RESOLVE_COMPLETE pResolveCompletionCallback; + PVOID pQueryContext; +} DNS_SERVICE_RESOLVE_REQUEST, *PDNS_SERVICE_RESOLVE_REQUEST; + DNS_STATUS WINAPI DnsAcquireContextHandle_A(DWORD,PVOID,PHANDLE); DNS_STATUS WINAPI DnsAcquireContextHandle_W(DWORD,PVOID,PHANDLE); #define DnsAcquireContextHandle WINELIB_NAME_AW(DnsAcquireContextHandle_) @@ -813,6 +851,14 @@ DNS_STATUS WINAPI DnsReplaceRecordSetW(PDNS_RECORDW,DWORD,HANDLE,PVOID,PVOID); DNS_STATUS WINAPI DnsReplaceRecordSetUTF8(PDNS_RECORDA,DWORD,HANDLE,PVOID,PVOID); #define DnsReplaceRecordSet WINELIB_NAME_AW(DnsReplaceRecordSet) DNS_STATUS WINAPI DnsServiceBrowse(PDNS_SERVICE_BROWSE_REQUEST, PDNS_SERVICE_CANCEL); +DNS_STATUS WINAPI DnsServiceBrowseCancel(PDNS_SERVICE_CANCEL); +PDNS_SERVICE_INSTANCE WINAPI DnsServiceConstructInstance(PCWSTR,PCWSTR,PIP4_ADDRESS,PIP6_ADDRESS,WORD,WORD,WORD,DWORD,PWSTR*,PWSTR*); +VOID WINAPI DnsServiceFreeInstance(PDNS_SERVICE_INSTANCE); +DNS_STATUS WINAPI DnsServiceRegister(PDNS_SERVICE_REGISTER_REQUEST, PDNS_SERVICE_CANCEL); +DNS_STATUS WINAPI DnsServiceDeRegister(PDNS_SERVICE_REGISTER_REQUEST, PDNS_SERVICE_CANCEL); +DNS_STATUS WINAPI DnsServiceRegisterCancel(PDNS_SERVICE_CANCEL); +DNS_STATUS WINAPI DnsServiceResolve(PDNS_SERVICE_RESOLVE_REQUEST, PDNS_SERVICE_CANCEL); +DNS_STATUS WINAPI DnsServiceResolveCancel(PDNS_SERVICE_CANCEL); DNS_STATUS WINAPI DnsValidateName_A(PCSTR,DNS_NAME_FORMAT); DNS_STATUS WINAPI DnsValidateName_W(PCWSTR, DNS_NAME_FORMAT); DNS_STATUS WINAPI DnsValidateName_UTF8(PCSTR,DNS_NAME_FORMAT); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11208
participants (2)
-
Dan Fraser (@DanFraser) -
DanFraser