How to compare BSTR against a string in c/c++?

Viewed 22723
wprintf(L"Selecting Audio Input Device: %s\n", 
                            varName.bstrVal);

if(0 == strcmp(varName.bstrVal, "IP Camera [JPEG/MJPEG]"))...

The above reports :

error C2664: 'strcmp' : cannot convert parameter 1 from 'BSTR' to 'const char *'
5 Answers

All other answers here are either outright wrong or partially incorrect because they are ignoring the fact that both BSTR and std::wstring can contain multiple embedded null characters.

That means they should not be compared using wcscmp(), which will stop comparison on the first \0 it encounters in either string.

Here is how to properly compare BSTR with std::wstring:

// Windows.h defines min() and max() as macros
#define NOMINMAX

#include <Windows.h>
#include <string>

// std::string_literals namespace requires C++14,
// but it is needed only to construct strings with
// embedded nulls, not for the comparison itself
using namespace std::string_literals;

int wmain(int argc, wchar_t *argv[])
{
    std::wstring    String1 = L"I am a happy BSTR \0with \0embedded \0null chars"s;
    std::wstring    Temp = L"I am a happy bstr \0with \0embedded \0NULL chars"s;
    BSTR            String2 = SysAllocStringLen(Temp.c_str(), Temp.size());

    if (String2 == nullptr) {
        return ERROR_OUTOFMEMORY;
    }

    // make sure not to create a security vulnerability by
    // reading past the end of either buffer when comparing
    const size_t MaxCount = std::min(String1.size(), static_cast<size_t>(SysStringLen(String2)));

    bool Equal = wcsncmp(String1.c_str(), String2, MaxCount) == 0;

    if (Equal) {
        wprintf(L"Strings are equal\n");
    } else {
        wprintf(L"Strings are NOT equal\n");
    }

    SysFreeString(String2);

    return 0;
}

Note that the example will print "Strings are NOT equal" unless you change it to use _wcsnicmp() for case-insensitive comparison.

Related