[v4 PATCH 4/4] dpnet: Add Sync support in IDirectPlay8Client EnumHost
Alistair Leslie-Hughes
leslie_alistair at hotmail.com
Thu Nov 17 01:08:59 CST 2016
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
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
More information about the wine-patches
mailing list