Вообщем то хукаю запросы в ядре к \device\afd (не спрашивайте зачем D).
Что то типа
if (IoControlCode == 0x12017 /*recv*/) {
st = Original_NtDeviceIoControlFile(
FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, IoControlCode,
InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength
);
if (st == STATUS_PENDING && Event != NULL) {
ZwWaitForSingleObject(Event, FALSE, NULL);
st = IoStatusBlock->Status;
}
if (NT_SUCCESS(st)) {
Trace("%p", IoStatusBlock->Information);
}
}
Собственно, в IoStatusBlock->Information мусор. Однако, в юзер приложении (сразу же после вызова) всё нормально, количество принятых байт. Что я делаю не так ?
S> if (st == STATUS_PENDING && Event != NULL) {
S> ZwWaitForSingleObject(Event, FALSE, NULL);
S> st = IoStatusBlock->Status;
S> }
А шо делать будем если st == STATUS_PENDING && Event == NULL ? А это может быть — completion ports, apc..
Кстати то, что вы вытворяете с event'ом, который передал вам юзер — тоже печалька. Ведь он может быть autoreset, и вы завесите приложение, поломав ему логику. Либо этот autoreset event может ожидать юзер в соседнем потоке. В результате он его дождется, а вы — нет. Результат — зависон.
Совет: ZwQueryInformationFile(...FileModeInformation..) и если там не фигурирует FILE_SYNCHRONOUS_IO_NONALERT|FILE_SYNCHRONOUS_IO_ALERT, то создаете свой event, суете его вместо юзерского.
Если функа вернула STATUS_PENDING — ждете свой ивент, когда дожидаете — сигналите юзерский ивент, если он не нулл. При этом вот этого вот тоже делать не стоит: st = IoStatusBlock->Status;
Если функа вернула чтото другое, и юзерский ивент не NULL: _проверяете_ свой ивент ожиданием с нулевым таймаутом, если он просигнален — сигнальте паровозиком юзерский ивент.
[UPD]
Я тут еще подумал, и пришел к выводу что стабильно рабочего решения для сценария с IOCP у вас таким путем не получится
Потому что параллельно работающий юзерский поток может получить через GetQueuedCompletionStatus уведомление о завершении _до_ того как раздуплится ваш код, ждущий на event'е. Получив его, он в свою очередь может уничтожить/резюзать текущую IoStatusBlock.
Я уж не говорю о таких "мелочах", как факт того что вы эффективно превращаете асинхронный вызов в синхронный, что поломает логику приложения которает даже юзает простые event'ы, а не IOCP, но которое делает wait на несколько событий (а вы — нет).