Как всем известно, наборы Nt функций указывают на обработчики, вызванные после переключения режима, т.е. после прохождения шлюза, Zw до этого. Т.е. если вызвать системный вызов (NtCreateFile) в контексте какого-то процесса, например, то обработчик проверит предыдущий режим, а так как предыдущий режим был usemode, произойдет исключение, и вызов возвратит 0xc0000005, значит нужно переключить(хотя, насколько я знаю, невозможно), что-бы обработчик, проверяя прошлый режим, убедился, что он был kernelmode, что делать в такой ситуации??? Тоже и с системными вызовами не экспортируемыми в ntoskrnl, тот же NtWriteVirtualMemory, найти адресс обработчика можно в SDT, можно восстановить ее, если таблица запатчена, но как вызвать ее в kernel'e, с предыдущим юзермодным режимом? В DriverEntry вызовы Nt проходят на ура, а в DrvDispatch, завершаются c0000005, т.е. обработчик проверяет предыдущий режим, так и есть.
Я у себя делал просто- выделял блок памяти в юзермоде, копировал в неё параметры, устанавливал на неё все указатели (причём как IN, так и OUT!) и вызывал Nt*. И всё работает!
Я ж тебе предлагал вариант через WorkItem. Там PreviousMode уж точно будет KernelMode. А вообще, странное решение какое-то: создавать файл из обработчика хука NtCreateFile. Не лучше ли накапливать данные в памяти? И если уж так нужно файло в драйвере создавать, то делать это где-нить в другом месте.
В системе есть несколько рабочих потоков (system worker threads), которые любой драйвер может использовать для всякой черновой работы. Работают они в контексте системного процесса. Особенно полезны, когда надо находясь на IRQL >= DISPATCH_LEVEL, сделать что-то, что на этом IRQL делать нельзя. Тогда можно дать эту работу рабочему потоку, т.к. он всегда на PASSIVE_LEVEL работает. Функции такие Код (Text): IoAllocateWorkItem - выделить управляющую структуру IoQueueWorkItem - подцепиться к рабочему потоку в очередь IoFreeWorkItem - освободить управляющую структуру В KmdKit даже пример есть \examples\basic\WorkItem