<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body><p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">Thank you for your answer!</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;"><br /></p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">I spent a lot of time testing a whole lot of different combinations and the results still confused me...</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;"><br /></p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;"><span style="font-family:Hack;">> There's also a part of me that would like to know what can possibly be </span></p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> the point of this API; it's hard to even think of what "reasonable" </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> behaviour is otherwise. Do you happen to know?</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> My best guess is that it's meant to explicitly interrupt poll requests </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> somehow (what, I/O cancellation wasn't good enough for them?), in which </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> case it'd be good to explicitly confirm or refute that the "exclusive" </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> poll really does act like a normal poll, and doesn't e.g. return </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> immediately.</p>
<br /><p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">I discovered this behavior while investigating an app that seemed to rely on them to interrupt some polls, and so far it seems to be its sole purpose.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">There is only one reason I can imagine a use for this instead of CancelIo(): As the NtDeviceIoControlFile()'s file handle is independent of the socket in params, it provides a way to interrupt another poll that waits on the same socket without the need to know the file handle that was originally given to it.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">�</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">Regardless its behaviour is kind of crazy.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">I tried to restrict to a subset of the tests to avoid polluting test_poll() too much, but indeed it requires an entire function to test it properly.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;"><br /></p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> I think these tests could be more extensive. For example:</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> * What happens if you try to perform a non-exclusive wait while an </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> exclusive wait is in progress? i.e. the inverse of the test added here.</p>
<p style="margin-top:12;margin-bottom:12;margin-left:0;margin-right:0;">So after some extensive testing, I'm rather confident that the logic for a new poll on a socket is:</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">(The main poll is an arbitrary designation for one of the poll waiting on the socket)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">If there is no main poll on the socket, then the new poll becomes the main poll.<br />If the main poll is terminated, then there is no main poll anymore.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">If the main poll is exclusive and the new poll is exclusive, then the main poll is terminated and the new poll becomes the main poll.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;"><br /></p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">The flag does not seem to do anything more than this (apart from requiring 0x7fffffff00000000 <= timeout <= 0x7fffffffffffffff).</p>
<p> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> * Can we verify that exclusive waits are specific to a given socket </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> (i.e. you can simultaneously do an exclusive wait on two different sockets?)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;"><br />Yes, the mechanism described earlier seems to be done on a per-socket basis.</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> * Can we test that exclusive waits apply if two unequal sets overlap?</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;"><br /></p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">Yes, it works the same way (a single common socket between exclusive polls is enough to wake the poll)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;"><br /></p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> * Can you do an exclusive wait on the same socket from two different </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> threads?</p>
<p> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">Can yes, didn't want to, but did it anyway :)<br />I get the expected result: It works exactly the same as the single threaded version.</p>
<br /><p style="margin-top:12;margin-bottom:12;margin-left:0;margin-right:0;">So I guess I now have enough insight to write a proper implementation.</p>
<p style="margin-top:12;margin-bottom:12;margin-left:0;margin-right:0;">The patch for the tests is attached to this job: <a href="https://testbot.winehq.org/JobDetails.pl?Key=97234">https://testbot.winehq.org/JobDetails.pl?Key=97234</a></p>
<p style="margin-top:12;margin-bottom:12;margin-left:0;margin-right:0;">Feel free to tell me if other tests come to your mind.</p>
<br /><p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">Le mercredi 1 septembre 2021, 17:52:14 CEST Guillaume Charifi a �crit�:</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> Signed-off-by: Guillaume Charifi <guillaume.charifi@sfr.fr></p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> ---</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>� dlls/ws2_32/tests/afd.c | 73 ++++++++++++++++++++++++++++++++++++++++-</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>� 1 file changed, 72 insertions(+), 1 deletion(-)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> index eb7c8ee50de..2568f251b6f 100644</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> --- a/dlls/ws2_32/tests/afd.c</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +++ b/dlls/ws2_32/tests/afd.c</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> @@ -148,8 +148,10 @@ static void test_poll(void)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� const struct sockaddr_in bind_addr = {.sin_family = AF_INET,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> .sin_addr.s_addr = htonl(INADDR_LOOPBACK)}; char in_buffer[offsetof(struct</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> afd_poll_params, sockets[3])]; char out_buffer[offsetof(struct</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> afd_poll_params, sockets[3])]; +��� char out_buffer1[offsetof(struct</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> afd_poll_params, sockets[3])]; struct afd_poll_params *in_params = (struct</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> afd_poll_params *)in_buffer; struct afd_poll_params *out_params = (struct</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> afd_poll_params *)out_buffer; +��� struct afd_poll_params *out_params1 =</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> (struct afd_poll_params *)out_buffer1; int large_buffer_size = 1024 * 1024;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� SOCKET client, server, listener;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� struct sockaddr_in addr;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> @@ -157,13 +159,14 @@ static void test_poll(void)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� IO_STATUS_BLOCK io;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� LARGE_INTEGER now;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� ULONG params_size;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> -��� HANDLE event;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� HANDLE event, event1;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� int ret, len;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� large_buffer = malloc(large_buffer_size);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� memset(in_buffer, 0, sizeof(in_buffer));</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� memset(out_buffer, 0, sizeof(out_buffer));</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� event = CreateEventW(NULL, TRUE, FALSE, NULL);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� event1 = CreateEventW(NULL, TRUE, FALSE, NULL);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� ret = bind(listener, (const struct sockaddr *)&bind_addr,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> sizeof(bind_addr)); @@ -208,10 +211,77 @@ static void test_poll(void)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>������������� IOCTL_AFD_POLL, in_params, params_size, out_params,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> params_size); ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� /* Test exclusive flag */</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� in_params->timeout = -1000 * 10000;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� in_params->count = 1;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� in_params->exclusive = FALSE;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� in_params->sockets[0].socket = client;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� in_params->sockets[0].flags = ~0;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� in_params->sockets[0].status = 0;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� out_params->sockets[0].socket = 0;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� out_params->sockets[0].flags = 0;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� out_params->sockets[0].status = 0xdeadbeef;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +����������� IOCTL_AFD_POLL, in_params, params_size, out_params,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> params_size); +��� ok(ret == STATUS_PENDING, "got %#x\n", ret);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� in_params->timeout = 0x7fffffffffffffff; /* TIMEOUT_INFINITE */</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� in_params->exclusive = TRUE;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ret = NtDeviceIoControlFile((HANDLE)listener, event1, NULL, NULL, &io,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +����������� IOCTL_AFD_POLL, in_params, params_size, out_params1,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> params_size); +��� ok(ret == STATUS_PENDING, "got %#x\n", ret);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ret = WaitForSingleObject(event, 100);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ok(ret == STATUS_TIMEOUT, "got %#x\n", ret);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ok(!out_params->sockets[0].socket, "got socket %#Ix\n",</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> out_params->sockets[0].socket); +��� ok(!out_params->sockets[0].flags, "got</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> flags %#x\n", out_params->sockets[0].flags); +�� </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> ok(out_params->sockets[0].status == 0xdeadbeef, "got status %#x\n",</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> out_params->sockets[0].status); +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� closesocket(client);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ret = WaitForSingleObject(event, 100);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ok(!ret, "got %#x\n", ret);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� out_params->sockets[0].socket = 0;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� out_params->sockets[0].flags = 0;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� out_params->sockets[0].status = 0xdeadbeef;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ret = NtDeviceIoControlFile((HANDLE)listener, event, NULL, NULL, &io,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +����������� IOCTL_AFD_POLL, in_params, params_size, out_params,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> params_size); +��� ok(ret == STATUS_PENDING, "got %#x\n", ret);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ret = NtDeviceIoControlFile((HANDLE)listener, event1, NULL, NULL, &io,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +����������� IOCTL_AFD_POLL, in_params, params_size, out_params1,</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> params_size); +��� ok(ret == STATUS_PENDING, "got %#x\n", ret);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ret = WaitForSingleObject(event, 100);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ok(!ret, "got %#x\n", ret);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ok(io.Status == STATUS_SUCCESS, "got %#x\n", io.Status);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ok(io.Information == offsetof(struct afd_poll_params, sockets[0]), "got</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> %#Ix\n", io.Information); +��� ok(out_params->timeout ==</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> 0x7fffffffffffffff, "got timeout %#I64x\n", out_params->timeout); +�� </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> ok(!out_params->count, "got count %u\n", out_params->count);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ok(!out_params->sockets[0].socket, "got socket %#Ix\n",</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> out_params->sockets[0].socket); +��� ok(!out_params->sockets[0].flags, "got</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> flags %#x\n", out_params->sockets[0].flags); +�� </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> ok(out_params->sockets[0].status == 0xdeadbeef, "got status %#x\n",</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> out_params->sockets[0].status); +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� closesocket(client);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ret = WaitForSingleObject(event1, 100);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� ok(!ret, "got %#x\n", ret);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� /* Basic semantics of the ioctl. */</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� in_params->timeout = 0;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� in_params->count = 1;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� in_params->exclusive = FALSE;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� in_params->sockets[0].socket = listener;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� in_params->sockets[0].flags = ~0;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� in_params->sockets[0].status = 0xdeadbeef;</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> @@ -743,6 +813,7 @@ static void test_poll(void)</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� closesocket(server);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> </p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� CloseHandle(event);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">> +��� CloseHandle(event1);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>����� free(large_buffer);</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;">>� }</p>
<p style="margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;"><br /></p>
</body>
</html>