RegisterDeviceNotification Returns NULL but notifications still recieved - c++

I'm using RegisterDeviceNotification to watch for changes to a USB device, using the WM_DEVICECHANGE event. However, when I call RegisterDeviceNotification() it returns NULL for the notification handle, which should indicate that it failed. But GetLastError() returns ERROR_SUCCESS and the notifications actually go through.
This causes real trouble when I, later on, need to UnRegister for notifications and then re-register. Since the handle it returned was NULL, I can't actually re-register. If I try, RegisterDeviceNotification() just hangs.
My code is as follows:
DEV_BROADCAST_HANDLE devBrHdr;
::ZeroMemory( &devBrHdr,sizeof( DEV_BROADCAST_HANDLE ) );
devBrHdr.dbch_size = sizeof( DEV_BROADCAST_HANDLE );
devBrHdr.dbch_devicetype = DBT_DEVTYP_HANDLE;
devBrHdr.dbch_handle = m_hDriver;
m_hDevNotify = ::RegisterDeviceNotification( hWnd,&devBrHdr,DEVICE_NOTIFY_WINDOW_HANDLE );
m_hDriver is the Handle to the driver, which I opened earlier, upon connecting to the device (a USB barcode scanner).
Any ideas what I'm doing wrong here?

Make sure you are not making another Win32 API call between RegisterDeviceNotification and GetLastError.
Check the value of devBrHdr.dbch_hdevnotify. It should contain the same handle returned by RegisterDeviceNotification.
Was the m_hDriver value obtained from a call to CreateFile?

Related

How to test USB HID handle as invalid due to device being replugged

In Windows 7 I have a handle to a custom USB HID device. I'm trying to determine if the handle is no longer able to access the device because the device has been unplugged and re-plugged. When this happens I/O attempts using WriteFile fail. However I am looking for a way to test the handle before doing any I/O to determine if the HID device handle is still valid. And when I say valid I mean handle is connected to device such that I will be able to do I/O to the device. I understand that technically the handle itself may be valid even when it has lost connection to the physical device. The current method in my code is to test by using an attempt to open a new handle to the device and if this succeeds then handle is valid and if it fails handle is not valid. This detects disconnect as expected if the device is unplugged at the time of the test. The problem with this is that if the device has been plugged back in then the test open succeeds but the actual handle used to do I/O (opened before the disconnected/reconnect) is no longer connected to the device. I'm looking for a benign call I can do with the actual I/O handle that will tell me if the device is connected but without doing any actual I/O.
I've tried a few calls so far but none return an indication of the device connection as I require.
DWORD handleInformation;
LARGE_INTEGER size = { 0, 0 };
BOOL isConnected;
isConnected = GetFileSizeEx(m_HidWriteHandle, &size);
isConnected = GetHandleInformation(m_HidWriteHandle, &handleInformation);
GetFileSizeEx always fails and GetLastError() reports (1) Invalid Function
GetHandleInformation always succeeds even when device has been disconnected/reconnected and handle is not able to access device.
The call to use is HidD_GetAttributes(handle, &attributes)
// Try to get the HID attributes. This will fail if device is
// unplugged or has been unplugged since CreateFile() call that
// created m_HidWritehandle
HIDD_ATTRIBUTES Attributes;
Attributes.Size = sizeof(Attributes);
m_HidPresent = HidD_GetAttributes(m_HidWriteHandle, &Attributes) != 0;
This will return false even if device has been plugged back in and thus can be used as an indicator of need to reconnect to HID device.

Calling WSAGetLastError() from an IOCP thread return incorrect result

I have called WSARecv() which returned WSA_IO_PENDING. I have then sent an RST packet from the other end. The GetQueuedCompletionStatus() function which exists in another thread has returned FALSE as expected, but when I called WSAGetLastError() I got 64 instead of WSAECONNRESET.
So why WSAGetLastError() did not return WSAECONNRESET?
Edit:
I forgot to mention that when I call WSAGetLastError() directly after a failing WSARecv() (because of an RST packet being received), the error code returned is WSAECONNRESET and not 64.
So it looks like the error code returned depends on whether WSARecv() has failed directly after calling it, or has failed later when retrieving a completion packet.
This is a generic issue with IOCP, you are making a low-level call to the TCP/IP driver stack. Which, as all drivers do in Windows, report failure with NTSTATUS error codes. The expected error here is STATUS_CONNECTION_RESET.
These native error codes need to be translated to a winapi error code. This translation is normally context-sensitive, it depends on what winapi library issued the driver command. In other words, you can only ever get a WSAECONNRESET error back if it was the Winsock library that did the translation. But that's not what happened in your program, it was GetQueuedCompletionStatus() that handled the error.
Which is a generic helper function that handles IOCP for any device driver. There is no context, the OVERLAPPED structure is not nearly enough to indicate how the I/O request got started. Turn to this KB article, it documents the default mapping from NTSTATUS error codes to winapi error codes. The mapping that GetQueuedCompletionStatus() uses. Relevant entries in the list are:
STATUS_NETWORK_NAME_DELETED ERROR_NETNAME_DELETED
STATUS_LOCAL_DISCONNECT ERROR_NETNAME_DELETED
STATUS_REMOTE_DISCONNECT ERROR_NETNAME_DELETED
STATUS_ADDRESS_CLOSED ERROR_NETNAME_DELETED
STATUS_CONNECTION_DISCONNECTED ERROR_NETNAME_DELETED
STATUS_CONNECTION_RESET ERROR_NETNAME_DELETED
These were, ahem, not fantastic choices. Probably goes back to very early Windows, back when Lanman was the network layer of choice. WSAGetLastError() is pretty powerless to map ERROR_NETNAME_DELETED back to a WSA specific error, the NTSTATUS code was lost when GetQueuedCompletionStatus() set the "last error" code for the thread. So it doesn't, it just returns what it can.
What you'd expect is a WSAGetQueuedCompletionStatus() function so this error translation can happen correctly, using Winsock rules. There isn't one. These days I prefer to use the ultimate authority on how to write Windows code properly, the .NET Framework source as available from the Reference Source. I linked to the source for SocketAsyncEventArgs.CompletionCallback() method. Which contains the key:
// The Async IO completed with a failure.
// here we need to call WSAGetOverlappedResult() just so Marshal.GetLastWin32Error() will return the correct error.
bool success = UnsafeNclNativeMethods.OSSOCK.WSAGetOverlappedResult(
m_CurrentSocket.SafeHandle,
m_PtrNativeOverlapped,
out numBytes,
false,
out socketFlags);
socketError = (SocketError)Marshal.GetLastWin32Error();
Or in other words, you have to make an extra call to WSAGetOverlappedResult() to get the proper return value from GetLastError(). This is not very intuitive :)

Invalid HANDLE from AfxBeginThread

I am writing a multi-threaded networked application, and I'm using a separate thread with a blocking socket to receive data asynchronously from the server.
When I need to shutdown the socket I use a function which checks if the receive thread is still running and if it is calls TerminateThread to end it as follows:
DWORD dwExitCode = 0;
if( GetExitCodeThread( theApp.m_hRecvThread, &dwExitCode ) && dwExitCode == STILL_ACTIVE )
TerminateThread( theApp.m_hRecvThread, 0 );
However, GetExitCodeThread returns FALSE, and when polling GetLastError() it returns 6 (ERROR_INVALID_HANDLE). Which suggests that I do not have the THREAD_QUERY_INFORMATION or THREAD_QUERY_LIMITED_INFORMATION access rights on the m_hRecvThread handle.
My m_hRecvThread handle is set when creating the thread like so:
m_hRecvThread = AfxBeginThread( RecvThread, hWndMainFrame );
This successfully creates the thread, and the thread is running fine and exhibiting expected functionality. The TerminateThread and GetExitCodeThread are being called from the same thread which created the Receive thread in the first place.
My understanding was that when using AfxBeginThread, the HANDLE returned had THREAD_ALL_ACCESS access rights, is this the case, and if so, why am I still getting ERROR_INVALID_HANDLE?
Thanks in advance!
The thread created using:
m_hRecvThread = AfxBeginThread( RecvThread, hWndMainFrame )
will return a pointer to winthread. But GetExitCodeThread() requires the handle to the thread for example, you can pass RecvThread->m_hThread, which will solve the issue

HttpAddUrl fails with ERROR_SHARING_VIOLATION (32L)

I am attempting to write a price listener.
the data arrives as a 'push' response, ie: chunked transfer-encoding.
i have decided to use the http server api, as both async wininet and winHTTP read data apis both close the connection if there is no data for a short while.
first of all, am i correct to use the http server api?
second, if i try to, as per the msdn example:
retCode = HttpInitialize(
HttpApiVersion,
HTTP_INITIALIZE_SERVER,
NULL
); // return is NO_ERROR
retCode = HttpCreateHttpHandle(
&hReqQueue,
0
); // return is NO_ERROR
std::wstring url = _T( "http://apidintegra.tkfweb.com:80/" );
retCode = HttpAddUrl(
hReqQueue,
url.c_str(),
NULL
); // always fails with ERROR_SHARING_VIOLATION
i always get a sharing violation. do i need to use netsh to configure the connection somehow? if so how? ive seen mention of configuring http.sys, and ive even tried executing the above code as an administrator.
I would be extremely grateful for some help, as there seems very little code out there for this!
Many thanks,
Jon
This error happens if the port is already in use by another process. That means another application uses the port (for example IIS or another web server).

Sending IOCTL from IRQL=DISPATCH_LEVEL (KbFilter/KMDF)

I am using the KbFilter example in the WDK, trying to send an IOCTL in a function that is called by KbFilter_ServiceCallback and therefore is executed at DISPATCH_LEVEL. The function just has to send an IOCTL and return, am not waiting for an output buffer to be filled so it can be asynchronous, fire and forget.
I am currently using the WDF functions WdfIoTargetFormatRequestForIoctl and WdfRequestSend to try and send at DISPATCH_LEVEL and getting nothing. The call to WdfRequestSend is succeeding but the IOCTL doesn't appear to be received.
Using either of WdfIoTargetSendIoctlSynchronously or the WDM pattern IoBuildDeviceIoControlRequest() and IoCallDriver() requires PASSIVE_LEVEL and the only way I know to call these at PASSIVE_LEVEL is to create a separate thread that runs at PASSIVE_LEVEL and pass it instructions via a buffer or a queue, synchronized with a spinlock and semaphore.
Can someone tell me if there is an easier way to pass IOCTLs to the drivers below my filter, or is the thread/queue approach the normal pattern when you need to do things at a higher IRQL? Under what circumstances can I use KeRaiseIrql and is this what I should use? Thanks.
Use IoAllocateIrp and IoCallDriver. They can be run at IRQL <= DISPATCH_LEVEL.
You cannot lower your IRQL (unless it is you who raised it). KeRaiseIrql is used only to raise IRQL. A call to KeRaiseIrql is valid if the caller specifies NewIrql >= CurrentIrql.
Be careful: Is your IOCTL expected at DISPATCH_LEVEL?
Here is a code snippet:
PIRP Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->RequestorMode = KernelMode;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;
PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);
stack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
stack->Parameters.DeviceIoControl.IoControlCode = ...