IOCreatePlugInInterfaceForService returns mysterious error - swift

I am trying to use some old IOKit functionality in a new Swift 4.0 Mac app (not iOS). I have created a bridging header to use an existing Objective C third party framework, DDHidLib, and I am current working in Xcode 9.
The code that attempts to create a plug in interface for a usb gamepad falls over on IOCreatePlugInInterfaceForService, returning a non-zero error.
The truly bizarre thing is I have an older app created in a previous version of Xcode that uses the same framework and works correctly after opening in the new Xcode 9. This previous project is still Swift using a bridging header for the same Obj-C framework. I have checked the build settings and tried to make everything match, but I get the same result; the old app works but any new apps do not.
Is there a way to either: find out the exact differences in build settings/compilers to see what the elusive difference may be, OR to step into the IOCreatePlugInInterfaceForService IOKit method to see what may be causing the error to be returned in one project but not another?
EDIT: Here is the method that is failing:
- (BOOL) createDeviceInterfaceWithError: (NSError **) error_; {
io_name_t className;
IOCFPlugInInterface ** plugInInterface = NULL;
SInt32 score = 0;
NSError * error = nil;
BOOL result = NO;
mDeviceInterface = NULL;
NSXReturnError(IOObjectGetClass(mHidDevice, className));
if (error)
goto done;
NSXReturnError(IOCreatePlugInInterfaceForService(mHidDevice, kIOHIDDeviceUserClientTypeID,kIOCFPlugInInterfaceID,&plugInInterface,&score));
if (error)
goto done;
//Call a method of the intermediate plug-in to create the device interface
NSXReturnError((*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID) &mDeviceInterface));
if (error)
goto done;
result = YES;
done:
if (plugInInterface != NULL)
{
(*plugInInterface)->Release(plugInInterface);
}
if (error_)
*error_ = error;
return result;
}
In the old version that works, IOCreatePlugInInterfaceForService always returns a value of 0. In all the versions that don't work, the return value appears to always be -536870210. The mHidDevice in this function is the io_object_t handle for the device.
EDIT2: Here is the IORegistryExplorer page for the device

Finally managed to resolve this after weeks of head scratching. The new Xcode 9 uses app sandboxing to basically prevent access to USB, bluetooth, camera and microphone etc. by default in a new app. Once I switched this off it reverted to it's expected behaviour.
Glad it was such a simple answer in the end but disappointed Xcode does not provide more descriptive error messages or responses to let a user know they are essentially preventing themselves from accessing the parts of the system they need.

Looks like kIOReturnNoResources is returned if the loop at the end of IOCreatePlugInInterfaceForService completes with haveOne == false for whatever reason. Perhaps Start() is returning false because another process or driver already has exclusive access? I'd check what clients the device has in IORegistryExplorer.

This error also happens when an application is trying to access the camera or bluetooth on MacOS 10.14 and higher. Permission shall be granted either explicitly by user (pop-up window), or through the Security & Privacy. The application should check for permission as shown here.

Related

Why is my CE app refusing to run?

I've been maintaining a Windows CE app for some time now (over a year) and have produced new versions of it from time to time, copying them to the handheld device[s] and running the new versions there.
Today, though, I created a new Windows CE app for the first time. It is a very simple utility.
To create it in VS 2008, I selected a C# "Smart Device Project" template, added a few controls and a bit of code, and built it.
Here are some of the options I selected:
I copied the .exe produced via building the project to the handheld device's Program Files folder:
...but it won't run. Is it in the wrong location? Does it need some ancillary files copied over? Is there some other sort of setup I need to do to get it to run? Or what?
UPDATE
Since there's not much of it, I'm pasting ALL the code below in case somebody thinks my code could be the problem:
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace PrinterCommanderCE
{
public partial class PrinterCommanderForm : Form
{
public PrinterCommanderForm()
{
InitializeComponent();
}
private void btnSendCommands_Click(object sender, EventArgs e)
{
SendPrinterCommands();
}
private void SendPrinterCommands()
{
bool successfulSend = false;
const string quote = "\"";
string keepPrinterOn = string.Format("! U1 setvar {0}power.dtr_power_off{0} {0}off{0}", quote);
string shutPrinterOff = string.Format("! U1 setvar {0}power.dtr_power_off{0} {0}on{0}", quote);
string advanceToBlackBar = string.Format("! U1 setvar {0}media.sense_mode{0} {0}bar{0}", quote);
string advanceToGap = string.Format("! U1 setvar {0}media.sense_mode{0} {0}gap{0}", quote);
if (radbtnBar.Checked)
{
successfulSend = SendCommandToPrinter(advanceToBlackBar);
}
else if (radbtnGap.Checked)
{
successfulSend = SendCommandToPrinter(advanceToGap);
}
if (successfulSend)
{
MessageBox.Show("label type command successfully sent");
}
else
{
MessageBox.Show("label type command NOT successfully sent");
}
if (ckbxPreventShutoff.Checked)
{
successfulSend = SendCommandToPrinter(keepPrinterOn);
}
else
{
successfulSend = SendCommandToPrinter(shutPrinterOff);
}
if (successfulSend)
{
MessageBox.Show("print shutoff command successfully sent");
}
else
{
MessageBox.Show("print shutoff command NOT successfully sent");
}
}
private bool SendCommandToPrinter(string cmd)
{
bool success = false;
try
{
SerialPort serialPort = new SerialPort();
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Open();
serialPort.Write(cmd);
serialPort.Close();
success = true;
}
catch
{
success = false;
}
return success;
}
}
}
UPDATE 2
Based on this, I added a global exception handler to the app so that Program.cs is now:
namespace PrinterCommanderCE
{
static class Program
{
[MTAThread]
static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler);
Application.Run(new PrinterCommanderForm());
}
static void GlobalExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
MessageBox.Show(string.Format("GlobalExceptionHandler caught : {0}", e.Message));
}
}
}
Yet running the new build shows nothing - it just "flashes" momentarily with about as much verbosity as Lee Harvey Oswald after Jack Ruby's friendly visit.
UPDATE 3
Could the problem be related to this, and if so, how to solve it?
The circumstance that both my updated version of an existing app AND this brand new and simple app refuse to run indicate there is something fundamentally flawed somewhere in the coding, building, or deployment process.
UPDATE 4
As this is a minimal utility, the reason it (and my legacy, much more involved) app are not working may have something to do with the project properties, how it's being built, a needed file not being copied over, or...???
NOTE: The desktop icon is "generic" (looks like a blank white form); this perhaps indicates a problem, but is it indicative of something awry or is it a minor (aesthetics-only) problem?
UPDATE 5
In Project > Properties..., Platform is set to "Active (Any CPU)" and Platform target the same ("Active (Any CPU)")
I have read that this is wrong, that it should be "x86", but there is no "x86" option available - Any CPU is the only one...?!?
UPDATE 6
In Project > Properties... > Devices, the "Deploy the latest version of the .NET Compact Framework (including Service Packs)" is checked. Is this as it should be?
UPDATE 7
Okay, here's the really strange part of all this:
I have two CF/CE apps that I need to run on these Motorola/Symbol 3090 and 3190 handheld devices.
One is this simple utility discussed above. I find that it actually does run on one of the devices (the 3190, FWIW). So it runs on one device, but not on the other.
HOWEVER, the other (legacy) .exe is the opposite - it runs on the 3090 (where the utility will not even start up), but not on the 3190.
So the utility's needs are met by the 3190, and the legacy util's needs are met by the 3090. However, the NEW version of the legacy app does not run on either device!
I am baffled; I feel as Casey Stengel must have when speaking once of his three catchers: "I got one that can throw but can't catch, one that can catch but can't throw, and one who can hit but can't do either."
UPDATE 8
The 3190 has a newer version of the CF installed; it seems that both the new and the old apps should run on the new device with the newer CE, but they don't - only the one built against/for the new framework does...
UPDATE 9
Here is what the 3090 looks like:
UPDATE 10
So I have two exes, one that runs on the devices (both of them now), and the other that will run on neither of the devices. The two exesw seem almost identical. I compared them with three tools: Red Gates' .NET Reflector; JetBrains' dotPeek, and Dependency Walker.
Here is what I found:
Dependency Walker
Both seem to have the same errors about missing dependencies (I didn't have them in the same folder with their dependent assemblies is probably the problem there)
.NET Reflector
The nonworking file has this entry that the working file does not:
[assembly: Debuggable(0x107)]
Is this the problem and, if so, how can I change it?
JetBrains dotPeek
The References in the working copy of the exe are all version 1.0.50000.0
The non-working exe has an identical list of References, and the same version number.
There is this difference, though:
For the working .exe, dotPeek says, "1.4.0.15, msil, Pocket PC v3.5"
For the non-working .exe, dotPeek says, "1.4.0.15, msil, .Net Framework v4.5"
Is this the problem and, if so, how can I change the non-working .exe to match the working one?
This last is disconcerting, primarily because I see no place in the non-working (newer) version of the project where a "4.5" string exists. Where could dotPeek be getting that information?
UPDATE 11
I do know now that the problem is somewhere between these two MessageBox.Show()s, because the first one I see, but not the second:
public static int Main(string [] args)
{
try
{
// A home-brewed exception handler (named ExceptionHandler()) is already defined, but I'm adding a global one
// for UNHANDLED exceptions (ExceptionHandler() is explicitly called throughout the code in catch blocks).
MessageBox.Show("made it into Main method"); // TODO: Remove after testing <= this one is seen
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler);
string name = Assembly.GetExecutingAssembly().GetName().Name;
IntPtr mutexHandle = CreateMutex(IntPtr.Zero, true, name);
long error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
{
ReleaseMutex(mutexHandle);
IntPtr hWnd = FindWindow("#NETCF_AGL_BASE_",null);
if ((int) hWnd > 0)
{
SetForegroundWindow(hWnd);
}
return 0;
}
ReleaseMutex(mutexHandle);
DeviceInfo devIn = DeviceInfo.GetInstance();
Wifi.DisableWifi();
// Instantiate a new instance of Form1.
frmCentral f1 = new frmCentral();
f1.Height = devIn.GetScreenHeight();
f1.Text = DPRU.GetFormTitle("DPRU HHS", "", "");
MessageBox.Show("made it before Application.Run() in Main method"); // TODO: Remove after testing <= this one is NOT seen
Application.Run(f1);
devIn.Close();
Application.Exit();
return 0;
}
catch(Exception ex)
{
DPRU.ExceptionHandler(ex, "Main");
return 0;
}
} // Main() method
UPDATE 12
More specifically, I've got infinite looping going on somehow; By mashing the "Ent" pill on the handheld device (that's what the button looks like - a "lozenge") - it sounds like gerbils tap-dancing (as debugging MessageBox.Show()s in two methods pop up and are dismissed over and over ad infinitum ad (literally) nauseum).
If an application does not start it is mostly missing something. As you compiled for WindowsCE and CF3.5, the Compact Framework 3.5 runimes have to be installed on the WindowsCE device.
Normally Compact Framework is part of Windows CE images, at least version 1.0, but who knows for your test device? If at least one CF is installed, an app requiring a newer CF version will show that on start by a message stating about the missed version. So either no CF is on your device, or something is goind real wrong.
You can run \Windows\cgacutil.exe to check the CF version installed on the device. The tool will show the version of installed CF.
You can debug using a TCP/IP connection or ActiveSync connection. See remote debuggung elsewhere in stackoverflow, I wrote a long aanswer about remote debug via TCP/IP. Or does your device neither have USB and WLAN or ENET?
Update: Here is the answer for remote debug via tcp/ip: VS2008 remotely connect to Win Mobile 6.1 Device This will also enable the remote deployment "In Project > Properties... > Devices, the "Deploy the latest version of the .NET Compact Framework (including Service Packs)" is checked. Is this as it should be?"
Are the earlier apps you wrote also written .NET? Compact framework does not care about the processor architecture, only the CF runtimes have to match the processor. So you do not need an x86 target as if you write a native C/C++ SmartDevice project.
To your comments:
a) CF1.0 is installed on the device.
b) the exe built on the colleagues computer seems to be built for CF1 and therefor runs OK.
c) your exe is built for CF 3.5 and does not run as there is no CF3.5 runtime on the device.
d) most CF exe files are very small as long as they do not include large resources or ...
Conclusion so far: Install the CF3.5 runtime onto the device: http://msdn.microsoft.com/en-us/library/bb788171%28v=vs.90%29.aspx.
To run the legacy app on both devices, the referenced Motorola or other 3rd party runtimes must also be installed. I stringly recommand to setup your environment so you can use ActiveSync/WMDC for development, deployment and debugging of the device. If you are unable look for some more experienced colleague.
Can you try to run it inside the debugger and check where it fails?
Can you place a breakpoint right at the beginning of Program.main and check if it's reached?
Debug output may also give you some interesting hints.

Camera::connect() brings AppOps Bad Call: on Android 4.4?

I wrote an apk to test camera on Android 4.2.2 before. This apk works fine.
However, when I moved this apk to Android 4.4.
I got a problem with Camera::connect().
Fail to call Camera::connect() and it prints message:
W/AppOps ( 1546): Bad call: specified package TestCamera under uid 1000 but it is really -1
I think the reason may be USE_CALLING_UID, security or something that I can't figure out.
Please give me some suggestions, thanks!
My apk is very simple, only one activity. In onCreate(), I called a jni function.
The jni function just do the code belowed:
int cameraId = 0;
String16 clientPackageName("TestToGoService");
sp<Camera> camera = Camera::connect(cameraId, clientPackageName, Camera::USE_CALLING_UID);
if (camera == NULL) {
ALOGE("camera==NULL.");
return -1;
}
ALOGV("camera=%p.",camera.get());
Try:
If I put the code above to a executable (main()), then Camera::connect() works OK.
I have already add permissons on AndroidManifest.xml
Thanks again!
I'm not sure if it's still of any help. I had the same error in the past. The problem is clientPackageName, that has to be set to the exact package name of your application (which must have the proper camera permissions set on the manifest).

Accurately reading of iPhone signal strength

There are a few questions on this already, but nothing in them seems to provide accurate results. I need to determine simply if the phone is connected to a cell network at a given moment.
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Reference/CTCarrier/Reference/Reference.html
This class seems to be documented incorrectly, returning values for mobileCountryCode, isoCountryCode and mobileNetworkCode where no SIM is installed to the phone. carrierName indicates a 'home' network or a previous home network if the phone has been unlocked.
I also looked up and found some people claiming the following to work, which uses an undocumented method of the CoreTelephony framework, but the results have been useless to me, reporting seemingly random figures, where perhaps it is not itself updating consistently.
-(int) getSignalStrength
{
void *libHandle = dlopen("/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony", RTLD_LAZY);
int (*CTGetSignalStrength)();
CTGetSignalStrength = dlsym(libHandle, "CTGetSignalStrength");
if( CTGetSignalStrength == NULL) NSLog(#"Could not find CTGetSignalStrength");
int result CTGetSignalStrength();
dlclose(libHandle);
return result;
}
Thanks.
Edit: The app is connected to an internal wifi and must remain so, making a reachability check more difficult.
I'm playing with this function and I've noticed you're calling it in an interesting way. I'm calling it by adding CoreTelephony.framework as a compile-time link. For the function itself, you'll want to declare it's prototype somewhere (perhaps immediately above the method you call from):
int CTGetSignalStrength();
This needs to be declared since it isn't in a public header for CoreTelephony.
Now, I built a simple app that prints signal strength every second.
int CTGetSignalStrength();
- (void)viewDidLoad
{
[super viewDidLoad];
while (true) {
printf("signal strength: %d\n", CTGetSignalStrength());
sleep(1);
}
}
I ran it on my iPad mini and it shows steady values until I picked it up, where the number went up. Wrapping my iPad in tin foil (tin foil is a debugging tool I have never used before) caused the number to go down. When I put my iPad in airplane mode, it kept repeating the last value, so this will not be an accurate measure for you.
If you want to test if a device currently has a cellular data network connection, you may be more interested in Reachability, specifically kSCNetworkReachabilityFlagsIsWWAN.
Ok I think I have the correct solution now, which was a bit simpler in the end.
The issue with the CTGetSignalStrength() method is that it works normally, but if you remove a sim, it reports the last signal before the removal. I found another method in the same framework called CTSIMSupportGetSIMStatus(), also undocumented, which can tell you if a SIM is currently connected. Using both as follows should confirm the current network signal.
First declare the methods:
NSString * CTSIMSupportGetSIMStatus();
int CTGetSignalStrength();
Then check connectivity to cell network like so:
NSString *status = CTSIMSupportGetSIMStatus();
int signalstrength = CTGetSignalStrength();
BOOL connected = ( [status isEqualToString: #"kCTSIMSupportSIMStatusReady"] && signalstrength > 0 );

Recent gyroscope support from Corona SDK seems to be non-responsive

I'm using a recent daily build of the Corona SDK (version 2001.562) to add gyroscope support to an existing application. Unfortunately, I can't seem to get the event-handling function for the gyroscope to fire. The application is running on an iPod touch, version 4.3.3.
I attach the gyroscope to an event handler like so:
if system.hasEventSource("gyroscope") then
feedbackFile = io.open(system.pathForFile("log.txt", system.DocumentsDirectory), "a");
feedbackFile:write((os.clock()-startupTime).."\tgyroscope on\n");
io.close(feedbackFile);
Runtime:addEventListener( "gyroscope", onGyroscopeDataReceived )
else
feedbackFile = io.open(system.pathForFile("log.txt", system.DocumentsDirectory), "a");
feedbackFile:write((os.clock()-startupTime).."\tgyroscope off\n");
io.close(feedbackFile);
end
When I launch the application on the device, then close it and download the resource files, I find that log.txt contains the line with a timestamp and "gyroscope on". Good so far!
On to the event-handling function:
local function onGyroscopeDataReceived(event)
feedbackFile = io.open(system.pathForFile("log.txt", system.DocumentsDirectory), "a");
feedbackFile:write((os.clock()-startupTime).."\tgyroscope reading delta="..event.deltaRotation..",x="..event.xRotation..",y="..event.yRotation..",z="..event.zRotation.."\n");
io.close(feedbackFile);
end
This line of information never appears in the log.txt file!
Please advise. Thanks in advance!
The problem is event.deltaRotation doesn't exist. You might mean event.deltaTime.
Then when you concatenate a nil value, Lua throws an error and your write code never gets completed. (The latest daily build will now print out a message when you encounter a Lua error on a device.)
The documentation shows how to compute your own deltaDegrees or deltaRadians:
http://developer.anscamobile.com/reference/index/events/gyroscope/eventxrotation
Just a wild guess but it may be your listener is never called --- I noticed your onGyroscopeDataReceived function is local. If that's the case, then you need to make sure the variable is declared prior to the addEventListener call.

How do I detect if XenApp Client is installed on user machine?

We are upgrading from Citrix Metaframe to XenApp, and I need to know if there's a way to programmatically detect if the XenApp Web Plugin v11.0 is already installed on a client machine when it contacts our webserver for login -- this was previously done for the Metaframe Web Client by attempting to instantiate the ICA client in an ASP script, which used the results to determine whether to offer the client as a download/install.
The current code for this detection is:
Set icaObj = CreateObject("Citrix.ICAClient")
The above code does not find the XenApp plugin.
I continued my research after posting this question and I finally found the answer. Only 3 views on this question since I posted it, but despite the disinterest I believe I should answer my question, "Just in Case" someone else has this problem.
I was mistaken in my statement in question that the code I posted didn't find the XenApp plugin. In fact, it does. It returns a valid object in the presence of both Metaframe and XenAppWeb. I posted this question on Citrix's own forums, and no answers there either.
What I did to find the answer was to create a VS2008 project to which I added a COM reference to the Citrix ICA library -- both of them, installed separately one at a time. I found that both had a COM library named WFICALib, and searched through both of them to see if there was something that might distinguish them. What I found was a property, ClientVersion, which was 9.0.xxx for Metaframe, and 11.0.xxxx for XenAppWeb.
BINGO!
From this I cut the following code to return the version as a function in VBScript:
Function GetVer()
Dim icaObj, Ver
On Error Resume Next
Set icaObj = CreateObject("Citrix.ICAClient")
if err.number = 0 then
if IsObject(icaObj) then
GetVer = icaObj.ClientVersion
else
GetVer = 0
end if
set icaObj = nothing
else
GetVer = 0
end if
End Function
ADDENDUM:
Since posting this answer, I have discovered that this script in the newer versions of Internet Explorer (e.g. IE9) is not reliably detecting the plugin -- sometimes it worked, and other times not! What I did to fix the problem was to switch the script to JScript instead of JavaScript, and the new version looks like this:
<script type="text/jscript">
function GetCitrixVersion() {
try {
var icaObj = new ActiveXObject("Citrix.ICAClient");
return icaObj.ClientVersion;
}
catch (e) {
return 0;
}
}
</script>
Note the script type is text/jscript, not text/javascript.