C++/VB - TAPI modem doesn't seem to receive all the data being sent to it

Asked By vandenberg_greg
11-Jan-10 11:34 PM
Andreas, thanks for the help with lineInitializeEx constanly returning
LINEERR_OPERATIONFAILED. It turned out that setting the thread priority to
Normal fixed it.

However now I am having a problem with my application skipping data that gets
sent to it. I have two separate threads that read and write from the modem.
My program sends a message to the calling program letting it know that
everything connected ok. The calling program immediately responds (< 1
millisecond) with its response, but this message is not getting picked up by
my program. After around 9 seconds the calling program sends the same
response again which is then picked up by my program, so it kind of works but
my boss does not like the delay. The old software that my application is based
on had custom written modem software in 16 bit assembly language and only
runs in DOS, but it appears to get everything written to it.

Could it be that the readfile and writefile functions my thread uses are
stepping on each other? is there a way to fix this? I tried putting a mutex
lock and unlock around the pertinant bits of code but this did not appear to
do anything.
TAPIaroundTheWorld
(1)
GetOverlappedResult
(1)
GetLastError
(1)
CTapiModem
(1)
LineInitializeEx
(1)
TransmitThread
(1)
HSerialHandle
(1)
ReceiveThread
(1)
  Andreas Marschall [exMVP TAPI] replied to vandenberg_greg
12-Jan-10 06:25 AM
Greg, you are welcome.


When you are using UniModem TSP to transfer data then you have to use
OVERLAPPED IO.
In addition it may even be required to increase (read and write) thread
priority above normal.
Please see the TapiComm sample from MS P-SDK:
http://www.tapi.info/default.aspx/TAPI/PSDKSamples.html
Especially see TapiComm.Doc for "overlapped" and "priority".

--
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 replied to vandenberg_greg
15-Jan-10 10:46 PM
Andreas,

Thanks for the help. I looked at the example you pointed me to, but am still
having problems.

I am using overlapped i/o and I bumped the priority up to above normal for
the transmit thread and highest for the receive thread but no luck.

For some reason ReadModem just is not getting any data in my thread. The
TransmitThread seems to work ok though.
I know ReadModem works since I used it earlier in my program in a non
threaded function during the logging in process to the calling program.

I thought it was getting data earlier but it turned out that some how the
buffer I used in ReceiveThread was getting overwritten with data in the
transmit thread. No events ever got signalled and dwReadLen in the ReadFile
call always returns 0 so I know it is not working right.


My code follows below. I made the ReceiveThread as simple as possible to
test it. The SendCommand function is the most important part of the
TransmitThread as far as TAPI is concerned.

ReadModem and WriteModem are the functions that use TAPI. ReceiveThread and
TransmitThread are the threads that use ReadModem and WriteModem,
respectively.

Do you have any ideas what I am doing wrong or what is going on?

Thanks,

Greg


bool CTapiModem::WriteModem(int len, unsigned char *buf, int timeout)
{

DWORD dwWriteLen =0;
int nRet;
char *szText;

OVERLAPPED ov = {0, 0, 0, 0, NULL}; // Initialization is important!

ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ov.Offset = 0;
ov.OffsetHigh = 0;

nRet = WriteFile(m_hSerialHandle,buf,len,&dwWriteLen,&ov);
if(!nRet)
{
nRet = GetLastError();
if(nRet != ERROR_IO_PENDING)
{
GetErrorString(nRet,szText);
return FALSE;
}

switch(WaitForSingleObject(ov.hEvent,timeout))
{
case WAIT_OBJECT_0:
GetOverlappedResult(m_hSerialHandle, &ov, &dwWriteLen,FALSE);
return TRUE;
break;
default:
break;
}
}
return FALSE;

}


int CTapiModem::ReadModem(unsigned char *buf, int *count, int timeout)
{
// read "count" bytes at a time from modem

DWORD dwReadLen =0;
int nRet;
char *szText;

OVERLAPPED ov = {0, 0, 0, 0, NULL}; // Initialization is important!;
//createEvent parameters:
//1 - pointer to security attibutes structure
//2 - manual reset
//3 - initial state
//4 name of event object
ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ov.Offset = 0;
ov.OffsetHigh = 0;


if (m_hSerialHandle != NULL)
{

nRet = ReadFile(m_hSerialHandle,buf,*count,&dwReadLen,&ov);

if (!nRet)
{
nRet = GetLastError();
  mikenac replied to vandenberg_greg
02-Feb-10 12:03 PM
Greg,

Out of curiosity, can you reboot and try to run this application again? I am
having a similar issue that occurs when the TAPI service gets "Goofed Up".
The service will not restart once the "Goof Up" occurs and requires a reboot
for me to again get data.
help
OffsetHigh = 0; if (m_hSerialHandle ! = NULL) { nRet = ReadFile(m_hSerialHandle, buf, *count, &dwReadLen, &ov); if (!nRet) { nRet = GetLastError(); if(nRet ! = ERROR_IO_PENDING) { GetErrorString(nRet, szText); if (nRet = = ERROR_INVALID_HANDLE) { return 1; } } } if (WaitForSingleObject(ov.hEvent, timeout) = = WAIT_OBJECT_0) { GetOverlappedResult(m_hSerialHandle, &ov, &dwReadLen, FALSE); } else { return 2; / / timeout elapsed, objects state = non-signalled / / = buffer empty else { *count = dwReadLen; return 0; } } else { *buf = NULL; return 5; / / m_hSerialHandle = = NULL } } Win32 TAPI Discussions TAPIaroundTheWorld (1) ReadIntervalTimeout (1) GetOverlappedResult (1) SetCommTimeouts (1) GetLastError (1) CTapiModem (1) ExMVP (1) HSerialHandle (1) So is my problem with readfile not a 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
When to call GetOverlappedResult()? C++ / VB In looking over the docs and sample applications on the MSDN site it's not obvious to me under what circumstances I should be calling GetOverlappedResult(). After some debugging I think I have the logic correct, but I want to confirm I'm not missing any other cases. The docs and samples seem to indicate that GetOverlappedResult() only needs to be called when one of the API's which take an OVERLAPPED object return FALSE and GetLastError() returns ERROR_IO_PENDING. This is how I initially implemented things. However, this wasn't sufficient. When ReadFile() returns FALSE and GetLastError() returns ERROR_MORE_DATA appears to be another case where you need to call GetOverlappedResult() because the ReadFile() call did not return the number of bytes read. Am I correct about this? Are there any other cases in which I should be calling GetOverlappedResult()? - - Thanks, Nick nicknospamdu@community.nospam remove "nospam" change community. to msn.com Win32 Kernel Discussions OVERLAPPED.Internal (1) FileStream.BeginRead (1) FileStream.EndRead (1) GetQueuedCompletionStatus (1) CreateIoCompletionPort (1) LpNumberOfBytesRead (1) GetOverlappedResult (1) Hi Nick, Are you using I / O completion port in your application? There are
LoadLibrary() fails but GetLastError() returns 0 C++ / VB Could anyone please explain why GetLastError() might return 0 after LoadLibrary() fails (i.e. returns NULL). GetLastError() is called immediately after LoadLibrary(). Thanks, Bogdan Win32 Kernel Discussions LoadLibrary (1) GetLastError (1) MSFTNGP (1) HModule (1) StrLibPath (1) KHHA (1) DLL (1) LoadLibraryEx (1) Hi Bogdan If the function fails, the return value is NULL. To get extended error information, call GetLastError. Windows Me / 98 / 95: If you are using LoadLibrary to load a module that contains hand some functions of the windows api do some strange things internally and sometimes the GetLastError() values are not valid returned from the function. This is what i found out over is rather simple: HINSTANCE hModule = LoadLibrary(strLibPath); ASSERT(NULL ! = hModule); if (NULL = = hModule) { DWORD dwError = ::GetLastError(); / / . . . } In one specific case, the API failed because strLibPath pointed to a nonexistent DLL (result running debug version of the app. I ignored ASSERT() between the call to LoadLibrary() and GetLastError(). Your "hook" hint woke me up. Thanks and sorry for the confusion. Bogdan keywords: LoadLibrary
Exception and GetLastError() C++ / VB Hi there: look at code blow / / / / / / / / / / / / / / / / / / / / try { blah blah blah }catch(. . .) { DWORD dw = GetLastError() } / / / / / / / / / / / / / / / / / / / / Does it make sence to call GetLastError() in catch block? In my opinion, I dont think it's necesary do like above but could sure about it. VC Language Discussions Visual Studio .NET (1) MiniDumpWriteDump (1) GetLastError (1) Report (1) APIs (1) DrWatson (1) Mortem (1) Postmortemdebug (1) There is not enough is stale. Regards, Will Hi, No, it does not make sense. Win32-APIs which use GetLastError to return error situations do not throw exceptions, so there should be no relationship between minidumps: Visual Studio .NET" http: / / www.codeproject.com / debug / postmortemdebug_standalone1.asp Alex keywords: Exception, and, GetLastError() description: Hi there: look at code blow / / / / / / / / / / / / / / / / / / / / try { blah blah blah }catch(. . .) { DWORD dw = GetLastError() } / / / / / / / / / / / / / / / / / / / / Does it