lukash Насчет динамической загрузки -- официальных, т.е. документированных способов динамически грузить NT-драйвера под 9х (сиречь WDM) вообще нету. Они расчитаны только на статическую загрузку, регистрацией в реестре и копированием в \System -- по аналогии с NT/XP, только с поправкой, что SCM недоступен. Недокументированный способ есть, но с нюансами: а) нельзя динамически выгрузить (т.е. будет жить до перезагрузки). б) зато можно повторно загружать тот же самый драйвер, как бы поверх. в) количество таких перезапусков драйвера ограничено -- после n-го их числа винда падает. Сколько точно не помню, что-то порядка десяти. г) дурацкое ограничение в ntkern.vxd на путь к драйверу -- он должен быть в \System, поэтому перед манипуляциями надо его туда копировать и соответственно удалять, когда он более не нужен. За исключением этих нюансов дин. загрузка WDM на 9х в принципе нормально реализуется. Cкачай вышеупомянутого Walter Oney, если еще нет -- там описаны различия между 9x и nt для wdm-драйверов, какие функции недоступны, какие работают несколько иначе и тп.
_BC_ Спасибо. Книгу скачал, понемногу разбираюсь... Смотрел немного твой загрузчик драйвера acpi_off, там ведь как раз так и реализовано, как ты говоришь? Но ведь там сам драйвер не совсем WDM, или нет, если не секрет?
WDM -- это по сути самые обычные NT'шные KMD-драйвера. С точки зрения NT, WDM -- всего лишь набор рекомендаций и требований к драйверам. А вот для 9x это уже весьма нечто -- возможность помимо vxd грузить NT'шные драйвера, пусть с кучей ограничений, но тем не менее. По докам они "source-level compatible", но реально они и binary-compatible -- если знать, чего надо избегать, чтобы этот драйвер работал и на 9х, и на NT. В первую очередь эта совместимость определяется набором доступных системных функций -- ntkern.vxd реализует далеко не все NT'шные сервисы. Есть утилита, afair от этой самой книжки, которая проверяет драйвер на соответствие WDM, т.е. будет ли он работать и под 9х, и под NT/XP. Она в т.ч. смотрит и на импортируемые драйвером функции. Если писать не полноценный драйвер для какой-нть реальной и сложной железки, а так, чисто под свой Ring0-код, то wdm под 9х самое то для плавной миграции с 9x на NT. Особенно когда привык к 9х, знаешь ее ядро, есть привычные инструменты и тп и тд -- а надо делать что-то под NT, которая после 9х вызывает почти суеверный ужас. Да, там остался и код для загрузки под 9х. Ща проверил под win98se на вмваре и не без удивления обнаружил, что оно работает и на 9х. Изначально это вообще-то совсем не планировалось. Тем более повезло, что вин9х может (ессно после чтения всей инфы) дискардить ACPI Reclaim Area, в которой располагаются используемые acpi_off таблицы. Вот тот самый фрагмент дин. загрузки nt-драйвера под 9x (т.е. из загрузчика off_drv.sys). Сначала для драйвера выполняется обычная регистрация, как будто это статик WDM и копирование в SYSTEM, разница, насколько помню, только в поле Start: Код (Text): ;------------------------------------------------- ; LoadDriver9x -- static wdm drv registration ;------------------------------------------------- LoadDriver9x proc pDrvName:DWORD, pServName:DWORD local ImagePath:BYTE:256, hkServices:DWORD, hkMyKey:DWORD, \ shit:DWORD, DestPath:BYTE:256, temp_str:BYTE:256 lea eax, [hkServices] push eax ; &hkKey push KEY_ALL_ACCESS ; Access push 0 ; reserved pushstr 'System\CurrentControlSet\Services' ; lpPath push HKEY_LOCAL_MACHINE call RegOpenKeyExA lea eax, [shit] push eax ; &dwDisp lea eax, [hkMyKey] ; &hKey push eax push 0 push KEY_ALL_ACCESS push REG_OPTION_NON_VOLATILE pushstr 0 ; lpClass push 0 push [pServName] push [hkServices] call RegCreateKeyExA lea eax, [shit] push eax ; lpFilePart lea eax, [ImagePath] push eax ; pPathBuf push 256 push [pDrvName] call GetFullPathNameA push 4 pushstr <1,0,0> push REG_DWORD push 0 pushstr 'Type' push [hkMyKey] call RegSetValueExA push 4 pushstr <3,0,0> ; <-- можно менять на нужное push REG_DWORD push 0 pushstr 'Start' push [hkMyKey] call RegSetValueExA push 4 pushstr <1,0,0> push REG_DWORD push 0 pushstr 'ErrorControl' push [hkMyKey] call RegSetValueExA push 4+1 pushstr 'Base' push REG_SZ push 0 pushstr 'Group' push [hkMyKey] call RegSetValueExA push edi push esi lea eax, [DestPath] mov esi, eax push eax call GetSystemDirectoryA, eax, 256 lea edi, [esi+eax] mov al, '\' stosb mov esi, [pDrvName] add_str1: lodsb cmp al, 0 stosb jnz add_str1 lea edx, [ImagePath] pop eax call CopyFile, edx, eax, 0 lea edi, [temp_str] mov edx, edi AddStr '\SystemRoot\SYSTEM\' mov esi, [pDrvName] add_str2: lodsb cmp al, 0 stosb jnz add_str2 call strlen, edx pop edx inc eax push eax push edx push REG_SZ push 0 pushstr 'ImagePath' push [hkMyKey] call RegSetValueExA call RegCloseKey, [hkMyKey] call RegCloseKey, [hkServices] pop esi pop edi ret LoadDriver9x endp ;------------------------------------------------- Собственно загрузка выглядит вот так: Код (Text): .code ; Const Data MyServName db SERVICE_NAME aslashname db APP_SYMLINK_NAME MyServName_uni dw str_len-2 dw str_len dd offset str str: unicode 0, %DRIVER_REG_PATH,0 str_len equ $-str ;---------------------------------------------------------------------------- ; WDM dynaload (both 9x and NT/XP) ;---------------------------------------------------------------------------- call GetVersion test eax, eax sets [PlatformID] js _w9x ; nt initialization push offset MyServName call UnloadDriverNT ; just for sure pushstr SERVICE_DESCRIPTION push offset MyServName pushstr DRIVER_FILE_NAME call LoadDriverNT ; стандартная загрузка NT-драйвера ч/з SCM test eax, eax jnz load_drv err_drv: FatalMes 'Loading Driver Failed!' _w9x: ; w9x initialization call Get_VxDCall push offset MyServName pushstr DRIVER_FILE_NAME call LoadDriver9x перемещаем unicode-строку с реестровым путем драйвера в System Area, иначе (с большой долей вероятности) можно нарваться на случайные глюки. Heil 9x! ;) xor eax, eax inc eax call Ring0_malloc ; shouldn't fail xchg edi, eax mov edx, edi mov eax, (str_len SHL 16) + str_len - 2 stosd lea eax, [edx+8] stosd mov esi, offset str mov ecx, str_len repz movsb ; собственно загрузка драйвера. Обратной функции к сожалению нету, т.к. ; wdm под 9x вообще расчитаны только на стат. загрузку push edx mov edx, esp mov eax, 85h int 2Eh pop edx load_drv: call CreateFileA, offset aslashname, \ GENERIC_READ+GENERIC_WRITE, \ FILE_SHARE_READ+FILE_SHARE_WRITE, \ 0, OPEN_EXISTING, 0, 0 test eax, eax js err_drv mov [drv_handle], eax ... ... дальше обычная работа с драйвером, одинаковая и для NT, и для 9x. Перед завершением ессно надо сделать cleanup -- удалить добавленный в реестр crap и файл драйвера в \System. ... ... (вспом. процедуры) ;------------------------------------------------------------------ ; win9x ring0 memory-allocation routines ;------------------------------------------------------------------ .data? VxDCall_addr dd ? .code Get_VxDCall: pushstr 'kernel32.dll' call LoadLibraryA mov ecx, [eax+3Ch] mov edx, [ecx+eax+78h] add edx, eax mov edx, [edx+1Ch] ; AddressOfFunctions RVA add edx, eax mov edi, [edx] add eax, edi ; eax = VxDCall linaddr mov [VxDCall_addr], eax ret Ring0_malloc: push ebx mov ebx, eax push 8 ; PR_FIXED push eax push 80080000h ;60000h ; PR_SHARED push 10000h ; _PageReserve call [VxDCall_addr] push eax push 60008h ; PC_FIXED + PC_USER + PC_WRITEABLE push 0 push 3 ; PD_FIXEDZERO push ebx ; nPages shr eax, 12 push eax push 10001h call [VxDCall_addr] pop eax pop ebx ret Ring0_free: push 0 push eax push 10002h call [VxDCall_addr] ret Чтобы заставить этот int 2Eh/85h работать, пришлось слегка поковырять ntkern.vxd и разобрать как он их грузит (в основном, почему не грузит ). В первую очередь напоролся на молчаливый отказ в загрузке, если драйвер находится не в \SYSTEM, затем поперли случайные падения при загрузке драйвера -- именно отсюда копирование regpath драйвера в System Area перед вызовом -- иначе бы работало через раз. Насчет ограничений -- n-ое кол-во перезапусков драйвера в принципе мешает только при интенсивной отладке, когда много раз грузишь-отлаживаешь-правишь баги-пересобираешь-по кругу. А так при обычной загрузке проблемы нет -- один раз грузится динамически, затем при повторном запуске проги проверяется, загружен ли уже драйвер, загружен -- значит используем без загрузки. То, что он остается до перезагрузки системы -- вообще фиолетово. В аттаче фрагмент ntkern.vxd, с именами экспортируемых функций -- может пригодиться, чтобы быстро глянуть, поддерживает ли он конкретную функцию или нет.
_BC_ Спасибо! Теперь уже точно разберусь (в общем уже вроде разобрался, ща буду играться с этим всем) Крута Просто интересно было как он работает, вот и поковырял его немножко (как раз аcpi изучал)