· Начало · Статистика · WASM.RU · Noir.Ru ·

 WASM Phorum (Оффлайн - 24.11.2003) —› WASM.WIN32 —› WDM драйвер не хочет выгрузиться

. 1 . 2 . >>

Посл.отвђт Сообщенiе


Дата: Окт 12, 2003 00:13:03 · Поправил: Безпощадный даос

Скачал пример WDM драйвера.
Проблема- почему он не хочет просто выгрузиться(DeviceManager->MyDriver->Uninstall)
, т.е. WinXP говорит- нужно перезагрузиться чтобы изменения (Uninstall) вступили в силу.

Например, драйвер, собранный в NumegaDriverStudio (на VC++) отлично выгружается-загружается без перезагрузок.

Подскажите что нужно дописать(?) в OnUnload чтобы драйвер выгружался нормально без перезагрузки!


;--------------------------------------
; Обработчик события выгрузки драйвера
;--------------------------------------
OnUnload proc near, DriverObject:PDRIVER_OBJECT

; Удаляем символическую связь
invoke IoDeleteSymbolicLink, addr Win32DeviceName

; Удаляем логическое устройство
mov eax, DriverObject
invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject

; Деинициализируем юникодовые строки
invoke RtlFreeUnicodeString,offset NtDeviceName
invoke RtlFreeUnicodeString,offset Win32DeviceName

ret
OnUnload endp
;--------------------------------------


Буду Очень благодарен за Помощь!


Дата: Окт 13, 2003 01:30:21

Ну.. хоть кто-нибудь чтото подскажите!!!!
Драйвер вот откуда (статья):
http://www.wasm.ru/article.php?article=drvw2k05

сами исходники:
http://four-f.narod.ru/KmdKit10.zip
зеркала:
http://www32.brinkster.com/fourf/KmdKit10.zip
http://wasm.ru/tools/11/KmdKit10.zip

update исходников:
http://www32.brinkster.com/fourf/kkupto11.zip

----
может драйвер не все после себя восстанавливает/отдает/освобождает/итд. ?
и поэтому он както некорректно выгружается?(точнее - Win не может его выгрузить, насколько я понимаю)

Хотябы подскажите в каком направлении думать :(

Спасибо!


Дата: Окт 13, 2003 02:12:17

у меня была такая проблемма , я справился , но не помню как , точно не скажу но это не при выгрузке драйвера, а при запуске (инсталляции) надо такие параметры давать , чтоб он без перезагрузки работал , извини непомню какие (прогу уже купили и я забыл)


Дата: Окт 13, 2003 14:31:52

[ prog: Скачал пример WDM драйвера. Проблема- почему он не хочет просто выгрузиться... ]

Что-то я не понял. Это мой драйвер из статьи не хочет выгружаться что ли? Все дрова я тестил под 2000/ХР/2003 - все работает и выгружается без проблем. Или проблема с твоим драйвером?


[ prog: Подскажите что нужно дописать(?) в OnUnload... ]

Ты должен вернуть STATUS_SUCCESS, т.к. RtlFreeUnicodeString по докам ничего не возвращает, т.е. в eax какой-нить мусор и система считает, что OnUnload не отработала. Наверное в этом проблема.


Дата: Окт 13, 2003 17:02:47 · Поправил: prog

Что-то я не понял. Это мой драйвер из статьи не хочет выгружаться что ли? Все дрова я тестил под 2000/ХР/2003 - все работает и выгружается без проблем. Или проблема с твоим драйвером?

Да. Я в этом драйвере из примера ничего не менял.
Взял исходники (KmdKit10.zip -> VirtToPhys), сделал свой .inf , скомпилировал, установил. Все хорошо.
Тутже делаю Uninstall - WinXP говорит, что нужно перегрузиться чтобы изменения вступили в силу.
Перезагружаюсь- все как он и обещал- драйвера нету.

Ты должен вернуть STATUS_SUCCESS, т.к. RtlFreeUnicodeString по докам ничего не возвращает, т.е. в eax какой-нить мусор и система считает, что OnUnload не отработала. Наверное в этом проблема.

В конце UnLoad записал в eax STATUS_SUCCESS - все тоже самое :(

Вот полный код драйвера (это из другого источника, но, помоему, все сделано также , как и в статье Four-F(Уважаемого мной! :) )):

Тут у меня еще одна ПРОБЛЕМА-
dll не видит буфер (buffered IOCTL). На С++ это лечилось заменой в драйвере (написанном на VС++) Irp.UserBuffer() на Irp.IoctlBuffer() :

//Получаем указатель на буфер пользователя
//buf=(unsigned int*) I.UserBuffer(); так dll не видит то, что возвращается в буфере
buf=(unsigned int*) I.IoctlBuffer(); так- видит

А как в ASM получить указатель на IoctlBuffer ?

Это- "SystemBuffer":
; Получаем указатель на системный буфер
mov eax,(_IRP ptr [ebx]).AssociatedIrp.SystemBuffer

А что такое и где его взять "IoctlBuffer" ?

Спасибо всем за помощь!!!





.586p
.model flat, stdcall
option casemap:none

; Включения
.nolist
include usewdm.inc
includelib wdm.lib

.list
include ioctlcodes.inc


; ---------------------------------------------------------------------- ----------------
.data

; Имя устройства NT
wsNtDeviceName dw '\','D','e','v','i','c','e','\','S','a','m','p','l','e','A','s','m','D ','r','v',0

; Имя линка
wsWin32DeviceName dw '\','D','o','s','D','e','v','i','c','e','s','\','S','a','m','p','l','e ','A','s','m','D','r','v',0


NtDeviceName UNICODE_STRING {0,0,0}
Win32DeviceName UNICODE_STRING {0,0,0}

; Указатель на device object
DeviceObject PDEVICE_OBJECT 0


; ---------------------------------------------------------------------- ----------------
.code

; ---------------------------------------------------------------------- ----------------
; Точка входа для первичной инициализации
; ---------------------------------------------------------------------- ----------------
DriverEntry proc near public, DriverObject:PDRIVER_OBJECT, RegistryPath:PUNICODE_STRING
LOCAL Status:DWORD
mov Status,STATUS_SUCCESS ; Статусное значение


push ebx
mov ebx,DriverObject
mov (DRIVER_OBJECT ptr [ebx]).DriverUnload, offset OnUnload
mov eax, offset OnDispatch
mov (DRIVER_OBJECT ptr [ebx]).MajorFunction[IRP_MJ_CREATE * (TYPE PDRIVER_DISPATCH)],eax
mov (DRIVER_OBJECT ptr [ebx]).MajorFunction[IRP_MJ_CLOSE * (TYPE PDRIVER_DISPATCH)],eax
mov (DRIVER_OBJECT ptr [ebx]).MajorFunction[IRP_MJ_DEVICE_CONTROL * (TYPE PDRIVER_DISPATCH)],eax
pop ebx


; Инициализируем юникодовые строки с именами устройства и линка
invoke RtlInitUnicodeString, offset NtDeviceName, offset wsNtDeviceName
invoke RtlInitUnicodeString, offset Win32DeviceName, offset wsWin32DeviceName


; Создаём логический объект устройства
invoke IoCreateDevice, DriverObject, 0, offset NtDeviceName, FILE_DEVICE_UNKNOWN,0,FALSE,offset DeviceObject;
cmp eax,STATUS_SUCCESS ; Проверим, не было ли ошибки.
jnz @F

; Создаём symbolic link
invoke IoCreateSymbolicLink, offset Win32DeviceName, offset NtDeviceName ; в eax останется код результата

@@:
ret
DriverEntry endp

; ---------------------------------------------------------------------- ----------------
; Обработчик события выгрузки драйвера
; ---------------------------------------------------------------------- ----------------
OnUnload proc near, DriverObject:PDRIVER_OBJECT
; Удаляем символическую связь
invoke IoDeleteSymbolicLink, addr Win32DeviceName

; Деинициализируем юникодовые строки
invoke RtlFreeUnicodeString,offset NtDeviceName
invoke RtlFreeUnicodeString,offset Win32DeviceName

mov eax, DriverObject
invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject

;!!!!Это добавил- ничего не изменилось!!!! (XP требует перезагрузки после Uninstall)
mov eax,STATUS_SUCCESS

ret

OnUnload endp

; ---------------------------------------------------------------------- ----------------
; Процедура обработки запроса device IO control
; Re: должна возвращать в eax статусный код
; ---------------------------------------------------------------------- ----------------

DeviceIoControlHandler proc near, Code:ULONG, pBuffer:PCHAR, InputBufferLength:ULONG, OutputBufferLength:ULONG, pOutputLength:PULONG

mov eax,Code
cmp eax,IOCTL_CODE_801 ; Тип запроса 1
jz IoCtl_1

; <...> -- Прочие запросы

mov eax,STATUS_NOT_IMPLEMENTED ; Непредусмотренный код запроса
ret

IoCtl_1:

; Пытаемся возвратить байт, на 01h бОльший, чем получили (НИЧЕГО НЕ ВОЗВРАЩАЕТСЯ!)
push ebx
xor eax,eax
mov ebx,pBuffer
mov al,BYTE ptr [ebx]
add al,01h
mov BYTE ptr [ebx],al
pop ebx

; Длина данных, передаваемых обратно приложению пользователя.
push ebx
mov eax,OutputBufferLength
mov ebx,pOutputLength
mov DWORD ptr [ebx],eax
pop ebx

@@:
mov eax,STATUS_SUCCESS
ret

DeviceIoControlHandler endp


; ---------------------------------------------------------------------- ----------------
; Диспетчер вызовов IRP_MJ_XXX
; ---------------------------------------------------------------------- ----------------
OnDispatch proc near, pDeviceObject:PDEVICE_OBJECT,pIrp:PIRP

LOCAL Status:DWORD ; Хранит статусное значение для возврата
LOCAL pIrpStack:DWORD ; Указывает на структурку IO_STACK_LOCATION

LOCAL Code ; Хранит код запроса DeviceIoControl
LOCAL InputBufferLength ; Хранит длину входного буфера
LOCAL OutputBufferLength ; Хранит длину выходного буфера
LOCAL pBuffer ; Хранит ссылку на буфер


mov Status,STATUS_UNSUCCESSFULL

push ebx
mov ebx,pIrp
mov eax,(_IRP ptr [ebx]).Tail.Overlay.CurrentStackLocation ; Восстанавливаем указатель на структуру IO_STACK_LOCATION
mov pIrpStack,eax

mov ebx,pIrpStack
mov al,(IO_STACK_LOCATION ptr [ebx]).MajorFunction ; Код сообщения
pop ebx

; IRP_MJ_CREATE -- CreateFile()
cmp al,IRP_MJ_CREATE
jnz @F

mov Status,STATUS_SUCCESS
jmp OnDispatchLeave

; IRP_MJ_CLOSE -- CloseHandle()
@@: cmp al,IRP_MJ_CLOSE
jnz @F

mov Status,STATUS_SUCCESS
jmp OnDispatchLeave

; IRP_MJ_DEVICE_CONTROL -- DeviceIoControl()
@@: cmp al,IRP_MJ_DEVICE_CONTROL
jnz @F

push ebx
mov ebx,pIrp

; Получаем указатель на системный буфер
mov eax,(_IRP ptr [ebx]).AssociatedIrp.SystemBuffer
mov pBuffer,eax


mov ebx,pIrpStack ; Подготовим параметры для вызова.
; Может, это не очень красиво, но упростит код в DeviceIoControlHandler

; Получаем код запроса
mov eax,(IO_STACK_LOCATION ptr [ebx]).Parameters.DeviceIoControl.IoControlCode
mov Code,eax

; Читаем длину входного буфера
mov eax,(IO_STACK_LOCATION ptr [ebx]).Parameters.DeviceIoControl.InputBufferLength
mov InputBufferLength,eax

; Читаем длину выходного буфера
mov eax,(IO_STACK_LOCATION ptr [ebx]).Parameters.DeviceIoControl.OutputBufferLength
mov OutputBufferLength,eax
mov ebx,pIrp

xor eax,eax ; Пока ничего не возвращаем
mov (_IRP ptr [ebx]).IoStatus.Information,eax
mov eax,ebx ; В обработчике потребуется смещение поля Information для записи длины возвращаемых данных
add eax,offset _IRP.IoStatus.Information
pop ebx

; Вызываем обработчик.
invoke DeviceIoControlHandler, Code, pBuffer, InputBufferLength, OutputBufferLength, eax
mov Status,eax ; Запомним код возврата
jmp OnDispatchLeave


@@: ; default
mov Status,STATUS_NOT_IMPLEMENTED

OnDispatchLeave:

mov ecx,pIrp ; Уведомим менеджер ввода-вывода об окончании обработки запроса
mov edx,0
call @IofCompleteRequest@8

mov eax,Status ; Запишем код возврата
push ebx
mov ebx,pIrp
mov (_IRP ptr [ebx]).IoStatus.Status,eax
pop ebx
ret

OnDispatch endp

end


Дата: Окт 13, 2003 18:07:59

[ prog: ...сделал свой .inf... ]

Ясно. Я с инфами никогда дело не имел. Поэтому конкретно ничего сказать не могу. Тебе нужно внимательно почитать в ддк раздел "Creating an INF File" и у Вальтера Они во втором издании есть глава "Distributing Device Drivers". Уверен, что там есть ответ на твой вопрос.


Дата: Окт 13, 2003 18:18:31 · Поправил: prog

Понятно.
Буду смотреть.
Но я взял .inf от своего драйвера, написанного на VC++
, который нормально грузится-выгружается. Поэтому и не думал, что дело может быть в .inf
Сейчас почитаю..
А насчет Буфера?
IoctlBuffer - нужно использовть при буферизированном способе общения драйвера с dll
а тут-

; Получаем указатель на системный буфер
mov eax,(_IRP ptr [ebx]).AssociatedIrp.SystemBuffer
mov pBuffer,eax

- аналог Irp.UserBuffer() в VC++

А как получить адрес IoctlBuffer ?


Дата: Окт 13, 2003 18:29:57

Насчет возвращения STATUS_SUCCESS из DriverUnload я, наверное, протупил. Похоже, что система вообще не проверяет это.


Дата: Окт 13, 2003 18:37:27

[ prog: А как получить адрес IoctlBuffer ? ]

Если ты используешь METHOD_BUFFERED, то система сама занимается копированием буферов. Поэтому она скопирует, то что было в твоем буфере в системное адресное пространство и ты в драйвере получишь указатель на него в _IRP.AssociatedIrp.SystemBuffer. В статье подробно про это написано.

По поводу невыгрузки. При инсталяции через инф задействуется P'n'P Manager. Видимо при выгрузке драйвер как-то должен его уведомить об этом. Как я не знаю - читай доки.


Дата: Окт 13, 2003 19:21:00 · Поправил: prog

Если ты используешь METHOD_BUFFERED, то система сама занимается копированием буферов. Поэтому она скопирует, то что было в твоем буфере в системное адресное пространство и ты в драйвере получишь указатель на него в _IRP.AssociatedIrp.SystemBuffer. В статье подробно про это написано.

Это я понимаю.
Драйвер Получает данные снаружи в _IRP.AssociatedIrp.SystemBuffer , с этим проблем нет.
Проблема- в обратном действии.
Я записываю в _IRP.AssociatedIrp.SystemBuffer данные - dll их не видит. Точнее - она видит какуюто "левую" область памяти (у моего конкретного кампутера там "ММММ...")
Вот в этом проблема.


Дата: Окт 14, 2003 00:31:00 · Поправил: prog

Ясно. Я с инфами никогда дело не имел. Поэтому конкретно ничего сказать не могу. Тебе нужно внимательно почитать в ддк раздел "Creating an INF File" и у Вальтера Они во втором издании есть глава "Distributing Device Drivers". Уверен, что там есть ответ на твой вопрос.

Сделал inf с помощью входящего в DDK geninf.exe по всем правилам.
Это ничего не дало- все также при DeviceManager->Driver->Unistall выдается- Теперь нужно перезагрузить компьютер.

у меня крыша уже едет. или уехала.
:(((

Кто-нибудь! Помогите! %(
Проблемы две:

1. в WinXP делаю драйверу Uninstall --> XP требует перезагрузки для того, чтобы закончить деинсталляцию драйвера. (собранный вроде по правилам .inf не помог)

2. записываю в _IRP.AssociatedIrp.SystemBuffer данные --> приложение (dll) их не видит (в dll все сделано заведомо правильно). (переданные из приложения (dll) данные драйвер отлично видит и берет из _IRP.AssociatedIrp.SystemBuffer)


Дата: Окт 14, 2003 03:35:31 · Поправил: prog

УРА!
проблема 2 разрешилась!
Как всегда- причина в моей невнимательности!

я везде использовал IOCTL в лоб- просто числом, например,

asm:
IOCTL_1 equ 801h
IOCTL_2 equ 802h

VC++ dll:
#define IOCTL_Command_1 0x801
#define IOCTL_Command_2 0x802

ВОТ ЛОПУХ!
Конечно! причина того, что данные из SystemBuffer не появлялись в выходном буффере- в том, что метод передачи данных был вообще не знаю какой...

сделал вот так:
asm:
CTL_CODE MACRO DeviceType:=<0>, Function:=<0>, Method:=<0>, Access:=<0>
EXITM %(((DeviceType) SHL 16) OR ((Access) SHL 14) OR ((Function) SHL 2) OR (Method))
ENDM

IOCTL_1 equ CTL_CODE(FILE_DEVICE_UNKNOWN, 801h, METHOD_BUFFERED, FILE_ANY_ACCESS)


VC++ dll:
#define IOCTL_Command_1 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)


И теперь данные из буфера появляются в выходном буфере в dll!
Спасибо всем!!!

Но теперь остается одна проблема-
в WinXP делаю драйверу Uninstall --> XP требует перезагрузки для того, чтобы закончить деинсталляцию драйвера. (собранный вроде по правилам .inf не помог)


Дата: Окт 14, 2003 11:23:18

[ prog: (собранный вроде по правилам .inf не помог) ]

Возможно, причина в том, что твой драйвер не является WDM драйвером. Это обычный kernel-mode driver и все мои примеры из статей тоже не WDM. WDM отличается от KMD поддержкой P'n'P. Точно я не знаю, но видимо он взаимодействует с диспетчером P'n'P вызывая его сервисы и наверное предоставляя ему свои колбэки. У тебя ничего этого нет - в этом, видимо, и причина. Кстати, не совсем понятно зачем устанавливать твой драйвер через инф. Посмотри примеры WDM-драйверов у того же Вальтера Они или еще где.


Дата: Окт 15, 2003 11:08:28 · Поправил: prog

У него все на C++ :(
Подскажите хоть какую-нибудь ссылку где можно посмотреть как решить проблему в MASM


Дата: Окт 15, 2003 11:24:45 · Поправил: Four-F

Вряд ли ты найдешь такую ссылку, ибо на асме дрова писать, тем более WDM, нонче не популярно - это удел энтузазистов. Читай Они и ддк, смотри примеры - другого путя, IMHO, нет.

Изучи С++, наконец - пригодится.

. 1 . 2 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.095