Reopening serial port fails if not closed properly with CloseHandle - c++

I am working with USB device on Windows that is seen as a virtual serial port. I can communicate with the device using CreateFile and ReadFile functions, but in some cases my application does not call CloseHandle (when my application in development crashes). After that all calls to CreateFile fail (ERROR_ACCESS_DENIED), and the only solution is to log in to my computer again. Is there any way to force closing the open handle (or reopening) programmatically?

This is certainly not normal. Windows automatically closes any handles that are left open after the process terminates. This must be a flaw in your USB device driver, although it is hard to see how it could mess this up. The ones that emulate serial ports are however notoriously lousy. Well, nothing much you can do but hope for a driver update from the manufacturer. Or a device from another manufacturer.

I agree with both previous posts.
This is not a normal situation.
Unplugging the USB device usually helps.
This problem is related to the glitches in the FTDI driver, which is responsible for implementing a virtual COM port.
On the other hand those "glitches" are related to various malfunctions of the USB devices. (Of course this doesn't justify the FTDI driver).
BTW there're several other known problems with some FTDI drivers:
Sometimes call to CloseHandle just hangs the calling thread.
Sometimes also the application is still "visible" in the task manager, even after it's closed. Task manager can't terminate the application, and the debugger can't be attached to it. Its EXE file is locked (can't be erased).
Usually unplugging the USB device immediately helps in those situations. The FTDI driver, which seems to be "waiting for something" awakes.

Is there any possibility that some threads or child processes of your crashed program are still running and holding a copy of the file handle? Perhaps a debugger process is still open? If so, those might be keeping the device open. I'd check Task Manager just to be sure; if so, force-killing the leftover processes might fix the problem.

One other thing that you don't want to happen is to have an open usb serial port and the user pull the usb to serial adapter. That bug has (is?) been around for a long time. Here was an answer to the bug
"Posted by Microsoft on 3/27/2009 at 4:03 PM
Hi,
Thank you for reporting this issue. We are aware of this problem and have fixed
it for the next major release of the .NET framework.
If you have any concerns, please reactivate this issue and I'll respond asap.
Thanks,
Kim Hamilton
Base Class Libraries"
Don't know if the problems are related. Microsoft Connect has more than a few USB Serial bugs reported.

Maybe you can add a Try catch close around your main code, and call CloseHandle in the catch close. Then even if the program craches, CloseHandle will be called.
try
{
HANDLE hPort = NULL;
hPort = CreateFile(...);
// You code...
}
catch (...)
{
if (hPort != NULL)
CloseHandle(hPort);
}

Try unplugging the device and plugging it back in. Sometimes Windows needs to be reminded that nobody's connected to that port anymore.

Related

Visual C++/MFC Disable Windows sounds

I'm building a C++/MFC desktop app that shares a lot of data with an USB device.
Because of how this devices works I need to close and open the virtual COM I use, severl times per minute.
Everything works well, but I would like to stop the annoying Windows USB connected/disconnected suound, that comes up every time I connect or disconnect the device.
So my question is: is there a way to disable/enable Windows event sounds (or a single event sound, even better) through my C++ code?
Obviously I could somehow turn down the volume, but that's not what I want, since it would stop sounds from every other app.
Is there a way to do something like this?
Thanks!

Programmatically Eject USB Device while it is in use

How can i programmatically eject USB Device even if it is in use?
Scenarios:
USB device attached to the system.
We get WM_DEVICECHANGE message by "RegisterDeviceNotification" through which we can handle events like DBT_DEVICEARRIVAL, DBT_DEVICEQUERYREMOVE etc.
Now if the device is in use, if we want to eject it from explorer, it prompts as "Problem Ejecting USB Mass Storage Device "This device is currently in use. Close any programs or windows that might be using the device, and then try again."
Question: 1: How can we eject USB without any prompt while it is in use?
Question: 2: How can we get notification when the user press eject from explorer for USB device ?
Thanks in advance :)
Well, you can't mechanically eject it. So what does it mean to software-eject it? It means that Windows will prevent any further handles to be created for files or directories. As a result, it's safe to remove the USB stick afterwards
Now what does it mean that the USB stick is in use? That just means there are open handles. It doesn't make a difference whether you prevent any further handles from being created. Removing a USB stick while there's a handle open means that you risk corrupting the content on the USB stick.
Therefore, it's not a matter of wanting to ejecting the USB stick while in use. The question simply makes no sense at all.
Note that Windows already tells you what you should in fact do: Close any programs or windows that might be using the device, and then try again.
Question two similarly does not make a lot of sense either. When disk F: is gone, why should you care about the details? After all, if you had reasons to care (e.g. open file), Windows would have blocked that operation.

Duplicate USB virtual serial ports being created - what might cause this?

I've got a strange problem with some code I inherited from another programmer who's left the company, and need some guidance on how to even begin to solve it.
The problem is this - on a semi-regular basis, we are finding that duplicate USB virtual comm ports are being created. For example, on my PC, when I view the Ports in Device Manager, and select "View Hidden Devices", I have two entries for the same device - one on COM6, and one on COM8.
Unfortunately, we cannot reliably re-create the problem. We suspect it may happen when someone quickly disconnects and reconnects the USB cable when our software is running, but that needs to be confirmed.
As far as I can tell, the code was written assuming that no one would ever unplug a cable. I see no logic whatsoever to detect this condition after the SW is started. And it fails when you re-plug the cable - silently generating read and write errors even after the cable is plugged back in. You have to restart the program before it will work again.
I have very little serial and USB experience, and am at a bit of a loss as to how to even get started on fixing this.
Can anyone suggest why this might be happening?
Misc. details, in case they might be relevant:
USB serial code is in a C++ DLL
VS2008
FTDIBUS USB/Serial drivers
Windows XP and Win7
Screen shot of duplicate Registry entries (note the value of the selected key!)
As explained on Raymond Chen's blog, the Old New Thing, here, and by commenters above:
https://blogs.msdn.com/b/oldnewthing/archive/2004/11/10/255047.aspx
To summarize:
Devices which are unplugged and plugged in again are tracked so they are not treated as a new device every time.
Usually this uses the device serial number to detect whether a device is the same one.
However not every device has a serial number. These devices are treated as the same device only if they have the same vendor ID and product ID and are plugged into the same port. If they are plugged into a different port they are treated as a different device.
Some manufacturers do not understand the word "Serial" in "Serial Number" and give all devices the same number instead of giving them numbers serially... To cope with this there is a registry setting which can be used to force these devices to be treated as if they have no serial number.
Therefore, if a device with no serial number or which is flagged in the Windows Registry as having duplicate serial numbers is plugged in to a serial port it has not been plugged into before, it will be treated as a new device rather than a reconnection of an old device. This will result in "Ghost" devices as you describe.
Some FTDI devices are specifically called out as having this problem by the manufacturer:
http://www.ftdichip.com/Support/Knowledgebase/index.html?ignorehardwareserialnumber.htm

Is there a way for C++ application function to turn on the computer?

i need to find away to turn on the pc from c++ application ,
is there any way to do this?
Thanks
If the computer is off, it can't be executing code, and therefore can't turn itself on programmatically.
ACPI changes that somewhat, but for us to be able to help, you have to be more specific about your exact requirements.
If you need to turn on a different computer, take a look at Wake-on-LAN.
You will not be able to write a program to turn a computer on that the program itself is installed on.
If you need to write an application that will turn on a different computer, Wake-on-LAN is the tool for you. Modern desktops have NICs that is always receiving power - even if the computer is in an S5 state. Assuming the BIOS supports it and it is enabled.
Wake-On-LAN works by sending a Magic Packet to the NIC. The details of what the payload consists of is outlined in the article.
This is possibly a duplicate of C#: How to wake up system which has been shutdown? (although that is C#).
One way to do it under windows is to create a timer with CreateWaitableTimer(), set the time with SetWaitableTimer() and then do a WaitForSingleObject(). Your code will pause, and you can put the computer into standby (maybe also hibernation, but not shutdown). When the timer is reached, the PC will resume and so will your program.
See here for a complete example in C. The example shows how to calculate the time difference for the timer, and how to do the waiting in a thread (if you are writing a graphical application).
I have to add, you can also schedule the computer to wake up using the Windows Task Scheduler ('Wake the computer to run this task'). This possibly also works when the computer is shut down. There is also an option in some computers BIOS to set a wake time.
Under Linux, you can set the computer to wake up by writing to a special file:
echo 2006-02-09 23:05:00 > /proc/acpi/alarm
Note that I haven't tested all of this, and it is highly dependent on the hardware (mainboard), but some kind of wake-up should be available on all modern PCs.
See also: http://en.wikipedia.org/wiki/Real-time_clock_alarm ,
and here is a program that claims to do it on windows: http://www.dennisbabkin.com/wosb/
Use strip. If you require a Windows computer to be turned on, the cross-tools i686-w64-mingw32-strip or x86_64-w64-mingw32-strip should be used. These command-line programs modify an executable, and the result is able to turn on a computer.
How could you turn on a computer from an application, when no processes are running on it when it's shut down ? You can turn on another computer (Wake on Lan), but not the one you are running.
It is possible.
First thing to do is configure Wake On Lan. Check out this post on Lifehacker on how to do it: http://lifehacker.com/348197/access-your-computer-anytime-and-save-energy-with-wake+on+lan.
(Or this link: http://hblg.info/2011/08/21/Wake-on-LAN-and-remote-login.html)
Then you need to send a magic packet from your C++ application. There are several web services that already do this from javascript (wakeonlan.me) , but it can be done from within a C++ application as well.
Chances are, that if you want to do this, you are working with servers.
In such case, your mainboard may should an IMPI baseboard management controller.
IPMI may be used to cycle the chassis power remotely.
Generally, the BMC will have its own IP address, to which you may connect to send control messages.

Find out which process has an exclusive lock on a USB device handle

I have a library that reads/writes to a USB-device using CreateFile() API. The device happens to implement the HID-device profile, such that it's compatible with Microsoft's HID class driver.
Some other application installed on the system is opening the device in read/write mode with no share mode. Which prevents my library (and anything that consumes it) from working with the device. I suppose that's the rub with being an HID-compatible device -- other driver software (mice, controllers, PHIDGETS, etc) can be uncooperative.
Anyway, the device file path is of the form:
1: "\\?\hid#hpqremhiddevice&col01#5&21ff20e7&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}".
2: "\\?\hid#vid_045e&pid_0023#7&34aa9ece&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}".
3: "\?\hid#vid_056a&pid_00b0&col01#6&5b05f29&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}".
And I'm trying to open it using code, like:
// First, open it with minimum permissions, this device may not be ours.
// we'll re-open it later in read/write
hid_device_ref = CreateFile(
device_path, GENERIC_READ,
0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
I've considered a tool like FileMon or Process Monitor from SysInternals. But I can't seem to get it to report usage on device file handles like the one listed above.
Have you tried the tool called handle from sysinternals?
Anyway, neither windows does this (display the name of the application that locked the device): when you try to eject an USB device, Windows just says that the device is currently in use and cannot be remove right now.
This is what I use to read from a Magtek card reader:
//Open file on the device
deviceHandle =
CreateFile (deviceDetail->DevicePath,
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
Try those options and see if you can at least read from the device.
I understand your pain here... I found the USB HID documentation to be basically wrong in several places.
[Edit] There's not much out there on this problem. Here's a codeproject link that lightly touches on the subject in a thread at the bottom. Sounds like maybe if it's a keyboard or mouse windows grabs it exclusively.
There's a trick you can do where you open the device handle requesting neither read nor write permission and interact with it using only feature reports. Jan Axelson mentions this trick in her books about USB HID devices. I believe this gets around the problem with the exclusive lock, which you would encounter (for example) when trying to open a handle to a device that Windows considers a system keyboard or mouse. Even though you can't read or write the handle, you can still send a feature report to the device using HidD_SetFeature and read a report from the device using HidD_GetFeature. I don't know offhand of a way to read input reports or send output reports under these circumstances, and perhaps it's impossible to do so, but you might not need either of those, especially if the device is "your" device in the sense that you control the firmware. Strictly speaking this does nothing to answer your question as asked, but it seemed potentially relevant so I figured I'd throw it out there.
Cool - I'll try those options, as they're probably better defaults given my intentions. Unfortunately, I know my device is there and I'll eventually need read/write access later on (once I inspect the descriptors and have verifed it is infact my device).
Which means that my real goal IS to know what's using it, so I can inform the customer/user: "Hey man, 'iexplore.exe' is currently using your SuperWidget device. You'll have to close that down in order to use SuperWidget application." (if not at the application-level, then at least at the phone support level.)
I forgot to mention that the windows error reported by GetLastError() is:
0x20. The process cannot access the file because it is being used by another process.
(So your sharing alternatives will probably get the file open, assuming no FILE_SHARE_NONE on behalf of the other process).
[edit]
Yeah, it's painful alright. I have seen mice and keyboards get locked by whatever Windows uses to read from them. I've also seen a lot of people have trouble inside a VM like Paralells on OS X, where the HID class driver has the device open exclusively preventing the VM from using standard USB requests.
I've seen some code that recreates what ProcessMonitor does. Maybe SysInternals is just electing to ignore device handles, but the same method (or a slight variation) can be employed here to determine the PID.
Mike