I'm trying to find the vendor id and the product id of a USB card. For this purpose, I use setupapi.dll. When I closed my program I have 0x80131623 (2146232797) appears. I don't know how I can fix it.
My code is :
result = HidD_GetHidGuid(ref HidGuid);
DeviceInfoSet = SetupDiGetClassDevs(ref HidGuid, IntPtr.Zero, IntPtr.Zero, 18);
do
{
SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
MyDeviceInterfaceData.cbSize = 28;
result = SetupDiEnumDeviceInterfaces(DeviceInfoSet, IntPtr.Zero, ref HidGuid, MemberIndex, ref MyDeviceInterfaceData);
//int lastError = Marshal.GetLastWin32Error();
if (result != 0)
{
//SP_DEVINFO_DATA MyDeviceInfoData = new SP_DEVINFO_DATA();
//MyDeviceInfoData.cbSize = Marshal.SizeOf(MyDeviceInfoData);
//Premier appel pour obtenir la taille du buffer
result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, ref MyDeviceInterfaceData, IntPtr.Zero, 0, out neededSize, IntPtr.Zero);
//int lastError = Marshal.GetLastWin32Error();
int requiredSize = (int)neededSize;
SP_DEVICE_INTERFACE_DETAIL_DATA MyDeviceInterfaceDetailData = new SP_DEVICE_INTERFACE_DETAIL_DATA();
if (IntPtr.Size == 8) // for 64 bit operating systems
MyDeviceInterfaceDetailData.cbSize = 8;
else
MyDeviceInterfaceDetailData.cbSize = 4 + Marshal.SystemDefaultCharSize; // for 32 bit systems
IntPtr detailDataBuffer = Marshal.AllocHGlobal(requiredSize);
Marshal.StructureToPtr(MyDeviceInterfaceDetailData, detailDataBuffer, true);
result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, ref MyDeviceInterfaceData, detailDataBuffer, requiredSize, out neededSize, IntPtr.Zero);
int lastError = Marshal.GetLastWin32Error();
//string instanceID = Marshal.PtrToStringAuto(detailDataBuffer);
Marshal.PtrToStructure(detailDataBuffer, MyDeviceInterfaceDetailData);
if (MyDeviceInterfaceDetailData.DevicePath.IndexOf("vid_04fa&pid_9123") != -1)
{
Marshal.FreeHGlobal(detailDataBuffer);
Marshal.FreeHGlobal(DeviceInfoSet);
return true;
}
MemberIndex++;
Marshal.FreeHGlobal(detailDataBuffer);
}
else
{
//int lastError = Marshal.GetLastWin32Error();
}
if (MemberIndex>=16) { lastDevice = true; }
} while (lastDevice == false);
Marshal.FreeHGlobal(DeviceInfoSet);
return false;
}
I think the problem is caused by Marshaling.
Related
I am always getting error at this line (in Runtime, not in Editor):
return Marshal.PtrToStringUni(ptr, object_TYPE_INFORMATION.Name.Length >> 1);
Here is my full code:
public static string getObjectTypeName(Win32API.SYSTEM_HANDLE_INFORMATION shHandle, Process process)
{
IntPtr hSourceProcessHandle = Win32API.OpenProcess(Win32API.ProcessAccessFlags.All, false, process.Id);
IntPtr zero = IntPtr.Zero;
Win32API.OBJECT_BASIC_INFORMATION object_BASIC_INFORMATION = default(Win32API.OBJECT_BASIC_INFORMATION);
IntPtr intPtr = IntPtr.Zero;
Win32API.OBJECT_TYPE_INFORMATION object_TYPE_INFORMATION = default(Win32API.OBJECT_TYPE_INFORMATION);
IntPtr intPtr2 = IntPtr.Zero;
IntPtr zero2 = IntPtr.Zero;
int num = 0;
IntPtr ptr = IntPtr.Zero;
bool flag = !Win32API.DuplicateHandle(hSourceProcessHandle, shHandle.Handle, Win32API.GetCurrentProcess(), out zero, 0u, false, 2u);
string result;
if (flag)
{
result = null;
}
else
{
intPtr = Marshal.AllocHGlobal(Marshal.SizeOf<Win32API.OBJECT_BASIC_INFORMATION>(object_BASIC_INFORMATION));
Win32API.NtQueryObject(zero, 0, intPtr, Marshal.SizeOf<Win32API.OBJECT_BASIC_INFORMATION>(object_BASIC_INFORMATION), ref num);
object_BASIC_INFORMATION = (Win32API.OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(intPtr, object_BASIC_INFORMATION.GetType());
Marshal.FreeHGlobal(intPtr);
intPtr2 = Marshal.AllocHGlobal(object_BASIC_INFORMATION.TypeInformationLength);
num = object_BASIC_INFORMATION.TypeInformationLength;
while (Win32API.NtQueryObject(zero, 2, intPtr2, num, ref num) == -1073741820)
{
Marshal.FreeHGlobal(intPtr2);
intPtr2 = Marshal.AllocHGlobal(num);
}
object_TYPE_INFORMATION = (Win32API.OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(intPtr2, object_TYPE_INFORMATION.GetType());
bool flag2 = Win32Processes.Is64Bits();
if (flag2)
{
ptr = new IntPtr(Convert.ToInt64(object_TYPE_INFORMATION.Name.Buffer.ToString(), 10) >> 32);
}
else
{
ptr = object_TYPE_INFORMATION.Name.Buffer;
}
Marshal.FreeHGlobal(intPtr2);
}
return Marshal.PtrToStringUni(ptr, object_TYPE_INFORMATION.Name.Length >> 1);
}
Error:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
.NET Framework Version: 4.6.1
What am I doing wrong?
I am trying to get the symbol information from an address but I am getting error 87 (0x57) ERROR_INVALID_PARAMETER, I have also found the same question here https://social.msdn.microsoft.com/Forums/en-US/bd3e1c89-83c7-41c3-9d5d-a41069da2555/retrieving-symbol-information-by-address-in-c?forum=netfxtoolsdev but the answer does not work for me or at least it is not clear. There is some related questions in SO like: SymFromAddr using C# but it seems there is no clues to solve this.
Note: DbgHelpNative class is a wrapper of the DbgHelp.dll for C#.
This is my code:
static IntPtr GetThreadStartAddress(int threadId)
{
var hThread = OpenThread(ThreadAccess.QueryInformation, false, threadId);
if (hThread == IntPtr.Zero) {
throw new Win32Exception();
}
var buf = Marshal.AllocHGlobal(IntPtr.Size);
try {
var result = NtQueryInformationThread(hThread,ThreadInfoClass.ThreadQuerySetWin32StartAddress,buf, IntPtr.Size, IntPtr.Zero);
if (result != 0) {
throw new Win32Exception(string.Format("NtQueryInformationThread failed; NTSTATUS = {0:X8}", result));
}
IntPtr threadAddress = Marshal.ReadIntPtr(buf);
if (DbgHelpNative.SymInitialize(IntPtr.Zero, null, false)) {
int bufferSize = Marshal.SizeOf(typeof(DbgHelpNative.SYMBOL_INFO)) + ((2000 - 2) * 2);
var buffer = Marshal.AllocHGlobal(bufferSize);
DbgHelpNative.SYMBOL_INFO symbolInfo = new DbgHelpNative.SYMBOL_INFO();
ulong displacement = 0;
Marshal.PtrToStructure(buffer, typeof(DbgHelpNative.SYMBOL_INFO));
symbolInfo.SizeOfStruct = (uint)Marshal.SizeOf(typeof(DbgHelpNative.SYMBOL_INFO));
symbolInfo.MaxNameLen = 2000;
if (DbgHelpNative.SymFromAddr(hThread, (ulong)threadAddress, out displacement, ref symbolInfo)) {
MessageBox.Show("Success");
} else {
var error = Marshal.GetLastWin32Error();
MessageBox.Show(error.ToString());
}
}
return threadAddress;
}
finally {
CloseHandle(hThread);
Marshal.FreeHGlobal(buf);
}
}
The correct code is:
static IntPtr GetThreadStartAddress(IntPtr hProc, int threadId)
{
IntPtr hThread = IntPtr.Zero;
GCHandle handle = default(GCHandle);
try
{
hThread = OpenThread(ThreadAccess.QueryInformation, false, threadId);
if (hThread == IntPtr.Zero)
{
throw new Win32Exception("OpenThread failed");
}
var threadAddress = new IntPtr[1];
handle = GCHandle.Alloc(threadAddress, GCHandleType.Pinned);
var result = NtQueryInformationThread(hThread, ThreadInfoClass.ThreadQuerySetWin32StartAddress, handle.AddrOfPinnedObject(), IntPtr.Size, IntPtr.Zero);
if (result != 0)
{
throw new Win32Exception(string.Format("NtQueryInformationThread failed; NTSTATUS = {0:X8}", result));
}
DbgHelpNative.SymSetOptions(DbgHelpNative.Options.SYMOPT_UNDNAME | DbgHelpNative.Options.SYMOPT_DEFERRED_LOADS);
if (!DbgHelpNative.SymInitialize(hProc, null, true))
{
throw new Win32Exception("SymInitialize failed");
}
DbgHelpNative.SYMBOL_INFO symbolInfo = new DbgHelpNative.SYMBOL_INFO();
// Look at your DbgHelpNative.SYMBOL_INFO.Name definition, there should be a SizeConst.
// Change the 1024 to the SizeConst
// If using Unicode, change 1024 to 1024 * 2
// In the end SizeOfStruct should be 88, both at 32 and 64 bits, both Ansi and Unicode
symbolInfo.SizeOfStruct = (uint)Marshal.SizeOf(typeof(DbgHelpNative.SYMBOL_INFO)) - 1024;
// Change the 1024 to the SizeConst (both for Ansi and Unicode)
symbolInfo.MaxNameLen = 1024;
ulong displacement;
if (!DbgHelpNative.SymFromAddr(hProc, (ulong)threadAddress[0], out displacement, ref symbolInfo))
{
throw new Win32Exception("SymFromAddr failed");
}
Console.WriteLine("Success");
return threadAddress[0];
}
finally
{
if (hThread != IntPtr.Zero)
{
CloseHandle(hThread);
}
if (handle.IsAllocated)
{
handle.Free();
}
}
}
**you'll have to do a small correction in the symbolInfo.SizeOfStruct and symbolInfo.MaxNameLen lines!
Note that you need both a hProc (a handle to the process) AND a threadId
For current process you can use this:
var proc = Process.GetCurrentProcess();
int id = proc.Threads[0].Id;
IntPtr addr = GetThreadStartAddress(proc.Handle, id);
Note that, if you are using this for the DbgHelpNative, I consider any PInvoke that uses Ansi instead of Unicode to be defective. Another (small, non-) problem is that the SizeConst in that library is set to 1024, but in the MSDN examples they use MAX_SYM_NAME, that is 2000... I haven't ever seen a 2000 character symbol, but...)
We are trying to read the ToolTips from system tray icons and the code is working but is returning zero intermittently for the the method below calling Kernel32.VirtualAllocEx
IntPtr ipRemoteBuffer = Kernel32.VirtualAllocEx(
hProcess,
IntPtr.Zero,
new UIntPtr(BUFFER_SIZE),
MemAllocationType.COMMIT,
MemoryProtection.PAGE_READWRITE);
if (ipRemoteBuffer == IntPtr.Zero)
return String.Empty;
It seems to work absolutely fine then suddenly stops working and returns IntPtr.Zero consistently. When checking Marshal.GetLastWin32Error() it returns 8 (not enough memory). Below is the full code:
public static string GetTooltip(string search)
{
IntPtr _ToolbarWindowHandle = GetSystemTrayHandle();
UInt32 count = User32.SendMessage(_ToolbarWindowHandle, TB.BUTTONCOUNT, 0, 0);
List<string> tooltips = new List<string>();
for (int i = 0; i < count; i++)
{
TBBUTTON tbButton = new TBBUTTON();
string text = String.Empty;
IntPtr ipWindowHandle = IntPtr.Zero;
text = GetTBButtonText(_ToolbarWindowHandle, i, ref tbButton, ref text, ref ipWindowHandle);
if (!String.IsNullOrWhiteSpace(text) && text.ToLowerInvariant().Contains(search.ToLowerInvariant()))
return text;
}
return String.Empty;
}
static unsafe string GetTBButtonText(IntPtr hToolbar, int i, ref TBBUTTON tbButton, ref string text, ref IntPtr ipWindowHandle)
{
const int BUFFER_SIZE = 0x1000;
byte[] localBuffer = new byte[BUFFER_SIZE];
UInt32 processId = 0;
UInt32 threadId = User32.GetWindowThreadProcessId(hToolbar, out processId);
IntPtr hProcess = Kernel32.OpenProcess(ProcessRights.ALL_ACCESS, false, processId);
if (hProcess == IntPtr.Zero)
return String.Empty;
IntPtr ipRemoteBuffer = Kernel32.VirtualAllocEx(
hProcess,
IntPtr.Zero,
new UIntPtr(BUFFER_SIZE),
MemAllocationType.COMMIT,
MemoryProtection.PAGE_READWRITE);
if (ipRemoteBuffer == IntPtr.Zero)
{
var error = Marshal.GetLastWin32Error();
return String.Empty;
}
// TBButton
fixed (TBBUTTON* pTBButton = &tbButton)
{
IntPtr ipTBButton = new IntPtr(pTBButton);
int b = (int)User32.SendMessage(hToolbar, TB.GETBUTTON, (IntPtr)i, ipRemoteBuffer);
if (b == 0)
return String.Empty;
// this is fixed
Int32 dwBytesRead = 0;
IntPtr ipBytesRead = new IntPtr(&dwBytesRead);
bool b2 = Kernel32.ReadProcessMemory(
hProcess,
ipRemoteBuffer,
ipTBButton,
new UIntPtr((uint)sizeof(TBBUTTON)),
ipBytesRead);
if (!b2)
return String.Empty;
}
// button text
fixed (byte* pLocalBuffer = localBuffer)
{
IntPtr ipLocalBuffer = new IntPtr(pLocalBuffer);
int chars = (int)User32.SendMessage(hToolbar, TB.GETBUTTONTEXTW, (IntPtr)tbButton.idCommand, ipRemoteBuffer);
if (chars == -1) { Debug.Assert(false); return ""; }
// this is fixed
Int32 dwBytesRead = 0;
IntPtr ipBytesRead = new IntPtr(&dwBytesRead);
bool b4 = Kernel32.ReadProcessMemory(
hProcess,
ipRemoteBuffer,
ipLocalBuffer,
new UIntPtr(BUFFER_SIZE),
ipBytesRead);
if (!b4)
return String.Empty;
text = Marshal.PtrToStringUni(ipLocalBuffer, chars);
return text;
}
}
OK if I make a call to release the memory like so the problem is solved.
const uint MEM_RELEASE = 0x8000;
UIntPtr uintPtr = UIntPtr.Zero;
var successfullyReleased = Kernel32.VirtualFreeEx(hProcess, ipRemoteBuffer, uintPtr, MEM_RELEASE);
if (!successfullyReleased)
{
}
I'm trying to find the vendor id and the product id of a USB card. For this purpose, I use setupapi.dll. In my code, I use the SetupDiGetDeviceInterfaceDetail call twice and on the second time, the function returns true with no error, but I don't know what I can do after that.
My code:
result = HidD_GetHidGuid(ref HidGuid);
DeviceInfoSet = SetupDiGetClassDevs(ref HidGuid, IntPtr.Zero, IntPtr.Zero, 18);
do
{
SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
MyDeviceInterfaceData.cbSize = 28;
result = SetupDiEnumDeviceInterfaces(DeviceInfoSet, IntPtr.Zero, ref HidGuid,
MemberIndex, ref MyDeviceInterfaceData);
if (result != 0)
{
result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, ref MyDeviceInterfaceData,
IntPtr.Zero, 0, out neededSize, IntPtr.Zero);
//int lastError = Marshal.GetLastWin32Error();
int requiredSize = (int)neededSize;
// build a DevInfo Data structure
SP_DEVINFO_DATA da = new SP_DEVINFO_DATA();
da.cbSize = Marshal.SizeOf(da);
SP_DEVICE_INTERFACE_DETAIL_DATA MyDeviceInterfaceDetailData = new
SP_DEVICE_INTERFACE_DETAIL_DATA();
if (IntPtr.Size == 8) // for 64 bit operating systems
MyDeviceInterfaceDetailData.cbSize = 8;
else
MyDeviceInterfaceDetailData.cbSize = 4 + Marshal.SystemDefaultCharSize;
// for 32 bit systems
IntPtr detailDataBuffer = Marshal.AllocHGlobal(requiredSize);
Marshal.StructureToPtr(MyDeviceInterfaceDetailData, detailDataBuffer, false);
result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, ref MyDeviceInterfaceData,
detailDataBuffer, requiredSize, out neededSize, IntPtr.Zero);
int lastError = Marshal.GetLastWin32Error();
When I try the following code, the result is "-" :
string instanceID = Marshal.PtrToStringAuto(detailDataBuffer);
How can I get the vendor ID and the product ID?
In the SP_DEVICE_INTERFACE_DETAIL_DATA struct you find the DevicePath, which is something like \?\hid#vid_045e&pid_00f0#7&13ac544b&0&0000#{GUID}. Just fiddle out the vid_045e and pid_00f0 part.
I am working on a program that is writing to an HID device and am getting the error 87, Invalid parameter on the WriteFile function. I got the functions from Jan Axelson's USB Complete so I'm not sure why I am getting the error.
I am using this to find my device:
private void USBInit()
{
IntPtr deviceInfoSet;
Int32 memberIndex = 0;
SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
Int32 bufferSize = 0;
IntPtr detailDataBuffer;
Boolean success = false;
deviceFound = false;
HidD_GetHidGuid(ref hidGuid); // Get the GUID
deviceInfoSet = SetupDiGetClassDevs // Get pointer to a device info set
(ref hidGuid,
IntPtr.Zero,
IntPtr.Zero,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
do
{
MyDeviceInterfaceData.cbSize = Marshal.SizeOf(MyDeviceInterfaceData); // Identify Device Interface
success = SetupDiEnumDeviceInterfaces
(deviceInfoSet,
IntPtr.Zero,
ref hidGuid,
memberIndex,
ref MyDeviceInterfaceData);
success = SetupDiGetDeviceInterfaceDetail // Request Structure with Device Path Name
(deviceInfoSet,
ref MyDeviceInterfaceData,
IntPtr.Zero,
0,
ref bufferSize,
IntPtr.Zero);
detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
success = SetupDiGetDeviceInterfaceDetail
(deviceInfoSet,
ref MyDeviceInterfaceData,
detailDataBuffer,
bufferSize,
ref bufferSize,
IntPtr.Zero);
IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4);
devicePathName = Marshal.PtrToStringAuto(pDevicePathName);
Marshal.FreeHGlobal(detailDataBuffer);
/* Request Communications Handle */
deviceHandle = CreateFile
(devicePathName,
(GENERIC_WRITE | GENERIC_READ),
FILE_SHARE_READ | FILE_SHARE_WRITE,
IntPtr.Zero,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
0);
/* Get Vendor ID and Product ID */
DeviceAttributes.Size = Marshal.SizeOf(DeviceAttributes);
success = HidD_GetAttributes(deviceHandle, ref DeviceAttributes);
// Compare Vendor ID and Product ID.
if ((DeviceAttributes.VendorID == myVendorID) && (DeviceAttributes.ProductID == myProductID))
{
MessageBoxResult res = System.Windows.MessageBox.Show("Device Found", "K-IX", MessageBoxButton.OK);
deviceFound = true;
/* Get pointer to capabilities */
success = HidD_GetPreparsedData(deviceHandle, ref preparsedData);
/* Get Device Capabilities */
Int32 result = 0;
result = HidP_GetCaps(preparsedData, ref Capabilities);
return;
}
else
{
// Not my device
memberIndex++;
deviceHandle.Close();
if (memberIndex == 128)
{ break; }
}
} while (!deviceFound);
}
And this is the code I am using to try to send to the device:
private void SendUSB()
{
Int32 numberOfBytesWritten = 0;
Byte[] outputReportBuffer = null;
Boolean success;
Boolean success2;
// Set size of the Output report buffer.
Array.Resize(ref outputReportBuffer, Capabilities.InputReportByteLength);
// Store Report ID in first byte of header.
outputReportBuffer[0] = 0;
// Store report data following the Report ID.
outputReportBuffer[1] = 0x01;
//outputReportBuffer[2] = 0x02;
// outputReportBuffer[3] = 0x03;
// Send Report
success = WriteFile
(deviceHandle,
outputReportBuffer,
outputReportBuffer.Length,
ref numberOfBytesWritten,
IntPtr.Zero);
if (!success)
{
Int32 lastError = Marshal.GetLastWin32Error();
}
success2 = HidD_FreePreparsedData(preparsedData);
}
I have verified that my report length expected for the device is 2, but am not sure where to go from here as USB and HID programming are new for me.
You specified FILE_FLAG_OVERLAPPED in the CreateFile() call but pass a null for the lpOverlapped argument in the WriteFile() call. That's not legal.
Remove the FILE_FLAG_OVERLAPPED option.