Глючит NDIS драйвер после загрузки и до бряков

Тема в разделе "WASM.NT.KERNEL", создана пользователем Nable, 25 окт 2008.

  1. Nable

    Nable New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2008
    Сообщения:
    14
    Подскажите пожалуйста в чем может быть дело. Никак не могу найти ответа или решения.
    Написал драйвер на асме. Под SI все проходит нормально и драйвер вроде как загрузился, но если выйти из SI или вовсе не брякаться, то выпадает странный BSOD. А это притом, что во всех функциях, не попадающих под DriverEntry, стоят бряки, т.е. до них винда не доходит. Драйвер для NDIS'а, поэтому есть предполажение, что до дравака не доходят IRP'ы от NDIS'а, но это только предполажение :)
    Прикрепил скриншот бсода. Могу выложить любую часть кода, скажите только какую :)
    Заранее спасибо!
     
  2. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Bug Check 0x7E: SYSTEM_THREAD_EXCEPTION_NOT_HANDLED
    Необработанное исключение с кодом 0x80000003 - означает, что винда как раз доходит до какого-то бряка, он вызывает исключение (как и положено бряку), и это исключение никто не обрабатывает. (Единственным кандидатом мог бы быть SoftICE, но он не лезет куда не просят - он же не знает о левых int3, которые ставил не он. Кстати, попросить его можно командой "i3here on" либо "i3here drivers").
     
  3. Nable

    Nable New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2008
    Сообщения:
    14
    2diamond: Странно но я только при помощи i3here и перехватывал бряки :)
    Я тут посидел с SI более детально и понял, что у меня не проверялась NdisMRegisterDevice на ошибки, и драйаер продолжал регистрироваться с заранее провальным результатом.
    NdisMRegisterDevice возвращает NDIS_STATUS_NOT_SUPPORTED (0C00000BBh), осталось понять почему...
     
  4. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Видимо, SI не везде способен отловить int3...
    А вообще для анализа подобных вещей есть стандартная техника - ставим Microsoft'овские Debugging Tools ( http://www.microsoft.com/whdc/devtools/debugging/default.mspx ), и аварийный дамп (судя по скриншоту, установлен полный дамп, и сохраняется он в %SystemRoot%\memory.dmp) можно загрузить в kd (консольный вариант, запускать с опцией -z <имя-дампа>) или WinDbg (GUIшный вариант, запускать с опцией -z либо запускать без опций и открывать дамп из меню). После загрузки команда !analyze -v покажет кучу всякой информации о том, где именно и в каком окружении произошёл BSOD.
     
  5. Nable

    Nable New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2008
    Сообщения:
    14
    брр... да вобще мутота выходит :)
    Сижу под отладкой. NdisMRegisterDevice завершается неудачей из-за того, что внутри нее IoGetDriverObjectExtension ничего не возвращает.
    не понятно :dntknw:
     
  6. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Хочется посмотреть на DriverEntry - никакие вызовы ndis-функций инициализации не забыты?
    Кстати, насчёт BSOD'а - если используется fasm, то вряд ли SI отреагирует на int 3 через пробел (aka CD 03 vs int3 = CC), а исключение будет то же самое.
     
  7. calidus

    calidus Member

    Публикаций:
    0
    Регистрация:
    27 дек 2005
    Сообщения:
    618
    Код в студию =)
     
  8. Nable

    Nable New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2008
    Сообщения:
    14
    пользуюсь последним masm'ом

    Прочитал внимательно документацию по NdisMRegisterDevice. Там сказано:
    "NdisMRegisterDevice returns STATUS_SUCCESS if it succeeds, NDIS_STATUS_NOT_SUPPORTED if the caller is not an NDIS miniport driver, or a failure code if it fails."
    А NdisMRegisterDevice вызывался до NdisIMRegisterLayeredMiniport
    Теперь NdisMRegisterDevice выполняется удачно, но на общем фронте нет успеха.

    Вот DriverEntry и используемая в ней функция RegisterVirtualDriver, плюс создание девайсов PtRegisterDevice. Пытаюсь переписать src/network/ndis/passthru из WDK на асм.
    Все вроде почти так как в примере, но из-за неработоспособности онного на асме, немного переделываю.
    Код (Text):
    1. DriverEntry proc DriverObject:PDRIVER_OBJECT, RegistryPath:PUNICODE_STRING
    2.     invoke  DbgPrint, offset MESSAGE_StartDriver
    3.  
    4.     mov eax, DriverObject
    5.         assume eax:PTR DRIVER_OBJECT
    6.     mov     [eax].DriverUnload, offset PtUnload
    7.         assume eax:nothing
    8.  
    9.     invoke  RegisterVirtualDriver, DriverObject, RegistryPath
    10.     ret        
    11. DriverEntry endp
    12.  
    13. RegisterVirtualDriver proc pDriverObject:PDRIVER_OBJECT, pRegistryPath:PUNICODE_STRING
    14.     LOCAL   Status  :NDIS_STATUS                           
    15.     LOCAL   PChars  :NDIS_PROTOCOL_CHARACTERISTICS      
    16.     LOCAL   MChars  :NDIS_MINIPORT_CHARACTERISTICS    
    17.  
    18.     and Status, NDIS_STATUS_SUCCESS
    19.     invoke  NdisAllocateSpinLock, addr GlobalLock
    20.     invoke  NdisMInitializeWrapper, addr NdisWrapperHandle, \
    21.                     pDriverObject,      \
    22.                     pRegistryPath,      \
    23.                     NULL
    24. MainLoop:
    25.     invoke  RtlZeroMemory, addr MChars, \
    26.                    sizeof NDIS_MINIPORT_CHARACTERISTICS
    27.     mov MChars.MajorNdisVersion, 5
    28.            mov  MChars.MinorNdisVersion, 1
    29.  
    30.         mov MChars.InitializeHandler,   offset MPInitialize
    31.         mov MChars.QueryInformationHandler, offset MPQueryInformation
    32.         mov MChars.SetInformationHandler,   offset MPSetInformation
    33.         mov MChars.ResetHandler,        NULL
    34.         mov MChars.TransferDataHandler,     offset MPTransferData
    35.         mov MChars.HaltHandler,         offset MPHalt
    36.            
    37.     .if NDIS51_MINIPORT
    38.            mov  MChars.CancelSendPacketsHandler,offset MPCancelSendPackets
    39.     mov MChars.PnPEventNotifyHandler,   offset MPDevicePnPEvent
    40.     mov     MChars.AdapterShutdownHandler,  offset MPAdapterShutdown
    41.     .endif; NDIS51_MINIPORT
    42.  
    43.     mov MChars.CheckForHangHandler, NULL
    44.     mov     MChars.ReturnPacketHandler, offset MPReturnPacket
    45.  
    46.            mov  MChars.SendHandler,         NULL  ;MPSend;
    47.     mov     MChars.SendPacketsHandler,  offset MPSendPackets
    48.  
    49.         invoke  NdisIMRegisterLayeredMiniport, NdisWrapperHandle,   \
    50.                                                addr MChars,     \
    51.                                                sizeof MChars,       \
    52.                                                addr DriverHandle
    53.     mov Status, eax
    54.     .if Status != NDIS_STATUS_SUCCESS
    55.         jmp EndLoop
    56.     .endif
    57.  
    58.    
    59.         invoke  RtlZeroMemory, addr PChars, \
    60.                    sizeof NDIS_PROTOCOL_CHARACTERISTICS
    61.            mov  PChars.MajorNdisVersion, 5
    62.     mov     PChars.MinorNdisVersion, 1
    63.  
    64.            invoke   NdisInitUnicodeString, addr PChars._Name,   \
    65.                        $CTA0("VOLT_PT")    ; Protocol name
    66.     ;   mov PChars.PName, addr PtName
    67.     mov     PChars.OpenAdapterCompleteHandler, offset PtOpenAdapterComplete
    68.     mov     PChars.CloseAdapterCompleteHandler,offset PtCloseAdapterComplete
    69.     mov     PChars.SendCompleteHandler,    offset PtSendComplete
    70.     mov     PChars.TransferDataCompleteHandler,offset PtTransferDataComplete
    71.    
    72.     mov     PChars.ResetCompleteHandler,       offset PtResetComplete
    73.     mov     PChars.RequestCompleteHandler,     offset PtRequestComplete
    74.     mov     PChars.ReceiveHandler,         offset PtReceive
    75.     mov     PChars.ReceiveCompleteHandler,     offset PtReceiveComplete
    76.     mov     PChars.StatusHandler,          offset PtStatus
    77.     mov     PChars.StatusCompleteHandler,      offset PtStatusComplete
    78.     mov     PChars.BindAdapterHandler,     offset PtBindAdapter
    79.     mov     PChars.UnbindAdapterHandler,       offset PtUnbindAdapter
    80.     mov     PChars.UnloadHandler,          offset PtUnloadProtocol
    81.  
    82.     mov     PChars.ReceivePacketHandler,       offset PtReceivePacket
    83.     mov     PChars.PnPEventHandler,        offset PtPNPHandler
    84.  
    85.         invoke  NdisRegisterProtocol, addr Status,  \
    86.                                   addr ProtHandle,  \
    87.                                       addr PChars,  \
    88.                                   sizeof NDIS_PROTOCOL_CHARACTERISTICS
    89.         .if Status != NDIS_STATUS_SUCCESS
    90.             invoke  NdisIMDeregisterLayeredMiniport, DriverHandle
    91.         jmp EndLoop
    92.     .endif
    93.  
    94.     invoke  NdisIMAssociateMiniport, DriverHandle,  \
    95.                      ProtHandle
    96.     jmp MainLoop
    97. EndLoop:   
    98.     .if Status != NDIS_STATUS_SUCCESS
    99.                        ; Поставил регистрацию девайсов сюда
    100.         invoke  PtRegisterDevice   
    101.         invoke  NdisTerminateWrapper, NdisWrapperHandle,    \
    102.                           NULL
    103.     .endif
    104.     mov eax, Status
    105.     ret
    106. RegisterVirtualDriver endp
    107.  
    108. PtRegisterDevice proc
    109.     LOCAL   Status                    :NDIS_STATUS
    110.     LOCAL   DeviceName                        :UNICODE_STRING        
    111.     LOCAL   DeviceLinkUnicodeString           :UNICODE_STRING        
    112.     LOCAL   DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]  :PDRIVER_DISPATCH      
    113.     mov Status, NDIS_STATUS_SUCCESS
    114.  
    115.     invoke  DbgPrint, $CTA0("++ PtRegisterDriver") 
    116.  
    117.     invoke  NdisAcquireSpinLock, addr GlobalLock
    118.  
    119.     inc MiniportCount
    120.    
    121.     .if MiniportCount == 1
    122. CDS:
    123.         invoke  NdisReleaseSpinLock, addr GlobalLock
    124.         invoke  NdisMSleep, 1
    125.         invoke  NdisAcquireSpinLock, addr GlobalLock
    126.         .if ControlDeviceState != PS_DEVICE_STATE_READY
    127.             jmp CDS
    128.         .endif
    129.  
    130.         mov ControlDeviceState, PS_DEVICE_STATE_CREATING
    131.         invoke  NdisReleaseSpinLock, addr GlobalLock
    132.             invoke  RtlZeroMemory, addr DispatchTable,  \
    133.             (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof PDRIVER_DISPATCH
    134.  
    135.         mov     DispatchTable[IRP_MJ_CREATE],         offset PtDispatch
    136.         mov     DispatchTable[IRP_MJ_CLEANUP],        offset PtDispatch
    137.         mov     DispatchTable[IRP_MJ_CLOSE],          offset PtDispatch
    138.         mov     DispatchTable[IRP_MJ_DEVICE_CONTROL], offset PtDispatch
    139.  
    140.         int 03h
    141.  
    142.         invoke  NdisMRegisterDevice, NdisWrapperHandle,        \
    143.                          addr NTDEVICE_STRING,         \
    144.                          addr LINKNAME_STRING,         \
    145.                          addr DispatchTable,       \
    146.                                  addr ControlDeviceObject,     \
    147.                                  addr NdisDeviceHandle
    148.  
    149.         mov Status, eax
    150.  
    151.         invoke  NdisAcquireSpinLock, addr GlobalLock
    152.         mov     ControlDeviceState, PS_DEVICE_STATE_READY
    153.     .endif
    154.  
    155.     invoke  NdisReleaseSpinLock, addr GlobalLock
    156.  
    157.     invoke  DbgPrint, $CTA0("-- PtRegisterDriver")     
    158.     mov eax, Status
    159.     ret
    160. PtRegisterDevice endp
     
  9. Nable

    Nable New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2008
    Сообщения:
    14
    Так. ну вроде с загрузкой разобрался и она проходит более менее успешно.
    Сейчас работаю над протокольной частью.
    Хотя после загрузки в WinObj при попытке просмотреть свойства девайса - бсод. и драйвер просмотреть нельзя. Думаю в этом виновата протокольная часть, ибо NDIS не доконца проинициализировал драйвер.
    И вот еще. Если трейсить агрузку в отладчике, то все хорошо - DriverEtry завершается успешно, а если без отладки - бсод. Забавно :)
     
  10. Serjb

    Serjb New Member

    Публикаций:
    0
    Регистрация:
    28 окт 2008
    Сообщения:
    5
    Прошу прощения. Смею спросить: а почему Вы игнорируете вызов
    invoke NdisIMAssociateMiniport, DriverHandle, ProtHandle

    в случае удачного завершения
    invoke NdisRegisterProtocol, addr Status, \
    addr ProtHandle, \
    addr PChars, \
    sizeof NDIS_PROTOCOL_CHARACTERISTICS

    в моём IM NDIS, NdisIMAssociateMiniport стоит непосредственно перед "регистрацией девайсов".

    Пишу на С/С++, прошу прощения если неправильно понял Ваш листинг.
     
  11. Serjb

    Serjb New Member

    Публикаций:
    0
    Регистрация:
    28 окт 2008
    Сообщения:
    5
    Ну где мои глаза были. Снимаю свой пост.
     
  12. Serjb

    Serjb New Member

    Публикаций:
    0
    Регистрация:
    28 окт 2008
    Сообщения:
    5
    Вот еще что. Попробуй PtRegisterDevice вызывать в DriverEntry после RegisterVirtualDriver.

    Сталкивался с проблемой когда функция NdisIMRegisterLayeredMiniport не успевала минипорт создать, но статус NDIS_STATUS_SUCCESS возвращала.

    И симптомы похожие, под отладчиком работает иначе вылетает.
     
  13. Nable

    Nable New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2008
    Сообщения:
    14
    Serjb прочитай мой предыдущий пост.
    Что поповоду "не успевает", то где лучше задержку посавить и какую? Перед NdisMRegisterDevice, поставить NdisMSleep(5)??
     
  14. Nable

    Nable New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2008
    Сообщения:
    14
    хм..
    Все регистрируется. Потом NDIS вызывает NetEventBindsComplete. Этого события не было в примере, по советам из MSDN я просто возвращаю NDIS_STATUS_SUCCESS. Все вроде хорошо и никаких бсодов.
    Только вот выгрузка драйвера в KmdManager завершается Fail-Команда неуместна для данной службы. Даже не попадаю на бряк в PtUnload
    Самая главная проблема остается. Не вызываются функции для обработки входящих и исходящих пакетов :dntknw:
     
  15. calidus

    calidus Member

    Публикаций:
    0
    Регистрация:
    27 дек 2005
    Сообщения:
    618
    Nable у тебя аська есть ? =)
     
  16. Serjb

    Serjb New Member

    Публикаций:
    0
    Регистрация:
    28 окт 2008
    Сообщения:
    5
    Nable , вот взгляни может поможет, у меня этот код работает

    ++MiniportCount;

    if (1 == MiniportCount)//MiniportCount
    {

    ControlDeviceState = PS_DEVICE_STATE_CREATING;

    NdisReleaseSpinLock(&g_Data.AdapterListLock);//&GlobalLock

    NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH));

    // Вход для пользовательского режима
    DispatchTable[IRP_MJ_CREATE] = RetOpen; // тут создаем
    DispatchTable[IRP_MJ_CLEANUP] = RetCleanup; // тут их чистим
    DispatchTable[IRP_MJ_CLOSE] = RetClose; // останавливаем захват пакетов
    DispatchTable[IRP_MJ_DEVICE_CONTROL] = RetIoControl; // получам адрес структуры описывающей буферы


    NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING);
    NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING);

    //
    // Регистрим устройство и таблицу DispatchTable точек вместо IoCreateDevice
    //

    Status = NdisMRegisterDevice(
    wrapperHandle,
    &DeviceName,
    &DeviceLinkUnicodeString,
    &DispatchTable[0],
    &ControlDeviceObject,
    &NdisDeviceHandle
    );

    ControlDeviceState = PS_DEVICE_STATE_READY;
    }

    Я сравнил свой код и твой: у меня намного меньше спинлоков. Может проблема в этом.


    теперь относительно "не успевает":

    NdisIMRegisterLayeredMiniport возвращает описатель NdisWrapperHandle практически мгновенно, но после или во время этого еще вызывается MPInitialize из MChars но она вызывается через DCP поэтому может возникнуть ситуация когда NdisWrapperHandle уже есть но структура не заполнена.

    Хотел дать ссылку на статью где это описано, но блин, не нашел. Вот стормозил с ответом, ну ты похоже разобрался сам.
     
  17. Serjb

    Serjb New Member

    Публикаций:
    0
    Регистрация:
    28 окт 2008
    Сообщения:
    5
    Да вот еще, ControlDeviceState это информативная переменная для NDIS а не для тебя, возможно процедура ходит вокруг CDS: ... jmp CDS
     
  18. Nable

    Nable New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2008
    Сообщения:
    14
    С регистрацией все нормально. в CDS не ходит потому что ControlDeviceState изначально PS_DEVICE_STATE_READY=0
    а вот тут интересно. Функция указана и присутствует в MChars, она создана и внутри нее стоит бряк. Но вот она ниразу не вызывалась :dntknw:
     
  19. Nable

    Nable New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2008
    Сообщения:
    14
    Serjb Куда мы смотрели? Вот последовательность действий.
    Код (Text):
    1. 1) During DriverEntry, the Passthru driver registers as a protocol and an Intermediate miniport driver.
    2.  
    3. 2) Later on, NDIS calls Passthru’s BindAdapterHandler, PtBindAdapter, for each underlying NDIS adapter to which it is configured to bind.
    4.  
    5. 3) In the context of BindAdapterHandler and after successfully opening a binding to the underlying adapter, the Passthru driver queries the reserved keyword "UpperBindings" to get a list of device names for the virtual adapters that this particular binding is to expose. Since this driver implements a 1:1 relationship between lower bindings and virtual adapters, this list contains a single name. “Mux” IM drivers that expose multiple virtual adapters over a single underlying adapter will process multiple entries in UpperBindings.
    6.  
    7. 4) For each device name, the Passthru driver calls NdisIMInitializeDeviceInstanceEx.
    8.  
    9. 5) In response, NDIS will eventually call back Passthru miniport’s MiniportInitialize entry point, MPInitialize.
    10.  
    11. ..
    12. 13.4 NDIS calls the Passthru driver’s ProtocolPnPEvent entry point (PtPnPHandler) whenever the underlying adapter is transitioned to a different power state. If the underlying adapter is transitioning to a low power state, the IM driver should wait for all outstanding sends and requests to complete.
    13. ..
    14. и.т.п.
    Так что, если подчиняться этим правилам и все делать как в примере, то второй шаг не выполняется, а после первого иногда выполняется сразу 13.4 :dntknw:
    Тут опять же, функция есть и там бряк.
    DriverEntry завершается успешно, но сразу после этого бсод под отладчиком или просто все виснет. (иногда проскальзывае и попадаю на бряк в PtPnPHandler [13,4])

    Прикрепил бсод и полезный код. Все в архиве
     
  20. Nable

    Nable New Member

    Публикаций:
    0
    Регистрация:
    22 окт 2008
    Сообщения:
    14
    Мдя. Возился с оригинальным примером из WDK. Готовый драйвер с двумя инфами в архиве ./passthru.
    В нем стоят бряки в начале DriverEntry и в PtBindAdapter. NDIS будет вызывать bindAdapter только если драйвер правильно подключить. Например так:
    Код (Text):
    1. Prepare an installation directory that contains these files: netsf.inf, netsf_m.inf, and passthru.sys.
    2. In Control Panel, open Network Connections.
    3. Right-click the relevant Local Area Connection icon and click Properties.
    4. Click Install, click Service, click Add, and then click Have Disk.
    5. Browse to the drive and directory that contain the files from step 1, and then click OK.
    6. Select “Passthru Driver” and click OK. This action should install the Passthru driver.
    7. Click OK or Yes each time the system prompts with a warning regarding installation of unsigned files. This step is necessary because binaries that are generated through the WDK build environment are not signed.
    Через KmdManager NDIS не будет реагировать на новый драйвер.

    Тогда возникает такой вопрос. Можно ли обойтись без использования дополнительных инфов? В документация вот что сказано:
    Код (Text):
    1. Alternate Installation
    2. You can install this sample programmatically by using the INetCfg APIs.
    Может также возможно сделать, чтобы драйвер не светился в свойствах сетевого подключения адаптера и диспетчере устройств?