From: Alistair Leslie-Hughes Subject: [v4 PATCH 4/4] dpnet: Add Sync support in IDirectPlay8Client EnumHost Message-Id: Date: Thu, 17 Nov 2016 07:08:59 +0000 In-Reply-To: <20161117070800.24733-1-leslie_alistair@hotmail.com> References: <20161117070800.24733-1-leslie_alistair@hotmail.com> Signed-off-by: Alistair Leslie-Hughes --- dlls/dpnet/client.c | 103 +++++++++++++++++++++++++++++++++++++++++---- dlls/dpnet/dpnet_private.h | 2 + dlls/dpnet/tests/client.c | 10 +++-- 3 files changed, 102 insertions(+), 13 deletions(-) diff --git a/dlls/dpnet/client.c b/dlls/dpnet/client.c index a8d46b1..94bfa1d 100644 --- a/dlls/dpnet/client.c +++ b/dlls/dpnet/client.c @@ -140,6 +140,8 @@ static ULONG WINAPI IDirectPlay8ClientImpl_Release(IDirectPlay8Client *iface) { closesocket(This->sock); + CloseHandle(This->cancelevent); + heap_free(This->username); heap_free(This->data); heap_free(This); @@ -229,7 +231,7 @@ static int send_packet_enum_query(SOCKET sock, GUID application, struct sockaddr } static void process_enumhost(SOCKET sock, IDirectPlay8Address *device, PFNDPNMESSAGEHANDLER msghandler, GUID application, - DWORD retrycnt, DWORD retrytime, DWORD timeout) + DWORD retrycnt, DWORD retrytime, DWORD timeout, HANDLE cancelevent) { char buffer[1024]; int buflen = sizeof(buffer); @@ -243,6 +245,15 @@ static void process_enumhost(SOCKET sock, IDirectPlay8Address *device, PFNDPNMES while(TRUE) { + if(cancelevent) + { + if(WaitForSingleObject(cancelevent, 500) != WAIT_TIMEOUT) + { + TRACE("Event Signaled.\n"); + break; + } + } + if(retrycnt && (GetTickCount() - starttime) >= retrytime) { TRACE("Sending Request.\n"); @@ -323,8 +334,11 @@ static void process_enumhost(SOCKET sock, IDirectPlay8Address *device, PFNDPNMES IDirectPlay8Address_Release(sender); - /* We have found a server, so exit now. */ - retrycnt = 0; + if(retrycnt != INFINITE) + { + /* We have found a server, so exit now. */ + retrycnt = 0; + } } break; } @@ -347,6 +361,31 @@ static void process_enumhost(SOCKET sock, IDirectPlay8Address *device, PFNDPNMES } } +struct dpthread_data +{ + SOCKET sock; + IDirectPlay8Address *device; + DWORD retrycnt; + DWORD retrytime; + DWORD timeout; + GUID app_guid; + + HANDLE cancelevent; + PFNDPNMESSAGEHANDLER msghandler; +}; + +static DWORD WINAPI enumhost_thread(void *threaddata) +{ + struct dpthread_data *tdata = (struct dpthread_data *)threaddata; + + process_enumhost(tdata->sock, tdata->device, tdata->msghandler, tdata->app_guid, + tdata->retrycnt, tdata->retrytime, tdata->timeout, tdata->cancelevent); + + heap_free(threaddata); + + return 0; +} + static HRESULT WINAPI IDirectPlay8ClientImpl_EnumHosts(IDirectPlay8Client *iface, PDPN_APPLICATION_DESC const pApplicationDesc, IDirectPlay8Address * const pAddrHost, IDirectPlay8Address * const pDeviceInfo, void * const pUserEnumData, @@ -358,7 +397,7 @@ static HRESULT WINAPI IDirectPlay8ClientImpl_EnumHosts(IDirectPlay8Client *iface IDirectPlay8Address *device = NULL; HRESULT hr; - FIXME("(%p):(%p,%p,%p,%p,%u,%u,%u,%u,%p,%p,%x) Semi-stub\n", This, pApplicationDesc, pAddrHost, pDeviceInfo, + TRACE("(%p):(%p,%p,%p,%p,%u,%u,%u,%u,%p,%p,%x)\n", This, pApplicationDesc, pAddrHost, pDeviceInfo, pUserEnumData, dwUserEnumDataSize, dwEnumCount, dwRetryInterval, dwTimeOut, pvUserContext, pAsyncHandle, dwFlags); @@ -396,12 +435,38 @@ static HRESULT WINAPI IDirectPlay8ClientImpl_EnumHosts(IDirectPlay8Client *iface DWORD timeout = dwTimeOut == INFINITE ? This->spcaps.dwDefaultEnumTimeout : dwTimeOut; process_enumhost(This->sock, device, This->msghandler, pApplicationDesc->guidApplication, - retrycnt, retrytime, timeout); + retrycnt, retrytime, timeout, NULL); IDirectPlay8Address_Release(device); } else - FIXME("Async EnumHost currently not supported.\n"); + { + struct dpthread_data *tdata; + + if(This->enumthread) + { + FIXME("Only one EnumHost is currently supported\n"); + return DPNERR_USERCANCEL; + } + + tdata = heap_alloc(sizeof(struct dpthread_data)); + if(!tdata) + return E_OUTOFMEMORY; + + tdata->sock = This->sock; + tdata->retrycnt = !dwEnumCount ? This->spcaps.dwDefaultEnumCount : dwEnumCount; + tdata->retrytime = dwRetryInterval == INFINITE ? This->spcaps.dwDefaultEnumRetryInterval : dwRetryInterval; + tdata->timeout = dwTimeOut == INFINITE ? This->spcaps.dwDefaultEnumTimeout : dwTimeOut; + tdata->msghandler = This->msghandler; + tdata->device = device; + tdata->app_guid = pApplicationDesc->guidApplication; + tdata->cancelevent = This->cancelevent = CreateEventA( NULL, TRUE, FALSE, NULL); + + This->enumthread = CreateThread(NULL, 0, &enumhost_thread, tdata, 0, 0); + } + + if(pAsyncHandle) + *pAsyncHandle = PtrToUlong(This->cancelevent); return (dwFlags & DPNENUMHOSTS_SYNC) ? DPN_OK : DPNSUCCESS_PENDING; } @@ -409,9 +474,19 @@ static HRESULT WINAPI IDirectPlay8ClientImpl_EnumHosts(IDirectPlay8Client *iface static HRESULT WINAPI IDirectPlay8ClientImpl_CancelAsyncOperation(IDirectPlay8Client *iface, const DPNHANDLE hAsyncHandle, const DWORD dwFlags) { - IDirectPlay8ClientImpl *This = impl_from_IDirectPlay8Client(iface); - FIXME("(%p):(%u,%x): Stub\n", This, hAsyncHandle, dwFlags); - return DPN_OK; + IDirectPlay8ClientImpl *This = impl_from_IDirectPlay8Client(iface); + FIXME("(%p):(%u,%x): Stub\n", This, hAsyncHandle, dwFlags); + + if(hAsyncHandle == PtrToUlong(This->cancelevent)) + { + SetEvent(This->cancelevent); + CloseHandle(This->cancelevent); + + CloseHandle(This->enumthread); + This->enumthread = NULL; + } + + return DPN_OK; } static HRESULT WINAPI IDirectPlay8ClientImpl_Connect(IDirectPlay8Client *iface, @@ -522,6 +597,15 @@ static HRESULT WINAPI IDirectPlay8ClientImpl_Close(IDirectPlay8Client *iface, co IDirectPlay8ClientImpl *This = impl_from_IDirectPlay8Client(iface); FIXME("(%p):(%x): Stub\n", This, dwFlags); + if(This->cancelevent) + { + SetEvent(This->cancelevent); + CloseHandle(This->cancelevent); + + CloseHandle(This->enumthread); + This->enumthread = NULL; + } + This->msghandler = NULL; return DPN_OK; @@ -641,6 +725,7 @@ HRESULT DPNET_CreateDirectPlay8Client(IClassFactory *iface, IUnknown *pUnkOuter, client->IDirectPlay8Client_iface.lpVtbl = &DirectPlay8Client_Vtbl; client->ref = 1; client->sock = INVALID_SOCKET; + client->enumthread = NULL; init_dpn_sp_caps(&client->spcaps); diff --git a/dlls/dpnet/dpnet_private.h b/dlls/dpnet/dpnet_private.h index dee1654..eb27cb6 100644 --- a/dlls/dpnet/dpnet_private.h +++ b/dlls/dpnet/dpnet_private.h @@ -66,6 +66,8 @@ struct IDirectPlay8ClientImpl DPN_SP_CAPS spcaps; SOCKET sock; + HANDLE enumthread; + HANDLE cancelevent; }; /* ------------------- */ diff --git a/dlls/dpnet/tests/client.c b/dlls/dpnet/tests/client.c index 5f832f2..2fd5b96 100644 --- a/dlls/dpnet/tests/client.c +++ b/dlls/dpnet/tests/client.c @@ -214,7 +214,7 @@ static void test_enum_hosts(void) hr = IDirectPlay8Client_EnumHosts(client, &appdesc, host, local, data, caps.dwMaxEnumPayloadSize, INFINITE, 0, INFINITE, NULL, &async, 0); ok(hr == DPNSUCCESS_PENDING, "got 0x%08x\n", hr); - todo_wine ok(async, "No Handle returned\n"); + ok(async, "No Handle returned\n"); /* This CancelAsyncOperation doesn't generate a DPN_MSGID_ASYNC_OP_COMPLETE */ hr = IDirectPlay8Client_CancelAsyncOperation(client, async, 0); @@ -226,14 +226,16 @@ static void test_enum_hosts(void) ok(hr == DPNERR_UNINITIALIZED, "IDirectPlay8Client_EnumHosts failed with 0x%08x\n", hr); /* Since we are running asynchronously, EnumHosts returns DPNSUCCESS_PENDING. */ + async = 0; hr = IDirectPlay8Client_EnumHosts(client, &appdesc, host, local, NULL, 0, INFINITE, 0, INFINITE, NULL, &async, 0); ok(hr == DPNSUCCESS_PENDING, "IDirectPlay8Client_EnumHosts failed with 0x%08x\n", hr); - todo_wine ok(async, "No Handle returned\n"); + ok(async, "No Handle returned\n"); + async2 = 0; hr = IDirectPlay8Client_EnumHosts(client, &appdesc, host, local, NULL, 0, INFINITE, 0, INFINITE, NULL, &async2, 0); - ok(hr == DPNSUCCESS_PENDING, "IDirectPlay8Client_EnumHosts failed with 0x%08x\n", hr); + todo_wine ok(hr == DPNSUCCESS_PENDING, "IDirectPlay8Client_EnumHosts failed with 0x%08x\n", hr); todo_wine ok(async2, "No Handle returned\n"); - todo_wine ok(async2 != async, "Same handle returned.\n"); + ok(async2 != async, "Same handle returned.\n"); Sleep(1000); -- 1.9.1