Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

Issue with the serial number of Usb storage device

Nikhil_V_SNikhil_V_S Member - All Emails Posts: 22
edited December 4 in NTDEV

Hi All,
I have created an application(using legacy file system driver) to control the exteranal storage device .
We mainly use this for blocking and allowing external storage devices.The application uniquelly identifies devices using its product id,vendor id,revision id and serial number.
This works fine, but with few devices we are getting the serial numer as aspecial character.
For example we have a device with pnpid "USBSTOR\DISK&VEN_KINGSTON&PROD_DATATRAVELER_2.0&REV_1.00\60A44C413BF2F0718628B8E0&0"
whie trying to get the serial number it returns a special character "6", but its acutal serial no is "60A44C413BF2F0718628B8E0".

The result was the same when we tried with WMI query.

here is the sample code code

   NTSTATUS GetDeviceTypeAndUniqueID(IN PDEVICE_OBJECT StorageStackDeviceObject, char* pszUniqueIDArg)
{
    char pszUniqueID[255];

    char szBuff[1024];
    STORAGE_PROPERTY_QUERY Query;
    //STORAGE_DEVICE_DESCRIPTOR Buffer[4];
    NTSTATUS Status = STATUS_SUCCESS;

    PSTORAGE_DEVICE_DESCRIPTOR Descriptor = NULL;
    PIRP NewIrp2 = NULL;
    PIO_STACK_LOCATION NextIrpStack = NULL;
    IO_STATUS_BLOCK IoStatus;
    char szSptr[2] = { '_', '\0' };
    SIZE_T szLength = 0;
    Query.PropertyId = StorageDeviceProperty;// first set the query properties 
    Query.QueryType = PropertyStandardQuery;
    memset(pszUniqueID, 0, 255);


    if (KeGetCurrentIrql() > PASSIVE_LEVEL)
    {
        return STATUS_SUCCESS;
    }
    if (StorageStackDeviceObject == NULL)
    {
        return STATUS_SUCCESS;
    }


    KeInitializeEvent(&WaitEvent_newIrp, NotificationEvent, TRUE);// initialize the waitable event

    __try

    {
        memset(szBuff, 0, 1024);

        NewIrp2 = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_QUERY_PROPERTY, StorageStackDeviceObject,
                                               (PVOID) & Query, sizeof(STORAGE_PROPERTY_QUERY),
                                               szBuff, 1024,
                                               FALSE, &WaitEvent_newIrp, &IoStatus);

        if (NewIrp2 == NULL)
        {
            return STATUS_SUCCESS;
        }

        Status = IoCallDriver(StorageStackDeviceObject, NewIrp2);// send this irp to the storage device 

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

    {
        //if(NT_SUCCESS(Status))
        if (szBuff != NULL)
        {
            try
            {
                Descriptor = (PSTORAGE_DEVICE_DESCRIPTOR)szBuff;
                Descriptor->Size = sizeof(szBuff);
                uBusType = Descriptor->BusType; //Get the bus type.
            }

            except(EXCEPTION_EXECUTE_HANDLER)

            {
                /* Error handling code */
            }
        }


        if (NT_SUCCESS(Status))
        {
            if (Descriptor != NULL)
            {
                char pszStart[255];
                try
                {
                    if (Descriptor->VendorIdOffset != 0)
                    {
                        memset(pszStart, 0, 255);
                        RtlStringCopyWorkerA(pszStart, 255, ((char*)(UINT_PTR)Descriptor + (DWORD32)Descriptor->VendorIdOffset), 255);
                        if (pszStart != ANSI_NULL)
                        {
                            RtlStringLengthWorkerA(pszStart, 255, &szLength);
                            if (szLength > 0)
                            {
                                RtlStringCopyWorkerA(pszStart, 255, (TrimLeft(pszStart)), 255);
                                RtlStringCopyWorkerA(pszUniqueID, 255, (ReplaceBlankto_(TrimRight(pszStart))), 255);
                            }
                        }
                    }
                }

                except(EXCEPTION_EXECUTE_HANDLER)

                  { 
                    /* Error handling code */
                }

                try
                {
                    if (Descriptor->ProductIdOffset != 0)//Is Valid ProductIDOffset, append it to the ID
                    {
                        memset(pszStart, 0, 255);
                        RtlStringCopyWorkerA(pszStart, 255, ((char*)(UINT_PTR)Descriptor + (DWORD32)Descriptor->ProductIdOffset), 255);
                        if (pszStart != ANSI_NULL)
                        {
                            RtlStringLengthWorkerA(pszStart, 255, &szLength);
                            if (szLength > 0)
                            {
                                RtlStringCbCatExA(pszUniqueID, 255, szSptr);
                                RtlStringCopyWorkerA(pszStart, 255, (TrimLeft(pszStart)), 255);
                                RtlStringCbCatExA(pszUniqueID, 255, (TrimRight(pszStart)));
                            }
                        }
                    }
                }

                except(EXCEPTION_EXECUTE_HANDLER)

                {
                    /* Error handling code */
                }
                try
                {
                    if (Descriptor->ProductRevisionOffset != 0)//Is Valid ProductRevisionOffset, append it to the ID
                    {
                        memset(pszStart, 0, 255);
                        RtlStringCopyWorkerA(pszStart, 255, ((char*)(UINT_PTR)Descriptor + (DWORD32)Descriptor->ProductRevisionOffset), 255);
                        if (pszStart != ANSI_NULL)
                        {
                            RtlStringLengthWorkerA(pszStart, 255, &szLength);
                            if (szLength > 0)
                            {
                                RtlStringCbCatExA(pszUniqueID, 255, szSptr);
                                RtlStringCopyWorkerA(pszStart, 255, (TrimLeft(pszStart)), 255);
                                RtlStringCbCatExA(pszUniqueID, 255, (TrimRight(pszStart)));
                            }
                        }
                    }
                }

                    except(EXCEPTION_EXECUTE_HANDLER)

                    {
                    /* Error handling code */
                }

                try
                {
                    if (Descriptor->SerialNumberOffset != 0)//Is Valid ProductRevisionOffset, append it to the ID
                    {
                        memset(pszStart, 0, 255);
                        RtlStringCopyWorkerA(pszStart, 255, ((char*)(UINT_PTR)Descriptor + (DWORD32)Descriptor->SerialNumberOffset), 255);
                        if (pszStart != ANSI_NULL)
                        {
                            RtlStringLengthWorkerA(pszStart, 255, &szLength);
                            if (szLength > 0)
                            {
                                RtlStringCbCatExA(pszUniqueID, 255, "(");
                                RtlStringCopyWorkerA(pszStart, 255, (TrimLeft(pszStart)), 255);
                                RtlStringCbCatExA(pszUniqueID, 255, (TrimRight(pszStart)));
                                RtlStringCbCatExA(pszUniqueID, 255, ")");
                            }
                        }
                    }
                }

                    except(EXCEPTION_EXECUTE_HANDLER)

                    {
                    /* Error handling code */
                }

                try
                {
                    c_upper_string(pszUniqueID);
                    RtlStringCopyWorkerA(pszUniqueIDArg, 255, pszUniqueID, 255);
                }

                    except(EXCEPTION_EXECUTE_HANDLER)

                    {
                    /* Error handling code */
                }
            }
            NewIrp2 = NULL;
        }
    }
return Status;
}

Thanks in advance. Can you suggest any solution for this.

Comments

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 12,715
    via Email
    Nikhil_V_S wrote:
    > I have created an application(using legacy file system driver) to control the exteranal storage device .
    >
    > We mainly use this for blocking and allowing external storage devices.The application uniquelly identifies devices using its product id,vendor id,revision id and serial number.
    >
    > This works fine, but with few devices we are getting the serial numer as aspecial character.
    >
    > For example we have a device with pnpid "USBSTOR\DISK&VEN_KINGSTON&PROD_DATATRAVELER_2.0&REV_1.00\60A44C413BF2F0718628B8E0&0"
    >
    > whie trying to get the serial number it returns a special character "6", but its acutal serial no is "60A44C413BF2F0718628B8E0".

    I don't know what you mean by "special character 6".  Have you dumped
    the memory in hex to see exactly what it contains?  You're not supposed
    to get a Unicode string there, but if you did get Unicode, it would
    certainly print as "6".

    By the way, you have this code repeated several times:

        memset(pszStart, 0, 255);
        RtlStringCopyWorkerA(pszStart, 255, ((char*)((UINT_PTR)Descriptor...));
        if (pszStart != ANSI_NULL)
        {
            RtlStringLengthWorkerA(pszStart, 255, &szLength);
            if (szLength > 0 )
            {
                ...

    There are some problems with this.  ANSI_NULL is a constant representing
    a 0 character.  You are comparing it to a pointer. You KNOW that the
    pointer is not null, because you just passed it to two different
    routines.  If you were trying to find out if the first character was a
    null, meaning the string is empty, then you need to dereference it:

        if (*pszStart != ANSI_NULL)

    In most cases, I find comparing to 0 constants to be less readable than
    just using the C's native "compare to zero" feature:

        if (*pszStart)

    HOWEVER, in this particular instance, that comparison is exactly the
    same as the next two lines of code, where you do strlen and check the
    length for zero.  You don't need both checks.  Do one or the other:
    either check the first character for zero, or check the strlen.

    Also, how do your TrimLeft and TrimRight and ReplaceBlackto_ functions
    work?  Do they modify the string in place and returning the new starting
    address?  Or are they returning a temporary buffer with the trimmed
    string?  In the first case, it would be silly to copy back into
    pszStart, and in the second case there is a memory leak.

    Where did you get your ntstrsafe.h?  In all the versions I know,
    RtlStringCopyWorkerA takes 5 parameters, and you're only supplying 4. 
    Also, you're always supplying 255 for the "characters to copy"
    parameter.  In those cases where you DO know the string length, that's
    what you should pass in.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Nikhil_V_SNikhil_V_S Member - All Emails Posts: 22
    edited December 5

    Thank you @Tim_Roberts
    I lost the special character on posting the question
    here I attach the screen shot

    I am using WDK 7.0

    I created my own RtlStringCopyWorkerA for copying the string and the defintion of Rtl functions are included in attached file.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 12,715
    via Email
    Nikhil_V_S wrote:
    > I lost the special character on posting the question
    >
    > here I attach the screen shot
    >
    > I am using WDK 7.0
    >
    > I created my own RtlStringCopyWorkerA for copying the string and the defintion of Rtl functions are included in attached file.

    The special character is 0xC0, not that it answers any questions.

    WHY on earth would you create your own functions with the same name as
    standard API functions but with different parameters?  You're just
    asking for trouble.

    Again, have you done a hex dump of the structure you get in your
    driver?  That might tell you if the pointer is one byte off for some
    reason, or if the data is actually truncated.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Mark_RoddyMark_Roddy Member - All Emails Posts: 4,277

    Seems over complicated.

    char * sernoBuf = ((char*)(UINT_PTR)Descriptor + (DWORD32)Descriptor->SerialNumberOffset);
    char * dest = whatever buffer pointer;
    size_t destSize = whatever number of bytes is the limit;
    Status = RtlStringCbCopyA(dest, destSize, sernoBuf);

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!