Я получил фрагмент кода из примера Bluetooth в Интернете, где мы используем условие:
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))) {
}
}
Теперь lpszServiceInstancename определено в winSock2.h, где я вижу:
#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;
Однако я получаю ошибку:
_wcsicmp ‘: невозможно преобразовать параметр 1 из’ LPSTR ‘в’ const wchar_t * ‘
Это, очевидно, не работает, потому что я не использую Unicode, но многобайтовый набор символов. Что бы вы посоветовали конвертировать pWSAQuerySet->lpszServiceInstanceName
в wchar
чтобы я сравнивал яблоки с яблоками?
Погуглить ошибку мне не очень помогло, боюсь, я ее плохо понимаю.
Можете ли вы помочь мне правильно использовать int MultiByteToWideChar ()? Заранее спасибо!
_wcsicmp_l()
ожидает двух wchar_t
строки, но вы передаете char
строка в первом параметре, следовательно, ошибка. Что значит pWSAQuerySet
указывает на WSAQUERYSETA
и не WSAQUERYSETW
, Поскольку ваш код использует TCHAR
-основан WSAQUERYSET
Это означает, что ваш проект настроен на MBCS, а не на Unicode.
Если pszRemoteName
это wchar_t
строка, то вы не можете сравнить его с char
строка. Это совершенно разные типы данных. Один из них должен быть преобразован в другой. В этом случае вам следует преобразовать lpszServiceInstanceName
значение для wchar_t
с помощью MultiByteToWideChar()
или эквивалентный, то вы можете сравнить преобразованное значение с pszRemoteName
Например:
int len = MultiByteToWideChar(CP_ACP, 0, pWSAQuerySet->lpszServiceInstanceName, -1, NULL, 0);
if (len > 0) {
wchar_t *pszServiceInstanceName = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, pWSAQuerySet->lpszServiceInstanceName, -1, pszServiceInstanceName, len);
if (CXN_SUCCESS == _wcsicmp_l(pszServiceInstanceName, pszRemoteName) {
//...
}
delete[] pszServiceInstanceName;
}
Альтернатива состоит в том, чтобы изменить код для использования WSAQUERYSETW
вместо WSAQUERYSETA
так что его lpszServiceInstanceName
полевые использования wchar_t
вместо char
, Вам не нужно менять весь проект на Unicode, чтобы использовать API Unicode. Просто прекратите использовать TCHAR
API-интерфейсы и использовать API-интерфейсы Unicode напрямую (так же, как вы используете wprintf()
вместо printf()
). В этом случае используйте WSALookupServiceBeginW()
а также WSALookupServiceNextW()
напрямую, например:
BOOL NameToBthAddr(_In_ LPCWSTR pszRemoteName, _Out_ PSOCKADDR_BTH pRemoteBtAddr)
{
INT iResult;
BOOL bContinueLookup = TRUE, bRemoteDeviceFound = FALSE;
ULONG ulFlags = 0, ulPQSSize = sizeof(WSAQUERYSETW);
HANDLE hLookup = NULL;
PWSAQUERYSETW pWSAQuerySet = NULL;
ZeroMemory(pRemoteBtAddr, sizeof(*pRemoteBtAddr));
pWSAQuerySet = (PWSAQUERYSETW) HeapAlloc(GetProcessHeap(), 0, ulPQSSize);
if (!pWSAQuerySet) {
wprintf(L"!ERROR! | Unable to allocate memory for WSAQUERYSET\n");
return FALSE;
}
//
// Search for the device with the correct name
//
for (int iRetryCount = 0; (!bRemoteDeviceFound) && (iRetryCount < CXN_MAX_INQUIRY_RETRY) && (bContinueLookup); ++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
//
hLookup = NULL;
ZeroMemory(pWSAQuerySet, ulPQSSize);
pWSAQuerySet->dwNameSpace = NS_BTH;
pWSAQuerySet->dwSize = ulPQSSize;
iResult = WSALookupServiceBeginW(pWSAQuerySet, ulFlags, &hLookup);
if (SOCKET_ERROR == iResult) {
wprintf(L"=CRITICAL= | WSALookupServiceBegin() failed with error code %d\n", WSAGetLastError());
break;
}
do {
//
// 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 = ulPQSSize;
do {
iResult = WSALookupServiceNextW(hLookup, ulFlags, &ulPQSSize, pWSAQuerySet);
if (SOCKET_ERROR != iResult) {
break;
}
iResult = WSAGetLastError();
if (WSAEFAULT != iResult) {
break;
}
PWSAQUERYSETW pNewWSAQuerySet = (PWSAQUERYSETW) HeapReAlloc(GetProcessHeap(), 0, pWSAQuerySet, ulPQSSize);
if (!pNewWSAQuerySet) {
wprintf(L"!ERROR! | Unable to re-allocate memory for WSAQUERYSET\n");
iResult = WSA_NOT_ENOUGH_MEMORY;
break;
}
pWSAQuerySet = pNewWSAQuerySet;
}
while (true);
if (NO_ERROR != iResult) {
if (WSA_E_NO_MORE != iResult) {
bContinueLookup = FALSE;
}
break;
}
//
// Compare the name to see if this is the device we are looking for.
//
if ((pWSAQuerySet->lpszServiceInstanceName) && (0 == _wcsicmp_l(pWSAQuerySet->lpszServiceInstanceName, pszRemoteName))) {
bRemoteDeviceFound = TRUE;
CopyMemory(pRemoteBtAddr, pWSAQuerySet->lpcsaBuffer->RemoteAddr.lpSockaddr, sizeof(*pRemoteBtAddr));
break;
}
}
while (true);
WSALookupServiceEnd(hLookup);
}
HeapFree(GetProcessHeap(), 0, pWSAQuerySet);
return bRemoteDeviceFound;
}
Других решений пока нет …