Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does PSTR type have different behavior on different visual studio projects types?

Tags:

c

string

I have following code that enumerates devices and write it description to console:

#include <windows.h>
#include <setupapi.h>

#include <stdio.h>
#include <tchar.h>

#ifdef  DEBUG
#undef  DBG
#define DBG 1
#endif

#if DBG
#define OOPS() Oops(__FILE__, __LINE__)
#else
#define  OOPS()
#endif

#define ALLOC(dwBytes) GlobalAlloc(GPTR,(dwBytes))

#define REALLOC(hMem, dwBytes) GlobalReAlloc((hMem), (dwBytes), (GMEM_MOVEABLE|GMEM_ZEROINIT))

#define FREE(hMem)  GlobalFree((hMem))

#define CHECKFORLEAKS()


_Success_(return == TRUE)
BOOL
GetDeviceProperty(
_In_    HDEVINFO         DeviceInfoSet,
_In_    PSP_DEVINFO_DATA DeviceInfoData,
_In_    DWORD            Property,
_Outptr_  LPTSTR        *ppBuffer
)
{
    BOOL bResult;
    DWORD requiredLength = 0;
    DWORD lastError;

    if(ppBuffer == NULL)
    {
        return FALSE;
    }

    *ppBuffer = NULL;

    bResult = SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
                                               DeviceInfoData,
                                               Property,
                                               NULL,
                                               NULL,
                                               0,
                                               &requiredLength);
    lastError = GetLastError();

    if((requiredLength == 0) || (bResult != FALSE && lastError != ERROR_INSUFFICIENT_BUFFER))
    {
        return FALSE;
    }

    *ppBuffer = ALLOC(requiredLength);

    if(*ppBuffer == NULL)
    {
        return FALSE;
    }

    bResult = SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
                                               DeviceInfoData,
                                               Property,
                                               NULL,
                                               (PBYTE)*ppBuffer,
                                               requiredLength,
                                               &requiredLength);
    if(bResult == FALSE)
    {
        FREE(*ppBuffer);
        *ppBuffer = NULL;
        return FALSE;
    }

    return TRUE;
}

void
EnumerateAllDevices(
)
{
    HDEVINFO deviceInfo = NULL;

    // Getting all present devices
    deviceInfo = SetupDiGetClassDevs(NULL,
                                     NULL,
                                     NULL,
                                     (DIGCF_ALLCLASSES | DIGCF_PRESENT));

    if(deviceInfo != INVALID_HANDLE_VALUE)
    {
        ULONG                    index;
        DWORD error;

        error = 0;
        index = 0;

        while(error != ERROR_NO_MORE_ITEMS)
        {

            BOOL success;
            SP_DEVINFO_DATA infoData;
            ZeroMemory(&infoData, sizeof(SP_DEVINFO_DATA));
            PSTR DeviceDescName = NULL;
            infoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

            success = SetupDiEnumDeviceInfo(deviceInfo,
                                            index,
                                            &infoData);

            index++;

            if(success == FALSE)
            {
                error = GetLastError();

                if(error != ERROR_NO_MORE_ITEMS)
                {
                    //OOPS();
                }
            }
            else
            {
                BOOL   bResult;

                bResult = GetDeviceProperty(deviceInfo,
                                            &infoData,
                                            SPDRP_DEVICEDESC,
                                            &DeviceDescName);
                if(bResult == FALSE)
                {
                    //OOPS();
                    break;
                }

                printf("DeviceDescName   = %s\n", DeviceDescName);
            }
        }
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    EnumerateAllDevices();
    return 0;
}

DeviceDescName is PSTR as you can see from the code. For some reason this works perfect for one project type Windows driver application. Here I see full device name DeviceDescName like "High Definition Audio Controller".

The same code is not working for other Console Application. Toolset v120. Here in DeviceDescName I see only first latter "H"(from "High Definition Audio Controller"). What can be the reason? (you can try this)

like image 446
Brans Ds Avatar asked May 16 '26 15:05

Brans Ds


1 Answers

It's because the driver project is compiled as UNICODE and PSTR points to a WCHAR * whereas your console application is not compiled as UNICODE and PSTR is rendered as a CHAR *.

You can try to compile your console application as UNICODE by tweaking the settings, but this may cause issues unless your code is carefully written and uses the right types - and it sounds like it doesn't.

An alternative is to use PWSTR for this code (and other similar instances), which will always be a wide character string.

like image 188
Nik Bougalis Avatar answered May 18 '26 03:05

Nik Bougalis