home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / k95source / settapi.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  65KB  |  2,350 lines

  1. /* C K N T A P  --  Kermit Telephony interface for MS Win32 TAPI systems */
  2.  
  3. /*
  4.   Author: Jeffrey Altman (jaltman@columbia.edu),
  5.   Columbia University Academic Information Systems, New York City.
  6.  
  7.   Copyright (C) 1985, 1997, Trustees of Columbia University in the City of New
  8.   York.
  9. */
  10.  
  11. /*
  12.  * =============================#includes=====================================
  13.  */
  14.  
  15. #include "ckcdeb.h"             /* Typedefs, debug formats, etc */
  16. #include "ckcker.h"             /* Kermit definitions */
  17. #include "ckucmd.h"
  18. #include "ckuusr.h"
  19. #include "ckowin.h"
  20. #include <string.h>
  21.  
  22. #include <windows.h>
  23. #define TAPI_CURRENT_VERSION 0x00010004
  24. #include <tapi.h>
  25. #include <mcx.h>
  26. /* all functions in this module return TRUE to indicate success */
  27. /* or FALSE to indicate failure */
  28. #ifndef ZIL_VERSION
  29. #include "ckntap.h"             /* Kermit Telephony */
  30. #else /* ZINC */
  31. #include "ktapi.h"
  32. #endif
  33. #include "cknwin.h"
  34.  
  35. #undef debug
  36. #define debug(a,b,c,d)
  37.  
  38. #ifdef CK_TAPI
  39. _PROTOTYP( char * cktapiErrorString, (DWORD));
  40. _PROTOTYP( void ReloadTapiLocations, (void));
  41.  
  42. struct keytab * tapilinetab=NULL, * _tapilinetab=NULL, * tapilocationtab=NULL ;
  43. int ntapiline=0, ntapilocation=0 ;
  44.  
  45. HINSTANCE hLib = NULL ;
  46. HINSTANCE hInstance=NULL;
  47. HWND hwndConsole=(HWND)0 ;
  48. extern char * termessage ;
  49. /*  Failure codes from ckudia.c */
  50. extern int fail_code;
  51.  
  52. #define F_TIME        1        /* timeout */
  53. #define F_INT        2        /* interrupt */
  54. #define F_MODEM        3        /* modem-detected failure */
  55. #define F_MINIT        4        /* cannot initialize modem */
  56.  
  57. int tapiopen = 0 ;
  58. int tapiconv = CK_AUTO ;         /* TAPI Conversion mode */
  59. int tapilights = TRUE;
  60. int tapipreterm = FALSE;
  61. int tapipostterm = FALSE;
  62. int tapimanual = FALSE;
  63. int tapiinactivity = 0;
  64. int tapibong = 8;
  65. int tapiusecfg = CK_OFF;
  66.  
  67. /* TAPI Location Information */
  68. char tapiloc[256] = "" ;
  69. int tapilocid = -1 ;
  70.  
  71. DWORD  tapiCountryID = -1L ;
  72. char   tapiAreaCode[32] = "" ;
  73. DWORD  tapiPreferredCardID=MAXDWORD;
  74. DWORD  tapiCountryCode=0;     
  75. char   tapiLocalAccessCode[32] = "" ;
  76. char   tapiLongDistAccessCode[32] = "";
  77. char   tapiTollPrefixList[4096]="";
  78. DWORD  tapiOptions=0;
  79. char   tapiCancelCallWaiting[32] = "";
  80. char   tapiCountryName[32] = "";
  81. char   tapiSameAreaRule[32] = "";
  82. char   tapiLongDistanceRule[32] = "";
  83. char   tapiInternationalRule[32] = "";
  84.  
  85. LONG (WINAPI *cklineInitialize)(LPHLINEAPP, HINSTANCE, LINECALLBACK, LPCSTR, LPDWORD ) = NULL ;
  86. LONG (WINAPI *cklineNegotiateAPIVersion)(HLINEAPP, DWORD, DWORD, DWORD, LPDWORD, LPLINEEXTENSIONID) = NULL ;
  87. LONG (WINAPI *cklineGetDevCaps)(HLINEAPP, DWORD, DWORD, DWORD, LPLINEDEVCAPS) = NULL ;
  88. LONG (WINAPI *cklineShutdown)(HLINEAPP) = NULL ;
  89. LONG (WINAPI *cklineOpen)(HLINEAPP, DWORD, LPHLINE, DWORD, DWORD, DWORD, DWORD, DWORD, 
  90.                   LPLINECALLPARAMS) = NULL ;
  91. LONG (WINAPI *cklineMakeCall)(HLINE hLine, LPHCALL lphCall, LPCSTR lpszDestAddress, 
  92.                       DWORD dwCountryCode, LPLINECALLPARAMS const lpCallParams) = NULL ;
  93. LONG (WINAPI *cklineDial)(HCALL hCall, LPCSTR lpszDestAddress, DWORD dwCountryCode) = NULL ;
  94. LONG (WINAPI *cklineDrop)(HCALL hCall, LPCSTR lpsUserUserInfo, DWORD dwSize) = NULL ;
  95. LONG (WINAPI *cklineAnswer)(HCALL hCall, LPCSTR lpsUserUserInfo, DWORD dwSize) = NULL ;
  96. LONG (WINAPI *cklineAccept)(HCALL hCall, LPCSTR lpsUserUserInfo, DWORD dwSize) = NULL ;
  97. LONG (WINAPI *cklineDeallocateCall)(HCALL hCall) = NULL ;
  98. LONG (WINAPI *cklineSetCallPrivilege)(HCALL,DWORD) = NULL ;
  99. LONG (WINAPI *cklineClose)(HLINE hLine) = NULL ;
  100. LONG (WINAPI *cklineHandoff)(HCALL,LPCSTR,DWORD) = NULL ;
  101. LONG (WINAPI *cklineGetID)(HLINE hLine, DWORD dwAddressID, HCALL hCall, 
  102.                DWORD dwSelect, LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass) = NULL ;
  103. LONG (WINAPI *cklineGetTranslateCaps)( HLINEAPP hLineApp, DWORD, 
  104.                                        LPLINETRANSLATECAPS lpLineTranslateCaps) = NULL ;
  105. LONG (WINAPI *cklineSetCurrentLocation)( HLINEAPP hLineApp, DWORD dwLocationID ) = NULL ;
  106. LONG (WINAPI *cklineSetStatusMessages)( HLINE hLine, DWORD dwLineStates, 
  107.                                         DWORD dwAddressStates ) = NULL ;
  108. LONG (WINAPI *cklineConfigDialog)( DWORD dwLine, HWND hwin, LPCSTR lpszTypes ) = NULL ;
  109. LONG (WINAPI *cklineTranslateDialog)( HLINEAPP hTAPI, DWORD dwLine, DWORD dwVersionToUse,
  110.                       HWND hwndOwner, LPCSTR lpszAddressIn ) = NULL ;
  111. LONG (WINAPI *cklineTranslateAddress)( HLINEAPP hTAPI, DWORD dwLine, DWORD dwVersionToUse,
  112.                        LPCSTR lpszAddressIn, DWORD dwCard,
  113.                        DWORD dwTranslateOptions,
  114.                        LPLINETRANSLATEOUTPUT lpTranslateOutput) = NULL ;
  115. LONG (WINAPI *cklineGetCountry)( DWORD, DWORD, LPLINECOUNTRYLIST ) = NULL;
  116. LONG (WINAPI *cklineGetDevConfig)(DWORD, LPVARSTRING, LPCSTR) = NULL;
  117. LONG (WINAPI *cklineGetLineDevStatus)(HLINE hLine,LPLINEDEVSTATUS lpLineDevStatus)=NULL;
  118. LONG (WINAPI *cklineSetDevConfig)(DWORD,LPVOID const,DWORD,LPCSTR)=NULL;
  119. LONG (WINAPI *cklineGetCallInfo)(HCALL, LPLINECALLINFO)=NULL;
  120. LONG (WINAPI *cklineMonitorMedia)(HCALL,DWORD)=NULL;
  121. LONG (WINAPI *cklineGetAppPriority)(LPCSTR,DWORD,LPLINEEXTENSIONID,
  122.                      DWORD,LPVARSTRING,LPDWORD)=NULL;
  123. LONG (WINAPI *cklineSetAppPriority)(LPCSTR,DWORD,LPLINEEXTENSIONID,
  124.                      DWORD,LPCSTR,DWORD)=NULL;
  125. LONG (WINAPI *cklineGetNumRings)(HLINE,DWORD,LPDWORD)=NULL;
  126. LONG (WINAPI *cklineSetNumRings)(HLINE,DWORD,DWORD)=NULL;
  127. LONG (WINAPI *cklineSetCallParams)(HCALL,DWORD,DWORD,DWORD,LPLINEDIALPARAMS)=NULL;
  128.  
  129. int 
  130. cktapiunload(void)
  131. {
  132.     FreeLibrary( hLib ) ;
  133.     hLib = NULL ;
  134.     cklineInitialize = NULL ;
  135.     return TRUE ;
  136. }
  137.  
  138.  
  139. int cktapiload(void) 
  140. {
  141.    DWORD rc = 0 ;
  142.     hLib = LoadLibrary("tapi32") ;
  143.    if ( !hLib )
  144.    {
  145.       rc = GetLastError() ;
  146.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  147.       return FALSE;
  148.    }
  149.  
  150.    if (((FARPROC) cklineInitialize = GetProcAddress( hLib, "lineInitialize" )) == NULL )
  151.    {
  152.       rc = GetLastError() ;
  153.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  154.       return FALSE;
  155.    }
  156.    if (((FARPROC) cklineNegotiateAPIVersion = GetProcAddress( hLib, "lineNegotiateAPIVersion" )) == NULL )
  157.    {
  158.       rc = GetLastError() ;
  159.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  160.       return FALSE;
  161.    }
  162.    if (((FARPROC) cklineGetDevCaps = GetProcAddress( hLib, "lineGetDevCaps" )) == NULL )
  163.    {
  164.       rc = GetLastError() ;
  165.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  166.       return FALSE;
  167.    }
  168.    if (((FARPROC) cklineShutdown = GetProcAddress( hLib, "lineShutdown" )) == NULL )
  169.    {
  170.       rc = GetLastError() ;
  171.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  172.       return FALSE;
  173.    }
  174.    if (((FARPROC) cklineOpen = GetProcAddress( hLib, "lineOpen" )) == NULL )
  175.    {
  176.       rc = GetLastError() ;
  177.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  178.       return FALSE;
  179.    }
  180.    if (((FARPROC) cklineMakeCall = GetProcAddress( hLib, "lineMakeCall" )) == NULL )
  181.    {
  182.       rc = GetLastError() ;
  183.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  184.       return FALSE;
  185.    }
  186.    if (((FARPROC) cklineDial = GetProcAddress( hLib, "lineDial" )) == NULL )
  187.    {
  188.       rc = GetLastError() ;
  189.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  190.       return FALSE;
  191.    }
  192.    if (((FARPROC) cklineDrop = GetProcAddress( hLib, "lineDrop" )) == NULL )
  193.    {
  194.       rc = GetLastError() ;
  195.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  196.       return FALSE;
  197.    }
  198.     if (((FARPROC) cklineAnswer = GetProcAddress( hLib, "lineAnswer" )) == NULL )
  199.     {
  200.     rc = GetLastError() ;
  201.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  202.     return FALSE;
  203.     }
  204.     if (((FARPROC) cklineAccept = GetProcAddress( hLib, "lineAccept" )) == NULL )
  205.     {
  206.     rc = GetLastError() ;
  207.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  208.     return FALSE;
  209.     }
  210.     if (((FARPROC) cklineDeallocateCall = GetProcAddress( hLib, "lineDeallocateCall" )) == NULL )
  211.     {
  212.     rc = GetLastError() ;
  213.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  214.     return FALSE;
  215.     }
  216.     if (((FARPROC) cklineClose = GetProcAddress( hLib, "lineClose" )) == NULL )
  217.    {
  218.       rc = GetLastError() ;
  219.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  220.       return FALSE;
  221.    }
  222.    if (((FARPROC) cklineGetID = GetProcAddress( hLib, "lineGetID" )) == NULL )
  223.    {
  224.       rc = GetLastError() ;
  225.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  226.       return FALSE;
  227.    }
  228.    if (((FARPROC) cklineGetTranslateCaps = GetProcAddress( hLib, "lineGetTranslateCaps" )) == NULL )
  229.    {
  230.       rc = GetLastError() ;
  231.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  232.       return FALSE;
  233.    }
  234.    if (((FARPROC) cklineSetCurrentLocation = GetProcAddress( hLib, "lineSetCurrentLocation" )) == NULL )
  235.    {
  236.       rc = GetLastError() ;
  237.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  238.       return FALSE;
  239.    }
  240.    if (((FARPROC) cklineSetStatusMessages = GetProcAddress( hLib, "lineSetStatusMessages" )) == NULL )
  241.    {
  242.       rc = GetLastError() ;
  243.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  244.       return FALSE;
  245.    }
  246.     if (((FARPROC) cklineConfigDialog = GetProcAddress( hLib, "lineConfigDialog" )) == NULL )
  247.     {
  248.     rc = GetLastError() ;
  249.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  250.     return FALSE;
  251.     }
  252.     if (((FARPROC) cklineTranslateDialog = GetProcAddress( hLib, "lineTranslateDialog" )) == NULL )
  253.     {
  254.     rc = GetLastError() ;
  255.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  256.     return FALSE;
  257.     }
  258.     if (((FARPROC) cklineTranslateAddress = 
  259.       GetProcAddress( hLib, "lineTranslateAddress" )) == NULL )
  260.     {
  261.     rc = GetLastError() ;
  262.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  263.     return FALSE;
  264.     }
  265.     if (((FARPROC) cklineGetCountry = 
  266.       GetProcAddress( hLib, "lineGetCountry" )) == NULL )
  267.     {
  268.     rc = GetLastError() ;
  269.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  270.     return FALSE;
  271.     }
  272.     if (((FARPROC) cklineGetLineDevStatus = 
  273.       GetProcAddress( hLib, "lineGetLineDevStatus" )) == NULL )
  274.     {
  275.     rc = GetLastError() ;
  276.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  277.     return FALSE;
  278.     }
  279.     if (((FARPROC) cklineGetDevConfig = 
  280.       GetProcAddress( hLib, "lineGetDevConfig" )) == NULL )
  281.     {
  282.     rc = GetLastError() ;
  283.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  284.     return FALSE;
  285.     }
  286.     if (((FARPROC) cklineSetDevConfig = 
  287.       GetProcAddress( hLib, "lineSetDevConfig" )) == NULL )
  288.     {
  289.     rc = GetLastError() ;
  290.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  291.     return FALSE;
  292.     }
  293.     if (((FARPROC) cklineHandoff = 
  294.       GetProcAddress( hLib, "lineHandoff" )) == NULL )
  295.     {
  296.     rc = GetLastError() ;
  297.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  298.     return FALSE;
  299.     }
  300.     if (((FARPROC) cklineSetCallPrivilege = 
  301.       GetProcAddress( hLib, "lineSetCallPrivilege" )) == NULL )
  302.     {
  303.     rc = GetLastError() ;
  304.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  305.     return FALSE;
  306.     }
  307.     if (((FARPROC) cklineGetCallInfo = 
  308.       GetProcAddress( hLib, "lineGetCallInfo" )) == NULL )
  309.     {
  310.     rc = GetLastError() ;
  311.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  312.     return FALSE;
  313.     }
  314.     if (((FARPROC) cklineMonitorMedia = 
  315.       GetProcAddress( hLib, "lineMonitorMedia" )) == NULL )
  316.     {
  317.     rc = GetLastError() ;
  318.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  319.     return FALSE;
  320.     }
  321.     if (((FARPROC) cklineGetAppPriority = 
  322.       GetProcAddress( hLib, "lineGetAppPriority" )) == NULL )
  323.     {
  324.     rc = GetLastError() ;
  325.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  326.     return FALSE;
  327.     }
  328.     if (((FARPROC) cklineSetAppPriority = 
  329.       GetProcAddress( hLib, "lineSetAppPriority" )) == NULL )
  330.     {
  331.     rc = GetLastError() ;
  332.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  333.     return FALSE;
  334.     }
  335.     if (((FARPROC) cklineGetNumRings = 
  336.       GetProcAddress( hLib, "lineGetNumRings" )) == NULL )
  337.     {
  338.     rc = GetLastError() ;
  339.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  340.     return FALSE;
  341.     }
  342.     if (((FARPROC) cklineSetNumRings = 
  343.       GetProcAddress( hLib, "lineSetNumRings" )) == NULL )
  344.     {
  345.     rc = GetLastError() ;
  346.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  347.     return FALSE;
  348.     }
  349.     if (((FARPROC) cklineSetCallParams = 
  350.       GetProcAddress( hLib, "lineSetCallParams" )) == NULL )
  351.     {
  352.     rc = GetLastError() ;
  353.     debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  354.     return FALSE;
  355.     }
  356.     return TRUE;
  357. }
  358.  
  359. // Global TAPI variables.
  360. HWND     g_hWndMainWindow = NULL;   // Apps main window.
  361. HWND     g_hDlgParentWindow = NULL; // This will be the parent of all dialogs.
  362. HLINEAPP g_hLineApp = NULL;
  363. LONG     g_lNumDevs = -1;
  364. DWORD    g_DataDevices = 0 ;
  365.  
  366. #define MAXDEVS 64
  367. LPLINEDEVCAPS g_lpLineDevCaps[64] ;
  368.  
  369. // Global variable that holds the handle to a TAPI dialog
  370. // that needs to be dismissed if line conditions change.
  371. HWND g_hDialog = NULL;
  372.  
  373. // Global flags to prevent re-entrancy problems.
  374. BOOL g_bShuttingDown = FALSE;
  375. BOOL g_bStoppingCall = FALSE;
  376. BOOL g_bInitializing = FALSE;
  377.  
  378.  
  379. // This sample only supports one call in progress at a time.
  380. BOOL g_bTapiInUse = FALSE;
  381.  
  382.  
  383. // Data needed per call.  This sample only supports one call.
  384. HCALL g_hCall = NULL;
  385. HLINE g_hLine = NULL;
  386. int ttyfd=-1 ; /* this holds the HLINE hLine */
  387. int mdmtyp=0;
  388. static int mdmtyp_sav=0;
  389. CHAR szModemName[256] ;
  390. DWORD LineDeviceId = -1;
  391. DWORD LineDeviceAPIVersion = 0 ;
  392. DWORD LineAddressCount = 0 ;
  393. DWORD LineMediaModes = 0 ;
  394.  
  395. DWORD g_dwAPIVersion = 0;
  396.  
  397. DWORD g_dwCallState = 0;
  398. char  g_szDisplayableAddress[1024] = "";
  399. char  g_szDialableAddress[1024] = "";
  400. BOOL  g_bConnected = FALSE;
  401. LPVOID g_lpDeviceConfig = NULL;
  402. DWORD g_dwSizeDeviceConfig;
  403.  
  404. // Global variables to allow us to do various waits.
  405. BOOL  g_bReplyReceived;
  406. DWORD g_dwRequestedID;
  407. long  g_lAsyncReply;
  408. BOOL  g_bCallStateReceived;
  409. BOOL  g_bAnswering = FALSE;
  410. BOOL  g_bDialing = FALSE;
  411. BOOL  g_bHangingUp = FALSE;
  412. BOOL  g_bClosing = FALSE;
  413.  
  414. int 
  415. cktapiinit()
  416. {
  417.     int i = 0 ;
  418.     // This will be the parent of all dialogs.
  419.     g_hWndMainWindow = g_hDlgParentWindow = hwndConsole; 
  420.  
  421.     for ( i=0 ; i < MAXDEVS ; i++ )
  422.     g_lpLineDevCaps[i] = NULL ;
  423.     g_lNumDevs = 0;
  424.  
  425.     if ( cktapiload() )
  426.     {
  427.         if (cktapiopen())
  428.         {
  429.            debug(F100,"TAPI open successful","",0);
  430.            g_DataDevices = cktapidevenum() ;
  431.            cktapiclose() ;
  432.            return TRUE ;
  433.         }
  434.         else 
  435.         {
  436.             debug(F100,"TAPI open failed","",0);
  437.         }
  438.     }
  439.     return FALSE;
  440. }
  441.  
  442. void
  443. OutputDebugLastError( DWORD x, char * string )
  444. {
  445.     char buf[1024];
  446.     sprintf(buf,"%s %s",string,cktapiErrorString(x));
  447.     debug(F111,"TAPI LastError",buf,x);
  448. #ifdef BETATEST_X
  449.     printf("TAPI LastError %s=%x\n",string,x);
  450. #endif
  451. }
  452.  
  453. void
  454. HandleNoMem( ) 
  455. {
  456.    debug(F100,"TAPI Out of Memory","",0);
  457. }
  458.  
  459. //
  460. //  FUNCTION: LPVOID CheckAndReAllocBuffer(LPVOID, size_t, LPCSTR)
  461. //
  462. //  PURPOSE: Checks and ReAllocates a buffer if necessary.
  463. //
  464. //  PARAMETERS:
  465. //    lpBuffer          - Pointer to buffer to be checked.  Can be NULL.
  466. //    sizeBufferMinimum - Minimum size that lpBuffer should be.
  467. //    szApiPhrase       - Phrase to print if an error occurs.
  468. //
  469. //  RETURN VALUE:
  470. //    Returns a pointer to a valid buffer that is guarenteed to be
  471. //    at least sizeBufferMinimum size.
  472. //    Returns NULL if an error occured.
  473. //
  474. //  COMMENTS:
  475. //
  476. //    This function is a helper function intended to make all of the 
  477. //    line API Wrapper Functions much simplier.  It allocates (or
  478. //    reallocates) a buffer of the requested size.
  479. //
  480. //    The returned pointer has been allocated with LocalAlloc,
  481. //    so LocalFree has to be called on it when you're finished with it,
  482. //    or there will be a memory leak.
  483. //
  484. //    Similarly, if a pointer is passed in, it *must* have been allocated
  485. //    with LocalAlloc and it could potentially be LocalFree()d.
  486. //
  487. //    If lpBuffer == NULL, then a new buffer is allocated.  It is
  488. //    normal to pass in NULL for this parameter the first time and only
  489. //    pass in a pointer if the buffer needs to be reallocated.
  490. //
  491. //    szApiPhrase is used only for debugging purposes.
  492. //
  493. //    It is assumed that the buffer returned from this function will be used
  494. //    to contain a variable sized structure.  Thus, the dwTotalSize field
  495. //    is always filled in before returning the pointer.
  496. //
  497. //
  498.  
  499. LPVOID 
  500. CheckAndReAllocBuffer(LPVOID lpBuffer, size_t sizeBufferMinimum, 
  501.                LPCSTR szApiPhrase)
  502. {
  503.     size_t sizeBuffer;
  504.  
  505.     if (lpBuffer == NULL)  // Allocate the buffer if necessary. 
  506.     {
  507.         sizeBuffer = sizeBufferMinimum;
  508.         lpBuffer = (LPVOID) LocalAlloc(LPTR, sizeBuffer);
  509.             
  510.         if (lpBuffer == NULL)
  511.         {
  512.             HandleNoMem();
  513.             return NULL;
  514.         }
  515.     }
  516.     else // If the structure already exists, make sure its good.
  517.     {
  518.         sizeBuffer = LocalSize((HLOCAL) lpBuffer);
  519.  
  520.         if (sizeBuffer == 0) // Bad pointer?
  521.         {
  522.             return NULL;
  523.         }
  524.  
  525.         // Was the buffer big enough for the structure?
  526.         if (sizeBuffer < sizeBufferMinimum)
  527.         {
  528.             LocalFree(lpBuffer);
  529.             return CheckAndReAllocBuffer(NULL, sizeBufferMinimum, szApiPhrase);
  530.         }
  531.  
  532.         // Lets zero the buffer out.
  533.         memset(lpBuffer, 0, sizeBuffer);
  534.     }
  535.                 
  536.     ((LPVARSTRING) lpBuffer ) -> dwTotalSize = (DWORD) sizeBuffer;
  537.     return lpBuffer;
  538. }
  539.  
  540. char *
  541. cktapiErrorString(DWORD error)
  542. {
  543.     char * estr = NULL;
  544.     switch ( error ) {
  545.     case 0:
  546.     estr = "Success";
  547.     break;
  548.     case LINEERR_ALLOCATED:
  549.     estr = "Line already allocated";
  550.     break;
  551.     case LINEERR_BADDEVICEID:
  552.     estr = "Bad device ID";
  553.     break;
  554.     case LINEERR_BEARERMODEUNAVAIL:
  555.     estr = "Requested Bearer Mode Unavailable";
  556.     break;
  557.     case LINEERR_CALLUNAVAIL:
  558.     estr = "Unable to place call on current device";
  559.     break;
  560.     case LINEERR_COMPLETIONOVERRUN               :
  561.     estr = "Completion Overrun";
  562.     break;
  563.     case LINEERR_CONFERENCEFULL                  :
  564.     estr = "Conference Full";
  565.     break;
  566.     case LINEERR_DIALBILLING                     :
  567.     estr = "Dial Billing error";
  568.     break;
  569.     case LINEERR_DIALDIALTONE                    :
  570.     estr = "Wait for Dial Tone not supported";
  571.     break;
  572.     case LINEERR_DIALPROMPT                      :
  573.     estr = "Wait for Dial Prompt not supported";
  574.     break;
  575.     case LINEERR_DIALQUIET                       :
  576.     estr = "Wait for Quiet not supported";
  577.     break;
  578.     case LINEERR_INCOMPATIBLEAPIVERSION          :
  579.     estr = "Incompatible TAPI Version";
  580.     break;
  581.     case LINEERR_INCOMPATIBLEEXTVERSION          :
  582.     estr = "Incompatible Extension Version";
  583.     break;
  584.     case LINEERR_INIFILECORRUPT                  :
  585.     estr = "TELEPHON.INI file corrupt";
  586.     break;
  587.     case LINEERR_INUSE                           :
  588.     estr = "Line in use";
  589.     break;
  590.     case LINEERR_INVALADDRESS                    :
  591.     estr = "Invalid Line Address";
  592.     break;
  593.     case LINEERR_INVALADDRESSID                  :
  594.     estr = "Invalid Line Address ID";
  595.     break;
  596.     case LINEERR_INVALADDRESSMODE                :
  597.     estr = "Invalid Line Address Mode";
  598.     break;
  599.     case LINEERR_INVALADDRESSSTATE               :
  600.     estr = "Invalid Line Address State";
  601.     break;
  602.     case LINEERR_INVALAPPHANDLE                  :
  603.     estr = "Invalid Application Handle";
  604.     break;
  605.     case LINEERR_INVALAPPNAME                    :
  606.     estr = "Invalid Application Name";
  607.     break;
  608.     case LINEERR_INVALBEARERMODE                 :
  609.     estr = "Invalid Bearer Mode";
  610.     break;
  611.     case LINEERR_INVALCALLCOMPLMODE              :
  612.     estr = "Invalid Call Completion Mode";
  613.     break;
  614.     case LINEERR_INVALCALLHANDLE                 :
  615.     estr = "Invalid Call Handle";
  616.     break;
  617.     case LINEERR_INVALCALLPARAMS                 :
  618.     estr = "Invalid Call Parameters";
  619.     break;
  620.     case LINEERR_INVALCALLPRIVILEGE              :
  621.     estr = "Invalid Call Privilege";
  622.     break;
  623.     case LINEERR_INVALCALLSELECT                 :
  624.     estr = "Invalid Call Selection";
  625.     break;
  626.     case LINEERR_INVALCALLSTATE                  :
  627.     estr = "Invalid Call State";
  628.     break;
  629.     case LINEERR_INVALCALLSTATELIST              :
  630.     estr = "Invalid Call State List";
  631.     break;
  632.     case LINEERR_INVALCARD                       :
  633.     estr = "Invalid Card";
  634.     break;
  635.     case LINEERR_INVALCOMPLETIONID               :
  636.     estr = "Invalid Completion ID";
  637.     break;
  638.     case LINEERR_INVALCONFCALLHANDLE             :
  639.     estr = "Invalid Conference Call Handle";
  640.     break;
  641.     case LINEERR_INVALCONSULTCALLHANDLE          :
  642.     estr = "Invalid Consulation Call Handle";
  643.     break;
  644.     case LINEERR_INVALCOUNTRYCODE                :
  645.     estr = "Invalid Country Code";
  646.     break;
  647.     case LINEERR_INVALDEVICECLASS                :
  648.     estr = "Invalid Device Class";
  649.     break;
  650.     case LINEERR_INVALDEVICEHANDLE               :
  651.     estr = "Invalid Device Handle";
  652.     break;
  653.     case LINEERR_INVALDIALPARAMS                 :
  654.     estr = "Invalid Dial Parameters";
  655.     break;
  656.     case LINEERR_INVALDIGITLIST                  :
  657.     estr = "Invalid Digit List";
  658.     break;
  659.     case LINEERR_INVALDIGITMODE                  :
  660.     estr = "Invalid Digit Mode";
  661.     break;
  662.     case LINEERR_INVALDIGITS                     :
  663.     estr = "Invalid Digits";
  664.     break;
  665.     case LINEERR_INVALEXTVERSION                 :
  666.     estr = "Invalid Extension Version";
  667.     break;
  668.     case LINEERR_INVALGROUPID                    :
  669.     estr = "Invalid Group ID";
  670.     break;
  671.     case LINEERR_INVALLINEHANDLE                 :
  672.     estr = "Invalid Line Handle";
  673.     break;
  674.     case LINEERR_INVALLINESTATE                  :
  675.     estr = "Invalid Line State";
  676.     break;
  677.     case LINEERR_INVALLOCATION                   :
  678.     estr = "Invalid Location";
  679.     break;
  680.     case LINEERR_INVALMEDIALIST                  :
  681.     estr = "Invalid Media List";
  682.     break;
  683.     case LINEERR_INVALMEDIAMODE                  :
  684.     estr = "Invalid Media Mode";
  685.     break;
  686.     case LINEERR_INVALMESSAGEID                  :
  687.     estr = "Invalid Message ID";
  688.     break;
  689.     case LINEERR_INVALPARAM                      :
  690.     estr = "Invalid Parameter";
  691.     break;
  692.     case LINEERR_INVALPARKID                     :
  693.     estr = "Invalid Park ID";
  694.     break;
  695.     case LINEERR_INVALPARKMODE                   :
  696.     estr = "Invaldi Park Mode";
  697.     break;
  698.     case LINEERR_INVALPOINTER                    :
  699.     estr = "Invalid Pointer";
  700.     break;
  701.     case LINEERR_INVALPRIVSELECT                 :
  702.     estr = "Invalid Privilege Select";
  703.     break;
  704.     case LINEERR_INVALRATE                       :
  705.     estr = "Invalid Rate";
  706.     break;
  707.     case LINEERR_INVALREQUESTMODE                :
  708.     estr = "Invalid Request Mode";
  709.     break;
  710.     case LINEERR_INVALTERMINALID                 :
  711.     estr = "Invalid Terminal ID";
  712.     break;
  713.     case LINEERR_INVALTERMINALMODE               :
  714.     estr = "Invalid Terminal Mode";
  715.     break;
  716.     case LINEERR_INVALTIMEOUT                    :
  717.     estr = "Invalid Timeout";
  718.     break;
  719.     case LINEERR_INVALTONE                       :
  720.     estr = "Invalid Tone";
  721.     break;
  722.     case LINEERR_INVALTONELIST                   :
  723.     estr = "Invalid Tone List";
  724.     break;
  725.     case LINEERR_INVALTONEMODE                   :
  726.     estr = "Invalid Tone Mode";
  727.     break;
  728.     case LINEERR_INVALTRANSFERMODE               :
  729.     estr = "Invalid Transfer Mode";
  730.     break;
  731.     case LINEERR_LINEMAPPERFAILED                :
  732.     estr = "Line Mapper Failed";
  733.     break;
  734.     case LINEERR_NOCONFERENCE                    :
  735.     estr = "No Conference available";
  736.     break;
  737.     case LINEERR_NODEVICE                        :
  738.     estr = "No Device available";
  739.     break;
  740.     case LINEERR_NODRIVER                        :
  741.     estr = "No Driver available";
  742.     break;
  743.     case LINEERR_NOMEM                           :
  744.     estr = "No memory available";
  745.     break;
  746.     case LINEERR_NOREQUEST                       :
  747.     estr = "No Request";
  748.     break;
  749.     case LINEERR_NOTOWNER                        :
  750.     estr = "Not owner";
  751.     break;
  752.     case LINEERR_NOTREGISTERED                   :
  753.     estr = "Not Registered";
  754.     break;
  755.     case LINEERR_OPERATIONFAILED                 :
  756.     estr = "Operation Failed";
  757.     break;
  758.     case LINEERR_OPERATIONUNAVAIL                :
  759.     estr = "Operation Unavailable";
  760.     break;
  761.     case LINEERR_RATEUNAVAIL                     :
  762.     estr = "Rate Unavailable";
  763.     break;
  764.     case LINEERR_RESOURCEUNAVAIL                 :
  765.     estr = "Resource Unavailable";
  766.     break;
  767.     case LINEERR_REQUESTOVERRUN                  :
  768.     estr = "Request Overrun";
  769.     break;
  770.     case LINEERR_STRUCTURETOOSMALL               :
  771.     estr = "Structure Too Small";
  772.     break;
  773.     case LINEERR_TARGETNOTFOUND                  :
  774.     estr = "Target Not Found";
  775.     break;
  776.     case LINEERR_TARGETSELF                      :
  777.     estr = "Target Self";
  778.     break;
  779.     case LINEERR_UNINITIALIZED                   :
  780.     estr = "TAPI Unititialized";
  781.     break;
  782.     case LINEERR_USERUSERINFOTOOBIG              :
  783.     estr = "User Info Too Big";
  784.     break;
  785.     case LINEERR_REINIT                          :
  786.     estr = "TAPI Reinitialization Required";
  787.     break;
  788.     case LINEERR_ADDRESSBLOCKED                  :
  789.     estr = "Address Blocked";
  790.     break;
  791.     case LINEERR_BILLINGREJECTED                 :
  792.     estr = "Billing Rejected";
  793.     break;
  794.     case LINEERR_INVALFEATURE                    :
  795.     estr = "Invalid Feature";
  796.     break;
  797.     case LINEERR_NOMULTIPLEINSTANCE              :
  798.     estr = "Multiple Instances not supported";
  799.     break;
  800. #ifdef COMMENT    /* TAPI 2.0 */
  801.     case LINEERR_INVALAGENTID                    :
  802.     estr = "Invalid Agent ID";
  803.     break;
  804.     case LINEERR_INVALAGENTGROUP                 :
  805.     estr = "Invalid Agent Group";
  806.     break;
  807.     case LINEERR_INVALPASSWORD                   :
  808.     estr = "Invalid Password";
  809.     break;
  810.     case LINEERR_INVALAGENTSTATE                 :
  811.     estr = "Invalid Agent State";
  812.     break;
  813.     case LINEERR_INVALAGENTACTIVITY              :
  814.     estr = "Invalid Agent Activity";
  815.     break;
  816.     case LINEERR_DIALVOICEDETECT                 :
  817.     estr = "Voice detected during dialing";
  818.     break;
  819. #endif /* COMMENT */
  820.     default:
  821.     estr = ((LONG) error) > 0 ? "Request ID" : "Unknown TAPI error";
  822.     break;
  823.     }
  824.     return estr;
  825. }
  826.  
  827. void 
  828. UpdateStatusBar( char * str, long param1, long param2 )
  829. {
  830.     char buf[1024];
  831.     sprintf(buf,"%s::%d,%d",str,param1,param2);
  832.     // MessageBox();  ????
  833. }
  834.  
  835. void 
  836. OutputDebugLineError( long param, char * str )
  837. {
  838.     char buf[1024];
  839.     sprintf(buf,"%s %s",str,cktapiErrorString(param));
  840.     // MessageBox();  ????
  841. }
  842.  
  843.  
  844. void 
  845. CALLBACK
  846. cklineCallbackFunc( DWORD dwDevice, DWORD dwMsg, 
  847.             DWORD dwCallbackInstance,
  848.             DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
  849. {
  850.     return;
  851.  
  852. }
  853.  
  854. BOOL 
  855. HandleLineErr(long lLineErr)
  856. {
  857.     if ( lLineErr )
  858.     return FALSE;
  859.     else return TRUE ;
  860. }
  861.  
  862. BOOL 
  863. HandleNoDevicesInstalled(void)
  864. {
  865.     return FALSE;
  866. }
  867.  
  868. BOOL g_bLineInitialized = FALSE;
  869. void
  870. wintapiinit( void )
  871. {
  872.     long lReturn;
  873.     BOOL bTryReInit = TRUE ;
  874.     
  875.     // Initialize TAPI
  876.     do
  877.     {
  878.         lReturn = (*cklineInitialize)(&g_hLineApp, GetModuleHandle(NULL), 
  879.              cklineCallbackFunc, "K95 Setup", &g_lNumDevs);
  880.     OutputDebugLastError(lReturn,"lineInitialize:");
  881.  
  882.         // If we get this error, its because some other app has yet
  883.         // to respond to the REINIT message.  Wait 5 seconds and try
  884.         // again.  If it still doesn't respond, tell the user.
  885.         if (lReturn == LINEERR_REINIT)
  886.         {
  887.             if (bTryReInit)
  888.             {
  889.         Sleep(5000);    /* wait 5 secs, try again */
  890.                 bTryReInit = FALSE;
  891.                 continue;
  892.             }
  893.             else
  894.             {
  895.                 MessageBox(g_hDlgParentWindow,
  896.                     "A change to the system configuration requires that "
  897.                     "all Telephony applications relinquish their use of "
  898.                     "Telephony before any can progress.  "
  899.                     "Some have not yet done so."
  900.                     ,"Warning",MB_OK);
  901.                 g_bInitializing = FALSE;
  902.                 return;
  903.             }
  904.         }
  905.  
  906.         if (lReturn == LINEERR_NODEVICE)
  907.         {
  908.             if (HandleNoDevicesInstalled())
  909.                 continue;
  910.             else
  911.             {
  912.                 g_bInitializing = FALSE;
  913.                 return;
  914.             }
  915.         }
  916.  
  917.         if (HandleLineErr(lReturn))
  918.             continue;
  919.         else
  920.         {
  921.             OutputDebugLineError(lReturn, 
  922.                 "lineInitialize unhandled error: ");
  923.             g_bInitializing = FALSE;
  924.             return;
  925.         }
  926.     }
  927.     while(lReturn != SUCCESS);
  928.  
  929.     g_bLineInitialized = TRUE;
  930. }
  931.  
  932. int 
  933. cktapiopen(void)
  934. {
  935.     if ( g_bClosing ) {
  936.     debug(F110,"TAPI Open","Close in progress",0);
  937.     while ( g_bClosing )
  938.         Sleep(500);
  939.     }
  940.     if ( tapiopen )
  941.     {
  942.     tapiopen++ ;
  943.     return TRUE ;
  944.     }
  945.  
  946.     debug(F100,"TAPI Open","",0);
  947.     g_bLineInitialized = FALSE;
  948.     wintapiinit();
  949.  
  950.     if ( !g_bLineInitialized )
  951.     return FALSE;
  952.  
  953.     tapiopen++;
  954.     return TRUE;
  955. }
  956.  
  957. int 
  958. cktapidevenum( void )
  959. {
  960.     int i = 0 ;
  961.     DWORD dwAPIVersion ;                    
  962.     LINEEXTENSIONID ExtensionID ;
  963.     int datalines = 0 ;
  964.     LONG rc;
  965.  
  966.     debug(F111,"TAPI Enumerate Devices","g_lNumDevs",g_lNumDevs);
  967.  
  968.     /* Free existing LineDevCaps */
  969.     for ( i = 0 ; i < g_lNumDevs ; i++ )
  970.     {
  971.     if ( g_lpLineDevCaps[i] )
  972.     {
  973.         free( g_lpLineDevCaps[i] ) ;
  974.         g_lpLineDevCaps[i] = NULL ;
  975.     }
  976.     }
  977.  
  978.     /* Enumerate current LineDevCaps */
  979.     for ( i=0 ; i < g_lNumDevs ; i++ )
  980.     {
  981.     g_lpLineDevCaps[i] = (LPLINEDEVCAPS) malloc (sizeof(LINEDEVCAPS)) ;
  982.     g_lpLineDevCaps[i]->dwTotalSize = sizeof(LINEDEVCAPS) ;
  983.     if ( rc = (*cklineNegotiateAPIVersion)(g_hLineApp, i, 
  984.                        TAPI_CURRENT_VERSION, 
  985.                        TAPI_CURRENT_VERSION,
  986.                        &dwAPIVersion, &ExtensionID))
  987.     {
  988.         OutputDebugLastError(rc,"lineNegotiateAPIVersion:");
  989.         free(g_lpLineDevCaps[i]);
  990.         g_lpLineDevCaps[i] = NULL ;
  991.         continue;
  992.     }
  993.     if (rc = (*cklineGetDevCaps)(g_hLineApp, i,
  994.                  dwAPIVersion, 0, g_lpLineDevCaps[i]))
  995.     {
  996.         OutputDebugLastError(rc,"lineGetDevCaps:");
  997.         free(g_lpLineDevCaps[i]);
  998.         g_lpLineDevCaps[i] = NULL ;
  999.         continue;
  1000.     }
  1001.  
  1002.     if ( g_lpLineDevCaps[i]->dwNeededSize > g_lpLineDevCaps[i]->dwTotalSize )
  1003.     {
  1004.         DWORD NeededSize = g_lpLineDevCaps[i]->dwNeededSize;
  1005.         free(g_lpLineDevCaps[i]) ;
  1006.         g_lpLineDevCaps[i] = (LPLINEDEVCAPS) malloc (NeededSize) ;
  1007.         g_lpLineDevCaps[i]->dwTotalSize = NeededSize ;
  1008.  
  1009.         if ((*cklineGetDevCaps)(g_hLineApp, i,
  1010.                                dwAPIVersion, 0, g_lpLineDevCaps[i]))
  1011.         {
  1012.         OutputDebugLastError(rc,"lineGetDevCaps:");
  1013.         free(g_lpLineDevCaps[i]);
  1014.         g_lpLineDevCaps[i] = NULL ;
  1015.         continue;
  1016.         }
  1017.     }
  1018.  
  1019.       /* We now have a successful LineDevCaps structure */
  1020.     if ( g_lpLineDevCaps[i]->dwMediaModes & LINEMEDIAMODE_DATAMODEM )
  1021.     {
  1022.          /* then this is a valid line to use for data connections */
  1023.         datalines++ ;
  1024.     }
  1025.     }
  1026.     debug(F111,"TAPI Enumerate Devices","datalines",datalines);
  1027.     return datalines ;
  1028. }
  1029.  
  1030. int 
  1031. cktapiclose(void)
  1032. {
  1033.     DWORD rc ;
  1034.  
  1035.     if ( g_bClosing ) {
  1036.     debug(F110,"TAPI Close","already in progress",0);
  1037.     while ( g_bClosing )
  1038.         Sleep(500);
  1039.     return TRUE;
  1040.     }
  1041.  
  1042.     if ( tapiopen > 0 )
  1043.     {
  1044.     tapiopen-- ;
  1045.  
  1046.     if ( tapiopen == 1 ) {
  1047.         g_bClosing = TRUE;
  1048.         debug(F100,"TAPI Close","",0);
  1049.         if ( g_hLine )
  1050.         {    
  1051.         rc = (*cklineClose)( g_hLine );
  1052.         OutputDebugLastError(rc,"lineClose:");
  1053.         g_hLine = NULL ;
  1054.         ttyfd = -1;
  1055.         }
  1056.     }
  1057.     if ( tapiopen == 0 ) {
  1058.         rc = (*cklineShutdown)( g_hLineApp ) ;
  1059.         OutputDebugLastError(rc,"lineShutdown:");
  1060.         g_hLineApp = NULL ;
  1061.     }
  1062.     g_bClosing = FALSE;
  1063.     }
  1064.     return TRUE;
  1065. }
  1066.  
  1067. int 
  1068. cktapiBuildLineTable( struct keytab ** pTable, struct keytab ** pTable2, int * pN )
  1069. {
  1070.     int i, n ;
  1071.     if ( *pTable )
  1072.     {
  1073.     for ( i=0 ; i < *pN ; i++ )
  1074.         free( (*pTable)[i].kwd ) ;
  1075.     free ( *pTable )  ;
  1076.     }
  1077.  
  1078.     if ( *pTable2 )
  1079.     {
  1080.     for ( i=0 ; i < *pN ; i++ )
  1081.         free( (*pTable2)[i].kwd ) ;
  1082.     free ( *pTable2 )  ;
  1083.     }
  1084.  
  1085.     *pTable = NULL ;
  1086.     *pTable2 = NULL ;
  1087.     *pN = 0 ; 
  1088.  
  1089.     cktapiopen() ;
  1090.     n = cktapidevenum() ;
  1091.     cktapiclose() ;
  1092.  
  1093.     debug(F100,"TAPI cktapiBuildLineTable","",0);
  1094.     if ( n )
  1095.     {
  1096.     *pTable = malloc( sizeof(struct keytab) * n ) ;
  1097.     *pTable2 = malloc( sizeof(struct keytab) * n ) ;
  1098.  
  1099.         for ( i=0 ; i < g_lNumDevs ; i++ ) {
  1100.         if ( g_lpLineDevCaps[i] == NULL )
  1101.         {
  1102.             debug(F111,"TAPI LineDevCaps entry is NULL","i",i);
  1103.         }
  1104.         else if ( g_lpLineDevCaps[i]->dwMediaModes & LINEMEDIAMODE_DATAMODEM )
  1105.         {
  1106.            char * newstr = _strdup( ((char *)(g_lpLineDevCaps[i]))+g_lpLineDevCaps[i]->dwLineNameOffset) ;
  1107.            char * newstr2 = _strdup( ((char *)(g_lpLineDevCaps[i]))+g_lpLineDevCaps[i]->dwLineNameOffset) ;
  1108.            int    newval = i;
  1109.            int j = 0, len = 0;
  1110.  
  1111.            debug(F111,"TAPI LINEMEDIAMODE_DATAMODEM",newstr,i);
  1112.  
  1113.            /* Make a version that uses Underscores instead of spaces */
  1114.            len = strlen(newstr2);
  1115.            for ( j=0 ; j<len ; j++) {
  1116.            switch ( newstr2[j] ) {
  1117.            case ' ':
  1118.                newstr2[j] = '_';
  1119.                break;
  1120.            case ',':
  1121.                newstr2[j] = '.';
  1122.                break;
  1123.            case ';':
  1124.                newstr2[j] = ':';
  1125.                break;
  1126.            case '\\':
  1127.                newstr2[j] = '/';
  1128.                break;
  1129.            case '?':
  1130.                newstr2[j] = '!';
  1131.                break;
  1132.            case '{':
  1133.                newstr2[j] = '[';
  1134.                break;
  1135.            case '}':
  1136.                newstr2[j] = ']';
  1137.                break;
  1138.            }
  1139.            }    
  1140.  
  1141.            for ( j=0 ; j < (*pN) ; j++ ) {
  1142.            int tempval=0;
  1143.            char * tempstr=NULL,*tempstr2=NULL;
  1144.  
  1145.            if ( _stricmp( (*pTable)[j].kwd, newstr ) > 0 ) 
  1146.            {
  1147.                tempval = (*pTable)[j].kwval;
  1148.                tempstr = (*pTable)[j].kwd;
  1149.                tempstr2 = (*pTable2)[j].kwd;
  1150.                (*pTable)[j].kwd = newstr ;
  1151.                (*pTable)[j].kwval = newval;
  1152.                (*pTable2)[j].kwd = newstr2 ;
  1153.                (*pTable2)[j].kwval = newval;
  1154.                newval = tempval;
  1155.                newstr = tempstr;
  1156.                (*pTable)[j].flgs = 0;
  1157.                newstr2 = tempstr2;
  1158.                (*pTable2)[j].flgs = 0;
  1159.            }
  1160.            }
  1161.            (*pTable)[*pN].kwd = newstr ;
  1162.            (*pTable)[*pN].kwval = newval;
  1163.            (*pTable)[*pN].flgs = 0 ;
  1164.            (*pTable2)[*pN].kwd = newstr2 ;
  1165.            (*pTable2)[*pN].kwval = newval;
  1166.            (*pTable2)[*pN].flgs = 0 ;
  1167.            (*pN)++ ;
  1168.        }
  1169.         else  
  1170.         {
  1171.            debug(F111,"TAPI ~LINEMEDIAMODE_DATAMODEM",
  1172.               ((char *)(g_lpLineDevCaps[i]))+g_lpLineDevCaps[i]->dwLineNameOffset,
  1173.               i);
  1174.         }
  1175.        }
  1176.  
  1177.        if ( *pN == 0 ) {
  1178.        /* TAPI Devices exist, but none can be used by Kermit */
  1179.        free ( *pTable )  ;
  1180.        free ( *pTable2 )  ;
  1181.        *pTable = NULL;
  1182.        *pTable2 = NULL;
  1183.        }
  1184.    }
  1185.    return *pN;
  1186. }
  1187.  
  1188. int 
  1189. cktapiGetCountryEntries( LPLINECOUNTRYLIST *lpCL, int * pN )
  1190. {
  1191.     LPLINECOUNTRYLIST  lpCountryList = NULL;
  1192.     LPLINECOUNTRYENTRY lpCountryEntry = NULL;
  1193.     DWORD dwSizeofCountryList = sizeof(LINECOUNTRYLIST);
  1194.     long lReturn=0;
  1195.     int i=0;
  1196.     OSVERSIONINFO osverinfo ;
  1197.     osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
  1198.     GetVersionEx( &osverinfo ) ;
  1199.  
  1200.     do
  1201.     {
  1202.     lpCountryList = 
  1203.         (LPLINECOUNTRYLIST) CheckAndReAllocBuffer((LPVOID) lpCountryList, 
  1204.                                dwSizeofCountryList,
  1205.                                "cktapiGetCountryEntries");
  1206.  
  1207.     if (lpCountryList == NULL)
  1208.         return 0;
  1209.  
  1210.     /* Win95 doesn't return anything is CountryID is 1 */
  1211.     lReturn = (*cklineGetCountry)(
  1212. #ifdef COMMENT
  1213.             osverinfo.dwPlatformId != 
  1214.             VER_PLATFORM_WIN32_WINDOWS ? tapiCountryID :
  1215. #endif
  1216.                        0, TAPI_CURRENT_VERSION,
  1217.                        lpCountryList);
  1218.  
  1219.     if (HandleLineErr(lReturn))
  1220.         ;
  1221.     else
  1222.     {
  1223.         OutputDebugLineError(lReturn, 
  1224.                   "lineGetCountry unhandled error: ");
  1225.         LocalFree(lpCountryList);
  1226.         return 0;
  1227.     }
  1228.  
  1229.     if ((lpCountryList -> dwNeededSize) >
  1230.          (lpCountryList -> dwTotalSize))
  1231.     {
  1232.         dwSizeofCountryList = lpCountryList ->dwNeededSize;
  1233.         lReturn = -1; // Lets loop again.
  1234.     }
  1235.     }
  1236.     while(lReturn != SUCCESS);
  1237.  
  1238.     *lpCL = lpCountryList;
  1239.     *pN = lpCountryList->dwNumCountries;
  1240.     return 1;
  1241. }
  1242.  
  1243. int 
  1244. cktapiGetLocationEntries( LPLINETRANSLATECAPS *lpTC,
  1245.               LPLINELOCATIONENTRY *lpLocationEntry, int * pN )
  1246. {
  1247.     LPLINETRANSLATECAPS lpTranslateCaps=NULL;
  1248.    DWORD dwSizeofTranslateCaps = sizeof(LINETRANSLATECAPS);
  1249.    long lReturn = 0;
  1250.    DWORD dwCounter;
  1251.    LPLINECARDENTRY lpLineCardEntry = NULL;
  1252.    int i = 0 ;
  1253.  
  1254.    cktapiopen() ;
  1255.  
  1256.    // First, get the TRANSLATECAPS
  1257.    do
  1258.    {
  1259.       lpTranslateCaps = (LPLINETRANSLATECAPS) CheckAndReAllocBuffer(
  1260.                  (LPVOID) lpTranslateCaps, dwSizeofTranslateCaps,
  1261.                  "cktapiBuildLocationTable");
  1262.  
  1263.       if (lpTranslateCaps == NULL)
  1264.       {
  1265.          cktapiclose();
  1266.          return 0;
  1267.       }
  1268.  
  1269.       lReturn = (*cklineGetTranslateCaps)(g_hLineApp, TAPI_CURRENT_VERSION,
  1270.                                       lpTranslateCaps);
  1271.  
  1272.       if (HandleLineErr(lReturn))
  1273.          ;
  1274.       else
  1275.       {
  1276.          OutputDebugLineError(lReturn, 
  1277.                                "lineGetTranslateCaps unhandled error: ");
  1278.          LocalFree(lpTranslateCaps);
  1279.       lpTranslateCaps = NULL;
  1280.          cktapiclose();
  1281.          return 0;
  1282.       }
  1283.  
  1284.       if ((lpTranslateCaps -> dwNeededSize) >
  1285.            (lpTranslateCaps -> dwTotalSize))
  1286.       {
  1287.          dwSizeofTranslateCaps = lpTranslateCaps ->dwNeededSize;
  1288.          lReturn = -1; // Lets loop again.
  1289.       }
  1290.    }
  1291.    while(lReturn != SUCCESS);
  1292.  
  1293.    cktapiclose() ;
  1294.  
  1295.    // Find the location information in the TRANSLATECAPS
  1296.    *lpLocationEntry = (LPLINELOCATIONENTRY)
  1297.       (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset);
  1298.     *pN = lpTranslateCaps->dwNumLocations;
  1299.     *lpTC = lpTranslateCaps;
  1300.    return 1;
  1301. }
  1302.  
  1303. int
  1304. cktapiGetCurrentLocationID( void )
  1305. {
  1306.     LPLINETRANSLATECAPS lpTranslateCaps = NULL;
  1307.     DWORD dwSizeofTranslateCaps = sizeof(LINETRANSLATECAPS);
  1308.     long lReturn;
  1309.     int  locationID=-1;
  1310.     
  1311.     // First, get the TRANSLATECAPS
  1312.     do
  1313.     {
  1314.     lpTranslateCaps = 
  1315.         (LPLINETRANSLATECAPS) CheckAndReAllocBuffer((LPVOID) lpTranslateCaps, 
  1316.                              dwSizeofTranslateCaps,
  1317.                              "cktapiGetCurrentLocationID");
  1318.  
  1319.     if (lpTranslateCaps == NULL)
  1320.         return -1;
  1321.  
  1322.     lReturn = (*cklineGetTranslateCaps)(g_hLineApp, TAPI_CURRENT_VERSION, 
  1323.                          lpTranslateCaps);
  1324.  
  1325.     if (HandleLineErr(lReturn))
  1326.         ;
  1327.     else
  1328.     {
  1329.         OutputDebugLineError(lReturn, 
  1330.                   "lineGetTranslateCaps unhandled error: ");
  1331.         LocalFree(lpTranslateCaps);
  1332.         return -1;
  1333.     }
  1334.  
  1335.     if ((lpTranslateCaps -> dwNeededSize) >
  1336.          (lpTranslateCaps -> dwTotalSize))
  1337.     {
  1338.         dwSizeofTranslateCaps = lpTranslateCaps ->dwNeededSize;
  1339.         lReturn = -1; // Lets loop again.
  1340.     }
  1341.     }
  1342.     while(lReturn != SUCCESS);
  1343.  
  1344.     locationID = lpTranslateCaps->dwCurrentLocationID;
  1345.  
  1346.     LocalFree(lpTranslateCaps);
  1347.     return locationID;
  1348. }
  1349.  
  1350. void
  1351. SaveTapiLocationInfo( LPLINETRANSLATECAPS lpTranslateCaps, 
  1352.               LPLINELOCATIONENTRY lpLocationEntry )
  1353. {
  1354.     LPLINECOUNTRYLIST  lpCountryList  = NULL;
  1355.     LPLINECOUNTRYENTRY lpCountryEntry = NULL;
  1356.     DWORD dwSizeofCountryList = sizeof(LINECOUNTRYLIST);
  1357.     long lReturn=0;
  1358.     int i=0;
  1359.     OSVERSIONINFO osverinfo ;
  1360.     osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
  1361.     GetVersionEx( &osverinfo ) ;
  1362.  
  1363.     tapilocid = lpLocationEntry->dwPermanentLocationID;
  1364.     strncpy(tapiloc, 
  1365.          (((LPSTR) lpTranslateCaps) +
  1366.            lpLocationEntry->dwLocationNameOffset),
  1367.          lpLocationEntry->dwLocationNameSize);
  1368.  
  1369.     tapiCountryID = lpLocationEntry->dwCountryID;
  1370.     tapiCountryCode = lpLocationEntry->dwCountryCode;
  1371.  
  1372.     do
  1373.     {
  1374.     lpCountryList = 
  1375.         (LPLINECOUNTRYLIST) CheckAndReAllocBuffer((LPVOID) lpCountryList, 
  1376.                              dwSizeofCountryList,
  1377.                              "SaveTapiLocationInfo");
  1378.  
  1379.     if (lpCountryList == NULL)
  1380.         return;
  1381.  
  1382.     /* Win95 doesn't return anything is CountryID is 1 */
  1383.     lReturn = (*cklineGetCountry)(osverinfo.dwPlatformId == 
  1384.                        VER_PLATFORM_WIN32_WINDOWS ? 0 
  1385.                        : tapiCountryID, TAPI_CURRENT_VERSION,
  1386.                        lpCountryList);
  1387.  
  1388.     if (HandleLineErr(lReturn))
  1389.         ;
  1390.     else
  1391.     {
  1392.         OutputDebugLineError(lReturn, 
  1393.                   "lineGetCountry unhandled error: ");
  1394.         LocalFree(lpCountryList);
  1395.         return;
  1396.     }
  1397.  
  1398.     if ((lpCountryList -> dwNeededSize) >
  1399.          (lpCountryList -> dwTotalSize))
  1400.     {
  1401.         dwSizeofCountryList = lpCountryList ->dwNeededSize;
  1402.         lReturn = -1; // Lets loop again.
  1403.     }
  1404.     }
  1405.     while(lReturn != SUCCESS);
  1406.  
  1407.     for ( i=0; i<lpCountryList->dwNumCountries; i++)
  1408.     {
  1409.         lpCountryEntry = (LPLINECOUNTRYENTRY) ((BYTE *)lpCountryList +
  1410.                         lpCountryList->dwCountryListOffset +
  1411.                         (i * sizeof(LINECOUNTRYENTRY)));
  1412.     if ( lpCountryEntry->dwCountryID == tapiCountryID )
  1413.         break;
  1414.     }
  1415.     if ( i == lpCountryList->dwNumCountries )
  1416.     lpCountryEntry = NULL;
  1417.  
  1418.     if ( lpCountryEntry ) {
  1419.     /* 'E' = Country Code */
  1420.     /* 'F' = Area Code    */
  1421.     /* 'G' = Local Number */
  1422.     strncpy(tapiCountryName,((LPSTR) lpCountryList +
  1423.                   lpCountryEntry->dwCountryNameOffset),
  1424.          lpCountryEntry->dwCountryNameSize);
  1425.     strncpy(tapiSameAreaRule,((LPSTR) lpCountryList +
  1426.                   lpCountryEntry->dwSameAreaRuleOffset),
  1427.          lpCountryEntry->dwSameAreaRuleSize);
  1428.     strncpy(tapiLongDistanceRule,((LPSTR) lpCountryList +
  1429.                   lpCountryEntry->dwLongDistanceRuleOffset),
  1430.          lpCountryEntry->dwLongDistanceRuleSize);
  1431.     strncpy(tapiInternationalRule,((LPSTR) lpCountryList +
  1432.                   lpCountryEntry->dwInternationalRuleOffset),
  1433.          lpCountryEntry->dwInternationalRuleSize);
  1434.     }
  1435.     else {
  1436.     tapiCountryName[0] = '\0';
  1437.     tapiSameAreaRule[0] = '\0';
  1438.     tapiLongDistanceRule[0] = '\0';
  1439.     tapiInternationalRule[0] = '\0';
  1440.     }
  1441.  
  1442.     strncpy(tapiAreaCode,
  1443.          (((LPSTR) lpTranslateCaps) +
  1444.            lpLocationEntry->dwCityCodeOffset),
  1445.          lpLocationEntry->dwCityCodeSize);
  1446.  
  1447.     tapiPreferredCardID = lpLocationEntry->dwPreferredCardID;
  1448.  
  1449.     tapiOptions = lpLocationEntry->dwOptions;
  1450.  
  1451.     strncpy(tapiLocalAccessCode, 
  1452.          (((LPSTR) lpTranslateCaps) +
  1453.            lpLocationEntry->dwLocalAccessCodeOffset),
  1454.          lpLocationEntry->dwLocalAccessCodeSize);
  1455.  
  1456.     strncpy(tapiLongDistAccessCode, 
  1457.          (((LPSTR) lpTranslateCaps) +
  1458.            lpLocationEntry->dwLongDistanceAccessCodeOffset),
  1459.          lpLocationEntry->dwLongDistanceAccessCodeSize);
  1460.  
  1461.     strncpy(tapiTollPrefixList, 
  1462.          (((LPSTR) lpTranslateCaps) +
  1463.            lpLocationEntry->dwTollPrefixListOffset),
  1464.          lpLocationEntry->dwTollPrefixListSize);
  1465.  
  1466.     strncpy(tapiCancelCallWaiting, 
  1467.          (((LPSTR) lpTranslateCaps) +
  1468.            lpLocationEntry->dwCancelCallWaitingOffset),
  1469.          lpLocationEntry->dwCancelCallWaitingSize);
  1470.  
  1471.     LocalFree(lpCountryList);
  1472. }
  1473.  
  1474. int 
  1475. cktapiFetchLocationInfoByName( char * CurrentLocation )
  1476. {
  1477.     LPLINETRANSLATECAPS lpTranslateCaps = NULL;
  1478.     DWORD dwSizeofTranslateCaps = sizeof(LINETRANSLATECAPS);
  1479.     long lReturn;
  1480.     DWORD dwCounter;
  1481.     LPLINELOCATIONENTRY lpLocationEntry;
  1482.     LPLINECARDENTRY lpLineCardEntry = NULL;
  1483.  
  1484.     /* If no name specified, use Current Location */
  1485.     if ( !CurrentLocation || !CurrentLocation[0] ) {
  1486.     int ID = cktapiGetCurrentLocationID();
  1487.     return cktapiFetchLocationInfoByID( ID );
  1488.     }
  1489.  
  1490.     // First, get the TRANSLATECAPS
  1491.     do
  1492.     {
  1493.     lpTranslateCaps = (LPLINETRANSLATECAPS) CheckAndReAllocBuffer(
  1494.                  (LPVOID) lpTranslateCaps, dwSizeofTranslateCaps,
  1495.                  "cktapiFetchLocationInfo");
  1496.  
  1497.     if (lpTranslateCaps == NULL)
  1498.         return FALSE;
  1499.  
  1500.     lReturn = (*cklineGetTranslateCaps)(g_hLineApp, TAPI_CURRENT_VERSION, 
  1501.                                       lpTranslateCaps);
  1502.  
  1503.     if (HandleLineErr(lReturn))
  1504.         ;
  1505.     else
  1506.     {
  1507.         OutputDebugLineError(lReturn, 
  1508.                   "lineGetTranslateCaps unhandled error: ");
  1509.         LocalFree(lpTranslateCaps);
  1510.         return FALSE;
  1511.     }
  1512.  
  1513.     if ((lpTranslateCaps -> dwNeededSize) >
  1514.          (lpTranslateCaps -> dwTotalSize))
  1515.     {
  1516.         dwSizeofTranslateCaps = lpTranslateCaps ->dwNeededSize;
  1517.         lReturn = -1; // Lets loop again.
  1518.     }
  1519.     }
  1520.     while(lReturn != SUCCESS);
  1521.  
  1522.     // Find the location information in the TRANSLATECAPS
  1523.     lpLocationEntry = (LPLINELOCATIONENTRY)
  1524.     (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset);
  1525.  
  1526.     // loop through all locations, looking for a location match
  1527.     for(dwCounter = 0; 
  1528.      dwCounter < lpTranslateCaps -> dwNumLocations;
  1529.      dwCounter++)
  1530.     {    
  1531.     if (_stricmp((((LPSTR) lpTranslateCaps) + 
  1532.                lpLocationEntry[dwCounter].dwLocationNameOffset),
  1533.               CurrentLocation)
  1534.          == 0)
  1535.     {    
  1536.         // Found it!  Set the current location, if necessary.
  1537.         int ID = cktapiGetCurrentLocationID();
  1538.         if ( ID != lpLocationEntry[dwCounter].dwPermanentLocationID )
  1539.         {
  1540.         lReturn = 
  1541.             (*cklineSetCurrentLocation)(g_hLineApp,
  1542.             lpLocationEntry[dwCounter].dwPermanentLocationID);
  1543.         OutputDebugLastError(lReturn,"lineSetCurrentLocation:");
  1544.         }
  1545.         break;
  1546.     }
  1547.     }
  1548.  
  1549.     // Was a match for lpszCurrentLocation found?
  1550.     if (lpLocationEntry[dwCounter].dwPreferredCardID == MAXDWORD)
  1551.     {
  1552.     LocalFree(lpTranslateCaps);
  1553.     return FALSE;
  1554.     }
  1555.  
  1556.     SaveTapiLocationInfo( lpTranslateCaps, &lpLocationEntry[dwCounter] );
  1557.     LocalFree(lpTranslateCaps);
  1558.     return TRUE;
  1559. }
  1560.  
  1561. int 
  1562. cktapiFetchLocationInfoByID( int LocationID )
  1563. {
  1564.     LPLINETRANSLATECAPS lpTranslateCaps = NULL;
  1565.     DWORD dwSizeofTranslateCaps = sizeof(LINETRANSLATECAPS);
  1566.     long lReturn;
  1567.     DWORD dwCounter;
  1568.     LPLINELOCATIONENTRY lpLocationEntry;
  1569.     LPLINECARDENTRY lpLineCardEntry = NULL;
  1570.  
  1571.    // First, get the TRANSLATECAPS
  1572.    do
  1573.    {
  1574.       lpTranslateCaps = (LPLINETRANSLATECAPS) CheckAndReAllocBuffer(
  1575.                  (LPVOID) lpTranslateCaps, dwSizeofTranslateCaps,
  1576.                  "cktapiFetchLocationInfo");
  1577.  
  1578.       if (lpTranslateCaps == NULL)
  1579.          return FALSE;
  1580.  
  1581.       lReturn = (*cklineGetTranslateCaps)(g_hLineApp, TAPI_CURRENT_VERSION, 
  1582.                                       lpTranslateCaps);
  1583.  
  1584.       if (HandleLineErr(lReturn))
  1585.          ;
  1586.       else
  1587.       {
  1588.          OutputDebugLineError(lReturn, 
  1589.                                "lineGetTranslateCaps unhandled error: ");
  1590.          LocalFree(lpTranslateCaps);
  1591.          return FALSE;
  1592.       }
  1593.  
  1594.       if ((lpTranslateCaps -> dwNeededSize) >
  1595.            (lpTranslateCaps -> dwTotalSize))
  1596.       {
  1597.          dwSizeofTranslateCaps = lpTranslateCaps ->dwNeededSize;
  1598.          lReturn = -1; // Lets loop again.
  1599.       }
  1600.    }
  1601.    while(lReturn != SUCCESS);
  1602.  
  1603.    // Find the location information in the TRANSLATECAPS
  1604.    lpLocationEntry = (LPLINELOCATIONENTRY)
  1605.       (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset);
  1606.  
  1607.     // If lpszCurrentLocation, then make that location 'current'
  1608.     if (LocationID == -1)
  1609.     {
  1610.     LocationID = cktapiGetCurrentLocationID();
  1611.     }
  1612.     // loop through all locations, looking for a location match
  1613.     for(dwCounter = 0; 
  1614.      dwCounter < lpTranslateCaps -> dwNumLocations;
  1615.      dwCounter++)
  1616.     {    
  1617.     if ( LocationID == lpLocationEntry[dwCounter].dwPermanentLocationID )
  1618.     {
  1619.         // Found it!  Set the current location, if necessary.
  1620.         int ID = cktapiGetCurrentLocationID();
  1621.         if ( ID != lpLocationEntry[dwCounter].dwPermanentLocationID )
  1622.         {
  1623.         lReturn = 
  1624.             (*cklineSetCurrentLocation)(g_hLineApp,
  1625.             lpLocationEntry[dwCounter].dwPermanentLocationID);
  1626.         OutputDebugLastError(lReturn,"lineSetCurrentLocation:");
  1627.         }
  1628.         break;    
  1629.     }
  1630.     }
  1631.  
  1632.     // Was a match for lpszCurrentLocation found?
  1633.     if (lpLocationEntry[dwCounter].dwPreferredCardID == MAXDWORD)
  1634.     {
  1635.     LocalFree(lpTranslateCaps);
  1636.     return FALSE;
  1637.     }
  1638.  
  1639.     SaveTapiLocationInfo( lpTranslateCaps, &lpLocationEntry[dwCounter] );
  1640.     LocalFree(lpTranslateCaps);
  1641.     return TRUE;
  1642. }
  1643.  
  1644.  
  1645. cktapiSetCurrentLocationID( DWORD ID )
  1646. {
  1647.     long lReturn;
  1648.     lReturn = 
  1649.     (*cklineSetCurrentLocation)(g_hLineApp, ID);
  1650.     return (lReturn == SUCCESS);
  1651. }
  1652.  
  1653. void
  1654. CopyTapiLocationInfoToKermitDialCmd( void )
  1655. {
  1656. }
  1657.  
  1658. #ifdef COMMENT
  1659. void
  1660. CopyTapiLocationInfoToKermitDialCmd( void )
  1661. {
  1662.     extern char *dialnpr;        /* DIAL PREFIX */
  1663.     extern char *diallac;        /* DIAL LOCAL-AREA-CODE */
  1664.     extern char *diallcc;        /* DIAL LOCAL-COUNTRY-CODE */
  1665.     extern char *dialixp;        /* DIAL INTL-PREFIX */
  1666.     extern char *dialixs;        /* DIAL INTL-SUFFIX */
  1667.     extern char *diallcp;        /* DIAL LOCAL-PREFIX */
  1668.     extern char *diallcs;        /* DIAL LOCAL-SUFFIX */
  1669.     extern char *dialldp;        /* DIAL LD-PREFIX */
  1670.     extern char *diallds;        /* DIAL LD-SUFFIX */
  1671.     extern char *dialpxx;        /* DIAL PBX-EXCHANGE */
  1672.     extern char *dialpxi;        /* DIAL INTERNAL-PREFIX */
  1673.     extern char *dialpxo;        /* DIAL OUTSIDE-PREFIX */
  1674.     extern char *dialsfx;        /* DIAL SUFFIX */
  1675.     extern char *dialtfp;        /* DIAL TOLL-FREE-PREFIX */
  1676.     extern int dialmth;            /* DIAL METHOD TONE/PULSE */
  1677.  
  1678.     char * p = NULL;
  1679.  
  1680.     /* Make sure there are valid values */
  1681.     if ( tapilocid == -1 ) {
  1682.     tapilocid = cktapiGetCurrentLocationID();
  1683.     cktapiFetchLocationInfoByID( tapilocid );
  1684.     if ( tapilocid == -1 )
  1685.         return;
  1686.     }
  1687.  
  1688.     /* Local Country Code */
  1689.     if ( diallcc )
  1690.     free( diallcc );
  1691.     diallcc = (char *) malloc( 20 ) ;
  1692.     if ( !diallcc )
  1693.     return;
  1694.     _itoa( tapiCountryCode, diallcc, 10 );
  1695.  
  1696.     /* Local Area Code */
  1697.     if ( diallac )
  1698.     free(diallac);
  1699.     diallac = strdup( tapiAreaCode );
  1700.  
  1701.     /* Long Distance Prefix */
  1702.     if ( dialldp )
  1703.     free(dialldp);
  1704.     /* The true Long Distance Prefix is the tapiLongDistAccessCode */
  1705.     /* plus the prefix portion of the tapiLongDistanceRule         */
  1706.     dialldp = (char *) malloc(strlen(tapiLongDistAccessCode) + 
  1707.                    strlen(tapiLongDistanceRule) + 1);
  1708.     if ( dialldp ) {
  1709.     strcpy(dialldp,tapiLongDistAccessCode);
  1710.     strcat(dialldp,tapiLongDistanceRule);
  1711.     p = dialldp;
  1712.     /* find the end of the prefix and null terminate it */
  1713.     while ( *p && *p != 'E' && *p != 'F' && *p != 'G' ) 
  1714.         p++;
  1715.     *p = '\0';
  1716.     }
  1717.     
  1718.     /* The Long Distance Suffix is the suffix portion of the       */
  1719.     /* tapiLongDistanceRule (if any)                    */
  1720.     if ( diallds )
  1721.     free(diallds);
  1722.     diallds = strdup( tapiLongDistanceRule );
  1723.     if ( diallds ) {
  1724.     p = diallds;
  1725.     /* blank out the prefix */
  1726.     while ( *p && *p != 'E' && *p != 'F' && *p != 'G' ) {
  1727.         *p = ' ';
  1728.         p++;
  1729.     }
  1730.     /* and then the dialing rule */
  1731.     while ( *p == 'E' || *p == 'F' || *p == 'G' ) {
  1732.         *p = ' ';
  1733.         p++;
  1734.     }
  1735.     if ( *p == '\0' ) {
  1736.         free(diallds);
  1737.         diallds = NULL;
  1738.     }
  1739.     }
  1740.  
  1741.     /* The International Prefix is the prefix portion of the       */
  1742.     /* tapiInternationalRule         */
  1743.     if ( dialixp )
  1744.     free(dialixp);
  1745.     /* The true International Prefix is the tapiLongDistAccessCode */
  1746.     /* plus the prefix portion of the tapiInternationalRule        */
  1747.     dialixp = (char *) malloc(strlen(tapiLongDistAccessCode) + 
  1748.                    strlen(tapiInternationalRule) + 1);
  1749.     if ( dialixp ) {
  1750.     strcpy(dialixp,tapiLongDistAccessCode);
  1751.     strcat(dialixp,tapiInternationalRule);
  1752.     p = dialixp;
  1753.     /* find the end of the prefix and null terminate it */
  1754.     while ( *p && *p != 'E' && *p != 'F' && *p != 'G' ) 
  1755.         p++;
  1756.     *p = '\0';
  1757.     }
  1758.     
  1759.     /* The International Suffix is the suffix portion of the       */
  1760.     /* tapiInternationalRule (if any)                    */
  1761.     if ( dialixs )
  1762.     free(dialixs);
  1763.     dialixs = strdup( tapiInternationalRule );
  1764.     if ( dialixs ) {
  1765.     p = dialixs;
  1766.     /* blank out the prefix */
  1767.     while ( *p && *p != 'E' && *p != 'F' && *p != 'G' ) {
  1768.         *p = ' ';
  1769.         p++;
  1770.     }
  1771.     /* and then the dialing rule */
  1772.     while ( *p == 'E' || *p == 'F' || *p == 'G' ) {
  1773.         *p = ' ';
  1774.         p++;
  1775.     }
  1776.     if ( *p == '\0' ) {
  1777.         free(dialixs);
  1778.         dialixs = NULL;
  1779.     }
  1780.     }
  1781.  
  1782.     /* We currently ignore the tapiLocalAccessCode                 */
  1783.     /* Local Prefix */
  1784.     if ( diallcp )
  1785.     free(diallcp);
  1786.     /* The true Local Prefix is the tapiLocalAccessCode */
  1787.     /* plus the prefix portion of the tapiSameAreaRule         */
  1788.     diallcp = (char *) malloc(strlen(tapiLocalAccessCode) + 
  1789.                    strlen(tapiSameAreaRule) + 1);
  1790.     if ( diallcp ) {
  1791.     strcpy(diallcp,tapiLocalAccessCode);
  1792.     strcat(diallcp,tapiSameAreaRule);
  1793.     p = diallcp;
  1794.     /* find the end of the prefix and null terminate it */
  1795.     while ( *p && *p != 'E' && *p != 'F' && *p != 'G' ) 
  1796.         p++;
  1797.     *p = '\0';
  1798.     }
  1799.     
  1800.     /* The Local Access Suffix is the suffix portion of the       */
  1801.     /* tapiLocalAccessRule (if any)                    */
  1802.     if ( diallcs )
  1803.     free(diallcs);
  1804.     diallcs = strdup( tapiSameAreaRule );
  1805.     if ( diallcs ) {
  1806.     p = diallcs;
  1807.     /* blank out the prefix */
  1808.     while ( *p && *p != 'E' && *p != 'F' && *p != 'G' ) {
  1809.         *p = ' ';
  1810.         p++;
  1811.     }
  1812.     /* and then the dialing rule */
  1813.     while ( *p == 'E' || *p == 'F' || *p == 'G' ) {
  1814.         *p = ' ';
  1815.         p++;
  1816.     }
  1817.     if ( *p == '\0' ) {
  1818.         free(diallcs);
  1819.         diallcs = NULL;
  1820.     }
  1821.     }
  1822.  
  1823.     /* All purpose Prefix */
  1824.     if ( dialnpr )
  1825.     free( dialnpr );
  1826.     dialnpr = strdup( tapiCancelCallWaiting );
  1827.  
  1828.     /* Pulse Dialing? */
  1829.     if ( tapiOptions & LINELOCATIONOPTION_PULSEDIAL )
  1830.     dialmth = XYDM_P;
  1831.     else
  1832.     dialmth = XYDM_T;
  1833. }
  1834. #endif /* COMMENT */
  1835.  
  1836. typedef struct tagCommID {
  1837.     HANDLE hModem ;
  1838.     char szModemName[1] ;
  1839. } CommID ;
  1840.  
  1841. HANDLE
  1842. GetModemHandleFromLine( HLINE hLine )
  1843. {
  1844.     CommID * cid;
  1845.     VARSTRING *vs;
  1846.     ULONG lrc ;
  1847.     DWORD dwSize;
  1848.     HANDLE hModem ;
  1849.  
  1850.     if ( hLine == NULL )
  1851.     hLine = g_hLine;
  1852.  
  1853.     if ( hLine == NULL )
  1854.     return NULL;
  1855.  
  1856.     /* The next four lines prepare a VARSTRING structure to
  1857.     pass to Windows though lineGetID */
  1858.     vs = (VARSTRING *) malloc (1024);
  1859.     if ( !vs )
  1860.     return NULL;
  1861.     memset(vs,0,1024);
  1862.     vs->dwTotalSize = 1024;
  1863.  
  1864.     do {
  1865.         /* get modem handle associated with the line */
  1866.     lrc = (*cklineGetID)(hLine, 0L, NULL,
  1867.                   LINECALLSELECT_LINE,
  1868.                   vs, "comm/datamodem") ;
  1869.     if ( ( lrc == LINEERR_STRUCTURETOOSMALL || lrc == 0 ) &&
  1870.          (vs->dwTotalSize < vs->dwNeededSize) ) {
  1871.         /* the next six lines reallocate the VARSTRING */
  1872.         dwSize = vs->dwNeededSize ;
  1873.         free(vs);
  1874.         vs = (VARSTRING *) malloc(dwSize);
  1875.         if ( !vs )
  1876.         return NULL;
  1877.         memset(vs,0,sizeof(vs));
  1878.         vs->dwTotalSize = dwSize ;
  1879.     }
  1880.     else if ( lrc ) {
  1881.         /* some kind of TAPI error */
  1882.         OutputDebugLastError(lrc,"lineGetID:");
  1883.         free(vs);
  1884.         return NULL;
  1885.     }
  1886.     else 
  1887.         break;  /* success */
  1888.     } while ( TRUE );
  1889.  
  1890.     cid = (CommID *) ((LPSTR)vs + vs->dwStringOffset);
  1891.  
  1892.     if ( !cid->hModem ) {
  1893.     SECURITY_ATTRIBUTES security ;
  1894.  
  1895.     security.nLength = sizeof(SECURITY_ATTRIBUTES);
  1896.     security.lpSecurityDescriptor = NULL ;
  1897.     security.bInheritHandle = TRUE ;
  1898.     strcpy( szModemName, "\\\\.\\" ) ;
  1899.     strcat( szModemName, &cid->szModemName[0] ) ;
  1900.     hModem = CreateFile( szModemName, 
  1901.                  GENERIC_READ | GENERIC_WRITE,
  1902.                  TRUE, /* do not share */
  1903.                  &security,          
  1904.                  OPEN_EXISTING,
  1905.                  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  1906.                  NULL);
  1907.     }
  1908.     else {
  1909.     lstrcpy( szModemName, &cid->szModemName[0] ) ;
  1910.     hModem = cid->hModem ;
  1911.     }
  1912.  
  1913.     free(vs);
  1914.     return hModem;
  1915. }
  1916.  
  1917. void
  1918. cktapiConfigureLine( int lineID )
  1919. {
  1920.     LPVARSTRING lpVarString = NULL;
  1921.     DWORD dwSizeofVarString = sizeof(VARSTRING) + 1024;
  1922.     LPCSTR binaryConfigString=NULL;
  1923.     LONG lReturn=-1;
  1924.  
  1925.     if ( !cktapiopen() )
  1926.     return;
  1927.  
  1928.     if ( lineID == -1 )
  1929.     lineID = LineDeviceId;
  1930.  
  1931.     debug(F111,"TAPI Configure Line Dialog","lineID",lineID);
  1932.     (*cklineConfigDialog)( lineID, hwndConsole, NULL );
  1933.  
  1934.     do
  1935.     {
  1936.     if ( lpVarString != NULL )
  1937.         free(lpVarString);
  1938.  
  1939.     // Allocate the VARSTRING structure
  1940.     lpVarString = malloc( dwSizeofVarString ) ;
  1941.     if (lpVarString == NULL)
  1942.         goto ErrorConfiguring;
  1943.     lpVarString->dwTotalSize = dwSizeofVarString;
  1944.  
  1945.     // Fill the VARSTRING structure
  1946.     lReturn = (*cklineGetDevConfig)( lineID, lpVarString, "comm/datamodem" );
  1947.     OutputDebugLastError(lReturn,"lineGetDevConfig:");
  1948.  
  1949.     if (HandleLineErr(lReturn))
  1950.         ; // Still need to check if structure was big enough.
  1951.         else
  1952.         {
  1953.         OutputDebugLineError(lReturn, 
  1954.                       "lineGetDevConfig unhandled error: ");
  1955.         goto ErrorConfiguring;
  1956.         }
  1957.  
  1958.     // If the VARSTRING wasn't big enough, loop again.
  1959.     if ((lpVarString -> dwNeededSize) > (lpVarString -> dwTotalSize))
  1960.     {
  1961.         dwSizeofVarString = lpVarString -> dwNeededSize;
  1962.         lReturn = -1; // Lets loop again.
  1963.     }
  1964.     }
  1965.     while(lReturn != SUCCESS);
  1966.  
  1967.     /* See cktapiGetModemSettings; we may know the format of this string */
  1968.     binaryConfigString = ((LPCSTR)((LPBYTE)lpVarString +
  1969.                     lpVarString->dwStringOffset));   
  1970.     
  1971.     ErrorConfiguring:
  1972.     if (lpVarString)
  1973.     free(lpVarString);
  1974.  
  1975.     cktapiclose();
  1976. }
  1977.  
  1978. void
  1979. cktapiDialingProp( void )
  1980. {
  1981.     DWORD dwAPIVersion ;                    
  1982.     LINEEXTENSIONID ExtensionID ;
  1983.     LONG rc;
  1984.     int ID;
  1985.  
  1986.     if ( !cktapiopen() )
  1987.     return;
  1988.  
  1989.     debug(F111,"TAPI Dialing Properties Dialog","device ID",LineDeviceId);
  1990.     rc = (*cklineNegotiateAPIVersion)(g_hLineApp, 
  1991.                        LineDeviceId == -1 ? 0 : LineDeviceId,
  1992.                        TAPI_CURRENT_VERSION, 
  1993.                        TAPI_CURRENT_VERSION,
  1994.                        &dwAPIVersion, &ExtensionID);
  1995.     rc = (*cklineTranslateDialog)( g_hLineApp, 
  1996.                    LineDeviceId == -1 ? 0 : LineDeviceId,
  1997.                    dwAPIVersion, hwndConsole, NULL );
  1998.     ID = cktapiGetCurrentLocationID();
  1999.     cktapiFetchLocationInfoByID( ID );
  2000.     cktapiclose();
  2001. }
  2002.  
  2003. int 
  2004. cktapiConvertPhoneNumber(char * source, char ** converted)
  2005. {
  2006.     DWORD dwAPIVersion ;                    
  2007.     LINEEXTENSIONID ExtensionID ;
  2008.     DWORD dwCard=0;
  2009.     DWORD dwTranslateOptions=LINETRANSLATEOPTION_CANCELCALLWAITING;
  2010.     LPLINETRANSLATEOUTPUT lplineTranslateOutput=NULL;
  2011.     DWORD dwSize=0;
  2012.     LONG rc = 0;
  2013.  
  2014.     if ( !cktapiopen() )
  2015.     return FALSE;
  2016.  
  2017.     rc = (*cklineNegotiateAPIVersion)(g_hLineApp, 
  2018.                        LineDeviceId == -1 ? 0 : LineDeviceId,
  2019.                        TAPI_CURRENT_VERSION, 
  2020.                        TAPI_CURRENT_VERSION,
  2021.                        &dwAPIVersion, &ExtensionID);
  2022.     if ( rc ) {
  2023.     cktapiclose();
  2024.     return FALSE;
  2025.     }
  2026.     dwSize = sizeof(LINETRANSLATEOUTPUT);
  2027.     lplineTranslateOutput = (LPLINETRANSLATEOUTPUT) malloc( dwSize ) ;
  2028.     if ( !lplineTranslateOutput ) {
  2029.     cktapiclose();
  2030.     return FALSE;
  2031.     }
  2032.     memset(lplineTranslateOutput,0,dwSize);
  2033.     lplineTranslateOutput->dwTotalSize = dwSize ;
  2034.  
  2035.     do {
  2036.     rc = (*cklineTranslateAddress)(g_hLineApp,
  2037.                     LineDeviceId == -1 ? 0 : LineDeviceId,
  2038.                     dwAPIVersion, 
  2039.                     source,
  2040.                     dwCard,
  2041.                     dwTranslateOptions,
  2042.                     lplineTranslateOutput
  2043.                     );
  2044.     if ( ( rc == LINEERR_STRUCTURETOOSMALL || rc == 0 ) &&
  2045.          (lplineTranslateOutput->dwTotalSize < lplineTranslateOutput->dwNeededSize) ) {
  2046.         /* the next six lines reallocate the LINETRANSLATEOUTPUT struct */
  2047.         dwSize = lplineTranslateOutput->dwNeededSize ;
  2048.         free(lplineTranslateOutput);
  2049.         lplineTranslateOutput = (LPLINETRANSLATEOUTPUT) malloc( dwSize ) ;
  2050.         if ( !lplineTranslateOutput ) {
  2051.         cktapiclose();
  2052.         return FALSE;
  2053.         }
  2054.         memset(lplineTranslateOutput,0,dwSize);
  2055.         lplineTranslateOutput->dwTotalSize = dwSize ;
  2056.     }
  2057.     else if ( rc ) {
  2058.         /* some kind of TAPI error */
  2059.         OutputDebugLastError(rc,"lineTranslateAddress:");
  2060.         free(lplineTranslateOutput);
  2061.         cktapiclose();
  2062.         return FALSE;
  2063.     }
  2064.     else 
  2065.         break;  /* success */
  2066.     } while ( TRUE );
  2067.  
  2068.     /* we now have the result, lets do something with it */
  2069.     *converted = (char *) malloc( lplineTranslateOutput->dwDialableStringSize+1);
  2070.     strncpy( *converted, (LPCSTR) lplineTranslateOutput + 
  2071.              lplineTranslateOutput->dwDialableStringOffset,
  2072.          lplineTranslateOutput->dwDialableStringSize);
  2073.     (*converted)[lplineTranslateOutput->dwDialableStringSize]='\0';
  2074.  
  2075.     free(lplineTranslateOutput);
  2076.     cktapiclose();
  2077.  
  2078.     return TRUE;
  2079. }
  2080.  
  2081. int
  2082. tapi_open( char * devicename )
  2083. {
  2084.     extern struct keytab * tapilinetab ;
  2085.     extern int ntapiline ;
  2086.     int i ;
  2087.     LINEEXTENSIONID ExtId ;
  2088.     int rc ;
  2089.     LPDEVCFG        lpDevCfg = NULL;
  2090.     LPCOMMCONFIG    lpCommConfig = NULL;
  2091.     LPMODEMSETTINGS lpModemSettings = NULL;
  2092.     DCB *           lpDCB = NULL;
  2093.  
  2094.     if ( !cktapiopen() )
  2095.     {
  2096.     return -1;
  2097.     }
  2098.  
  2099.     /* Find the Line ID */
  2100.     for ( i=0 ; i<ntapiline ; i++ )
  2101.     {
  2102.     if ( !strcmp( devicename, tapilinetab[i].kwd ) )
  2103.     {
  2104.         LineDeviceId = tapilinetab[i].kwval ;
  2105.         break;
  2106.     }
  2107.     }
  2108.  
  2109.     if ( i == ntapiline )
  2110.     {
  2111.     cktapiclose();
  2112.     return -1 ;
  2113.     }
  2114.  
  2115.     /* Negotiate API Version for the Line Device */
  2116.     {
  2117.     rc = (*cklineNegotiateAPIVersion)( g_hLineApp, LineDeviceId,
  2118.                        TAPI_CURRENT_VERSION, TAPI_CURRENT_VERSION,
  2119.                        &LineDeviceAPIVersion, 
  2120.                        &ExtId ) ;
  2121.     if ( rc < 0 )
  2122.     {
  2123.         cktapiclose();
  2124.         return -1;
  2125.     }
  2126.     }
  2127.  
  2128.     /* Get Line Device Capabilities */
  2129.     {
  2130.     /* The line device capabilities have already been placed into */
  2131.     /* g_lpLineDevCaps[LineDeviceId]                              */
  2132.     }
  2133.  
  2134.     /* Get Addresses and Media modes */
  2135.     {
  2136.     LineAddressCount = g_lpLineDevCaps[LineDeviceId]->dwNumAddresses ;
  2137.     LineMediaModes = g_lpLineDevCaps[LineDeviceId]->dwMediaModes ;
  2138.     }
  2139.  
  2140.     if ( g_hLine == NULL ) {
  2141.     /* Call lineOpen() */
  2142.     rc = -1 ;
  2143.     while ( rc < 0 )
  2144.     {
  2145.         rc = (*cklineOpen)( g_hLineApp, LineDeviceId, &g_hLine, 
  2146.                 LineDeviceAPIVersion, 0,
  2147.                 (DWORD) hInstance, 
  2148.                 LINECALLPRIVILEGE_OWNER | LINECALLPRIVILEGE_MONITOR,
  2149.                 LINEMEDIAMODE_DATAMODEM,
  2150.                 NULL);
  2151.         OutputDebugLastError(rc,"lineOpen:");
  2152.         switch ( rc ) {
  2153.         case LINEERR_ALLOCATED:
  2154.         cktapiclose();
  2155.         return -1;
  2156.  
  2157.         default:
  2158.         if ( HandleLineErr(rc) )
  2159.         {
  2160.             continue;
  2161.         }
  2162.         else 
  2163.         {
  2164.             debug(F111,"TAPI lineOpen","g_hLine",g_hLine);
  2165.             g_hLine = NULL;
  2166.             cktapiclose();
  2167.             return -1;
  2168.         }    
  2169.         }
  2170.     }
  2171.     }
  2172.  
  2173.     /* Specify which event messages we are interested in */
  2174.     rc = (*cklineSetStatusMessages)(g_hLine, 
  2175.                      LINEDEVSTATE_CONNECTED | 
  2176.                      LINEDEVSTATE_DISCONNECTED |
  2177.                      LINEDEVSTATE_OUTOFSERVICE |
  2178.                      LINEDEVSTATE_MAINTENANCE |
  2179.                      LINEDEVSTATE_OPEN |
  2180.                      LINEDEVSTATE_CLOSE |
  2181.                      LINEDEVSTATE_RINGING |
  2182.                      LINEDEVSTATE_OTHER |
  2183.                      LINEDEVSTATE_REINIT,
  2184.                      0);
  2185.     OutputDebugLastError(rc,"lineSetStatusMessages:");
  2186.     if ( rc )
  2187.     {
  2188.     cktapiclose();
  2189.     return -1 ;
  2190.     }
  2191.     ttyfd = -2;            /* We don't have a real handle yet */
  2192.  
  2193.     /* Do this just to set the name of the Modem */
  2194.     CloseHandle( GetModemHandleFromLine( g_hLine ) );
  2195.     return 0;
  2196. }
  2197.  
  2198.  
  2199. int 
  2200. tapi_clos( void ) 
  2201. {
  2202.    cktapiclose() ;
  2203.    return -1;
  2204. }
  2205.  
  2206. int
  2207. cktapiCallInProgress( void )
  2208. {
  2209.     LPLINEDEVSTATUS lpLineDevStatus=NULL;
  2210.     DWORD dwSizeofLineDevStatus = sizeof(LINEDEVSTATUS);
  2211.     LONG lReturn;
  2212.     int InProgress = TRUE;
  2213.  
  2214.     if ( g_hCall != NULL )
  2215.     return FALSE;
  2216.  
  2217.     if ( g_hLine == NULL )
  2218.     return TRUE;
  2219.  
  2220.     do
  2221.     {
  2222.     lpLineDevStatus = 
  2223.         (LPLINEDEVSTATUS) CheckAndReAllocBuffer((LPVOID) lpLineDevStatus, 
  2224.                              dwSizeofLineDevStatus,
  2225.                              "cktapiCallInProgress");
  2226.     if (lpLineDevStatus == NULL)
  2227.     {
  2228.         return TRUE;
  2229.     }
  2230.  
  2231.     lReturn = (*cklineGetLineDevStatus)(g_hLine, lpLineDevStatus);
  2232.     if (HandleLineErr(lReturn))
  2233.         ;
  2234.     else
  2235.     {
  2236.         OutputDebugLineError(lReturn, 
  2237.                   "lineGetDevStatus unhandled error: ");
  2238.         LocalFree(lpLineDevStatus);
  2239.         return TRUE;
  2240.     }
  2241.  
  2242.     if ((lpLineDevStatus -> dwNeededSize) >
  2243.          (lpLineDevStatus -> dwTotalSize))
  2244.     {
  2245.         dwSizeofLineDevStatus = lpLineDevStatus ->dwNeededSize;
  2246.         lReturn = -1; // Lets loop again.
  2247.     }
  2248.     }
  2249.     while(lReturn != SUCCESS);
  2250.  
  2251.     InProgress = lpLineDevStatus->dwNumActiveCalls 
  2252.     + lpLineDevStatus->dwNumOnHoldCalls 
  2253.         + lpLineDevStatus->dwNumOnHoldPendCalls
  2254.         - (g_hCall!=NULL?1:0);
  2255.  
  2256.     LocalFree( lpLineDevStatus );
  2257.     return InProgress;
  2258. }
  2259.  
  2260. int
  2261. cktapiGetModemSettings( LPDEVCFG * lppDevCfg, 
  2262.             LPMODEMSETTINGS * lppModemSettings,
  2263.             LPCOMMCONFIG * lppCommConfig,
  2264.             DCB **     lppDCB )
  2265. {
  2266.     static VARSTRING *vs=NULL;
  2267.     DWORD dwSize=0;
  2268.     ULONG lrc=0 ;
  2269.     LPDEVCFG        lpDevCfg = NULL;
  2270.     LPCOMMCONFIG    lpCommConfig = NULL;
  2271.     LPMODEMSETTINGS lpModemSettings = NULL;
  2272.     DCB *           lpDCB = NULL;
  2273.  
  2274.     if ( lppDevCfg )
  2275.     *lppDevCfg = NULL;
  2276.     if ( lppCommConfig )
  2277.     *lppCommConfig = NULL;
  2278.     if ( lppDCB )
  2279.     *lppDCB = NULL;
  2280.     if ( lppModemSettings )
  2281.     *lppModemSettings = NULL;
  2282.     
  2283.     if ( vs != NULL ) {            /* free previous VARSTRING */
  2284.     free(vs);
  2285.     vs = NULL;
  2286.     }
  2287.  
  2288.     if ( g_hLine == NULL )
  2289.     return FALSE;
  2290.  
  2291.     /* The next four lines prepare a VARSTRING structure to
  2292.     pass to Windows though lineGetID */
  2293.     vs = (VARSTRING *) malloc (1024);
  2294.     if ( !vs ) {
  2295.     return FALSE;
  2296.     }
  2297.     memset(vs,0,1024);
  2298.     vs->dwTotalSize = 1024;
  2299.  
  2300.     do {
  2301.         /* get Modem Device Configuration */
  2302.     lrc = (*cklineGetDevConfig)( LineDeviceId, vs, "comm/datamodem" );
  2303.     if ( ( lrc == LINEERR_STRUCTURETOOSMALL || lrc == 0 ) &&
  2304.          (vs->dwTotalSize < vs->dwNeededSize) ) {
  2305.         /* the next six lines reallocate the VARSTRING */
  2306.         dwSize = vs->dwNeededSize ;
  2307.         free(vs);
  2308.         vs = (VARSTRING *) malloc(dwSize);
  2309.         if ( !vs ) {
  2310.         return FALSE;
  2311.         }
  2312.         memset(vs,0,sizeof(vs));
  2313.         vs->dwTotalSize = dwSize ;
  2314.     }
  2315.     else if ( lrc ) {
  2316.         /* some kind of TAPI error */
  2317.         OutputDebugLastError(lrc,"lineGetDevConfig:");
  2318.         free(vs);
  2319.         return FALSE;
  2320.     }
  2321.     else 
  2322.         break;  /* success */
  2323.     } while ( TRUE );
  2324.  
  2325.     lpDevCfg     = (LPDEVCFG) ((LPSTR)vs + vs->dwStringOffset);
  2326.     if ( lpDevCfg == NULL ) {
  2327.     free(vs);
  2328.     return FALSE;
  2329.     }
  2330.  
  2331.     lpCommConfig = (LPCOMMCONFIG) &lpDevCfg->commconfig;
  2332.  
  2333.     lpDCB = &lpCommConfig->dcb;
  2334.  
  2335.     lpModemSettings = (LPMODEMSETTINGS)((LPSTR)lpCommConfig +
  2336.                      lpCommConfig->dwProviderOffset);
  2337.  
  2338.     if ( lppDevCfg )
  2339.     *lppDevCfg = lpDevCfg;
  2340.     if ( lppCommConfig )
  2341.     *lppCommConfig = lpCommConfig;
  2342.     if ( lppDCB )
  2343.     *lppDCB = lpDCB;
  2344.     if ( lppModemSettings )
  2345.     *lppModemSettings = lpModemSettings;
  2346.     return TRUE;
  2347. }
  2348.  
  2349. #endif /* CK_TAPI */
  2350.