Доброго времени суток, господа! Я новичок в .NET (в основном на C++ писал). Пишу тестовое приложение использующее unmanaged функции TAPI. Код всей программы приведен ниже. Компилируется нормально и запускается на Pocket PC. Функция lineMakeCall также осуществляет звонок (мобильник лежит рядом и начинает музычку играть), но не работает LineCallBack, т.е. при дозвоне должен перехватываться соответствующий message LINECALLSTATE_PROCEEDING и выводится текст в поле и кнопочки состояние менять, но этого не происходит... Если при дебаге поставить внутрь функции LineCallBack брейкпоинт, то после срабатывания lineMakeCall студия2005 закрывается по ошибке

и предлагает отправить отчет в microsoft... Вот такие пироги... Третий день уже мучаюсь с этим TAPI

Мне этот код уже снится, где я мог накосячить?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace incomCall
{
public partial class Form1 : Form
{
private Tapi.CallBackDelegate callBackDelegate;
private IntPtr callBackPointer;
private IntPtr hLineApp;
private IntPtr hLine;
private IntPtr lphCall;
int ret;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Инициализация TAPI и открытие линии
callBackDelegate = new Tapi.CallBackDelegate(LineCallBack);
callBackPointer = Marshal.GetFunctionPointerForDelegate(callBackDelegate);
int dwNumDev;
int num1 = 0x20000;
// lineInitializeEx
Tapi.LINEINITIALIZEEXPARAMS lineInitializeParams = new Tapi.LINEINITIALIZEEXPARAMS();
lineInitializeParams.dwTotalSize = (uint)Marshal.SizeOf(lineInitializeParams);
lineInitializeParams.dwNeededSize = lineInitializeParams.dwTotalSize;
lineInitializeParams.dwUsedSize = 512;
lineInitializeParams.dwOptions = Tapi.LINEINITIALIZEEXOPTION_USEHIDDENWINDOW;
lineInitializeParams.hEvent = IntPtr.Zero;
lineInitializeParams.hCompletionPort = IntPtr.Zero;
lineInitializeParams.dwCompletionKey = 0;
ret = Tapi.lineInitializeEx(out hLineApp, IntPtr.Zero, callBackPointer, null,
out dwNumDev, ref num1, ref lineInitializeParams);
// lineNegotiateAPIVerison
int version;
int dwAPIVersionLow = 0x10004;
int dwAPIVersionHigh = 0x20000;
Tapi.LINEEXTENSIONID lineExtensionID;
ret = Tapi.lineNegotiateAPIVersion(hLineApp, 0, dwAPIVersionLow,
dwAPIVersionHigh, out version, out lineExtensionID);
// lineOpen
ret = Tapi.lineOpen(hLineApp, 0, out hLine, version, 0, 0, Tapi.LINECALLPRIVILEGE_MONITOR,
Tapi.LINEMEDIAMODE_DATAMODEM, IntPtr.Zero);
}
private void buttonDial_Click(object sender, EventArgs e)
{
labelStatus.Text = "";
buttonDial.Enabled = false;
buttonHangUp.Enabled = false;
buttonAnswer.Enabled = false;
ret = Tapi.lineMakeCall(hLine, out lphCall, textBoxNumber.Text, 0, IntPtr.Zero);
}
private void buttonHangUp_Click(object sender, EventArgs e)
{
labelStatus.Text = "";
buttonDial.Enabled = false;
buttonHangUp.Enabled = false;
buttonAnswer.Enabled = false;
Tapi.lineSetCallPrivilege(lphCall, Tapi.LINECALLPRIVILEGE_OWNER);
if (lphCall != IntPtr.Zero)
{
Tapi.lineDrop(lphCall, null, 0);
}
}
private void buttonAnswer_Click(object sender, EventArgs e)
{
labelStatus.Text = "";
buttonDial.Enabled = false;
buttonHangUp.Enabled = false;
buttonAnswer.Enabled = false;
}
private void Form1_Closing(object sender, CancelEventArgs e)
{
if (hLine != IntPtr.Zero)
{
Tapi.lineClose(hLine);
hLine = IntPtr.Zero;
lphCall = IntPtr.Zero;
Tapi.lineShutdown(hLineApp);
}
}
private void LineCallBack(int hDevice, int dwMsg, int dwCallbackInstance, int dwParam1, int dwParam2, int dwParam3)
{
switch (dwMsg)
{
case Tapi.LINE_CALLSTATE:
lphCall = (IntPtr)hDevice;
Tapi.lineSetCallPrivilege(lphCall, Tapi.LINECALLPRIVILEGE_OWNER);
switch (dwParam1)
{
case Tapi.LINECALLSTATE_PROCEEDING:
// Перехватываем звонок пользователя
labelStatus.Text = "Дозвон...";
buttonDial.Enabled = false;
buttonHangUp.Enabled = true;
buttonAnswer.Enabled = false;
break;
case Tapi.LINECALLSTATE_OFFERING:
// Здесь мы оказываемся, когда нам звонят
labelStatus.Text = "Входящий звонок...";
buttonDial.Enabled = false;
buttonHangUp.Enabled = true;
buttonAnswer.Enabled = true;
break;
case Tapi.LINECALLSTATE_CONNECTED:
// Здесь - когда нам ответили
labelStatus.Text = "Соединилось.";
buttonDial.Enabled = false;
buttonHangUp.Enabled = true;
buttonAnswer.Enabled = false;
break;
case Tapi.LINECALLSTATE_DISCONNECTED:
// Здесь - когда разговор завершился с другой стороны
labelStatus.Text = "Разъединилось.";
buttonDial.Enabled = true;
buttonHangUp.Enabled = false;
buttonAnswer.Enabled = false;
break;
case Tapi.LINECALLSTATE_IDLE:
// Здесь - когда разговор завершился с нашей стороны
Tapi.lineDeallocateCall(lphCall);
labelStatus.Text = "Разъединилось.";
buttonDial.Enabled = true;
buttonHangUp.Enabled = false;
buttonAnswer.Enabled = false;
break;
case Tapi.LINECALLSTATE_BUSY:
// Занято
labelStatus.Text = "Занято...";
buttonDial.Enabled = false;
buttonHangUp.Enabled = true;
buttonAnswer.Enabled = false;
break;
default:
break;
}
break;
// case Tapi.LINE_REPLY:
// ret = dwParam2;
// break;
default:
break;
}
}
}
public class Tapi
{
public delegate void CallBackDelegate(int hDevice, int dwMsg, int dwCallbackInstance, int dwParam1, int dwParam2, int dwParam3);
public const Int32 LINE_CALLSTATE = 2;
public const Int32 LINE_REPLY = 12;
public const Int32 LINECALLSTATE_OFFERING = 0x00000002;
public const Int32 LINECALLSTATE_PROCEEDING = 0x00000200;
public const Int32 LINECALLSTATE_CONNECTED = 0x00000100;
public const Int32 LINECALLSTATE_DISCONNECTED = 0x00004000;
public const Int32 LINECALLSTATE_BUSY = 0x00000040;
public const Int32 LINECALLSTATE_IDLE = 0x00000001;
public const Int32 LINEINITIALIZEEXOPTION_USEHIDDENWINDOW = 0x00000001;
// public const Int32 LINEINITIALIZEEXOPTION_USEEVENT = 0x00000002;
public const Int32 LINECALLPRIVILEGE_MONITOR = 0x00000002;
public const Int32 LINECALLPRIVILEGE_OWNER = 0x00000004;
// public const Int32 LINEMEDIAMODE_INTERACTIVEVOICE = 0x00000004;
public const Int32 LINEMEDIAMODE_DATAMODEM = 0x00000010;
[StructLayout(LayoutKind.Explicit)]
public struct LINEINITIALIZEEXPARAMS
{
[FieldOffset(0)]
public UInt32 dwTotalSize;
[FieldOffset(4)]
public UInt32 dwNeededSize;
[FieldOffset(8)]
public UInt32 dwUsedSize;
[FieldOffset(12)]
public UInt32 dwOptions;
[FieldOffset(16)]
public IntPtr hEvent;
[FieldOffset(16)]
public IntPtr hCompletionPort;
[FieldOffset(20)]
public UInt32 dwCompletionKey;
}
[StructLayout(LayoutKind.Sequential)]
public struct LINEEXTENSIONID
{
public UInt32 dwExtensionID0;
public UInt32 dwExtensionID1;
public UInt32 dwExtensionID2;
public UInt32 dwExtensionID3;
}
[DllImport("coredll.dll", SetLastError = true)]
public extern static Int32 lineInitializeEx(
out IntPtr lphLineApp,
IntPtr hInstance,
IntPtr lpfnCallback,
string lpszFriendlyAppName,
out int lpdwNumDevs,
ref int lpdwAPIVersion,
ref LINEINITIALIZEEXPARAMS lpLineInitializeExParams
);
[DllImport("coredll.dll", SetLastError = true)]
public extern static Int32 lineNegotiateAPIVersion(
IntPtr lphLineApp,
UInt32 dwDeviceID,
int dwAPILowVersion,
int dwAPIHighVersion,
out int lpdwAPIVersion,
out LINEEXTENSIONID lpExtensionID
);
[DllImport("coredll.dll", SetLastError = true)]
public extern static Int32 lineOpen(
IntPtr lphLineApp,
UInt32 dwDeviceID,
out IntPtr lphLine,
int dwAPIVersion,
UInt32 dwExtVersion,
UInt32 dwCallbackInstance,
UInt32 dwPrivileges,
UInt32 dwMediaModes,
IntPtr lpCallParams
);
[DllImport("coredll.dll", SetLastError = true)]
public extern static Int32 lineMakeCall(
IntPtr hLine,
out IntPtr lphCall,
string lpszDestAddress,
UInt32 dwCountryCode,
IntPtr lpCallParams
);
[DllImport("coredll.dll", SetLastError = true)]
public extern static Int32 lineSetCallPrivilege(
IntPtr lphCall,
UInt32 dwCallPrivilege
);
[DllImport("coredll.dll", SetLastError = true)]
public extern static Int32 lineDrop(
IntPtr lphCall,
string lpsUserUserInfo,
UInt32 dwSize
);
[DllImport("coredll.dll", SetLastError = true)]
public extern static Int32 lineDeallocateCall(
IntPtr lphCall
);
[DllImport("coredll.dll", SetLastError = true)]
public extern static Int32 lineClose(
IntPtr hLine
);
[DllImport("coredll.dll", SetLastError = true)]
public extern static Int32 lineShutdown(
IntPtr hLineApp
);
}
}