USB GPSデバイスに接続しようとしています。 CreateFile WinApi(デバイスマネージャで指定されたパスを使用)経由で手動でファイルを作成すると、デバイスに正常に接続できます。Win32Api USB SetupDiGetDeviceInterfaceDetailが失敗する
ただし、列挙を使用してデバイスを選択しようとすると、SetupDiGetDeviceInterfaceDetailコールに失敗します。
私は正しく動作するCコードを持っていますが、C#変換は正しく動作するようには見えません。私は本質的に同じ結果で多くのバリエーションを試しました。
// Get enumerator handle for the specified ClassGuid
HDEVINFO theDevInfo = SetupDiGetClassDevs((GUID*)&GUID_DEVINTERFACE_GRMNUSB, NULL, NULL,
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
SP_DEVICE_INTERFACE_DATA theInterfaceData;
theInterfaceData.cbSize = sizeof(theInterfaceData);
// populate theInterfaceData which contains device class information
if (!SetupDiEnumDeviceInterfaces(theDevInfo, NULL, (GUID*)&GUID_DEVINTERFACE_GRMNUSB, 0, &theInterfaceData) &&
GetLastError() == ERROR_NO_MORE_ITEMS)
{
gHandle = 0;
return;
}
// This is normally used to obtain the device path information using theInterfaceData obtained above
bool initialized = SetupDiGetDeviceInterfaceDetail(theDevInfo, &theInterfaceData, NULL, 0, &theBytesReturned, NULL);
// theBytesReturned = 83
theDevDetailData =
(PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(theBytesReturned);
theDevDetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
bool initialized = SetupDiGetDeviceInterfaceDetail(theDevInfo, &theInterfaceData, theDevDetailData, theBytesReturned, NULL, &theDevInfoData);
を作品
CコードはC#
[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean SetupDiGetDeviceInterfaceDetail(
IntPtr hDevInfo,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
IntPtr deviceInterfaceDetailData,
UInt32 deviceInterfaceDetailDataSize,
out UInt32 requiredSize,
IntPtr deviceInfoData
);
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DATA
{
public Int32 cbSize;
public Guid interfaceClassGuid;
public Int32 flags;
private UIntPtr reserved;
}
// Get enumerator handle for the specified ClassGuid
IntPtr theDevInfo = SetupDiGetClassDevs(ref ClassGuid, (DiGetClassFlags.DIGCF_PRESENT | DiGetClassFlags.DIGCF_DEVICEINTERFACE));
SP_DEVICE_INTERFACE_DATA DevInterfaceData = new SP_DEVICE_INTERFACE_DATA();
DevInterfaceData.cbSize = Marshal.SizeOf(DevInterfaceData);
initialized = SetupDiEnumDeviceInterfaces(theDevInfo, IntPtr.Zero, ref ClassGuid, 0,
ref DevInterfaceData);
// I assume The DevInterfaceData is populated correctly as it matches the C Code
// And I've compared the values in memory and they match
uint bytesReturned = 0;
initialized = SetupDiGetDeviceInterfaceDetail(theDevInfo, ref DevInterfaceData, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);
// I expect bytesReturned = 83 and initialized = true which is the value that is returned in the C Code
// Instead the value 162 is returned
いいえ、スタックを破壊します。 Marshal.AllocHGlobal()を使用して、必要なサイズのバッファを割り当てます。あなたが最初の呼び出しから得たサイズ。 –
なぜスタックは壊れていますか? Win32api呼び出しを行うと適切なメモリがマーシャリングされないでしょうか? – galford13x
@ HansPassant 'IntPtr.Size'のテストがなぜ必要なのか説明できます.Marshalerを使って' SizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA) 'を得ることはできません。私はそれが何とかパッディングと関係があると思いますか? –