mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
Added support for [6.0.0+] web functionality. Various minor changes.
This commit is contained in:
parent
26458fc1e8
commit
d4de738dfd
@ -29,6 +29,18 @@ typedef enum {
|
||||
WebExitReason_ErrorDialog = 0x7, ///< The applet exited after displaying an error dialog.
|
||||
} WebExitReason;
|
||||
|
||||
/// Button values for \ref webConfigSetBootFooterButtonVisible.
|
||||
typedef enum {
|
||||
WebFooterButtonId_None = 0, ///< None, for empty \ref WebBootFooterButtonEntry. Invalid for \ref webConfigSetBootFooterButtonVisible input.
|
||||
WebFooterButtonId_Type1 = 1, ///< Unknown button Id 1.
|
||||
WebFooterButtonId_Type2 = 2, ///< Unknown button Id 2.
|
||||
WebFooterButtonId_Type3 = 3, ///< Unknown button Id 3.
|
||||
WebFooterButtonId_Type4 = 4, ///< Unknown button Id 4.
|
||||
WebFooterButtonId_Type5 = 5, ///< Unknown button Id 5.
|
||||
WebFooterButtonId_Type6 = 6, ///< Unknown button Id 6.
|
||||
WebFooterButtonId_Max, ///< Values starting with this are invalid.
|
||||
} WebFooterButtonId;
|
||||
|
||||
/// Struct for the WebWifi applet input storage.
|
||||
typedef struct {
|
||||
u32 unk_x0; ///< Official sw sets this to 0 with appletStorageWrite, separately from the rest of the config struct.
|
||||
@ -91,6 +103,14 @@ typedef struct {
|
||||
WebCommonTLVStorage storage; ///< Reply data for reply=true.
|
||||
} WebCommonReply;
|
||||
|
||||
/// Entry data for ::WebArgType_BootFooterButton.
|
||||
typedef struct {
|
||||
WebFooterButtonId id;
|
||||
u8 visible;
|
||||
u16 unk_x5;
|
||||
u8 unk_x7;
|
||||
} PACKED WebBootFooterButtonEntry;
|
||||
|
||||
/// Types for \ref WebArgTLV, input storage.
|
||||
typedef enum {
|
||||
WebArgType_Url = 0x1, ///< [1.0.0+] String, size 0xC00. Initial URL.
|
||||
@ -106,7 +126,7 @@ typedef enum {
|
||||
WebArgType_UnknownC = 0xC, ///< [1.0.0+] u8
|
||||
WebArgType_UnknownD = 0xD, ///< [1.0.0+] u8
|
||||
WebArgType_UserID = 0xE, ///< [1.0.0+] u128 userID, controls which user-specific savedata to mount.
|
||||
WebArgType_AlbumEntry = 0xF, ///< [1.0.0+] Share-applet caps AlbumEntry
|
||||
WebArgType_AlbumEntry0 = 0xF, ///< [1.0.0+] Share-applet caps AlbumEntry, entry 0.
|
||||
WebArgType_ScreenShot = 0x10, ///< [1.0.0+] u8 bool
|
||||
WebArgType_EcClientCert = 0x11, ///< [1.0.0+] u8 bool
|
||||
WebArgType_Unknown12 = 0x12, ///< [1.0.0+] u8
|
||||
@ -124,14 +144,15 @@ typedef enum {
|
||||
WebArgType_DisplayUrlKind = 0x1F, ///< [1.0.0+] u8 bool, DisplayUrlKind (value = (input_enumval==0x1)).
|
||||
WebArgType_BootAsMediaPlayer = 0x21, ///< [2.0.0+] u8 bool
|
||||
WebArgType_ShopJump = 0x22, ///< [2.0.0+] u8 bool
|
||||
WebArgType_MediaPlayerUserGestureRestriction = 0x23, ///< [2.0.0+] u8 bool
|
||||
WebArgType_MediaPlayerUserGestureRestriction = 0x23, ///< [2.0.0-5.1.0] u8 bool
|
||||
WebArgType_MediaAutoPlay = 0x23, ///< [6.0.0+] u8 bool
|
||||
WebArgType_LobbyParameter = 0x24, ///< [2.0.0+] String, size 0x100.
|
||||
WebArgType_ApplicationAlbumEntry = 0x26, ///< [3.0.0+] Share-applet caps ApplicationAlbumEntry
|
||||
WebArgType_JsExtension = 0x27, ///< [3.0.0+] u8 bool
|
||||
WebArgType_AdditionalCommentText = 0x28, ///< [4.0.0+] String, size 0x100. Share-applet AdditionalCommentText.
|
||||
WebArgType_TouchEnabledOnContents = 0x29, ///< [4.0.0+] u8 bool
|
||||
WebArgType_UserAgentAdditionalString = 0x2A, ///< [4.0.0+] String, size 0x80.
|
||||
WebArgType_AdditionalMediaData = 0x2B, ///< [4.0.0+] Share-applet 0x10-byte u8 array, AdditionalMediaData. If the user-input size is less than 0x10, the remaining data used for the TLV is cleared.
|
||||
WebArgType_AdditionalMediaData0 = 0x2B, ///< [4.0.0+] Share-applet 0x10-byte u8 array, AdditionalMediaData. Entry 0. If the user-input size is less than 0x10, the remaining data used for the TLV is cleared.
|
||||
WebArgType_MediaPlayerAutoClose = 0x2C, ///< [4.0.0+] u8 bool
|
||||
WebArgType_PageCache = 0x2D, ///< [4.0.0+] u8 bool
|
||||
WebArgType_WebAudio = 0x2E, ///< [4.0.0+] u8 bool
|
||||
@ -142,6 +163,16 @@ typedef enum {
|
||||
WebArgType_MediaCreatorApplicationRatingAge = 0x34, ///< [5.0.0+] Share-applet 0x20-byte s8 array, MediaCreatorApplicationRatingAge.
|
||||
WebArgType_BootLoadingIcon = 0x35, ///< [5.0.0+] u8 bool
|
||||
WebArgType_PageScrollIndicator = 0x36, ///< [5.0.0+] u8 bool
|
||||
WebArgType_MediaPlayerSpeedControl = 0x37, ///< [6.0.0+] u8 bool
|
||||
WebArgType_AlbumEntry1 = 0x38, ///< [6.0.0+] Share-applet caps AlbumEntry, entry 1.
|
||||
WebArgType_AlbumEntry2 = 0x39, ///< [6.0.0+] Share-applet caps AlbumEntry, entry 2.
|
||||
WebArgType_AlbumEntry3 = 0x3A, ///< [6.0.0+] Share-applet caps AlbumEntry, entry 3.
|
||||
WebArgType_AdditionalMediaData1 = 0x3B, ///< [6.0.0+] Share-applet 0x10-byte u8 array, AdditionalMediaData. Entry 1.
|
||||
WebArgType_AdditionalMediaData2 = 0x3C, ///< [6.0.0+] Share-applet 0x10-byte u8 array, AdditionalMediaData. Entry 2.
|
||||
WebArgType_AdditionalMediaData3 = 0x3D, ///< [6.0.0+] Share-applet 0x10-byte u8 array, AdditionalMediaData. Entry 3.
|
||||
WebArgType_BootFooterButton = 0x3E, ///< [6.0.0+] Array of \ref WebBootFooterButtonEntry with 0x10 entries.
|
||||
WebArgType_OverrideWebAudioVolume = 0x3F, ///< [6.0.0+] float
|
||||
WebArgType_OverrideMediaAudioVolume = 0x40, ///< [6.0.0+] float
|
||||
} WebArgType;
|
||||
|
||||
/// Types for \ref WebArgTLV, output storage.
|
||||
@ -261,7 +292,7 @@ Result webOfflineCreate(WebCommonConfig* config, WebDocumentKind docKind, u64 ti
|
||||
/**
|
||||
* @brief Creates the config for ShareApplet. This applet is for social media posting/settings.
|
||||
* @note If a non-zero userID isn't set with \ref webConfigSetUserID prior to using \ref webConfigShow, the applet will launch the profile-selector applet to select an account.
|
||||
* @note An error will be displayed if neither \ref webConfigSetAlbumEntry or \ref webConfigSetApplicationAlbumEntry are used prior to using \ref webConfigShow, with ::WebShareStartPage_Default.
|
||||
* @note An error will be displayed if neither \ref webConfigSetAlbumEntry, nor \ref webConfigSetApplicationAlbumEntry, nor \ref webConfigAddAlbumEntryAndMediaData are used prior to using \ref webConfigShow, with ::WebShareStartPage_Default.
|
||||
* @note Uses \ref webConfigSetLeftStickMode with ::WebLeftStickMode_Cursor, \ref webConfigSetUserID with userID=0, \ref webConfigSetDisplayUrlKind with kind=true, and sets ::WebArgType_Unknown14/::WebArgType_Unknown15 to value 1. Uses \ref webConfigSetBootDisplayKind with ::WebBootDisplayKind_Unknown3.
|
||||
* @param config WebCommonConfig object.
|
||||
* @param page \ref WebShareStartPage
|
||||
@ -318,7 +349,7 @@ Result webConfigSetUserID(WebCommonConfig* config, u128 userID);
|
||||
* @param config WebCommonConfig object.
|
||||
* @param entry \ref CapsAlbumEntry
|
||||
*/
|
||||
Result webConfigSetAlbumEntry(WebCommonConfig* config, CapsAlbumEntry *entry);
|
||||
Result webConfigSetAlbumEntry(WebCommonConfig* config, const CapsAlbumEntry *entry);
|
||||
|
||||
/**
|
||||
* @brief Sets the ScreenShot flag, which controls whether screen-shot capture is allowed.
|
||||
@ -433,12 +464,20 @@ Result webConfigSetShopJump(WebCommonConfig* config, bool flag);
|
||||
|
||||
/**
|
||||
* @brief Sets the MediaPlayerUserGestureRestriction flag.
|
||||
* @note Only available with config created by \ref webPageCreate on [2.0.0+].
|
||||
* @note Only available with config created by \ref webPageCreate on [2.0.0-5.1.0].
|
||||
* @param config WebCommonConfig object.
|
||||
* @param flag Flag
|
||||
*/
|
||||
Result webConfigSetMediaPlayerUserGestureRestriction(WebCommonConfig* config, bool flag);
|
||||
|
||||
/**
|
||||
* @brief Sets whether MediaAutoPlay is enabled.
|
||||
* @note Only available with config created by \ref webOfflineCreate or \ref webPageCreate, on [6.0.0+].
|
||||
* @param config WebCommonConfig object.
|
||||
* @param flag Flag
|
||||
*/
|
||||
Result webConfigSetMediaAutoPlay(WebCommonConfig* config, bool flag);
|
||||
|
||||
/**
|
||||
* @brief Sets the LobbyParameter.
|
||||
* @note Only available with config created by \ref webLobbyCreate.
|
||||
@ -560,6 +599,49 @@ Result webConfigSetBootLoadingIcon(WebCommonConfig* config, bool flag);
|
||||
*/
|
||||
Result webConfigSetPageScrollIndicator(WebCommonConfig* config, bool flag);
|
||||
|
||||
/**
|
||||
* @brief Sets whether MediaPlayerSpeedControl is enabled.
|
||||
* @note Only available with config created by \ref webOfflineCreate or \ref webPageCreate, on [6.0.0+].
|
||||
* @param config WebCommonConfig object.
|
||||
* @param flag Flag
|
||||
*/
|
||||
Result webConfigSetMediaPlayerSpeedControl(WebCommonConfig* config, bool flag);
|
||||
|
||||
/**
|
||||
* @brief Adds a pair of Share CapsAlbumEntry + optionally AdditionalMediaData. This can be used up to 4 times, for setting multiple pairs.
|
||||
* @note Only available with config created by \ref webShareCreate on [6.0.0+].
|
||||
* @param config WebCommonConfig object.
|
||||
* @param entry \ref CapsAlbumEntry
|
||||
* @param data Input data for AdditionalMediaData. Optional, can be NULL.
|
||||
* @param size Size of the input data, max size is 0x10. Optional, can be 0.
|
||||
*/
|
||||
Result webConfigAddAlbumEntryAndMediaData(WebCommonConfig* config, const CapsAlbumEntry *entry, const u8* data, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Sets whether the specified BootFooterButton is visible.
|
||||
* @note Only available with config created by \ref webOfflineCreate on [6.0.0+].
|
||||
* @param config WebCommonConfig object.
|
||||
* @param button \ref WebFooterButtonId
|
||||
* @param visible Visible flag.
|
||||
*/
|
||||
Result webConfigSetBootFooterButtonVisible(WebCommonConfig* config, WebFooterButtonId button, bool visible);
|
||||
|
||||
/**
|
||||
* @brief Sets OverrideWebAudioVolume.
|
||||
* @note Only available with config created by \ref webOfflineCreate or \ref webPageCreate, on [6.0.0+].
|
||||
* @param config WebCommonConfig object.
|
||||
* @param value Value
|
||||
*/
|
||||
Result webConfigSetOverrideWebAudioVolume(WebCommonConfig* config, float value);
|
||||
|
||||
/**
|
||||
* @brief Sets OverrideMediaAudioVolume.
|
||||
* @note Only available with config created by \ref webOfflineCreate or \ref webPageCreate, on [6.0.0+].
|
||||
* @param config WebCommonConfig object.
|
||||
* @param value Value
|
||||
*/
|
||||
Result webConfigSetOverrideMediaAudioVolume(WebCommonConfig* config, float value);
|
||||
|
||||
/**
|
||||
* @brief Launches the {web applet} with the specified config and waits for it to exit.
|
||||
* @param config WebCommonConfig object.
|
||||
|
@ -172,7 +172,7 @@ static Result _webTLVRead(WebCommonTLVStorage *storage, u16 type, void* argdata,
|
||||
if (size < offset + sizeof(WebArgTLV) + argdata_size) return rc;
|
||||
|
||||
offset+= sizeof(WebArgTLV);
|
||||
memcpy(argdata, &dataptr[offset], argdata_size);
|
||||
if (argdata) memcpy(argdata, &dataptr[offset], argdata_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -238,6 +238,10 @@ static Result _webConfigSetU64(WebCommonConfig* config, u16 type, u64 arg) {
|
||||
return _webTLVSet(config, type, &arg, sizeof(arg));
|
||||
}
|
||||
|
||||
static Result _webConfigSetFloat(WebCommonConfig* config, u16 type, float arg) {
|
||||
return _webTLVSet(config, type, &arg, sizeof(arg));
|
||||
}
|
||||
|
||||
static Result _webConfigSetString(WebCommonConfig* config, u16 type, const char* str, u16 argdata_size_total) {
|
||||
u16 arglen = strlen(str);
|
||||
if (arglen >= argdata_size_total) arglen = argdata_size_total-1; //The string must be NUL-terminated.
|
||||
@ -400,9 +404,13 @@ Result webConfigSetUserID(WebCommonConfig* config, u128 userID) {
|
||||
return _webTLVSet(config, WebArgType_UserID, &userID, sizeof(userID));
|
||||
}
|
||||
|
||||
Result webConfigSetAlbumEntry(WebCommonConfig* config, CapsAlbumEntry *entry) {
|
||||
static Result _webConfigSetAlbumEntryTLV(WebCommonConfig* config, WebArgType type, const CapsAlbumEntry *entry) {
|
||||
if (_webGetShimKind(config) != WebShimKind_Share) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
return _webTLVSet(config, WebArgType_AlbumEntry, entry, sizeof(*entry));
|
||||
return _webTLVSet(config, type, entry, sizeof(*entry));
|
||||
}
|
||||
|
||||
Result webConfigSetAlbumEntry(WebCommonConfig* config, const CapsAlbumEntry *entry) {
|
||||
return _webConfigSetAlbumEntryTLV(config, WebArgType_AlbumEntry0, entry);
|
||||
}
|
||||
|
||||
Result webConfigSetScreenShot(WebCommonConfig* config, bool flag) {
|
||||
@ -490,10 +498,17 @@ Result webConfigSetShopJump(WebCommonConfig* config, bool flag) {
|
||||
|
||||
Result webConfigSetMediaPlayerUserGestureRestriction(WebCommonConfig* config, bool flag) {
|
||||
if (_webGetShimKind(config) != WebShimKind_Web) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
if (hosversionBefore(2,0,0) || hosversionAtLeast(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
return _webConfigSetFlag(config, WebArgType_MediaPlayerUserGestureRestriction, flag);
|
||||
}
|
||||
|
||||
Result webConfigSetMediaAutoPlay(WebCommonConfig* config, bool flag) {
|
||||
WebShimKind shim = _webGetShimKind(config);
|
||||
if (shim != WebShimKind_Offline && shim != WebShimKind_Web) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
return _webConfigSetFlag(config, WebArgType_MediaAutoPlay, flag);
|
||||
}
|
||||
|
||||
Result webConfigSetLobbyParameter(WebCommonConfig* config, const char* str) {
|
||||
if (_webGetShimKind(config) != WebShimKind_Lobby) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
return _webConfigSetString(config, WebArgType_LobbyParameter, str, 0x100);
|
||||
@ -531,10 +546,14 @@ Result webConfigSetUserAgentAdditionalString(WebCommonConfig* config, const char
|
||||
return _webConfigSetString(config, WebArgType_UserAgentAdditionalString, str, 0x80);
|
||||
}
|
||||
|
||||
Result webConfigSetAdditionalMediaData(WebCommonConfig* config, const u8* data, size_t size) {
|
||||
static Result _webConfigSetAdditionalMediaDataTLV(WebCommonConfig* config, WebArgType type, const u8* data, size_t size) {
|
||||
if (_webGetShimKind(config) != WebShimKind_Share) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
return _webTLVWrite(&config->arg, WebArgType_AdditionalMediaData, data, size, 0x10);
|
||||
return _webTLVWrite(&config->arg, type, data, size, 0x10);
|
||||
}
|
||||
|
||||
Result webConfigSetAdditionalMediaData(WebCommonConfig* config, const u8* data, size_t size) {
|
||||
return _webConfigSetAdditionalMediaDataTLV(config, WebArgType_AdditionalMediaData0, data, size);
|
||||
}
|
||||
|
||||
Result webConfigSetMediaPlayerAutoClose(WebCommonConfig* config, bool flag) {
|
||||
@ -591,6 +610,79 @@ Result webConfigSetPageScrollIndicator(WebCommonConfig* config, bool flag) {
|
||||
return _webConfigSetFlag(config, WebArgType_PageScrollIndicator, flag);
|
||||
}
|
||||
|
||||
Result webConfigSetMediaPlayerSpeedControl(WebCommonConfig* config, bool flag) {
|
||||
WebShimKind shim = _webGetShimKind(config);
|
||||
if (shim != WebShimKind_Offline && shim != WebShimKind_Web) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
return _webConfigSetFlag(config, WebArgType_MediaPlayerSpeedControl, flag);
|
||||
}
|
||||
|
||||
Result webConfigAddAlbumEntryAndMediaData(WebCommonConfig* config, const CapsAlbumEntry *entry, const u8* data, size_t size) {
|
||||
Result rc=0;
|
||||
u32 i;
|
||||
WebArgType album_type, media_type;
|
||||
WebArgType album_types[4] = {WebArgType_AlbumEntry0, WebArgType_AlbumEntry1, WebArgType_AlbumEntry2, WebArgType_AlbumEntry3};
|
||||
WebArgType media_types[4] = {WebArgType_AdditionalMediaData0, WebArgType_AdditionalMediaData1, WebArgType_AdditionalMediaData2, WebArgType_AdditionalMediaData3};
|
||||
if (_webGetShimKind(config) != WebShimKind_Share) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
|
||||
// Find a TLV which is not yet set.
|
||||
for(i=0; i<4; i++) {
|
||||
album_type = album_types[i];
|
||||
media_type = media_types[i];
|
||||
rc = _webConfigGet(config, album_type, NULL, sizeof(*entry));
|
||||
if (R_FAILED(rc)) break;
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc)) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
|
||||
|
||||
rc = _webConfigSetAlbumEntryTLV(config, album_type, entry);
|
||||
if (R_SUCCEEDED(rc) && data && size)rc = _webConfigSetAdditionalMediaDataTLV(config, media_type, data, size);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result webConfigSetBootFooterButtonVisible(WebCommonConfig* config, WebFooterButtonId button, bool visible) {
|
||||
Result rc=0;
|
||||
u32 i=0;
|
||||
WebBootFooterButtonEntry entries[0x10];
|
||||
size_t total_entries = sizeof(entries)/sizeof(WebBootFooterButtonEntry);
|
||||
if (_webGetShimKind(config) != WebShimKind_Offline) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
if (button==WebFooterButtonId_None || button>=WebFooterButtonId_Max) return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
memset(entries, 0, sizeof(entries));
|
||||
rc = _webConfigGet(config, WebArgType_BootFooterButton, entries, sizeof(entries));
|
||||
if (R_FAILED(rc)) rc = 0;
|
||||
else {
|
||||
for(i=0; i<total_entries; i++) {
|
||||
if (entries[i].id == button || entries[i].id == WebFooterButtonId_None) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i>=total_entries) return MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
||||
|
||||
if (entries[i].id == WebFooterButtonId_None) entries[i].id = button;
|
||||
entries[i].visible = visible!=0;
|
||||
//Official sw accesses unk_x5/unk_x7, but it doesn't set those using any user input.
|
||||
|
||||
return _webTLVSet(config, WebArgType_BootFooterButton, entries, sizeof(entries));
|
||||
}
|
||||
|
||||
Result webConfigSetOverrideWebAudioVolume(WebCommonConfig* config, float value) {
|
||||
WebShimKind shim = _webGetShimKind(config);
|
||||
if (shim != WebShimKind_Offline && shim != WebShimKind_Web) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
return _webConfigSetFloat(config, WebArgType_OverrideWebAudioVolume, value);
|
||||
}
|
||||
|
||||
Result webConfigSetOverrideMediaAudioVolume(WebCommonConfig* config, float value) {
|
||||
WebShimKind shim = _webGetShimKind(config);
|
||||
if (shim != WebShimKind_Offline && shim != WebShimKind_Web) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
return _webConfigSetFloat(config, WebArgType_OverrideMediaAudioVolume, value);
|
||||
}
|
||||
|
||||
Result webConfigShow(WebCommonConfig* config, WebCommonReply *out) {
|
||||
void* reply = NULL;
|
||||
size_t size = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user