Как обновить какой-нибудь COM-код маршаллинга для работы в 64-битной системе? - PullRequest
0 голосов
/ 12 июля 2011

У нас есть некоторый код .NET, который вызывает COM-компонент (dnsapi.dll), чтобы запросить, есть ли у домена записи MX, связанные с ним, для проверки адресов электронной почты, введенных на нашем сайте.

Проблема в том, что мы обновляем 32-битные системы до 64-битных, и код, который маршалирует между типами COM и .NET (и очищается после), больше не работает должным образом.

Вызов COM помещает результаты в память и возвращает указатель на то, где они находятся. Код, который марширует результаты в структуру .NET, по-прежнему работает нормально, но код, который очищает память после повреждения кучи и сбоя пула приложений IIS.

Это определенно проблема 64/32 бита, потому что я создал небольшое консольное приложение, которое вызывает тот же код, и оно прекрасно работает, когда я компилирую его для 32-битной системы, но отображает такое же поведение повреждения кучи, когда я компилирую его для 64-битной системы.

Я нашел сообщение stackoverflow , где у кого-то возникла та же проблема, и они сказали, что решение было:

Решение состоит в том, чтобы удостовериться, что структура win32 и структура c # являются битовыми (размерными) отображениями. Этого можно добиться, используя точный тип c # для типа win32.

До этого я мало общался и не уверен, что нужно изменить. Вот что документация MSDN говорит о том, что нативная структура выглядит так:

typedef struct _DnsRecord {
  DNS_RECORD *pNext;
  PWSTR      pName;
  WORD       wType;
  WORD       wDataLength;
  union {
    DWORD            DW;
    DNS_RECORD_FLAGS S;
  } Flags;
  DWORD      dwTtl;
  DWORD      dwReserved;
  union {
    DNS_A_DATA      A;
    DNS_SOA_DATA    SOA, Soa;
    DNS_PTR_DATA    PTR, Ptr, NS, Ns, CNAME, Cname, DNAME, Dname, MB, Mb, MD, Md, MF, Mf, MG, Mg, MR, Mr;
    DNS_MINFO_DATA  MINFO, Minfo, RP, Rp;
    DNS_MX_DATA     MX, Mx, AFSDB, Afsdb, RT, Rt;
    DNS_TXT_DATA    HINFO, Hinfo, ISDN, Isdn, TXT, Txt, X25;
    DNS_NULL_DATA   Null;
    DNS_WKS_DATA    WKS, Wks;
    DNS_AAAA_DATA   AAAA;
    DNS_KEY_DATA    KEY, Key;
    DNS_SIG_DATA    SIG, Sig;
    DNS_ATMA_DATA   ATMA, Atma;
    DNS_NXT_DATA    NXT, Nxt;
    DNS_SRV_DATA    SRV, Srv;
    DNS_NAPTR_DATA  NAPTR, Naptr;
    DNS_OPT_DATA    OPT, Opt;
    DNS_DS_DATA     DS, Ds;
    DNS_RRSIG_DATA  RRSIG, Rrsig;
    DNS_NSEC_DATA   NSEC, Nsec;
    DNS_DNSKEY_DATA DNSKEY, Dnskey;
    DNS_TKEY_DATA   TKEY, Tkey;
    DNS_TSIG_DATA   TSIG, Tsig;
    DNS_WINS_DATA   WINS, Wins;
    DNS_WINSR_DATA    WINSR, WinsR, NBSTAT, Nbstat;
    DNS_DHCID_DATA    DHCID;
  } Data;
} DNS_RECORD, *PDNS_RECORD;

Вот наша структура .NET:

[StructLayout(LayoutKind.Sequential)]
private struct DNSRecord
{
    public IntPtr pNext;
    public string pName;
    public Int16 wType;
    public Int16 wDataLength;
    public Int32 dwflags;
    public Int32 dwTtl;
    public Int32 dwReserved;
    public IntPtr pNameExchange;
    public Int16 wPreference;
    public Int16 Pad;
}

Я знаю, что IntPtr имеет разный размер в зависимости от того, работает ли приложение как 64-битное или 32-битное, но это не то, что я могу специально контролировать. Я не уверен, нужно ли мне увеличивать или уменьшать поля. В идеале мне бы очень хотелось понять, что происходит и почему это проблема.

Я знаю, что другим вариантом будет просто использовать стороннюю библиотеку, которая делает это исключительно через код CLR. К сожалению, это библиотека .NET1.1, которую сейчас будет сложно обновить, поэтому мы не можем просто подключить библиотеку .NET. Я искал библиотеку .NET, которая может запрашивать записи MX, и все они требуют более новой версии .NET.

1 Ответ

0 голосов
/ 12 июля 2011

Да, ваша структура слишком короткая, вы неправильно обработали поле данных.Структура должна быть 64 байта в 32-битном режиме, 88 байтов в 64-битном режиме.Память также повреждена в 32-разрядной версии IIS, вы просто не заметили этого.

Используйте Marshal.SizeOf (typeof (DNSRecord)) для проверки.Вы получите необходимые размеры, добавив следующие поля в структуру:

[StructLayout(LayoutKind.Sequential)]
struct DNSRecord {
    public IntPtr pNext;
    // etc..
    public Int16 Pad;
    private int Pad1;
    private int Pad2;
    private int Pad3;
    private int Pad4;
    private int Pad5;
    private IntPtr Pad6;
    private IntPtr Pad7;
    private IntPtr Pad8;
}
...