win10 Audio 5.1 channel config - winapi

I'm trying to change the channel set(like stereo to 5.1), but every api I tried just failed.
Like IDirectSound8::SetSpeakerConfig which now is NOP, according to microsoft.
now I'm trying IAudioChannelConfig interface, but somehow it failed again.
it just returns E_NOINTERFACE.
here's part of my code.
HRESULT get_chann_interface(IMMDevice *pEndpoint)
{
HRESULT hr;
PROPVARIANT *pActivationParams = NULL; // set to NULL to activate IDeviceTopology
IDeviceTopology *dev_topo;
hr = pEndpoint->Activate(IID_IDeviceTopology, CLSCTX_ALL, pActivationParams,(void**)&dev_topo);
if (hr < 0 || dev_topo == NULL)
{
err_out("IDeviceTopology activate failed: ", hr);
exit(hr);
}
IConnector *iconn;
hr = dev_topo->GetConnector(0, &iconn);// there is only 1 connector in the device topology
if (hr < 0)
{
err_out("IConnector interface get failed: ", hr);
exit(hr);
}
IPart *ipart;
hr = iconn->QueryInterface(IID_IPart, (void **)&ipart);
if (hr < 0)
{
err_out("IPart interface query failed: ", hr);
exit(hr);
}
IAudioChannelConfig *ichann_config;
hr = ipart->Activate(CLSCTX_ALL, IID_IAudioChannelConfig, (void **)&ichann_config);
if (hr < 0)
{
err_out("IAudioChannelConfig interface Activate failed: ", hr);
return(hr);
}
DWORD pdwConfig;
hr = ichann_config->GetChannelConfig(&pdwConfig);
if (hr<0)
err_out("GetChannelConfig failed: ", hr);
else
cout<<"channel config:" << hex << pdwConfig << endl;
SAFE_RELEASE(ichann_config)
SAFE_RELEASE(ipart)
SAFE_RELEASE(iconn)
SAFE_RELEASE(dev_topo)
}
I just failed to activate IAudioChannelConfig interface.
anyone knows any reasons?
thanks in advance.

Related

auto install NDIS filter driver

I'm trying to do an automatic install for the NDIS filter driver.
Kernel debugging is enabled on my machine so driver signing is not required.
P.s. some of the code, I took from this question, but it's still doesn't work.
It gives me this dialog, where the default path to dir wrong.
Also, I watch this topic, but links there aren't workable.
How I can set a default path to .sys file?
Thanks.
....
DWORD size = 0;
isCopied = SetupCopyOEMInfA(pathToInf, // ( C:\[SomeDirs]\[driverInfFile.inf] )
pathToBin, // ( C:\[SomeDirs]\ ) here is driverSysFile.sys
SPOST_PATH,
SP_COPY_NEWER,
NULL,
0,
&size,
NULL);
....
INetCfg *pnc = NULL;
INetCfgClassSetup *pncClassSetup = NULL;
HRESULT hr;
....
hr = CoCreateInstance( CLSID_CNetCfg,
NULL, CLSCTX_INPROC_SERVER,
IID_INetCfg,
(void**)&pnc );
....
INetCfgLock *pncfglock = NULL;
pnc->QueryInterface(IID_INetCfgLock, (LPVOID*)&pncfglock);
pncfglock->AcquireWriteLock(5000, L"MY CLIENT", &szwrClient)
....
hr = pnc->QueryNetCfgClass ( &GUID_DEVCLASS_NETSERVICE,
IID_INetCfgClassSetup,
(void**)&pncClassSetup );
....
OBO_TOKEN OboToken;
ZeroMemory( &OboToken, sizeof(OboToken) );
OboToken.Type = OBO_USER;
INetCfgComponent* NDIS_Component;
//
// I read, that this 2 param both need for automatic setup, and if one is set,
// the second must be setted too.
// But the second[pszwAnswerSections] need to be list of sections in the inf file.
// And it not so cool to parse inf file manually, why OS cant do this???
LPCWSTR pszwAnswerFile = NULL;
LPCWSTR pszwAnswerSections = NULL;
//
// this call fails:
hr = pncClassSetup->Install(COMPONENT_ID,
&OboToken,
NSF_POSTSYSINSTALL,
0,
pszwAnswerFile,
pszwAnswerSections ,
&NDIS_Component);
You can use below code for installing protocol driver. I had created a win32 application for installing protocol driver and assumed that inf and driver file are at same location where executable binary is present. Sometime there are chances that driver file does not get copied so copy it via code. I had used this and it is working perfectly.
#define NDISPROT_SERVICE_PNP_DEVICE_ID_A "PROTOCOL DEVICE NAME"
HRESULT InstallSpecifiedComponent(LPTSTR lpszInfFile, LPTSTR lpszPnpID, const GUID *pguidClass)
{
INetCfg *pnc = NULL;
LPTSTR lpszApp = NULL;
HRESULT hr = S_OK;
hr = HrGetINetCfg(TRUE, APP_NAME, &pnc, &lpszApp);
if(S_OK == hr)
{
//
// Install the network component.
//
PrintMsg(NULL, L"InstallSpecifiedComponent : HrGetINetCfg success.\n");
hr = HrInstallNetComponent(pnc, lpszPnpID, pguidClass, lpszInfFile);
if((S_OK == hr) || (NETCFG_S_REBOOT == hr))
{
PrintMsg(NULL, L"InstallSpecifiedComponent : HrInstallNetComponent success.\n");
hr = pnc->Apply();
if (S_OK == hr)
{
PrintMsg(NULL, L"InstallSpecifiedComponent : Apply success.\n");
}
else
{
PrintMsg(NULL, L"InstallSpecifiedComponent : Apply fail with error code %d.\n", GetLastError());
}
}
else
{
PrintMsg(NULL, L"InstallSpecifiedComponent : HrInstallNetComponent fail with error code %d.\n", GetLastError());
if(HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr)
{
PrintMsg(hr, L"InstallSpecifiedComponent : Couldn't install the network component.");
}
}
HrReleaseINetCfg(pnc, TRUE);
}
else
{
PrintMsg(NULL, L"InstallSpecifiedComponent : HrGetINetCfg fail with error code %d.\n", GetLastError());
if((NETCFG_E_NO_WRITE_LOCK == hr) && lpszApp )
{
PrintMsg(hr, L"InstallSpecifiedComponent : %s currently holds the lock, try later.", lpszApp);
CoTaskMemFree(lpszApp);
}
else
{
PrintMsg(hr, L"InstallSpecifiedComponent : Couldn't the get notify object interface.");
}
}
PrintMsg(NULL, L"InstallSpecifiedComponent : InstallSpecifiedComponent exit.\n");
return hr;
}
DWORD InstallDriver()
{
DWORD nResult = 0;
HRESULT hr = S_OK;
memset(g_szInfFileFullPath, 0, _MAX_PATH * sizeof(TCHAR));
// Get Path to Service INF File
// The INF file is assumed to be in the same folder as this application.
// Below function returns full path for inf file present in same folder
nResult = GetInfFilePath(g_szInfFileFullPath, MAX_PATH);
if(0 == nResult)
{
return nResult;
}
hr = InstallSpecifiedComponent(g_szInfFileFullPath, NDISPROT_SERVICE_PNP_DEVICE_ID, &GUID_DEVCLASS_NETTRANS);
if(S_OK == hr)
{
PrintMsg(NULL, L"InstallDriver : InstallSpecifiedComponent success.\n");
nResult = 1;
}
else
{
PrintMsg(hr, L"InstallDriver : InstallSpecifiedComponent fail with error code %d.\n", GetLastError());
}
PrintMsg(NULL, L"InstallDriver : InstallDriver exit.\n");
return nResult;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
//Driver Installation.
nRetCode = InstallDriver();
if(1 == nRetCode)
{
Sleep(1000 * 2);
// Sometimes driver file does not get copied into systme32\drivers folder, so just for precaution copy it using code
if(CopyDrvFile())
{
system("net start ekaprot6");
}
}
return nRetCode;
}

Can't get SID from DACL

I am trying to get the DACL of service, and then get the SIDs. Here is my code:
PSECURITY_DESCRIPTOR psd = NULL;
DWORD dwSize = 0;
DWORD dwBytesNeeded = 0;
BOOL bDaclPresent = FALSE; // tu Trua mashin aq DACL
PACL pacl = NULL;
BOOL bDaclDefaulted = FALSE;
PEXPLICIT_ACCESS bevri = NULL;
ULONG aq = 0;
char ** gio = NULL;
serviceManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
SC_HANDLE me = OpenService(serviceManager, serviceName, READ_CONTROL);
if (serviceManager == NULL)
{
fprintf(fp, "OpenService: fail %d\n.\n", GetLastError());
fflush(fp);
}
if (!QueryServiceObjectSecurity(me, DACL_SECURITY_INFORMATION, &psd, 0, &dwBytesNeeded))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
dwSize = dwBytesNeeded;
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
if (psd == NULL)
{
fprintf(fp, "HeapAlloc failed\n");
fflush(fp);
}
if (!QueryServiceObjectSecurity(me, DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded))
{
fprintf(fp, "QueryServiceObjectSecurity failed %d\n", (int)GetLastError());
fflush(fp);
}
}
else
{
fprintf(fp, "QueryServiceObjectSecurity failed %d\n", (int)GetLastError());
fflush(fp);
}
}
if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclDefaulted))
{
fprintf(fp, "GetSecurityDescriptorDacl failed %d\n", (int)GetLastError());
fflush(fp);
}
if (GetExplicitEntriesFromAcl(pacl, &aq, &bevri) != ERROR_SUCCESS)
{
fprintf(fp, "GetExplicitEntriesFromAcl: failed %d.\n", (int)GetLastError());
fflush(fp);
}
for (ULONG i = 0; i < aq; i++)
{
if (ConvertSidToStringSid(&bevri->Trustee.ptstrName[GetTrusteeForm(&bevri->Trustee)], gio) == 0)
{
fprintf(fp, "ConvertSidToStringSid: failed %d.\n", (int)GetLastError());
fflush(fp);
}
for (int index = 0; gio[index] != NULL; index++)
{
char * myString = gio[index];
fprintf(fp, "Value: %s\n",myString);
}
}
I've read in documentation that GetTrusteeForm function would indicate if Trustee has SID or name, it returned 0s which in TRUSTEE_FORM indicates to TRUSTEE_IS_SID. My problem is that I have ConvertSidToStringSid: failed 87. which is The parameter is incorrect.. I can't figure out why am I getting this. P.S. I'm sorry I know that this part of code is not really helpful to reproduce the issue, but I thought someone might knew what would problem be. Any help would be appriciated. Thanks.

Is there any way to pair Bluetooth device in Windows programmatically

there's a question:
Is there any way to pair Bluetooth device in Windows programmatically? (c++, c#)
thanks for replies
Yes, the reference documentation is available on MSDN.
32feet.NET is a C# wrapper, available here. Information on pairing is here.
Python is a tempting and overall easy solution, but PyBlueZ does not expose the windows Bluetooth authentication APIs here: https://msdn.microsoft.com/en-us/library/windows/desktop/cc766819(v=vs.85).aspx
One way to get around this is to create a command line tool and use this through Python. To create command line tools for Windows, use Visual Studio and add the necessary libraries to your project linker properties: Bthprops.lib and ws2_32.lib
Below is the code for a project to make a command line tool with 1 parameter, the MAC address, that pairs the specified device using "Just Works" pairing. See commented code for using passkey pairing.
#include "stdafx.h"
#include <initguid.h>
#include <winsock2.h>
#include <BluetoothAPIs.h>
#include <ws2bth.h>
BOOL WINAPI BluetoothAuthCallback(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams);
int _tmain(int argc, _TCHAR* argv[])
{
SOCKADDR_BTH sa = { 0 };
int sa_len = sizeof(sa);
DWORD dwRet;
BLUETOOTH_DEVICE_INFO btdi = { 0 };
HBLUETOOTH_AUTHENTICATION_REGISTRATION hRegHandle = 0;
// initialize windows sockets
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 0);
if (WSAStartup(wVersionRequested, &wsaData) != 0) {
ExitProcess(2);
}
// parse the specified Bluetooth address
if (argc < 2) {
fprintf(stderr, "usage: csbtpair <addr>\n"
"\n addr must be in the form (XX:XX:XX:XX:XX:XX)");
ExitProcess(2);
}
if (SOCKET_ERROR == WSAStringToAddress(argv[1], AF_BTH,
NULL, (LPSOCKADDR)&sa, &sa_len)) {
ExitProcess(2);
}
// setup device info
btdi.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);
btdi.Address.ullLong = sa.btAddr;
btdi.ulClassofDevice = 0;
btdi.fConnected = false;
btdi.fRemembered = false;
btdi.fAuthenticated = false;
// register authentication callback. this prevents UI from showing up.
dwRet = BluetoothRegisterForAuthenticationEx(&btdi, &hRegHandle, &BluetoothAuthCallback, NULL);
if (dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothRegisterForAuthenticationEx ret %d\n", dwRet);
ExitProcess(2);
}
// authenticate device (will call authentication callback)
AUTHENTICATION_REQUIREMENTS authreqs = MITMProtectionNotRequired;
fprintf(stderr, "BluetoothAuthReqs = %d\n", authreqs);
dwRet = BluetoothAuthenticateDeviceEx(NULL, NULL, &btdi, NULL, authreqs);
if (dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothAuthenticateDevice ret %d\n", dwRet);
if (dwRet == ERROR_CANCELLED)
{
fprintf(stderr, "Cancelled");
}
else if (dwRet == ERROR_INVALID_PARAMETER)
{
fprintf(stderr, "Invalid Parameter");
}
else if (dwRet == ERROR_NO_MORE_ITEMS)
{
fprintf(stderr, "Already paired!");
}
}
fprintf(stderr, "pairing finish\n");
ExitProcess(0);
return 0;
}
// Authentication callback
BOOL WINAPI BluetoothAuthCallback(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams)
{
DWORD dwRet;
fprintf(stderr, "BluetoothAuthCallback 0x%x\n", pAuthCallbackParams->deviceInfo.Address.ullLong);
BLUETOOTH_AUTHENTICATE_RESPONSE AuthRes;
AuthRes.authMethod = pAuthCallbackParams->authenticationMethod;
fprintf(stderr, "Authmethod %d\n", AuthRes.authMethod);
// Check to make sure we are using numeric comparison (Just Works)
if (AuthRes.authMethod == BLUETOOTH_AUTHENTICATION_METHOD_NUMERIC_COMPARISON)
{
fprintf(stderr, "Numeric Comparison supported\n");
}
AuthRes.bthAddressRemote = pAuthCallbackParams->deviceInfo.Address;
AuthRes.negativeResponse = FALSE;
// Commented out code is used for pairing using the BLUETOOTH_AUTHENTICATION_METHOD_PASSKEY method
//memcpy_s(AuthRes.pinInfo.pin, sizeof(AuthRes.pinInfo.pin), L"1234", 0);
//AuthRes.pinInfo.pinLength = 0;
// Respond with numerical value for Just Works pairing
AuthRes.numericCompInfo.NumericValue = 1;
// Send authentication response to authenticate device
dwRet = BluetoothSendAuthenticationResponseEx(NULL, &AuthRes);
if (dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothSendAuthenticationResponseEx ret %d\n", dwRet);
if (dwRet == ERROR_CANCELLED)
{
fprintf(stderr, "Bluetooth device denied passkey response or communicatino problem.\n");
}
else if (dwRet == E_FAIL)
{
fprintf(stderr, "Device returned a failure code during authentication.\n");
}
else if (dwRet == 1244)
{
fprintf(stderr, "Not authenticated\n");
}
}
else
{
fprintf(stderr, "BluetoothAuthCallback finish\n");
}
return 1; // This value is ignored
}
In lieu of creating this yourself, you may want to try this pre-made solution:
http://bluetoothinstaller.com/bluetooth-command-line-tools/
It did not work for my particular solution.
Then, you will need to run your downloaded or custom command line tool from python as an administrator. To do this reliably, I recommend the stackoverflow question:
How to run python script with elevated privilege on windows
I meet the same problem,and I have resolved the problem, Maybe you can try it:
make a windows tool named pairtool.exe, it help you to pairing with command line. the key api is BluetoothAuthenticateDevice, please refering the functions document
dwRet = BluetoothAuthenticateDevice(NULL, NULL, &btdi, L"1234", 4);
if(dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothAuthenticateDevice ret %d\n", dwRet);
ExitProcess(2);
}
python code:
def connect2Btdev(devName):
#found the device addr
addr = inquiry(devName)
if addr == None:
return None
#pairing with pairtool.exe
cmd=r'%s %s' % ('pairtool.exe',addr)
ret = os.system(cmd)
if ret <> 0:
return None
here is all the code of pairtool.exe:
#include "stdafx.h"
#include <initguid.h>
#include <winsock2.h>
#include <BluetoothAPIs.h>
#include <ws2bth.h>
bool BluetoothAuthCallback(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams)
{
DWORD dwRet;
fprintf(stderr, "BluetoothAuthCallback 0x%x\n", pAuthCallbackParams->deviceInfo.Address.ullLong);
dwRet = BluetoothSendAuthenticationResponse(NULL, &(pAuthCallbackParams->deviceInfo), L"1234");
if(dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothSendAuthenticationResponse ret %d\n", dwRet);
ExitProcess(2);
return 1;
}
fprintf(stderr, "BluetoothAuthCallback finish\n");
ExitProcess(0);
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
SOCKADDR_BTH sa = { 0 };
int sa_len = sizeof(sa);
DWORD dwRet;
BLUETOOTH_DEVICE_INFO btdi = {0};
HBLUETOOTH_AUTHENTICATION_REGISTRATION hRegHandle = 0;
// initialize windows sockets
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 2, 0 );
if( WSAStartup( wVersionRequested, &wsaData ) != 0 ) {
ExitProcess(2);
}
// parse the specified Bluetooth address
if( argc < 2 ) {
fprintf(stderr, "usage: rfcomm-client <addr>\n"
"\n addr must be in the form (XX:XX:XX:XX:XX:XX)");
ExitProcess(2);
}
if( SOCKET_ERROR == WSAStringToAddress( argv[1], AF_BTH,
NULL, (LPSOCKADDR) &sa, &sa_len ) ) {
ExitProcess(2);
}
//注册回调函数
btdi.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);
btdi.Address.ullLong = sa.btAddr;
btdi.ulClassofDevice = 0;
btdi.fConnected = false;
btdi.fRemembered = false;
btdi.fAuthenticated = false;
dwRet = BluetoothRegisterForAuthenticationEx(&btdi, &hRegHandle, &BluetoothAuthCallback, NULL);
if(dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothRegisterForAuthenticationEx ret %d\n", dwRet);
ExitProcess(2);
}
dwRet = BluetoothAuthenticateDevice(NULL, NULL, &btdi, L"1234", 4);
if(dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothAuthenticateDevice ret %d\n", dwRet);
ExitProcess(2);
}
Sleep(1000);
fprintf(stderr, "pairing finish\n");
ExitProcess(0);
return 0;
}
Microsoft has introduced Windows.Devices.Enumeration API available for UWP and traditional applications, which makes pairing of bluetooth devices very easy (for details look at the official C# and C++ example). As far as I understand it is the API which is used by built-in "Bluetooth & other devices" UI dialog. As of an example of what console utility you can write using this API you can take a look at my console BluetoothDevicePairing utility.
You can do so by using the functions documented under MSDN Bluetooth Functions.
These enable searching and pairing of bluetooth devices programmatically.

How do proxy/stub and typelib marshaling performance compare?

Suppose I need to implement an out-proc COM server and all the COM-interfaces are Automation-compatible. I can either create and register a proxy/stub combination or create and register a type library and rely on Automation marshaller.
I'm well aware of all the maintenance aspects of the two approaches. This question is about runtime performance only.
I can't find any hard data - only claims like
"Automation marshaller is generic, so it is slower" which I won't believe right away because there're just several Automation-compatible types and so switching between them is not that hard
"Automation marshaller will have to load the type library" which is fair point, but this will have to be done only once and if I have hundred thousand COM-calls afterwards I don't care much of that one-time overhead
Is there any measurement data on which - proxy/stub marshaling or typelib marshaling - is faster in the long run?
Once the proxy is created, the performance of PSOAInterface should be identical to that of a /Oicf proxy/stub library, according to Don Box in Essential Com (p. 228) and his Microsoft Systems Journal article (Jan 1999).
But as of Windows 8.1, the creation of the PSOAInterface proxies can be very sub-optimal. Don Box claims in the above article that combase!CreateProxyFromTypeInfo and the type library marshaler perform caching. However, in my testing the type library is reloaded from file after every time you release all your interfaces. This is a significant problem with the UIAutomation library, which uses the IGlobalInterfaceTable extensively, causing a bunch of extra system calls.
Here is my test. One apartment instantiates a coclass, and then another apartment unmarshals it into proxies 10000 times. It takes about 5s when using PSOAInterface. If I instead create and register a MIDL proxy/stub, it only takes about 100ms.
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <comdef.h>
// RemoteProxyFactory32 from oleacc.dll {53362c64-a296-4f2d-a2f8-fd984d08340b}
static IID CLSID_RemoteProxyFactory32 = GUID{ 0x53362c64, 0xa296, 0x4f2d, { 0xa2, 0xf8, 0xfd, 0x98, 0x4d, 0x08, 0x34, 0x0b } };
// IRemoteProxyFactory from oleacc.dll {8628f27d-64a2-4ed6-906b-e6155314c16a}
static IID IID_IRemoteProxyFactory = GUID{ 0x8628f27d, 0x64a2, 0x4ed6, { 0x90, 0x6b, 0xe6, 0x15, 0x53, 0x14, 0xc1, 0x6a } };
struct register_interface_thread {
HANDLE hInterfaceRegistered;
DWORD dwCookie;
HANDLE hShouldClose;
};
DWORD WINAPI RegisterInterfaceThread(_In_ LPVOID lpParameter) {
struct register_interface_thread& state = *(struct register_interface_thread*)(lpParameter);
HRESULT hr;
if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED))) {
fprintf(stderr, "Error CoInitializeEx: 0x%08x\n", hr);
}
else {
IUnknown *pv;
if (FAILED(hr = CoCreateInstance(CLSID_RemoteProxyFactory32, NULL, CLSCTX_LOCAL_SERVER, IID_IRemoteProxyFactory, (LPVOID*)&pv))) {
fprintf(stderr, "CocCreateInstance(RemoteProxyFactory32 of oleacc.dll) failed with hresult 0x%x\n", hr);
}
else {
IGlobalInterfaceTable *pIGlobalInterfaceTable;
if (FAILED(hr = CoCreateInstance
(
CLSID_StdGlobalInterfaceTable,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable,
(void **)&pIGlobalInterfaceTable
))) {
fprintf(stderr, "CocCreateInstance(StdGlobalInterfaceTable) failed with hresult 0x%x\n", hr);
}
else {
DWORD dwCookie;
if (FAILED(hr = pIGlobalInterfaceTable->RegisterInterfaceInGlobal(pv, IID_IRemoteProxyFactory, &dwCookie))) {
fprintf(stderr, "RegisterInterfaceInGlobal failed with hresult 0x%x\n", hr);
}
else {
fprintf(stdout, "Successfully registered interface; cookie=0x%x\n", dwCookie);
state.dwCookie = dwCookie;
if (!SetEvent(state.hInterfaceRegistered)) {
DWORD err = GetLastError();
fprintf(stderr, "Error SetEvent(hInterfaceRegistered): 0x%x\n", err);
}
else {
DWORD waitResult;
if (WAIT_OBJECT_0 != (waitResult = WaitForSingleObject(state.hShouldClose, INFINITE))) {
DWORD err = GetLastError();
fprintf(stderr, "Error WaitForSingleObject: returned 0x%x; error=0x%08x\n", waitResult, err);
hr = err;
}
else {
fprintf(stdout, "Successfully joined thread; dwCookie=0x%x\n", state.dwCookie);
}
}
}
pIGlobalInterfaceTable->Release();
}
if (pv != NULL)
pv->Release();
}
CoUninitialize();
fprintf(stdout, "Thread going away\n");
}
return 0;
}
int main(int argc, char* argv[]) {
HRESULT hr;
if (FAILED(hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) {
fprintf(stderr, "Error CoInitializeEx: 0x%08x\n", hr);
}
else {
struct register_interface_thread state;
state.dwCookie = 0;
state.hInterfaceRegistered = CreateEventEx(NULL, TEXT("hInterfaceRegistered"), CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
state.hShouldClose = CreateEventEx(NULL, TEXT("hShouldClose"), CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
HANDLE hThread = CreateThread(NULL, 0, RegisterInterfaceThread, &state, 0, NULL);
if (hThread == NULL) {
DWORD err = GetLastError();
fprintf(stderr, "Error CreateThread: 0x%08x\n", err);
hr = err;
}
else {
DWORD waitResult;
if (WAIT_OBJECT_0 != (waitResult = WaitForSingleObject(state.hInterfaceRegistered, INFINITE))) {
DWORD err = GetLastError();
fprintf(stderr, "Error WaitForSingleObject: returned 0x%x; error=0x%08x\n", waitResult, err);
hr = err;
}
else {
fprintf(stdout, "Successfully waited for hInterfaceRegistered; dwCookie=0x%x\n", state.dwCookie);
IGlobalInterfaceTable *pIGlobalInterfaceTable;
if (FAILED(hr = CoCreateInstance
(
CLSID_StdGlobalInterfaceTable,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable,
(void **)&pIGlobalInterfaceTable
))) {
fprintf(stderr, "CoCreateInstance(StdGlobalInterfaceTable) failed with hresult 0x%x\n", hr);
}
else {
IUnknown *pv = NULL;
DWORD start_time = GetTickCount();
DWORD i;
for (i = 0; i != 10000; i++) {
if (FAILED(hr = pIGlobalInterfaceTable->GetInterfaceFromGlobal(state.dwCookie, IID_IRemoteProxyFactory, (LPVOID*)&pv))) {
fprintf(stderr, "GetInterfaceFromGlobal failed with hresult 0x%x\n", hr);
break;
}
else {
pv->Release();
}
}
DWORD end_time = GetTickCount();
DWORD difference = end_time - start_time;
fprintf(stdout, "%u iterations completed in %ums\n", i, difference);
pIGlobalInterfaceTable->Release();
}
if (!SetEvent(state.hShouldClose)) {
DWORD err = GetLastError();
fprintf(stderr, "SetEvent(hShouldClose) failed; err=0x%x\n", err);
hr = err;
}
else {
if (WAIT_OBJECT_0 != (waitResult = WaitForSingleObject(hThread, INFINITE))) {
DWORD err = GetLastError();
fprintf(stderr, "Error WaitForSingleObject(hThread): returned 0x%x; error=0x%08x\n", waitResult, err);
hr = err;
}
else {
printf("successfully joined thread.\n");
}
}
}
}
}
return hr;
}
Running it in windbg confirms that it reloads the type library 10000 times.
bp KERNELBASE!CreateFileW "r $t0 = #$t0 + 1; g"
bp OLEAUT32!LoadTypeLibEx "r $t1 = #$t1 + 1; g"
g
r $t0, $t1
$t0=000000000000c35c $t1=0000000000002712

How to tell digital camera from other devices using WPD and using Setup API

I've got 2 tasks:
a) distinguish digital cameras from other MTP-devices, obtained by IPortableDeviceManager::GetDeviceList;
b) I want to find connected digital cameras with Setup API. My thought was to get all USB devices first:
SetupDiGetClassDevs( &GUID_DEVINTERFACE_USB_DEVICE, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
But after doing that I've run out of ideas. Specifically, I can't figure out how to obtain USB interface descriptors for a specific USB device. I mean USB interfaces, not what is called an interface in setup API.
Thanks in advance.
Here's how it's done with WPD (assuming you have an already opened device named wpdDev):
IPortableDeviceCapabilities* pCaps = 0;
IPortableDevice* pWpdDev = wpdDev.getWpdDev();
hr = pWpdDev->Capabilities(&pCaps);
if (hr != S_OK || !pCaps)
{
Logger() << "Failed to obtain capabilities for device" << CString::fromUtf16(deviceId).toUtf8().getData();
continue;
}
IPortableDevicePropVariantCollection* pCategories = 0;
hr = pCaps->GetFunctionalCategories(&pCategories);
if (hr != S_OK || !pCategories)
{
Logger() << "Failed to obtain functional categories for device" << CString::fromUtf16(deviceId).toUtf8().getData();
continue;
}
DWORD numCategories = 0;
hr = pCategories->GetCount(&numCategories);
if (hr != S_OK || !numCategories)
{
Logger() << "Failed to obtain functional categories for device" << CString::fromUtf16(deviceId).toUtf8().getData();
continue;
}
bool isCamera = wpdDev.vendor() == CANON_VENDOR_ID;
//Просматриваем все категории и проверяем, может ли устройство выполнять функции камеры
for (size_t idx = 0; idx < numCategories; ++idx)
{
PROPVARIANT pv = {0};
PropVariantInit(&pv);
hr = pCategories->GetAt(idx, &pv);
if (hr == S_OK)
// We have a functional category. It is assumed that
// functional categories are returned as VT_CLSID
// VarTypes.
if ((pv.puuid != NULL) && (pv.vt == VT_CLSID))
if (IsEqualGUID(WPD_FUNCTIONAL_CATEGORY_STILL_IMAGE_CAPTURE, *(pv.puuid)))
isCamera = true;
PropVariantClear(&pv);
}

Resources