Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

lineInitializeEx LINEERR_OPERATIONFAILED problem

56 views
Skip to first unread message

vandenberg_greg

unread,
Dec 23, 2009, 12:17:01 AM12/23/09
to
I'm using TAPI in a visual c++ application that will be on 23 remote laptops
distributed around the world in order to collect satellite data. I would
like everything to be as robust as possible and handle accidental
disconnects gracefully by shutting off the lineEventThread, then closing,
then reopening the modem and restarting everything (from another thread). I
simulate this by unplugging and replugging the phone line back in. So far my
program works great but every once in a while when the program closes then
reopens the modem the lineInitializeEx function returns a
LINEERR_OPERATIONFAILED message. Once this happens lineInitializeEx keeps
returning this message indefinitely. Is the some way to clear up
lineInitializEx in my program?

Here's my Openmodem() and Close() and lineEventThread:

int CTapiModem::OpenModem(LPVOID lp)
{
LINEINITIALIZEEXPARAMS stInitParams;
LINEDEVCAPS *lpDevCaps =NULL;
LONG lRet;

DWORD dwMediaMode;
DWORD dwNumDevs =0;
DWORD dwTAPIVer =TAPI_CURRENT_VERSION;
DWORD dwTmpVer =0;
LINEEXTENSIONID stExtID;
unsigned long i;

CWinguardDlg *m_pOwner;

m_pObj = lp;

m_pOwner = (CWinguardDlg *) m_pObj;


m_pOwner->StatusPrint("******* OPENING MODEM*********");
TRACE("******CTapiModem:Open()\n");

m_hEventFromThread = NULL;
m_hLineMsgThread = NULL; // TAPI Event monitoring thread.
m_bStopLineEventThread = FALSE;
m_dwLineMsg= 0;
m_nDevID = 0;
m_hLineApp = NULL;
m_hLine = NULL;
m_hCall = NULL;



SecState = SS_Idle;

m_hSerialHandle = NULL;


dwMediaMode = LINEMEDIAMODE_DATAMODEM; // data/fax this should be

lRet = lineSetNumRings(m_hLine,0,4);


memset(&stInitParams, 0, sizeof(LINEINITIALIZEEXPARAMS));
// set the options...
stInitParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
stInitParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;

// Initialize TAPI.
lRet = lineInitializeEx(&m_hLineApp,
AfxGetInstanceHandle(),
NULL,
AfxGetAppName(),
&dwNumDevs,
&dwTAPIVer,
&stInitParams);

if(lRet) //error
{
TRACE(" IN OPEN MODEM AFTER lineInitializeEx, %x\n",
lRet);
return lRet;
}

// Got the event handle...
m_hLineEvent = stInitParams.Handles.hEvent;

m_nDevID = -1;
// go through the device list and select the appropriate device to
transfer voice
for(i=0;i<dwNumDevs;i++) //i=0 == built in modem which
{
lRet = lineNegotiateAPIVersion(m_hLineApp, i, dwTAPIVer,
dwTAPIVer, &dwTmpVer, &stExtID);
if(lRet != 0)
continue;

lpDevCaps = (LINEDEVCAPS
*)malloc(sizeof(LINEDEVCAPS)+1024);// Allocate a little extra memory...

memset(lpDevCaps, 0, sizeof(LINEDEVCAPS)+1024);
lpDevCaps->dwTotalSize = sizeof(LINEDEVCAPS)+1024;

lRet = lineGetDevCaps(m_hLineApp, i, dwTmpVer, 0,
lpDevCaps);

if(lRet) //error
{
free(lpDevCaps);\
lpDevCaps=NULL;
continue;
}

char *szText = ((char*)lpDevCaps) +
lpDevCaps->dwLineNameOffset;// FOR DEBUGGING
// for more refer LINEMEDIAMODE_ Constants in MSDN

if(lpDevCaps->dwMediaModes & dwMediaMode)
{
free(lpDevCaps);
m_nDevID = i;
break;
}
free(lpDevCaps);
}



if(m_nDevID < 0)
{
TRACE("LINEERR_BADDEVICEID: %x\n", LINEERR_BADDEVICEID);
return LINEERR_BADDEVICEID; // no device available
}

// Open the line...
lRet = lineOpen(m_hLineApp, m_nDevID, &m_hLine, dwTAPIVer,
0x00000000, 1,LINECALLPRIVILEGE_OWNER,dwMediaMode,NULL);
if(lRet)
{
TRACE(" IN OPEN MODEM AFTER lineOpen, %x\n", lRet);
lineShutdown(m_hLineApp);
return lRet;
}

// We want to be notified for everything
lRet = lineSetStatusMessages(m_hLine, 0x1ffffff, 0);
if(lRet)
{
TRACE(" IN OPEN MODEM AFTER lineSetStatusMessages, %x\n",
lRet);
lineShutdown(m_hLineApp);
return lRet;
}


m_bStopLineEventThread = FALSE;


DWORD lineEventID;

m_hLineMsgThread =
CreateThread(NULL,NULL,LineEventThread,this,NULL,&lineEventID);
TRACE("After createthread, LineEventThread ID: %x\n", lineEventID);

SetThreadPriority(m_hLineMsgThread, THREAD_PRIORITY_BELOW_NORMAL);
m_hEventFromThread = CreateEvent(NULL,0,0,NULL);

m_pOwner->m_StopGetByte = CreateEvent(0, TRUE, FALSE, 0);
m_pOwner->m_WaitGetByte = CreateEvent(0, TRUE, FALSE, 0);

return 0;
}

int CTapiModem::Close(LPVOID lp)
{
LINECALLSTATUS stLineStatus;
LONG lRet;

CWinguardDlg *m_pOwner;

m_pObj = lp;

m_pOwner = (CWinguardDlg *) m_pObj;


TRACE(" ************CTapiModem::Close()\n");

if(m_hCall) // Call might be in progress...
{
memset(&stLineStatus, 0, sizeof(LINECALLSTATUS));

lRet = lineGetCallStatus(m_hCall, &stLineStatus);
// Technically, lineGetCallStatus returns more info
than
// there is in the structure. Since we don't care
about it,
// We just go on our merry way...
if(!lRet) // If it didn't fail, there's at least a call that
needs to be dropped.
lineDrop(m_hCall, NULL, 0);

// lineDeallocateCall(m_hCall);
m_hCall = NULL;
}

if (m_hSerialHandle)
{
CloseHandle(m_hSerialHandle);
m_hSerialHandle = NULL;
}

if(m_hLine)
lineClose(m_hLine);
m_hLine = NULL;

if(m_hLineMsgThread)
{
m_bStopLineEventThread = TRUE; // stop the event waiting
thread
TRACE("B4 WaitForSingleObject(m_hLineMsgThread, INFINITE)\n");
WaitForSingleObject(m_hLineMsgThread, INFINITE); // Wait for
it to comit suicide..
TRACE("F2 WaitForSingleObject(m_hLineMsgThread, INFINITE)\n");
CloseHandle(m_hLineMsgThread);
CloseHandle(m_hEventFromThread);
}


if(m_hLineApp)
lineShutdown(m_hLineApp);
m_hLineApp = NULL;

m_hLineMsgThread = NULL;
m_hEventFromThread = NULL;

m_dwLineMsg= 0;
m_nDevID = -1;

if (m_pOwner->m_StopGetByte)
{
CloseHandle(m_pOwner->m_StopGetByte);
m_pOwner->m_StopGetByte =NULL;
}

if (m_pOwner->m_WaitGetByte)
{
CloseHandle(m_pOwner->m_WaitGetByte);
m_pOwner->m_WaitGetByte =NULL;
}
//wait for thread to terminate
Sleep(100);


return 0;
}

HANDLE CTapiModem::GetHandle(const char *szClassType, long *lError)
{

HANDLE mHandle;

VARSTRING *pvarStrDevID = (VARSTRING
*)malloc(sizeof(VARSTRING)+255);

memset(pvarStrDevID,0,sizeof(VARSTRING)+255);
pvarStrDevID->dwTotalSize = sizeof(VARSTRING)+255;

long lRet =
lineGetID(m_hLine,0,m_hCall,LINECALLSELECT_LINE,pvarStrDevID,szClassType);
if(lRet)
{
*lError = lRet;
return NULL;
}

*lError = 0;

mHandle = *((LPHANDLE)((char *)pvarStrDevID +
pvarStrDevID->dwStringOffset));
free(pvarStrDevID);

return mHandle;
}

//**************************************************************************
********

DWORD WINAPI CTapiModem::LineEventThread(LPVOID lpVoid)

{
long lRet;
LINEMESSAGE stLineMsg;
char *szError;
CTapiModem *pcTapiModem = (CTapiModem *)lpVoid;


CWinguardDlg *m_pOwner;


m_pOwner = (CWinguardDlg *) pcTapiModem->m_pObj;
modem_task *mtask = m_pOwner->m_p_modem_task;

TRACE("in LineEventTHREAD,m_bStopLineEventThread: %d\n",
pcTapiModem->m_bStopLineEventThread);

while(!pcTapiModem->m_bStopLineEventThread)
{
// Get a TAPI event if available, wait for 10ms just enough
to give up quantum

int iret = WaitForSingleObject(pcTapiModem->m_hLineEvent, 1);
if (iret == WAIT_OBJECT_0)
{
//TAPI's got something
if ((lRet = lineGetMessage(pcTapiModem->m_hLineApp,
&stLineMsg, 0)) != 0)
{
return lRet;
}
TRACE("*in LineEventTHREAD, dwMessageID: %d\n",
stLineMsg.dwMessageID);

// Process the returned msg
switch (stLineMsg.dwMessageID)
{
case LINE_REPLY: // Sent after lineMakeCall or lineDrop

// Get a TAPI event if available, wait for 10ms just enough
to give up quontum
TRACE("LINE_REPLY \n");
pcTapiModem->SecState = SS_StartConnection;
break;

case LINE_CALLSTATE: // Sent after change of call state
TRACE("LINE_CALLSTATE \n");
switch (stLineMsg.dwParam1)
{
case LINECALLSTATE_OFFERING: //Incoming call is
offering. answer and
// connect
// Get the call handle
TRACE("LINECALLSTATE_OFFERING\n");
pcTapiModem->m_hCall = (HCALL)stLineMsg.hDevice;
pcTapiModem->m_dwLineMsg = LINECALLSTATE_OFFERING;
lRet = lineAnswer(pcTapiModem->m_hCall, NULL, 0);
lRet = (lRet>0)?0:lRet;
break;

case LINECALLSTATE_IDLE:
TRACE("-------LINECALLSTATE_IDLE\n");
lineDeallocateCall(pcTapiModem->m_hCall);
pcTapiModem->m_hCall = NULL;

if(pcTapiModem->m_hLine)
lineClose(pcTapiModem->m_hLine);
pcTapiModem->m_hLine = NULL;

if(pcTapiModem->m_hLineApp)
lineShutdown(pcTapiModem->m_hLineApp);
pcTapiModem->m_hLineApp = NULL;


pcTapiModem->m_bStopLineEventThread = TRUE;

pcTapiModem->m_dwLineMsg= 0;
pcTapiModem->m_nDevID = -1;

break;

case LINECALLSTATE_CONNECTED:

if(stLineMsg.dwCallbackInstance == 1)
{
m_pOwner->StatusPrint("+++++
CONNECTED ++++++");
pcTapiModem->SecState =
SS_ConnectInProgress;

TRACE("LINECALLSTATE_CONNECTED\n");
pcTapiModem->m_dwLineMsg =
LINECALLSTATE_CONNECTED;

pcTapiModem->m_hSerialHandle =
pcTapiModem->GetHandle("comm/datamodem",&lRet);
if(lRet)
{
pcTapiModem->m_hSerialHandle = NULL;
pcTapiModem->GetErrorString(lRet,szError);
TRACE("GetHandle returns: %d\n", szError);
return 0;
}
}
break;

case LINECALLSTATE_DISCONNECTED:
m_pOwner->StatusPrint("*** DISCONNECTED
***");
TRACE("-----LINECALLSTATE_DISCONNECTED
***\n");
lineDrop(pcTapiModem->m_hCall, NULL, 0);

CloseHandle(pcTapiModem->m_hSerialHandle);
pcTapiModem->m_hSerialHandle = NULL;
pcTapiModem->SecState = SS_DisConnected;

::SetEvent(m_pOwner->m_StopGetByte);

TRACE("@@@@ IN LINECALLSTATE_DISCONNECTED: b4 waitforsingleobject
m_pOwner->m_WaitGetByte %x\n",
m_pOwner->m_WaitGetByte);
::WaitForSingleObject(m_pOwner->m_WaitGetByte, 5000); //wait
5 seconds
TRACE("@@@@ IN LINECALLSTATE_DISCONNECTED: f2 waitforsingleobject\n");

// Close handles

pcTapiModem->m_hCall = NULL;

break;

default:
TRACE("in LineEventTHREAD, DEFAULT: dwMessageID:
%x\n",
stLineMsg.dwMessageID);

break;
}
break;

default:
break;
}

} //end if


} //endwhile
TRACE("CTapiModem::LineEventThread FINISHED\n");
pcTapiModem->m_hLineMsgThread = NULL;


return 0;
}

//**************************************************************************
*****

Gregory Hartmann
Performance Evaluation
InDyne, WROCI
Vandenberg AFB, CA
Work: (805)605-2056 / DSN 275-2056

Andreas Marschall [exMVP TAPI]

unread,
Dec 23, 2009, 6:44:16 AM12/23/09
to
"vandenberg_greg" <vandenb...@discussions.microsoft.com> schrieb im
Newsbeitrag news:ABE4A8F1-5E8C-4808...@microsoft.com...

> I'm using TAPI in a visual c++ application that will be on 23 remote
> laptops
> distributed around the world in order to collect satellite data. I would
> like everything to be as robust as possible and handle accidental
> disconnects gracefully by shutting off the lineEventThread, then closing,
> then reopening the modem and restarting everything (from another thread).
> I
> simulate this by unplugging and replugging the phone line back in. So far
> my
> program works great but every once in a while when the program closes then
> reopens the modem the lineInitializeEx function returns a
> LINEERR_OPERATIONFAILED message. Once this happens lineInitializeEx keeps
> returning this message indefinitely.

Gregory,
what do you do to clear this isuue?
- Restart your app
- Restart TAPISRV (Telephony Service)
- Reboot (external) modem
- Reboot PC


> Is the some way to clear up
> lineInitializEx in my program?

The question is: why does lineInitializEx () fail repeatedly.
I guess due to an issue within the Modem HW / driver or UniModem TSP.
This cannot be cleared from within a TAPI app.
Maybe there is something in your code that may cause this "once in a while",
i.e. a race condition when releasing stuff prior your re-establish attempt.

I noticed a couple of thingschqving a quick look at your code:

- it isn't recommended to lineClose() / lineShutdown after each call. Only
do this when you actually want to exit your app

- usage of LINECALLPRIVILEGE_OWNER | LINECALLPRIVILEGE_MONITOR instead of
solely LINECALLPRIVILEGE_OWNER

> SetThreadPriority(m_hLineMsgThread, THREAD_PRIORITY_BELOW_NORMAL);
- it isn't recommended to handle events with lowered priority
- if you handle COM port data then even higher priority for this thread m,ay
be worth trying

> case LINE_REPLY: // Sent after lineMakeCall or lineDrop

> pcTapiModem->SecState = SS_StartConnection;
- This caues SS_StartConnection on all LINE_REPLY. Is that what you
intended?

> //wait for thread to terminate
> Sleep(100);

- you don't check here whether the thread actually terminated


--
Best Regards
Andreas Marschall
Microsoft MVP for TAPI / Windows SDK / Visual C++ 2003-2008
TAPI / TSP Developer and Tester
My TAPI and TSPI FAQ:
http://www.I-B-A-M.de/Andreas_Marschall's_TAPI_and_TSPI_FAQ.htm
My Toto� Tools (a collection of free, mostly TAPI related tools):
http://www.i-b-a-m.de/Andreas_Marschall's_Toto_Tools.htm
TAPI development around the world (Frappr! map):
http://www.frappr.com/TAPIaroundTheWorld
* Please post all messages and replies to the newsgroup so all may
* benefit from the discussion. Private mail is usually not replied to.
* This posting is provided "AS IS" with no warranties, and confers no
rights.

vandenberg_greg

unread,
Dec 23, 2009, 4:58:01 PM12/23/09
to

> .
>
Andreas,

Thanks for the prompt reply. I will look into the issues you brought up
after next week after Christmas. If I stop my application by quitting Debug
(I am running this in Debug mode) then restart using Debug (f5) everything
clears up and runs fine until I make it hang up again.

vandenberg_greg

unread,
Dec 23, 2009, 5:00:02 PM12/23/09
to


"Andreas Marschall [exMVP TAPI]" wrote:

> .
>
Also, I am using the internal modem on a Sony Vaio

Andreas Marschall [exMVP TAPI]

unread,
Dec 24, 2009, 8:18:16 AM12/24/09
to
"vandenberg_greg" <vandenb...@discussions.microsoft.com> schrieb im
Newsbeitrag news:6EDF5BAD-72B6-4787...@microsoft.com...

> Andreas,
>
> Thanks for the prompt reply. I will look into the issues you brought up
> after next week after Christmas. If I stop my application by quitting
> Debug
> (I am running this in Debug mode) then restart using Debug (f5) everything
> clears up and runs fine until I make it hang up again.

Gregory, you are welcome.

Are you encountering the issue only with the debug version of your app, or
even only if you run it in the debugger,
or is also occuring with the release version (not runnin in debugger) ?

0 new messages