I'm currently using JulMar's ATAPI to interact with Microsoft's Telephony API (TAPI) 2.x.
Whenever I try to place a call onto a specified line or address, I get an ObjectDispoedException. I think this exception is thrown, becasue the LineMakeCall-Function never sets the HCALL handle.
DLLImport:
[DllImport("Tapi32.dll", EntryPoint = "lineMakeCallW", CharSet = CharSet.Auto)]
internal static extern int lineMakeCall(HTLINE hLine, out uint hCall, string DestAddress, int CountryCode, IntPtr lpCallParams);
Function call:
uint hCall = 0;
int rc = NativeMethods.lineMakeCall(Line.Handle, out hCall, address, countryCode, lpCp);
Now, the problem is when this method terminates, hCall is not set and I don't understand why. However, when I change the target framework to .NET 4 or higher (I'm running my application on .NET 3.5 by default), hCall will be set.
From what I understand, the out parameter has to be set before the function terminates.
I read up on the differences between .NET 3.5 and .NET 4 but I didn't find anything usefull for my case.
Does anbody have any idea why the out parameter isn't being set?
Edit:
I finally managed to get it working and want to share this solution. I basically did what was recommended by Kris Vanherck
Try changing your signature of out uint hCall into ref IntPtr lphCall
DLLImport:
[DllImport("Tapi32.dll", EntryPoint = "lineMakeCallW", CharSet = CharSet.Auto)]
internal static extern int lineMakeCall(HTLINE hLine, IntPtr hCall, string DestAddress, int CountryCode, IntPtr lpCallParams);
Function call:
public TapiCall MakeCall(string address, int countryCode, MakeCallParams param)
{
if (!Line.IsOpen)
throw new TapiException("Line is not open", NativeMethods.LINEERR_OPERATIONUNAVAIL);
IntPtr lpCp = IntPtr.Zero;
//jf 2016-10-07
IntPtr lpHcall = IntPtr.Zero;
//jf
try
{
lpCp = MakeCallParams.ProcessCallParams(_addressId, param, 0);
//jf 2016-10-16
CallHandle callHandle = new CallHandle();
lpHcall = Marshal.AllocHGlobal(Marshal.SizeOf(callHandle));
Marshal.StructureToPtr(callHandle, lpHcall, true);
//jf
int rc = NativeMethods.lineMakeCall(Line.Handle, lpHcall, address, countryCode, lpCp);
if (rc < 0)
throw new TapiException("lineMakeCall failed", rc);
else
{
// Wait for the LINE_REPLY so we don't need to deal with the value type
// issues of IntPtr being filled in async.
var req = new PendingTapiRequest(rc, null, null);
Line.TapiManager.AddAsyncRequest(req);
req.AsyncWaitHandle.WaitOne();
if (req.Result < 0)
throw new TapiException("lineMakeCall failed", req.Result);
//jf 2016-10-07
Marshal.PtrToStructure(lpHcall, callHandle);
//jf
var call = new TapiCall(this, callHandle.hCall);
AddCall(call);
return call;
}
}
finally
{
//jf 2016-10-07
if(lpHcall != IntPtr.Zero)
Marshal.FreeHGlobal(lpHcall);
//jf
if (lpCp != IntPtr.Zero)
Marshal.FreeHGlobal(lpCp);
}
}
And finally the CallHandle class:
[StructLayout(LayoutKind.Sequential)]
internal class CallHandle
{
internal uint hCall;
}