Hi,
We are using the OEM version of V-Serial Port ActiveX, when developing our software, we encountered some problems on creating multiple COM ports dymamically
(1) The CreatePort method can only create one COM port successfully; latter call of this function will fail!
(2) The first call of CreatePort return value is 0XFFFFFFFF, this value seems strange, we think it should be 0X01
(3) This function can accept port name with more than 128 characters, it is right! I have tested. It can create port name such as “COM1234”, but can not create port name such as “HelloMickle.ding”, there is no mention on this port name specification in the function description. According to our experience, the port name ranges from COM1 to COM255, if the port name is beyond this range, then there should be any restrictions on the name, isn’t it?
(4) In the first time I have ever call this driver, I try to create port name “Hello Mickle.ding”, it failed, then I try to create port name “COM1234”, it succeed, but trouble comes up. The Windows hints to find new hardware and proceed to install driver for “Eltima Virtual Serial Ports” at the root of the device manager, then I was forced THREE times to install driver evserial.sys for this new device, after this procedure, there will be THREE “Eltima Virtual Serial Ports” in the device manager. Later whatever COM port name I create via the CreatePort method, the system will hint me to install this driver (I will delete this driver before every test). So, I reboot my machine, this new hardware driver install procedure disappear, what is wrong with it?
(5) What is the correct way to create multiple COM ports? Creating one instance of IID_IVSPortAx and then multiple call of vsp->CreatePort? This is the first way; another way is creating multiple instance of IVSPortAx and then calling the CreatePort function of each instance?
(6) On exit my program; the serial port will be automatically deleted even if I never manually delete it. this is bad for me. Because in my application, there are two separate program, one for system configuration, another for data communication. The former will manage the serial port: Create/Delete/Rename and registry read/write, the latter will open these virtual serial ports for data communication as enumerated or settings in the registry. Now in my configuration application, when I close this application by close the MS-COM interface, the V-Serial Ports deleted! How to solve this issue?
Thanks & Best Regards
Notes: The OS is MS Windows XP SP3 (CHS)
Appended is the source code on operation the V-Serial Port: (Most of them copied from the VC6.0 console sample just for compilation OK)
// -----------------------------------------------------------------------------
// DESCRIPTION:
// -----------------------------------------------------------------------------
#include "VSerial.h"
// -----------------------------------------------------------------------------
// DESCRIPTION:
// -----------------------------------------------------------------------------
#include <stdio.h>
// -----------------------------------------------------------------------------
// DESCRIPTION:
// -----------------------------------------------------------------------------
#include <conio.h>
// -----------------------------------------------------------------------------
// DESCRIPTION:
// -----------------------------------------------------------------------------
#include <comdef.h>
// -----------------------------------------------------------------------------
// DESCRIPTION:
// -----------------------------------------------------------------------------
#import "VSPort.dll"
// -----------------------------------------------------------------------------
// DESCRIPTION:
// -----------------------------------------------------------------------------
#include "VSPort.h"
// -----------------------------------------------------------------------------
// DESCRIPTION:
// -----------------------------------------------------------------------------
#define IID_DEFINED
// -----------------------------------------------------------------------------
// DESCRIPTION:
// -----------------------------------------------------------------------------
#include "VSPort_i.c"
// -----------------------------------------------------------------------------
// DESCRIPTION:
// -----------------------------------------------------------------------------
CComModule _Module;
VSPortLib::IVSPortAxPtr vsp;
DWORD dwAdvise = 0;
bool IsExit = false;
/////////////////////////////////////////////////////////////////////////////
// CDriver
class CDriver :
public IDispatchImpl<_IVSPortAxEvents, &DIID__IVSPortAxEvents, &CLSID_VSPortAx>,
public CComObjectRoot
{
public:
CDriver() {}
BEGIN_COM_MAP(CDriver)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY_IID(DIID__IVSPortAxEvents, IDispatch)
END_COM_MAP()
STDMETHOD(Invoke)(DISPID dispidMember, REFIID, LCID, WORD, DISPPARAMS* pDispParams,
VARIANT*, EXCEPINFO*, UINT*)
{
switch (dispidMember)
{
case 1: // OnRxChar
{
printf ("OnRxChar %d ", pDispParams->rgvarg[0].lVal);
printf ("\n");
}
break;
case 2: // OnDTR
printf ("OnDTR %s\n", pDispParams->rgvarg->boolVal?"true":"false");
break;
case 3: // OnRTS
printf ("OnRTS %s\n", pDispParams->rgvarg->boolVal?"true":"false");
break;
case 4: // OnRing
printf ("OnRING %s\n", pDispParams->rgvarg->boolVal?"true":"false");
break;
case 5: // OnOpenClose
printf ("OnOpenClose %s\n", pDispParams->rgvarg->boolVal?"true":"false");
IsExit = pDispParams->rgvarg->boolVal?false:true;
printf ("Bye");
break;
case 6: // OnTimeouts
printf ("OnTimeouts\n"
"\tReadIntervalTimeout - %d\n"
"\tReadTotalTimeoutMultiplier - %d\n"
"\tReadTotalTimeoutConstant - %d\n"
"\tWriteTotalTimeoutMultiplier - %d\n"
"\tWriteTotalTimeoutConstant - %d\n"
,pDispParams->rgvarg[4].lVal
,pDispParams->rgvarg[3].lVal
,pDispParams->rgvarg[2].lVal
,pDispParams->rgvarg[1].lVal
,pDispParams->rgvarg[0].lVal);
break;
case 7: // OnLineControl
printf ("OnLineControl sb=%d p=%d db=%d\n"
,pDispParams->rgvarg[2].lVal
,pDispParams->rgvarg[1].lVal
,pDispParams->rgvarg[0].lVal);
break;
case 8: // OnHandflow
printf ("OnHandflow ch=%x fr=%x xon=%x xoff=%x\n"
,pDispParams->rgvarg[3].lVal
,pDispParams->rgvarg[2].lVal
,pDispParams->rgvarg[1].lVal
,pDispParams->rgvarg[0].lVal);
break;
case 9: // OnSpecialChars
printf ("OnSpecialChars EofChar=%x\n\tErrorChar=%xn\tBreakChar=%xn\tEventChar=%xn\tXOnChar=%xn\tXOffChar=%x\n"
,pDispParams->rgvarg[5].lVal
,pDispParams->rgvarg[4].lVal
,pDispParams->rgvarg[3].lVal
,pDispParams->rgvarg[2].lVal
,pDispParams->rgvarg[1].lVal
,pDispParams->rgvarg[0].lVal);
break;
case 10: // OnBaudRate
printf ("OnBaudRate %d\n", pDispParams[0].rgvarg->lVal);
break;
case 11: // OnDCD
printf ("OnDCD %s\n", pDispParams->rgvarg->boolVal?"true":"false");
break;
case 12: // OnEvent
printf ("OnEvent %x\n", pDispParams->rgvarg->lVal);
break;
}
return S_OK;
}
};
// *****************************************************************************
// Design Notes:
// -----------------------------------------------------------------------------
int InitVSerialService()
{
HRESULT dwRetVal;
// The Class Factory
LPCLASSFACTORY2 pClassFactory;
// Initialize the COM
CoInitialize( NULL );
// Initialize the ATL COM
_Module.Init( NULL, GetModuleHandle( NULL ) );
// The driver object
CComObject<CDriver> * pDriver;
// Get the class factory
dwRetVal = CoGetClassObject(
CLSID_VSPortAx,
CLSCTX_INPROC_SERVER,
NULL,
IID_IClassFactory2,
( LPVOID * )( &pClassFactory ) );
// Make sure the driver installed
if ( FAILED( dwRetVal ) )
{
return 0X00;
}
CComBSTR bstr = L"Copyright (c) ELTIMA Software";
// Create the instance of this driver
dwRetVal = pClassFactory->CreateInstanceLic(
NULL,
NULL,
IID_IVSPortAx,
bstr,
( void** )&vsp );
// Make sure this driver installed
if ( FAILED( dwRetVal ) )
{
return 0X00;
}
// Create the driver instance
CComObject<CDriver>::CreateInstance( &pDriver );
// Setup the connection point
dwRetVal = AtlAdvise( vsp, pDriver->GetUnknown(), DIID__IVSPortAxEvents, &dwAdvise );
// Make sure the driver instance is OK
if ( FAILED( dwRetVal ) )
{
return 0X00;
}
return 0X01;
}
// *****************************************************************************
// Design Notes:
// -----------------------------------------------------------------------------
void StopVSerialService()
{
// Stop the this the client with the connection point
AtlUnadvise( vsp, DIID__IVSPortAxEvents, dwAdvise );
// Release the service
vsp.Release();
// Uninitialize the COM
CoUninitialize();
}
// *****************************************************************************
// Design Notes:
// -----------------------------------------------------------------------------
int CreateVSerialPort( char * pName )
{
return vsp->CreatePort( _bstr_t( pName ) );
}
// *****************************************************************************
// Design Notes:
// -----------------------------------------------------------------------------
int DeleteVSerialPort( char * pName )
{
BOOL bRetVal;
// Attch this V-Serial Port
bRetVal = vsp->Attach( _bstr_t( pName ) );
if ( !bRetVal )
{
return 0X00;
}
return vsp->Delete();
}
// *****************************************************************************
// Design Notes:
// -----------------------------------------------------------------------------
DWORD GetVSerialCount()
{
return vsp->GetCountVirtualPort();
}
// *****************************************************************************
// Design Notes:
// -----------------------------------------------------------------------------
int GetCOMPortName( DWORD dwPortID, char * pName, DWORD iSize )
{
// Get the V-Serial Port Name
BSTR pVSerial = vsp->EnumVirtualPort( dwPortID );
// Validate the size
if ( iSize <= 0X06 )
{
return 0X00;
}
// Get the COM port name
strcpy( pName, _bstr_t( pVSerial ) );
return 0X01;
}