События Event в WinApi
Подскажите пожалуйста, вот на MSDN есть пример вызова GetAddrInfoExW, приведу только небольшую часть:
https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfoexw
Там есть пример вызова функции CreateEvent:
QueryContext.CompleteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
Но, в описании функции CreateEvent на том же MSDN`е нет ни какого QueryContext.CompleteEvent, CreateEvent возвращает обычный HANDLE:
HANDLE CreateEventA(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCSTR lpName
);
Я что то не пойму что такое QueryContext.CompleteEvent и откуда он вообще взялся ?
Ответы (1 шт):
Прокоментирую для вас код
int __cdecl wmain( _In_ int Argc, PWCHAR Argv[]) {
INT Error = ERROR_SUCCESS;
WSADATA wsaData;
BOOL IsWSAStartupCalled = FALSE;
ADDRINFOEX Hints;
QUERY_CONTEXT QueryContext; // Вот отсюда он взялся
// .. пропускаю кусок
QueryContext.CompleteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// Создали Event событие
if (QueryContext.CompleteEvent == NULL)
{
// ... Если не создалось - ошибка
}
// Делаем вызов
Error = GetAddrInfoExW(Argv[1], NULL, NS_DNS, NULL, &Hints,
&QueryContext.QueryResults, NULL,
&QueryContext.QueryOverlapped,
QueryCompleteCallback,
&CancelHandle);
// Так как мы передали Event - ответ должен быть PENDING
if (Error != WSA_IO_PENDING)
{ // Если ответ не PENDING, ответ 0 не будет, а ошибку обработает код ниже, который в QueryCompleteCallback
QueryCompleteCallback(Error, 0, &QueryContext.QueryOverlapped);
goto exit; // и на выход
}
// Ждем время QueryTimeout = 5 секунд пока не произойдёт событие
if (WaitForSingleObject(QueryContext.CompleteEvent,
QueryTimeout) == WAIT_TIMEOUT )
{
wprintf(L"Пишем что недождались ");
GetAddrInfoExCancel(&CancelHandle); // Отмена вызова
WaitForSingleObject(QueryContext.CompleteEvent, INFINITE);// Ждём отмену до бесконечности
}
А тут ещё хитрость, они передали каллбек, QueryCompleteCallback (ниже по коду) будет вызвано в то время, пока будет идти первый WaitForSingleObject.
Это обычный механизм обращения с Overlapped-event. Похожее можно делать и с чтением файла и с другими операциями, которые могут растянуться во времени.
HANDLE позволяет хранить в себе какие угодно kernel обьекты. Файлы, pipe-ы, Thread, их список тут а функции собраны тут (msdn) в функциях есть "лишнии" обьекты которые не имеют хандлов.
Есть специальные функции NtQueryObject и подобных - которые могут узнать тип хандла. Особенность хандла в том, что для любого хандла можно делать CloseHandle, будь то файл, Event, Thread, Process и так далее. Да, в самом низу примера от микрософт - они закрывают хандл. Наверно это для удобства сделано. Так уже сложилось начиная ещё с первых (или вторых) версий винды так принято с хандлами делать.