From 5783d896347a807fbdd66f11bef2188e4962c562 Mon Sep 17 00:00:00 2001 From: Rohan Singh Date: Fri, 13 Dec 2024 19:44:08 -0500 Subject: [PATCH] Manually marshal server list filters to fix crashing --- .../Interfaces/ISteamMatchmakingServers.cs | 30 +++++----- Facepunch.Steamworks/ServerList/Favourites.cs | 10 +--- Facepunch.Steamworks/ServerList/Friends.cs | 10 +--- Facepunch.Steamworks/ServerList/History.cs | 10 +--- Facepunch.Steamworks/ServerList/Internet.cs | 11 +--- .../ServerList/LocalNetwork.cs | 6 +- .../ServerList/ServerFilterMarshaler.cs | 58 +++++++++++++++++++ Generator/Types/BaseType.cs | 5 +- 8 files changed, 90 insertions(+), 50 deletions(-) create mode 100644 Facepunch.Steamworks/ServerList/ServerFilterMarshaler.cs diff --git a/Facepunch.Steamworks/Generated/Interfaces/ISteamMatchmakingServers.cs b/Facepunch.Steamworks/Generated/Interfaces/ISteamMatchmakingServers.cs index 677fb3a..93f582b 100644 --- a/Facepunch.Steamworks/Generated/Interfaces/ISteamMatchmakingServers.cs +++ b/Facepunch.Steamworks/Generated/Interfaces/ISteamMatchmakingServers.cs @@ -23,12 +23,12 @@ namespace Steamworks #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestInternetServerList", CallingConvention = Platform.CC)] - private static extern HServerListRequest _RequestInternetServerList( IntPtr self, AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); + private static extern HServerListRequest _RequestInternetServerList( IntPtr self, AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); #endregion - internal HServerListRequest RequestInternetServerList( AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) + internal HServerListRequest RequestInternetServerList( AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) { - var returnValue = _RequestInternetServerList( Self, iApp, ref ppchFilters, nFilters, pRequestServersResponse ); + var returnValue = _RequestInternetServerList( Self, iApp, ppchFilters, nFilters, pRequestServersResponse ); return returnValue; } @@ -45,45 +45,45 @@ namespace Steamworks #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestFriendsServerList", CallingConvention = Platform.CC)] - private static extern HServerListRequest _RequestFriendsServerList( IntPtr self, AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); + private static extern HServerListRequest _RequestFriendsServerList( IntPtr self, AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); #endregion - internal HServerListRequest RequestFriendsServerList( AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) + internal HServerListRequest RequestFriendsServerList( AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) { - var returnValue = _RequestFriendsServerList( Self, iApp, ref ppchFilters, nFilters, pRequestServersResponse ); + var returnValue = _RequestFriendsServerList( Self, iApp, ppchFilters, nFilters, pRequestServersResponse ); return returnValue; } #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestFavoritesServerList", CallingConvention = Platform.CC)] - private static extern HServerListRequest _RequestFavoritesServerList( IntPtr self, AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); + private static extern HServerListRequest _RequestFavoritesServerList( IntPtr self, AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); #endregion - internal HServerListRequest RequestFavoritesServerList( AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) + internal HServerListRequest RequestFavoritesServerList( AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) { - var returnValue = _RequestFavoritesServerList( Self, iApp, ref ppchFilters, nFilters, pRequestServersResponse ); + var returnValue = _RequestFavoritesServerList( Self, iApp, ppchFilters, nFilters, pRequestServersResponse ); return returnValue; } #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestHistoryServerList", CallingConvention = Platform.CC)] - private static extern HServerListRequest _RequestHistoryServerList( IntPtr self, AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); + private static extern HServerListRequest _RequestHistoryServerList( IntPtr self, AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); #endregion - internal HServerListRequest RequestHistoryServerList( AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) + internal HServerListRequest RequestHistoryServerList( AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) { - var returnValue = _RequestHistoryServerList( Self, iApp, ref ppchFilters, nFilters, pRequestServersResponse ); + var returnValue = _RequestHistoryServerList( Self, iApp, ppchFilters, nFilters, pRequestServersResponse ); return returnValue; } #region FunctionMeta [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_RequestSpectatorServerList", CallingConvention = Platform.CC)] - private static extern HServerListRequest _RequestSpectatorServerList( IntPtr self, AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); + private static extern HServerListRequest _RequestSpectatorServerList( IntPtr self, AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ); #endregion - internal HServerListRequest RequestSpectatorServerList( AppId iApp, [In,Out] ref MatchMakingKeyValuePair[] ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) + internal HServerListRequest RequestSpectatorServerList( AppId iApp, IntPtr ppchFilters, uint nFilters, IntPtr pRequestServersResponse ) { - var returnValue = _RequestSpectatorServerList( Self, iApp, ref ppchFilters, nFilters, pRequestServersResponse ); + var returnValue = _RequestSpectatorServerList( Self, iApp, ppchFilters, nFilters, pRequestServersResponse ); return returnValue; } diff --git a/Facepunch.Steamworks/ServerList/Favourites.cs b/Facepunch.Steamworks/ServerList/Favourites.cs index 6f1ffa3..fb1bbd4 100644 --- a/Facepunch.Steamworks/ServerList/Favourites.cs +++ b/Facepunch.Steamworks/ServerList/Favourites.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; namespace Steamworks.ServerList { @@ -10,8 +6,8 @@ namespace Steamworks.ServerList { internal override void LaunchQuery() { - var filters = GetFilters(); - request = Internal.RequestFavoritesServerList( AppId.Value, ref filters, (uint)filters.Length, IntPtr.Zero ); + using var filters = new ServerFilterMarshaler( GetFilters() ); + request = Internal.RequestFavoritesServerList( AppId.Value, filters.Pointer, (uint)filters.Count, IntPtr.Zero ); } } -} \ No newline at end of file +} diff --git a/Facepunch.Steamworks/ServerList/Friends.cs b/Facepunch.Steamworks/ServerList/Friends.cs index eb66a69..40a7f26 100644 --- a/Facepunch.Steamworks/ServerList/Friends.cs +++ b/Facepunch.Steamworks/ServerList/Friends.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; namespace Steamworks.ServerList { @@ -10,8 +6,8 @@ namespace Steamworks.ServerList { internal override void LaunchQuery() { - var filters = GetFilters(); - request = Internal.RequestFriendsServerList( AppId.Value, ref filters, (uint)filters.Length, IntPtr.Zero ); + using var filters = new ServerFilterMarshaler( GetFilters() ); + request = Internal.RequestFriendsServerList( AppId.Value, filters.Pointer, (uint)filters.Count, IntPtr.Zero ); } } -} \ No newline at end of file +} diff --git a/Facepunch.Steamworks/ServerList/History.cs b/Facepunch.Steamworks/ServerList/History.cs index 55ccc16..7b90657 100644 --- a/Facepunch.Steamworks/ServerList/History.cs +++ b/Facepunch.Steamworks/ServerList/History.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; namespace Steamworks.ServerList { @@ -10,8 +6,8 @@ namespace Steamworks.ServerList { internal override void LaunchQuery() { - var filters = GetFilters(); - request = Internal.RequestHistoryServerList( AppId.Value, ref filters, (uint)filters.Length, IntPtr.Zero ); + using var filters = new ServerFilterMarshaler( GetFilters() ); + request = Internal.RequestHistoryServerList( AppId.Value, filters.Pointer, (uint)filters.Count, IntPtr.Zero ); } } -} \ No newline at end of file +} diff --git a/Facepunch.Steamworks/ServerList/Internet.cs b/Facepunch.Steamworks/ServerList/Internet.cs index abb2fd0..8bca15d 100644 --- a/Facepunch.Steamworks/ServerList/Internet.cs +++ b/Facepunch.Steamworks/ServerList/Internet.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; namespace Steamworks.ServerList { @@ -10,9 +6,8 @@ namespace Steamworks.ServerList { internal override void LaunchQuery() { - var filters = GetFilters(); - - request = Internal.RequestInternetServerList( AppId.Value, ref filters, (uint)filters.Length, IntPtr.Zero ); + using var filters = new ServerFilterMarshaler( GetFilters() ); + request = Internal.RequestInternetServerList( AppId.Value, filters.Pointer, (uint)filters.Count, IntPtr.Zero ); } } -} \ No newline at end of file +} diff --git a/Facepunch.Steamworks/ServerList/LocalNetwork.cs b/Facepunch.Steamworks/ServerList/LocalNetwork.cs index 7468873..73da488 100644 --- a/Facepunch.Steamworks/ServerList/LocalNetwork.cs +++ b/Facepunch.Steamworks/ServerList/LocalNetwork.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; namespace Steamworks.ServerList { @@ -13,4 +9,4 @@ namespace Steamworks.ServerList request = Internal.RequestLANServerList( AppId.Value, IntPtr.Zero ); } } -} \ No newline at end of file +} diff --git a/Facepunch.Steamworks/ServerList/ServerFilterMarshaler.cs b/Facepunch.Steamworks/ServerList/ServerFilterMarshaler.cs new file mode 100644 index 0000000..c0baf6d --- /dev/null +++ b/Facepunch.Steamworks/ServerList/ServerFilterMarshaler.cs @@ -0,0 +1,58 @@ +using System; +using System.Runtime.InteropServices; +using Steamworks.Data; + +namespace Steamworks.ServerList; + +internal struct ServerFilterMarshaler : IDisposable +{ + private static readonly int SizeOfPointer = Marshal.SizeOf(); + private static readonly int SizeOfKeyValuePair = Marshal.SizeOf(); + + private IntPtr _arrayPtr; + private IntPtr _itemsPtr; + + public int Count { get; private set; } + public IntPtr Pointer => _arrayPtr; + + public ServerFilterMarshaler( MatchMakingKeyValuePair[] filters ) + { + if ( filters == null || filters.Length == 0 ) + { + Count = 0; + _arrayPtr = IntPtr.Zero; + _itemsPtr = IntPtr.Zero; + return; + } + + Count = filters.Length; + _arrayPtr = Marshal.AllocHGlobal( SizeOfPointer * filters.Length ); + _itemsPtr = Marshal.AllocHGlobal( SizeOfKeyValuePair * filters.Length ); + + var arrayDst = _arrayPtr; + var itemDst = _itemsPtr; + foreach ( var filter in filters ) + { + Marshal.WriteIntPtr( arrayDst, itemDst ); + arrayDst += SizeOfPointer; + + Marshal.StructureToPtr( filter, itemDst, false ); + itemDst += SizeOfKeyValuePair; + } + } + + public void Dispose() + { + if ( _arrayPtr != IntPtr.Zero ) + { + Marshal.FreeHGlobal( _arrayPtr ); + _arrayPtr = IntPtr.Zero; + } + + if ( _itemsPtr != IntPtr.Zero ) + { + Marshal.FreeHGlobal( _itemsPtr ); + _itemsPtr = IntPtr.Zero; + } + } +} diff --git a/Generator/Types/BaseType.cs b/Generator/Types/BaseType.cs index 0bafad8..45a965d 100644 --- a/Generator/Types/BaseType.cs +++ b/Generator/Types/BaseType.cs @@ -17,13 +17,16 @@ internal class BaseType { type = Cleanup.ConvertType( type ); + var typeNoSpaces = type.Replace( " ", "" ); + if ( varname == "ppOutMessages" ) return new PointerType { NativeType = "void *", VarName = varname }; if ( type == "SteamAPIWarningMessageHook_t" ) return new PointerType { NativeType = type, VarName = varname }; + if ( typeNoSpaces == "MatchMakingKeyValuePair**") return new PointerType { NativeType = "MatchMakingKeyValuePair_t", VarName = varname }; if ( type == "SteamAPICall_t" ) return new SteamApiCallType { NativeType = type, VarName = varname, CallResult = callresult }; if ( type == "void" ) return new VoidType { NativeType = type, VarName = varname }; - if ( type.Replace( " ", "" ).StartsWith( "constchar*" ) ) return new ConstCharType { NativeType = type, VarName = varname }; + if ( typeNoSpaces.StartsWith( "constchar*" ) ) return new ConstCharType { NativeType = type, VarName = varname }; if ( type == "char *" ) return new FetchStringType { NativeType = type, VarName = varname, BufferSizeParamName = bufferSizeName }; var basicType = type.Replace( "const ", "" ).Trim( ' ', '*', '&' );