Issue with the serial number of Usb storage device

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.

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.

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.

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.

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);

thank you all

Is there any way to find the PUSBDEVICEINFO in file system driver