Имеется колбэк NewNtGdiBitBlt(... HDC hDCSrc...). Пытаюсь передать данные заданной области HDC в юзермод. Проблема в том что документированные функции GDI используют функции с SURFOBJ аргументми. Как получить их из HDC не представляю. Есть мысль использовать юзермодный подход. NtGdiCreateCompatibleBitmap NtGdiCreateDIBSection NtGdiSelectBitmap NtGdiGetDIBitsInternal но уж больно сложно получается. Искать обявления недокументированные + NtGdiGetDIBitsInternal буфер возможно захочет исключительно юзермодный. Да и по задумке эти сервисы не вызываются из ядра и как себя поведут пока не ясно. Еще есть мысль использовать HDC юзермодный. Сделать ему ObReferenceObjectByHandle и вызывать TrueNtGdiBitBlt, а DIBits получать в юземоде, но тогда не понятно как реализовать очередь и обеспечить "Compatible" у обоих HDC.
Проложая свою тему. Решил в своем обработчике NewNtGdiBitBlt делать прыжок в юзермод через KeUserModeCallback (APC не подходит, оно, я так понимаю, сразу же меня в контекст нужного процесса не переключит), и там уже с этим HDC работать. Возникли несколько вопросов касаемо KeUserModeCallback. 1) Пишут "её можно вызывать если драйвер не был ранее приаттачен ни к одному процессу" тоесть вызывать перед ней KeAttachProcess к своему процессу не получится? 2) Пишут "Для вызова кода режима пользователя нам необходимо выделить память где-нибудь пониже KernelCallbackTable (следует использовать флаг MEM_TOP_DOWN в ZwAllocateVirtualMemory)" Есть какая то разница повыше или пониже? Мой обработчик по адресу 401ХХХh 3) пробовал подменить в адрес таблице на адрес свого юзермод обработчика и вызвать KeUserModeCallback(0x53...) В результате, что бы я не делал KeUserModeCallback возвращает c0000005. Но пример с MEM_TOP_DOWN рабоатет отлично.
1. Нет смысла. Может потребоваться переключение между сессиями(MmAttachSession()). 2. Адрес буфера значения не имеет(в пределах пользовательского сегмента кода). Его нужно заблочить(MmSecureVM()), запретить саспенд апк(KeEnterCriticalRegion()) и защитить код SEH. Иначе вы создадите уязвимость в системе. Пользовательский T-фрейм должен быть сформирован. 3. Перед вызовом теневого колбека необходимо разрешить доставку саспенд апк. Пользовательский хэндлер должен быть зареган в apfnDispatch[] и заключён в сех. После возврата из колбека необходимо вновь запретить доставку саспенд апк. На время вызова колбека IRQL нельзя повышать(пассив).
Удалось выяснить в чем проблема. Мой код с KeUserModeCallback отлично работает например из диспетчера IO. Но если его использовать из NewNtGdiBitBlt (драйвер уже приаттачен к какому-то процессу) то после вызова KeAttachProcess к своему приложению, KeUserModeCallback возвращает c0000005. Попробовал сделать так NewNtGdiBitBlt{ KeDetachProcess() KeAttachProcess(мой процесс) KeUserModeCallback() KeDetachProcess() KeAttachProcess(тот процесс что вызывал NewNtGdiBitBlt) } ничего не поменялось.
assorted Ну давайте гадать. Вызывается ли хэндлер в apfnDispatch[] и если вызывается, то что возвращает ?
Посмотреть не успел, скорее всего не вызывается. Сделал решение простое как три копейки - SetEvent в юзермод и с помощью KeWaitForSingleObject жду завершения операции через IO. Тема не актуальна. Спасибо klzlk.