diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index bd6506d67b..640c6a509f 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -1065,12 +1065,24 @@ static int sceNetInit(MIPSState *mips, u32 poolSize, u32 calloutPri, u32 callout // Free(delete) thread info / data. // Normal usage: sceKernelDeleteThread followed by sceNetFreeThreadInfo with the same threadID as argument +// Both take any thread, also the current one or one that has ended (pspautotests net/inet/offline). +static bool IsThreadID(SceUID thid) { + int type = 0; + return thid != 0 && kernelObjects.GetIDType(thid, &type) && type == SCE_KERNEL_TMID_Thread; +} + static int sceNetFreeThreadinfo(SceUID thid) { + if (!IsThreadID(thid)) { + return hleLogError(Log::sceNet, 0x80410104, "not a thread"); + } return hleLogError(Log::sceNet, 0, "UNIMPL"); } // Abort a thread. static int sceNetThreadAbort(SceUID thid) { + if (!IsThreadID(thid)) { + return hleLogError(Log::sceNet, 0x80410104, "not a thread"); + } return hleLogError(Log::sceNet, 0, "UNIMPL"); } @@ -1184,7 +1196,7 @@ static void sceNetEtherStrton(u32 bufferPtr, u32 macPtr) { static int sceNetGetMallocStat(u32 statPtr) { auto stat = PSPPointer::Create(statPtr); if (!stat.IsValid()) - return hleLogError(Log::sceNet, 0, "invalid address"); + return hleLogError(Log::sceNet, 0x80410103, "invalid address"); *stat = netMallocStat; stat.NotifyWrite("sceNetGetMallocStat"); @@ -1497,6 +1509,10 @@ static int NetApctl_AddHandler(u32 handlerPtr, u32 handlerArg) { // TODO: Should we allow the same handler to be added more than once? static u32 sceNetApctlAddHandler(u32 handlerPtr, u32 handlerArg) { INFO_LOG(Log::sceNet, "%s(%08x, %08x)", __FUNCTION__, handlerPtr, handlerArg); + // A game gets two (pspautotests net/inet/offline). + if (apctlHandlers.size() >= MAX_APCTL_GAME_HANDLERS) { + return hleLogError(Log::sceNet, 0x80410A0F, "too many handlers"); + } return NetApctl_AddHandler(handlerPtr, handlerArg); } @@ -1513,6 +1529,14 @@ static int NetApctl_DelHandler(u32 handlerID) { static int sceNetApctlDelHandler(u32 handlerID) { INFO_LOG(Log::sceNet, "%s(%d)", __FUNCTION__, handlerID); + // An ID that can't be a handler's (100, -1) and a free one give different errors + // (pspautotests net/inet/offline). Where the range ends is inferred from the handler limit. + if (handlerID >= MAX_APCTL_GAME_HANDLERS) { + return hleLogError(Log::sceNet, 0x80410A82, "bad handler id"); + } + if (apctlHandlers.find(handlerID) == apctlHandlers.end()) { + return hleLogError(Log::sceNet, SCE_NET_APCTL_ERROR_INVALID_ID, "no such handler"); + } return NetApctl_DelHandler(handlerID); } @@ -1575,7 +1599,7 @@ static int sceNetApctlGetState(u32 pStateAddr) { return hleLogDebug(Log::sceNet, 0); } - return hleLogError(Log::sceNet, -1, "apctl invalid arg"); // 0x8002013A or ERROR_NET_WLAN_INVALID_ARG ? + return hleLogError(Log::sceNet, 0x80410A03, "apctl invalid arg"); // pspautotests net/inet/offline } // This one logs like a syscall because it's called at the end of some. @@ -1601,8 +1625,9 @@ int NetApctl_GetBSSDescIDListUser(u32 sizeAddr, u32 bufAddr) { const int userInfoSize = 8; // 8 bytes per entry (next address + entry id) // Faking 4 entries, games like MGS:PW Recruit will need to have a different AP for each entry int entries = 4; - if (!Memory::IsValid4AlignedAddress(sizeAddr) || !Memory::IsValidAddress(bufAddr)) - return hleLogError(Log::sceNet, -1, "apctl invalid arg"); // 0x8002013A or ERROR_NET_WLAN_INVALID_ARG ? + // A NULL buffer asks for the size (pspautotests net/inet/offline). + if (!Memory::IsValid4AlignedAddress(sizeAddr) || (bufAddr != 0 && !Memory::IsValidAddress(bufAddr))) + return hleLogError(Log::sceNet, 0x80410A03, "apctl invalid arg"); int size = Memory::ReadUnchecked_U32(sizeAddr); // Return size required @@ -1748,16 +1773,14 @@ static int sceNetApctlDelInternalHandler(u32 handlerID) { static int sceNetApctlAddInternal03Handler(u32 handlerPtr, u32 handlerArg) { ERROR_LOG(Log::sceNet, "UNIMPL %s(%08x, %08x)", __FUNCTION__, handlerPtr, handlerArg); - // This seems to be a 3rd kind of handler - // Simple forward, don't need to use hleCall - return sceNetApctlAddHandler(handlerPtr, handlerArg); + // This seems to be a 3rd kind of handler. The game handler limit doesn't apply. + return NetApctl_AddHandler(handlerPtr, handlerArg); } static int sceNetApctlDelInternal03Handler(u32 handlerID) { ERROR_LOG(Log::sceNet, "UNIMPL %s(%i)", __FUNCTION__, handlerID); // This seems to be a 3rd kind of handler - // Simple forward, don't need to use hleCall - return sceNetApctlDelHandler(handlerID); + return NetApctl_DelHandler(handlerID); } static int sceNetApctl_lib2_69745F0A(int handlerId) { diff --git a/Core/HLE/sceNet.h b/Core/HLE/sceNet.h index 8851f219b4..5418efa2fb 100644 --- a/Core/HLE/sceNet.h +++ b/Core/HLE/sceNet.h @@ -38,6 +38,7 @@ // TODO: Determine how many handlers we can actually have const size_t MAX_APCTL_HANDLERS = 32; +const size_t MAX_APCTL_GAME_HANDLERS = 2; // Through sceNetApctlAddHandler (pspautotests net/inet/offline) typedef void(*sceNetApctlHandler)(int oldState, int newState, int event, int error, void* pArg);