如何在WINCE7 C#.net中将结构指针发送到DeviceIoControl API

时间:2014-03-18 12:11:24

标签: c# .net windows-ce

我正在开发WIN CE平台,用C#.Net开发Windows窗体。

DeviceIoControl API可以正常使用c ++控制台应用程序中的参数(如下所述)。

  

nuiouser.h中的PNIC_STATISTICS结构

  global declarations :
  TCHAR PCI1_NAME[] = _T("PCI\\ManiXX1"); 
  TCHAR *AUB_NAME = NULL;       
  AUB_NAME = PCI1_NAME; 

   pNICStat = (PNIC_STATISTICS)malloc(sizeof(NIC_STATISTICS)) ;

   pNICStat->ptcDeviceName = AUB_NAME ;           //wchar_t* ptcDeviceName 

   DeviceIoControl( hUB94Port,                         //void*
                 IOCTL_NDISUIO_NIC_STATISTICS,
                 pNICStat,                         //PNIC_STATISTICS 
                 0,
                 pNICStat,                        //PNIC_STATISTICS 
                 sizeof(NIC_STATISTICS),
                 &dwReturnedBytes,
                 NULL
               );

< ============================================= =================================> 但是我在使用C#.Net CF为WIN-CE7实现相同的问题

我的WIN-CE代码如下:

C#中的修改结构:

    [StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]
    public struct __NIC_STAT
    {

        ulong Size;               //  Of this structure.

        public Char[] ptcDeviceName;      //  The device name to be queried.. 

        ulong DeviceState;        //  DEVICE_STATE_XXX above
        ulong DeviceState;        //  DEVICE_STATE_XXX above
        ulong MediaType;          //  NdisMediumXXX
        ulong MediaState;         //  MEDIA_STATE_XXX above
        ulong PhysicalMediaType;
        ulong LinkSpeed;          //  In 100bits/s. 10Mb/s = 100000
        UInt64 PacketsSent;
        UInt64 PacketsReceived;
        ulong InitTime;           //  In milliseconds
        ulong ConnectTime;        //  In seconds
        UInt64 BytesSent;          //  0 - Unknown (or not supported)
        UInt64 BytesReceived;      //  0 - Unknown (or not supported)
        UInt64 DirectedBytesReceived;
        UInt64 DirectedPacketsReceived;
        ulong PacketsReceiveErrors;
        ulong PacketsSendErrors;
        ulong ResetCount;
        ulong MediaSenseConnectCount;
        ulong MediaSenseDisconnectCount; 

    } ;

从这个结构我只是填写ptcDeviceName并尝试发送。

 __NIC_STAT NIC_STAT = new __NIC_STAT();

  Char[] toBytes = {'P','C','I','\\','M','a','n','i','X','X','1','\0'}

  NIC_STAT.ptcDeviceName = toBytes;        //public Char[] ptcDeviceName; in structure 
                                      // __NIC_STAT this is the same structure as 
                                      //in  nuiouser.h     


    int sz = Marshal.SizeOf(NIC_STAT.GetType());//sometimes Getting exception here

     intptr ptr = Marshal.AllocHGlobal(sz);

     Marshal.StructureToPtr((__NIC_STAT)NIC_STAT, ptr, false);

   unsafe 
   {           

         DeviceIoControl(hFileHandle,
                     IOCTL_NDISUIO_NIC_STATISTICS,
                     ref ptr,
                     0,
                     ref ptr,
                     sz,
                     ref dwReturnedBytes,
                     0);
  }//unsafe

这是相应的原型

  [DllImport("coredll.dll", CharSet = CharSet.Auto, SetLastError = true)]
unsafe public static extern bool DeviceIoControl(
                                                  int hDevice, 
                                                  int dwIoControlCode, 
                                                  ref intptr InBuffer,
                                                  int nInBufferSize,
                                                  ref intptr OutBuffer,
                                                  int nOutputBufferSize, 
                                                  ref int pBytesReturned,
                                                  int pOverlapped
                                                 );

在Win-CE中,DeviceIoControl()失败,异常并且没有显示任何错误代码。有时会将错误代码设为87(无效参数)。

我觉得ptcDeviceName正在创建问题,或者可能是因为为指针(ptr)分配内存?

在控制台应用程序中,我们将ptcDeviceName作为Wchar_t *发送,但在WIN-CE中,所以我使用

public Char[] ptcDeviceName;

有谁能告诉我我做错了什么。?

1 个答案:

答案 0 :(得分:4)

你在这里遇到了几个问题。

首先,你似乎认为ulong在C#中是32位,但事实并非如此。它是64位,所以你的结构完全映射错误。

其次,我确定你需要在将结构传递给调用之前设置struct Size成员。

第三,ptcDeviceName成员是指向宽字符串的指针。这意味着在结构本身中它是4个字节。我可能会把它变成IntPtr。然后,您需要单独分配字符串,将其固定,并将指针指向该成员插槽。由于`StringToHGlobal在CF中不存在,它看起来像这样:

public struct __NIC_STAT
{
    public uint Size;
    public IntPtr ptcDeviceName;
    public uint DeviceState;
    public uint DeviceState;
    public uint MediaType;
    public uint MediaState;
    public uint PhysicalMediaType;
    public uint LinkSpeed;
    public ulong PacketsSent;
    public ulong PacketsReceived;
    public uint InitTime;
    public uint ConnectTime;
    public ulong BytesSent;
    public ulong BytesReceived;
    public ulong DirectedBytesReceived;
    public ulong DirectedPacketsReceived;
    public uint PacketsReceiveErrors;
    public uint PacketsSendErrors;
    public uint ResetCount;
    public uint MediaSenseConnectCount;
    public uint MediaSenseDisconnectCount;
};

....
var myStruct = new __NIC_STAT();
myStruct.Size = (15 * 4) + (6 * 8);
var name = "PCI\\Manixx1\0";
var nameBytes = Encoding.Unicode.GetBytes(name);
myStruct.ptcDeviceName = Marshal.AllocHGlobal(nameBytes.Length);
try
{
    Marshal.Copy(nameBytes, 0, myStruct.ptcDeviceName, nameBytes.Length);
    // make the IOCTL call, a-la
    NativeMethods.DeviceIoControl(...., ref myStruct, ....);
}
finally
{
    Marshal.FreeHGlobal(myStruct.ptcDeviceName);
}