У нас есть некоторый код .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.