может ли DriverEntry функция создавать поток? причём поток должен продолжать работать, а функция DriverEntry должна завершиться. Код (Text): void __cdecl Test(PVOID a) { LARGE_INTEGER delay; delay.QuadPart = SEC(1000); while(1) KeDelayExecutionThread(KernelMode,0,&delay); } DriverEntry(..) { PsCreateSystemThread(&hThread,THREAD_ALL_ACCESS,0,0,0,Test,0); return 0; } проблемма в том, что при загрузке дрова лоадер виснет, хотя, (смотрел в сайсе) функция DriverEntry завершается и возвращает 0, PsCreateSystemThread срабатывает удачно, поток запускается.
Да. Так оно и будет. Точнее поток начинает жить своей жизнью безотносительно к тому, что делает и как завершается DriverEntry. Проблема только в том, что код потоковой функции находится в теле драйвера. Т.е. драйвер должен оставаться загружен всё время пока живёт поток. Но если DriverEntry не создаст device object (если это legacy драйвер) и у драйвера нет функции AddDevice (если это legacy драйвер), то по выходу из DriverEntry загрузчик проверит, создал ли драйвер девайс. Если нет, то вызовет его DriverUnload и попытается выгрузить его из памяти. Тут у тебя косяк и происходит. Ещё м.б. завязка на хендл потока... т.е. в объекте драйвера увеличивается счетчик ссылок и пока он не обнулится драйвер не может быть выгружен, но на 100% не скажу... уже не помню всех деталей. В любом случае, legacy драйвер обязан создать девайс в DriverEntry, иначе система считает, что такой драйвер без девайса нафиг ей не нужен и стремиться от него избавиться.
Ну дык он и не пытается его выгрузить, всего лишь загрузить. Ну хотя для эксперимента можно попробовать закрыть хендл потока в DriverEntry, только не вызовет ли это его завершения? Счетчик хендов ведь упадет до нуля.. хотя, наверное, при старте счетчик ссылок увеличивается.. я хз ) Хм.. а почему тогда принудительно не килляются дрова, не создающие девайсов, но имеющие DriverUnload ? У меня они выгружаются только явно, по ZwUnloadDriver и никак иначе
Ну... вобщем немного понятно.. попробую помудить с созданием потока. Есть ещё вопрос. Если я вызову ZwUnloadDriver - система прибъёт этот поток или же мне необходимо самому его прибить? Немного странно: есть функция ZwTerminateThread.ntdll - она есть и в СДТ, но в экспорте ntoskrnl такой функции нет. отсюда вопрос - можно ли убивать ей системные потоки?
Всем спасибо за ответы. Вобщем проблемма была в том, что: Код (Text): PsCreateSystemThread(&hThread,THREAD_ALL_ACCESS,0,0,0,Test,0); четвёртым параметром необходимо указывать не 0, а -1 т.е. NtCurrentThread(). я подумал что 0, т.к. в ДДК написано optional: Код (Text): IN HANDLE ProcessHandle OPTIONAL, Далее - система сама потоки не убивает, а при попытке выгрузить дров, не убив поток вылазит сайс и говорит fault! т.е. образ выгружается, а поток продолжает работать.
gevara <В любом случае, legacy драйвер обязан создать девайс в DriverEntry, иначе система считает, что такой драйвер без девайса нафиг ей не нужен и стремиться от него избавиться.> Абсолютно не стремится. Даже если драйвер не создал устройства, но, DriverEntry вернуло Success, драйвер остаётся в памяти. Другое дело, если DriverEntry располагается в удаляемой секции, и процедура потока тоже в ней. В таком случае, на ядре со страницами по 4к произойдёт освобождение заданной странички и тогда само собой либо поток зависает либо бсод. Если страничка 4м, то как правило код DriverEntry остаётся, но может быть забит нулями, видел и такое, а это значит, что данный кусок памяти перестаёт быть виден как занятый. Соответственно с ним может случиться всё что угодно. Если драйвер компилён майкросовтовским компилером, то он почти всегда в 99,99% случаев создаёт секцию INIT, что собственно и подтверждает всё вышесказанное. Да, и кроме того, ты в DriverEntry не пишешь ничего в Pe - заголовок? это тоже одна из причин взвисов. В общем, смотри внимательно. Создавать девайс необязательно, иначе нелогичность выходит, если драйвер удаляет свой девайс оно что, должно быть автоматом должно быть выгружено? так и руктиты бы их большая часть по крайней мере не смогли бы работать)))
Нет. Только сам системный поток может самого себя завершить вызовом PsTerminateSystemThread. Я уже не помню всех деталей, но... Код (Text): NTSTATUS IopLoadDriver( ... ) { ... // // If we load the driver because we think it is a legacy driver and // it does not create any device object in its DriverEntry. We will // unload this driver. // if (NT_SUCCESS(status) && !IopIsLegacyDriver(driverObject)) { if (driverObject->DeviceObject == NULL && ... ) { IopDriverLoadingFailed(KeyHandle, NULL); status = STATUS_PLUGPLAY_NO_DEVICE; ... } if (!NT_SUCCESS(status)) { if (driverObject->DriverUnload) { driverObject->Flags |= DRVO_UNLOAD_INVOKED; driverObject->DriverUnload(driverObject); IopBootLog(&baseName, FALSE); } } } ... }
> Нет. Только сам системный поток может самого себя завершить вызовом PsTerminateSystemThread. мдя.. это плохо. То есть придётся создавать механизм, чтобы при запуске DriverUnload поток выходил из бесконечного цикла...
<Я уже не помню всех деталей, но...> Хм, ну чессслово, сколько дров делал без устройства, никогда ничего не выгружалось.
k3internal +1 Four-F Ну так оно возвращает только STATUS_PLUGPLAY_NO_DEVICE, я не помню, а может это и не статус ошибки вовсе, поэтому и незачем выгружать драйвер.
Вполне возможно что я ошибаюсь или путаю что-то. Раз говорите, что не выгружаются, значит так оно и есть.