Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix UTF8 strings inside structs #347

Merged
merged 2 commits into from
Aug 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Plugins/Steamworks.NET/InteropHelp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ public static string PtrToStringUTF8(IntPtr nativeUtf8) {
return Encoding.UTF8.GetString(buffer);
}

public static string ByteArrayToStringUTF8(byte[] buffer) {
int length = 0;
while (length < buffer.Length && buffer[length] != 0) {
length++;
}

return Encoding.UTF8.GetString(buffer, 0, length);
}

public static void StringToByteArrayUTF8(string str, byte[] outArrayBuffer, int outArrayBufferSize)
{
outArrayBuffer = new byte[outArrayBufferSize];
int length = Encoding.UTF8.GetBytes(str, 0, str.Length, outArrayBuffer, 0);
outArrayBuffer[length] = 0;
}

// This is for 'const char *' arguments which we need to ensure do not get GC'd while Steam is using them.
// We can't use an ICustomMarshaler because Unity crashes when a string between 96 and 127 characters long is defined/initialized at the top of class scope...
#if UNITY_EDITOR || UNITY_STANDALONE || STEAMWORKS_WIN || STEAMWORKS_LIN_OSX
Expand Down
225 changes: 175 additions & 50 deletions Plugins/Steamworks.NET/autogen/SteamCallbacks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,13 @@ public struct AppProofOfPurchaseKeyResponse_t {
public EResult m_eResult;
public uint m_nAppID;
public uint m_cchKeyLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cubAppProofOfPurchaseKeyMax)]
public string m_rgchKey;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cubAppProofOfPurchaseKeyMax)]
private byte[] m_rgchKey_;
public string m_rgchKey
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchKey_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchKey_, Constants.k_cubAppProofOfPurchaseKeyMax); }
}
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -145,10 +150,20 @@ public struct GameOverlayActivated_t {
[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 32)]
public struct GameServerChangeRequested_t {
public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 32;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string m_rgchServer; // server address ("127.0.0.1:27015", "tf2.valvesoftware.com")
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string m_rgchPassword; // server password, if any
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
private byte[] m_rgchServer_;
public string m_rgchServer // server address ("127.0.0.1:27015", "tf2.valvesoftware.com")
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchServer_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchServer_, 64); }
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
private byte[] m_rgchPassword_;
public string m_rgchPassword // server password, if any
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchPassword_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchPassword_, 64); }
}
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -215,8 +230,13 @@ public struct FriendRichPresenceUpdate_t {
public struct GameRichPresenceJoinRequested_t {
public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 37;
public CSteamID m_steamIDFriend; // the friend they did the join via (will be invalid if not directly via a friend)
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchMaxRichPresenceValueLength)]
public string m_rgchConnect;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchMaxRichPresenceValueLength)]
private byte[] m_rgchConnect_;
public string m_rgchConnect
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchConnect_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchConnect_, Constants.k_cchMaxRichPresenceValueLength); }
}
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -351,8 +371,13 @@ public struct UnreadChatMessagesChanged_t {
[CallbackIdentity(Constants.k_iSteamFriendsCallbacks + 49)]
public struct OverlayBrowserProtocolNavigation_t {
public const int k_iCallback = Constants.k_iSteamFriendsCallbacks + 49;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
public string rgchURI;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
private byte[] rgchURI_;
public string rgchURI
{
get { return InteropHelp.ByteArrayToStringUTF8(rgchURI_); }
set { InteropHelp.StringToByteArrayUTF8(value, rgchURI_, 1024); }
}
}

// callbacks
Expand Down Expand Up @@ -391,8 +416,13 @@ public struct GSClientDeny_t {
public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 2;
public CSteamID m_SteamID;
public EDenyReason m_eDenyReason;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string m_rgchOptionalText;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
private byte[] m_rgchOptionalText_;
public string m_rgchOptionalText
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchOptionalText_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchOptionalText_, 128); }
}
}

// request the game server should kick the user
Expand All @@ -412,8 +442,13 @@ public struct GSClientKick_t {
public struct GSClientAchievementStatus_t {
public const int k_iCallback = Constants.k_iSteamGameServerCallbacks + 6;
public ulong m_SteamID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string m_pchAchievement;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
private byte[] m_pchAchievement_;
public string m_pchAchievement
{
get { return InteropHelp.ByteArrayToStringUTF8(m_pchAchievement_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_pchAchievement_, 128); }
}
[MarshalAs(UnmanagedType.I1)]
public bool m_bUnlocked;
}
Expand Down Expand Up @@ -957,8 +992,13 @@ public struct SteamInventoryStartPurchaseResult_t {
public struct SteamInventoryRequestPricesResult_t {
public const int k_iCallback = Constants.k_iClientInventoryCallbacks + 5;
public EResult m_result;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string m_rgchCurrency;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
private byte[] m_rgchCurrency_;
public string m_rgchCurrency
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchCurrency_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchCurrency_, 4); }
}
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -1251,8 +1291,13 @@ public struct JoinPartyCallback_t {
public EResult m_eResult;
public PartyBeaconID_t m_ulBeaconID;
public CSteamID m_SteamIDBeaconOwner;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string m_rgchConnectString;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
private byte[] m_rgchConnectString_;
public string m_rgchConnectString
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchConnectString_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchConnectString_, 256); }
}
}

// Response to CreateBeacon request. If successful, the beacon ID is provided.
Expand Down Expand Up @@ -1510,8 +1555,13 @@ public struct SteamNetAuthenticationStatus_t {

/// Non-localized English language status. For diagnostic/debugging
/// purposes only.
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string m_debugMsg;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
private byte[] m_debugMsg_;
public string m_debugMsg
{
get { return InteropHelp.ByteArrayToStringUTF8(m_debugMsg_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_debugMsg_, 256); }
}
}

/// A struct used to describe our readiness to use the relay network.
Expand Down Expand Up @@ -1546,8 +1596,13 @@ public struct SteamRelayNetworkStatus_t {

/// Non-localized English language status. For diagnostic/debugging
/// purposes only.
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string m_debugMsg;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
private byte[] m_debugMsg_;
public string m_debugMsg
{
get { return InteropHelp.ByteArrayToStringUTF8(m_debugMsg_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_debugMsg_, 256); }
}
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -1608,8 +1663,13 @@ public struct RemoteStorageAppSyncedServer_t {
[CallbackIdentity(Constants.k_iClientRemoteStorageCallbacks + 3)]
public struct RemoteStorageAppSyncProgress_t {
public const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 3;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchFilenameMax)]
public string m_rgchCurrentFile; // Current file being transferred
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchFilenameMax)]
private byte[] m_rgchCurrentFile_;
public string m_rgchCurrentFile // Current file being transferred
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchCurrentFile_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchCurrentFile_, Constants.k_cchFilenameMax); }
}
public AppId_t m_nAppID; // App this info relates to
public uint m_uBytesTransferredThisChunk; // Bytes transferred this chunk
public double m_dAppPercentComplete; // Percent complete that this app's transfers are
Expand Down Expand Up @@ -1641,8 +1701,13 @@ public struct RemoteStorageFileShareResult_t {
public const int k_iCallback = Constants.k_iClientRemoteStorageCallbacks + 7;
public EResult m_eResult; // The result of the operation
public UGCHandle_t m_hFile; // The handle that can be shared with users and features
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchFilenameMax)]
public string m_rgchFilename; // The name of the file that was shared
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchFilenameMax)]
private byte[] m_rgchFilename_;
public string m_rgchFilename // The name of the file that was shared
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchFilename_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchFilename_, Constants.k_cchFilenameMax); }
}
}

// k_iClientRemoteStorageCallbacks + 8 is deprecated! Do not reuse
Expand Down Expand Up @@ -1746,8 +1811,13 @@ public struct RemoteStorageDownloadUGCResult_t {
public UGCHandle_t m_hFile; // The handle to the file that was attempted to be downloaded.
public AppId_t m_nAppID; // ID of the app that created this file.
public int m_nSizeInBytes; // The size of the file that was downloaded, in bytes.
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchFilenameMax)]
public string m_pchFileName; // The name of the file that was downloaded.
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchFilenameMax)]
private byte[] m_pchFileName_;
public string m_pchFileName // The name of the file that was downloaded.
{
get { return InteropHelp.ByteArrayToStringUTF8(m_pchFileName_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_pchFileName_, Constants.k_cchFilenameMax); }
}
public ulong m_ulSteamIDOwner; // Steam ID of the user who created this content.
}

Expand All @@ -1762,10 +1832,20 @@ public struct RemoteStorageGetPublishedFileDetailsResult_t {
public PublishedFileId_t m_nPublishedFileId;
public AppId_t m_nCreatorAppID; // ID of the app that created this file.
public AppId_t m_nConsumerAppID; // ID of the app that will consume this file.
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedDocumentTitleMax)]
public string m_rgchTitle; // title of document
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedDocumentDescriptionMax)]
public string m_rgchDescription; // description of document
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedDocumentTitleMax)]
private byte[] m_rgchTitle_;
public string m_rgchTitle // title of document
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchTitle_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchTitle_, Constants.k_cchPublishedDocumentTitleMax); }
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedDocumentDescriptionMax)]
private byte[] m_rgchDescription_;
public string m_rgchDescription // description of document
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchDescription_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchDescription_, Constants.k_cchPublishedDocumentDescriptionMax); }
}
public UGCHandle_t m_hFile; // The handle of the primary file
public UGCHandle_t m_hPreviewFile; // The handle of the preview file
public ulong m_ulSteamIDOwner; // Steam ID of the user who created this content.
Expand All @@ -1774,16 +1854,31 @@ public struct RemoteStorageGetPublishedFileDetailsResult_t {
public ERemoteStoragePublishedFileVisibility m_eVisibility;
[MarshalAs(UnmanagedType.I1)]
public bool m_bBanned;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchTagListMax)]
public string m_rgchTags; // comma separated list of all tags associated with this file
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchTagListMax)]
private byte[] m_rgchTags_;
public string m_rgchTags // comma separated list of all tags associated with this file
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchTags_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchTags_, Constants.k_cchTagListMax); }
}
[MarshalAs(UnmanagedType.I1)]
public bool m_bTagsTruncated; // whether the list of tags was too long to be returned in the provided buffer
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchFilenameMax)]
public string m_pchFileName; // The name of the primary file
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchFilenameMax)]
private byte[] m_pchFileName_;
public string m_pchFileName // The name of the primary file
{
get { return InteropHelp.ByteArrayToStringUTF8(m_pchFileName_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_pchFileName_, Constants.k_cchFilenameMax); }
}
public int m_nFileSize; // Size of the primary file
public int m_nPreviewFileSize; // Size of the preview file
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedFileURLMax)]
public string m_rgchURL; // URL (for a video or a website)
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedFileURLMax)]
private byte[] m_rgchURL_;
public string m_rgchURL // URL (for a video or a website)
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchURL_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchURL_, Constants.k_cchPublishedFileURLMax); }
}
public EWorkshopFileType m_eFileType; // Type of the file
[MarshalAs(UnmanagedType.I1)]
public bool m_bAcceptedForUse; // developer has specifically flagged this item as accepted in the Workshop
Expand Down Expand Up @@ -1993,8 +2088,13 @@ public struct SteamUGCQueryCompleted_t {
public uint m_unTotalMatchingResults;
[MarshalAs(UnmanagedType.I1)]
public bool m_bCachedData; // indicates whether this data was retrieved from the local on-disk cache
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchPublishedFileURLMax)]
public string m_rgchNextCursor; // If a paging cursor was used, then this will be the next cursor to get the next result set.
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchPublishedFileURLMax)]
private byte[] m_rgchNextCursor_;
public string m_rgchNextCursor // If a paging cursor was used, then this will be the next cursor to get the next result set.
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchNextCursor_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchNextCursor_, Constants.k_cchPublishedFileURLMax); }
}
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -2328,8 +2428,13 @@ public struct GetAuthSessionTicketResponse_t {
[CallbackIdentity(Constants.k_iSteamUserCallbacks + 64)]
public struct GameWebCallback_t {
public const int k_iCallback = Constants.k_iSteamUserCallbacks + 64;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string m_szURL;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
private byte[] m_szURL_;
public string m_szURL
{
get { return InteropHelp.ByteArrayToStringUTF8(m_szURL_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_szURL_, 256); }
}
}

//-----------------------------------------------------------------------------
Expand All @@ -2339,8 +2444,13 @@ public struct GameWebCallback_t {
[CallbackIdentity(Constants.k_iSteamUserCallbacks + 65)]
public struct StoreAuthURLResponse_t {
public const int k_iCallback = Constants.k_iSteamUserCallbacks + 65;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]
public string m_szURL;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
private byte[] m_szURL_;
public string m_szURL
{
get { return InteropHelp.ByteArrayToStringUTF8(m_szURL_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_szURL_, 512); }
}
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -2427,8 +2537,13 @@ public struct UserAchievementStored_t {
public ulong m_nGameID; // Game this is for
[MarshalAs(UnmanagedType.I1)]
public bool m_bGroupAchievement; // if this is a "group" achievement
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchStatNameMax)]
public string m_rgchAchievementName; // name of the achievement
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchStatNameMax)]
private byte[] m_rgchAchievementName_;
public string m_rgchAchievementName // name of the achievement
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchAchievementName_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchAchievementName_, Constants.k_cchStatNameMax); }
}
public uint m_nCurProgress; // current progress towards the achievement
public uint m_nMaxProgress; // "out of" this many
}
Expand Down Expand Up @@ -2502,8 +2617,13 @@ public struct UserAchievementIconFetched_t {
public const int k_iCallback = Constants.k_iSteamUserStatsCallbacks + 9;

public CGameID m_nGameID; // Game this is for
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.k_cchStatNameMax)]
public string m_rgchAchievementName; // name of the achievement
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.k_cchStatNameMax)]
private byte[] m_rgchAchievementName_;
public string m_rgchAchievementName // name of the achievement
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchAchievementName_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchAchievementName_, Constants.k_cchStatNameMax); }
}
[MarshalAs(UnmanagedType.I1)]
public bool m_bAchieved; // Is the icon for the achieved or not achieved version?
public int m_nIconHandle; // Handle to the image, which can be used in SteamUtils()->GetImageRGBA(), 0 means no image is set for the achievement
Expand Down Expand Up @@ -2614,8 +2734,13 @@ public struct GetVideoURLResult_t {
public const int k_iCallback = Constants.k_iClientVideoCallbacks + 11;
public EResult m_eResult;
public AppId_t m_unVideoAppID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string m_rgchURL;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
private byte[] m_rgchURL_;
public string m_rgchURL
{
get { return InteropHelp.ByteArrayToStringUTF8(m_rgchURL_); }
set { InteropHelp.StringToByteArrayUTF8(value, m_rgchURL_, 256); }
}
}

[StructLayout(LayoutKind.Sequential, Pack = Packsize.value)]
Expand Down
Loading