Monitor's com port - reading only. 

On line web page:
http://tunesmithy.co.uk/comportmonitor.htm

E-mail support@tunesmithy.co.uk

In a nutshell:


When you start, you make an event which will be set to stop 
the com port monitor thread if needed - e.g. in your
WinMain proc, or WM_INITDIALOG or the like. Also
begin the thread to monitor it:

  case WM_INITDIALOG :
  {
   hEndComPortEvent = CreateEvent
   (
    NULL,   // no security attributes 
    TRUE,  // auto reset event 
    FALSE,  // not signaled 
    NULL    // no name 
    );
   _beginthread(MonitorComPort,0,(int *)icom);

Now in the thread, what you do is:

char *szComm[]= "com1"; // or "com2" etc.
HANDLE hCom;

 hCom = CreateFile
  (szComm,GENERIC_READ 
		 ,0, // exclusive access
		 NULL, // no security
		 OPEN_EXISTING,
		 FILE_FLAG_OVERLAPPED, // overlapped I/O
		 NULL  // null template 
  );

Has to be overlapped i.o. so that the com port monitor thread can
be closed without using TerminateThread - if you want
to stop and start it anyway - e.g. to change any of the settings 
while it is running.

if(hCom)
{
 DCB      dcb;
 SetupComm(hCom, MAX_BUFF, MAX_BUFF); // set buffer sizes
 GetCommState(hCom, &dcb);

 // Then set all the parameters in the dcb structure that you need to
 // set - if you want to use the existing values, don't need to do anything
 // here.

 // Now do the time outs - use MAXDWORD if unsure
 COMMTIMEOUTS CommTimeouts;

 SetCommState(hCom, &dcb);
 GetCommTimeouts(hCom, &CommTimeouts);
 CommTimeouts.ReadIntervalTimeout = MAXDWORD;//100;
 CommTimeouts.ReadTotalTimeoutConstant = 0;//100;
 CommTimeouts.ReadTotalTimeoutMultiplier =0;// 50;
 CommTimeouts.WriteTotalTimeoutConstant = 0;//100;
 CommTimeouts.WriteTotalTimeoutMultiplier = 0;//50;
 bPortReady = SetCommTimeouts(hCom, &CommTimeouts);

 // Make an overlapped structure for i.o.

 OVERLAPPED overlapped;
 memset(&overlapped,0,sizeof(overlapped));
  overlapped.hEvent = CreateEvent(
   NULL,   // no security attributes 
   TRUE,  // auto reset event 
   FALSE,  // not signaled 
   NULL    // no name 
   );


 // Set the mask for the events you want to listen for
 fSuccess = SetCommMask
  (hCom,EV_RXCHAR | EV_RXFLAG);

  // If all is well, go into a loop looking for data

  // Now here the thing is that we read the data as overlapped.
  // So WaitCommEvent will return immediately - and set the
  // handle in its overlapped structure when data arrives.



  if(fSuccess)
  {
   DWORD dwError=0;
   COMSTAT comState;
   HANDLE hArray[2];// an array of events to pass to WaitForMultipleObjects 
   hArray[0]=overlapped.hEvent;
   hArray[1]=hEndComPortEvent;
   ClearCommError(hCom,&dwError,&comState); 
   for(;;)
   {
    WaitCommEvent(hCom, &dwEvtMask,&overlapped); // wait for data - but this
                                                 // will return immediately because
                                                 // it is overlapped
    ClearCommError(hCom,&dwError,&comState); 
    // wait for either of the two events to get signalled
    // - the one from WaitCommEvent or the one you set yourself
    // to end this thread
    switch(WaitForMultipleObjects(2,hArray,FALSE, INFINITE))
    {
     case WAIT_OBJECT_0:// input pending - this is the first of the array
                        // entries, i.e. overlapped.hEvent
      ResetEvent(hArray[0]);// reset the event to not signalled
      break;
     case WAIT_OBJECT_0+1:// this is the one to end the thread
      ResetEvent(hArray[1]);
      goto end_thread;
     case WAIT_FAILED:;
    }
    // now we can get the data
    for(;;)
    {
     int iBytesReadThisTime=0;
     int iBytesWas=iBytesRead;
     BOOL bRead;
     if(end_com_threads)
      goto end_thread;
     bRead= ReadFile(hCom, &szData[iBytesRead], MAX_BUFF-iBytesRead-1, &iBytesReadThisTime,&overlapped);
     iBytesRead+=iBytesReadThisTime;
     if(bRead==FALSE&&GetLastError()==ERROR_IO_PENDING)
     {
      Sleep(2);
      read_loops++;
      continue;
     }
     else
     // we have got it all now
      break;
    }
    szData[iBytesRead]='\0';
   }
 // Clean up - just close the handle. PurgeCom just in case we
 // stopped it in the middle of something.

 end_thread:;
 if(hCom)
 {
  PurgeComm(hCom,PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_TXABORT);
  CloseHandle(hCom);
  hCom=0;
 }

So, here is the source code for the thread.

You need to include this procedure your project, and also outside of it, 
you need these global variables, which you can set accordingly

int icom=1;
char start_up=1;
char use_existing_settings;
HANDLE hEndComPortEvent;
int BaudRate=2400;
int ByteSize=8;
int Parity=NOPARITY; // EVENPARITY // ODDPARITY

To start the thread use
_beginthread(MonitorComPort,0,NULL);

Whenever you change any settings, use the same call
- the thread will end its own previous instance if any.

When finished, call SetEvent(hEndComPortEvent);

To test if it is still running, check to see
if hEndComPortEvent is non zero.

void MonitorComPort(void *pvoid)
{
 // minimal version with no error reporting or indications of
 // progress apart from data received.
 HANDLE   hCom=0;
 BOOL     bPortReady=0;
 DCB      dcb;
 COMMTIMEOUTS CommTimeouts;
 OVERLAPPED overlapped;
 BOOL fSuccess=0;
 DWORD dwEvtMask=0;
 int nEvents=0;
 int ii=0;
 char szCom[STRMAX];
 static char com_running;
 char szmsg[STRMAX];
 sprintf(szCom,"com%d",icom);
 memset(&dcb,0,sizeof(DCB));
 if(hEndComPortEvent)
 {
  SetEvent(hEndComPortEvent);
  Sleep(200);
  {
   int ii=0;
   for(ii=0;ii<20;ii++)
   {
    Sleep(50);
    if(hEndComPortEvent==0)
     break;
   }
  }
  if(hEndComPortEvent)
   // couldn't close the thread
   return;
 }
 hCom = CreateFile
  (szCom
		 ,GENERIC_READ // | GENERIC_WRITE,
		 ,0, // exclusive access
		 NULL, // no security
		 OPEN_EXISTING,
		 FILE_FLAG_OVERLAPPED, // overlapped I/O
		 NULL  // null template 
  );
 if(hCom==INVALID_HANDLE_VALUE)
 {
  sprintf(szmsg,"Couldn't open Com port %d",icom);
  AddEvent(szmsg);
  return;
 }
 if(!hEndComPortEvent)
  hEndComPortEvent = CreateEvent
  (
   NULL,   // no security attributes 
   TRUE,  // auto reset event 
   FALSE,  // not signaled 
   NULL    // no name 
   );
 memset(&dcb,0,sizeof(dcb));
 dcb.DCBlength=sizeof(dcb);
 SetupComm(hCom, MAX_BUFF, MAX_BUFF); // set buffer sizes
 GetCommState(hCom, &dcb);
 // Set all the parameters in the dcb structure that you need to
 // set - if you want to use the existing values, don't need to do anything
 // here.
 if(use_existing_settings)
 {
		Parity=dcb.Parity;
		BaudRate=dcb.BaudRate;
		ByteSize=dcb.ByteSize;
  UpdateComPortDialog();
 }
 else
 {
  dcb.DCBlength = sizeof ( DCB ) ;
  dcb.BaudRate        = BaudRate;
  dcb.ByteSize        = (BYTE) ByteSize;// number of bits/byte, 4-8
  dcb.Parity=Parity;
  dcb.fParity=Parity==NOPARITY?0:1;
  dcb.StopBits = ONESTOPBIT;    // options are 0,1,2 = 1, 1.5, 2 - this is a matter of the amplitude of the stop bit signal
                                // which is why you have fractional values
  dcb.fOutxCtsFlow    = 0;
  dcb.fOutxDsrFlow    = 0;
  dcb.fDtrControl     = DTR_CONTROL_DISABLE;
  dcb.fDsrSensitivity = 0;
  dcb.fRtsControl     = RTS_CONTROL_DISABLE;
  dcb.fOutX           = 0;
  dcb.fInX            = 0;
  dcb.fErrorChar      = 0;
  dcb.fBinary         = 1;
  dcb.fNull           = 0;
  dcb.fAbortOnError   = 0;
  dcb.wReserved       = 0;
  dcb.XonLim          = 2;
  dcb.XoffLim         = 4;
  dcb.XonChar         = 0x13;
  dcb.XoffChar        = 0x19;
  dcb.EvtChar         = 0;
 }
 SetCommState(hCom, &dcb);
 // Now do the time outs - use MAXDWORD if unsure
 GetCommTimeouts(hCom, &CommTimeouts);
 CommTimeouts.ReadIntervalTimeout = MAXDWORD;//100;
 CommTimeouts.ReadTotalTimeoutConstant = 0;//100;
 CommTimeouts.ReadTotalTimeoutMultiplier =0;// 50;
 CommTimeouts.WriteTotalTimeoutConstant = 0;//100;
 CommTimeouts.WriteTotalTimeoutMultiplier = 0;//50;
 bPortReady = SetCommTimeouts(hCom, &CommTimeouts);
 // Make an overlapped structure for i.o.
 memset(&overlapped,0,sizeof(overlapped));
  overlapped.hEvent = CreateEvent(
   NULL,   // no security attributes 
   TRUE,  // auto reset event 
   FALSE,  // not signaled 
   NULL    // no name 
   );
 // Set the mask for the events you want to listen for
 fSuccess = SetCommMask
  (hCom,EV_RXCHAR | EV_RXFLAG);
 if(fSuccess)
 {
  HANDLE hArray[2];
  DWORD dwError=0;
  COMSTAT comState;
  hArray[0]=overlapped.hEvent;
  hArray[1]=hEndComPortEvent;
  ClearCommError(hCom,&dwError,&comState); 
  sprintf(szmsg,"Com port %d opened and initialised successfully",icom);
  AddEvent(szmsg);
  // If all is well, go into a loop looking for data

  // Now here the thing is that we read the data as overlapped.
  // So WaitCommEvent will return immediately - and set the
  // handle in its overlapped structure when data arrives.
  for(;;)
  {
   int iBytesRead=0;
   char szData[MAX_BUFF];
   int read_loops=0,read_loops_since_data=0;
   WaitCommEvent(hCom, &dwEvtMask,&overlapped);
   ClearCommError(hCom,&dwError,&comState); 
   switch(WaitForMultipleObjects(2,hArray,FALSE, INFINITE))
   {
    case WAIT_OBJECT_0:// input pending - this is the first of the array
                       // entries, i.e. overlapped.hEvent
     ResetEvent(hArray[0]);// reset the event to not signalled
     break;
    case WAIT_OBJECT_0+1:// this is the one to end the thread
     ResetEvent(hArray[1]);
     sprintf(szmsg,"Close request for Com port %d",icom);
     AddEvent(szmsg);
     goto end_thread;
    case WAIT_FAILED:;
   }
   if(end_com_threads)
    goto end_thread;
   for(;;)
   {
    int iBytesReadThisTime=0;
    int iBytesWas=iBytesRead;
    BOOL bRead;
    if(end_com_threads)
     goto end_thread;
    bRead= ReadFile(hCom, &szData[iBytesRead], MAX_BUFF-iBytesRead-1, &iBytesReadThisTime,&overlapped);
    iBytesRead+=iBytesReadThisTime;
    if(bRead==FALSE&&GetLastError()==ERROR_IO_PENDING)
    {
     Sleep(2);
     read_loops++;
     continue;
    }
    else
    // we have got it all now
     break;
   }
   szData[iBytesRead]='\0';
   if(szData[0]!='\0')
   {
    AddEvent("Data Received:");
    AddEvent(szData);
    SetDlgItemText(hMDlgComPortMonitor,IDC_EDIT_COM_EVENT,szData);
    nEvents++;
    sprintf(szmsg,"%d",nEvents);
    SetDlgItemText(hMDlgComPortMonitor,IDC_EDIT_COM_NEVENTS,szmsg);
   }
  }
 }
 end_thread:;
 if(hCom)
 {
  PurgeComm(hCom,PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_TXABORT);
  CloseHandle(hCom);
  hCom=0;
 }
 if(hEndComPortEvent)
  CloseHandle(hEndComPortEvent);
 hEndComPortEvent=0;
 sprintf(szmsg,"Closed Com port %d",icom);
 AddEvent(szmsg);
 com_running=0;
}