【问题标题】:Marshal.PtrToStringUni(s) returns class name instead of messageMarshal.PtrToStringUni(s) 返回类名而不是消息
【发布时间】:2013-05-06 15:11:36
【问题描述】:

我目前正在尝试让我的内核过滤器与我的 c# 应用程序进行通信。内核应用程序在我的结构中发送一个带有文件路径的 UNICODE_STRING。所有其他变量似乎都很好,缓冲区位置在用户和内核应用程序中似乎相同,但是当我调用我的 ToString 方法时,我得到了

usermodeFilter.MinifilterWrapper+NativeMethods+COMMAND_MESSAGE

我的 c# 代码看起来像这样

    private NativeMethods.USERCOMMAND_MESSAGE data = new NativeMethods.USERCOMMAND_MESSAGE();

    [SecurityPermission(SecurityAction.Demand)]
    public void FilterGetMessage()
    {

        UInt32 result = NativeMethods.FilterGetMessage(_handle, ref data, (UInt32)Marshal.SizeOf(typeof(NativeMethods.USERCOMMAND_MESSAGE)), IntPtr.Zero);
        if (result == NativeMethods.S_OK)
        {
            Console.WriteLine("message recived");
            Console.WriteLine(this.getProcessNameFromId((int)this.data.cmdMessage.procesID));
            Console.WriteLine(this.data.cmdMessage.ToString());
        }
        else
        {
            throw new InvalidOperationException("Unknown error, number " +result);
        }

    }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct COMMAND_MESSAGE { 
            public UInt32 procesID;
            public UNICODE_STRING fileName;
         } 

        [StructLayout(LayoutKind.Sequential)]
        public struct UNICODE_STRING : IDisposable
        {
            public ushort Length;
            public ushort MaximumLength;
            private IntPtr buffer;

            public UNICODE_STRING(string s)
            {
                Length = (ushort)(s.Length * 2);
                MaximumLength = (ushort)(Length + 2);
                buffer = Marshal.StringToHGlobalUni(s);
            }

            public void Dispose()
            {
                Marshal.FreeHGlobal(buffer);
                buffer = IntPtr.Zero;
            }

            public override string ToString()
            {
                return Marshal.PtrToStringUni(buffer);
            }
          }

C++部分代码看起来

            WCHAR parametersKeyBuffer[255];
            gCmdMessageSend.name.Buffer = parametersKeyBuffer;
            gCmdMessageSend.name.MaximumLength = sizeof(parametersKeyBuffer);
            gCmdMessageSend.name.Length = 0;
            RtlCopyUnicodeString(&gCmdMessageSend.name, &fileInfo->Name);
            if (FsClientPort)
                {
                    ulReplayLength = sizeof(gCmdMessageSend);
                    status = FltSendMessage(gFilterHandle, &FsClientPort, &gCmdMessageSend, sizeof(gCmdMessageSend), NULL, &ulReplayLength, &timeout);
                }

顺便说一句,我也获得了对内存位置的无效访问。 Marshal.FreeHGlobal(buffer) 时出错;所以我猜我做错了什么

【问题讨论】:

  • 如果您更改buffer 指向的位置,您可能会收到Invalid access to memory location 错误。你应该只在原生土地上操纵缓冲区,而不是改变它指向的东西。
  • 我在缓冲区做错了,现在在Marshal.PtrToStringUni 之后我得到Attempted to read or write protected memory. This is often an indication that other memory is corrupt

标签: c# .net string memory-management marshalling


【解决方案1】:

Console.WriteLine(this.data.cmdMessage.ToString());

您没有被覆盖的ToString() 方法,因此它将默认为类型名称。您还需要覆盖该类中的ToString() 方法(COMMAND_MESSAGE)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    相关资源
    最近更新 更多