4 #if (_MSC_FULL_VER < 180031101) 5 #error At least Visual Studio 2013 Update 4 is required to compile this backend 22 #pragma comment(lib, "cfgmgr32.lib") 23 #pragma comment(lib, "setupapi.lib") 30 DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
32 DEFINE_GUID(GUID_DEVINTERFACE_IMAGE_WIN10, 0x6bdd1fc6L, 0x810f, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f);
33 DEFINE_GUID(GUID_DEVINTERFACE_CAMERA_WIN10, 0xca3e7ab9, 0xb4c3, 0x4ae6, 0x82, 0x51, 0x57, 0x9e, 0xf9, 0x33, 0x89, 0x0f);
36 DEFINE_GUID(GUID_DEVINTERFACE_IMAGE_WIN7, 0xe659c3ec, 0xbf3c, 0x48a5, 0x81, 0x92, 0x30, 0x73, 0xe8, 0x22, 0xd7, 0xcd);
39 DEFINE_GUID(GUID_DEVINTERFACE_CAMERA_WIN7, 0x50537bc3, 0x2919, 0x452d, 0x88, 0xa9, 0xb1, 0x3b, 0xbf, 0x7d, 0x24, 0x59);
41 #define CREATE_MUTEX_RETRY_NUM (5) 51 return sizeof(
T) * vec.size();
57 std::wstring errorMessage = (err.ErrorMessage()) ? err.ErrorMessage() : L
"";
59 ss <<
"HResult 0x" << std::hex << hr <<
": \"" <<
win_to_utf(errorMessage.data()) <<
"\"";
63 typedef ULONG(__stdcall*
fnRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation);
68 RTL_OSVERSIONINFOEXW verInfo = { 0 };
69 verInfo.dwOSVersionInfoSize =
sizeof(verInfo);
70 static auto RtlGetVersion =
reinterpret_cast<fnRtlGetVersion>(GetProcAddress(GetModuleHandleW(L
"ntdll.dll"),
"RtlGetVersion"));
71 if (RtlGetVersion !=
nullptr && RtlGetVersion(reinterpret_cast<PRTL_OSVERSIONINFOW>(&verInfo)) == 0)
73 return verInfo.dwMajorVersion >= 0x0A && verInfo.dwBuildNumber >= 15063;
79 bool check(
const char *
call, HRESULT hr,
bool to_throw)
96 auto len = WideCharToMultiByte(CP_UTF8, 0, s, -1,
nullptr, 0,
nullptr,
nullptr);
98 throw std::runtime_error(
to_string() <<
"WideCharToMultiByte(...) returned 0 and GetLastError() is " << GetLastError());
101 len = WideCharToMultiByte(CP_UTF8, 0, s, -1, &buffer[0], static_cast<int>(buffer.size())+1,
nullptr,
nullptr);
103 throw std::runtime_error(
to_string() <<
"WideCharToMultiByte(...) returned 0 and GetLastError() is " << GetLastError());
110 std::vector<std::string> tokens;
111 std::string::size_type
i1 = 0;
114 auto i2 =
string.find(separator, i1);
115 if(
i2 == std::string::npos)
117 tokens.push_back(
string.substr(i1));
120 tokens.push_back(
string.substr(i1,
i2-i1));
137 if(tokens.size() < 1 || (tokens[0] != R
"(\\?\usb)" && tokens[0] != R"(\\?\hid)")) return false;
138 if(tokens.size() < 3)
147 LOG_ERROR(
"malformed vid string: " << tokens[1]);
153 LOG_ERROR(
"malformed pid string: " << tokens[1]);
159 LOG_ERROR(
"malformed mi string: " << tokens[1]);
166 LOG_ERROR(
"malformed id string: " << tokens[2]);
175 if (tokens.size() >= 3)
176 device_guid = tokens[3];
191 if (tokens.size() < 1 || (tokens[0] != R
"(\\?\usb)" && tokens[0] != R"(\\?\hid)")) return false;
192 if (tokens.size() < 3)
201 LOG_ERROR(
"malformed vid string: " << tokens[1]);
207 LOG_ERROR(
"malformed pid string: " << tokens[1]);
218 auto name = device_id;
221 if (tokens.size() < 1 )
223 if( tokens[0] !=
"usb" && tokens[0] !=
"hid" )
232 LOG_ERROR(
"incomplete device id: " << device_id );
238 LOG_ERROR(
"malformed vid string: " << tokens[1]);
244 LOG_ERROR(
"malformed pid string: " << tokens[1]);
250 LOG_ERROR(
"malformed mi string: " << tokens[1]);
257 LOG_ERROR(
"malformed id string: " << tokens[2]);
266 USB_NODE_CONNECTION_DRIVERKEY_NAME
key;
267 key.ConnectionIndex =
index;
269 if (!DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, &key,
sizeof(key), &key,
sizeof(key),
nullptr,
nullptr))
274 if (key.ActualLength <
sizeof(key))
return false;
276 auto alloc = std::malloc(key.ActualLength);
278 throw std::bad_alloc();
280 auto pKey = std::shared_ptr<USB_NODE_CONNECTION_DRIVERKEY_NAME>(
reinterpret_cast<USB_NODE_CONNECTION_DRIVERKEY_NAME *
>(alloc), std::free);
282 pKey->ConnectionIndex =
index;
283 if (DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, pKey.get(), key.ActualLength, pKey.get(), key.ActualLength,
nullptr,
nullptr))
286 if (targetKey == pKey->DriverKeyName) {
298 USB_NODE_CONNECTION_NAME
name;
299 name.ConnectionIndex =
index;
300 if (!DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_NAME, &name,
sizeof(name), &name,
sizeof(name),
nullptr,
nullptr))
302 return std::wstring(L
"");
306 if (name.ActualLength <
sizeof(name))
return std::wstring(L
"");
307 auto alloc = std::malloc(name.ActualLength);
308 auto pName = std::shared_ptr<USB_NODE_CONNECTION_NAME>(
reinterpret_cast<USB_NODE_CONNECTION_NAME *
>(alloc), std::free);
311 pName->ConnectionIndex =
index;
312 if (DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_NAME, pName.get(), name.ActualLength, pName.get(), name.ActualLength,
nullptr,
nullptr))
314 return std::wstring(pName->NodeName);
317 return std::wstring(L
"");
320 std::tuple<std::string,usb_spec>
handle_usb_hub(
const std::wstring & targetKey,
const std::wstring &
path)
326 std::wstring fullPath = L
"\\\\.\\" +
path;
328 HANDLE
h = CreateFile(fullPath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
nullptr, OPEN_EXISTING, 0,
nullptr);
329 if (h == INVALID_HANDLE_VALUE)
return res;
330 auto h_gc = std::shared_ptr<void>(
h, CloseHandle);
332 USB_NODE_INFORMATION
info{};
333 if (!DeviceIoControl(h, IOCTL_USB_GET_NODE_INFORMATION, &
info,
sizeof(
info), &
info,
sizeof(
info),
nullptr,
nullptr))
337 for (ULONG
i = 1;
i <=
info.u.HubInformation.HubDescriptor.bNumberOfPorts; ++
i)
340 char buf[
sizeof(USB_NODE_CONNECTION_INFORMATION_EX)] = { 0 };
341 PUSB_NODE_CONNECTION_INFORMATION_EX pConInfo =
reinterpret_cast<PUSB_NODE_CONNECTION_INFORMATION_EX
>(
buf);
344 pConInfo->ConnectionIndex =
i;
345 if (!DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, pConInfo,
sizeof(
buf), pConInfo,
sizeof(
buf),
nullptr,
nullptr))
351 if (pConInfo->ConnectionStatus != DeviceConnected)
357 if (pConInfo->DeviceIsHub)
364 static_cast<usb_spec>(pConInfo->DeviceDescriptor.bcdUSB));
368 if( ! std::get<0>(
res).empty() )
378 ULONG cch_required = 0;
379 if( CM_Get_Device_ID_Size( &cch_required, devinst, 0 ) != CR_SUCCESS )
384 std::vector<WCHAR>
buf( cch_required + 1 );
385 if( CM_Get_Device_ID( devinst, buf.data(), cch_required, 0 ) != CR_SUCCESS )
429 if( wcsncmp( path, L
"\\\\?\\", 4 ) )
430 return std::wstring();
431 std::wstring inst_id( path + 4 );
433 for(
auto x = inst_id.find( L
'#' );
434 x != std::wstring::npos;
435 x = inst_id.find( L
'#',
x + 1 ) )
437 if( inst_id[
x + 1] == L
'{' )
442 inst_id.replace(
x, 1, 1, L
'\\' );
451 if( CM_Locate_DevNode( &devinst,
nullptr, CM_LOCATE_DEVNODE_NORMAL ) != CR_SUCCESS )
460 if( CM_Locate_DevNode( &devinst, const_cast< DEVINSTID >( inst_id.data() ), CM_LOCATE_DEVNODE_PHANTOM ) != CR_SUCCESS )
469 if( CM_Get_Parent( &parent,
get(), 0 ) != CR_SUCCESS )
478 if( CM_Get_Child( &child,
get(), 0 ) != CR_SUCCESS )
487 if( CM_Get_Sibling( &sibling,
get(), 0 ) != CR_SUCCESS )
497 auto rv = CM_Get_DevNode_Property(
get(), &property, &type,
nullptr, &cb, 0 );
498 if( rv != CR_BUFFER_SMALL )
500 if( type != DEVPROP_TYPE_STRING )
504 if( CM_Get_DevNode_Property(
get(), &property, &type, (PBYTE) str.data(), &cb, 0 ) != CR_SUCCESS )
513 SP_DEVINFO_DATA devInfo = {
sizeof(SP_DEVINFO_DATA) };
514 std::vector<GUID>
guids = {
515 GUID_DEVINTERFACE_IMAGE_WIN7,
516 GUID_DEVINTERFACE_CAMERA_WIN7,
517 GUID_DEVINTERFACE_IMAGE_WIN10,
518 GUID_DEVINTERFACE_CAMERA_WIN10
521 for (
auto guid : guids)
524 HDEVINFO
device_info = SetupDiGetClassDevsEx(static_cast<const GUID *>(&
guid),
nullptr,
nullptr, DIGCF_PRESENT,
nullptr,
nullptr,
nullptr);
527 auto di = std::shared_ptr<void>(device_info, SetupDiDestroyDeviceInfoList);
529 if (device_info == INVALID_HANDLE_VALUE)
535 for (
int member_index = 0; ; ++member_index)
538 if (SetupDiEnumDeviceInfo(device_info, member_index, &devInfo) ==
FALSE)
540 if( GetLastError() == ERROR_NO_MORE_ITEMS )
550 LOG_ERROR(
"Could not find camera (vid " << std::hex << device_vid <<
" pid " << std::hex << device_pid <<
" uid " << device_uid <<
") in windows device tree" );
557 unsigned long buf_size = 0;
561 if( !
get_id( devinst, &device_id ) )
571 if (usb_vid != device_vid || usb_pid != device_pid || usb_unique_id != device_uid)
576 if (CM_Get_Parent(&parent, devinst, 0) != CR_SUCCESS)
583 if (CM_Get_Device_ID_Size(&buf_size, parent, 0) != CR_SUCCESS)
585 LOG_ERROR(
"CM_Get_Device_ID_Size failed");
589 std::vector<WCHAR> pInstID2(buf_size + 1);
591 if (CM_Get_Device_ID( parent, pInstID2.data(), ULONG(
vector_bytes_size(pInstID2)), 0) != CR_SUCCESS)
598 uint16_t parent_vid, parent_pid, parent_mi;
602 HDEVINFO
device_info = SetupDiGetClassDevs(
nullptr, pInstID2.data(),
nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES);
603 if (device_info == INVALID_HANDLE_VALUE)
606 if( 0 == parent_id.compare( 0, 4,
"HID\\" ))
612 auto di = std::shared_ptr<void>( device_info, SetupDiDestroyDeviceInfoList );
614 SP_DEVICE_INTERFACE_DATA interfaceData = {
sizeof( SP_DEVICE_INTERFACE_DATA ) };
615 if (SetupDiEnumDeviceInterfaces(device_info,
nullptr, &GUID_DEVINTERFACE_USB_DEVICE, 0, &interfaceData) ==
FALSE)
617 LOG_ERROR(
"SetupDiEnumDeviceInterfaces failed");
623 SetupDiGetDeviceInterfaceDetail(device_info, &interfaceData,
nullptr, 0, &buf_size,
nullptr);
624 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
626 LOG_ERROR(
"SetupDiGetDeviceInterfaceDetail failed");
630 std::vector<BYTE> detail_data_buff(buf_size);
631 SP_DEVICE_INTERFACE_DETAIL_DATA* detail_data =
reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA *
>(detail_data_buff.data());
633 detail_data->cbSize =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
634 SP_DEVINFO_DATA parent_data = {
sizeof(SP_DEVINFO_DATA) };
635 if (!SetupDiGetDeviceInterfaceDetail(device_info, &interfaceData, detail_data, ULONG(
vector_bytes_size(detail_data_buff)),
nullptr, &parent_data))
637 LOG_ERROR(
"SetupDiGetDeviceInterfaceDetail failed");
645 std::wstring ws(detail_data->DevicePath);
650 if ( parent_uid.empty())
658 SetupDiGetDeviceRegistryProperty(device_info, &parent_data, SPDRP_DRIVER,
nullptr,
nullptr, 0, &buf_size);
659 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
661 LOG_ERROR(
"SetupDiGetDeviceRegistryProperty failed in an unexpected manner");
665 std::vector<BYTE> driver_key(buf_size);
667 if (!SetupDiGetDeviceRegistryProperty(device_info, &parent_data, SPDRP_DRIVER,
nullptr, driver_key.data(), (ULONG)
vector_bytes_size(driver_key),
nullptr))
669 LOG_ERROR(
"SetupDiGetDeviceRegistryProperty failed");
674 std::wstring targetKey(reinterpret_cast<const wchar_t*>(driver_key.data()));
677 for (
int i = 0;;
i++)
679 std::wstringstream
buf;
680 buf <<
"\\\\.\\HCD" <<
i;
681 std::wstring hcd = buf.str();
684 HANDLE
h = CreateFile(hcd.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr, OPEN_EXISTING, 0,
nullptr);
685 auto h_gc = std::shared_ptr<void>(
h, CloseHandle);
686 if (h == INVALID_HANDLE_VALUE)
693 USB_ROOT_HUB_NAME
name;
696 if (!DeviceIoControl(h, IOCTL_USB_GET_ROOT_HUB_NAME,
nullptr, 0, &name,
sizeof(name),
nullptr,
nullptr)) {
701 std::vector<char> name_buff(name.ActualLength);
702 USB_ROOT_HUB_NAME* pName =
reinterpret_cast<USB_ROOT_HUB_NAME *
>(name_buff.data());
705 if (!DeviceIoControl(h, IOCTL_USB_GET_ROOT_HUB_NAME,
nullptr, 0, pName, (ULONG)
vector_bytes_size(name_buff),
nullptr,
nullptr)) {
711 auto usb_res =
handle_usb_hub(targetKey, std::wstring(pName->RootHubName));
712 if( ! std::get<0>(usb_res).empty() )
714 location = std::get<0>(usb_res);
715 spec = std::get<1>(usb_res);
724 #define MAX_HANDLES 64 741 if (
_handle ==
nullptr)
return false;
748 if (
_handle ==
nullptr)
return false;
750 return WaitForSingleObject(
_handle, timeout) == WAIT_OBJECT_0;
759 for (
auto& evnt : events)
761 handles[
i] = evnt->get_handle();
764 auto res = WaitForMultipleObjects(static_cast<DWORD>(events.size()), handles, waitAll, timeout);
765 if (
res < (WAIT_OBJECT_0 + events.size()))
767 return events[
res - WAIT_OBJECT_0];
777 return wait(events,
true, timeout);
782 return wait(events,
false, timeout);
787 if (
_handle ==
nullptr)
return false;
788 return ResetEvent(
_handle) != 0;
801 WCHAR *pszStringSecurityDescriptor;
802 pszStringSecurityDescriptor = L
"D:(A;;GA;;;WD)(A;;GA;;;AN)S:(ML;;NW;;;ME)";
803 PSECURITY_DESCRIPTOR pSecDesc;
804 if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
805 pszStringSecurityDescriptor, SDDL_REVISION_1, &pSecDesc,
nullptr))
813 _winusb_mutex(nullptr)
821 CString IDstr(camID);
824 lstr.Format(L
"Global\\IVCAM_DLL_WINUSB_MUTEX%s", IDstr);
828 SECURITY_ATTRIBUTES SecAttr;
829 SecAttr.nLength =
sizeof(SECURITY_ATTRIBUTES);
830 SecAttr.lpSecurityDescriptor = pSecDesc;
831 SecAttr.bInheritHandle =
FALSE;
844 else if (GetLastError() == ERROR_ALREADY_EXISTS)
854 CString IDstr(camID);
857 lstr.Format(L
"Global\\IVCAM_DLL_WINUSB_MUTEX%s", IDstr.GetString());
868 else if (GetLastError() == ERROR_ALREADY_EXISTS)
888 switch (stsCreateMutex)
892 throw std::runtime_error(
"CreateNamedMutex returned Mutex_TotalFailure");
909 throw std::runtime_error(
"OpenNamedMutex returned error " + stsOpenMutex);
916 throw std::runtime_error(
"Open mutex failed!");
927 switch (stsCreateMutex)
933 auto res = CloseHandle(tempMutex);
936 throw std::runtime_error(
"CloseHandle failed");
942 throw std::runtime_error(
"CreateNamedMutex returned Mutex_TotalFailure");
961 throw std::runtime_error(
"OpenNamedMutex failed with error " + stsOpenMutex);
969 throw std::runtime_error(
"Open mutex failed!");
982 throw std::runtime_error(
"Acquire failed!");
991 throw std::runtime_error(
"Failed to release winUsb named Mutex! LastError: " + GetLastError());
1010 : runtime_error(generate_message(message).c_str())
1015 std::stringstream ss;
1016 ss << message <<
" Last Error: " <<
last_error_string(GetLastError()) << std::endl;
1023 LPSTR messageBuffer =
nullptr;
1024 size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
1025 nullptr, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPSTR>(&messageBuffer), 0,
nullptr);
1029 LocalFree(messageBuffer);
#define CREATE_MUTEX_RETRY_NUM
GLenum GLuint GLenum GLsizei const GLchar * message
std::istringstream istringstream
GLuint const GLchar * name
GLuint64 GLenum void * handle
GLsizei const GLchar *const * path
GLsizei const GLchar *const * string
GLfloat GLfloat GLfloat GLfloat h
GLenum GLuint GLenum GLsizei const GLchar * buf
def info(name, value, persistent=False)
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED)
GLbitfield GLuint64 timeout
GLuint GLenum GLenum transform
std::string to_string(T value)