I got a piece of code from a Bluetooth example on the web, where we use a condition:
ULONG NameToBthAddr(_In_ const LPWSTR pszRemoteName, _Out_ PSOCKADDR_BTH pRemoteBtAddr)
{
INT iResult = CXN_SUCCESS;
BOOL bContinueLookup = FALSE, bRemoteDeviceFound = FALSE;
ULONG ulFlags = 0, ulPQSSize = sizeof(WSAQUERYSET);
HANDLE hLookup = NULL;
PWSAQUERYSET pWSAQuerySet = NULL;
ZeroMemory(pRemoteBtAddr, sizeof(*pRemoteBtAddr));
pWSAQuerySet = (PWSAQUERYSET)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
ulPQSSize);
if (NULL ==
) {
iResult = STATUS_NO_MEMORY;
wprintf(L"!ERROR! | Unable to allocate memory for WSAQUERYSET\n");
}
//
// Search for the device with the correct name
//
if (CXN_SUCCESS == iResult) {
for (INT iRetryCount = 0;
!bRemoteDeviceFound && (iRetryCount < CXN_MAX_INQUIRY_RETRY);
iRetryCount++) {
//
// WSALookupService is used for both service search and device inquiry
// LUP_CONTAINERS is the flag which signals that we're doing a device inquiry.
//
ulFlags = LUP_CONTAINERS;
//
// Friendly device name (if available) will be returned in lpszServiceInstanceName
//
ulFlags |= LUP_RETURN_NAME;
//
// BTH_ADDR will be returned in lpcsaBuffer member of WSAQUERYSET
//
ulFlags |= LUP_RETURN_ADDR;
if (0 == iRetryCount) {
wprintf(L"*INFO* | Inquiring device from cache...\n");
}
else {
//
// Flush the device cache for all inquiries, except for the first inquiry
//
// By setting LUP_FLUSHCACHE flag, we're asking the lookup service to do
// a fresh lookup instead of pulling the information from device cache.
//
ulFlags |= LUP_FLUSHCACHE;
//
// Pause for some time before all the inquiries after the first inquiry
//
// Remote Name requests will arrive after device inquiry has
// completed. Without a window to receive IN_RANGE notifications,
// we don't have a direct mechanism to determine when remote
// name requests have completed.
//
wprintf(L"*INFO* | Unable to find device. Waiting for %d seconds before re-inquiry...\n", CXN_DELAY_NEXT_INQUIRY);
Sleep(CXN_DELAY_NEXT_INQUIRY * 1000);
wprintf(L"*INFO* | Inquiring device ...\n");
}
//
// Start the lookup service
//
iResult = CXN_SUCCESS;
hLookup = 0;
bContinueLookup = FALSE;
ZeroMemory(pWSAQuerySet, ulPQSSize);
pWSAQuerySet->dwNameSpace = NS_BTH;
pWSAQuerySet->dwSize = sizeof(WSAQUERYSET);
iResult = WSALookupServiceBegin(pWSAQuerySet, ulFlags, &hLookup);
//
// Even if we have an error, we want to continue until we
// reach the CXN_MAX_INQUIRY_RETRY
//
if ((NO_ERROR == iResult) && (NULL != hLookup)) {
bContinueLookup = TRUE;
}
else if (0 < iRetryCount) {
wprintf(L"=CRITICAL= | WSALookupServiceBegin() failed with error code %d, WSAGetLastError = %d\n", iResult, WSAGetLastError());
break;
}
while (bContinueLookup) {
//
// Get information about next bluetooth device
//
// Note you may pass the same WSAQUERYSET from LookupBegin
// as long as you don't need to modify any of the pointer
// members of the structure, etc.
//
// ZeroMemory(pWSAQuerySet, ulPQSSize);
// pWSAQuerySet->dwNameSpace = NS_BTH;
// pWSAQuerySet->dwSize = sizeof(WSAQUERYSET);
if (NO_ERROR == WSALookupServiceNext(hLookup,
ulFlags,
&ulPQSSize,
pWSAQuerySet)) {
//
// Compare the name to see if this is the device we are looking for.
//
if ((pWSAQuerySet->lpszServiceInstanceName != NULL) &&
(CXN_SUCCESS == _wcsicmp_l(pWSAQuerySet->lpszServiceInstanceName, pszRemoteName))) {
}
}
Now, the lpszServiceInstancename is defined inside winSock2.h where I see:
#ifdef UNICODE
typedef WSAQUERYSETW WSAQUERYSET;
typedef PWSAQUERYSETW PWSAQUERYSET;
typedef LPWSAQUERYSETW LPWSAQUERYSET;
typedef WSAQUERYSET2W WSAQUERYSET2;
typedef PWSAQUERYSET2W PWSAQUERYSET2;
typedef LPWSAQUERYSET2W LPWSAQUERYSET2;
#else
typedef WSAQUERYSETA WSAQUERYSET;
typedef PWSAQUERYSETA PWSAQUERYSET;
typedef LPWSAQUERYSETA LPWSAQUERYSET;
typedef WSAQUERYSET2A WSAQUERYSET2;
typedef PWSAQUERYSET2A PWSAQUERYSET2;
typedef LPWSAQUERYSET2A LPWSAQUERYSET2;
#endif /* UNICODE */
typedef struct _WSAQuerySetA
{
DWORD dwSize;
LPSTR lpszServiceInstanceName;
LPGUID lpServiceClassId;
LPWSAVERSION lpVersion;
LPSTR lpszComment;
DWORD dwNameSpace;
LPGUID lpNSProviderId;
LPSTR lpszContext;
DWORD dwNumberOfProtocols;
__field_ecount(dwNumberOfProtocols) LPAFPROTOCOLS lpafpProtocols;
LPSTR lpszQueryString;
DWORD dwNumberOfCsAddrs;
__field_ecount(dwNumberOfCsAddrs) LPCSADDR_INFO lpcsaBuffer;
DWORD dwOutputFlags;
LPBLOB lpBlob;
} WSAQUERYSETA, *PWSAQUERYSETA, *LPWSAQUERYSETA;
typedef __struct_bcount(dwSize) struct _WSAQuerySetW
{
DWORD dwSize;
LPWSTR lpszServiceInstanceName;
LPGUID lpServiceClassId;
LPWSAVERSION lpVersion;
LPWSTR lpszComment;
DWORD dwNameSpace;
LPGUID lpNSProviderId;
LPWSTR lpszContext;
DWORD dwNumberOfProtocols;
__field_ecount(dwNumberOfProtocols) LPAFPROTOCOLS lpafpProtocols;
LPWSTR lpszQueryString;
DWORD dwNumberOfCsAddrs;
__field_ecount(dwNumberOfCsAddrs) LPCSADDR_INFO lpcsaBuffer;
DWORD dwOutputFlags;
LPBLOB lpBlob;
} WSAQUERYSETW, *PWSAQUERYSETW, *LPWSAQUERYSETW;
However I get an error:
_wcsicmp' : cannot convert parameter 1 from 'LPSTR' to 'const wchar_t *'
This obviously doesn't work because I don't use Unicode but Multi Byte character set. What would you recommend to convert the pWSAQuerySet->lpszServiceInstanceName
to wchar
so that I compare apples with apples?
Googling the error hasn't helped me much, I am afraid that I don't understand it well. Can you help me use properly the int MultiByteToWideChar() ? Thank you in advance!
_wcsicmp_l()
expects twowchar_t
strings, but you are passing achar
string in the first parameter, hence the error. Which meanspWSAQuerySet
is pointing at aWSAQUERYSETA
and not aWSAQUERYSETW
. Since your code is using theTCHAR
-basedWSAQUERYSET
, that means your project is set to MBCS and not Unicode.If
pszRemoteName
is awchar_t
string, then you cannot compare it to achar
string. They are completely different data types. One of them has to be converted to the other. In this case, you should convert thelpszServiceInstanceName
value towchar_t
usingMultiByteToWideChar()
or equivilent, then you can compare the converted value topszRemoteName
, eg:The alternative is to change the code to use
WSAQUERYSETW
instead ofWSAQUERYSETA
so that itslpszServiceInstanceName
field useswchar_t
instead ofchar
. You don't have to change the whole project to Unicode in order to use Unicode APIs. Just stop usingTCHAR
-based APIs and use the Unicode APIs directly (just like you are usingwprintf()
instead ofprintf()
). In this case, useWSALookupServiceBeginW()
andWSALookupServiceNextW()
directly, eg: