2015-03-02 176 views
1

我的單元在64位運行時測試了這段代碼的崩潰。Marshal.PtrToStructure在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); 

回答

2

該結構已正確翻譯。它的大小是正確的。你的函數調用翻譯是正確的。

問題是您正在傳遞級別3.這意味着該函數返回USER_INFO_3而不是USER_INFO_4NetUserEnum的文檔完全沒有提及它曾經返回USER_INFO_4值。要獲得USER_INFO_4值,您必須致電NetUserGetInfo

調用NetUserEnum傳遞服務器名稱和級別值0。這將列舉用戶名稱。然後將這些用戶名和服務器名稱一起傳遞給NetUserGetInfo,級別爲4.

+1

令人驚訝的是,這顯然在x86上工作了很多年。也許是一個隨機崩潰的來源。我最終實現了184字節的USER_INFO_3結構。 – 2015-03-05 23:25:45

相關問題