WinUSB_Initialize function occurs INVALID_FUNCTION (0x1) Error - c#

Why does the WinUSB_Initialize function occur INVALID_FUNCTION (0x1) Error?
This is a function from the winusb.dll which returns an interface handle.
I would like to get an Interface handle.
I already have a Device handle.
internal struct devInfo
{
internal SafeFileHandle deviceHandle;
internal IntPtr winUsbHandle;
internal Byte bulkInPipe;
internal Byte bulkOutPipe;
internal Byte interruptInPipe;
internal Byte interruptOutPipe;
internal UInt32 devicespeed;
}
internal const Int32 FILE_ATTRIBUTE_NORMAL = 0X80;
internal const Int32 FILE_FLAG_OVERLAPPED = 0X40000000;
internal const Int32 FILE_SHARE_READ = 1;
internal const Int32 FILE_SHARE_WRITE = 2;
internal const UInt32 GENERIC_READ = 0X80000000;
internal const UInt32 GENERIC_WRITE = 0X40000000;
internal const Int32 OPEN_EXISTING = 3;
[DllImport("winusb.dll", SetLastError = true)]
internal static extern Boolean WinUsb_Initialize
(SafeFileHandle DeviceHandle,
ref IntPtr InterfaceHandle);
internal devInfo myDevInfo; // = new devInfo();
public IntPtr Get_WinUSB_handle()
{
Guid myGuid = Get_HID_GUID();
IntPtr deviceInfoSet = Get_Device_Info_Set(myGuid);
SP_DEVICE_INTERFACE_DATA MyDeviceInterfaeData = Get_Device_Interface_Data(deviceInfoSet, myGuid);
IntPtr detailDataBuffer = Get_Structure_with_Device_PathName(deviceInfoSet, ref MyDeviceInterfaeData);
string devicePathName = Get_Device_PathName(detailDataBuffer);
myDevInfo.deviceHandle= CreateFile(devicePathName,
(GENERIC_WRITE | GENERIC_READ),
FILE_SHARE_READ | FILE_SHARE_WRITE,
IntPtr.Zero,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
Boolean success;
success = WinUsb_Initialize(myDevInfo.deviceHandle, ref myDevInfo.winUsbHandle);
System.Console.WriteLine(Marshal.GetLastWin32Error());
System.Console.WriteLine(success);
return myDevInfo.winUsbHandle;
}

success = WinUsb_Initialize(...);
System.Console.WriteLine(Marshal.GetLastWin32Error());
This kind of error checking is wrong. It is only valid to call Marshal.GetLastWin32Error() when a winapi function failed. So a rock-hard requirement is to check success first. Calling GetLastWin32Error() anyway produces an arbitrary garbage value if the function actually succeeded. ERROR_INVALID_FUNCTION certainly has a high garbage value.
The code is also fairly broken when there actually is an error, it doesn't nearly make enough noise and the client code can easily ignore the invalid handle value. Proper code is:
bool success = WinUsb_Initialize(...);
if (!success) throw new System.ComponentModel.Win32Exception();
The exception constructor already calls Marshal.GetLastWin32Error() and will produce an appropriate localized error message.

I believe you are connecting to a device that is not actually using winusb.sys as one of its drivers. To other people who might read this, you can check if a device uses winusb.sys by double-clicking it in the Device Manager, going to the "Driver" tab, and clicking on "Driver Details". If you don't see winusb.sys there then this is not a WinUSB device.
To have a WinUSB device, you need to write a proper INF file and then tell Windows to use it one way or another.
It looks like you are trying to access an HID. Instead of using WinUSB I would recommend HIDAPI.

Related

Calling FreeLibraryAndExitThread externally for a remote process

I'm to trying to call FreeLibraryAndExitThread externally in another process (using CreateRemoteThread) so that I can unload a module I loaded in externally through LoadLibrary.
I understand that whilst CreateRemoteThread takes 1 parameter, you can provide it with a struct of multiple arguments if you need more than one.
If have tried the following which did not unload the module. In fact it seemed to do nothing.
Note I have removed all error checking to keep this post simple and short
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetProcAddress(IntPtr moduleHandle, string procName);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr VirtualAllocEx(IntPtr processHandle, IntPtr baseAddress, int size, int allocationType, int protection);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool WriteProcessMemory(IntPtr processHandle, IntPtr baseAddress, byte[] buffer, int size, int bytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr CreateRemoteThread(IntPtr processHandle, IntPtr threadAttributes, int stackSize, IntPtr startAddress, IntPtr parameter, int creationFlags, int threadId);
private struct FreeLibraryAndExitThreadParameters
{
internal IntPtr ModuleAddress;
internal int ExitCode;
}
var process = Process.GetProcessesByName("notepad")[0];
var freeLibraryAndExitThreadAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "FreeLibraryAndExitThread");
// Get an instance of the module - dllName is the name of the module I am trying to unload
var module = process.Modules.Cast<ProcessModule>().SingleOrDefault(m => string.Equals(m.ModuleName, dllName, StringComparison.OrdinalIgnoreCase));
var freeLibraryAndExitThreadParameters = new FreeLibraryAndExitThreadParameters { ModuleAddress = module.BaseAddress, ExitCode = 0 };
// This code turns the struct into a byte array
var structureSize = Marshal.SizeOf(freeLibraryAndExitThreadParameters);
var structureBytes = new byte[structureSize];
var buffer = Marshal.AllocHGlobal(structureSize);
Marshal.StructureToPtr(freeLibraryAndExitThreadParameters, buffer, true);
Marshal.Copy(buffer, structureBytes, 0, structureSize);
Marshal.FreeHGlobal(buffer);
// Allocate memory in the remote process with commit and reserve allocation type and PageExecuteReadWrite permissions
var remoteAddress = VirtualAllocEx(process.Handle, IntPtr.Zero, structureSize, 0x01000 | 0x02000, 0x040);
// Write the structure into the remote process
WriteProcessMemory(process.Handle, remoteAddress, buffer, structureSize, 0);
// Finally call CreateRemoteThread to execute the function in the remote process
CreateRemoteThread(process.Handle, IntPtr.Zero, 0, freeLibraryAndExitThreadAddress, remoteAddress, 0, 0);
None of the pinvoke calls are actually failing and I can see that the bytes are being written into memory but nothing seems to happen after the remote thread is created - In my actual code I call WaitForSingleObject and the thread finishes its task also with no problem.
Can someone point out what I'm doing wrong and how I can fix this problem so that I can externally call FreeLibraryAndExitThread in a remote process?
It may be worth mentioning that I can use FreeLibrary with this method - it works fine(removing the struct as it only takes 1 parameter) but I specifically need to use FreeLibraryAndExitThread for the module I need to unload which is why I am not using the simpler FreeLibrary.
formally this is simply, all what we need
CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)FreeLibraryAndExitThread, hmod, 0, 0)
where hmod is address of module in remote process. address of FreeLibraryAndExitThread can be take from current process kernel32!FreeLibraryAndExitThread - until kernel32.dll is loaded at the same base address in all processes.
that
DECLSPEC_NORETURN
VOID
WINAPI
FreeLibraryAndExitThread(
_In_ HMODULE hLibModule,
_In_ DWORD dwExitCode
);
take 2 parameters in concrete case no problem. as result of call - CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)FreeLibraryAndExitThread, hmod, 0, 0) the FreeLibraryAndExitThread will be called via stdcall (WINAPI) calling convention with single parameter - hmod. the second parameter dwExitCode will be undefined in this case, but it not play any role - any return code of thread is ok. system not interpret this value. and because this concrete api never return - different in parameter count also not play role.
another question - for what, which sense unload module in remote process. and if module really will be unloaded (the FreeLibrary call only decrement module load count, so module not always will be unloaded during this call) and after this some code in remote process call code of unloading module - think not need explain what is be in this case

Trouble calling SystemParametersInfo

Recently I've been trying to call the SystemParametersInfo method from managed code, without any success.
The problem is that, after calling the method, the method returns false (indicating failure), however GetLastError (retrieved by Marshal.GetLastWin32Error()) is 0.
I tried to invoke the method from C++ as a test (with the exact same parameters), and it works completely fine from there.
The P/Invoke declaration of the method is this:
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SystemParametersInfo(SPI uiAction, int uiParam, ref STICKYKEYS pvParam, SPIF fWinIni);
internal struct STICKYKEYS
{
public int cbSize;
public int dwFlags;
}
And the invocation is as follows:
NativeMethods.STICKYKEYS stickyKeys = default(NativeMethods.STICKYKEYS);
bool result = NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_GETSTICKYKEYS, StickyKeysSize, ref stickyKeys, 0);
int error = Marshal.GetLastWin32Error();
The SPI.SPI_GETSTICKYKEYS is0x003A (as seen on MSDN).
Here the result is false, and the error returned is 0.
Also this is complied as a 64-bit executable if that matters.
I'm completely at my wit's end, do you have any idea what I might be doing wrong?
As GSerg pointed it out to me, my issue was that I need to pass in the size of the struct both directly as a parameter, and as the cbSize member of the struct that I passed in by reference.
The correct code is:
int stickyKeysSize = Marshal.SizeOf(typeof (NativeMethods.STICKYKEYS));
NativeMethods.STICKYKEYS stickyKeys = new NativeMethods.STICKYKEYS {cbSize = stickyKeysSize, dwFlags = 0};
bool result = NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_GETSTICKYKEYS, stickyKeysSize, ref stickyKeys, 0);
if (!result) throw new System.ComponentModel.Win32Exception();
return stickyKeys;

Custom HID Async Read give strange GetOverlappedResults results

I have been working with a USB device (HID custom device), I wrote some code for test the device, simple things: the detection of the device connected and a Write-then-Read cycle, the task of the write/read cycle is send a 64 bytes block with the command in the first byte and the device send me back a block of 64 bytes with the same command in the first byte, the numbers from 1 to 6 in the next six bytes and the rest is uninitialized garbage, then that block is passed to a rich textbox to be displayed.
The program detect the device and the first time that I call the write/read cycle it work without problems but only the first time, the subsecuents calls may result ok o maybe not, in the case of not the read value is garbage and in some occations something occurs and vshost.exe stops work and close my program...
This is the code of the read file:
public bool ReadUSB18F(ref byte[] InBuffer)
{
int Bsize = 65;
InBuffer = new byte[Bsize];
IntPtr UnManagedBuffer = Marshal.AllocHGlobal(Bsize);
IntPtr UnManagedOverlapStruct = Marshal.AllocHGlobal(Marshal.SizeOf(Overlappedbuffer));
Marshal.StructureToPtr(Overlappedbuffer, UnManagedOverlapStruct, false);
if (ReadFile(USBDeviceInfo.ReadHandle, UnManagedBuffer, Bsize, IntPtr.Zero, UnManagedOverlapStruct) == false)
{
if (Marshal.GetLastWin32Error().ToString() == ERROR_IO_PENDING)
{
long bytesreadcount = 0;
bool final = GetOverlappedResult(USBDeviceInfo.ReadHandle, ref Overlappedbuffer, ref bytesreadcount, true);
MessageBox.Show("GetOverlappedResult:"+ final.ToString()+", GetLastWin32Error: " + Marshal.GetLastWin32Error().ToString()+", Byte read count: " + bytesreadcount.ToString());
}
else
{
string error = Marshal.GetLastWin32Error().ToString();
if (error != "0")
{
return false;
}
}
}
Marshal.Copy(UnManagedBuffer, InBuffer, 0, Bsize);
Marshal.FreeHGlobal(UnManagedBuffer);
Marshal.FreeHGlobal(UnManagedOverlapStruct);
return true;
}
I use two handles one for read and other to write. Doing some debug I found that GetOverlappingResult give me a true and ERROR_IO_PENDING, but bWait is true and GetOverlappingResult must wait until the read is complete at least in theory.
In a desperate effort to found a solution I put a messagebox that show the result of GetOverlappingResult, the error from calling the function and the count of bytes read but then something happened, whenever the error ocurs and the messagebox appears (showing effectively that GetOverlappingResult give true, and a ERROR_IO_PENDING), at the moment that I click OK all the data is displayed in the rich textbox as if read was done correctly, like magic, I suppose that the messagebox wait of click event to continue give the necessary time to complete the read, but that wait is supossed to be completed by the GetOverlappingResult, is like GetOverlappingResult don't do their work OR I do something wrong.
Those are my declarations of CreateFile, ReadFile, GetOverlappingResult:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern SafeFileHandle CreateFile(
[MarshalAs(UnmanagedType.LPStr)]
string strName,
uint nAccess,
uint nShareMode,
IntPtr lpSecurity,
uint nCreationFlags,
uint nAttributes,
IntPtr lpTemplate
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadFile
(
SafeFileHandle hFile, // SafeFileHandle to file
IntPtr pBuffer, // data buffer
int NumberOfBytesToRead, // number of bytes to read
IntPtr pNumberOfBytesRead, // number of bytes read
IntPtr OverlappedBuffer
//IntPtr OverlappedBuffer // overlapped buffer
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetOverlappedResult(
SafeFileHandle hFile,
[In] ref Overlapped lpOverlapped,
ref long lpNumberofBytesTransferred,
bool bWait
);
Declaration of the read and write handles:
USBDeviceInfo.ReadHandle = CreateFile(USBDeviceInfo.DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, IntPtr.Zero);
USBDeviceInfo.WriteHandle = CreateFile(USBDeviceInfo.DevicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
Help me guys please, I´ve been stuck on this for a week.

How to write the C# prototype to P/Invoke a function which takes a char* as an argument, and returns its value there

As the title suggests, I'm trying to write some C# code to interop with a C DLL (It's a Windows device driver, basically). The error code function signature in C is:
UINT DLLErrorMsg( DWORD errorCode, char * pBuf, UINT nSize );
nSize is the size of pBuf. If nSize can fit the error message, it is copied into pBuf and 0 returned, otherwise (the buffer was too small and) the return value is the minimum size the buffer needs to be to fit the error message.
I've tried some variants of the following:
internal class DLLWrapper
{
[DllImport(_libName, EntryPoint="DLLErrorMsg", CallingConvention=CallingConvention.Cdecl)]
public static extern UInt32 GetErrorMessage(UInt32 dwError, ref char * pBuf, UInt32 nBufSize);
}
The client code at the moment looks something like this:
GetError( UInt32 errorCode )
{
char[] errorMsg = new char[bufSize];
UInt32 moreChars = DLLWrapper.GetErrorMessage(errorCode, out errorMsg, bufSize);
if (moreChars > 0)
{
errorMsg = new char[moreChars];
TWLDLLInterface.GetErrorMessage(errorCode, out errorMsg, moreChars);
}
}
But I get an exception at the call to GetErrorMessage:
An unhandled exception of type 'System.ArgumentException' occurred in NdevInterface.dll
Additional information: Method's type signature is not Interop compatible.
I've also tried playing around with IntPtr and trying Marshal.IntPtrToStringAuto(), but that wasn't helpful because I need to allocate the buffer, and I obviously can't cast a char[] into an IntPtr.
I've tried searching through the MSDN and general internet for tips on how to do this, but most of it seems to be a little different than what I'm trying.
What am I doing wrong?
You can marshal this using a StringBuilder. For details, see this P/Invoke intro:
[DllImport(_libName, EntryPoint="DLLErrorMsg", CallingConvention=CallingConvention.Cdecl)]
public static extern UInt32 GetErrorMessage(UInt32 dwError, StringBuilder pBuf, UInt32 nBufSize);
Just make sure the StringBuilder has been constructed with enough memory for the pBuf to get filled in.
This example is very similar to what you're trying to achieve.
I think you want this:
internal class DLLWrapper
{
[DllImport(_libName, EntryPoint="DLLErrorMsg", CallingConvention=CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern UInt32 GetErrorMessage(UInt32 dwError, StringBuilder * pBuf, UInt32 nBufSize);
public static UInt32 GetErrorMessage( UInt32 dwError, out string msg)
{
uint buffersize = 1024;
StringBuilder sb = new StringBuilder((int)buffersize);
uint result = GetErrorMessage( dwError, sb, buffersize );
msg = sb.ToString();
return result;
}
}

P/Invoking CreateToolhelp32Snapshot failing in Compact Framework

Hey, im doing a little app for my smart phone, using Windows Mobile 6. I'm trying to get all currently running processec, but method CreateToolhelp32Snapshot always returns -1. So now im stuck. I tried to get error with invoking GetLastError() method, but that method returns 0 value.
Here is a snippet of my code.
private const int TH32CS_SNAPPROCESS = 0x00000002;
[DllImport("toolhelp.dll")]
public static extern IntPtr CreateToolhelp32Snapshot(uint flags,
uint processid);
public static Process[] GetProcesses()
{
ArrayList procList = new ArrayList();
IntPtr handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if ((int)handle > 0)
{
try
{
PROCESSENTRY32 peCurr;
PROCESSENTRY32 pe32 = new PROCESSENTRY32();
// get byte array to pass to API call
byte[] peBytes = pe32.ToByteArray();
// get the first process
int retval = Process32First(handle, peBytes);
First, your handle check is wrong. It's common for the high bit to be on in a handle, causing it to look like a negative number when cast to a signed int. You should be checking that is isn't NULL (0) or INVALID_HANDLE_VALUE (-1 / 0xffffffff).
You shouldn't be "invoking GetLastError" but calling Marshal.GetLastWin32Error()
You've not set the SetLastError attribute in the P/Invoke declaration. In C# it defaults to false, in VB it defaults to true.
Where's your PROCESS32 implementation? The docs clearly state that the dwLength member must be set before the call and it's not clear here if that's happening.
As a side note, the Smart Device Framework's OpenNETCF.ToolHelp namespace has all of this implemented and working (in case you'd rather not reinvent the wheel).
Instead of
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
use
private const int TH32CS_SNAPNOHEAPS = 0x40000000;
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPNOHEAPS, 0);
By default CreateToolhelp32Snapshot will try to snapshot the heaps and that can cause an out of memory error.
Found this at https://social.msdn.microsoft.com/Forums/en-US/e91d845d-d51e-45ad-8acf-737e832c20d0/createtoolhelp32snapshot-windows-mobile-5?forum=vssmartdevicesnative and it solved my problem.
If you're not seeing valid "last error" information, perhaps you might need to add the "SetLastError" attribute on the API's DllImport attribute (MSDN reference with code examples). According to the documentation of this attribute, you should set SetLastError to...
...true to indicate that the callee will
call SetLastError; otherwise, false.
The default is false.
The runtime marshaler calls
GetLastError and caches the value
returned to prevent it from being
overwritten by other API calls. You
can retrieve the error code by calling
GetLastWin32Error
As for the API failure you're seeing, I don't spot anything obvious offhand; the code you have seems very similar to the sample code here.
This is the proper implementation based on the MSDN documentation
private const int INVALID_HANDLE_VALUE = -1;
[Flags]
private enum SnapshotFlags : uint
{
HeapList = 0x00000001,
Process = 0x00000002,
Thread = 0x00000004,
Module = 0x00000008,
Module32 = 0x00000010,
Inherit = 0x80000000,
All = 0x0000001F,
NoHeaps = 0x40000000
}
[DllImport("toolhelp.dll"]
private static extern IntPtr CreateToolhelp32Snapshot(SnapshotFlags dwFlags, int th32ProcessID);
[StructLayout(LayoutKind.Sequential)]
public struct PROCESSENTRY32
{
public uint dwSize;
public uint cntUsage;
public uint th32ProcessID;
public IntPtr th32DefaultHeapID;
public uint th32ModuleID;
public uint cntThreads;
public uint th32ParentProcessID;
public int pcPriClassBase;
public uint dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szExeFile;
};
IntPtr hSnap = CreateToolhelp32Snapshot(SnapshotFlags.Process, 0);
if (hSnap.ToInt64() != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 procEntry = new PROCESSENTRY32();
procEntry.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));
if (Process32First(hSnap, ref procEntry))
{
do
{
//do whatever you want here
} while (Process32Next(hSnap, ref procEntry));
}
}
CloseHandle(hSnap);
Most importantly is this line, because you must set the size of the procEntry:
procEntry.dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32));

Categories