IOBluetoothDevice openConnection fails - identify error code - cocoa

I am writing a Cocoa application which uses bluetooth. I am trying to connect to a bluetooth device but it fails.
IOBluetoothDevice *btDevice;
// I do search and find the device
btDevice = ;//device found
//btDevice is not nil
IOReturn status = [btDevice openConnection];
if (status != kIOReturnSuccess) {
NSLog( #"Error - failed to connect. %d", status );
}
And I get the device when searches, but openConnection method fails. And NSLog prints
Error = failed to connect. 4
Now what this error code indicates?
I looked at IOKit.framework/IOReturn.h file and it shows many error codes
#define kIOReturnError iokit_common_err(0x2bc) // general error
#define kIOReturnNoMemory iokit_common_err(0x2bd) // can't allocate memory
#define kIOReturnNoResources iokit_common_err(0x2be) // resource shortage
#define kIOReturnIPCError iokit_common_err(0x2bf) // error during IPC
#define kIOReturnNoDevice iokit_common_err(0x2c0) // no such device
.......
//And many more
And I wrote a function to identify what is error code 4
- (void)logError:(OSStatus)status{
if (status == kIOReturnError) {
NSLog(#"kIOReturnError");
}else if(status == kIOReturnNoMemory){
NSLog(#"kIOReturnNoMemory");
}else if(status == kIOReturnNoResources){
NSLog(#"kIOReturnNoResources");
}else if(status == kIOReturnIPCError){
NSLog(#"kIOReturnIPCError");
}else if(status == kIOReturnNoDevice){
......
......
}else{
NSLog(#"No price for you");
}
}
And it prints
No price for you
What does error code 4 imply? Also is there any easier way to identify error reason from OSStatus error codes?

[IOBluetoothDevice openConnection] returns an IOReturn code (which is a I/O Kit specific error number) while your logError: method tests for OSStatus codes.
OSStatus is not the same as IOReturn.
Apple has a Technical Q&A that explains the macros to lookup I/O Kit errors.
http://developer.apple.com/library/mac/#qa/qa1075/_index.html
In your case it seems to be a Mach error (that's probably the 0x4 hi bits of the error that show up as decimal 4 in your log line).

I think the 4 response is actually kBluetoothHCIErrorPageTimeout. The only code I've found that uses this is this: https://www.ida.liu.se/~TDDD63/projects/2013/mindstorms/Installation/Mac/lightblue-0.4-master/src/mac/_bluetoothsockets.py

Related

Unable to update Console Cursor Info (PCONSOLE_CURSOR_INFO) due to security

In console application, I want to write the output at a specific location and there should be no cursor at the console (Windows CMD). To do so, I got following way:
HANDLE hdl = GetStdHandle(STD_OUTPUT_HANDLE);
if (hdl == INVALID_HANDLE_VALUE)
{
printf("Error : Unable to get console handle.\n");
return 0;
}
PCONSOLE_CURSOR_INFO lpConsoleCursorInfo = { NULL };
if (!GetConsoleCursorInfo(hdl, &lpConsoleCursorInfo))
{
printf("Error : Unable to get console cursor information.\n");
return 0;
}
lpConsoleCursorInfo->dwSize = 1; //App exit at this point with error code 0xC0000005h
I got runtime error 0xC0000005h. By searching, I have reach at the conclusion that it is a security level issue, and to setup access level SECURITY_DESCRIPTOR is used.
I am unable to find the way how to set the access level to STD_OUTPUT_HANDLE that already created and associated with my console application by visual studio console application.
Can someone point me in the right direction?
There is no security issue, you simply don't understand how Windows pointer types work. PCONSOLE_CURSOR_INFO is just a pointer, remove the P.
CONSOLE_CURSOR_INFO ConsoleCursorInfo = { NULL };
if (!GetConsoleCursorInfo(hdl, &ConsoleCursorInfo)) ...
else ConsoleCursorInfo.dwSize = ...

How to get parameters of an Picture Transfer Protocol event in Windows Portable Devices?

I'm trying to support a digital camera with WPD. I have working request/data/response communication (PTP types 1,2,3), but have problems with events (type 4). From the event I need a command code (ex. 0xc102) and up to three integer parameters.
I have registered and am receiving events using the code from Microsoft's Portable Devices COM API Sample, and it catches the occurrence of the event easily - but I have no way to get the parameters. The command code is not provided directly, but it is embedded as part of the (supposedly random) CLSID.
I have tried to use the event object's IPortableDeviceValues as I would in parsing a response, but when trying to call GetIPortableDevicePropVariantCollectionValue the API returns a HRESULT of ERROR_NOT_FOUND (0x80070490). This call is used in getting params from the response object.
I tried (code inserted in CPortableDeviceEventsCallback::OnEvent):
HRESULT hr;
// Try to get all available data from the event:
DWORD pcelt{};
pEventParameters->GetCount(&pcelt);
printf("pEventParameters->GetCount: %d\n", pcelt);
for (unsigned int i = 0; i < pcelt; i++)
{
PROPERTYKEY pk;
PROPVARIANT pv;
pEventParameters->GetAt(i, &pk, &pv);
printf("PARAM %ws %d -> ", (PWSTR)CGuidToString(pk.fmtid), pk.pid);
switch (pv.vt)
{
case VT_UNKNOWN: printf("unknown\n"); break;
case VT_LPWSTR: printf("VT_LPWSTR: %ws\n", pv.pwszVal); break;
case VT_CLSID:
{
// note that OLECHAR is a typedef'd wchar_t
WCHAR szGUID[64] = { 0 };
_GUID guid = *pv.puuid;
(void)StringFromGUID2(guid, szGUID, 64);
printf("VT_CLSID: %ws\n", szGUID);
break;
}
default: printf("not supported vt %d\n", pv.vt); break;
}
}
// PRINTED: pEventParameters->GetCount: 3
// PRINTED: PARAM {15AB1953-F817-4FEF-A921-5676E838F6E0} 3 -> VT_CLSID: {C1020000-5738-4FF2-8445-BE3126691059}
// PRINTED: PARAM {4D545058-EF88-4E4D-95C3-4F327F728A96} 1011 -> VT_IUNKNOWN
// PRINTED: PARAM {15AB1953-F817-4FEF-A921-5676E838F6E0} 2 -> VT_LPWSTR: \\?\usb#vid_04da&pid_2382#0000000000000000000xhr1805180002#{6ac27878-a6fa-4155-ba85-f98f491d4f33}
// Try to get response code as if this was response (PTP type 3) - ERROR_NOT_SUPPORTED
DWORD dwResponseCode{};
hr = pEventParameters->GetUnsignedIntegerValue(WPD_PROPERTY_MTP_EXT_RESPONSE_CODE, &dwResponseCode);
assert(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
// Try to get params as if this was response (PTP type 3) - ERROR_NOT_SUPPORTED
CComPtr<IPortableDevicePropVariantCollection> spRespParams;
hr = pEventParameters->GetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_MTP_EXT_RESPONSE_PARAMS, &spRespParams);
assert(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
I also tried to get WPD_EVENT_PARAMETER_OBJECT_PARENT_PERSISTENT_UNIQUE_ID and WPD_EVENT_PARAMETER_OBJECT_CREATION_COOKIE from it, but they are not set.
There is also WPD_EVENT_ATTRIBUTE_OPTIONS, WPD_EVENT_ATTRIBUTE_NAME and WPD_EVENT_ATTRIBUTE_PARAMETERS - but I have no idea on how to get to them, nor is there anything of interest inside.
Or maybe what I seek is in the IUNKNOWN that I ignore in the switch case? But what type could it be?
The data is there, I can see it in Wireshark+USBPcap and other PTP applications use it.
Found the answer in https://blogs.msdn.microsoft.com/dimeby8/2006/10/06/listening-to-mtp-events/
It was the IUnknown, and it's type was IPortableDevicePropVariantCollection with GUID 4D545058-EF88-4E4D-95C3-4F327F728A96.

What's the meaning of the error value 0x16f returned by the GetLastError() function

When I call the function CreateProcessAsUser(), it returns a failure.
And then the call to GetLastError() to check why the error occurred returns the value 0x16f.
I couldn't find out what the error is supposed to mean.
ERROR_CHILD_PROCESS_BLOCKED is converted NTSTATUS - STATUS_CHILD_PROCESS_BLOCKED (0xC000049D) - I search in ntoskrnl.exe and found that this code referenced only from 2 place when NtCreateUserProcess called - from SeSubProcessToken and for log error:
NtCreateUserProcess
PspAllocateProcess
PspInitializeProcessSecurity
SeSubProcessToken
if (!SeTokenIsNoChildProcessRestricted(Token))
{
status = STATUS_CHILD_PROCESS_BLOCKED;
}
if (PspAllocateProcess() == STATUS_CHILD_PROCESS_BLOCKED)
{
EtwTraceDeniedTokenCreation();
}
so when SeTokenIsNoChildProcessRestricted(Token) return FALSE you can got ERROR_CHILD_PROCESS_BLOCKED from CreateProcess.
this is new api, exist only from 1607 build of win10
#if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
NTKERNELAPI
BOOLEAN
SeTokenIsNoChildProcessRestricted(
_In_ PACCESS_TOKEN Token
);// return (Token->TokenFlags & 0x80000) != 0;
#endif
declared in ntifs.h but not documented.
so process, which fail call CreateProcessAsUser is somehow restricted. Windows Store sandbox , as how Harry Johnston guess ?

DeviceIoControl error 1 incorrect function

I have created a device in kernel space and the access it in user space using CreateFile I am able to send ioctl to the driver and they are executed properly. The don't know how to trace what happens after WdfRequestComplete and upon return I end with error 1 (invalid function). Before this is flagged as dup please note there is a difference with this in that I write my driver ioctl and in that I am using synch io not asynch.
In user space:
fd = CreateFile(dev_path,
(FILE_GENERIC_READ | FILE_GENERIC_WRITE),
(FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL, OPEN_EXISTING, 0, NULL);
// ... error checking code here
DeviceIoControl(fd, // device handler
VIRTQC_CMD_MMAP, // command to send
&inputBuffer,
inputBufferLength,
&outputBuffer,
outputBufferLength,
&returnLength,
(LPOVERLAPPED)NULL); // overlapped structure not needed using sync io
and in Kernel space
status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &inputBuffer, NULL);
if (!NT_SUCCESS(status))
{
WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
return;
}
inputVirtArg = (VirtioQCArg*)inputBuffer;
status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &outputBuffer, NULL);
if (!NT_SUCCESS(status))
{
WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
return;
}
outputVirtArg = (VirtioQCArg*)outputBuffer;
switch (IoControlCode)
{
case VIRTQC_CMD_MMAP:
if (PsGetCurrentThread() == irp->Tail.Overlay.Thread)
{
status = CreateAndMapMemory(device, &(inputVirtArg), &(outputVirtArg));
outputVirtArg->flag = (!NT_SUCCESS(status)) ? 0 : 1;
}
else
status = STATUS_UNSUCCESSFUL;
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
WdfRequestComplete(Request, status);
Update 1:
I have tried WdfRequestCompleteWithInformation(Request, status, OutputBufferLength); but same result.
Also, I notice that the address of inputBuffer and outputBuffer are the same.
Update 2:
I tried doing
temp = ExAllocatePoolWithTag(
NonPagedPool,
PAGE_SIZE,
MEMORY_TAG
);
// other code to
RtlCopyMemory((VirtioQCArg*)outputBuffer, temp, OutputBufferLength);
still get error 1
I had defined my ioctl cmds as enums in my linux driver (which works fine) and when implementing the driver in windows I used the same enum definition.
enum
{
// Module & Execution control (driver API)
VIRTIQC_SET = 200,
VIRTIQC_UNSET,
// more cmds.....
}
In windows defining control codes take a bit more. As explained here the CTL_CODE macro should be used to define new IOCTL control codes.
#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)
In my case I ended up with defining this:
#define VIRTQC_MAP CTL_CODE(FILE_DEVICE_NETWORK, 0xC8, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
#define VIRTQC_UNMAP CTL_CODE(FILE_DEVICE_NETWORK, 0xC9, METHOD_OUT_DIRECT, FILE_READ_DATA)
I know the function code less than 0x800 are reserved for MS but the device on my host requires this codes so I'm just providing what is being asked.

How do cdev and its associated file operation work?

Actually working on a PCI driver.
I have two PCIe cards with same device ID and vendor ID.
So to make a difference, I assign these two cards with two different MINOR numbers.
//request for device numbers
error = alloc_chrdev_region(&devt, 0, cards_found, DEVICE_NAME);
if (error == 0)
{
major = MAJOR(devt);
printk(KERN_INFO "(drv_init): MAJOR number is %d\n", major);
printk(KERN_INFO "(drv_init): MINOR number range from 0 to %d\n", cards_found-1);
cdevs = cdev_alloc();
cdevs->owner = THIS_MODULE;
cdev_init(cdevs, fops);
for(i=0;i<cards_found,i++)
{
devt = MKDEV(major, i);
error = cdev_add(cdevs, devt, 1);
if (error == 0)
{
printk(KERN_INFO "(drv_init): cdev_add success for minor number: %d", i);
}
else
{
printk(KERN_ALERT "(drv_init): cdev_add failed for minor number: %d,error code: %d, exit driver\n", i, error);
devt = MKDEV(major, 0);
unregister_chrdev_region(devt, cards_found);
pci_unregister_driver(&my_pci_driver);
return(error);
}
}
} `
I'm doing this because all docs I found on internet suggests that one MINOR number for one device.
But I can't understand how could OS know which card is targeted when I do a fops_open, since the fops is bundled to all devices.
Need your help, Thx everyone.
PS: fops = file operations
Signature of .open operation is
int open(struct inode* inode, struct file* file)
Minor number of device opened can be obtained via
iminor(inode)
Other file operations also may obtain device number using file->f_inode as inode.
Alternatively, .open may store some device-specific data in file->f_private, and other operations may access them that way.

Resources