Kernel32 CreateFile not giving exclusive access to USB device - c#

I am taking what was traditionally a single-instance-only application and updating it so multiple instances can execute on the same PC. Each instance will require exclusive access to a USB device. The first application instance opens a USB device with the following command (some Kernel32 wrappers for C# are in place) and gets a valid handle, as expected:
this.handle = Kernel32.CreateFile(
pathToUsbDevice,
Convert.ToUInt32(FileRead.Read | FileRead.Write),
Convert.ToUInt32(FileShare.None),
IntPtr.Zero,
Convert.ToUInt32(CreateDisposition.OpenExisting),
Convert.ToUInt32(FileFlags.Overlapped),
IntPtr.Zero);
The problem is that I then open the second instance of the application and it is able to also get a valid handle to the same device (while the first instance still has its handle). This seems incorrect to me, as my understanding of CreateFile is that it should return an invalid file handle if that device is already opened exclusively (sharing set to 0, or None).
Am I doing something wrong in CreateFile? Perhaps my assumption that it will return an invalid handle if the device is already exclusively opened is incorrect? How can I exclusively open the device for a single application instance so that other application instances cannot open it?
In case it matters, the development & test PC is Windows 7 Professional, 64-bit, building the app via Visual Studio Express 2013.

Looks like it is a device driver issue. I've found a similar discussion:
It's up to the driver to manage shared/non-shared, not the IO manager. So you
have two choices:
Mark your device exclusive in the INF (see the Exclusive registry value under
http://msdn.microsoft.com/en-us/library/windows/hardware/ff546320(v=3Dvs.85).aspx
)
Add file create/close handlers in your driver and manage the count of clients
yourself
You might want to use some other approach to ensure only one instance of your app is accessing device (like using a named global mutex to guard device access).

Related

What device information can I access from the Hololens at run time? (OS Level, Serial Code etc)

What device information can I access from the Hololens at run time using MRTK?
Can MRTK determine a unique identifier for each Hololens device that runs my program? Ideally this would be a serial code, but any other unique identifier from the device would be useful.
I am trying to determine ways to track how many unique devices are running my program, as well as how often they run it.
I am aware that using a managed device might be one way to do this, but I am curious if there is any way to get such information without needing to set up ID Management.
You can use the instance of the EasClientDeviceInformation to get device information from the local device. The property Id provides the identifier of the local device. you can use the following code:
using Windows.Security.ExchangeActiveSyncProvisioning;
. . .
EasClientDeviceInformation deviceInfo = new EasClientDeviceInformation();
var deviceIdentifier = deviceInfo.Id;
In addition, you can retrieve more device information through other properties of the instance, a specific sample is provided here: Client Device Information sample.

Reliable method for detecting if Webex Client is running

What is the best method for determining if the Cisco Webex client is running on a user's computer? Currently, I'm checking for a running process like this:
public static bool IsWebExClientRunning()
{
// webex process name started from internet browser (could change). Just use Process Explorer to find the sub process name.
// alternate name - CiscoWebexWebService
Process[] pname = Process.GetProcessesByName("atmgr");
return pname.Length > 0;
}
While this method works, there could be an instance where Cisco pushes out updates to their client that changes the process name which would break this code if we're looking for a specific process name.
The Webex client starts as a child process from an Internet browser since it is technically a browser plugin and it doesn't show up on its own in Windows Task Manager. I have seen both atmgr and CiscoWebexWebService using Process Explorer to find the process. Sometimes, depending on the host operating system, Windows XP/Windows 7, it will just display atmgr and not the child process CiscoWebexWebService belonging to atmgr. It also varies slightly based on the browser that is used. It runs as a browser plugin for all supported browsers and for unsupported browsers, it will give the option to run as a standalone application.
The process tree can vary (i.e. other browsers/operating systems), but it looks something like this:
iexplore.exe
-> atmgr.exe
-> CiscoWebexWebService.exe
Obviously, all checks must be done client side and not server side, but is there a better method for approaching this?
I spoke with a Cisco specialist and they said that my current approach should be safe for detecting if the Webex client is running a user's machine. They were able to confirm that the process name is atmgr.exe and should not change in the near future.

Allowing connection to .NET COM server with mismatching integrity level

I'm having an issue with a COM based client-server setup. The COM server is written in C# (.NET 4.0) and runs as a (registered) local server.
Depending on which application connects to the server, other clients will receive a Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)
The underlying issue is explained here (in the section COM is integrity aware). The way I understand it, it is being caused by the fact that an elevated application creates the server with a higher integrity level. When another non-elevated application then connects, it is not allowed to connect to the same instance. The same happens when a non-elevated application creates the process, followed an elevated application connecting.
I've tried to implement the solution described on the page: modifying the registry to set a security descriptor that should allow all clients to connect. There is a code sample in C++, but this does effectively the same thing in .NET:
// Security Descriptor with NO_EXECUTE_UP
var sd = new RawSecurityDescriptor("O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)");
byte[] securityDescriptor = new Byte[sd.BinaryLength];
sd.GetBinaryForm(securityDescriptor, 0);
RegistryKey key = Registry.ClassesRoot.OpenSubKey("AppID\\{APP-ID-GUID}", true);
if (key == null)
{
key = Registry.ClassesRoot.CreateSubKey("AppID\\{APP-ID-GUID}");
}
using (key)
{
key.SetValue("LaunchPermission", securityDescriptor, RegistryValueKind.Binary);
}
However, this does not have the desired effect. When the second client tries to create an instance of the object in question, Windows tries to launch a separate instance of my COM Server, but the server prevents two instances from running as the same user. Given the permissions I've set, I would not expect a second instance to launch in the first place.
Since one of the client applications is running in Medium IL and the other in High IL, I also experimented with variants on the mandatory label, like:
O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;ME)
O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)(ML;;NX;;;ME)(ML;;NX;;;HI)
I've also tried setting the ROTFlags registry key to 0x1 (ROTFLAGS_ALLOWANYCLIENT) as suggested on the page, still no change in behavior.
I've established that the LaunchPermission registry value is being used in some way. I cannot discover where it's being read using Process Monitor, but when I use the dcomcnfg.exe tool to set the same key, I can force the server to fail loading by denying launch permissions.
I would like to point out that my server process does not need elevation. How do I make both elevated and non-elevated processes capable of connecting to a single server instance?
According to Windows Vista Security Model Analysis you will need to use shared objects such as a named pipe to go between the different IL. Also, the shared object should have an IL equivalent to your lowest IL being used.
you have to Set Debug option to Any cpu in VS.

Suppress BTExplorer when another application needs to access the bluetooth connection (Bluetopia)

I am developing a C# device application for Motorola MC55 devices (Bluetopia is used). This application sets the bluetooth inquiry and pairing procedure in motion (by means of the Enterprise Mobility Developer Kit) and writes down the virtual serial port #:
public void DoConnection(IRemoteBTDevice rd)
{
RemoteDevice remoteDevice = new RemoteDevice(rd.DeviceName, rd.Id.Replace(":", ""), "");
this.bluetooth.RemoteDevices.Add(remoteDevice);
this.bluetooth.RemoteDevices.Refresh();
if (!remoteDevice.IsPaired)
{
remoteDevice.Pair(rd.Pin);
}
//TODO Note serial port # (get it by means of remoteDevice.LocalComPort)
//Works smoothly, but a second process has to do this (requirement).
remoteDevice.OpenPort();
}
But as soon as a second process (e.g. another c# device application) opens that serial port, BTExplorer is launched. How do I suppress this phenomenon?
this.comX = new SerialPort(this.BluetoothPortName);
this.comX.Open();
I'm just using another Assembly: http://32feet.codeplex.com/. It works smoothly for Motorola ES400 (Microsoft Stack). After seeing this: http://32feet.codeplex.com/wikipage?title=Stonestreet%20One%20Bluetopia, I used the same code, but it doesn't work trouble-free for MC55 yet.
Thank you for your support,
Roger Huber
As I understand it, it is BTExplorer.exe that actually provides/controls the virtual COM port service, so it needs to be running when a virtual COM port is in use...
Do be sure to let know what the issues you see on your MC55 when using my 32feet.NET Bluetopia support. As I noted at 32feet.NET: Stonestreet One Bluetopia I tested on a M3 Mobile device which has a quite recent version of the Bluetopia stack. Maybe StoneStreetOne changed something between your versions... (If Bluetopia start-up fails completely then I've more logging in version 3.3 -- which I'm not too far away from releasing).
Of course if that second C# program needs to use a virtual COM port then 32feet.NET won't help -- BTExplorer is still required as discussed above. However if you could change that program to use BluetoothClient etc instead of COM ports... (Remembering of course the "Bluetopia one at a time" restriction of course).
Alan

Simple cross-platform process to process communication in Mono?

I'm working on a Mono application that will run on Linux, Mac, and Windows, and need the ability for apps (on a single os) to send simple string messages to each other.
Specifically, I want a Single Instance Application. If a second instance is attempted to be started, it will instead send a message to the single instance already running.
DBus is out, as I don't want to have that be an additional requirement.
Socket communication seems to be hard, as windows seems to not allow permission to connect.
Memory Mapped Files seems not to be supported in Mono.
Named Pipes appears not to be supported in Mono.
IPC seems not to be supported on Mono.
So, is there a simple method to send string messages on a single machine to a server app that works on each os, without requiring permissions, or additional dependencies?
On my ubuntu (10.10 mono version: 2.6.7) I've tried using WCF for interprocess communication with BasicHttpBinding, NetTcpBinding and NetNamedPipeBinding. First 2 worked fine, for NetNamedPipeBinding I got an error:
Channel type IDuplexSessionChannel is
not supported
when calling ChannelFactory.CreateChannel() method.
I've also tried using Remoting (which is a legacy technology since WCF came out) with IpcChannel; example from this msdn page started and worked without problems on my machine.
I suppose you shouldn't have problems using WCF or Remoting on Windows either, not sure about Mac though, don't have any of those around to test. Let me know if you need any code examples.
hope this helps, regards
I wrote about this on the mono-dev mailing list. Several general-purpose inter-process messaging systems were considered, including DBus, System.Threading.Mutex class, WCF, Remoting, Named Pipes... The conclusions were basically mono doesn't support Mutex class (works for inter-thread, not for inter-process) and there's nothing platform agnostic available.
I have only been able to imagine three possible solutions. All have their drawbacks. Maybe there's a better solution available, or maybe just better solutions for specific purposes, or maybe there exist some cross-platform 3rd party libraries you could include in your app (I don't know.) But these are the best solutions I've been able to find so far:
Open or create a file in a known location, with exclusive lock. (FileShare.None). Each application tries to open the file, do its work, and close the file. If failing to open, Thread.Sleep(1) and try again. This is kind of ghetto, but it works cross-platform to provide inter-process mutex.
Sockets. First application listens on localhost, some high numbered port. Second application attempts to listen on that port, fails to open (because some other process already has it) so second process sends a message to the first process, which is already listening on that port.
If you have access to a transactional database, or message passing system (sqs, rabbitmq, etc) use it.
Of course, you could detect which platform you're on, and then use whatever works on that platform.
Solved my problem with two techniques: a named mutex (so that the app can be run on the same machine by different users), and a watcher on a message file. The file is opened and written to for communication. Here is a basic solution, written in IronPython 2.6:
(mutex, locked) = System.Threading.Mutex(True, "MyApp/%s" % System.Environment.UserName, None)
if locked:
watcher = System.IO.FileSystemWatcher()
watcher.Path = path_to_user_dir
watcher.Filter = "messages"
watcher.NotifyFilter = System.IO.NotifyFilters.LastWrite
watcher.Changed += handleMessages
watcher.EnableRaisingEvents = True
else:
messages = os.path.join(path_to_user_dir, "messages")
fp = file(messages, "a")
fp.write(command)
fp.close()
sys.exit(0)
For your simple reason for needing IPC, I'd look for another solution.
This code is confirmed to work on Linux and Windows. Should work on Mac as well:
public static IList Processes()
{
IList<Process> processes = new List<Process>();
foreach (System.Diagnostics.Process process in System.Diagnostics.Process.GetProcesses())
{
Process p = new Process();
p.Pid = process.Id;
p.Name = process.ProcessName;
processes.Add(p);
}
return processes;
}
Just iterate through the list and look for your own ProcessName.
To send a message to your application, just use MyProcess.StandardInput to write to the applications standard input. This only works assuming your application is a GUI application though.
If you have problems with that, then you could maybe use a specialized "lock" file. Using the FileSystemWatcher class you can check when it changes. This way the second instance could write a message in the file and then the first instance notice that it changes and can read in the contents of the file to get a message.

Categories