WriteFile Fails with error code 87 when writing to USB - windows

I am trying to communicatate with a USB device on Windows 7. After I find the device using the vendor and product ID I open it with the following command
dev->device_handle = CreateFile( path, (GENERIC_WRITE | GENERIC_READ),
(FILE_SHARE_READ|FILE_SHARE_WRITE),
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
Then I do a write into the device using
res = WriteFile(dev->device_handle, buf, length, &bytes_written, &ol);
where length is 64.
My device can read and write 64 bytes of data in this interface and this has been tested on Linux and using another tool in windows (I dont have the source of the tool).
The WriteFile function gives me an error code of 87. which is invalid parameters.
Could anybody please point me out the mistake I am making.
P.S. I have already analysed the question
WriteFile returning error code 87
I have made some debug logs
--------------------------------------------------
Before write call
dev_handle:152
buf:2293463
length:65
bytes_written:0
overlap:0
--------------------------------------------------
--------------------------------------------------
After write call
dev_handle:152
buf:2293463
length:65
bytes_written:0
overlap:259
--------------------------------------------------
Last Error: 87

Well, there are 5 parameters:
dev->device_handle could be INVALID_HANDLE_VALUE if CreateFile failed.
buf should not be NULL
length cannot be checked, so it can't be the problem.
&bytes_written is rather pointless (use GetOverlappedResult).
&lo must contain a valid offset and event. Also, all other fields must be zeroed.
Lacking context, we can't fault any specific parameter. I'd check &bytes_written first because it's the most obvious suspect to me.

Related

How to pass file name to kernel mode driver?

I want to read from already opened file. There are some examples available like general/ioctl in windows driver samples or How to open a file from a kernel mode device driver and how to read from or write to the file, but first passes file handle of file opened in user mode application (I obviously cannot open file opened by other application due to sharing violation error and handle is null), second shows sample of code without function parameters (I guess for EvtDeviceFileCreate(IN WDFDEVICE Device, IN WDFREQUEST Request, IN WDFFILEOBJECT FileObject) function). Where and how I'm suppose to pass file name to work with file? I want to open it and read by offset plus block length.
Somehow it wasn't obvious to me that DEVICE_NAME in
hDevice = CreateFileW(DEVICE_NAME,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
where
#define DEVICE_NAME L"\\\\.\\MYDRIVERNAME\\PathFileName"
is actually call to driver's EvtDeviceFileCreate function and
fileName = WdfFileObjectGetFileName(FileObject);
returns that filename parameter.

Received invalid Windows system error code

In my C++ Windows application I received what appears to be an invalid system error code using GetLastError() after a failed Overlapped I/O operation.
// Code
DWORD errorCode = GetLastError();
loggerInt1(LOGERROR, "failed getIoResult, errorCode %d", (int)errorCode);
// Log file
failed getIoResult, errorCode -1073741781
failed getIoResult, errorCode -1073741781
failed getIoResult, errorCode -1073741781
//... many more times at different time points
errorCode is a DWORD, which is an unsigned long, and I casted it to int. But Windows system error codes should only be between 0 and 15999, well within an int.
-1073741781 is C000 002B on 32-bit system (mine) and FFFF FFFF C000 002B on 64-bit system. Interpreted as unsigned long it's 3,221,225,515 (32-bit) or some freakishly huge number (64-bit). Either way it's well outside of the 0-15999 range of a Windows system error.
How can this be? Is there a sane reason for why I got such an error code?
0xC000002B is an NTSTATUS code which resolves to STATUS_PARITY_ERROR.
There is no contractual agreement that a value stored here is a standard Win32 error code. The documentation for GetLastError vaguely implies this:
The error codes returned by a function are not part of the Windows API
specification and can vary by operating system or device driver. For this reason, we cannot provide the complete list of error codes that can be returned by each function
The standard error codes are well documented, so the above statement wouldn't make much sense if all possible results are initially understood.
Note that some WINAPIs can also return HRESULT values.

Windows drivers - shared memory from user mode->kernel mode

I'm messing around with some driver development and I'm having an issue getting some of my code to work. I'm not sure if it's a quirk with the API that I'm unaware of or what.
I have a user app that has created a named shared object under BaseNamedObjects with CreateFileMapping, MapViewOfFile, etc. I'm trying to read this shared object inside of my driver code using ZwOpenSection and ZwMapViewOfSection
The problem code is below:
char *sharedData = NULL;
SIZE_T vs = 256;
InitializeObjectAttributes(&myAttributes,&sectionName,OBJ_KERNEL_HANDLE,NULL,NULL);
ZwOpenSection(&sectionHandle,SECTION_MAP_READ,&myAttributes)
ZwMapViewOfSection(&sectionHandle, ZwGetCurrentProcess(), (PVOID *)sharedData, 0, 256,
NULL, &vs, ViewUnmap, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
The call to ZwOpenSection completes successfully and I get the object properly, but the second call fails. The status returned says it's an issue with the ninth parameter, but I've tried every combination I could think of with nothing to show for it, so I'm not sure if it's an issue with a different parameter causing the 9th to be "incorrect" or if I'm missing something else
Thanks.
Is the access permission with which the section was created the same as the one you have passed here?
MEM_COMMIT is not allowed in a direct call in this function. If you still want to commit and reserve pages, try calling the virtualalloc(), otherwise just pass NULL in the 8th parameter.

DeviceIoControl returns ERROR_INVALID_USER_BUFFER

I'm trying to call IOCTL_BTH_GET_LOCAL_INFO using DeviceIoControl, which I believe it can be done (accordingly to Bluetooth Profile Driver IOCTLs).
I'm on a Windows 7 x64 using Visual Studio 2012 (probably with default configuration).
The handle have a valid value (I removed the validation code) but DeviceIoControl always returns ERROR_INVALID_USER_BUFFER (error 1784).
Here's the code:
int main() {
BTH_LOCAL_RADIO_INFO buffer;
BOOL fStatus;
HANDLE h;
DWORD returned = 0;
h = CreateFile(
TEXT("\\\\.\\BthPan"),
GENERIC_READ | GENERIC_WRITE ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
fStatus = DeviceIoControl(
h,
IOCTL_BTH_GET_LOCAL_INFO,
NULL, 0,
(LPVOID)&buffer, sizeof(BTH_LOCAL_RADIO_INFO),
&returned,
(LPOVERLAPPED) NULL
);
(...)
After some research I tried the following solutions:
Changing the structure pack alignment to 1/4/8 byte (with VS options);
Using values which are 8-byte aligned (later I've found out that
this was already happening, even with data types smaller than 8 bytes). After a while I've read somewhere that DeviceIoControl deals with misaligment for you, so probably no need to worry about that.
All of the solutions above have failed. What do you think it is? VS have a bunch of configurations for Win32, but that never gave me a problem before (first time with IOCTL though).
I've seen some of that code on 32feet.NET, so probably it's just an error of mine (I can't see any difference).
You're sending IOCTL_BTH_GET_LOCAL_INFO to the wrong device (Bluetooth Personal Area Network instead of Bluetooth Radio).
So I suggest you to use BluetoothFindFirstRadio, BluetoothFindNextRadio and BluetoothFindRadioClose to simply iterate through local Bluetooth radios, rather than to guess the correct DOS Device Names for them.

Why does DeviceIoControl prepend 12 bytes of information to the user-provided input buffer?

I hope this does not turn out to be a totally braindead question.
I am editing a template WDF Windows USB device driver to send formatted data to one of the device's bulk out pipes; the data has to be set up in a certain way to tell the device to read an internal register.
The problem is that I cannot get the data to go across the bus in the exact format necessary. I wrote a small test app to enumerate the device and call DeviceIoControl with the input buffer set to a struct I set up according to spec.
I have a copy of a USB bus trace for a working case (performed by a driver whose source I have no access to), and I captured a bus trace for what happens when I call the custom IOCTL in my driver. What I see go across the bus is the data structure I set up prefixed with twelve bytes of data; the data structure is correct, but I want to know what the initial twelve bytes of data are, and stop the driver from sending them.
The driver, I believe, has been written properly; I put some debug traces in the driver and it looks like the buffer retrieved by WdfRequestRetrieveInputMemory already has the 12 bytes prepended, so this seems like this is happening pre-driver.
If it is useful information, the IOCTL is set up as METHOD_BUFFERED with FILE_ANY_ACCESS.
The relevant portion of the test code that sets this up is very simple:
const ULONG ulBufferSize = sizeof( CONTROL_READ_DATA );
unsigned char pBuffer[sizeof(CONTROL_READ_DATA)];
DWORD dwBytesReturned;
CONTROL_READ_DATA* readData = (CONTROL_READ_DATA*)pBuffer;
readData->field1 = data;
readData->field2 = moreData;
// ... all fields filled in...
// Send IOCTLs into camera
if( !::DeviceIoControl( hDevice,
IOCTL_CUSTOM_000,
&readData,
ulBufferSize,
&readData,
ulBufferSize,
&dwBytesReturned,
NULL ) )
{
dwError = ::GetLastError();
// Clean up here
return dwError;
}
The data I see go across the bus is: 80FD1200 CCCCCCCC CCCCCCCC + (My data).
Does anyone have any insights?
Wow, really ridiculous error. Notice I'm passing the address of readData to DeviceIoControl, which itself is already a pointer. I can't believe I wasted so much time on this.
Thanks all!
Alignment of the data is the culprit. Check out http://msdn.microsoft.com/en-us/library/2e70t5y1(v=vs.80).aspx to set it to one.

Resources