how to get serial number via win32 wpd api - winapi

as shown in title, i search on google for this question, but there seems that no way get serial number via WPD(Windows Portable Device) api, and in MSDN, i found the WPD_DEVICE_SERIAL_NUMBER property of Portable Device, can anyone tell me how to get this property using wpd api?

The C++ sample can be found here and here

Bit of a process. Basic steps are as follows:
Get and populate a IPortableDeviceValues of your client info
// Create our client information collection
ThrowIfFailed(CoCreateInstance(
CLSID_PortableDeviceValues,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&clientInfo)));
// We have to provide at the least our name, version, revision
ThrowIfFailed(clientInfo->SetStringValue(
WPD_CLIENT_NAME,
L"My super cool WPD client"));
ThrowIfFailed(clientInfo->SetUnsignedIntegerValue(
WPD_CLIENT_MAJOR_VERSION,
1));
ThrowIfFailed(clientInfo->SetUnsignedIntegerValue(
WPD_CLIENT_MINOR_VERSION,
0));
ThrowIfFailed(clientInfo->SetUnsignedIntegerValue(
WPD_CLIENT_REVISION,
1));
Get an IPortableDevice with CoCreateInstance
// A WPD device is represented by an IPortableDevice instance
ThrowIfFailed(CoCreateInstance(
CLSID_PortableDevice,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&device)));
Connect to the device using IPortableDevice::Open, passing the device's ID and the above client info
device->Open(deviceId.c_str(), clientInfo);
Get the device's IPortableDeviceContent using IPortableDevice::Content
CComPtr<IPortableDeviceContent> retVal;
ThrowIfFailedWithMessage(
device.Content(&retVal),
L"! Failed to get IPortableDeviceContent from IPortableDevice");
Get the content's IPortableDeviceProperties using IPortableDeviceContent::Properties
CComPtr<IPortableDeviceProperties> retVal;
ThrowIfFailedWithMessage(
content.Properties(&retVal),
L"! Failed to get IPortableDeviceProperties from IPortableDeviceContent");
Get the properties' IPortableDeviceValues using IPortableDeviceProperties::GetValues, passing "DEVICE" for pszObjectID and nullptr for pKeys
CComPtr<IPortableDeviceValues> retVal;
ThrowIfFailedWithMessage(
properties.GetValues(objectId.c_str(), nullptr, &retVal),
L"! Failed to get IPortableDeviceValues from IPortableDeviceProperties");
Get the serial number from the values using IPortableDeviceValues::GetStringValue, passing WPD_DEVICE_SERIAL_NUMBER for key
propertyKey = WPD_DEVICE_SERIAL_NUMBER;
LPWSTR value = nullptr;
ThrowIfFailedWithMessage(
values.GetStringValue(propertyKey, &value),
L"! Failed to get string value from IPortableDeviceValues");
propertyValue = value;
if (value != nullptr)
{
CoTaskMemFree(value);
}
By no means a complete listing, sorry. The ThrowIf* functions are just basic helpers I wrote to go from checking HRESULTs to throwing exceptions. Hopefully this points you in the right direction.
Additional references:
The dimeby8 blog
WPD Application Programming Interface

Related

IOCreatePlugInInterfaceForService failed w/ kIOReturnNoResources/0xe00002be

IOCreatePlugInInterfaceForService failed w/ kIOReturnNoResources/0xe00002be
I am rewriting old FireWire based command line utility into XPCService. I need some help about an IOKit function.
Following part is to get IOCFPlugInInterface for FireWireAVCLibUnit.(almost same as original code; basic idea comes from legacy simpleAVC samplecode).
When I call IOCreatePlugInInterfaceForService() in the XPCService, it always failed returning 0xe00002be = kIOReturnNoResources in IOReturn.h.
I have confirmed no sandbox, no hardened for the XPC Service.
Original command line utility works perfectly on macOS 10.14 though, would you someone give me a hint on this topic?
CFDictionaryRef dict = CFDictionaryCreateCopy(kCFAllocatorDefault, self.dict);
kern_return_t result = IOServiceGetMatchingServices(kIOMasterPortDefault, dict, &serviceIterator);
if (result == KERN_SUCCESS && serviceIterator != IO_OBJECT_NULL) {
while ((service = IOIteratorNext(serviceIterator)) != IO_OBJECT_NULL) {
SInt32 score = 0;
kern_return_t result = IOCreatePlugInInterfaceForService(service,
kIOFireWireAVCLibUnitTypeID,
kIOCFPlugInInterfaceID,
&interface,
&score);
if (result != KERN_SUCCESS) continue;
// result 0xe00002be = kIOReturnNoResources in IOReturn.h
break;
}
}
Additional details
I have find IOCFPlugIn.c in opensource.apple.com. After basic verification,
- IOCreatePlugInInterfaceForService() failed to IOCFPlugIn->Start() .
(*iunknown)->QueryInterface(iunknown, CFUUIDGetUUIDBytes(interfaceType),
(LPVOID *)&interface);
<snip>
kr = (*interface)->Probe(interface, plist, service, &score);
<snip>
haveOne = (kIOReturnSuccess == (*interface)->Start(interface, plist, service));
Probe() returned kIOReturnSuccess though,
Start() failed w/ kIOReturnNoDevice = 0xe00002c0. and haveOne = false.
Finally IOCreatePlugInInterfaceForService() returned kIOReturnNoResources = 0xe00002be.
Is this related to some security feature on macOS?
MODIFIED
I have found hardened runtime with Camera access was rejected FireWireAVCLibUnit (tccd shows error).
Even if no sandbox, no hardened for the XPC Service in Xcode was checked, XPCservice is handled via sandbox. (macOS 10.14.6 + Xcode 10.3)
I would appreciate if you have an advice.
I have found the solution.
- Add NSCameraUsageDescription in Info.plist, and IOFireWireAVCUserClient will work.
- If sandboxed, com.apple.security.device.firewire is also required.
Even if capabilities-sandbox is off, tccd verify info.plist.
If “Privacy - Camera Usage Description” is not available, sandboxd reject to use IOFireWireAVCUserClient device.
Information Property List Key Reference/Cocoa Keys

IPropertyStore_Commit method - is it needed and why isn't it implemented?

I'm trying to change the value of a flag in an IPropertyStore. However, my code seems to behave the same way, regardless of the value of the flag.
Is this because my code doesn't call IPropertyStore_Commit after changing the flag?
I did try to call the method, however I got an error code 0x80004001 which means "not implemented". Hence, the second part of my question: why isn't it implemented?
In more detail, I'm working on a Java softphone which makes use of WASAPI (via the JNI) for some of the audio processing. The native code is written in C.
Having recently enabled AES (Acoustic Echo Suppression), I've found that AGC (Automatic Gain Control) is also enabled. I'm trying to disable AGC by setting the MFPKEY_WMAAECMA_FEATR_AGC key on an IPropertyStore object. However, whatever I set the value to be makes no difference.
The relevant code snippets are as follows:
// Obtain the property store
void *pvObject;
HRESULT hr = IMediaObject_QueryInterface((IMediaObject *) thiz, &iid_, &pvObject);
// Do some checking that the store is valid...
// Set the value of the AGC key:
PROPVARIANT propvar = ...
IPropertyStore_SetValue((IPropertyStore *)pvObject, (REFPROPERTYKEY) key, &propvar);
// Call commit - fails, with 0x80004001:
HRESULT hr = IPropertyStore_Commit((IPropertyStore *)pvObject);
A couple of issues:
I'm not sure what thiz actually is; I'm pretty sure it's not an IMediaObject interface.
You can't just cast from IMediaObject to IPropertyStore; you have to QueryInterface the IMediaObject pointer for IPropertyStore.
You shouldn't need to call IPropertyStore_Commit; at least, not for setting the AGC key.
When you're calling IPropertyStore_SetValue, make sure the PROPVARIANT is initialized correctly. MFPKEY_WMAAECMA_FEATR_AGC is a BOOLEAN property, so your code needs to look something like this:
IMediaObject *pvObject;
HRESULT hr = IUnknown_QueryInterface((IUnknown*) thiz, IID_PPV_ARGS(&pvObject));
if (SUCCEEDED(hr))
{
IPropertyStore* pvPropStore;
hr = IMediaObject_QueryInterface(pvObject, IID_PPV_ARGS(&pvPropStore));
if (SUCCEEDED(hr))
{
PROPVARIANT pvFeature;
PropVariantInit(&pvFeature);
pvFeature.vt = VT_BOOL;
pvFeature.boolVal = fValue ? VBTRUE : VBFALSE;
hr = IPropertyStore_SetValue(pvPropStore, MFPKEY_WMAAECMA_FEATR_AGC, pvFeature);
}
}

How to get device descriptor and configuration descriptor of usb device in Mac?

I have minimum exposure to xcode and I/Okit framework. I have seen device descriptor and configuration descriptor of a usb device in USB prober.
I have written an xcode program using I/O kit framework which gives the usb device name as output, when we give product id and vendor id of that device as input.
/*Take the vendor and product id from console*/
printf("\nEnter the vendor id : ");
scanf("%lx",&usbVendor);
printf("\nEnter the product id :");
scanf("%lx",&usbProduct);
/* Set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
if (matchingDict == NULL)
{
return -1; // fail
}
// Create a CFNumber for the idVendor and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor);
CFDictionarySetValue(matchingDict,
CFSTR(kUSBVendorID),
numberRef);
CFRelease(numberRef);
// Create a CFNumber for the idProduct and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct);
CFDictionarySetValue(matchingDict,
CFSTR(kUSBProductID),
numberRef);
CFRelease(numberRef);
numberRef = NULL;
/*Get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS)
{
return -1;// fail
}
/* iterate */
while ((device = IOIteratorNext(iter)))
{
/*Display the device names */
io_name_t deviceName;
kr = IORegistryEntryGetName(device, deviceName);
if (KERN_SUCCESS != kr) {
deviceName[0] = '\0';
}
printf("\ndeviceName:%s",deviceName);
/*Free the reference taken before continuing to the next item */
IOObjectRelease(device);
}
/*Release the iterator */
IOObjectRelease(iter);
return 0;
}
I need to modify this, so that on giving vendor and product id of usb device, i will get the device descriptor and configuration descriptor( as shown in USB prober) as output.
Here i just gave an example, code can change but the output must be the descriptor( atleast the device decriptor).
Thanks in advance...
I think u should download the source code of USBProber rather than figure it out by yourself.
All the information presents in the USBProber u could get sooner or later by analyzing the source code.
Here is link to download the source code of IOUSBFamily, with USBProber inside it.
http://opensource.apple.com/tarballs/IOUSBFamily/
To get the configuration descriptors you can use code like this:
IOUSBDeviceInterface650** dev = ...;
IOUSBConfigurationDescriptor* configDesc = nullptr;
// Get the configuration descriptor for the first configuration (configuration 0).
kern_return_t kr = (*dev)->GetConfigurationDescriptorPtr(dev, 0, &configDesc);
if (kr != kIOReturnSuccess)
return an_error;
// Now use configDesc->...
Unfortunately there doesn't seem to be a function to get the device descriptor. There are functions to get some of it:
kr = (*dev)->GetDeviceClass(dev, &desc.bDeviceClass);
kr = (*dev)->GetDeviceSubClass(dev, &desc.bDeviceSubClass);
kr = (*dev)->GetDeviceProtocol(dev, &desc.bDeviceProtocol);
kr = (*dev)->GetDeviceVendor(dev, &desc.idVendor);
kr = (*dev)->GetDeviceProduct(dev, &desc.idProduct);
kr = (*dev)->GetDeviceReleaseNumber(dev, &desc.bcdDevice);
kr = (*dev)->GetNumberOfConfigurations(dev, &desc.bNumConfigurations);
But I don't see a way to get iManufacturer, iProduct, iSerial, bMaxPacketSize0, or bcdUSB.
There is a way around this - instead of using the built-in functions you can just do a control request to get the device descriptor (and configuration descriptors if you like) manually using a control transfer.
The USB 2.0 spec describes how to do this. Basically you:
Do a control transfer with bmRequestType = Device | Standard | In, bRequest = USB_GET_DESCRIPTOR_REQUEST, wValue = (USB_DEVICE_DESCRIPTOR_TYPE << 8), wIndex = 0, wLength = 2. That will fail because the descriptor is longer than 2, but it gets you the descriptor header which includes its length.
Repeat that request but with the correct length.
For configuration descriptors, do a third request with length wTotalLength.
You can do it with one less request since you know the size of the descriptors in advance, but I like to do it like that because then you can wrap it up in a very general getDescriptor() method.
In theory you can do it as simply as this:
IOUSBDeviceDescriptor devDesc;
IOUSBDevRequest request;
request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
request.bRequest = kUSBRqGetDescriptor;
request.wValue = kUSBDeviceDesc << 8;
request.wIndex = 0;
request.wLength = sizeof(devDesc); // 18
request.pData = &devDesc;
request.wLenDone = 0;
kern_return_t kr = (*dev)->DeviceRequest(dev, &request);
But for some reason that is giving me a kIOUSBPipeStalled error. Not sure why.
Edit: I forgot the << 8. Now it works. :-)
The header IOKit/usb/USBSpec.h has a documented list of property keys corresponding to values inside the different descriptors. You can use those with IORegistryEntrySearchCFProperty (or similar functions) to get the descriptor values. This way you don't need a device request from an IOUSBDeviceInterface, which is advantageous because:
the documentation (comments) say that all device requests require an opened USB device and you may not have permission to do that for all devices (it's possible the documentation is wrong, at least for descriptor requests, but I have no guarantee of that and it seems better to follow it anyway)
device requests can block for an indeterminate amount of time
the manufacturer, product, and serial number strings (which are referenced by the device descriptor, but are not technically part of it) are not retrieved in this request
For getting device descriptor and configuration decriptor, we can use functions in IOUSBDeviceInterface class
Link: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/IOKit/IOUSBLib_h/Classes/IOUSBDeviceInterface/index.html#//apple_ref/doc/com/intfm/IOUSBDeviceInterface/
For getting interface descriptor and end point descriptor, we can use functions in IOUSBInterfaceInterface class
Link: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/IOKit/IOUSBLib_h/Classes/IOUSBInterfaceInterface/

What is Target Device of IOCTL_USB_GET_ROOT_HUB_NAME (USB driver specific IOCTL IRQ)

I am a bit confused by the USB IOCTL IOCTL_USB_GET_ROOT_HUB_NAME. What is the target device of it? Although the MSDN WDK doc clearly indicates the target device, I am still confused by the USBVIEW sample provided by the WDK. The reason I'm confused is as follows:
I am new to kernel mode and USB driver writing in Windows and is now studying the USBVIEW sample from the windows driver kit http://msdn.microsoft.com/en-us/library/ff558728(v=vs.85).aspx. The MSDN describes the first step the USBVIEW sample performs as:
Enumerate host controllers and root
hubs. Host controllers have symbolic
link names of the form "HCDx", where x
starts at 0.
Use CreateFile() to open each host
controller symbolic link.
Create a node in the tree view to
represent each host controller.
After a host controller has been
opened, send the host controller an
IOCTL_USB_GET_ROOT_HUB_NAME request to
get the symbolic link name of the root
hub that is part of the host
controller
But, I double checked the usage of IOCTL_USB_GET_ROOT_HUB_NAME in MSDN http://msdn.microsoft.com/en-us/library/ff537326(v=VS.85).aspx
which says:
IOCTL_USB_GET_ROOT_HUB_NAME is a
user-mode I/O control request. This
request targets the USB hub FDO.
Note that the target of the IOCTL_USB_GET_ROOT_HUB_NAME IRP is a USB Hub FDO. However, as described by the USBVIEW sample, we just retreived the host controller symbolic link which means the device object is a host controller device object. How could we send it a IOCTL_USB_GET_ROOT_HUB_NAME IRP? Should we retreive a USB hub FDO somehow first?
I would guess it's an unfortunate copy-paste error. IOCTL_USB_GET_ROOT_HUB_NAME is indeed sent to the host controller and therefore handled by the USB Host Controller FDO.
By the way, just to put you in context:
The term "FDO" only loosely concerns user mode -- it's not like you can access any other "xDO" anyway. If you were to send this IOCTL in kernel mode, then sure, you can send an IOCTL to any specific device object in the device stack ("can" doesn't mean "should", mind you). However, a DeviceIoControl from a user mode application always sends IOCTLs to the top of the device stack (therefore it passes all the filters, the FDO and down to the PDO).
This question was asked on March 28, so I really hope you've solved it by now :)
As the documentation states you will need a handle to the USB host controller but it is not very clear on how you are supposed to get such a handle. In USBView something similar to this function is used to get the device path name by passing GUID_DEVINTERFACE_USB_HOST_CONTROLLER (include initguid.h and usbiodef.h):
vector<wstring> EnumDevices(
_In_ const GUID Guid
)
{
vector<wstring> r;
int index = 0;
HDEVINFO hDevInfo = SetupDiGetClassDevs(&Guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SP_DEVINFO_DATA DevInfoData;
memset(&DevInfoData, 0, sizeof(SP_DEVINFO_DATA));
DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
while (SetupDiEnumDeviceInfo(hDevInfo, index, &DevInfoData)) {
index++;
int jndex = 0;
SP_DEVICE_INTERFACE_DATA DevIntData;
memset(&DevIntData, 0, sizeof(SP_DEVICE_INTERFACE_DATA));
DevIntData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
while (SetupDiEnumDeviceInterfaces(
hDevInfo,
&DevInfoData, &Guid, jndex, &DevIntData
)) {
jndex++;
// Get the size required for the structure.
DWORD RequiredSize;
SetupDiGetDeviceInterfaceDetail(
hDevInfo, &DevIntData, NULL, NULL, &RequiredSize, NULL
);
PSP_DEVICE_INTERFACE_DETAIL_DATA pDevIntDetData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + RequiredSize
);
memset(pDevIntDetData, 0, sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + RequiredSize);
pDevIntDetData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
SetupDiGetDeviceInterfaceDetail(
hDevInfo,
&DevIntData,
pDevIntDetData, RequiredSize,
NULL,
&DevInfoData
);
r.push_back(wstring(pDevIntDetData->DevicePath));
free(pDevIntDetData);
}
}
return r;
}
Keep in mind using the above function you can also request devices of type GUID_DEVINTERFACE_USB_HUB and GUID_DEVINTERFACE_USB_DEVICE which may eliminate any need to interact with the host controller or hubs directly.

Determine the registered application for an extension

I've got a file extension and I'd like to get the name of the application (if there is one) that will be invoked when I ShellExecute a file of that type. This is a WTL/C++ app. Is there any sample code out there that does this?
Thanks!
twk,
You're probably looking for the Win32 AssocQueryStringByKey Function.
http://msdn.microsoft.com/en-us/library/bb773473(VS.85).aspx
The ASSOCSTR value that specifies the type of string that is to be returned:
typedef enum {
ASSOCSTR_COMMAND = 1,
ASSOCSTR_EXECUTABLE,
ASSOCSTR_FRIENDLYDOCNAME,
ASSOCSTR_FRIENDLYAPPNAME,
ASSOCSTR_NOOPEN,
ASSOCSTR_SHELLNEWVALUE,
ASSOCSTR_DDECOMMAND,
ASSOCSTR_DDEIFEXEC,
ASSOCSTR_DDEAPPLICATION,
ASSOCSTR_DDETOPIC,
ASSOCSTR_INFOTIP,
ASSOCSTR_QUICKTIP,
ASSOCSTR_TILEINFO,
ASSOCSTR_CONTENTTYPE,
ASSOCSTR_DEFAULTICON,
ASSOCSTR_SHELLEXTENSION,
ASSOCSTR_DROPTARGET,
ASSOCSTR_DELEGATEEXECUTE,
ASSOCSTR_MAX
} ASSOCSTR;
My guess is that you want ASSOCSTR_FRIENDLYAPPNAME.
DWORD dwSize = 255;
TCHAR sBuffer[MAX_PATH] = {0};
HRESULT hr = AssocQueryString(0, ASSOCSTR_EXECUTABLE, _T(".htm"), _T("Open"), sBuffer, &dwSize);
CString csExt;
csExt.Format(_T("%s"), sBuffer);
AfxMessageBox(csExt);
Sorry, no code, but some useful information. See this related question: how-does-vista-generate-the-icon-for-documents-associated-to-my-application
It asked about icons, but it turns out the program associated to an extension is stored in the same place in the registry as the icon for that extension.
It's a Win32 FAQ since 1995 (Shell, see Google Groups, Win32)

Resources