Кто-нибудь знает о реализации, аналогичной SafeHandle, в которой не используется IntPtr, из которого я могу получить производные? Или я должен создать новую ручку в целом? Мне нужны такие функции, как DangerousGetHandle () и SetHandle (), так как они используются во всей библиотеке, которую я использую.
Причина, по которой я спрашиваю, состоит в том, что я пишу приложение, которое использует управляемую Atapi библиотеку .NET для TAPI 2.x (доступно здесь: http://atapi.codeplex.com/). Приложение предназначено для 32- и 64-разрядных платформ, и в настоящее время отлично работает на 32-разрядных, но при работе на 64-разрядных оно выдает ошибку в этой строке в классе библиотеки TapiCall:
rc = NativeMethods.lineGetCallStatus(_hCall, pLcs);
Первые строки детализации исключения:
System.ObjectDisposedException was unhandled
Message=Safe handle has been closed
Source=mscorlib
ObjectName=""
StackTrace:
at System.StubHelpers.StubHelpers.SafeHandleC2NHelper(Object pThis, IntPtr pCleanupWorkList)
at JulMar.Atapi.Interop.NativeMethods.lineGetCallStatus(HTCALL hCall, IntPtr lpCallStatus)
Я проследил несколько вызовов и считаю, что источником проблемы является следующий вызов нативной функции в Tapi32.dll:
int rc = NativeMethods.lineMakeCall(Line.Handle, out hCall, address, countryCode, lpCp);
(Определено в TAPI здесь: http://msdn.microsoft.com/en-us/library/ms735988(VS.85).aspx)
Значение hCall в 64-битном формате равно «0», тогда как в 32-битном - это 5-значный дескриптор. Значения других параметров выглядят нормально и идентичны на обеих платформах.
Я предполагаю, что часть проблемы связана с Line.Handle, который является производным от SafeHandle и определяется в библиотеке следующим образом:
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
internal class HTLINE : SafeHandle
{
internal HTLINE()
: base(IntPtr.Zero, true)
{
}
internal HTLINE(IntPtr preexistingHandle, bool ownsHandle)
: base(preexistingHandle, ownsHandle)
{
}
protected override bool ReleaseHandle()
{
if (handle != IntPtr.Zero)
{
NativeMethods.lineClose(handle);
handle = IntPtr.Zero;
}
return true;
}
public override bool IsInvalid
{
get { return handle == IntPtr.Zero; }
}
}
Базовым дескриптором является IntPtr, и, поскольку он имеет разные размеры для 32- и 64-разрядных, я подумал, что это может вызвать проблемы, если TAPI ожидает всего 4 байта, как в 32-разрядных. Чтобы проверить эту теорию, я думал о создании дескриптора, который не использует IntPtr. Это звучит как разумный подход?
Спасибо за любой совет.