[PATCH resend 1/4] iphlpapi: Implement asynchronous events for IcmpSendEcho2(Ex).
Gabriel Ivăncescu
gabrielopcode at gmail.com
Tue Jun 15 07:50:24 CDT 2021
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
dlls/iphlpapi/icmp.c | 108 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 100 insertions(+), 8 deletions(-)
diff --git a/dlls/iphlpapi/icmp.c b/dlls/iphlpapi/icmp.c
index 8ef0321..ceeab69 100644
--- a/dlls/iphlpapi/icmp.c
+++ b/dlls/iphlpapi/icmp.c
@@ -106,9 +106,42 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
typedef struct {
int sid;
+ LONG lock_count;
+ HANDLE lock_event;
IP_OPTION_INFORMATION default_opts;
} icmp_t;
+static void icmp_lock(icmp_t *icp)
+{
+ InterlockedIncrement(&icp->lock_count);
+}
+
+static void icmp_unlock(icmp_t *icp)
+{
+ if (InterlockedDecrement(&icp->lock_count) == 0x80000000)
+ {
+ if (icp->lock_event)
+ SetEvent(icp->lock_event);
+ }
+}
+
+static void icmp_wait_for_released_locks(icmp_t *icp)
+{
+ HANDLE event = CreateEventW(NULL, TRUE, FALSE, NULL);
+
+ icp->lock_event = event;
+ if (InterlockedExchangeAdd(&icp->lock_count, 0x80000000) != 0)
+ {
+ do
+ {
+ if (event) WaitForSingleObjectEx(event, INFINITE, TRUE);
+ else SleepEx(1, TRUE);
+ }
+ while (icp->lock_count != 0x80000000);
+ }
+ if (event) CloseHandle(event);
+}
+
#define IP_OPTS_UNKNOWN 0
#define IP_OPTS_DEFAULT 1
#define IP_OPTS_CUSTOM 2
@@ -347,6 +380,30 @@ done:
return res;
}
+struct icmp_get_reply_async_ctx
+{
+ icmp_t *icp;
+ HANDLE event;
+ unsigned char *buffer;
+ void *reply_buf;
+ DWORD reply_size;
+ DWORD send_time;
+ DWORD timeout;
+};
+
+static DWORD WINAPI icmp_get_reply_async_func(VOID *parameter)
+{
+ struct icmp_get_reply_async_ctx *ctx = parameter;
+
+ icmp_get_reply(ctx->icp->sid, ctx->buffer, ctx->send_time, ctx->reply_buf, ctx->reply_size, ctx->timeout);
+
+ SetEvent(ctx->event);
+
+ icmp_unlock(ctx->icp);
+ HeapFree(GetProcessHeap(), 0, ctx);
+ return 0;
+}
+
/*
@@ -381,6 +438,7 @@ HANDLE WINAPI Icmp6CreateFile(VOID)
}
icp->sid=sid;
icp->default_opts.OptionsSize=IP_OPTS_UNKNOWN;
+ icp->lock_count=0;
return (HANDLE)icp;
}
@@ -439,6 +497,7 @@ HANDLE WINAPI IcmpCreateFile(VOID)
}
icp->sid=sid;
icp->default_opts.OptionsSize=IP_OPTS_UNKNOWN;
+ icp->lock_count=0;
return (HANDLE)icp;
}
@@ -455,6 +514,9 @@ BOOL WINAPI IcmpCloseHandle(HANDLE IcmpHandle)
return FALSE;
}
+ /* Windows waits until all outstanding async requests are complete or timed out */
+ icmp_wait_for_released_locks(icp);
+
close( icp->sid );
HeapFree(GetProcessHeap (), 0, icp);
return TRUE;
@@ -526,6 +588,7 @@ DWORD WINAPI IcmpSendEcho2Ex(
unsigned char *buffer;
int reqsize, repsize;
DWORD send_time;
+ DWORD res = 0;
TRACE("(%p, %p, %p, %p, %08x, %08x, %p, %d, %p, %p, %d, %d)\n", IcmpHandle,
Event, ApcRoutine, ApcContext, SourceAddress, DestinationAddress, RequestData,
@@ -553,11 +616,6 @@ DWORD WINAPI IcmpSendEcho2Ex(
return 0;
}
- if (Event)
- {
- FIXME("unsupported for events\n");
- return 0;
- }
if (ApcRoutine)
{
FIXME("unsupported for APCs\n");
@@ -569,6 +627,8 @@ DWORD WINAPI IcmpSendEcho2Ex(
return 0;
}
+ icmp_lock(icp);
+
/* Prepare the request */
id=getpid() & 0xFFFF;
seq=InterlockedIncrement(&icmp_sequence) & 0xFFFF;
@@ -580,7 +640,7 @@ DWORD WINAPI IcmpSendEcho2Ex(
buffer = HeapAlloc(GetProcessHeap(), 0, max( repsize, reqsize ));
if (buffer == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
- return 0;
+ goto done;
}
icmp_header=(struct icmp*)buffer;
@@ -661,10 +721,42 @@ DWORD WINAPI IcmpSendEcho2Ex(
}
}
HeapFree(GetProcessHeap(), 0, buffer);
- return 0;
+ goto done;
}
- return icmp_get_reply(icp->sid, buffer, send_time, ReplyBuffer, ReplySize, Timeout);
+ if (Event)
+ {
+ struct icmp_get_reply_async_ctx *ctx = HeapAlloc(GetProcessHeap(), 0, sizeof(*ctx));
+
+ if (ctx)
+ {
+ ctx->icp = icp;
+ ctx->event = Event;
+ ctx->buffer = buffer;
+ ctx->reply_buf = ReplyBuffer;
+ ctx->reply_size = ReplySize;
+ ctx->send_time = send_time;
+ ctx->timeout = Timeout;
+ if (QueueUserWorkItem(icmp_get_reply_async_func, ctx, WT_EXECUTEDEFAULT | WT_EXECUTELONGFUNCTION))
+ {
+ SetLastError(ERROR_IO_PENDING);
+ return 0;
+ }
+
+ HeapFree(GetProcessHeap(), 0, ctx);
+ }
+ else
+ SetLastError(ERROR_OUTOFMEMORY);
+
+ HeapFree(GetProcessHeap(), 0, buffer);
+ goto done;
+ }
+
+ res = icmp_get_reply(icp->sid, buffer, send_time, ReplyBuffer, ReplySize, Timeout);
+
+done:
+ icmp_unlock(icp);
+ return res;
}
/*
--
2.31.1
More information about the wine-devel
mailing list