From 89c0b5f20b115fa53ec30338843edeb817147dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 7 Apr 2025 22:16:32 +0200 Subject: [PATCH] sceNetResolver: Move error codes to enum, modernize logging --- Core/HLE/ErrorCodes.h | 26 ++++++++ Core/HLE/sceKernel.cpp | 24 +++++++ Core/HLE/sceNet.cpp | 6 +- Core/HLE/sceNetResolver.cpp | 121 +++++++++++++++++++----------------- Core/HLE/sceNetResolver.h | 27 -------- 5 files changed, 119 insertions(+), 85 deletions(-) diff --git a/Core/HLE/ErrorCodes.h b/Core/HLE/ErrorCodes.h index 0642f3ff48..beb00143af 100644 --- a/Core/HLE/ErrorCodes.h +++ b/Core/HLE/ErrorCodes.h @@ -512,4 +512,30 @@ enum PSPErrorCode : u32 { SCE_MP3_ERROR_BAD_RESET_FRAME = 0x80671501, SCE_MP3_ERROR_BAD_ADDR = 0x80671002, SCE_MP3_ERROR_BAD_SIZE = 0x80671003, + + // pspnet_resolver + SCE_NET_RESOLVER_ERROR_NOT_TERMINATED = 0x80410401, + SCE_NET_RESOLVER_ERROR_NO_DNS_SERVER = 0x80410402, + SCE_NET_RESOLVER_ERROR_INVALID_PTR = 0x80410403, + SCE_NET_RESOLVER_ERROR_INVALID_BUFLEN = 0x80410404, + SCE_NET_RESOLVER_ERROR_INVALID_ID = 0x80410405, + SCE_NET_RESOLVER_ERROR_ID_MAX = 0x80410406, + SCE_NET_RESOLVER_ERROR_NO_MEM = 0x80410407, + SCE_NET_RESOLVER_ERROR_BAD_ID = 0x80410408, // ERROR_NET_RESOLVER_ID_NOT_FOUND + SCE_NET_RESOLVER_ERROR_CTX_BUSY = 0x80410409, + SCE_NET_RESOLVER_ERROR_ALREADY_STOPPED = 0x8041040a, + SCE_NET_RESOLVER_ERROR_NOT_SUPPORTED = 0x8041040b, + SCE_NET_RESOLVER_ERROR_BUF_NO_SPACE = 0x8041040c, + SCE_NET_RESOLVER_ERROR_INVALID_PACKET = 0x8041040d, + SCE_NET_RESOLVER_ERROR_STOPPED = 0x8041040e, + SCE_NET_RESOLVER_ERROR_SOCKET = 0x8041040f, + SCE_NET_RESOLVER_ERROR_TIMEOUT = 0x80410410, + SCE_NET_RESOLVER_ERROR_NO_RECORD = 0x80410411, + SCE_NET_RESOLVER_ERROR_RES_PACKET_FORMAT = 0x80410412, + SCE_NET_RESOLVER_ERROR_RES_SERVER_FAILURE = 0x80410413, + SCE_NET_RESOLVER_ERROR_INVALID_HOST = 0x80410414, // ERROR_NET_RESOLVER_NO_HOST + SCE_NET_RESOLVER_ERROR_RES_NOT_IMPLEMENTED = 0x80410415, + SCE_NET_RESOLVER_ERROR_RES_SERVER_REFUSED = 0x80410416, + SCE_NET_RESOLVER_ERROR_INTERNAL = 0x80410417, + }; diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 6cc6011066..85827d3be7 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -1512,6 +1512,30 @@ const char *KernelErrorToString(u32 err) { case SCE_MP3_ERROR_BAD_ADDR: return "SCE_MP3_ERROR_BAD_ADDR"; case SCE_MP3_ERROR_BAD_SIZE: return "SCE_MP3_ERROR_BAD_SIZE"; + case SCE_NET_RESOLVER_ERROR_NOT_TERMINATED: return "SCE_NET_RESOLVER_ERROR_NOT_TERMINATED"; + case SCE_NET_RESOLVER_ERROR_NO_DNS_SERVER: return "SCE_NET_RESOLVER_ERROR_NO_DNS_SERVER"; + case SCE_NET_RESOLVER_ERROR_INVALID_PTR: return "SCE_NET_RESOLVER_ERROR_INVALID_PTR"; + case SCE_NET_RESOLVER_ERROR_INVALID_BUFLEN: return "SCE_NET_RESOLVER_ERROR_INVALID_BUFLEN"; + case SCE_NET_RESOLVER_ERROR_INVALID_ID: return "SCE_NET_RESOLVER_ERROR_INVALID_ID"; + case SCE_NET_RESOLVER_ERROR_ID_MAX: return "SCE_NET_RESOLVER_ERROR_ID_MAX"; + case SCE_NET_RESOLVER_ERROR_NO_MEM: return "SCE_NET_RESOLVER_ERROR_NO_MEM"; + case SCE_NET_RESOLVER_ERROR_BAD_ID: return "SCE_NET_RESOLVER_ERROR_BAD_ID"; + case SCE_NET_RESOLVER_ERROR_CTX_BUSY: return "SCE_NET_RESOLVER_ERROR_CTX_BUSY"; + case SCE_NET_RESOLVER_ERROR_ALREADY_STOPPED: return "SCE_NET_RESOLVER_ERROR_ALREADY_STOPPED"; + case SCE_NET_RESOLVER_ERROR_NOT_SUPPORTED: return "SCE_NET_RESOLVER_ERROR_NOT_SUPPORTED"; + case SCE_NET_RESOLVER_ERROR_BUF_NO_SPACE: return "SCE_NET_RESOLVER_ERROR_BUF_NO_SPACE"; + case SCE_NET_RESOLVER_ERROR_INVALID_PACKET: return "SCE_NET_RESOLVER_ERROR_INVALID_PACKET"; + case SCE_NET_RESOLVER_ERROR_STOPPED: return "SCE_NET_RESOLVER_ERROR_STOPPED"; + case SCE_NET_RESOLVER_ERROR_SOCKET: return "SCE_NET_RESOLVER_ERROR_SOCKET"; + case SCE_NET_RESOLVER_ERROR_TIMEOUT: return "SCE_NET_RESOLVER_ERROR_TIMEOUT"; + case SCE_NET_RESOLVER_ERROR_NO_RECORD: return "SCE_NET_RESOLVER_ERROR_NO_RECORD"; + case SCE_NET_RESOLVER_ERROR_RES_PACKET_FORMAT: return "SCE_NET_RESOLVER_ERROR_RES_PACKET_FORMAT"; + case SCE_NET_RESOLVER_ERROR_RES_SERVER_FAILURE: return "SCE_NET_RESOLVER_ERROR_RES_SERVER_FAILURE"; + case SCE_NET_RESOLVER_ERROR_INVALID_HOST: return "SCE_NET_RESOLVER_ERROR_INVALID_HOST"; + case SCE_NET_RESOLVER_ERROR_RES_NOT_IMPLEMENTED: return "SCE_NET_RESOLVER_ERROR_RES_NOT_IMPLEMENTED"; + case SCE_NET_RESOLVER_ERROR_RES_SERVER_REFUSED: return "SCE_NET_RESOLVER_ERROR_RES_SERVER_REFUSED"; + case SCE_NET_RESOLVER_ERROR_INTERNAL: return "SCE_NET_RESOLVER_ERROR_INTERNAL"; + default: return nullptr; } diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 4adfa686cc..3b3b34273f 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -327,7 +327,8 @@ bool LoadAutoDNS(std::string_view json) { return false; } - // If dyn_dns is non-empty, try to use it to replace the specified DNS. + // If dyn_dns is non-empty, try to use it to replace the specified DNS server. + // Additionally, this removes all fixed lookups from the table. // If fails, we just use the dns. TODO: Do this in the background somehow... const auto &dns = g_infraDNSConfig.dns; const auto &dyn_dns = g_infraDNSConfig.dyn_dns; @@ -1182,6 +1183,9 @@ int NetApctl_Term() { apctlThreadID = 0; } + // Clear out handlers. + apctlHandlers.clear(); + g_netApctlInited = false; netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED; return 0; diff --git a/Core/HLE/sceNetResolver.cpp b/Core/HLE/sceNetResolver.cpp index d6ba8de9ac..dcafede224 100644 --- a/Core/HLE/sceNetResolver.cpp +++ b/Core/HLE/sceNetResolver.cpp @@ -30,6 +30,7 @@ #include "Common/Serialize/SerializeMap.h" #include "Core/Config.h" #include "Core/HLE/HLE.h" +#include "Core/HLE/ErrorCodes.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HLE/sceKernelMemory.h" #include "Core/MIPS/MIPS.h" @@ -61,36 +62,30 @@ struct NetResolver { static int g_currentNetResolverId = 1; static std::unordered_map g_netResolvers; -static std::mutex g_netResolversLock; // Do we really need this? // NOTE: It starts as true, needed for Outrun 2006. static bool g_netResolverInitialized = true; static int sceNetResolverInit() { // Hardcoded mHostToAlias entries here have been moved to the infra-dns.json file. + g_netResolverInitialized = true; return hleLogInfo(Log::sceNet, 0); } void __NetResolverShutdown() { - std::unique_lock lock(g_netResolversLock); g_netResolvers.clear(); + g_netResolverInitialized = false; } static int sceNetResolverTerm() { - g_netResolverInitialized = false; __NetResolverShutdown(); return hleLogInfo(Log::sceNet, 0); } +// TODO: Add DoState, store the ID gen and active resolvers. + // Note: timeouts are in seconds -static int NetResolver_StartNtoA(u32 resolverId, u32 hostnamePtr, u32 inAddrPtr, int timeout, int retry) { - std::unique_lock lock(g_netResolversLock); - - auto iter = g_netResolvers.find(resolverId); - if (iter == g_netResolvers.end()) { - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_BAD_ID, "Bad Resolver Id: %i", resolverId); - } - +static int NetResolver_StartNtoA(NetResolver *resolver, u32 hostnamePtr, u32 inAddrPtr, int timeout, int retry) { addrinfo *resolved = nullptr; std::string err; @@ -127,7 +122,7 @@ static int NetResolver_StartNtoA(u32 resolverId, u32 hostnamePtr, u32 inAddrPtr, } // Flag resolver as in-progress - not relevant for sync functions but potentially relevant for async - iter->second.isRunning = true; + resolver->isRunning = true; // Now use the configured primary DNS server to do a lookup. // If auto DNS, use the server from that config. @@ -141,9 +136,9 @@ static int NetResolver_StartNtoA(u32 resolverId, u32 hostnamePtr, u32 inAddrPtr, if (net::DirectDNSLookupIPV4(dnsServer.c_str(), hostname.c_str(), &resolvedAddr)) { char temp[32]; inet_ntop(AF_INET, &resolvedAddr, temp, sizeof(temp)); - INFO_LOG(Log::sceNet, "Direct lookup of '%s' from '%s' succeeded: %s (%08x)", hostname.c_str(), dnsServer.c_str(), temp, resolvedAddr); - iter->second.isRunning = false; + resolver->isRunning = false; Memory::Write_U32(resolvedAddr, inAddrPtr); + INFO_LOG(Log::sceNet, "Direct lookup of '%s' from '%s' succeeded: %s (%08x)", hostname.c_str(), dnsServer.c_str(), temp, resolvedAddr); return 0; } @@ -152,8 +147,8 @@ static int NetResolver_StartNtoA(u32 resolverId, u32 hostnamePtr, u32 inAddrPtr, // Attempt to execute an OS DNS resolution if (!net::DNSResolve(hostname, "", &resolved, err)) { // TODO: Return an error based on the outputted "err" (unfortunately it's already converted to string) - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_INVALID_HOST, - "OS DNS Error Resolving %s (%s)\n", hostname.c_str(), err.c_str()); + ERROR_LOG(Log::sceNet, "OS DNS Error Resolving %s (%s)\n", hostname.c_str(), err.c_str()); + return SCE_NET_RESOLVER_ERROR_INVALID_HOST; } // If successful, write to memory @@ -168,78 +163,94 @@ static int NetResolver_StartNtoA(u32 resolverId, u32 hostnamePtr, u32 inAddrPtr, net::DNSResolveFree(resolved); Memory::Write_U32(addr.in.sin_addr.s_addr, inAddrPtr); + resolver->isRunning = false; INFO_LOG(Log::sceNet, "%s - Hostname: %s => IPv4: %s", __FUNCTION__, hostname.c_str(), ip2str(addr.in.sin_addr, false).c_str()); } // Flag resolver as complete - iter->second.isRunning = false; + resolver->isRunning = false; return 0; } static int sceNetResolverStartNtoA(int resolverId, u32 hostnamePtr, u32 inAddrPtr, int timeout, int retry) { if (!g_netResolverInitialized) { - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_STOPPED, "Resolver Subsystem Stopped (Resolver Id: %i)", resolverId); + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_STOPPED, "Resolver subsystem not running"); + } + + auto iter = g_netResolvers.find(resolverId); + if (iter == g_netResolvers.end()) { + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_BAD_ID, "Bad Resolver Id: %i", resolverId); } for (int attempt = 0; attempt < retry; ++attempt) { - if (const int status = NetResolver_StartNtoA(resolverId, hostnamePtr, inAddrPtr, timeout, retry); status >= 0) { - return hleLogInfo(Log::sceNet, status); + const int status = NetResolver_StartNtoA(&iter->second, hostnamePtr, inAddrPtr, timeout, retry); + if (status >= 0) { + return hleLogDebugOrError(Log::sceNet, status); } } - return -1; + return hleLogError(Log::sceNet, -1); } static int sceNetResolverStartNtoAAsync(int resolverId, u32 hostnamePtr, u32 inAddrPtr, int timeout, int retry) { if (!g_netResolverInitialized) { - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_STOPPED, "Resolver Subsystem Stopped (Resolver Id: %i)", - resolverId); + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_STOPPED, "Resolver subsystem not running"); } - ERROR_LOG_REPORT_ONCE(sceNetResolverStartNtoAAsync, Log::sceNet, "UNIMPL %s(%d, %08x, %08x, %d, %d) at %08x", - __FUNCTION__, resolverId, hostnamePtr, inAddrPtr, timeout, retry, currentMIPS->pc); - return NetResolver_StartNtoA(resolverId, hostnamePtr, inAddrPtr, timeout, retry); + + auto iter = g_netResolvers.find(resolverId); + if (iter == g_netResolvers.end()) { + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_BAD_ID, "Bad Resolver Id: %i", resolverId); + } + + const int status = NetResolver_StartNtoA(&iter->second, hostnamePtr, inAddrPtr, timeout, retry); + return hleLogDebugOrError(Log::sceNet, status); } static int sceNetResolverPollAsync(int resolverId, u32 unknown) { - ERROR_LOG_REPORT_ONCE(sceNetResolverPollAsync, Log::sceNet, "UNIMPL %s(%d, %08x) at %08x", __FUNCTION__, resolverId, unknown, currentMIPS->pc); + if (!g_netResolverInitialized) { + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_STOPPED, "Resolver subsystem not running"); + } + // TODO: Implement after confirming that this returns the state of resolver.isRunning - return 0; + return hleLogError(Log::sceNet, 0, "UNIMPL"); } static int sceNetResolverWaitAsync(int resolverId, u32 unknown) { - ERROR_LOG_REPORT_ONCE(sceNetResolverWaitAsync, Log::sceNet, "UNIMPL %s(%d, %08x) at %08x", __FUNCTION__, resolverId, unknown, currentMIPS->pc); - // TODO: Implement after confirming that this blocks current thread until resolver.isRunning flips to false - return 0; + if (!g_netResolverInitialized) { + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_STOPPED, "Resolver subsystem not running"); + } + + // TODO: Implement after confirming that this blocks current thread until resolver.isRunning flips to false + return hleLogError(Log::sceNet, 0, "UNIMPL"); } static int sceNetResolverStartAtoN(int resolverId, u32 inAddr, u32 hostnamePtr, int hostnameLength, int timeout, int retry) { - ERROR_LOG_REPORT_ONCE(sceNetResolverStartAtoN, Log::sceNet, "UNIMPL %s(%d, %08x[%s], %08x, %i, %i, %i) at %08x", - __FUNCTION__, resolverId, inAddr, ip2str(*(in_addr*)&inAddr, false).c_str(), hostnamePtr, - hostnameLength, timeout, retry, currentMIPS->pc); + if (!g_netResolverInitialized) { + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_STOPPED, "Resolver subsystem not running"); + } // TODO: Implement via getnameinfo - return 0; + return hleLogError(Log::sceNet, 0, "UNIMPL"); } static int sceNetResolverStartAtoNAsync(int resolverId, u32 inAddr, u32 hostnamePtr, int hostnameLength, int timeout, int retry) { - ERROR_LOG_REPORT_ONCE(sceNetResolverStartAtoNAsync, Log::sceNet, "UNIMPL %s(%d, %08x[%s], %08x, %i, %i, %i) at %08x", - __FUNCTION__, resolverId, inAddr, ip2str(*(in_addr*)&inAddr, false).c_str(), hostnamePtr, - hostnameLength, timeout, retry, currentMIPS->pc); - return 0; + if (!g_netResolverInitialized) { + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_STOPPED, "Resolver subsystem not running"); + } + return hleLogError(Log::sceNet, 0, "UNIMPL"); } static int sceNetResolverCreate(u32 resolverIdPtr, u32 bufferPtr, int bufferLen) { if (!Memory::IsValidRange(resolverIdPtr, 4)) - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_INVALID_PTR, "Invalid Ptr: %08x", resolverIdPtr); + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_INVALID_PTR, "Invalid Ptr: %08x", resolverIdPtr); if (Memory::IsValidRange(bufferPtr, 4) && bufferLen < 1) - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_INVALID_BUFLEN, "Invalid Buffer Length: %i", bufferLen); + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_INVALID_BUFLEN, "Invalid Buffer Length: %i", bufferLen); - // Outrun calls this without init. + // Outrun calls this without init. Something else must have initialized it, unclear what. - // TODO: Consider using SceUidManager instead of this 1-indexed id - // TODO: Implement ERROR_NET_RESOLVER_ID_MAX (possibly 32?) - std::unique_lock lock(g_netResolversLock); - int currentNetResolverId = g_currentNetResolverId++; + // TODO: Consider using SceUidManager instead of this 1-indexed id - not sure what the PSP does. Actually, probably not using SceUID. + // TODO: Implement SCE_NET_RESOLVER_ERROR_ID_MAX (possibly 32?) + const int currentNetResolverId = g_currentNetResolverId++; g_netResolvers[currentNetResolverId] = NetResolver{ currentNetResolverId, // id false, @@ -247,25 +258,23 @@ static int sceNetResolverCreate(u32 resolverIdPtr, u32 bufferPtr, int bufferLen) (u32)bufferLen // bufferLen }; - Memory::Write_U32(currentNetResolverId, resolverIdPtr); - return hleLogInfo(Log::sceNet, 0, "ID: %d", Memory::Read_U32(resolverIdPtr)); + Memory::WriteUnchecked_U32(currentNetResolverId, resolverIdPtr); + return hleLogInfo(Log::sceNet, 0, "ID: %d", currentNetResolverId); } static int sceNetResolverStop(u32 resolverId) { if (!g_netResolverInitialized) { - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_STOPPED, "Resolver Subsystem Stopped"); + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_STOPPED, "Resolver subsystem not running"); } - std::unique_lock lock(g_netResolversLock); - const auto resolverIter = g_netResolvers.find(resolverId); if (resolverIter == g_netResolvers.end()) { - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_BAD_ID, "Bad Resolver Id: %i", resolverId); + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_BAD_ID, "Bad Resolver Id: %i", resolverId); } if (resolverIter->second.isRunning) { - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_ALREADY_STOPPED, "Resolver Already Stopped (Id: %i)", resolverId); + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_ALREADY_STOPPED, "Resolver Already Stopped (Id: %i)", resolverId); } resolverIter->second.isRunning = false; @@ -274,14 +283,12 @@ static int sceNetResolverStop(u32 resolverId) { static int sceNetResolverDelete(u32 resolverId) { if (!g_netResolverInitialized) { - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_STOPPED, "Resolver Subsystem Stopped"); + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_STOPPED, "Resolver subsystem not running"); } - std::unique_lock lock(g_netResolversLock); - const auto resolverIter = g_netResolvers.find(resolverId); if (resolverIter == g_netResolvers.end()) { - return hleLogError(Log::sceNet, ERROR_NET_RESOLVER_BAD_ID, "Bad Resolver Id: %i", resolverId); + return hleLogError(Log::sceNet, SCE_NET_RESOLVER_ERROR_BAD_ID, "Bad Resolver Id: %i", resolverId); } g_netResolvers.erase(resolverIter); diff --git a/Core/HLE/sceNetResolver.h b/Core/HLE/sceNetResolver.h index 257f330875..1da834b391 100644 --- a/Core/HLE/sceNetResolver.h +++ b/Core/HLE/sceNetResolver.h @@ -19,33 +19,6 @@ #include #include -enum { - // pspnet_resolver - ERROR_NET_RESOLVER_NOT_TERMINATED = 0x80410401, - ERROR_NET_RESOLVER_NO_DNS_SERVER = 0x80410402, - ERROR_NET_RESOLVER_INVALID_PTR = 0x80410403, - ERROR_NET_RESOLVER_INVALID_BUFLEN = 0x80410404, - ERROR_NET_RESOLVER_INVALID_ID = 0x80410405, - ERROR_NET_RESOLVER_ID_MAX = 0x80410406, - ERROR_NET_RESOLVER_NO_MEM = 0x80410407, - ERROR_NET_RESOLVER_BAD_ID = 0x80410408, // ERROR_NET_RESOLVER_ID_NOT_FOUND - ERROR_NET_RESOLVER_CTX_BUSY = 0x80410409, - ERROR_NET_RESOLVER_ALREADY_STOPPED = 0x8041040a, - ERROR_NET_RESOLVER_NOT_SUPPORTED = 0x8041040b, - ERROR_NET_RESOLVER_BUF_NO_SPACE = 0x8041040c, - ERROR_NET_RESOLVER_INVALID_PACKET = 0x8041040d, - ERROR_NET_RESOLVER_STOPPED = 0x8041040e, - ERROR_NET_RESOLVER_SOCKET = 0x8041040f, - ERROR_NET_RESOLVER_TIMEOUT = 0x80410410, - ERROR_NET_RESOLVER_NO_RECORD = 0x80410411, - ERROR_NET_RESOLVER_RES_PACKET_FORMAT = 0x80410412, - ERROR_NET_RESOLVER_RES_SERVER_FAILURE = 0x80410413, - ERROR_NET_RESOLVER_INVALID_HOST = 0x80410414, // ERROR_NET_RESOLVER_NO_HOST - ERROR_NET_RESOLVER_RES_NOT_IMPLEMENTED = 0x80410415, - ERROR_NET_RESOLVER_RES_SERVER_REFUSED = 0x80410416, - ERROR_NET_RESOLVER_INTERNAL = 0x80410417, -}; - void __NetResolverShutdown(); void Register_sceNetResolver();