Re: серийный номер usb-устройства
От: dimb82  
Дата: 03.07.10 08:53
Оценка: 5 (1)
Здравствуйте, Аноним, Вы писали:

А>Подскажите, как в файловом фильтре, например при обработке IRP_MJ_CREATE определить серийник флешки подключенной через usb, к которой происходит обращение ?

А>Спасибо.

Как определить в IRP_MJ_CREATE не скажу. Да и надо ли каждый раз делать это при обработке каждого IRP_MJ_CREATE? Не проще ли сделать это в момент IRP_MN_MOUNT_VOLUME, а потом просто сохранить полученный серийный номер в своём deviceExtension?

Если я не ошибаюсь, то обычно InstanceId у device object, созданного драйвером USBSTOR, совпадает с серийным номером флэшки. То есть нужно получить этот самый device object, а потом узнать его InstanceId.

Когда приходит пакет IRP_MN_MOUNT_VOLUME, то можно получить device object тома:

storageStackDeviceObject = irpSp->Parameters.MountVolume.Vpb->RealDevice;


Теперь нужно выцепить из этого объекта другой device object, созданный драйвером USBSTOR. Вот примерный код для этого:

PDEVICE_OBJECT FilterGetDiskObject(PDEVICE_OBJECT pVolumeObject)
{
    KEVENT    waitEvent;
    PIRP    pNewIrp;
    NTSTATUS    status;
    PVOLUME_DISK_EXTENTS    pVolumeExtents;
    UNICODE_STRING    strDeviceName;
    IO_STATUS_BLOCK    IoStatus;
    PIO_STACK_LOCATION    pStackLocation;
    PFILE_OBJECT    pFileObject;
    PDEVICE_OBJECT    pDeviceObject;
    PDEVICE_OBJECT    pLowerDevice;
    wchar_t    data[25];

    KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);
    pVolumeExtents = (PVOLUME_DISK_EXTENTS) ExAllocatePoolWithTag(NonPagedPool, sizeof(VOLUME_DISK_EXTENTS), 'USBL');

    pNewIrp = IoBuildDeviceIoControlRequest(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
        pVolumeObject, NULL, 0, (PVOID) pVolumeExtents, sizeof(VOLUME_DISK_EXTENTS),
        FALSE, &waitEvent, &IoStatus);

    if (!pNewIrp)
    {
        ExFreePool(pVolumeExtents);
        return NULL;
    }

    // send this irp to the storage device
    pStackLocation = IoGetNextIrpStackLocation(pNewIrp);
    status = IoCallDriver(pVolumeObject, pNewIrp);

    if (status == STATUS_PENDING)
    {
        status = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL);
        status = IoStatus.Status;
    }

    if (!NT_SUCCESS(status))
    {
        ExFreePool(pVolumeExtents);
        return NULL;
    }

    swprintf(data, L"\\GLOBAL??\\PhysicalDrive%d", pVolumeExtents->Extents[0].DiskNumber);
    RtlInitUnicodeString(&strDeviceName, data); 
    ExFreePool(pVolumeExtents);

    pDeviceObject = NULL;
    IoGetDeviceObjectPointer(&strDeviceName, 0, &pFileObject, &pDeviceObject);

    if (pDeviceObject == NULL)
        return NULL;

    pLowerDevice = IoGetDeviceAttachmentBaseRef(pDeviceObject);
    ObDereferenceObject(pFileObject);

    return pLowerDevice;
}


Не забудьте потом вызвать ObDereferenceObject, когда полученный объект больше не будет нужен.
Потом надо убедиться, что это USB-устройство. Сделать это можно примерно так:

BOOLEAN IsUSBDevice(PDEVICE_OBJECT PDO)
{
    NTSTATUS    status;
    GUID        busGuid;
    WCHAR        wszEnumerator[30];
    DEVICE_REMOVAL_POLICY    removePolicy = (DEVICE_REMOVAL_POLICY) 0;
    ULONG        retLength;

    if (PDO == NULL)
        return FALSE;

    status = IoGetDeviceProperty(PDO, DevicePropertyBusTypeGuid, 16, &busGuid, &retLength);
    if (status == STATUS_SUCCESS)
    {
        GUID    usbGuid = GUID_BUS_TYPE_USB;

        if (memcmp(&busGuid, &usbGuid, sizeof(GUID)) == 0)
            return TRUE;
    }

    status = IoGetDeviceProperty(PDO, DevicePropertyEnumeratorName, 30, wszEnumerator, &retLength);
    if (status == STATUS_SUCCESS)
    {
        if (wszEnumerator[0] == L'U' &&
            wszEnumerator[1] == L'S' &&
            wszEnumerator[2] == L'B')
            return TRUE;
    }

    status = IoGetDeviceProperty(PDO, DevicePropertyRemovalPolicy, sizeof(DEVICE_REMOVAL_POLICY), 
        &removePolicy, &retLength);

    if (status == STATUS_SUCCESS)
    {
        if (removePolicy == 0 || removePolicy == 1)
            return FALSE;

        return TRUE;
    }

    return FALSE;
}


Тут три проверки. Первую проверку можно убрать, так как сейчас USBSTOR не поддерживает запрос на DevicePropertyBusTypeGuid. У меня, по крайней мере, ни разу не получалось его выполнить с успехом для USB-дисков. Обычно срабатывает вторая проверка. Но нужно иметь в виду, что проверка довольно грубая. Третья проверка на то, является ли устройство Removable. Я не уверен, что проверка на 100% точная.

Теперь надо получить InstanceId. Кода для этого я тут не приведу. Но можно попробовать послать устройству пакет IRP_MN_QUERY_ID/BusQueryInstanceID.

Надеюсь, местные гуру поправят или уточнят меня, если я где-то ошибаюсь.
серийный номер usb-устройства
От: Аноним  
Дата: 02.07.10 17:43
Оценка:
Подскажите, как в файловом фильтре, например при обработке IRP_MJ_CREATE определить серийник флешки подключенной через usb, к которой происходит обращение ?
Спасибо.
Re: серийный номер usb-устройства
От: Аноним  
Дата: 08.07.10 13:46
Оценка:
выяснил что серийник хранится в USB_StringDescriptor
каким образом можно этот USB_StringDescriptor получить ?
Re: серийный номер usb-устройства
От: Alexey Frolov Беларусь  
Дата: 08.07.10 16:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Подскажите, как в файловом фильтре, например при обработке IRP_MJ_CREATE определить серийник флешки подключенной через usb, к которой происходит обращение ?

А>Спасибо.

а у вас фильтр или минифильтр? правильно вам посоветовали что это надо делать не в IRP_MJ_CREATE
в минифильтре — InstanceSetup
в фильтре — смотри выше

параметры можно получить запросом

IoBuildDeviceIoControlRequest(IOCTL_STORAGE_QUERY_PROPERTY...)


typedef struct _STORAGE_DEVICE_DESCRIPTOR {

    ULONG Version;
    ULONG Size;
    UCHAR DeviceType;
    UCHAR DeviceTypeModifier;
    BOOLEAN RemovableMedia;
    BOOLEAN CommandQueueing;
    ULONG VendorIdOffset;
    ULONG ProductIdOffset;
    ULONG ProductRevisionOffset;
    ULONG SerialNumberOffset;
    STORAGE_BUS_TYPE BusType;
    ULONG RawPropertiesLength;
    UCHAR RawDeviceProperties[1];

} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;
Re[2]: серийный номер usb-устройства
От: Аноним  
Дата: 09.07.10 04:43
Оценка:
Здравствуйте, Alexey Frolov, Вы писали:

AF>а у вас фильтр или минифильтр? правильно вам посоветовали что это надо делать не в IRP_MJ_CREATE

у меня фильтр. вернее два фильтра — один файловый, второй wdm.
с файловым, спасибо, ясно.
а как быть с wdm фильтром ? т.е. нужно получать серийник для любого подключаемого usb устройства.
это надо делать в AddDevice или в обработчике IRP_MN_START_DEVICE ?
и как в этом случае получить USB_StringDescriptor ?
Re[3]: серийный номер usb-устройства
От: Alexey Frolov Беларусь  
Дата: 09.07.10 09:28
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Alexey Frolov, Вы писали:


AF>>а у вас фильтр или минифильтр? правильно вам посоветовали что это надо делать не в IRP_MJ_CREATE

А>у меня фильтр. вернее два фильтра — один файловый, второй wdm.
А>с файловым, спасибо, ясно.
А>а как быть с wdm фильтром ? т.е. нужно получать серийник для любого подключаемого usb устройства.
А>это надо делать в AddDevice или в обработчике IRP_MN_START_DEVICE ?
А>и как в этом случае получить USB_StringDescriptor ?

Я бы делал в AddDevice, можно отправить запрос IOCTL_INTERNAL_USB_SUBMIT_URB (URB_CONTROL_DESCRIPTOR_REQUEST)
получить USB_DEVICE_DESCRIPTOR и оттуда серийник, как отправить запрос — пройдитесь поиском по форуму по IOCTL_INTERNAL_USB_SUBMIT_URB
Re[3]: серийный номер usb-устройства
От: dimb82  
Дата: 09.07.10 09:43
Оценка:
Здравствуйте, Аноним, Вы писали:

А>а как быть с wdm фильтром ? т.е. нужно получать серийник для любого подключаемого usb устройства.

А>это надо делать в AddDevice или в обработчике IRP_MN_START_DEVICE ?
А>и как в этом случае получить USB_StringDescriptor ?

А можно поинтересоваться, как ваш фильтр будет подключаться ко всем подключаемым USB-устройствам?
Re[4]: серийный номер usb-устройства
От: Аноним  
Дата: 09.07.10 10:59
Оценка:
Здравствуйте, Alexey Frolov, Вы писали:

AF>Я бы делал в AddDevice, можно отправить запрос IOCTL_INTERNAL_USB_SUBMIT_URB (URB_CONTROL_DESCRIPTOR_REQUEST)

AF>получить USB_DEVICE_DESCRIPTOR и оттуда серийник, как отправить запрос — пройдитесь поиском по форуму по IOCTL_INTERNAL_USB_SUBMIT_URB

в USB_DEVICE_DESCRIPTOR не серийник, а индекс строки содержащей серийник в USB_StringDescriptor
для нее наверное надо запросить USB_STRING_DESCRIPTOR_TYPE. попробую
Re[4]: серийный номер usb-устройства
От: Аноним  
Дата: 09.07.10 12:26
Оценка:
Здравствуйте, dimb82, Вы писали:

D>А можно поинтересоваться, как ваш фильтр будет подключаться ко всем подключаемым USB-устройствам?


я его прописываю как нижний фильтр для класса usb
Re[5]: серийный номер usb-устройства
От: dimb82  
Дата: 09.07.10 12:43
Оценка:
D>>А можно поинтересоваться, как ваш фильтр будет подключаться ко всем подключаемым USB-устройствам?
А>я его прописываю как нижний фильтр для класса usb

Это который Universal Serial Bus controllers? А такой фильтр цепляется к устройствам отличным от USB хост-контроллера? Или ко всем child PDO тоже цепляется?
Re[5]: серийный номер usb-устройства
От: Alexey Frolov Беларусь  
Дата: 09.07.10 14:34
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Alexey Frolov, Вы писали:


AF>>Я бы делал в AddDevice, можно отправить запрос IOCTL_INTERNAL_USB_SUBMIT_URB (URB_CONTROL_DESCRIPTOR_REQUEST)

AF>>получить USB_DEVICE_DESCRIPTOR и оттуда серийник, как отправить запрос — пройдитесь поиском по форуму по IOCTL_INTERNAL_USB_SUBMIT_URB

А>в USB_DEVICE_DESCRIPTOR не серийник, а индекс строки содержащей серийник в USB_StringDescriptor

А>для нее наверное надо запросить USB_STRING_DESCRIPTOR_TYPE. попробую

да, совершенно верно, вторым запросом получите USB_STRING_DESCRIPTOR c нужным индексом
Re[5]: серийный номер usb-устройства
От: _f_b_i_  
Дата: 09.07.10 20:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, dimb82, Вы писали:


D>>А можно поинтересоваться, как ваш фильтр будет подключаться ко всем подключаемым USB-устройствам?


А>я его прописываю как нижний фильтр для класса usb


не будет работать для некотрых USB устройств типа images/web_video — хотя они чистые USB.
Re[6]: серийный номер usb-устройства
От: Аноним  
Дата: 12.07.10 04:47
Оценка:
Здравствуйте, Alexey Frolov, Вы писали:


А>>в USB_DEVICE_DESCRIPTOR не серийник, а индекс строки содержащей серийник в USB_StringDescriptor

А>>для нее наверное надо запросить USB_STRING_DESCRIPTOR_TYPE. попробую

AF>да, совершенно верно, вторым запросом получите USB_STRING_DESCRIPTOR c нужным индексом


не получается. пробовал для флешки.
получаю USB_DEVICE_DESCRIPTOR в нем iSerialNumber = 0 (продукт и вендор ид правильные)
получаю USB_STRING_DESCRIPTOR, ошибок нет, но ничего похожего на серийник не видно, сравнивал со строкой из диспетчера устройств->контроллеры usb->запоминающие устройство для usb->свойства->сведения->код экземпляра (у меня там usb\vid_0457&pid_0151\c950d47504e28e)
первый байт USB_STRING_DESCRIPTOR — длина (у меня 4), второй — тип (у меня 3), дальше должен идти серийник, но его там нет.
в чем может быть дело ?
Re[7]: серийный номер usb-устройства
От: Alexey Frolov Беларусь  
Дата: 12.07.10 14:24
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Alexey Frolov, Вы писали:



А>>>в USB_DEVICE_DESCRIPTOR не серийник, а индекс строки содержащей серийник в USB_StringDescriptor

А>>>для нее наверное надо запросить USB_STRING_DESCRIPTOR_TYPE. попробую

AF>>да, совершенно верно, вторым запросом получите USB_STRING_DESCRIPTOR c нужным индексом


А>не получается. пробовал для флешки.

А>получаю USB_DEVICE_DESCRIPTOR в нем iSerialNumber = 0 (продукт и вендор ид правильные)
А>получаю USB_STRING_DESCRIPTOR, ошибок нет, но ничего похожего на серийник не видно, сравнивал со строкой из диспетчера устройств->контроллеры usb->запоминающие устройство для usb->свойства->сведения->код экземпляра (у меня там usb\vid_0457&pid_0151\c950d47504e28e)
А>первый байт USB_STRING_DESCRIPTOR — длина (у меня 4), второй — тип (у меня 3), дальше должен идти серийник, но его там нет.
А>в чем может быть дело ?

сходу не скажу, может код покажете?
Re[8]: серийный номер usb-устройства
От: Аноним  
Дата: 12.07.10 14:56
Оценка:
Здравствуйте, Alexey Frolov, Вы писали:

AF>сходу не скажу, может код покажете?



NTSTATUS SendAwaitUrb(PDEVICE_OBJECT fido, PURB pUrb)
{
    KEVENT event;
    PIRP pIrp = NULL;
    IO_STATUS_BLOCK ioStatus;
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION nextStack = NULL;
    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;

    KeInitializeEvent(&event, NotificationEvent, FALSE);
    pIrp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
                     pdx->NextLowerDriver,
                     NULL,
                     0,
                     NULL,
                     0,
                     TRUE,
                     &event,
                     &ioStatus); 

    if (NULL == pIrp)
    {
        status = ioStatus.Status;
        goto exit;
    }

    nextStack = IoGetNextIrpStackLocation(pIrp);
    nextStack->Parameters.Others.Argument1 = pUrb;
    status = IoCallDriver(pdx->NextLowerDriver, pIrp);

    if (STATUS_PENDING == status)
    {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = ioStatus.Status;
    }

exit:
    return status;
}



    URB urb1, urb2;
    USB_DEVICE_DESCRIPTOR dd = {0};
    USB_STRING_DESCRIPTOR sd = {0};
    NTSTATUS status = STATUS_SUCCESS;
    USBD_STATUS ustatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION pdx = fido->DeviceExtension;

    UsbBuildGetDescriptorRequest(&urb1,
                 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                 USB_DEVICE_DESCRIPTOR_TYPE,
                 0,
                 0,
                 &dd,
                 NULL,
                 sizeof(USB_DEVICE_DESCRIPTOR),
                 NULL);

    status = SendAwaitUrb(fido, &urb1);
    if (STATUS_SUCCESS != status)
        goto exit;

    pdx->idVendor = dd.idVendor;
    pdx->idProduct = dd.idProduct;

    UsbBuildGetDescriptorRequest(&urb2,
                 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                 USB_STRING_DESCRIPTOR_TYPE,
                 0,
                 0,
                 &sd,
                 NULL,
                 sizeof(USB_STRING_DESCRIPTOR),
                 NULL);

    status = SendAwaitUrb(fido, &urb2);
    if (STATUS_SUCCESS != status)
        goto exit;
Re[9]: серийный номер usb-устройства
От: Alexey Frolov Беларусь  
Дата: 12.07.10 15:42
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Alexey Frolov, Вы писали:


AF>>сходу не скажу, может код покажете?



А>
А>    URB urb1, urb2;
А>    USB_DEVICE_DESCRIPTOR dd = {0};
А>    USB_STRING_DESCRIPTOR sd = {0};
А>    NTSTATUS status = STATUS_SUCCESS;
А>    USBD_STATUS ustatus = STATUS_SUCCESS;
А>    PDEVICE_EXTENSION pdx = fido->DeviceExtension;

А>    UsbBuildGetDescriptorRequest(&urb1,
А>                 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
А>                 USB_DEVICE_DESCRIPTOR_TYPE,
А>                 0,
А>                 0,
А>                 &dd,
А>                 NULL,
А>                 sizeof(USB_DEVICE_DESCRIPTOR),
А>                 NULL);

А>    status = SendAwaitUrb(fido, &urb1);
А>    if (STATUS_SUCCESS != status)
А>        goto exit;

    pdx->>idVendor = dd.idVendor;
    pdx->>idProduct = dd.idProduct;

А>    UsbBuildGetDescriptorRequest(&urb2,
А>                 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
А>                 USB_STRING_DESCRIPTOR_TYPE,
А>                 0,
А>                 0,
А>                 &sd,
А>                 NULL,
А>                 sizeof(USB_STRING_DESCRIPTOR),
А>                 NULL);

А>    status = SendAwaitUrb(fido, &urb2);
А>    if (STATUS_SUCCESS != status) // неужели здесь все нормально?
А>        goto exit;
А>


typedef struct _USB_STRING_DESCRIPTOR {
  UCHAR  bLength ;
  UCHAR  bDescriptorType ;
  WCHAR  bString[1] ;
} USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR

Members
bLength 
Specifies the length, in bytes, of the descriptor. 
bDescriptorType 
Specifies the descriptor type. Must always be USB_STRING_DESCRIPTOR_TYPE. 
bString 
Pointer to a client-allocated buffer that contains, on return from the host controller driver, a Unicode string with the requested string descriptor.


по идее первый символ серийника сюда влезет, но не факт что железка его вернет, скорее всего в статусе получите что буфер маленький
вам нужно выделить буфер под строку побольше, если слепить на коленке то что то вроде


        struct USB_STRING_DESCRIPTOR_FIXED_64 {
          UCHAR  bLength ;
          UCHAR  bDescriptorType ;
          WCHAR  bString[64] ;
        } sd64;

    UsbBuildGetDescriptorRequest(&urb2,
                 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                 USB_STRING_DESCRIPTOR_TYPE,
                 0,
                 0,
                 &sd64,
                 NULL,
                 sizeof(USB_STRING_DESCRIPTOR_FIXED_64),
                 NULL);


но я рекомендовал бы сделать по-нормальному
Re[7]: серийный номер usb-устройства
От: _f_b_i_  
Дата: 12.07.10 20:24
Оценка:
Здравствуйте, Аноним, Вы писали:

А>первый байт USB_STRING_DESCRIPTOR — длина (у меня 4), второй — тип (у меня 3), дальше должен идти серийник, но его там нет.

А>в чем может быть дело ?

Читаем заголовок дискриптора (index = 0, type = 03, langid = 0)
04 — bLength
03 — bDescriptorType

Дальше вычитываем весь дискриптор полностью — устройство должно предложить набор поддерживаемых языков

04 — bLength
03 — bDescriptorType
04 09 — wLangId (English)
могут быть еще, но длина будет другой

дальше вычитываем дискриптор на выбранном языке (index = 0, type = 03, langid = 0х0409)
22 — bLength
03 — bDescriptorType

ну дальше читаем весь дискриптор польностью.

Приблизительно такой алгоритм вычитывания стринг дискринтора.
Вообще можно взять любой USB монитор и посмотреть как usbstor.sys вычитывает дискриптор флешки.
Re[8]: серийный номер usb-устройства
От: Аноним  
Дата: 13.07.10 04:25
Оценка:
Здравствуйте, _f_b_i_, Вы писали:

___>Дальше вычитываем весь дискриптор полностью — устройство должно предложить набор поддерживаемых языков


___>04 — bLength

___>03 — bDescriptorType
___>04 09 — wLangId (English)
___>могут быть еще, но длина будет другой

___>дальше вычитываем дискриптор на выбранном языке (index = 0, type = 03, langid = 0х0409)

___>22 — bLength
___>03 — bDescriptorType

___>ну дальше читаем весь дискриптор польностью.


что значит "вычитываем" ?
это новый запрос надо послать ? как он формируется ? как узнать, что еще не все данные прочитаны ?
у меня все вызовы возвращают 0, т.е. никто не говорит, что буфер слишком мал
Re[9]: серийный номер usb-устройства
От: _f_b_i_  
Дата: 13.07.10 05:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, _f_b_i_, Вы писали:


___>>ну дальше читаем весь дискриптор польностью.


А>что значит "вычитываем" ?


Вычитываем значит что читаем дискриптор (как и любой другой дискриптор USB устройства за два этапа)

1-й этап выделяем память и читаем заголовок USB_STRING_DESCRIPTOR, причем index дискриптора всегда = 0

UCHAR bLength ;
UCHAR bDescriptorType ;

2-й этап выделяем столько памяти сколько вернулось в bLength и читаем еще раз.
После этого получаем массив языков стринговые дискрипторы которых будут возвращатся устройством.

3-й этап выбираем нужный язык и читаем стринговый дискриптор еще раз. При этом index дискриптора берем из USB_DEVICE_DESCRIPTOR,
а LangId заполняем значением (значениями) который получили на этапе 2.

4-й этап выделяем память в bLength байт и читаем дискриптор польностью. На этот раз получишь тот дискриптор который нужен.
Re[10]: серийный номер usb-устройства
От: Аноним  
Дата: 13.07.10 06:52
Оценка:
Здравствуйте, _f_b_i_, Вы писали:

извиняюсь не понял.
первый раз я передаю в качестве буфера USB_STRING_DESCRIPTOR sd = {0}
получаю:
db sd
04 03 09 04 ...
т.е. длина 4 байта 4, но sizeof(sd) тоже равен 4 байта
если теперь в качестве буфера передать sd заполненный на первом вызове (т.е. с установленным langid), то ни чего не меняется
причем iSerialNumber у меня равен 0
т.е. мне нужен первый элемент массива стринг дескрипторов ?
Re[11]: серийный номер usb-устройства
От: Аноним  
Дата: 13.07.10 07:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, _f_b_i_, Вы писали:


почти разобрался, теперь дескриптор получаю, но не могу предварительно получить его длину
1. index=0, langid=0, в качестве буфера &sd
получаю length = 4, lengid = 0x409
2. index=0, langid=0x409, в качестве буфера &sd
получаю length = 4, lengid = 0x409
3. index=0, langid=0x409, в качестве буфера 108 байт
получаю серийник
Re[12]: серийный номер usb-устройства
От: _f_b_i_  
Дата: 13.07.10 07:51
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, _f_b_i_, Вы писали:


А>почти разобрался, теперь дескриптор получаю, но не могу предварительно получить его длину

А>1. index=0, langid=0, в качестве буфера &sd
А>получаю length = 4, lengid = 0x409
А>2. index=0, langid=0x409, в качестве буфера &sd
А>получаю length = 4, lengid = 0x409
А>3. index=0, langid=0x409, в качестве буфера 108 байт
А>получаю серийник

Гы... в качестве буфера &sd можно использовать ТОЛЬКО для вычитывания заголовка и все.

Тоесть:

1. index=0, langid=0, size = sizeof (sd) минус вот тот WCHAR[1], buf = &sd; В результате 04 03
2. index=0, langid=0, size = bLength, buf = ExAllocatePool(); В результате 04 03 04 09
3
. index=0х0409, langid=из дискриптора, size = sizeof (sd) — WCHAR[1], buf = &sd; 6с 03 (тут должны быть твои 108 байт)
4. index=0х0409, langid=из дискриптора, size = bLength, buf = ExAllocatePool(); В результате 6с 03 .. .. ..

Длину получаешь на шаге 1, 3, и.т.д.
Re[13]: серийный номер usb-устройства
От: _f_b_i_  
Дата: 13.07.10 08:01
Оценка:
Здравствуйте, _f_b_i_, Вы писали:

___>Тоесть:


___>1. index=0, langid=0, size = sizeof (sd) минус вот тот WCHAR[1], buf = &sd; В результате 04 03

___>2. index=0, langid=0, size = bLength, buf = ExAllocatePool(); В результате 04 03 04 09
___>3. index=0х0409, langid=из дискриптора, size = sizeof (sd) — WCHAR[1], buf = &sd; 6с 03 (тут должны быть твои 108 байт)
___>4. index=0х0409, langid=из дискриптора, size = bLength, buf = ExAllocatePool(); В результате 6с 03 .. .. ..

Опечатался.. конечно же

index=из дискриптора, langid=0х0409

Кстати, строго говоря не у каждого девайса есть серийный номер. Если в дискрипторе устройства записан нолик, то серийника нет.

И еще раз, чтобы лучше понять как все происходит, советую поставить какой то USB Monitor и посмотреть в живую на поряток отправки URB запросов к девайсу
по время вычитывания String дискрипторов.
Re[2]: серийный номер usb-устройства
От: Аноним  
Дата: 19.12.11 13:51
Оценка:
Здравствуйте, dimb82, Вы писали:

Я все сделал как Вы описали но почемуто у меня серийник = 0
Серийник у флешки точно есть.
Проблема получить из драйвера файловой системи. Из под драйвера USB я получаю серийник безпроблем.
Уже бьюсь 2 недели ничего не получается.
Может подскажете вчем может быть проблема?




D>Здравствуйте, Аноним, Вы писали:


А>>Подскажите, как в файловом фильтре, например при обработке IRP_MJ_CREATE определить серийник флешки подключенной через usb, к которой происходит обращение ?

А>>Спасибо.

D>Как определить в IRP_MJ_CREATE не скажу. Да и надо ли каждый раз делать это при обработке каждого IRP_MJ_CREATE? Не проще ли сделать это в момент IRP_MN_MOUNT_VOLUME, а потом просто сохранить полученный серийный номер в своём deviceExtension?


D>Если я не ошибаюсь, то обычно InstanceId у device object, созданного драйвером USBSTOR, совпадает с серийным номером флэшки. То есть нужно получить этот самый device object, а потом узнать его InstanceId.


D>Когда приходит пакет IRP_MN_MOUNT_VOLUME, то можно получить device object тома:


D>
D>storageStackDeviceObject = irpSp->Parameters.MountVolume.Vpb->RealDevice;
D>


D>Теперь нужно выцепить из этого объекта другой device object, созданный драйвером USBSTOR. Вот примерный код для этого:


D>
D>PDEVICE_OBJECT FilterGetDiskObject(PDEVICE_OBJECT pVolumeObject)
D>{
D>    KEVENT    waitEvent;
D>    PIRP    pNewIrp;
D>    NTSTATUS    status;
D>    PVOLUME_DISK_EXTENTS    pVolumeExtents;
D>    UNICODE_STRING    strDeviceName;
D>    IO_STATUS_BLOCK    IoStatus;
D>    PIO_STACK_LOCATION    pStackLocation;
D>    PFILE_OBJECT    pFileObject;
D>    PDEVICE_OBJECT    pDeviceObject;
D>    PDEVICE_OBJECT    pLowerDevice;
D>    wchar_t    data[25];

D>    KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);
D>    pVolumeExtents = (PVOLUME_DISK_EXTENTS) ExAllocatePoolWithTag(NonPagedPool, sizeof(VOLUME_DISK_EXTENTS), 'USBL');

D>    pNewIrp = IoBuildDeviceIoControlRequest(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
D>        pVolumeObject, NULL, 0, (PVOID) pVolumeExtents, sizeof(VOLUME_DISK_EXTENTS),
D>        FALSE, &waitEvent, &IoStatus);

D>    if (!pNewIrp)
D>    {
D>        ExFreePool(pVolumeExtents);
D>        return NULL;
D>    }

D>    // send this irp to the storage device
D>    pStackLocation = IoGetNextIrpStackLocation(pNewIrp);
D>    status = IoCallDriver(pVolumeObject, pNewIrp);

D>    if (status == STATUS_PENDING)
D>    {
D>        status = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL);
D>        status = IoStatus.Status;
D>    }

D>    if (!NT_SUCCESS(status))
D>    {
D>        ExFreePool(pVolumeExtents);
D>        return NULL;
D>    }

D>    swprintf(data, L"\\GLOBAL??\\PhysicalDrive%d", pVolumeExtents->Extents[0].DiskNumber);
D>    RtlInitUnicodeString(&strDeviceName, data); 
D>    ExFreePool(pVolumeExtents);

D>    pDeviceObject = NULL;
D>    IoGetDeviceObjectPointer(&strDeviceName, 0, &pFileObject, &pDeviceObject);

D>    if (pDeviceObject == NULL)
D>        return NULL;

D>    pLowerDevice = IoGetDeviceAttachmentBaseRef(pDeviceObject);
D>    ObDereferenceObject(pFileObject);

D>    return pLowerDevice;
D>}

D>


D>Не забудьте потом вызвать ObDereferenceObject, когда полученный объект больше не будет нужен.

D>Потом надо убедиться, что это USB-устройство. Сделать это можно примерно так:

D>
D>BOOLEAN IsUSBDevice(PDEVICE_OBJECT PDO)
D>{
D>    NTSTATUS    status;
D>    GUID        busGuid;
D>    WCHAR        wszEnumerator[30];
D>    DEVICE_REMOVAL_POLICY    removePolicy = (DEVICE_REMOVAL_POLICY) 0;
D>    ULONG        retLength;

D>    if (PDO == NULL)
D>        return FALSE;

D>    status = IoGetDeviceProperty(PDO, DevicePropertyBusTypeGuid, 16, &busGuid, &retLength);
D>    if (status == STATUS_SUCCESS)
D>    {
D>        GUID    usbGuid = GUID_BUS_TYPE_USB;

D>        if (memcmp(&busGuid, &usbGuid, sizeof(GUID)) == 0)
D>            return TRUE;
D>    }

D>    status = IoGetDeviceProperty(PDO, DevicePropertyEnumeratorName, 30, wszEnumerator, &retLength);
D>    if (status == STATUS_SUCCESS)
D>    {
D>        if (wszEnumerator[0] == L'U' &&
D>            wszEnumerator[1] == L'S' &&
D>            wszEnumerator[2] == L'B')
D>            return TRUE;
D>    }

D>    status = IoGetDeviceProperty(PDO, DevicePropertyRemovalPolicy, sizeof(DEVICE_REMOVAL_POLICY), 
D>        &removePolicy, &retLength);

D>    if (status == STATUS_SUCCESS)
D>    {
D>        if (removePolicy == 0 || removePolicy == 1)
D>            return FALSE;

D>        return TRUE;
D>    }

D>    return FALSE;
D>}

D>


D>Тут три проверки. Первую проверку можно убрать, так как сейчас USBSTOR не поддерживает запрос на DevicePropertyBusTypeGuid. У меня, по крайней мере, ни разу не получалось его выполнить с успехом для USB-дисков. Обычно срабатывает вторая проверка. Но нужно иметь в виду, что проверка довольно грубая. Третья проверка на то, является ли устройство Removable. Я не уверен, что проверка на 100% точная.


D>Теперь надо получить InstanceId. Кода для этого я тут не приведу. Но можно попробовать послать устройству пакет IRP_MN_QUERY_ID/BusQueryInstanceID.


D>Надеюсь, местные гуру поправят или уточнят меня, если я где-то ошибаюсь.
Re[3]: серийный номер usb-устройства
От: dimb82  
Дата: 19.12.11 16:46
Оценка:
Что именно не получается? На каком этапе получаете ошибку?


А>Я все сделал как Вы описали но почемуто у меня серийник = 0

А>Серийник у флешки точно есть.
А>Проблема получить из драйвера файловой системи. Из под драйвера USB я получаю серийник безпроблем.
А>Уже бьюсь 2 недели ничего не получается.
А>Может подскажете вчем может быть проблема?
Re[4]: серийный номер usb-устройства
От: dvasya  
Дата: 20.12.11 07:19
Оценка:
Здравствуйте, dimb82, Вы писали:

D>Что именно не получается? На каком этапе получаете ошибку?


Вот привожу код

Не получается сделать запрос USB — устройству

...
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FSControl;
...

NTSTATUS FSControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
...
        CurrentStackLocation = IoGetCurrentIrpStackLocation(Irp);
        ASSERT(CurrentStackLocation);        

        DeviceExtension = (PFSOBSRVDEVICEEXTENSION)(DeviceObject->DeviceExtension);

        if (CurrentStackLocation->MinorFunction == IRP_MN_MOUNT_VOLUME)
        {
            if(IsUSBDevice(CurrentStackLocation->Parameters.MountVolume.Vpb->RealDevice))
            {                
                GetDeviceSeriallNumber(DeviceExtension, FilterGetDiskObject(CurrentStackLocation->Parameters.MountVolume.Vpb->RealDevice));                    
            }
        }
...
}

PDEVICE_OBJECT FilterGetDiskObject(PDEVICE_OBJECT pVolumeObject)
{
    KEVENT    waitEvent;
    PIRP    pNewIrp;
    NTSTATUS    status;
    PVOLUME_DISK_EXTENTS    pVolumeExtents;
    UNICODE_STRING    strDeviceName;
    IO_STATUS_BLOCK    IoStatus;
    PIO_STACK_LOCATION    pStackLocation;
    PFILE_OBJECT    pFileObject;
    PDEVICE_OBJECT    pDeviceObject;
    PDEVICE_OBJECT    pLowerDevice;
    wchar_t    data[25];

    KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);
    pVolumeExtents = (PVOLUME_DISK_EXTENTS) ExAllocatePoolWithTag(NonPagedPool, sizeof(VOLUME_DISK_EXTENTS), 'USBL');

    pNewIrp = IoBuildDeviceIoControlRequest(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
        pVolumeObject, NULL, 0, (PVOID) pVolumeExtents, sizeof(VOLUME_DISK_EXTENTS),
        FALSE, &waitEvent, &IoStatus);

    if (!pNewIrp)
    {
        ExFreePool(pVolumeExtents);
        return NULL;
    }

    // send this irp to the storage device
    pStackLocation = IoGetNextIrpStackLocation(pNewIrp);
    status = IoCallDriver(pVolumeObject, pNewIrp);

    if (status == STATUS_PENDING)
    {
        status = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL);
        status = IoStatus.Status;
    }

    if (!NT_SUCCESS(status))
    {
        ExFreePool(pVolumeExtents);
        return NULL;
    }

    swprintf(data, L"\\GLOBAL??\\PhysicalDrive%d", pVolumeExtents->Extents[0].DiskNumber);
    RtlInitUnicodeString(&strDeviceName, data); 
    ExFreePool(pVolumeExtents);

    pDeviceObject = NULL;
    IoGetDeviceObjectPointer(&strDeviceName, 0, &pFileObject, &pDeviceObject);

    if (pDeviceObject == NULL)
        return NULL;

    pLowerDevice = IoGetDeviceAttachmentBaseRef(pDeviceObject);
    ObDereferenceObject(pFileObject);

    return pLowerDevice;
}

NTSTATUS GetDeviceSeriallNumber(PVOID pDeviceExtension, PDEVICE_OBJECT DiskDeviceObject)
{
    PIRP Irp;
    KEVENT Event;
    IO_STATUS_BLOCK Iosb;
    PFSOBSRVDEVICEEXTENSION DeviceExtension = (PFSOBSRVDEVICEEXTENSION)pDeviceExtension;
    USB_DEVICE_DESCRIPTOR  deviceDescriptor = {0};
    USB_STRING_DESCRIPTOR    stringDescriptor = {0};
    PDEVICE_EXTENSION pdx = NULL;
    STORAGE_PROPERTY_QUERY PropQuery;
    PSTORAGE_DEVICE_DESCRIPTOR pDesc = NULL;
    PFILE_OBJECT        pFileObject;
    PDEVICE_OBJECT        pDeviceObject;
    PDEVICE_OBJECT        pLowerDevice;
    NTSTATUS            Status = STATUS_SUCCESS;
    ULONG                QuerySize = 0x4000;
    ULONG                retLength = 0;
    ULONG                ulResultLength = 0;
    PVOID                infoBuffer = NULL;
    PVOID                QueryBuffer = NULL;
    PURB                Urb,Urb1;    
    ULONG                size;    
    UNICODE_STRING        puString = {0,0,0};
    UNICODE_STRING        strDeviceName;
    WCHAR                wcharbuff[260];    
    
    __try
    {        
        if(!DiskDeviceObject)
        {
            Status = STATUS_UNSUCCESSFUL;
            __leave;
        }
        QueryBuffer = ExAllocatePoolWithTag( PagedPool, QuerySize, _ALLOC_TAG );
        if ( !QueryBuffer )
        {
            __leave;
        }

        pdx = (PDEVICE_EXTENSION)DiskDeviceObject->DeviceExtension;

        memset( &PropQuery, 0, sizeof(PropQuery) );
        memset( QueryBuffer, 0, QuerySize );
        PropQuery.PropertyId = StorageDeviceProperty;
        PropQuery.QueryType = PropertyStandardQuery;
        
        KeInitializeEvent( &Event, NotificationEvent, FALSE );        
        Irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_QUERY_PROPERTY,
            DiskDeviceObject,
            &PropQuery,
            sizeof(PropQuery),
            QueryBuffer,
            QuerySize,            
            FALSE,
            &Event, 
            &Iosb);
        
        if (!Irp)
        {
            Status = STATUS_UNSUCCESSFUL;
            __leave;
        }
        
        Status = IoCallDriver( DiskDeviceObject, Irp);
        
        if ( STATUS_PENDING == Status )
        {
            KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER) NULL );
            Status = Iosb.Status;
        }
        
        if ( !NT_SUCCESS( Status ) )
        {
            __leave;
        }

        if ( !Iosb.Information )
        {
            Status = STATUS_UNSUCCESSFUL;
            __leave;
        }
        
        pDesc = (PSTORAGE_DEVICE_DESCRIPTOR)QueryBuffer;

        if (pDesc)
        {
            DPRINT("%S. %s. Vendor %s\n", DRIVER_NAME, __FUNCTION__,
                (LPCSTR)((ULONG_PTR)pDesc + pDesc->VendorIdOffset)); //Сдесь данные правильные

            DPRINT("%S. %s. Product %s\n", DRIVER_NAME, __FUNCTION__,
                (LPCSTR)((ULONG_PTR)pDesc + pDesc->ProductIdOffset)); //И сдесь тоже данные правильные

            DPRINT("%S. %s. Serial %s\n", DRIVER_NAME, __FUNCTION__, 
                (LPCSTR)((ULONG_PTR)pDesc + pDesc->SerialNumberOffset)); //Сдесь просто скобка '(' смещение = 0
        }

        Status = IoGetDeviceProperty(DiskDeviceObject, DevicePropertyPhysicalDeviceObjectName, sizeof(wcharbuff), wcharbuff, &ulResultLength);
        if(wcharbuff)
        {
            RtlInitUnicodeString(&strDeviceName, wcharbuff); 
            IoGetDeviceObjectPointer(&strDeviceName, 0, &pFileObject, &pDeviceObject);

            if (pDeviceObject == NULL)
                 __leave;

            pLowerDevice = IoGetDeviceAttachmentBaseRef(pDeviceObject);
            ObDereferenceObject(pFileObject);
        }
    }
    __finally
    {
        if ( QueryBuffer )
        {
            ExFreePool( QueryBuffer );
            QueryBuffer = NULL;
        }
    }    
   


    if (!pLowerDevice)
    {
        return STATUS_UNSUCCESSFUL;
    }

    Urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
    Urb1 = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
    //size = sizeof(USB_DEVICE_DESCRIPTOR);
    //deviceDescriptor = ExAllocatePool(NonPagedPool, size);

    DeviceExtension->langid = 0;
    UsbBuildGetDescriptorRequest(Urb,
        (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), 
        USB_DEVICE_DESCRIPTOR_TYPE,
        0,
        0, //DeviceExtension->langid,
        &deviceDescriptor,
        NULL,
        sizeof(USB_DEVICE_DESCRIPTOR),
        NULL);
         
    if(DiskDeviceObject->Vpb->RealDevice)
        Status = SendAwaitUrb(DiskDeviceObject->Vpb->RealDevice, Urb); //Ошибка здесь статус != STATUS_SUCCESS
    
    //pLowerDevice->DeviceExtension->idVendor = deviceDescriptor.idVendor;
    //pLowerDevice->DeviceExtension->idProduct = deviceDescriptor.idProduct;

    Urb1 = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
    size = sizeof(USB_STRING_DESCRIPTOR);

    UsbBuildGetDescriptorRequest(Urb1,
                 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                 USB_STRING_DESCRIPTOR_TYPE,
                 0,
                 0,
                 &stringDescriptor,
                 NULL,
                 size,
                 NULL);

    if(DiskDeviceObject->Vpb->RealDevice)
        Status = SendAwaitUrb(DiskDeviceObject->Vpb->RealDevice, Urb1);    //Ошибка здесь тоже статус != STATUS_SUCCESS

    //if (STATUS_SUCCESS != Status) 
      // return STATUS_UNSUCCESSFUL;
    //Status = DoCallUSBD(pLowerDevice, Urb1);

    if (NT_SUCCESS(Status))
    {       
        if(deviceDescriptor.iManufacturer)
        {
            Status = GetStringDescriptor(DeviceExtension, deviceDescriptor.iManufacturer, &puString);
            if (NT_SUCCESS(Status)) 
            {
                DeviceExtension->DeviceManufacturer = ExAllocatePool(NonPagedPool, puString.Length*sizeof(WCHAR));
                DeviceExtension->DeviceManufacturer = puString.Buffer;
                DPRINT("Manufacturer %S\n", puString.Buffer);
            }
        }

        if(deviceDescriptor.iProduct)
        {
            Status = GetStringDescriptor(DeviceExtension, deviceDescriptor.iProduct, &puString);
            if (NT_SUCCESS(Status))
            {
                DeviceExtension->DeviceProduct = ExAllocatePool(NonPagedPool, puString.Length*sizeof(WCHAR));
                DeviceExtension->DeviceProduct = puString.Buffer;
                DPRINT("Product %S\n", puString.Buffer);
            }
        }

        if(deviceDescriptor.iSerialNumber)
        {
            Status = GetStringDescriptor(DeviceExtension, deviceDescriptor.iSerialNumber, &puString); 
            if (NT_SUCCESS(Status)) 
            {
                DeviceExtension->DeviceSerialNumber = ExAllocatePool(NonPagedPool, puString.Length*sizeof(WCHAR));
                DeviceExtension->DeviceSerialNumber = puString.Buffer;
                DeviceExtension->DeviceSerialNumberLength = puString.Length + sizeof(WCHAR);
                DPRINT("SerialNumber %S\n", puString.Buffer);
            }
        }
    }

    // Освободить занятую память
    if (&deviceDescriptor)
    {
        ExFreePool(&deviceDescriptor);
        //deviceDescriptor = {0};
    }

    if (&Urb)
    {
        ExFreePool(&Urb);
        //&Urb = NULL;
    }

    if (&Urb1)
    {
        ExFreePool(&Urb1);
        //&Urb1 = NULL;
    }

    return Status;
}

NTSTATUS SendAwaitUrb(PDEVICE_OBJECT fido, PURB pUrb)
{
    KEVENT event;
    PIRP pIrp = NULL;
    IO_STATUS_BLOCK ioStatus;
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION nextStack = NULL;
    //PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;

    KeInitializeEvent(&event, NotificationEvent, FALSE);
    pIrp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
                     fido, //pdx->NextLowerDriver,
                     NULL,
                     0,
                     NULL,
                     0,
                     TRUE,
                     &event,
                     &ioStatus); 

    if (NULL == pIrp)
    {
        status = ioStatus.Status;
        goto exit;
    }

    nextStack = IoGetNextIrpStackLocation(pIrp);
    nextStack->Parameters.Others.Argument1 = pUrb;
    status = IoCallDriver(fido, pIrp);

    if (STATUS_PENDING == status)
    {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = ioStatus.Status;
    }

exit:
    return status;
}
Re[5]: серийный номер usb-устройства
От: dvasya  
Дата: 20.12.11 14:26
Оценка:
Напишу проще

PDEVICE_OBJECT DiskDeviceObject = FilterGetDiskObject(CurrentStackLocation->Parameters.MountVolume.Vpb->RealDevice);


не выполняется запрос к USB устройству

UsbBuildGetDescriptorRequest(Urb,
        sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), 
        USB_DEVICE_DESCRIPTOR_TYPE,
        0,
        DeviceExtension->langid,
        deviceDescriptor,
        NULL,
        size,
        NULL);
         
    if(DiskDeviceObject)
        Status = DoCallUSBD(DiskDeviceObject, Urb);
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.