Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1587 lines
44 KiB

/* File: D:\WACKER\cncttapi\enum.c (Created: 23-Mar-1994)
*
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 29 $
* $Date: 7/02/02 8:27a $
*/
#define TAPI_CURRENT_VERSION 0x00010004 // cab:11/14/96 - required!
#undef MODEM_NEGOTIATED_DCE_RATE
#include <tapi.h>
#include <unimodem.h>
#include <limits.h>
#pragma hdrstop
#include <time.h>
#include <string.h>
#include <tdll\stdtyp.h>
#include <tdll\session.h>
#include <tdll\tdll.h>
#include <tdll\mc.h>
#include <tdll\assert.h>
#include <tdll\errorbox.h>
#include <tdll\cnct.h>
#include <tdll\hlptable.h>
#include <tdll\globals.h>
#include <tdll\com.h>
#include <term\res.h>
#include <tdll\htchar.h>
#include <tdll\misc.h>
#include "cncttapi.hh"
#include "cncttapi.h"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* EnumerateTapiLocations
*
* DESCRIPTION:
* Enumerates tapi locations and puts them in the given combo box.
*
* ARGUMENTS:
* hhDriver - private driver handle
* hwndCB - window handle of combo box
* hwndTB - calling card text window
*
* RETURNS:
* 0 on success, else error
*
*/
int EnumerateTapiLocations(const HHDRIVER hhDriver, const HWND hwndCB,
const HWND hwndTB)
{
DWORD i, dwSize;
LRESULT lr;
TCHAR *pach = NULL;
TCHAR ach[256];
DWORD dwPreferredCardID = (DWORD)-1;
DWORD dwCountryID = 1;
LINETRANSLATECAPS *pLnTransCap = NULL;
LINELOCATIONENTRY *pLnLocEntry = NULL;
LINECARDENTRY *pLnCardEntry = NULL;
/* --- Enumerate locations --- */
if (hhDriver == 0)
{
return -1;
}
if ((pLnTransCap = malloc(sizeof(LINETRANSLATECAPS))) == 0)
{
assert(FALSE);
return -2;
}
dwSize = 0; // used in this loop to call the dialog only once.
do {
memset(pLnTransCap, 0, sizeof(LINETRANSLATECAPS)); //* temp
pLnTransCap->dwTotalSize = sizeof(LINETRANSLATECAPS); //* temp
if ((i = TRAP(lineGetTranslateCaps(hhDriver->hLineApp, TAPI_VER,
pLnTransCap))) != 0)
{
if ( i == LINEERR_INIFILECORRUPT )
{
// Unfortunately, lineTranslateDialog does not return
// a failure code if the user clicks cancel. So if
// we fail the second time on lineGetTranslateCaps()
// don't bother to do anything else.
//
if (dwSize == 0)
{
LoadString(glblQueryDllHinst(), IDS_ER_TAPI_NEEDS_INFO,
ach, sizeof(ach) / sizeof(TCHAR));
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach,
NULL, MB_OK | MB_ICONINFORMATION, 0);
free(pLnTransCap);
pLnTransCap = NULL;
return -3;
}
if (TRAP(lineTranslateDialog(hhDriver->hLineApp, 0,
TAPI_VER, sessQueryHwnd(hhDriver->hSession), 0))
== 0)
{
dwSize = 1;
continue;
}
}
free(pLnTransCap);
pLnTransCap = NULL;
return -4;
}
}
while (i); // end of do.
if (pLnTransCap->dwNeededSize > pLnTransCap->dwTotalSize)
{
dwSize = pLnTransCap->dwNeededSize;
free(pLnTransCap);
pLnTransCap = NULL;
if ((pLnTransCap = malloc(dwSize)) == 0)
{
assert(FALSE);
return -5;
}
pLnTransCap->dwTotalSize = dwSize;
if (TRAP(lineGetTranslateCaps(hhDriver->hLineApp, TAPI_VER,
pLnTransCap)) != 0)
{
free(pLnTransCap);
pLnTransCap = NULL;
return -6;
}
}
/* --- Clear combo box --- */
if (IsWindow(hwndCB))
SendMessage(hwndCB, CB_RESETCONTENT, 0, 0);
/* --- Setup pointer to entry structure and enumerate --- */
pLnLocEntry = (LINELOCATIONENTRY *)
((LPSTR)pLnTransCap + pLnTransCap->dwLocationListOffset);
for (i = 0 ; i < pLnTransCap->dwNumLocations ; ++i)
{
if (pLnLocEntry->dwLocationNameSize == 0)
continue;
pach = (LPSTR)pLnTransCap + pLnLocEntry->dwLocationNameOffset;
if (pLnLocEntry->dwLocationNameSize)
MemCopy(ach, pach, pLnLocEntry->dwLocationNameSize);
ach[pLnLocEntry->dwLocationNameSize] = TEXT('\0');
if (IsWindow(hwndCB))
{
lr = SendMessage(hwndCB, CB_ADDSTRING, 0, (LPARAM)ach);
if (lr != CB_ERR)
{
SendMessage(hwndCB, CB_SETITEMDATA, (WPARAM)lr,
(LPARAM)pLnLocEntry->dwPermanentLocationID);
}
else
{
assert(FALSE);
}
}
// Make sure we have a default by setting the first valid entry
// we ecounter to the default. Later in the enumeration, if we
// encounter another ID as the default, we can reset it.
if (pLnLocEntry->dwPermanentLocationID ==
pLnTransCap->dwCurrentLocationID
|| dwPreferredCardID == (DWORD)-1)
{
dwPreferredCardID = pLnLocEntry->dwPreferredCardID;
if (hhDriver->dwCountryID == (DWORD)-1)
dwCountryID = pLnLocEntry->dwCountryID;
/* --- Get default location area code if not specified --- */
if (pLnLocEntry->dwCityCodeSize)
{
pach = (LPSTR)pLnTransCap +
pLnLocEntry->dwCityCodeOffset;
if (pLnLocEntry->dwCityCodeSize)
MemCopy(hhDriver->achDefaultAreaCode, pach, pLnLocEntry->dwCityCodeSize);
hhDriver->achDefaultAreaCode[pLnLocEntry->dwCityCodeSize] =
TEXT('\0');
}
}
pLnLocEntry += 1;
}
// If we don't have a country code loaded for this session, then
// use the country code of the current location.
//
if (hhDriver->dwCountryID == (DWORD)-1)
hhDriver->dwCountryID = dwCountryID;
/* --- Select the default location --- */
if (IsWindow(hwndCB))
{
// mrw,2/13/95 - changed so that selection is made by quering
// the combo box rather than saving the index which proved
// unreliable.
//
for (i = 0 ; i < pLnTransCap->dwNumLocations ; ++i)
{
lr = SendMessage(hwndCB, CB_GETITEMDATA, (WPARAM)i, 0);
if (lr != CB_ERR)
{
if ((DWORD)lr == pLnTransCap->dwCurrentLocationID)
SendMessage(hwndCB, CB_SETCURSEL, i, 0);
}
}
}
/* --- Now find the card entry --- */
if (dwPreferredCardID != (DWORD)-1)
{
pLnCardEntry = (LINECARDENTRY *)
((LPSTR)pLnTransCap + pLnTransCap->dwCardListOffset);
for (i = 0 ; i < pLnTransCap->dwNumCards ; ++i)
{
if (pLnCardEntry->dwPermanentCardID == dwPreferredCardID)
{
if (pLnCardEntry->dwCardNameSize == 0)
break;
pach = (LPSTR)pLnTransCap + pLnCardEntry->dwCardNameOffset;
if (pLnCardEntry->dwCardNameSize)
MemCopy(ach, pach, pLnCardEntry->dwCardNameSize);
ach[pLnCardEntry->dwCardNameSize] = TEXT('\0');
if (IsWindow(hwndTB))
SetWindowText(hwndTB, ach);
break;
}
pLnCardEntry += 1;
}
}
free(pLnTransCap);
pLnTransCap = NULL;
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* EnumerateCountryCodes
*
* DESCRIPTION:
* Enumerates available country codes.
*
* ARGUMENTS:
* hhDriver - private driver handle
* hwndCB - combobox to fill
*
* RETURNS:
* 0=success, else error code.
*
*/
int EnumerateCountryCodes(const HHDRIVER hhDriver, const HWND hwndCB)
{
int iIdx;
DWORD dw;
DWORD dwID;
DWORD dwSize;
TCHAR ach[100];
LPLINECOUNTRYLIST pcl = NULL;
LPLINECOUNTRYENTRY pce;
if (hhDriver == 0)
goto ERROR_EXIT;
/* --- Usual junk to make a TAPI call --- */
if ((pcl = (LPLINECOUNTRYLIST)malloc(sizeof(LINECOUNTRYLIST))) == 0)
{
assert(0);
goto ERROR_EXIT;
}
memset( pcl, 0, sizeof(LINECOUNTRYLIST) );
pcl->dwTotalSize = sizeof(LINECOUNTRYLIST);
// Get the country list all at once.
//
if (lineGetCountry(0, TAPI_VER, pcl) != 0)
{
assert(0);
goto ERROR_EXIT;
}
if (pcl->dwNeededSize > pcl->dwTotalSize)
{
dwSize = pcl->dwNeededSize;
free(pcl);
pcl = NULL;
if ((pcl = (LPLINECOUNTRYLIST)malloc(dwSize)) == 0)
{
assert(0);
goto ERROR_EXIT;
}
memset( pcl, 0, dwSize );
pcl->dwTotalSize = dwSize;
if (lineGetCountry(0, TAPI_VER, pcl) != 0)
{
assert(0);
goto ERROR_EXIT;
}
}
// Empty contents of combo box.
//
if (hwndCB)
SendMessage(hwndCB, CB_RESETCONTENT, 0, 0);
// Country List array starts here...
//
pce = (LPLINECOUNTRYENTRY)((BYTE *)pcl + pcl->dwCountryListOffset);
// Loop thru list of countries and insert into combo box.
//
for (dw = 0 ; dw < pcl->dwNumCountries ; ++dw, ++pce)
{
// Format so country name is first.
//
wsprintf(ach, "%s (%d)", (BYTE *)pcl + pce->dwCountryNameOffset,
pce->dwCountryCode);
// Add to combo box
//
iIdx = (int)SendMessage(hwndCB, CB_ADDSTRING, 0, (LPARAM)ach);
if (iIdx != CB_ERR)
{
SendMessage(hwndCB, CB_SETITEMDATA, (WPARAM)iIdx,
(LPARAM)pce->dwCountryID);
}
}
// Find the current ID and select it.
//
for (dw = 0 ; dw < pcl->dwNumCountries ; ++dw)
{
dwID = (DWORD)SendMessage(hwndCB, CB_GETITEMDATA, (WPARAM)dw, 0);
if (dwID == hhDriver->dwCountryID)
{
SendMessage(hwndCB, CB_SETCURSEL, (WPARAM)dw, 0);
break;
}
}
// Clean up and exit
//
free(pcl);
pcl = NULL;
return 0;
/*==========*/
ERROR_EXIT:
/*==========*/
if (pcl)
{
free(pcl);
pcl = NULL;
}
return -1;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* EnumerateAreaCodes
*
* DESCRIPTION:
* Lists last 10 area codes used.
*
* ARGUMENTS:
* hhDriver - private driver handle
* hwndCB - combobox to fill
*
* RETURNS:
* 0=success, else error.
*
*/
int EnumerateAreaCodes(const HHDRIVER hhDriver, const HWND hwndCB)
{
if (hhDriver == 0)
{
assert(FALSE);
return -1;
}
if (hhDriver->achAreaCode[0] == TEXT('\0'))
{
StrCharCopyN(hhDriver->achAreaCode, hhDriver->achDefaultAreaCode,
sizeof(hhDriver->achAreaCode) / sizeof(TCHAR));
}
SetWindowText(hwndCB, hhDriver->achAreaCode);
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* EnumerateLines
*
* DESCRIPTION:
* Enumerates available lines. If hwndCB is non-zero, loads names.
*
* ARGUMENTS:
* hhDriver - private driver handle
* hwndCB - combo box
*
* RETURNS:
* 0=success, -1=error
*
*/
int EnumerateLines(const HHDRIVER hhDriver, const HWND hwndCB)
{
int fHotPhone;
int fRet;
DWORD i;
DWORD dwSize;
DWORD dwAPIVersion;
LINEEXTENSIONID LnExtId;
LPLINEDEVCAPS pLnDevCaps = NULL;
PSTLINEIDS pstLineIds = NULL;
TCHAR * pachLine;
TCHAR achLine[256];
TCHAR ach[256];
LRESULT lr;
if (hhDriver == 0)
{
return -1;
}
// This call knows to free the itemdata associated with this combo.
//
mscResetComboBox(hwndCB);
/* --- Initialize stuff --- */
pLnDevCaps = 0;
hhDriver->dwLine = (DWORD)-1;
hhDriver->fMatchedPermanentLineID = FALSE;
/* --- Enumerate the devices --- */
for (i = 0 ; i < hhDriver->dwLineCnt ; ++i)
{
if (lineNegotiateAPIVersion(hhDriver->hLineApp, i, TAPI_VER,
TAPI_VER, &dwAPIVersion, &LnExtId) != 0)
{
// Could be a 1.3 driver, we continue.
continue;
}
fRet = CheckHotPhone(hhDriver, i, &fHotPhone);
if (fRet < 0)
{
assert(0);
continue;
}
else if (fRet == 0 && fHotPhone)
{
continue;
}
if ((pLnDevCaps = malloc(sizeof(LINEDEVCAPS))) == 0)
{
assert(0);
continue;
}
// TAPI says its too small if we just allocate sizeof(LINEDEVCAPS)
//
memset( pLnDevCaps, 0, sizeof(LINEDEVCAPS) );
pLnDevCaps->dwTotalSize = sizeof(LINEDEVCAPS);
/* --- Make call to find out how much we need for this device --- */
if (TRAP(lineGetDevCaps(hhDriver->hLineApp, i, dwAPIVersion, 0,
pLnDevCaps)) != 0)
{
assert(0);
continue;
}
/* --- Find out how big structure really needs to be --- */
if (pLnDevCaps->dwNeededSize > pLnDevCaps->dwTotalSize)
{
dwSize = pLnDevCaps->dwNeededSize;
free(pLnDevCaps);
pLnDevCaps = NULL;
pLnDevCaps = malloc(dwSize);
if (pLnDevCaps == 0)
{
assert(FALSE);
continue;
}
pLnDevCaps->dwTotalSize = dwSize;
/* --- Try again --- */
if (lineGetDevCaps(hhDriver->hLineApp, i, dwAPIVersion, 0,
pLnDevCaps) != 0)
{
assert(FALSE);
free(pLnDevCaps);
pLnDevCaps = NULL;
continue;
}
}
/* --- Check the information we're interested in --- */
//mpt:03-19-98 added a MaxRate check to eliminate the MS VPN adapter
// from the list of available devices.
//mpt 06-23-98 added a MaxNumActiveCalls check to eliminate the
// H323 and Line0 devices from showing up in our list
if (pLnDevCaps->dwLineNameSize == 0 ||
(pLnDevCaps->dwMaxRate == 0 || pLnDevCaps->dwMaxRate >= 1048576) ||
(pLnDevCaps->dwMaxNumActiveCalls > 1 && pLnDevCaps->dwMaxNumActiveCalls != 32768) )
{
free(pLnDevCaps);
pLnDevCaps = NULL;
continue;
}
pachLine = (BYTE *)pLnDevCaps + pLnDevCaps->dwLineNameOffset;
if (pLnDevCaps->dwLineNameSize)
MemCopy(achLine, pachLine, pLnDevCaps->dwLineNameSize);
achLine[pLnDevCaps->dwLineNameSize] = TEXT('\0');
/* --- Put name in combo box if given one --- */
if (IsWindow(hwndCB))
{
// I need to associate two pieces of data with each
// item (permanent line id and relative line id). Both
// are double words and CB_SETITEMDATA only stores a
// a double word. So malloc a structure to hold both
// ids and store a pointer to the memory in the combobox.
// Call the mscResetComboBox() defined in the file to reset
// the contents of the combobox and free the associated
// memory. mscResetComboBox() is also called in the dialog
// destroy.
//
pstLineIds = malloc(sizeof(*pstLineIds));
if (pstLineIds == 0)
{
assert(FALSE);
free(pLnDevCaps);
pLnDevCaps = NULL;
continue;
}
pstLineIds->dwLineId = i;
pstLineIds->dwPermanentLineId = pLnDevCaps->dwPermanentLineID;
// Add the name to the combobox. Since names are sorted,
// the index of the item is returned from SendMessage and
// stored in lr. Save this index for use below.
//
lr = SendMessage(hwndCB, CB_ADDSTRING, 0, (LPARAM)achLine);
if (lr != CB_ERR)
{
// Note: lr was set above CB_ADDSTRING call.
//
if (SendMessage(hwndCB, CB_SETITEMDATA, (WPARAM)lr,
(LPARAM)pstLineIds) == CB_ERR)
{
assert(FALSE);
free(pstLineIds);
free(pLnDevCaps);
pstLineIds = NULL;
pLnDevCaps = NULL;
continue;
}
}
else
{
free(pstLineIds);
free(pLnDevCaps);
pstLineIds = NULL;
pLnDevCaps = NULL;
continue;
}
}
//
// Only set the Modem as a match if the line device's
// dwPermanentLineID is the same as the drivers dwPermanentLineId.
//
// NOTE: We will set the default in the property page if a match
// is not found in this function. REV: 11/5/2001
//
if (pLnDevCaps->dwPermanentLineID == hhDriver->dwPermanentLineId) //||
//hhDriver->dwLine == (DWORD)-1)
{
hhDriver->dwLine = i;
hhDriver->dwAPIVersion = dwAPIVersion;
StrCharCopyN(hhDriver->achLineName, achLine,
sizeof(hhDriver->achLineName) / sizeof(TCHAR));
if (IsWindow(hwndCB))
{
// Note: lr was set above CB_ADDSTRING call.
//
SendMessage(hwndCB, CB_SETCURSEL, (WPARAM)lr, 0);
}
if (pLnDevCaps->dwPermanentLineID == hhDriver->dwPermanentLineId)
{
hhDriver->fMatchedPermanentLineID = TRUE;
}
}
/* --- Free allocated space --- */
free(pLnDevCaps);
pLnDevCaps = NULL;
}
// Load the direct to com port stuff first
if (LoadString(glblQueryDllHinst(), IDS_CNCT_DIRECTCOM, achLine,
sizeof(achLine) / sizeof(TCHAR)) == 0)
{
assert(FALSE);
// The loading of the string has failed from the resource, so
// add the non-localized string here (I don't believe this string
// is ever translated). REV 8/13/99
//
StrCharCopyN(achLine, TEXT("Direct to Com%d"), sizeof(achLine) / sizeof(TCHAR));
//return -1;
}
// Another nasty bug, DIRECT_COM4 is defined as 0x5A2175d4, which
// makes this one heck of a loop. I think we only want to do this
// four times (as opposed to 1.5 billion). - cab:11/14/96
//
// for (i = 0 ; i < DIRECT_COM4 ; ++i)
//
for( i = 0; i < 4; i++ )
{
wsprintf(ach, achLine, i+1);
if (IsWindow(hwndCB))
{
lr = SendMessage(hwndCB, CB_INSERTSTRING, (WPARAM)-1,
(LPARAM)ach);
pstLineIds = malloc(sizeof(*pstLineIds));
if (pstLineIds == 0)
{
assert(FALSE);
continue;
}
// We don't use a line id here, only a permanent line id.
//
pstLineIds->dwPermanentLineId = DIRECT_COM1+i;
// Note: lr was set above CB_INSERTSTRING call.
//
if (SendMessage(hwndCB, CB_SETITEMDATA, (WPARAM)lr,
(LPARAM)pstLineIds) == CB_ERR)
{
assert(FALSE);
free(pstLineIds);
pstLineIds = NULL;
continue;
}
}
// If this is what was saved in the data file, then set
// the line ids.
//
// Only set the serial port as a match if the drivers
// dwPermanentLineId is equal to DIRECT_COM1+i.
//
// Since dwPermanentLineId is unique on Win9.x so we don't need to
// set the driver's name to the serial port's name. REV: 4/15/2002
//
// NOTE: We will set the default in the property page if a match
// is not found in this function. REV: 11/5/2001
//
if ((DIRECT_COM1+i) == hhDriver->dwPermanentLineId) //||
//hhDriver->dwLine == (DWORD)-1)
{
hhDriver->dwLine = 0;
StrCharCopyN(hhDriver->achLineName, ach,
sizeof(hhDriver->achLineName) / sizeof(TCHAR));
if (IsWindow(hwndCB))
{
// Note: lr was set above CB_ADDSTRING call.
//
SendMessage(hwndCB, CB_SETCURSEL, (WPARAM)lr, 0);
}
hhDriver->fMatchedPermanentLineID = TRUE;
}
}
#if defined(INCL_WINSOCK)
// This is causing a syntax error, so I am fixing it. Why nobody
// found this sooner, I have no idea. - cab:11/14/96
//
//if (LoadString(glblQueryDllHinst(), IDS_WINSOCK_SETTINGS_STR, ach,
// sizeof(ach));
//
if (LoadString(glblQueryDllHinst(), IDS_WINSOCK_SETTINGS_STR, ach,
sizeof(ach) / sizeof(TCHAR)) == 0)
{
assert(FALSE);
// The loading of the string has failed from the resource, so
// add the non-localized string here (I don't believe this string
// is ever translated). REV 8/13/99
//
StrCharCopyN(ach, TEXT("TCP/IP (Winsock)"), sizeof(ach) / sizeof(TCHAR));
//return -1;
}
if (IsWindow(hwndCB))
{
lr = SendMessage(hwndCB, CB_INSERTSTRING, (WPARAM)-1,
(LPARAM)ach);
pstLineIds = malloc(sizeof(*pstLineIds));
if (pstLineIds == 0)
{
assert(FALSE);
free(pstLineIds);
pstLineIds = NULL;
return 0;
}
// We don't use a line id here, only a permanent line id.
//
pstLineIds->dwPermanentLineId = DIRECT_COMWINSOCK;
// Note: lr was set above CB_INSERTSTRING call.
//
if (SendMessage(hwndCB, CB_SETITEMDATA, (WPARAM)lr,
(LPARAM)pstLineIds) == CB_ERR)
{
assert(FALSE);
}
}
// Check to see if the current connection is winsock. - cab:11/15/96
//
// Only set the Winsock(TCP/IP) as a match if the drivers
// dwPermanentLineId is DIRECT_COMWSOCK.
//
// NOTE: We will set the default in the property page if a match
// is not found in this function. REV: 11/5/2001
//
if (DIRECT_COMWINSOCK == hhDriver->dwPermanentLineId) //||
//hhDriver->dwLine == (DWORD)-1)
{
hhDriver->dwLine = 0;
StrCharCopyN(hhDriver->achLineName, ach, sizeof(hhDriver->achLineName) / sizeof(TCHAR));
if (IsWindow(hwndCB))
{
// Note: lr was set above CB_INSERTSTRING call.
//
SendMessage(hwndCB, CB_SETCURSEL, (WPARAM)lr, 0);
}
if (DIRECT_COMWINSOCK == hhDriver->dwPermanentLineId)
{
hhDriver->fMatchedPermanentLineID = TRUE;
}
// Don't free the pstLineIds since it will be freed in the
// mscResetComboBox() function. We were previously freeing the
// memory twice causing a crash with the MSVC 6.0 runtime DLL's.
// I'm suprised this did not present itself earlier. REV 8/17/98
//
//free(pstLineIds);
}
#endif
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* EnumerateLinesNT
*
* DESCRIPTION:
* Enumerates available lines. This function is similar to EnumerateLines, but
* we use different methods to enumerate the ports under Windows NT.
*
* ARGUMENTS:
* hhDriver - private driver handle
* hwndCB - combo box
*
* RETURNS:
* 0=success, -1=error
*
*/
int EnumerateLinesNT(const HHDRIVER hhDriver, const HWND hwndCB)
{
int fHotPhone;
int fRet;
DWORD i;
DWORD dwSize;
DWORD dwAPIVersion;
LINEEXTENSIONID LnExtId;
LPLINEDEVCAPS pLnDevCaps = NULL;
PSTLINEIDS pstLineIds = NULL;
TCHAR * pachLine;
TCHAR achLine[256];
TCHAR ach[256];
TCHAR ab[256];
LRESULT lr;
LRESULT nNumberItemInList = 0;
HKEY hKey;
LONG retval;
DWORD dwType;
DWORD dwSizeBuf;
DWORD iMaxComPortEnum = SHRT_MAX; // Make sure we have a
// limit on the number of
// ports we enumerate so
// that we don't get into
// an endless loop. SHRT_MAX
// is the scroll bar maximum
// used in the combo box
// dropdown list.
// REV: 11/14/2000.
if (hhDriver == 0)
{
return -1;
}
// This call knows to free the itemdata associated with this combo.
//
mscResetComboBox(hwndCB);
/* --- Initialize stuff --- */
pLnDevCaps = 0;
if ( StrCharCmp(hhDriver->achLineName, "") == 0 )
{
hhDriver->dwLine = (DWORD)-1;
}
else
{
hhDriver->dwLine = 0;
}
hhDriver->fMatchedPermanentLineID = FALSE;
/* --- Enumerate the devices --- */
for (i = 0 ; i < hhDriver->dwLineCnt ; ++i)
{
if (retval = lineNegotiateAPIVersion(hhDriver->hLineApp, i, TAPI_VER,
TAPI_VER, &dwAPIVersion, &LnExtId) != 0)
{
// Could be a 1.3 driver, we continue.
continue;
}
fRet = CheckHotPhone(hhDriver, i, &fHotPhone);
if (fRet < 0)
{
assert(0);
continue;
}
else if (fRet == 0 && fHotPhone)
{
continue;
}
if ((pLnDevCaps = malloc(sizeof(LINEDEVCAPS))) == 0)
{
assert(0);
continue;
}
if (hhDriver->hLineApp == 0)
{
assert(FALSE);
continue;
}
// TAPI says its too small if we just allocate sizeof(LINEDEVCAPS)
//
pLnDevCaps->dwTotalSize = sizeof(LINEDEVCAPS);
/* --- Make call to find out how much we need for this device --- */
if (TRAP(lineGetDevCaps(hhDriver->hLineApp, i, dwAPIVersion, 0,
pLnDevCaps)) != 0)
{
assert(0);
continue;
}
/* --- Find out how big structure really needs to be --- */
if (pLnDevCaps->dwNeededSize > pLnDevCaps->dwTotalSize)
{
dwSize = pLnDevCaps->dwNeededSize;
free(pLnDevCaps);
pLnDevCaps = NULL;
pLnDevCaps = malloc(dwSize);
if (pLnDevCaps == 0)
{
assert(FALSE);
continue;
}
pLnDevCaps->dwTotalSize = dwSize;
/* --- Try again --- */
if (lineGetDevCaps(hhDriver->hLineApp, i, dwAPIVersion, 0,
pLnDevCaps) != 0)
{
assert(FALSE);
continue;
}
}
/* --- Check the information we're interested in --- */
//mpt:03-19-98 added a MaxRate check to eliminate the MS VPN adapter
// from the list of available devices.
//mpt 06-23-98 added a MaxNumActiveCalls check to eliminate the
// H323 and Line0 devices from showing up in our list
if (pLnDevCaps->dwLineNameSize == 0 ||
(pLnDevCaps->dwMaxRate == 0 || pLnDevCaps->dwMaxRate >= 1048576) ||
(pLnDevCaps->dwMaxNumActiveCalls > 1 && pLnDevCaps->dwMaxNumActiveCalls != 32768) )
{
free(pLnDevCaps);
pLnDevCaps = NULL;
continue;
}
pachLine = (BYTE *)pLnDevCaps + pLnDevCaps->dwLineNameOffset;
if (pLnDevCaps->dwLineNameSize)
MemCopy(achLine, pachLine, pLnDevCaps->dwLineNameSize);
achLine[pLnDevCaps->dwLineNameSize] = TEXT('\0');
/* --- Put name in combo box if given one --- */
if (IsWindow(hwndCB))
{
// I need to associate two pieces of data with each
// item (permanent line id and relative line id). Both
// are double words and CB_SETITEMDATA only stores a
// a double word. So malloc a structure to hold both
// ids and store a pointer to the memory in the combobox.
// Call the mscResetComboBox() defined in the file to reset
// the contents of the combobox and free the associated
// memory. mscResetComboBox() is also called in the dialog
// destroy.
//
pstLineIds = malloc(sizeof(*pstLineIds));
if (pstLineIds == 0)
{
assert(FALSE);
free(pLnDevCaps);
pLnDevCaps = NULL;
continue;
}
pstLineIds->dwLineId = i;
pstLineIds->dwPermanentLineId = pLnDevCaps->dwPermanentLineID;
// Add the name to the combobox. Since names are sorted,
// the index of the item is returned from SendMessage and
// stored in lr. Save this index for use below.
//
lr = SendMessage(hwndCB, CB_ADDSTRING, 0, (LPARAM)achLine);
if (lr != CB_ERR && lr != CB_ERRSPACE)
{
nNumberItemInList++;
// Note: lr was set above CB_ADDSTRING call.
//
if (SendMessage(hwndCB, CB_SETITEMDATA, (WPARAM)lr,
(LPARAM)pstLineIds) == CB_ERR)
{
assert(FALSE);
free(pstLineIds);
free(pLnDevCaps);
pstLineIds = NULL;
pLnDevCaps = NULL;
continue;
}
}
else
{
free(pstLineIds);
free(pLnDevCaps);
pstLineIds = NULL;
pLnDevCaps = NULL;
continue;
}
}
//
// Only set the Modem as a match if the line device's
// dwPermanentLineID is the same as the drivers dwPermanentLineId.
//
// NOTE: We will set the default in the property page if a match
// is not found in this function. REV: 11/5/2001
//
if (pLnDevCaps->dwPermanentLineID == hhDriver->dwPermanentLineId) //||
//hhDriver->dwLine == (DWORD)-1)
{
hhDriver->dwLine = i;
hhDriver->dwAPIVersion = dwAPIVersion;
StrCharCopyN(hhDriver->achLineName, achLine,
sizeof(hhDriver->achLineName) / sizeof(TCHAR));
if (IsWindow(hwndCB))
{
// Note: lr was set above CB_ADDSTRING call.
//
SendMessage(hwndCB, CB_SETCURSEL, (WPARAM)lr, 0);
}
if (pLnDevCaps->dwPermanentLineID == hhDriver->dwPermanentLineId)
hhDriver->fMatchedPermanentLineID = TRUE;
}
/* --- Free allocated space --- */
free(pLnDevCaps);
pLnDevCaps = NULL;
}
// Load the direct to com port stuff first
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("hardware\\devicemap\\serialcomm"),
0, KEY_READ, &hKey) != ERROR_SUCCESS)
{
assert(FALSE);
// We used to return FALSE here which would mean the TCP/IP
// would not be in the enumerated connection methods (modem,
// COM port or Winsock) in the "Connect Using:" dropdown
// combobox in the properties for the entries. Since the
// return value was never checked, we can just continue on
// to finish the enumerations for the combobox. Now we just
// set the number of COM ports to enumerate to 0. REV 8/13/99.
//
//return FALSE;
iMaxComPortEnum = 0;
}
// Make sure we don't enumerate mar than the maximum number of ports
// minus the number of TAPI devices. If we are including WINSOCK, then
// subtract 1 for the TCP/IP (WinSock) combobox item.
#if defined(INCL_WINSOCK)
iMaxComPortEnum = iMaxComPortEnum - (DWORD)nNumberItemInList - 1;
#else
iMaxComPortEnum = iMaxComPortEnum - (DWORD)nNumberItemInList;
#endif
// We now use a variable for the number of drives to enumerate.
// We have set the number of COM ports to enumerate in a variable
// above (iMaxComPortEnum == 0 if no COM ports installed). REV 8/13/99.
//
for (i = 0 ; i < iMaxComPortEnum ; ++i)
{
dwSizeBuf = sizeof(ab) / sizeof(TCHAR);
dwSize = sizeof(ach) / sizeof(TCHAR);
// Enumerate devices under our serialcomm key
//
if (RegEnumValue(hKey, i, ach, &dwSize, 0, &dwType, ab,
&dwSizeBuf) != ERROR_SUCCESS)
{
break;
}
// Ignore anything that isn't a string.
//
if (dwType != REG_SZ)
continue;
if (IsWindow(hwndCB))
{
lr = SendMessage(hwndCB, CB_INSERTSTRING, (WPARAM)-1,
(LPARAM)ab);
//
// See if an error occured due to out of memory. If so,
// then don't enumerate any more ports. REV: 11/15/2000
//
if( lr == CB_ERRSPACE || lr == CB_ERR )
{
break;
}
nNumberItemInList++;
pstLineIds = malloc(sizeof(*pstLineIds));
if (pstLineIds == 0)
{
assert(FALSE);
continue;
}
// We don't use a line id here, only a permanent line id.
//
pstLineIds->dwPermanentLineId = DIRECT_COM_DEVICE;
// Note: lr was set above CB_INSERTSTRING call.
//
if (SendMessage(hwndCB, CB_SETITEMDATA, (WPARAM)lr,
(LPARAM)pstLineIds) == CB_ERR)
{
assert(FALSE);
free(pstLineIds);
pstLineIds = NULL;
continue;
}
}
//
// Only set the serial port as a match if the drivers
// dwPermanentLineId is equal to DIRECT_COM_DEVICE or
// in the range from DIRECT_COM1 to DIRECT_COM4 and the
// driver's name is the same as the serial port's name.
//
// NOTE: We will set the default in the property page if a match
// is not found in this function. REV: 11/5/2001
//
if ( hhDriver->fMatchedPermanentLineID == FALSE &&
StrCharCmp(hhDriver->achComDeviceName, ab) == 0 &&
( //hhDriver->dwPermanentLineId == (DWORD)-1 ||
IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) ||
hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE ) )
{
hhDriver->dwLine = 0;
StrCharCopyN(hhDriver->achLineName, ab,
sizeof(hhDriver->achLineName) / sizeof(TCHAR));
if (IsWindow(hwndCB))
{
// Note: lr was set above CB_ADDSTRING call.
//
SendMessage(hwndCB, CB_SETCURSEL, (WPARAM)lr, 0);
}
hhDriver->fMatchedPermanentLineID = TRUE;
}
}
#if defined(INCL_WINSOCK)
// This is causing a syntax error, so I am fixing it. Why nobody
// found this sooner, I have no idea. - cab:11/14/96
//
//if (LoadString(glblQueryDllHinst(), IDS_WINSOCK_SETTINGS_STR, ach,
// sizeof(ach));
//
if (LoadString(glblQueryDllHinst(), IDS_WINSOCK_SETTINGS_STR, ach,
sizeof(ach) / sizeof(TCHAR)) == 0)
{
assert(FALSE);
// The loading of the string has failed from the resource, so
// add the non-localized string here (I don't believe this string
// is ever translated). REV 8/13/99
//
StrCharCopyN(ach, TEXT("TCP/IP (Winsock)"), sizeof(ach) / sizeof(TCHAR));
//return -1;
}
if (IsWindow(hwndCB))
{
lr = SendMessage(hwndCB, CB_INSERTSTRING, (WPARAM)-1,
(LPARAM)ach);
//
// See if an error occured due to out of memory. If so,
// then delete the last COM port added so there is room
// for the TCP/IP (Winsock) item. REV: 11/15/2000
//
if( lr == CB_ERRSPACE )
{
lr = SendMessage(hwndCB, CB_DELETESTRING, (WPARAM)nNumberItemInList - 1,
(LPARAM)0);
lr = SendMessage(hwndCB, CB_INSERTSTRING, (WPARAM)-1,
(LPARAM)ach);
}
if (lr != CB_ERR && lr != CB_ERRSPACE)
{
pstLineIds = malloc(sizeof(*pstLineIds));
if (pstLineIds == 0)
{
assert(FALSE);
free(pstLineIds);
pstLineIds = NULL;
return 0;
}
// We don't use a line id here, only a permanent line id.
//
pstLineIds->dwPermanentLineId = DIRECT_COMWINSOCK;
// Note: lr was set above CB_INSERTSTRING call.
//
if (SendMessage(hwndCB, CB_SETITEMDATA, (WPARAM)lr,
(LPARAM)pstLineIds) == CB_ERR)
{
assert(FALSE);
}
}
}
// Check to see if the current connection is winsock. - cab:11/15/96
//
// Only set the Winsock(TCP/IP) as a match if the drivers
// dwPermanentLineId is DIRECT_COMWSOCK.
//
// NOTE: We will set the default in the property page if a match
// is not found in this function. REV: 11/5/2001
//
if (DIRECT_COMWINSOCK == hhDriver->dwPermanentLineId) //||
//hhDriver->dwLine == (DWORD)-1)
{
hhDriver->dwLine = 0;
StrCharCopyN(hhDriver->achLineName, ach,
sizeof(hhDriver->achLineName) / sizeof(TCHAR));
if (IsWindow(hwndCB))
{
// Note: lr was set above CB_INSERTSTRING call.
//
SendMessage(hwndCB, CB_SETCURSEL, (WPARAM)lr, 0);
}
if (DIRECT_COMWINSOCK == hhDriver->dwPermanentLineId)
{
hhDriver->fMatchedPermanentLineID = TRUE;
}
// Don't free the pstLineIds since it will be freed in the
// mscResetComboBox() function. We were previously freeing the
// memory twice causing a crash with the MSVC 6.0 runtime DLL's.
// I'm suprised this did not present itself earlier. REV 8/17/98
//
//free(pstLineIds);
}
#endif
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* DoLineGetCountry
*
* DESCRIPTION:
* Wrapper indended to query for a single country. The caller must
* free the pcl when finished.
*
* ARGUMENTS:
* dwCountryID - ID of country
* dwApiVersion - Api version (no longer used)
* ppcl - pointer to a LPLINECOUNTRYLIST
*
* RETURNS:
* 0=OK
*
*/
int DoLineGetCountry(const DWORD dwCountryID, const DWORD dwAPIVersion,
LPLINECOUNTRYLIST *ppcl)
{
DWORD dwSize;
LPLINECOUNTRYLIST pcl = NULL;
if ((pcl = malloc(sizeof(LINECOUNTRYLIST))) == 0)
{
assert(FALSE);
return -1;
}
pcl->dwTotalSize = sizeof(LINECOUNTRYLIST);
if (lineGetCountry(dwCountryID, TAPI_VER, pcl) != 0)
{
assert(FALSE);
free(pcl);
pcl = NULL;
return -1;
}
if (pcl->dwNeededSize > pcl->dwTotalSize)
{
dwSize = pcl->dwNeededSize;
free(pcl);
pcl = NULL;
if ((pcl = malloc(dwSize)) == 0)
{
assert(FALSE);
return -1;
}
pcl->dwTotalSize = dwSize;
if (lineGetCountry(dwCountryID, TAPI_VER, pcl) != 0)
{
assert(FALSE);
free(pcl);
pcl = NULL;
return -1;
}
}
*ppcl = pcl;
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* cnctdrvGetComSettingsString
*
* DESCRIPTION:
* Retrieves a string formatted for display on the status line.
*
* ARGUMENTS:
* hhDriver - private driver handle
* pachStr - buffer to store string
* cb - size of buffer
*
* RETURNS:
* 0=OK,else error
*
*/
int cnctdrvGetComSettingsString(const HHDRIVER hhDriver, LPTSTR pachStr,
const size_t cb)
{
static CHAR acParity[] = "NOEMS"; // see com.h
static CHAR *pachStop[] = {"1", "1.5", "2"};
HCOM hCom;
TCHAR ach[100];
LPVARSTRING pvs = NULL;
int fAutoDetect = FALSE;
long lBaud = 0;
int iDataBits = 8;
int iParity = 0;
int iStopBits = 0;
#if defined(MODEM_NEGOTIATED_DCE_RATE) // TODO:REV 5/29/2002
long lNegBaud = 0;
#endif // defined(MODEM_NEGOTIATED_DCE_RATE)
// Check the parameters
//
if (hhDriver == 0)
{
assert(0);
return -1;
}
if (pachStr == 0 || cb == 0)
{
assert(0);
return -2;
}
ach[0] = TEXT('\0');
if ((hCom = sessQueryComHdl(hhDriver->hSession)) == 0)
return -7;
// //MPT:11-01-98 Microsoft made these changes to fix a bug relating
// // to working with multiple connection devices.
// if (ComGetAutoDetect(hCom, &fAutoDetect) == COM_OK && fAutoDetect)
// {
// LoadString(glblQueryDllHinst(), IDS_STATUSBR_AUTODETECT, ach,
// sizeof(ach) / sizeof(TCHAR));
// }
#if defined(INCL_WINSOCK)
/*else*/ if (hhDriver->dwPermanentLineId == DIRECT_COMWINSOCK)
{
// Baud rate, data bits, parity, stop bits don't make sense in
// TCP/IP. Load an alternate string.
//
LoadString(glblQueryDllHinst(), IDS_STATUSBR_COM_TCPIP, ach,
sizeof(ach) / sizeof(TCHAR));
}
#endif
else if (IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4)
|| hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE)
{
ComGetBaud(hCom, &lBaud);
ComGetDataBits(hCom, &iDataBits);
ComGetParity(hCom, &iParity);
ComGetStopBits(hCom, &iStopBits);
wsprintf(ach, "%ld %d-%c-%s", lBaud, iDataBits,
acParity[iParity], pachStop[iStopBits]);
}
// Usual lines of code for a TAPI call
//
else if (hhDriver->dwLine != (DWORD)-1)
{
int retValue = 0;
iDataBits = 8;
iParity = NOPARITY;
iStopBits = ONESTOPBIT;
retValue = cncttapiGetLineConfig( hhDriver->dwLine, (VOID **) &pvs);
if (retValue != 0)
{
return retValue;
}
else
{
// The structure of the DevConfig block is as follows
//
// VARSTRING
// UMDEVCFGHDR
// COMMCONFIG
// MODEMSETTINGS
//
// The UMDEVCFG structure used below is defined in the
// UNIMODEM.H provided in the platform SDK (in the nih
// directory for HTPE). REV: 12/01/2000
//
PUMDEVCFG pDevCfg = NULL;
pDevCfg = (UMDEVCFG *)((BYTE *)pvs + pvs->dwStringOffset);
// commconfig struct has a DCB structure we dereference for the
// com settings.
//
lBaud = pDevCfg->commconfig.dcb.BaudRate;
iDataBits = pDevCfg->commconfig.dcb.ByteSize;
iParity = pDevCfg->commconfig.dcb.Parity;
iStopBits = pDevCfg->commconfig.dcb.StopBits;
#if defined(MODEM_NEGOTIATED_DCE_RATE) // TODO:REV 5/29/2002
//
// See if this is a modem connection and connected, then get
// the negotiated baud rate instead of the default max rate
// the modem is set up for. -- REV: 5/29/2002
//
if (pDevCfg->commconfig.dwProviderSubType == PST_MODEM)
{
MODEMSETTINGS * pModemSettings = (MODEMSETTINGS *)pDevCfg->commconfig.wcProviderData;
if (pModemSettings)
{
lNegBaud = pModemSettings->dwNegotiatedDCERate;
}
}
#endif // defined(MODEM_NEGOTIATED_DCE_RATE)
}
#if defined(MODEM_NEGOTIATED_DCE_RATE) // TODO:REV 5/29/2002
if (lNegBaud > 0)
{
wsprintf(ach, "%ld %d-%c-%s", lNegBaud, iDataBits,
acParity[iParity], pachStop[iStopBits]);
}
else
{
wsprintf(ach, "%ld %d-%c-%s", lBaud, iDataBits,
acParity[iParity], pachStop[iStopBits]);
}
#else // defined(MODEM_NEGOTIATED_DCE_RATE)
wsprintf(ach, "%ld %d-%c-%s", lBaud, iDataBits,
acParity[iParity], pachStop[iStopBits]);
#endif //defined(MODEM_NEGOTIATED_DCE_RATE)
}
// Moved this test to last so any change from 8N1 will not show auto-detect jkh 9/9/98
if (iDataBits == 8 && iParity == NOPARITY && iStopBits == ONESTOPBIT &&
ComGetAutoDetect(hCom, &fAutoDetect) == COM_OK && fAutoDetect)
{
LoadString(glblQueryDllHinst(), IDS_STATUSBR_AUTODETECT, ach,
sizeof(ach) / sizeof(TCHAR));
}
StrCharCopyN(pachStr, ach, cb);
pachStr[cb-1] = TEXT('\0');
free(pvs);
pvs = NULL;
return 0;
}
#if !defined(NDEBUG)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* tapiTrap
*
* DESCRIPTION:
* Trap TAPI error conditions.
*
* ARGUMENTS:
* dw - result code from tapi
* file - file where error occured
* line - line where error occured
*
* RETURNS:
* dw
*
*/
DWORD tapiTrap(const DWORD dw, const TCHAR *file, const int line)
{
char ach[256];
if (dw != 0)
{
wsprintf(ach, "TAPI returned %x on line %d of file %s", dw, line, file);
MessageBox(NULL, ach, "TAPI Trap", MB_OK | MB_ICONINFORMATION);
}
return dw;
}
#endif