diff --git a/dlls/dpnet/client.c b/dlls/dpnet/client.c index bf2b8d2c465..f6f9e79136e 100644 --- a/dlls/dpnet/client.c +++ b/dlls/dpnet/client.c @@ -86,8 +86,11 @@ static ULONG WINAPI IDirectPlay8ClientImpl_Release(IDirectPlay8Client *iface) TRACE("(%p) ref=%u\n", This, ref); - if (!ref) { - HeapFree(GetProcessHeap(), 0, This); + if (!ref) + { + heap_free(This->username); + heap_free(This->data); + heap_free(This); } return ref; } @@ -182,9 +185,50 @@ static HRESULT WINAPI IDirectPlay8ClientImpl_SetClientInfo(IDirectPlay8Client *i const DPN_PLAYER_INFO * const pdpnPlayerInfo, void * const pvAsyncContext, DPNHANDLE * const phAsyncHandle, const DWORD dwFlags) { - IDirectPlay8ClientImpl *This = impl_from_IDirectPlay8Client(iface); - FIXME("(%p):(%p,%p,%x): Stub\n", This, pvAsyncContext, phAsyncHandle, dwFlags); - return DPN_OK; + IDirectPlay8ClientImpl *This = impl_from_IDirectPlay8Client(iface); + FIXME("(%p):(%p,%p,%x): Semi-stub.\n", This, pvAsyncContext, phAsyncHandle, dwFlags); + + if(!pdpnPlayerInfo) + return E_POINTER; + + if(phAsyncHandle) + FIXME("Async handle currently not supported.\n"); + + if (pdpnPlayerInfo->dwInfoFlags & DPNINFO_NAME) + { + heap_free(This->username); + This->username = NULL; + + if(pdpnPlayerInfo->pwszName) + { + This->username = heap_strdupW(pdpnPlayerInfo->pwszName); + if (!This->username) + return E_OUTOFMEMORY; + } + } + + if (pdpnPlayerInfo->dwInfoFlags & DPNINFO_DATA) + { + heap_free(This->data); + This->data = NULL; + This->datasize = 0; + + if(!pdpnPlayerInfo->pvData && pdpnPlayerInfo->dwDataSize) + return E_POINTER; + + if(pdpnPlayerInfo->dwDataSize && pdpnPlayerInfo->pvData) + { + This->data = heap_alloc(pdpnPlayerInfo->dwDataSize); + if (!This->data) + return E_OUTOFMEMORY; + + This->datasize = pdpnPlayerInfo->dwDataSize; + + memcpy(This->data, pdpnPlayerInfo->pvData, pdpnPlayerInfo->dwDataSize); + } + } + + return DPN_OK; } static HRESULT WINAPI IDirectPlay8ClientImpl_GetServerInfo(IDirectPlay8Client *iface, diff --git a/dlls/dpnet/dpnet_private.h b/dlls/dpnet/dpnet_private.h index 05608a64a68..dc6a4f13cba 100644 --- a/dlls/dpnet/dpnet_private.h +++ b/dlls/dpnet/dpnet_private.h @@ -56,6 +56,9 @@ struct IDirectPlay8ClientImpl PFNDPNMESSAGEHANDLER msghandler; DWORD flags; void *usercontext; + WCHAR *username; + void *data; + DWORD datasize; DPN_SP_CAPS spcaps; }; diff --git a/dlls/dpnet/tests/client.c b/dlls/dpnet/tests/client.c index 253526adec3..f7d6c53b511 100644 --- a/dlls/dpnet/tests/client.c +++ b/dlls/dpnet/tests/client.c @@ -230,6 +230,71 @@ static void test_lobbyclient(void) } } +static void test_player_info(void) +{ + HRESULT hr; + DPN_PLAYER_INFO info; + WCHAR name[] = {'w','i','n','e',0}; + WCHAR name2[] = {'w','i','n','e','2',0}; + WCHAR data[] = {'X','X','X','X',0}; + + ZeroMemory( &info, sizeof(DPN_PLAYER_INFO) ); + info.dwSize = sizeof(DPN_PLAYER_INFO); + info.dwInfoFlags = DPNINFO_NAME; + + hr = IDirectPlay8Client_SetClientInfo(client, NULL, NULL, NULL, DPNSETCLIENTINFO_SYNC); + ok(hr == E_POINTER, "got %x\n", hr); + + info.pwszName = NULL; + hr = IDirectPlay8Client_SetClientInfo(client, &info, NULL, NULL, DPNSETCLIENTINFO_SYNC); + ok(hr == S_OK, "got %x\n", hr); + + info.pwszName = name; + hr = IDirectPlay8Client_SetClientInfo(client, &info, NULL, NULL, DPNSETCLIENTINFO_SYNC); + ok(hr == S_OK, "got %x\n", hr); + + info.dwInfoFlags = DPNINFO_NAME; + info.pwszName = name2; + hr = IDirectPlay8Client_SetClientInfo(client, &info, NULL, NULL, DPNSETCLIENTINFO_SYNC); + ok(hr == S_OK, "got %x\n", hr); + + info.dwInfoFlags = DPNINFO_DATA; + info.pwszName = NULL; + info.pvData = NULL; + info.dwDataSize = sizeof(data); + hr = IDirectPlay8Client_SetClientInfo(client, &info, NULL, NULL, DPNSETCLIENTINFO_SYNC); + ok(hr == E_POINTER, "got %x\n", hr); + + info.dwInfoFlags = DPNINFO_DATA; + info.pwszName = NULL; + info.pvData = data; + info.dwDataSize = 0; + hr = IDirectPlay8Client_SetClientInfo(client, &info, NULL, NULL, DPNSETCLIENTINFO_SYNC); + ok(hr == S_OK, "got %x\n", hr); + + info.dwInfoFlags = DPNINFO_DATA; + info.pwszName = NULL; + info.pvData = data; + info.dwDataSize = sizeof(data); + hr = IDirectPlay8Client_SetClientInfo(client, &info, NULL, NULL, DPNSETCLIENTINFO_SYNC); + ok(hr == S_OK, "got %x\n", hr); + + info.dwInfoFlags = DPNINFO_DATA | DPNINFO_NAME; + info.pwszName = name; + info.pvData = data; + info.dwDataSize = sizeof(data); + hr = IDirectPlay8Client_SetClientInfo(client, &info, NULL, NULL, DPNSETCLIENTINFO_SYNC); + ok(hr == S_OK, "got %x\n", hr); + + /* Leave ClientInfo with only the name set. */ + info.dwInfoFlags = DPNINFO_DATA | DPNINFO_NAME; + info.pwszName = name; + info.pvData = NULL; + info.dwDataSize = 0; + hr = IDirectPlay8Client_SetClientInfo(client, &info, NULL, NULL, DPNSETCLIENTINFO_SYNC); + ok(hr == S_OK, "got %x\n", hr); +} + static void test_cleanup_dp(void) { HRESULT hr; @@ -258,6 +323,7 @@ START_TEST(client) test_enum_service_providers(); test_enum_hosts(); test_get_sp_caps(); + test_player_info(); test_lobbyclient(); test_cleanup_dp(); }