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...
Пока на собственное сообщение не было ответов, его можно удалить.