【问题标题】:Marshal.PtrToStructure crashing on 64bitMarshal.PtrToStructure 在 64 位上崩溃
【发布时间】:2015-03-02 08:07:25
【问题描述】:

在 64 位运行时,我的单元测试在这段代码上崩溃。

崩溃发生在循环第二次迭代的 Marshal.PtrToStructure 调用上。 “entriesRead”说 4 所以它应该能够正确读取,但它没有。 Marshal.SizeOf(typeof(WinAPI.NETAPI32.USER_INFO_4)) 是 64 位的 192 字节。这是错误的根源吗?

    ....
    try {
            int entriesRead;
            int totalEntries;
            int resumeHandle;
            var result = WinAPI.NETAPI32.NetUserEnum(
                this.NTCompatibleHostName,
                3,
                2,
                out bufPtr,
                -1,
                out entriesRead,
                out totalEntries,
                out resumeHandle
            );
            if (result != 0) {
                throw new NetApiException(
                    result,
                    "Failed to enumerate local users on host '{0}'",
                    Host
                );
            }
            var structSize = Marshal.SizeOf(typeof(WinAPI.NETAPI32.USER_INFO_4));
            var startAddr = bufPtr.ToInt64();
            var endAddr = startAddr + entriesRead * structSize;
            for (var offset = startAddr; offset < endAddr; offset += structSize) {
                var userInfo =
                    (WinAPI.NETAPI32.USER_INFO_4)Marshal.PtrToStructure(
                        new IntPtr(offset),
                        typeof(WinAPI.NETAPI32.USER_INFO_4)

                    );

            }
        } catch (Exception error) {
        } 

        [StructLayout(LayoutKind.Sequential)]
        public struct USER_INFO_4 {
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_name;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_password;
            public uint usri4_password_age;
            public uint usri4_priv;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_home_dir;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_comment;
            public uint usri4_flags;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_script_path;
            public uint usri4_auth_flags;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_full_name;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_usr_comment;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_parms;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_workstations;
            public uint usri4_last_logon;
            public uint usri4_last_logoff;
            public uint usri4_acct_expires;
            public uint usri4_max_storage;
            public uint usri4_units_per_week;
            public IntPtr usri4_logon_hours;
            public uint usri4_bad_pw_count;
            public uint usri4_num_logons;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_logon_server;
            public uint usri4_country_code;
            public uint usri4_code_page;
            public IntPtr usri4_user_sid;
            public uint usri4_primary_group_id;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_profile;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string usri4_home_dir_drive;
            public uint usri4_password_expired;
        }


        [DllImport("netapi32.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern NET_API_STATUS NetUserEnum([MarshalAs(UnmanagedType.LPWStr)] string servername, int level, int filter, out IntPtr bufptr, int prefmaxlen, out int entriesread, out int totalentries, out int resume_handle);

【问题讨论】:

    标签: c# crash 64-bit pinvoke


    【解决方案1】:

    结构被正确翻译。它的大小是正确的。您对函数调用的翻译是正确的。

    问题在于您通过了级别 3。这意味着该函数返回 USER_INFO_3 而不是 USER_INFO_4NetUserEnum 的文档绝对没有提到它曾经返回 USER_INFO_4 值。为了获得USER_INFO_4 值,您必须调用NetUserGetInfo

    调用NetUserEnum 传递服务器名称和0 的级别值。这将枚举用户名。然后将每个用户名连同服务器名称一起传递给级别为 4 的 NetUserGetInfo

    【讨论】:

    • 令人惊讶的是,这显然在 x86 上工作了很多年。也许是随机崩溃的来源。我最终实现了 184 字节的 USER_INFO_3 结构。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-07
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 2020-03-17
    相关资源
    最近更新 更多