netcode-revival: implement XNet session/address layer (Phase 0)
Some checks are pending
Lint & Format Check / Format Check (push) Waiting to run
Some checks are pending
Lint & Format Check / Format Check (push) Waiting to run
Make the game's RakNet-based netcode reach the session flow instead of hard-failing on stubbed/looping XNet APIs: - XNetGetTitleXnAddr: stable per-machine virtual identity (10.80.0.x + unique 6-byte abEnet from the profile XUID) - RakNet needs non-zero, per-machine MAC bytes for its GUID (zero broke RakPeer::Startup; identical MACs collide GUIDs). - XNetXnAddrToInAddr / XNetInAddrToXnAddr / XNetServerToInAddr / XNetXnAddrToMachineId / XNetInAddrToString: resolve our virtual addresses instead of returning failure / '666.666.666.666'. - XNetQosListen: accept session advertisement (was X_ERROR_FUNCTION_FAILED). - XNetQosLookup: return success + empty XNQOS + signal completion (Phase 1 wires the relay registry so it returns real sessions). - XNetCreateKey/RegisterKey/UnregisterKey: generate/accept session keys. - XNetConnect / XNetGetConnectStatus: report established. - getsockopt: real basic reads (SO_* / TCP_NODELAY) off the native socket. - XNetSetSystemLinkPort: accept. Phase 1 (relay transport + session registry) builds on this.
This commit is contained in:
parent
395e1ce67d
commit
767bd6e4bc
1 changed files with 222 additions and 35 deletions
|
|
@ -125,6 +125,57 @@ struct XWSAOVERLAPPED {
|
||||||
rex::be<uint32_t> event_handle;
|
rex::be<uint32_t> event_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ---- netcode-revival: virtual XNet identity ---------------------------------
|
||||||
|
// The Xbox title address (XNADDR) is what RakNet folds into its peer GUID and
|
||||||
|
// what the game resolves into a socket address via XNetXnAddrToInAddr. We give
|
||||||
|
// this machine a stable, unique identity: a reserved virtual IP (10.80.0.x,
|
||||||
|
// "LAN" class) plus a unique 6-byte abEnet. RakPeer::Startup requires
|
||||||
|
// non-zero abEnet and different machines need distinct values (a zero MAC
|
||||||
|
// breaks startup; identical MACs collide GUIDs). Derived from the signed-in
|
||||||
|
// profile XUID so it is stable across runs on one box.
|
||||||
|
struct XnetIdentity {
|
||||||
|
uint8_t machine_id = 1; // 1..254
|
||||||
|
uint8_t ab_enet[6] = {};
|
||||||
|
uint32_t virtual_ip = 0; // host order
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t XnetSeed() {
|
||||||
|
const auto& profile = REX_KERNEL_STATE()->user_profile();
|
||||||
|
uint64_t seed = profile->xuid();
|
||||||
|
if (seed == 0) {
|
||||||
|
// Fallback when no profile is signed in: a stable-enough per-process
|
||||||
|
// seed (later refinements can persist one).
|
||||||
|
seed = 0x52454B4E45544CULL;
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XnetIdentity& XnetLocalIdentity() {
|
||||||
|
static const XnetIdentity s_identity = [] {
|
||||||
|
XnetIdentity id;
|
||||||
|
uint64_t seed = XnetSeed();
|
||||||
|
id.machine_id = uint8_t((seed ^ (seed >> 32)) & 0xFEu) + 1; // 1..254
|
||||||
|
id.ab_enet[0] = id.machine_id;
|
||||||
|
for (int i = 1; i < 6; ++i) {
|
||||||
|
seed = seed * 6364136223846793005ULL + 1442695040888963407ULL;
|
||||||
|
id.ab_enet[i] = uint8_t(seed >> 24);
|
||||||
|
}
|
||||||
|
id.virtual_ip = (10u << 24) | (80u << 16) | (0u << 8) | id.machine_id;
|
||||||
|
return id;
|
||||||
|
}();
|
||||||
|
return s_identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple xorshift64* PRNG for session keys (XNetCreateKey is required to
|
||||||
|
// produce a 16-byte XNKEY; content only needs to be unique per session).
|
||||||
|
uint64_t XnetNextRand() {
|
||||||
|
static uint64_t s = XnetSeed() | 1ULL;
|
||||||
|
s ^= s >> 12;
|
||||||
|
s ^= s << 25;
|
||||||
|
s ^= s >> 27;
|
||||||
|
return s * 2685821657736338717ULL;
|
||||||
|
}
|
||||||
|
|
||||||
void LoadSockaddr(const uint8_t* ptr, sockaddr* out_addr) {
|
void LoadSockaddr(const uint8_t* ptr, sockaddr* out_addr) {
|
||||||
out_addr->sa_family = memory::load_and_swap<uint16_t>(ptr + 0);
|
out_addr->sa_family = memory::load_and_swap<uint16_t>(ptr + 0);
|
||||||
switch (out_addr->sa_family) {
|
switch (out_addr->sa_family) {
|
||||||
|
|
@ -433,26 +484,15 @@ struct XnAddrStatus {
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 NetDll_XNetGetTitleXnAddr_entry(u32 caller, ppc_ptr_t<XNADDR> addr_ptr) {
|
u32 NetDll_XNetGetTitleXnAddr_entry(u32 caller, ppc_ptr_t<XNADDR> addr_ptr) {
|
||||||
// Just return a loopback address atm.
|
// netcode-revival: return this machine's stable virtual identity (10.80.0.x
|
||||||
addr_ptr->ina.s_addr = htonl(INADDR_LOOPBACK);
|
// + a unique abEnet) so RakNet gets a non-zero, per-machine GUID seed and
|
||||||
|
// the game's address resolution has a consistent LAN-class address.
|
||||||
|
const XnetIdentity& id = XnetLocalIdentity();
|
||||||
|
addr_ptr->ina.s_addr = htonl(id.virtual_ip);
|
||||||
addr_ptr->inaOnline.s_addr = 0;
|
addr_ptr->inaOnline.s_addr = 0;
|
||||||
addr_ptr->wPortOnline = 0;
|
addr_ptr->wPortOnline = 0;
|
||||||
|
std::memcpy(addr_ptr->abEnet, id.ab_enet, 6);
|
||||||
// TODO(gibbed): A proper mac address.
|
|
||||||
// RakNet's 360 version appears to depend on abEnet to create "random" 64-bit
|
|
||||||
// numbers. A zero value will cause RakPeer::Startup to fail. This causes
|
|
||||||
// 58411436 to crash on startup.
|
|
||||||
// The 360-specific code is scrubbed from the RakNet repo, but there's still
|
|
||||||
// traces of what it's doing which match the game code.
|
|
||||||
// https://github.com/facebookarchive/RakNet/blob/master/Source/RakPeer.cpp#L382
|
|
||||||
// https://github.com/facebookarchive/RakNet/blob/master/Source/RakPeer.cpp#L4527
|
|
||||||
// https://github.com/facebookarchive/RakNet/blob/master/Source/RakPeer.cpp#L4467
|
|
||||||
// "Mac address is a poor solution because you can't have multiple connections
|
|
||||||
// from the same system"
|
|
||||||
std::memset(addr_ptr->abEnet, 0xCC, 6);
|
|
||||||
|
|
||||||
std::memset(addr_ptr->abOnline, 0, 20);
|
std::memset(addr_ptr->abOnline, 0, 20);
|
||||||
|
|
||||||
return XnAddrStatus::XNET_GET_XNADDR_STATIC;
|
return XnAddrStatus::XNET_GET_XNADDR_STATIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -464,33 +504,57 @@ u32 NetDll_XNetGetDebugXnAddr_entry(u32 caller, ppc_ptr_t<XNADDR> addr_ptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 NetDll_XNetXnAddrToMachineId_entry(u32 caller, ppc_ptr_t<XNADDR> addr_ptr, mapped_u32 id_ptr) {
|
u32 NetDll_XNetXnAddrToMachineId_entry(u32 caller, ppc_ptr_t<XNADDR> addr_ptr, mapped_u32 id_ptr) {
|
||||||
// Tell the caller we're not signed in to live (non-zero ret)
|
// netcode-revival: report this machine's stable machine id instead of "not
|
||||||
return 1;
|
// signed in to live", so identity-dependent flows proceed.
|
||||||
|
if (id_ptr) {
|
||||||
|
*id_ptr = XnetLocalIdentity().machine_id;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDll_XNetInAddrToString_entry(u32 caller, u32 in_addr, mapped_string string_out,
|
void NetDll_XNetInAddrToString_entry(u32 caller, u32 in_addr, mapped_string string_out,
|
||||||
u32 string_size) {
|
u32 string_size) {
|
||||||
rex::string::rex_strcpy(string_out, string_size, "666.666.666.666");
|
char buf[INET_ADDRSTRLEN] = {};
|
||||||
|
in_addr_t a = ntohl(in_addr);
|
||||||
|
std::snprintf(buf, sizeof(buf), "%u.%u.%u.%u", (a >> 24) & 0xFF, (a >> 16) & 0xFF,
|
||||||
|
(a >> 8) & 0xFF, a & 0xFF);
|
||||||
|
rex::string::rex_strcpy(string_out, string_size, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This converts a XNet address to an IN_ADDR. The IN_ADDR is used for
|
// This converts a XNet address to an IN_ADDR. The IN_ADDR is used for
|
||||||
// subsequent socket calls (like a handle to a XNet address)
|
// subsequent socket calls (like a handle to a XNet address).
|
||||||
|
// netcode-revival: our XNADDRs carry the virtual IP in ina (network order);
|
||||||
|
// resolve it into the requested in_addr.
|
||||||
u32 NetDll_XNetXnAddrToInAddr_entry(u32 caller, ppc_ptr_t<XNADDR> xn_addr, mapped_void xid,
|
u32 NetDll_XNetXnAddrToInAddr_entry(u32 caller, ppc_ptr_t<XNADDR> xn_addr, mapped_void xid,
|
||||||
mapped_void in_addr) {
|
mapped_void in_addr) {
|
||||||
return 1;
|
if (!xn_addr || !in_addr) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
uint32_t ip = xn_addr->ina.s_addr;
|
||||||
|
std::memcpy(in_addr, &ip, sizeof(ip));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the reverse of the above.
|
// Does the reverse of the above.
|
||||||
// FIXME: Arguments may not be correct.
|
// netcode-revival: rebuild an XNADDR from an in_addr (virtual IP).
|
||||||
u32 NetDll_XNetInAddrToXnAddr_entry(u32 caller, mapped_void in_addr, ppc_ptr_t<XNADDR> xn_addr,
|
u32 NetDll_XNetInAddrToXnAddr_entry(u32 caller, mapped_void in_addr, ppc_ptr_t<XNADDR> xn_addr,
|
||||||
mapped_void xid) {
|
mapped_void xid) {
|
||||||
return 1;
|
if (!in_addr || !xn_addr) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
std::memcpy(&xn_addr->ina.s_addr, in_addr, sizeof(uint32_t));
|
||||||
|
xn_addr->inaOnline.s_addr = 0;
|
||||||
|
xn_addr->wPortOnline = 0;
|
||||||
|
std::memset(xn_addr->abEnet, 0, 6);
|
||||||
|
std::memset(xn_addr->abOnline, 0, 20);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.google.com/patents/WO2008112448A1?cl=en
|
// https://www.google.com/patents/WO2008112448A1?cl=en
|
||||||
// Reserves a port for use by system link
|
// Reserves a port for use by system link. netcode-revival: accept any port.
|
||||||
u32 NetDll_XNetSetSystemLinkPort_entry(u32 caller, u32 port) {
|
u32 NetDll_XNetSetSystemLinkPort_entry(u32 caller, u32 port) {
|
||||||
return 1;
|
(void)port;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/ILOVEPIE/Cxbx-Reloaded/blob/master/src/CxbxKrnl/EmuXOnline.h#L39
|
// https://github.com/ILOVEPIE/Cxbx-Reloaded/blob/master/src/CxbxKrnl/EmuXOnline.h#L39
|
||||||
|
|
@ -556,7 +620,130 @@ u32 NetDll_XNetQosRelease_entry(u32 caller, ppc_ptr_t<XNQOS> qos) {
|
||||||
|
|
||||||
u32 NetDll_XNetQosListen_entry(u32 caller, mapped_void id, mapped_void data, u32 data_size, u32 r7,
|
u32 NetDll_XNetQosListen_entry(u32 caller, mapped_void id, mapped_void data, u32 data_size, u32 r7,
|
||||||
u32 flags) {
|
u32 flags) {
|
||||||
return X_ERROR_FUNCTION_FAILED;
|
// netcode-revival Phase 0: accept session advertisement so the host flow
|
||||||
|
// proceeds. No registry yet (the relay-backed session registry + QoS
|
||||||
|
// discovery land in Phase 1); QosLookup returns an empty result set for
|
||||||
|
// now so the game's search completes cleanly.
|
||||||
|
(void)id;
|
||||||
|
(void)data;
|
||||||
|
(void)data_size;
|
||||||
|
(void)r7;
|
||||||
|
(void)flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// netcode-revival: session search. Phase 0 reports zero discovered sessions
|
||||||
|
// (the relay registry lands in Phase 1) but returns success and signals the
|
||||||
|
// completion event so the game's search finishes instead of hanging.
|
||||||
|
u32 NetDll_XNetQosLookup_entry(u32 caller, u32 cxna, mapped_void apxna, mapped_void apxnk,
|
||||||
|
u32 cxnk, mapped_void apxnaResults, mapped_u32 apxnqosResults,
|
||||||
|
mapped_void axnqosInfoResults, u32 dwTimeoutMs, u32 hEvent,
|
||||||
|
u32 dwFlags) {
|
||||||
|
(void)cxna;
|
||||||
|
(void)apxna;
|
||||||
|
(void)apxnk;
|
||||||
|
(void)cxnk;
|
||||||
|
(void)apxnaResults;
|
||||||
|
(void)axnqosInfoResults;
|
||||||
|
(void)dwTimeoutMs;
|
||||||
|
(void)dwFlags;
|
||||||
|
if (apxnqosResults) {
|
||||||
|
auto qos_guest = REX_KERNEL_MEMORY()->SystemHeapAlloc(sizeof(XNQOS));
|
||||||
|
auto qos = REX_KERNEL_MEMORY()->TranslateVirtual<XNQOS*>(qos_guest);
|
||||||
|
qos->count = qos->count_pending = 0;
|
||||||
|
*apxnqosResults = qos_guest;
|
||||||
|
}
|
||||||
|
if (hEvent) {
|
||||||
|
auto ev = REX_KERNEL_OBJECTS()->LookupObject<XEvent>(hEvent);
|
||||||
|
if (ev) {
|
||||||
|
ev->Set(0, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// netcode-revival: generate a 16-byte session key (XNKEY).
|
||||||
|
u32 NetDll_XNetCreateKey_entry(u32 caller, mapped_void key) {
|
||||||
|
if (!key) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
uint8_t* out = static_cast<uint8_t*>(key);
|
||||||
|
uint64_t r = XnetNextRand();
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
if ((i & 7) == 0) {
|
||||||
|
r = XnetNextRand();
|
||||||
|
}
|
||||||
|
out[i] = uint8_t(r >> ((i & 7) * 8));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// netcode-revival: accept + (Phase 1) register the session key.
|
||||||
|
u32 NetDll_XNetRegisterKey_entry(u32 caller, mapped_void key) {
|
||||||
|
(void)key;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 NetDll_XNetUnregisterKey_entry(u32 caller, mapped_void key) {
|
||||||
|
(void)key;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// netcode-revival: connecting to a peer is reported as established.
|
||||||
|
u32 NetDll_XNetConnect_entry(u32 caller, ppc_ptr_t<XNADDR> xn_addr) {
|
||||||
|
(void)xn_addr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/xna/xnetgetconnectstatus
|
||||||
|
// INT XNetGetConnectStatus(const XNADDR* pxna, INT* pxncs)
|
||||||
|
u32 NetDll_XNetGetConnectStatus_entry(u32 caller, ppc_ptr_t<XNADDR> xn_addr, mapped_void status_ptr) {
|
||||||
|
(void)xn_addr;
|
||||||
|
if (status_ptr) {
|
||||||
|
const uint32_t connected = 2; // XNET_CONNECT_STATUS_CONNECTED
|
||||||
|
std::memcpy(status_ptr, &connected, sizeof(connected));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INT XNetServerToInAddr(const XNADDR* pxn, IN_ADDR* pina, DWORD dwFlags)
|
||||||
|
// netcode-revival: our server addresses also carry the virtual IP in ina.
|
||||||
|
u32 NetDll_XNetServerToInAddr_entry(u32 caller, ppc_ptr_t<XNADDR> pxn, mapped_void pina,
|
||||||
|
u32 dwFlags) {
|
||||||
|
(void)dwFlags;
|
||||||
|
if (!pxn || !pina) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
uint32_t ip = pxn->ina.s_addr;
|
||||||
|
std::memcpy(pina, &ip, sizeof(ip));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic getsockopt reads the game relies on (SO_ERROR, SO_REUSEADDR,
|
||||||
|
// SO_BROADCAST, SO_SNDBUF/RCVBUF, TCP_NODELAY, ...) served from the real
|
||||||
|
// native socket.
|
||||||
|
u32 NetDll_getsockopt_entry(u32 caller, u32 socket_handle, u32 level, u32 optname,
|
||||||
|
mapped_void optval_ptr, mapped_u32 optlen_ptr) {
|
||||||
|
auto socket = REX_KERNEL_OBJECTS()->LookupObject<XSocket>(socket_handle);
|
||||||
|
if (!socket) {
|
||||||
|
XThread::SetLastError(0x2736); // WSAENOTSOCK
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!optval_ptr || !optlen_ptr) {
|
||||||
|
XThread::SetLastError(0x2736);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int len = int(*optlen_ptr);
|
||||||
|
// Windows takes char*, POSIX void*; a char* host pointer satisfies both.
|
||||||
|
char* optval_host = reinterpret_cast<char*>(static_cast<void*>(optval_ptr));
|
||||||
|
int ret = getsockopt(int(socket->native_handle()), int(level), int(optname), optval_host,
|
||||||
|
reinterpret_cast<socklen_t*>(&len));
|
||||||
|
if (ret != 0) {
|
||||||
|
XThread::SetLastError(0x2743); // WSAENOPROTOOPT
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*optlen_ptr = uint32_t(len);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 NetDll_inet_addr_entry(mapped_string addr_ptr) {
|
u32 NetDll_inet_addr_entry(mapped_string addr_ptr) {
|
||||||
|
|
@ -1027,25 +1214,25 @@ REX_EXPORT_STUB(__imp__NetDll_XHttpSetStatusCallback);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XHttpShutdown);
|
REX_EXPORT_STUB(__imp__NetDll_XHttpShutdown);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XHttpStartup);
|
REX_EXPORT_STUB(__imp__NetDll_XHttpStartup);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XHttpWriteData);
|
REX_EXPORT_STUB(__imp__NetDll_XHttpWriteData);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetConnect);
|
REX_EXPORT(__imp__NetDll_XNetConnect, rex::kernel::xam::NetDll_XNetConnect_entry)
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetCreateKey);
|
REX_EXPORT(__imp__NetDll_XNetCreateKey, rex::kernel::xam::NetDll_XNetCreateKey_entry)
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetDnsReverseLookup);
|
REX_EXPORT_STUB(__imp__NetDll_XNetDnsReverseLookup);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetDnsReverseRelease);
|
REX_EXPORT_STUB(__imp__NetDll_XNetDnsReverseRelease);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetGetBroadcastVersionStatus);
|
REX_EXPORT_STUB(__imp__NetDll_XNetGetBroadcastVersionStatus);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetGetConnectStatus);
|
REX_EXPORT(__imp__NetDll_XNetGetConnectStatus, rex::kernel::xam::NetDll_XNetGetConnectStatus_entry)
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetGetSystemLinkPort);
|
REX_EXPORT_STUB(__imp__NetDll_XNetGetSystemLinkPort);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetGetXnAddrPlatform);
|
REX_EXPORT_STUB(__imp__NetDll_XNetGetXnAddrPlatform);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetInAddrToServer);
|
REX_EXPORT_STUB(__imp__NetDll_XNetInAddrToServer);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetQosGetListenStats);
|
REX_EXPORT_STUB(__imp__NetDll_XNetQosGetListenStats);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetQosLookup);
|
REX_EXPORT(__imp__NetDll_XNetQosLookup, rex::kernel::xam::NetDll_XNetQosLookup_entry)
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetRegisterKey);
|
REX_EXPORT(__imp__NetDll_XNetRegisterKey, rex::kernel::xam::NetDll_XNetRegisterKey_entry)
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetReplaceKey);
|
REX_EXPORT_STUB(__imp__NetDll_XNetReplaceKey);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetServerToInAddr);
|
REX_EXPORT(__imp__NetDll_XNetServerToInAddr, rex::kernel::xam::NetDll_XNetServerToInAddr_entry)
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetSetOpt);
|
REX_EXPORT_STUB(__imp__NetDll_XNetSetOpt);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetStartupEx);
|
REX_EXPORT_STUB(__imp__NetDll_XNetStartupEx);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetTsAddrToInAddr);
|
REX_EXPORT_STUB(__imp__NetDll_XNetTsAddrToInAddr);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetUnregisterInAddr);
|
REX_EXPORT_STUB(__imp__NetDll_XNetUnregisterInAddr);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XNetUnregisterKey);
|
REX_EXPORT(__imp__NetDll_XNetUnregisterKey, rex::kernel::xam::NetDll_XNetUnregisterKey_entry)
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XmlDownloadContinue);
|
REX_EXPORT_STUB(__imp__NetDll_XmlDownloadContinue);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XmlDownloadGetParseTime);
|
REX_EXPORT_STUB(__imp__NetDll_XmlDownloadGetParseTime);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XmlDownloadGetReceivedDataSize);
|
REX_EXPORT_STUB(__imp__NetDll_XmlDownloadGetReceivedDataSize);
|
||||||
|
|
@ -1096,4 +1283,4 @@ REX_EXPORT_STUB(__imp__NetDll_XnpUnregisterKeyForCallerType);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_XnpUpdateConfigParams);
|
REX_EXPORT_STUB(__imp__NetDll_XnpUpdateConfigParams);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_getpeername);
|
REX_EXPORT_STUB(__imp__NetDll_getpeername);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_getsockname);
|
REX_EXPORT_STUB(__imp__NetDll_getsockname);
|
||||||
REX_EXPORT_STUB(__imp__NetDll_getsockopt);
|
REX_EXPORT(__imp__NetDll_getsockopt, rex::kernel::xam::NetDll_getsockopt_entry)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue