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

  1. /* C K N T A P  --  Kermit Telephony interface for MS Win32 TAPI systems */
  2.  
  3. /*
  4.   Author: Jeffrey E Altman (jaltman@secure-endpoints.com),
  5.             Secure Endpoints Inc., New York City.
  6.  
  7.   Copyright (C) 1985, 2004, 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. #include "ckntap.h"             /* Kermit Telephony */
  29. #include "cknwin.h"
  30.  
  31. #ifdef CK_TAPI
  32.  
  33. _PROTOTYP( char * cktapiErrorString, (DWORD));
  34.  
  35. extern int tttapi ;                     /* is Line TAPI ? */
  36. extern struct keytab * tapilinetab, * tapilocationtab ;
  37. extern int ntapiline, ntapilocation ;
  38. extern long speed;
  39. extern int parity, flow;
  40. #ifndef NODIAL
  41. extern int dialdpy;
  42. extern int
  43. dialidt,                        /* DIAL IGNORE-DIAL-TONE */
  44. dialec,                         /* DIAL ERROR-CORRECTION */
  45. dialdc,                         /* DIAL COMPRESSION  */
  46. dialfc,                         /* DIAL FLOW-CONTROL */
  47. dialmth,                        /* DIAL METHOD */
  48. dialmauto,                      /* DIAL METHOD AUTO */
  49. mdmspd,                         /* SPEED-MATCHING */
  50. mdmspk,                         /* SPEAKER ON/OFF */
  51. mdmvol;                         /* SPEAKER VOLUME */
  52. extern int waitct;                  /* DIAL TIMEOUT */
  53. extern MDMINF *modemp[];
  54. extern MDMINF GENERIC;
  55. #else /* NODIAL */
  56. int dialdpy = 0;
  57. int waitct = 254;
  58. #endif /* NODIAL */
  59.  
  60. HINSTANCE hLib = NULL ;
  61. extern HINSTANCE hInstance ;
  62. extern HWND hwndConsole ;
  63. extern char * termessage ;
  64. #ifndef NODIAL
  65. /*  Failure codes from ckudia.c */
  66. extern int fail_code;
  67.  
  68. #define F_TIME          1               /* timeout */
  69. #define F_INT           2               /* interrupt */
  70. #define F_MODEM         3               /* modem-detected failure */
  71. #define F_MINIT         4               /* cannot initialize modem */
  72. #endif /* NODIAL */
  73.  
  74. int tapiopen = 0;
  75. int tapipass = CK_ON ;                  /* TAPI Passthrough mode */
  76. int tapiconv = CK_AUTO ;                /* TAPI Conversion mode */
  77. int tapilights = TRUE;
  78. int tapipreterm = FALSE;
  79. int tapipostterm = FALSE;
  80. int tapimanual = FALSE;
  81. int tapiinactivity = 0;
  82. int tapibong = 8;
  83. int tapiusecfg = CK_OFF;
  84.  
  85. /* TAPI Location Information */
  86. char tapiloc[257] = "" ;
  87. int tapilocid = -1 ;
  88.  
  89. DWORD  tapiCountryID = -1 ;
  90. char   tapiAreaCode[65] = "" ;
  91. DWORD  tapiPreferredCardID=MAXDWORD;
  92. DWORD  tapiCountryCode=0;
  93. char   tapiLocalAccessCode[65] = "" ;
  94. char   tapiLongDistAccessCode[65] = "";
  95. char   tapiTollPrefixList[4097]="";
  96. DWORD  tapiOptions=0;
  97. char   tapiCancelCallWaiting[65] = "";
  98. char   tapiCountryName[65] = "";
  99. char   tapiSameAreaRule[65] = "";
  100. char   tapiLongDistanceRule[65] = "";
  101. char   tapiInternationalRule[65] = "";
  102.  
  103. LONG (WINAPI *cklineInitialize)(LPHLINEAPP, HINSTANCE, LINECALLBACK, LPCSTR, LPDWORD ) = NULL ;
  104. LONG (WINAPI *cklineNegotiateAPIVersion)(HLINEAPP, DWORD, DWORD, DWORD, LPDWORD, LPLINEEXTENSIONID) = NULL ;
  105. LONG (WINAPI *cklineGetDevCaps)(HLINEAPP, DWORD, DWORD, DWORD, LPLINEDEVCAPS) = NULL ;
  106. LONG (WINAPI *cklineShutdown)(HLINEAPP) = NULL ;
  107. LONG (WINAPI *cklineOpen)(HLINEAPP, DWORD, LPHLINE, DWORD, DWORD, DWORD, DWORD, DWORD,
  108.                   LPLINECALLPARAMS) = NULL ;
  109. LONG (WINAPI *cklineMakeCall)(HLINE hLine, LPHCALL lphCall, LPCSTR lpszDestAddress,
  110.                       DWORD dwCountryCode, LPLINECALLPARAMS const lpCallParams) = NULL ;
  111. LONG (WINAPI *cklineDial)(HCALL hCall, LPCSTR lpszDestAddress, DWORD dwCountryCode) = NULL ;
  112. LONG (WINAPI *cklineDrop)(HCALL hCall, LPCSTR lpsUserUserInfo, DWORD dwSize) = NULL ;
  113. LONG (WINAPI *cklineAnswer)(HCALL hCall, LPCSTR lpsUserUserInfo, DWORD dwSize) = NULL ;
  114. LONG (WINAPI *cklineAccept)(HCALL hCall, LPCSTR lpsUserUserInfo, DWORD dwSize) = NULL ;
  115. LONG (WINAPI *cklineDeallocateCall)(HCALL hCall) = NULL ;
  116. LONG (WINAPI *cklineSetCallPrivilege)(HCALL,DWORD) = NULL ;
  117. LONG (WINAPI *cklineClose)(HLINE hLine) = NULL ;
  118. LONG (WINAPI *cklineHandoff)(HCALL,LPCSTR,DWORD) = NULL ;
  119. LONG (WINAPI *cklineGetID)(HLINE hLine, DWORD dwAddressID, HCALL hCall,
  120.                DWORD dwSelect, LPVARSTRING lpDeviceID, LPCSTR lpszDeviceClass) = NULL ;
  121. LONG (WINAPI *cklineGetTranslateCaps)( HLINEAPP hLineApp, DWORD,
  122.                                        LPLINETRANSLATECAPS lpLineTranslateCaps) = NULL ;
  123. LONG (WINAPI *cklineSetCurrentLocation)( HLINEAPP hLineApp, DWORD dwLocationID ) = NULL ;
  124. LONG (WINAPI *cklineSetStatusMessages)( HLINE hLine, DWORD dwLineStates,
  125.                                         DWORD dwAddressStates ) = NULL ;
  126. LONG (WINAPI *cklineConfigDialog)( DWORD dwLine, HWND hwin, LPCSTR lpszTypes ) = NULL ;
  127. LONG (WINAPI *cklineTranslateDialog)( HLINEAPP hTAPI, DWORD dwLine, DWORD dwVersionToUse,
  128.                                       HWND hwndOwner, LPCSTR lpszAddressIn ) = NULL ;
  129. LONG (WINAPI *cklineTranslateAddress)( HLINEAPP hTAPI, DWORD dwLine, DWORD dwVersionToUse,
  130.                                        LPCSTR lpszAddressIn, DWORD dwCard,
  131.                                        DWORD dwTranslateOptions,
  132.                                        LPLINETRANSLATEOUTPUT lpTranslateOutput) = NULL ;
  133. LONG (WINAPI *cklineGetCountry)( DWORD, DWORD, LPLINECOUNTRYLIST ) = NULL;
  134. LONG (WINAPI *cklineGetDevConfig)(DWORD, LPVARSTRING, LPCSTR) = NULL;
  135. LONG (WINAPI *cklineGetLineDevStatus)(HLINE hLine,LPLINEDEVSTATUS lpLineDevStatus)=NULL;
  136. LONG (WINAPI *cklineSetDevConfig)(DWORD,LPVOID const,DWORD,LPCSTR)=NULL;
  137. LONG (WINAPI *cklineGetCallInfo)(HCALL, LPLINECALLINFO)=NULL;
  138. LONG (WINAPI *cklineMonitorMedia)(HCALL,DWORD)=NULL;
  139. LONG (WINAPI *cklineGetAppPriority)(LPCSTR,DWORD,LPLINEEXTENSIONID,
  140.                                      DWORD,LPVARSTRING,LPDWORD)=NULL;
  141. LONG (WINAPI *cklineSetAppPriority)(LPCSTR,DWORD,LPLINEEXTENSIONID,
  142.                                      DWORD,LPCSTR,DWORD)=NULL;
  143. LONG (WINAPI *cklineGetNumRings)(HLINE,DWORD,LPDWORD)=NULL;
  144. LONG (WINAPI *cklineSetNumRings)(HLINE,DWORD,DWORD)=NULL;
  145. LONG (WINAPI *cklineSetCallParams)(HCALL,DWORD,DWORD,DWORD,LPLINEDIALPARAMS)=NULL;
  146.  
  147.  
  148. int
  149. cktapiunload(void)
  150. {
  151.     debug(F100,"Closing TAPI Semaphores","",0);
  152.     CloseTAPIInitSem();
  153.     CloseTAPIConnectSem();
  154.     CloseTAPIAnswerSem();
  155.     debug(F100,"Freeing the TAPI Library","",0);
  156.     FreeLibrary( hLib ) ;
  157.     hLib = NULL ;
  158.     cklineInitialize = NULL ;
  159.     debug(F100,"TAPI unload complete","",0);
  160.     return TRUE ;
  161. }
  162.  
  163. int cktapiload(void)
  164. {
  165.    DWORD rc = 0 ;
  166.     hLib = LoadLibrary("tapi32") ;
  167.    if ( !hLib )
  168.    {
  169.       rc = GetLastError() ;
  170.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  171.       return FALSE;
  172.    }
  173.  
  174.    if (((FARPROC) cklineInitialize = GetProcAddress( hLib, "lineInitialize" )) == NULL )
  175.    {
  176.       rc = GetLastError() ;
  177.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  178.       return FALSE;
  179.    }
  180.    if (((FARPROC) cklineNegotiateAPIVersion = GetProcAddress( hLib, "lineNegotiateAPIVersion" )) == NULL )
  181.    {
  182.       rc = GetLastError() ;
  183.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  184.       return FALSE;
  185.    }
  186.    if (((FARPROC) cklineGetDevCaps = GetProcAddress( hLib, "lineGetDevCaps" )) == NULL )
  187.    {
  188.       rc = GetLastError() ;
  189.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  190.       return FALSE;
  191.    }
  192.    if (((FARPROC) cklineShutdown = GetProcAddress( hLib, "lineShutdown" )) == NULL )
  193.    {
  194.       rc = GetLastError() ;
  195.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  196.       return FALSE;
  197.    }
  198.    if (((FARPROC) cklineOpen = GetProcAddress( hLib, "lineOpen" )) == NULL )
  199.    {
  200.       rc = GetLastError() ;
  201.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  202.       return FALSE;
  203.    }
  204.    if (((FARPROC) cklineMakeCall = GetProcAddress( hLib, "lineMakeCall" )) == NULL )
  205.    {
  206.       rc = GetLastError() ;
  207.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  208.       return FALSE;
  209.    }
  210.    if (((FARPROC) cklineDial = GetProcAddress( hLib, "lineDial" )) == NULL )
  211.    {
  212.       rc = GetLastError() ;
  213.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  214.       return FALSE;
  215.    }
  216.    if (((FARPROC) cklineDrop = GetProcAddress( hLib, "lineDrop" )) == NULL )
  217.    {
  218.       rc = GetLastError() ;
  219.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  220.       return FALSE;
  221.    }
  222.     if (((FARPROC) cklineAnswer = GetProcAddress( hLib, "lineAnswer" )) == NULL )
  223.     {
  224.         rc = GetLastError() ;
  225.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  226.         return FALSE;
  227.     }
  228.     if (((FARPROC) cklineAccept = GetProcAddress( hLib, "lineAccept" )) == NULL )
  229.     {
  230.         rc = GetLastError() ;
  231.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  232.         return FALSE;
  233.     }
  234.     if (((FARPROC) cklineDeallocateCall = GetProcAddress( hLib, "lineDeallocateCall" )) == NULL )
  235.     {
  236.         rc = GetLastError() ;
  237.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  238.         return FALSE;
  239.     }
  240.     if (((FARPROC) cklineClose = GetProcAddress( hLib, "lineClose" )) == NULL )
  241.    {
  242.       rc = GetLastError() ;
  243.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  244.       return FALSE;
  245.    }
  246.    if (((FARPROC) cklineGetID = GetProcAddress( hLib, "lineGetID" )) == NULL )
  247.    {
  248.       rc = GetLastError() ;
  249.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  250.       return FALSE;
  251.    }
  252.    if (((FARPROC) cklineGetTranslateCaps = GetProcAddress( hLib, "lineGetTranslateCaps" )) == NULL )
  253.    {
  254.       rc = GetLastError() ;
  255.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  256.       return FALSE;
  257.    }
  258.    if (((FARPROC) cklineSetCurrentLocation = GetProcAddress( hLib, "lineSetCurrentLocation" )) == NULL )
  259.    {
  260.       rc = GetLastError() ;
  261.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  262.       return FALSE;
  263.    }
  264.    if (((FARPROC) cklineSetStatusMessages = GetProcAddress( hLib, "lineSetStatusMessages" )) == NULL )
  265.    {
  266.       rc = GetLastError() ;
  267.       debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  268.       return FALSE;
  269.    }
  270.     if (((FARPROC) cklineConfigDialog = GetProcAddress( hLib, "lineConfigDialog" )) == NULL )
  271.     {
  272.         rc = GetLastError() ;
  273.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  274.         return FALSE;
  275.     }
  276.     if (((FARPROC) cklineTranslateDialog = GetProcAddress( hLib, "lineTranslateDialog" )) == NULL )
  277.     {
  278.         rc = GetLastError() ;
  279.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  280.         return FALSE;
  281.     }
  282.     if (((FARPROC) cklineTranslateAddress =
  283.           GetProcAddress( hLib, "lineTranslateAddress" )) == NULL )
  284.     {
  285.         rc = GetLastError() ;
  286.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  287.         return FALSE;
  288.     }
  289.     if (((FARPROC) cklineGetCountry =
  290.           GetProcAddress( hLib, "lineGetCountry" )) == NULL )
  291.     {
  292.         rc = GetLastError() ;
  293.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  294.         return FALSE;
  295.     }
  296.     if (((FARPROC) cklineGetLineDevStatus =
  297.           GetProcAddress( hLib, "lineGetLineDevStatus" )) == NULL )
  298.     {
  299.         rc = GetLastError() ;
  300.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  301.         return FALSE;
  302.     }
  303.     if (((FARPROC) cklineGetDevConfig =
  304.           GetProcAddress( hLib, "lineGetDevConfig" )) == NULL )
  305.     {
  306.         rc = GetLastError() ;
  307.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  308.         return FALSE;
  309.     }
  310.     if (((FARPROC) cklineSetDevConfig =
  311.           GetProcAddress( hLib, "lineSetDevConfig" )) == NULL )
  312.     {
  313.         rc = GetLastError() ;
  314.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  315.         return FALSE;
  316.     }
  317.     if (((FARPROC) cklineHandoff =
  318.           GetProcAddress( hLib, "lineHandoff" )) == NULL )
  319.     {
  320.         rc = GetLastError() ;
  321.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  322.         return FALSE;
  323.     }
  324.     if (((FARPROC) cklineSetCallPrivilege =
  325.           GetProcAddress( hLib, "lineSetCallPrivilege" )) == NULL )
  326.     {
  327.         rc = GetLastError() ;
  328.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  329.         return FALSE;
  330.     }
  331.     if (((FARPROC) cklineGetCallInfo =
  332.           GetProcAddress( hLib, "lineGetCallInfo" )) == NULL )
  333.     {
  334.         rc = GetLastError() ;
  335.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  336.         return FALSE;
  337.     }
  338.     if (((FARPROC) cklineMonitorMedia =
  339.           GetProcAddress( hLib, "lineMonitorMedia" )) == NULL )
  340.     {
  341.         rc = GetLastError() ;
  342.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  343.         return FALSE;
  344.     }
  345.     if (((FARPROC) cklineGetAppPriority =
  346.           GetProcAddress( hLib, "lineGetAppPriority" )) == NULL )
  347.     {
  348.         rc = GetLastError() ;
  349.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  350.         return FALSE;
  351.     }
  352.     if (((FARPROC) cklineSetAppPriority =
  353.           GetProcAddress( hLib, "lineSetAppPriority" )) == NULL )
  354.     {
  355.         rc = GetLastError() ;
  356.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  357.         return FALSE;
  358.     }
  359.     if (((FARPROC) cklineGetNumRings =
  360.           GetProcAddress( hLib, "lineGetNumRings" )) == NULL )
  361.     {
  362.         rc = GetLastError() ;
  363.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  364.         return FALSE;
  365.     }
  366.     if (((FARPROC) cklineSetNumRings =
  367.           GetProcAddress( hLib, "lineSetNumRings" )) == NULL )
  368.     {
  369.         rc = GetLastError() ;
  370.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  371.         return FALSE;
  372.     }
  373.     if (((FARPROC) cklineSetCallParams =
  374.           GetProcAddress( hLib, "lineSetCallParams" )) == NULL )
  375.     {
  376.         rc = GetLastError() ;
  377.         debug(F111, "cktapiload LoadLibrary failed","tapi32",rc) ;
  378.         return FALSE;
  379.     }
  380.  
  381.     CreateTAPIInitSem( FALSE );
  382.     CreateTAPIConnectSem( FALSE );
  383.     CreateTAPIAnswerSem( FALSE );
  384.     return TRUE;
  385. }
  386.  
  387. // Global TAPI variables.
  388. HWND     g_hWndMainWindow = NULL;   // Apps main window.
  389. HWND     g_hDlgParentWindow = NULL; // This will be the parent of all dialogs.
  390. HLINEAPP g_hLineApp = (HLINEAPP) 0;
  391. DWORD    g_dwNumDevs = -1;
  392. DWORD    g_DataDevices = 0 ;
  393.  
  394. #define MAXDEVS 64
  395. LPLINEDEVCAPS g_lpLineDevCaps[64] ;
  396. extern HINSTANCE hInst ;
  397.  
  398. // Global variable that holds the handle to a TAPI dialog
  399. // that needs to be dismissed if line conditions change.
  400. HWND g_hDialog = NULL;
  401.  
  402. // Global flags to prevent re-entrancy problems.
  403. BOOL g_bShuttingDown = FALSE;
  404. BOOL g_bStoppingCall = FALSE;
  405. BOOL g_bInitializing = FALSE;
  406.  
  407.  
  408. // This sample only supports one call in progress at a time.
  409. BOOL g_bTapiInUse = FALSE;
  410.  
  411.  
  412. // Data needed per call.  This sample only supports one call.
  413. HCALL g_hCall = (HCALL) 0;
  414. HLINE g_hLine = (HLINE) 0;
  415. extern int ttyfd ; /* this holds the HLINE hLine */
  416. extern int mdmtyp ;
  417. static int mdmtyp_sav=0;
  418. CHAR szModemName[256] ;
  419. DWORD LineDeviceId = -1;
  420. DWORD LineDeviceAPIVersion = 0 ;
  421. DWORD LineAddressCount = 0 ;
  422. DWORD LineMediaModes = 0 ;
  423.  
  424. DWORD g_dwAPIVersion = 0;
  425.  
  426. DWORD g_dwCallState = 0;
  427. BOOL  g_bConnected = FALSE;
  428.  
  429. // Global variables to allow us to do various waits.
  430. BOOL  g_bReplyReceived=FALSE;
  431. DWORD g_dwRequestedID=0;
  432. long  g_lAsyncReply=SUCCESS;
  433. BOOL  g_bCallStateReceived=FALSE;
  434. BOOL  g_bAnswering = FALSE;
  435. BOOL  g_bDialing = FALSE;
  436. BOOL  g_bHangingUp = FALSE;
  437. BOOL  g_bClosing = FALSE;
  438.  
  439. int
  440. cktapiinit(void)
  441. {
  442.     int i = 0 ;
  443.     // This will be the parent of all dialogs.
  444.     g_hWndMainWindow = g_hDlgParentWindow = hwndConsole;
  445.  
  446.     for ( i=0 ; i < MAXDEVS ; i++ )
  447.         g_lpLineDevCaps[i] = NULL ;
  448.  
  449.     if ( cktapiload() )
  450.     {
  451.         if (cktapiopen())
  452.         {
  453.            debug(F100,"TAPI open successful","",0);
  454.            g_DataDevices = cktapidevenum() ;
  455.            cktapiclose() ;
  456.            return TRUE ;
  457.         }
  458.         else
  459.         {
  460.             debug(F100,"TAPI open failed","",0);
  461.         }
  462.     }
  463.     return FALSE;
  464. }
  465.  
  466. void
  467. OutputDebugLastError( DWORD x, char * string )
  468. {
  469.     char buf[1024];
  470.     sprintf(buf,"%s %s",string,cktapiErrorString(x));
  471.     debug(F111,"TAPI LastError",buf,x);
  472. #ifdef BETADEBUG
  473.     printf("TAPI LastError %s=%x\n",string,x);
  474. #endif
  475. }
  476.  
  477. void
  478. HandleNoMem( )
  479. {
  480.    debug(F100,"TAPI Out of Memory","",0);
  481. }
  482.  
  483. //
  484. //  FUNCTION: LPVOID CheckAndReAllocBuffer(LPVOID, size_t, LPCSTR)
  485. //
  486. //  PURPOSE: Checks and ReAllocates a buffer if necessary.
  487. //
  488. //  PARAMETERS:
  489. //    lpBuffer          - Pointer to buffer to be checked.  Can be NULL.
  490. //    sizeBufferMinimum - Minimum size that lpBuffer should be.
  491. //    szApiPhrase       - Phrase to print if an error occurs.
  492. //
  493. //  RETURN VALUE:
  494. //    Returns a pointer to a valid buffer that is guarenteed to be
  495. //    at least sizeBufferMinimum size.
  496. //    Returns NULL if an error occured.
  497. //
  498. //  COMMENTS:
  499. //
  500. //    This function is a helper function intended to make all of the
  501. //    line API Wrapper Functions much simplier.  It allocates (or
  502. //    reallocates) a buffer of the requested size.
  503. //
  504. //    The returned pointer has been allocated with LocalAlloc,
  505. //    so LocalFree has to be called on it when you're finished with it,
  506. //    or there will be a memory leak.
  507. //
  508. //    Similarly, if a pointer is passed in, it *must* have been allocated
  509. //    with LocalAlloc and it could potentially be LocalFree()d.
  510. //
  511. //    If lpBuffer == NULL, then a new buffer is allocated.  It is
  512. //    normal to pass in NULL for this parameter the first time and only
  513. //    pass in a pointer if the buffer needs to be reallocated.
  514. //
  515. //    szApiPhrase is used only for debugging purposes.
  516. //
  517. //    It is assumed that the buffer returned from this function will be used
  518. //    to contain a variable sized structure.  Thus, the dwTotalSize field
  519. //    is always filled in before returning the pointer.
  520. //
  521. //
  522.  
  523. LPVOID
  524. CheckAndReAllocBuffer(LPVOID lpBuffer, size_t sizeBufferMinimum,
  525.                        LPCSTR szApiPhrase)
  526. {
  527.     size_t sizeBuffer;
  528.  
  529.     debug(F110,"CheckAndReAllocBuffer",szApiPhrase,0);
  530.     debug(F111,"CheckAndReAllocBuffer","lpBuffer",lpBuffer);
  531.     debug(F111,"CheckAndReAllocBuffer","sizeBufferMinimum",sizeBufferMinimum);
  532.  
  533.     if (lpBuffer == NULL)  // Allocate the buffer if necessary.
  534.     {
  535.         sizeBuffer = sizeBufferMinimum;
  536.         lpBuffer = (LPVOID) LocalAlloc(LPTR, sizeBuffer);
  537.  
  538.         if (lpBuffer == NULL)
  539.         {
  540.             HandleNoMem();
  541.             return NULL;
  542.         }
  543.     }
  544.     else // If the structure already exists, make sure its good.
  545.     {
  546.         sizeBuffer = LocalSize((HLOCAL) lpBuffer);
  547.  
  548.         if (sizeBuffer == 0) // Bad pointer?
  549.         {
  550.             return NULL;
  551.         }
  552.  
  553.         // Was the buffer big enough for the structure?
  554.         if (sizeBuffer < sizeBufferMinimum)
  555.         {
  556.             LocalFree(lpBuffer);
  557.             return CheckAndReAllocBuffer(NULL, sizeBufferMinimum, szApiPhrase);
  558.         }
  559.  
  560.         // Lets zero the buffer out.
  561.         memset(lpBuffer, 0, sizeBuffer);
  562.     }
  563.  
  564.     ((LPVARSTRING) lpBuffer ) -> dwTotalSize = (DWORD) sizeBuffer;
  565.     return lpBuffer;
  566. }
  567.  
  568. char *
  569. cktapiErrorString(DWORD error)
  570. {
  571.     char * estr = NULL;
  572.     switch ( error ) {
  573.     case 0:
  574.         estr = "Success";
  575.         break;
  576.     case LINEERR_ALLOCATED:
  577.         estr = "Line already allocated";
  578.         break;
  579.     case LINEERR_BADDEVICEID:
  580.         estr = "Bad device ID";
  581.         break;
  582.     case LINEERR_BEARERMODEUNAVAIL:
  583.         estr = "Requested Bearer Mode Unavailable";
  584.         break;
  585.     case LINEERR_CALLUNAVAIL:
  586.         estr = "Unable to place call on current device";
  587.         break;
  588.     case LINEERR_COMPLETIONOVERRUN               :
  589.         estr = "Completion Overrun";
  590.         break;
  591.     case LINEERR_CONFERENCEFULL                  :
  592.         estr = "Conference Full";
  593.         break;
  594.     case LINEERR_DIALBILLING                     :
  595.         estr = "Dial Billing error";
  596.         break;
  597.     case LINEERR_DIALDIALTONE                    :
  598.         estr = "Wait for Dial Tone not supported";
  599.         break;
  600.     case LINEERR_DIALPROMPT                      :
  601.         estr = "Wait for Dial Prompt not supported";
  602.         break;
  603.     case LINEERR_DIALQUIET                       :
  604.         estr = "Wait for Quiet not supported";
  605.         break;
  606.     case LINEERR_INCOMPATIBLEAPIVERSION          :
  607.         estr = "Incompatible TAPI Version";
  608.         break;
  609.     case LINEERR_INCOMPATIBLEEXTVERSION          :
  610.         estr = "Incompatible Extension Version";
  611.         break;
  612.     case LINEERR_INIFILECORRUPT                  :
  613.         estr = "TELEPHON.INI file corrupt";
  614.         break;
  615.     case LINEERR_INUSE                           :
  616.         estr = "Line in use";
  617.         break;
  618.     case LINEERR_INVALADDRESS                    :
  619.         estr = "Invalid Line Address";
  620.         break;
  621.     case LINEERR_INVALADDRESSID                  :
  622.         estr = "Invalid Line Address ID";
  623.         break;
  624.     case LINEERR_INVALADDRESSMODE                :
  625.         estr = "Invalid Line Address Mode";
  626.         break;
  627.     case LINEERR_INVALADDRESSSTATE               :
  628.         estr = "Invalid Line Address State";
  629.         break;
  630.     case LINEERR_INVALAPPHANDLE                  :
  631.         estr = "Invalid Application Handle";
  632.         break;
  633.     case LINEERR_INVALAPPNAME                    :
  634.         estr = "Invalid Application Name";
  635.         break;
  636.     case LINEERR_INVALBEARERMODE                 :
  637.         estr = "Invalid Bearer Mode";
  638.         break;
  639.     case LINEERR_INVALCALLCOMPLMODE              :
  640.         estr = "Invalid Call Completion Mode";
  641.         break;
  642.     case LINEERR_INVALCALLHANDLE                 :
  643.         estr = "Invalid Call Handle";
  644.         break;
  645.     case LINEERR_INVALCALLPARAMS                 :
  646.         estr = "Invalid Call Parameters";
  647.         break;
  648.     case LINEERR_INVALCALLPRIVILEGE              :
  649.         estr = "Invalid Call Privilege";
  650.         break;
  651.     case LINEERR_INVALCALLSELECT                 :
  652.         estr = "Invalid Call Selection";
  653.         break;
  654.     case LINEERR_INVALCALLSTATE                  :
  655.         estr = "Invalid Call State";
  656.         break;
  657.     case LINEERR_INVALCALLSTATELIST              :
  658.         estr = "Invalid Call State List";
  659.         break;
  660.     case LINEERR_INVALCARD                       :
  661.         estr = "Invalid Card";
  662.         break;
  663.     case LINEERR_INVALCOMPLETIONID               :
  664.         estr = "Invalid Completion ID";
  665.         break;
  666.     case LINEERR_INVALCONFCALLHANDLE             :
  667.         estr = "Invalid Conference Call Handle";
  668.         break;
  669.     case LINEERR_INVALCONSULTCALLHANDLE          :
  670.         estr = "Invalid Consulation Call Handle";
  671.         break;
  672.     case LINEERR_INVALCOUNTRYCODE                :
  673.         estr = "Invalid Country Code";
  674.         break;
  675.     case LINEERR_INVALDEVICECLASS                :
  676.         estr = "Invalid Device Class";
  677.         break;
  678.     case LINEERR_INVALDEVICEHANDLE               :
  679.         estr = "Invalid Device Handle";
  680.         break;
  681.     case LINEERR_INVALDIALPARAMS                 :
  682.         estr = "Invalid Dial Parameters";
  683.         break;
  684.     case LINEERR_INVALDIGITLIST                  :
  685.         estr = "Invalid Digit List";
  686.         break;
  687.     case LINEERR_INVALDIGITMODE                  :
  688.         estr = "Invalid Digit Mode";
  689.         break;
  690.     case LINEERR_INVALDIGITS                     :
  691.         estr = "Invalid Digits";
  692.         break;
  693.     case LINEERR_INVALEXTVERSION                 :
  694.         estr = "Invalid Extension Version";
  695.         break;
  696.     case LINEERR_INVALGROUPID                    :
  697.         estr = "Invalid Group ID";
  698.         break;
  699.     case LINEERR_INVALLINEHANDLE                 :
  700.         estr = "Invalid Line Handle";
  701.         break;
  702.     case LINEERR_INVALLINESTATE                  :
  703.         estr = "Invalid Line State";
  704.         break;
  705.     case LINEERR_INVALLOCATION                   :
  706.         estr = "Invalid Location";
  707.         break;
  708.     case LINEERR_INVALMEDIALIST                  :
  709.         estr = "Invalid Media List";
  710.         break;
  711.     case LINEERR_INVALMEDIAMODE                  :
  712.         estr = "Invalid Media Mode";
  713.         break;
  714.     case LINEERR_INVALMESSAGEID                  :
  715.         estr = "Invalid Message ID";
  716.         break;
  717.     case LINEERR_INVALPARAM                      :
  718.         estr = "Invalid Parameter";
  719.         break;
  720.     case LINEERR_INVALPARKID                     :
  721.         estr = "Invalid Park ID";
  722.         break;
  723.     case LINEERR_INVALPARKMODE                   :
  724.         estr = "Invaldi Park Mode";
  725.         break;
  726.     case LINEERR_INVALPOINTER                    :
  727.         estr = "Invalid Pointer";
  728.         break;
  729.     case LINEERR_INVALPRIVSELECT                 :
  730.         estr = "Invalid Privilege Select";
  731.         break;
  732.     case LINEERR_INVALRATE                       :
  733.         estr = "Invalid Rate";
  734.         break;
  735.     case LINEERR_INVALREQUESTMODE                :
  736.         estr = "Invalid Request Mode";
  737.         break;
  738.     case LINEERR_INVALTERMINALID                 :
  739.         estr = "Invalid Terminal ID";
  740.         break;
  741.     case LINEERR_INVALTERMINALMODE               :
  742.         estr = "Invalid Terminal Mode";
  743.         break;
  744.     case LINEERR_INVALTIMEOUT                    :
  745.         estr = "Invalid Timeout";
  746.         break;
  747.     case LINEERR_INVALTONE                       :
  748.         estr = "Invalid Tone";
  749.         break;
  750.     case LINEERR_INVALTONELIST                   :
  751.         estr = "Invalid Tone List";
  752.         break;
  753.     case LINEERR_INVALTONEMODE                   :
  754.         estr = "Invalid Tone Mode";
  755.         break;
  756.     case LINEERR_INVALTRANSFERMODE               :
  757.         estr = "Invalid Transfer Mode";
  758.         break;
  759.     case LINEERR_LINEMAPPERFAILED                :
  760.         estr = "Line Mapper Failed";
  761.         break;
  762.     case LINEERR_NOCONFERENCE                    :
  763.         estr = "No Conference available";
  764.         break;
  765.     case LINEERR_NODEVICE                        :
  766.         estr = "No Device available";
  767.         break;
  768.     case LINEERR_NODRIVER                        :
  769.         estr = "No Driver available";
  770.         break;
  771.     case LINEERR_NOMEM                           :
  772.         estr = "No memory available";
  773.         break;
  774.     case LINEERR_NOREQUEST                       :
  775.         estr = "No Request";
  776.         break;
  777.     case LINEERR_NOTOWNER                        :
  778.         estr = "Not owner";
  779.         break;
  780.     case LINEERR_NOTREGISTERED                   :
  781.         estr = "Not Registered";
  782.         break;
  783.     case LINEERR_OPERATIONFAILED                 :
  784.         estr = "Operation Failed";
  785.         break;
  786.     case LINEERR_OPERATIONUNAVAIL                :
  787.         estr = "Operation Unavailable";
  788.         break;
  789.     case LINEERR_RATEUNAVAIL                     :
  790.         estr = "Rate Unavailable";
  791.         break;
  792.     case LINEERR_RESOURCEUNAVAIL                 :
  793.         estr = "Resource Unavailable";
  794.         break;
  795.     case LINEERR_REQUESTOVERRUN                  :
  796.         estr = "Request Overrun";
  797.         break;
  798.     case LINEERR_STRUCTURETOOSMALL               :
  799.         estr = "Structure Too Small";
  800.         break;
  801.     case LINEERR_TARGETNOTFOUND                  :
  802.         estr = "Target Not Found";
  803.         break;
  804.     case LINEERR_TARGETSELF                      :
  805.         estr = "Target Self";
  806.         break;
  807.     case LINEERR_UNINITIALIZED                   :
  808.         estr = "TAPI Unititialized";
  809.         break;
  810.     case LINEERR_USERUSERINFOTOOBIG              :
  811.         estr = "User Info Too Big";
  812.         break;
  813.     case LINEERR_REINIT                          :
  814.         estr = "TAPI Reinitialization Required";
  815.         break;
  816.     case LINEERR_ADDRESSBLOCKED                  :
  817.         estr = "Address Blocked";
  818.         break;
  819.     case LINEERR_BILLINGREJECTED                 :
  820.         estr = "Billing Rejected";
  821.         break;
  822.     case LINEERR_INVALFEATURE                    :
  823.         estr = "Invalid Feature";
  824.         break;
  825.     case LINEERR_NOMULTIPLEINSTANCE              :
  826.         estr = "Multiple Instances not supported";
  827.         break;
  828. #ifdef COMMENT  /* TAPI 2.0 */
  829.     case LINEERR_INVALAGENTID                    :
  830.         estr = "Invalid Agent ID";
  831.         break;
  832.     case LINEERR_INVALAGENTGROUP                 :
  833.         estr = "Invalid Agent Group";
  834.         break;
  835.     case LINEERR_INVALPASSWORD                   :
  836.         estr = "Invalid Password";
  837.         break;
  838.     case LINEERR_INVALAGENTSTATE                 :
  839.         estr = "Invalid Agent State";
  840.         break;
  841.     case LINEERR_INVALAGENTACTIVITY              :
  842.         estr = "Invalid Agent Activity";
  843.         break;
  844.     case LINEERR_DIALVOICEDETECT                 :
  845.         estr = "Voice detected during dialing";
  846.         break;
  847. #endif /* COMMENT */
  848.     default:
  849.         estr = ((LONG) error) > 0 ? "Request ID" : "Unknown TAPI error";
  850.         break;
  851.     }
  852.     return estr;
  853. }
  854.  
  855. void
  856. UpdateStatusBar( char * str, long param1, long param2 )
  857. {
  858.     char buf[1024];
  859.     sprintf(buf,"%s::%d,%d",str,param1,param2);
  860.     debug(F110,"TAPI Status Message",buf,0);
  861.  
  862.     if ( dialdpy )
  863.         printf( "%s\n",str ) ;
  864. }
  865.  
  866. void
  867. OutputDebugLineError( long param, char * str )
  868. {
  869.     char buf[1024];
  870.     sprintf(buf,"%s %s",str,cktapiErrorString(param));
  871. #ifdef BETADEBUG
  872.     printf("TAPI Debug Line Error: %s=%s(0x%x)\n",str,
  873.             cktapiErrorString(param),param);
  874. #endif /* BETADEBUG */
  875.     debug(F111,"TAPI Debug Line Error",buf,param);
  876. }
  877.  
  878. void
  879. OutputDebugLineCallback(
  880.         DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance,
  881.         DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
  882. {
  883.     char buf[1024];
  884.     sprintf(buf,"(%d,%d,%d,%d,%d,%d)",
  885.              dwDevice,dwMsg,dwCallbackInstance,
  886.              dwParam1,dwParam2,dwParam3);
  887.     debug(F110,"TAPI Line Callback",buf,0);
  888. }
  889.  
  890. //
  891. //  FUNCTION: DoLineReply(..)
  892. //
  893. //  PURPOSE: Handle LINE_REPLY asynchronous messages.
  894. //
  895. //  PARAMETERS:
  896. //    dwDevice  - Line Handle associated with this LINE_REPLY.
  897. //    dwMsg     - Should always be LINE_REPLY.
  898. //    dwCallbackInstance - Unused by this sample.
  899. //    dwParam1  - Asynchronous request ID.
  900. //    dwParam2  - success or LINEERR error value.
  901. //    dwParam3  - Unused.
  902. //
  903. //  RETURN VALUE:
  904. //    none
  905. //
  906. //  COMMENTS:
  907. //
  908. //    All line API calls that return an asynchronous request ID
  909. //    will eventually cause a LINE_REPLY message.  Handle it.
  910. //
  911. //    This sample assumes only one call at time, and that we wait
  912. //    for a LINE_REPLY before making any other line API calls.
  913. //
  914. //    The only exception to the above is that we might shut down
  915. //    the line before receiving a LINE_REPLY.
  916. //
  917. //
  918.  
  919. void
  920. DoLineReply(
  921.     DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
  922.     DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
  923. {
  924.     debug(F111,"TAPI LINE REPLY","Requested ID",g_dwRequestedID);
  925.     debug(F111,"TAPI LINE REPLY","Message ID",dwParam1);
  926.     OutputDebugLineError((long) dwParam2, "LINE_REPLY error: ");
  927.  
  928.     while ( g_dwRequestedID == 0 ) {
  929.         msleep(100);
  930.     }
  931.  
  932.     // If we are currently waiting for this async Request ID
  933.     // then set the global variables to acknowledge it.
  934.     if (g_dwRequestedID == dwParam1)
  935.     {
  936. #ifdef BETADEBUG
  937.         printf("LINE_REPLY: dwRequestedID == dwParam1\n");
  938. #endif
  939.         g_lAsyncReply = (long) dwParam2;
  940.         g_bReplyReceived = TRUE;
  941.     }
  942. #ifdef BETADEBUG
  943.     else {
  944.         printf("LINE_REPLY: dwRequestedID != dwParam1\n");
  945.     }
  946. #endif
  947. }
  948.  
  949.  
  950. //
  951. //  FUNCTION: DoLineClose(..)
  952. //
  953. //  PURPOSE: Handle LINE_CLOSE asynchronous messages.
  954. //
  955. //  PARAMETERS:
  956. //    dwDevice  - Line Handle that was closed.
  957. //    dwMsg     - Should always be LINE_CLOSE.
  958. //    dwCallbackInstance - Unused by this sample.
  959. //    dwParam1  - Unused.
  960. //    dwParam2  - Unused.
  961. //    dwParam3  - Unused.
  962. //
  963. //  RETURN VALUE:
  964. //    none
  965. //
  966. //  COMMENTS:
  967. //
  968. //    This message is sent when something outside our app shuts
  969. //    down a line in use.
  970. //
  971. //    The hLine (and any hCall on this line) are no longer valid.
  972. //
  973. //
  974.  
  975. void
  976. DoLineClose(
  977.     DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
  978.     DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
  979. {
  980.     // Line has been shut down.  Clean up our internal variables.
  981.     if ( (HLINE) dwDevice == g_hLine ) {
  982.         cktapicloseasync();
  983.         debug(F110,"TAPI","Line was shutdown by TAPI",0);
  984.         printf("%s was shut down.\n",szModemName);
  985.     }
  986. }
  987.  
  988.  
  989. //
  990. //  FUNCTION: DoLineCreate(..)
  991. //
  992. //  PURPOSE: Handle LINE_LINECREATE asynchronous messages.
  993. //
  994. //  PARAMETERS:
  995. //    dwDevice  - Unused.
  996. //    dwMsg     - Should always be LINE_CREATE.
  997. //    dwCallbackInstance - Unused.
  998. //    dwParam1  - dwDeviceID of new Line created.
  999. //    dwParam2  - Unused.
  1000. //    dwParam3  - Unused.
  1001. //
  1002. //  RETURN VALUE:
  1003. //    none
  1004. //
  1005. //  COMMENTS:
  1006. //
  1007. //    This message is new for Windows 95.  It is sent when a new line is
  1008. //    added to the system.  This allows us to handle new lines without having
  1009. //    to REINIT.  This allows for much more graceful Plug and Play.
  1010. //
  1011. //
  1012.  
  1013. void
  1014. DoLineCreate(
  1015.     DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
  1016.     DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
  1017. {
  1018.     // dwParam1 is the Device ID of the new line.
  1019.     // Add one to get the number of total devices.
  1020.     if (g_dwNumDevs <= dwParam1)
  1021.         g_dwNumDevs = dwParam1+1;
  1022.     g_DataDevices = cktapidevenum() ;
  1023.     debug(F111,"TAPI","A new line device has been added to the system",
  1024.            g_DataDevices);
  1025. #ifdef BETADEBUG
  1026.     printf("A new line device has been added to the system.\n");
  1027. #endif /* BETADEBUG */
  1028. }
  1029.  
  1030. //
  1031. //  FUNCTION: DoLineDevState(..)
  1032. //
  1033. //  PURPOSE: Handle LINE_LINEDEVSTATE asynchronous messages.
  1034. //
  1035. //  PARAMETERS:
  1036. //    dwDevice  - Line Handle that was closed.
  1037. //    dwMsg     - Should always be LINE_LINEDEVSTATE.
  1038. //    dwCallbackInstance - Unused by this sample.
  1039. //    dwParam1  - LINEDEVSTATE constant.
  1040. //    dwParam2  - Depends on dwParam1.
  1041. //    dwParam3  - Depends on dwParam1.
  1042. //
  1043. //  RETURN VALUE:
  1044. //    none
  1045. //
  1046. //  COMMENTS:
  1047. //
  1048. //    The LINE_LINEDEVSTATE message is received if the state of the line
  1049. //    changes.  Examples are RINGING, MAINTENANCE, MSGWAITON.
  1050. //
  1051. //    Assuming that any LINEDEVSTATE that removes the line from use by TAPI
  1052. //    will also send a LINE_CLOSE message.
  1053. //
  1054. //
  1055.  
  1056. void
  1057. DoLineDevState(
  1058.     DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
  1059.     DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
  1060. {
  1061.     switch(dwParam1)
  1062.     {
  1063.     case LINEDEVSTATE_RINGING: {
  1064.         UpdateStatusBar("Line Ringing",1,0);
  1065.         break;
  1066.     }
  1067.  
  1068.     case LINEDEVSTATE_REINIT:
  1069.         // This is an important case!  Usually means that a service provider
  1070.         // has changed in such a way that requires TAPI to REINIT.
  1071.         // Note that there are both 'soft' REINITs and 'hard' REINITs.
  1072.         // Soft REINITs don't actually require a full shutdown but is instead
  1073.         // just an informational change that historically required a REINIT
  1074.         // to force the application to deal with.  TAPI API Version 1.3 apps
  1075.         // will still need to do a full REINIT for both hard and soft REINITs.
  1076.  
  1077.         switch(dwParam2)
  1078.         {
  1079.             // This is the hard REINIT.  No reason given, just REINIT.
  1080.             // TAPI is waiting for everyone to shutdown.
  1081.             // Our response is to immediately shutdown any calls,
  1082.             // shutdown our use of TAPI and notify the user.
  1083.         case 0:
  1084. #ifdef BETADEBUG
  1085.             printf("Line configuration has changed\n");
  1086. #endif /* BETADEBUG */
  1087.             if ( (HLINE) dwDevice == g_hLine ) {
  1088.                 cktapicloseasync();
  1089.                 printf("TAPI line configuration has changed.  Shutdown required.\n");
  1090.                 debug(F111,"TAPI LINEDEVSTATE_REINIT-0","Shutdown required",dwDevice);
  1091.             }
  1092.             break;
  1093.  
  1094.         case LINE_CREATE:
  1095. #ifdef BETADEBUG
  1096.             printf("Soft REINIT: LINE_CREATE.\n");
  1097. #endif /* BETADEBUG */
  1098.             DoLineCreate(dwDevice, dwParam2, dwCallbackInstance,
  1099.                           dwParam3, 0, 0);
  1100.             break;
  1101.  
  1102.         case LINE_LINEDEVSTATE:
  1103. #ifdef BETADEBUG
  1104.             printf("Soft REINIT: LINE_LINEDEVSTATE.\n");
  1105. #endif /* BETADEBUG */
  1106.  
  1107.             DoLineDevState(dwDevice, dwParam2, dwCallbackInstance,
  1108.                             dwParam3, 0, 0);
  1109.             break;
  1110.  
  1111.             // There might be other reasons to send a soft reinit.
  1112.             // No need to to shutdown for these.
  1113.         default:
  1114. #ifdef BETADEBUG
  1115.             printf("Ignoring soft REINIT\n");
  1116. #endif /* BETADEBUG */
  1117.             break;
  1118.         }
  1119.         break;
  1120.  
  1121.     case LINEDEVSTATE_OUTOFSERVICE:
  1122.         if ( (HLINE) dwDevice == g_hLine ) {
  1123.             cktapicloseasync();
  1124.             printf("%s is now Out of Service\n",szModemName);
  1125.             debug(F111,"TAPI LINEDEVSTATE_OUTOFSERVICE",szModemName,dwDevice);
  1126.         }
  1127.         break;
  1128.  
  1129.     case LINEDEVSTATE_DISCONNECTED:
  1130.         if ( (HLINE) dwDevice == g_hLine &&
  1131.              g_hCall != (HCALL) 0 ) {
  1132.             cktapidisconnect();
  1133.             printf("%s is now disconnected\n",szModemName);
  1134.             debug(F111,"TAPI LINEDEVSTATE_DISCONNECTED",szModemName,dwDevice);
  1135.         }
  1136.         break;
  1137.  
  1138.     case LINEDEVSTATE_MAINTENANCE:
  1139.         if ( (HLINE) dwDevice == g_hLine ) {
  1140.             cktapicloseasync();
  1141.             printf("%s is now out for maintenance\n",szModemName);
  1142.             debug(F111,"TAPI LINEDEVSTATE_MAINTENANCE",szModemName,dwDevice);
  1143.         }
  1144.         break;
  1145.  
  1146.     case LINEDEVSTATE_TRANSLATECHANGE:
  1147. #ifdef BETADEBUG
  1148.         printf("Translate Change\n");
  1149. #endif
  1150.         debug(F100,"TAPI LINEDEVSTATE_TRANSLATECHANGE","",0);
  1151. #ifndef NODIAL
  1152.         if ( 1 || tapiconv == CK_ON ||
  1153.              tapiconv == CK_AUTO && tttapi && !tapipass ) {
  1154.             /* Reload TAPI Location Information From Scratch */
  1155.             tapilocid = -1;
  1156.             CopyTapiLocationInfoToKermitDialCmd();
  1157.         }
  1158. #endif /* NODIAL */
  1159.         break;
  1160.  
  1161.     case LINEDEVSTATE_REMOVED:
  1162. #ifdef BETADEBUG
  1163.         printf("A Line device has been removed; no action taken.\n");
  1164. #endif
  1165.         if (g_dwNumDevs <= dwParam1)
  1166.             g_dwNumDevs = dwParam1+1;
  1167.         g_DataDevices = cktapidevenum() ;
  1168.         debug(F111,"TAPI LINEDEVSTATE_REMOVED",
  1169.                "A line device has been removed; no action taken",
  1170.                g_DataDevices);
  1171.         break;
  1172.  
  1173.     case LINEDEVSTATE_CLOSE:
  1174. #ifdef BETADEBUG
  1175.         printf("A Line device has been closed; no action taken.\n");
  1176. #endif /* BETADEBUG */
  1177.         debug(F110,"TAPI LINEDEVSTATE_CLOSE","A Line device has been closed; no action taken",
  1178.                0);
  1179.         break;
  1180.  
  1181.     case LINEDEVSTATE_OPEN:
  1182. #ifdef BETADEBUG
  1183.         printf("A Line device has been opened; no action taken.\n");
  1184. #endif /* BETADEBUG */
  1185.         debug(F110,"TAPI LINEDEVSTATE_OPEN","A Line device has been openned; no action taken",
  1186.                0);
  1187.         break;
  1188.  
  1189.     default:
  1190. #ifdef BETADEBUG
  1191.         printf("Unhandled LINEDEVSTATE message\n");
  1192. #endif
  1193.         debug(F111,"TAPI LINEDEVSTATE_???",
  1194.                "Unhandled LINEDEVSTATE message",
  1195.                dwParam1);
  1196.         break;
  1197.     }
  1198. }
  1199.  
  1200.  
  1201.  
  1202. //
  1203. //  FUNCTION: DoLineCallState(..)
  1204. //
  1205. //  PURPOSE: Handle LINE_CALLSTATE asynchronous messages.
  1206. //
  1207. //  PARAMETERS:
  1208. //    dwDevice  - Handle to Call who's state is changing.
  1209. //    dwMsg     - Should always be LINE_CALLSTATE.
  1210. //    dwCallbackInstance - Unused by this sample.
  1211. //    dwParam1  - LINECALLSTATE constant specifying state change.
  1212. //    dwParam2  - Specific to dwParam1.
  1213. //    dwParam3  - LINECALLPRIVILEGE change, if any.
  1214. //
  1215. //  RETURN VALUE:
  1216. //    none
  1217. //
  1218. //  COMMENTS:
  1219. //
  1220. //    This message is received whenever a call changes state.  Lots of
  1221. //    things we do, ranging from notifying the user to closing the line
  1222. //    to actually connecting to the target of our phone call.
  1223. //
  1224. //    What we do is usually obvious based on the call state change.
  1225. //
  1226.  
  1227. void
  1228. DoLineCallState(
  1229.     DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
  1230.     DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
  1231. {
  1232.     // Error if this CALLSTATE doesn't apply to our call in progress.
  1233.     if ( g_hCall != (HCALL)0 && (HCALL) dwDevice != g_hCall ||
  1234.          g_hCall == (HCALL)0 && !g_bDialing && !g_bAnswering )
  1235.     {
  1236.         int rc=0;
  1237.         debug(F101,"LINE_CALLSTATE: Unknown device ID '0x%lx'.","",dwDevice);
  1238. #ifdef BETADEBUG
  1239.         printf("LINE_CALLSTATE: Unknown device ID '0x%lx\n",dwDevice);
  1240. #endif
  1241.         rc = (*cklineDeallocateCall)((HCALL)dwDevice);
  1242.         OutputDebugLastError(rc,"DoLineCallState() lineDeallocateCall: ");
  1243. #ifdef BETADEBUG
  1244.         printf("  DoLineCallState() lineDeallocateCall = %x\n",rc);
  1245. #endif
  1246.         return;
  1247.     }
  1248.  
  1249.     // This sets the global g_dwCallState variable so if we are waiting
  1250.     // for a specific call state change, we will know when it happens.
  1251.     g_dwCallState = dwParam1;
  1252.     g_bCallStateReceived = TRUE;
  1253.  
  1254.     // dwParam3 contains changes to LINECALLPRIVILEGE, if there are any.
  1255.     switch (dwParam3)
  1256.     {
  1257.     case 0:
  1258.         break; // no change to call state
  1259.  
  1260.         // close line if we are made monitor.  Shouldn't happen!
  1261.     case LINECALLPRIVILEGE_MONITOR:
  1262. #ifdef BETADEBUG
  1263.         printf("line has monitor privilege\n");
  1264. #endif
  1265.         //cktapiclose();
  1266.         break;
  1267.  
  1268.         // close line if we are made owner.  Shouldn't happen!
  1269.     case LINECALLPRIVILEGE_OWNER:
  1270. #ifdef BETADEBUG
  1271.         printf("line has owner privilege\n");
  1272. #endif
  1273.         //cktapiclose();
  1274.         break;
  1275.  
  1276.     default: // Shouldn't happen!  All cases handled.
  1277. #ifdef BETADEBUG
  1278.         printf("Unknown LINECALLPRIVILEGE message\n");
  1279. #endif
  1280.         //cktapiclose();
  1281.         return;
  1282.     }
  1283.  
  1284.     // dwParam1 is the specific CALLSTATE change that is occurring.
  1285.     switch (dwParam1)
  1286.     {
  1287.     case LINECALLSTATE_DIALTONE:
  1288.         if ( g_bDialing )
  1289.             UpdateStatusBar("Dial Tone",1,0);
  1290.         break;
  1291.  
  1292.     case LINECALLSTATE_DIALING:
  1293.         if ( g_bDialing )
  1294.             UpdateStatusBar("Dialing Call",1,0);
  1295.         break;
  1296.  
  1297.     case LINECALLSTATE_PROCEEDING:
  1298.         if ( g_bDialing )
  1299.             UpdateStatusBar("Call is Proceeding",1,0);
  1300.         break;
  1301.  
  1302.     case LINECALLSTATE_RINGBACK:
  1303.         UpdateStatusBar("RingBack",1,0);
  1304.         break;
  1305.  
  1306.     case LINECALLSTATE_BUSY:
  1307.         if ( g_bDialing ) {
  1308.             UpdateStatusBar("Line is busy",1,0);
  1309.             PostTAPIConnectSem();
  1310.         }
  1311.         break;
  1312.  
  1313.     case LINECALLSTATE_IDLE:
  1314.         msleep(1000);
  1315.         UpdateStatusBar("Line is idle",1,0);
  1316.         if ( ttyfd != -1 && ttyfd != -2 ) {
  1317.             cktapidisconnect();
  1318.             SetConnectMode(FALSE);
  1319.         }
  1320.         PostTAPIConnectSem();
  1321.         break;
  1322.  
  1323.     case LINECALLSTATE_SPECIALINFO:
  1324.         UpdateStatusBar("Special Info, probably couldn't dial number",1,0);
  1325.         PostTAPIConnectSem();
  1326.         break;
  1327.  
  1328.     case LINECALLSTATE_DISCONNECTED:
  1329.         {
  1330.             LPSTR pszReasonDisconnected;
  1331.  
  1332.             switch (dwParam2)
  1333.             {
  1334.             case LINEDISCONNECTMODE_NORMAL:
  1335.                 pszReasonDisconnected = "Remote Party Disconnected";
  1336.                 break;
  1337.  
  1338.             case LINEDISCONNECTMODE_UNKNOWN:
  1339.                 pszReasonDisconnected = "Disconnected: Unknown reason";
  1340.                 break;
  1341.  
  1342.             case LINEDISCONNECTMODE_REJECT:
  1343.                 pszReasonDisconnected = "Remote Party rejected call";
  1344.                 break;
  1345.  
  1346.             case LINEDISCONNECTMODE_PICKUP:
  1347.                 pszReasonDisconnected =
  1348.                     "Disconnected: Local phone picked up";
  1349.                 break;
  1350.  
  1351.             case LINEDISCONNECTMODE_FORWARDED:
  1352.                 pszReasonDisconnected = "Disconnected: Forwarded";
  1353.                 break;
  1354.  
  1355.             case LINEDISCONNECTMODE_BUSY:
  1356.                 pszReasonDisconnected = "Disconnected: Busy";
  1357.                 break;
  1358.  
  1359.             case LINEDISCONNECTMODE_NOANSWER:
  1360.                 pszReasonDisconnected = "Disconnected: No Answer";
  1361.                 break;
  1362.  
  1363.             case LINEDISCONNECTMODE_BADADDRESS:
  1364.                 pszReasonDisconnected = "Disconnected: Bad Address";
  1365.                 break;
  1366.  
  1367.             case LINEDISCONNECTMODE_UNREACHABLE:
  1368.                 pszReasonDisconnected = "Disconnected: Unreachable";
  1369.                 break;
  1370.  
  1371.             case LINEDISCONNECTMODE_CONGESTION:
  1372.                 pszReasonDisconnected = "Disconnected: Congestion";
  1373.                 break;
  1374.  
  1375.             case LINEDISCONNECTMODE_INCOMPATIBLE:
  1376.                 pszReasonDisconnected = "Disconnected: Incompatible";
  1377.                 break;
  1378.  
  1379.             case LINEDISCONNECTMODE_UNAVAIL:
  1380.                 pszReasonDisconnected = "Disconnected: Unavail";
  1381.                 break;
  1382.  
  1383.             case LINEDISCONNECTMODE_NODIALTONE:
  1384.                 pszReasonDisconnected = "Disconnected: No Dial Tone";
  1385.                 break;
  1386.  
  1387.             default:
  1388.                 pszReasonDisconnected =
  1389.                     "Disconnected: LINECALLSTATE; Bad Reason";
  1390.                 break;
  1391.             }
  1392.             if ( ttyfd != -1 && ttyfd != -2 ) {
  1393.                 cktapidisconnect();
  1394.                 SetConnectMode(FALSE);
  1395.             }
  1396.             PostTAPIConnectSem() ;
  1397.             UpdateStatusBar(pszReasonDisconnected,1,0);
  1398.             break;
  1399.         }
  1400.  
  1401.  
  1402.     case LINECALLSTATE_CONNECTED:  // CONNECTED!!!
  1403.         {
  1404.             int rc;
  1405.             LPVARSTRING lpVarString = NULL;
  1406.             DWORD dwSizeofVarString = sizeof(VARSTRING) + 1024;
  1407.             long lReturn;
  1408.  
  1409.             // Very first, make sure this isn't a duplicated message.
  1410.             // A CALLSTATE message can be sent whenever there is a
  1411.             // change to the capabilities of a line, meaning that it is
  1412.             // possible to receive multiple CONNECTED messages per call.
  1413.             // The CONNECTED CALLSTATE message is the only one in TapiComm
  1414.             // where it would cause problems if it where sent more
  1415.             // than once.
  1416.  
  1417.             if ( g_bConnected && (HCALL) dwDevice == g_hCall )
  1418.                 break;
  1419.  
  1420.             if (!(g_bDialing || g_bAnswering)) {
  1421.                 /* Get the hCall */
  1422.                 g_hCall = (HCALL) dwDevice;
  1423.                 debug(F110,"TAPI LINECALLSTATE_CONNECTED",
  1424.                        "were not Dialing and we're not Answering",0);
  1425.  
  1426.                 if ( dwParam3 == LINECALLPRIVILEGE_OWNER ) {
  1427.                     /* Need to check the Bearer Mode of the call */
  1428.  
  1429.                     /* are we even answering calls? */
  1430.                     rc = (*cklineHandoff)(g_hCall, NULL, LINEMEDIAMODE_DATAMODEM);
  1431.                     OutputDebugLastError(rc,"lineHandoff:");
  1432.                     rc = (*cklineDeallocateCall)(g_hCall);
  1433.                     OutputDebugLastError(rc,"lineDeallocateCall:");
  1434.                     if ( rc < 0 ) {
  1435.                         cktapidisconnect();
  1436.                     }
  1437.                     else {
  1438.                         g_hCall = (HCALL)0;
  1439.                     }
  1440.                 }
  1441.                 else /* if ( dwParam3 == LINECALLPRIVILEGE_MONITOR ) */ {
  1442.                     rc = (*cklineDeallocateCall)(g_hCall);
  1443.                     OutputDebugLastError(rc,"lineDeallocateCall:");
  1444.                     g_hCall = (HCALL)0;
  1445.                 }
  1446.                 break;
  1447.             }
  1448.  
  1449.             if ( g_bAnswering && g_hCall == (HCALL)0 ) {
  1450.                 UpdateStatusBar("Incoming call being offered in connected state.",1,0);
  1451.                 g_hCall = (HCALL) dwDevice;
  1452.                 PostTAPIAnswerSem();
  1453.             }
  1454.  
  1455.             UpdateStatusBar("Connection complete.",1,0);
  1456.             g_bConnected = TRUE;
  1457.  
  1458.             // Get the handle to the comm port from the driver so we can start
  1459.             // communicating.  This is returned in a LPVARSTRING structure.
  1460.             do
  1461.             {
  1462.                 // Free any preexiting VARSTRING
  1463.                 if ( lpVarString != NULL )
  1464.                     free(lpVarString);
  1465.  
  1466.                 // Allocate the VARSTRING structure
  1467.                 lpVarString = malloc( dwSizeofVarString ) ;
  1468.                 if (lpVarString == NULL)
  1469.                     goto ErrorConnecting;
  1470.                 lpVarString->dwTotalSize = dwSizeofVarString;
  1471.  
  1472.                 // Fill the VARSTRING structure
  1473.                 lReturn = (*cklineGetID)(0, 0, g_hCall, LINECALLSELECT_CALL,
  1474.                     lpVarString, "comm/datamodem");
  1475.  
  1476.                 if (HandleLineErr(lReturn))
  1477.                     ; // Still need to check if structure was big enough.
  1478.                 else
  1479.                 {
  1480.                     OutputDebugLineError(lReturn,
  1481.                         "lineGetID unhandled error:");
  1482.                     goto ErrorConnecting;
  1483.                 }
  1484.  
  1485.                 // If the VARSTRING wasn't big enough, loop again.
  1486.                 if ((lpVarString -> dwNeededSize) > (lpVarString -> dwTotalSize))
  1487.                 {
  1488.                     dwSizeofVarString = lpVarString -> dwNeededSize;
  1489.                     lReturn = -1; // Lets loop again.
  1490.                 }
  1491.             }
  1492.             while(lReturn != SUCCESS);
  1493.  
  1494.  
  1495.             // Again, the handle to the comm port is contained in a
  1496.             // LPVARSTRING structure.  Thus, the handle is the very first
  1497.             // thing after the end of the structure.  Note that the name of
  1498.             // the comm port is right after the handle, but I don't want it.
  1499.             debug(F111,"TAPI DoLineCallState","ttyfd",ttyfd);
  1500.             (HANDLE) ttyfd =
  1501.                 *((LPHANDLE)((LPBYTE)lpVarString +
  1502.                     lpVarString -> dwStringOffset));
  1503.             debug(F111,"TAPI DoLineCallState","ttyfd",ttyfd);
  1504.             lReturn = SetCommMask( (HANDLE) ttyfd, EV_RXCHAR ) ;
  1505.             debug(F111,"TAPI DoLineCallState","SetCommMask",lReturn);
  1506.             lReturn = SetupComm( (HANDLE) ttyfd, 20000, 20000 ) ;
  1507.             debug(F111,"TAPI DoLineCallState","SetupComm",lReturn);
  1508.             lReturn = PurgeComm( (HANDLE) ttyfd,
  1509.                        PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR );
  1510.             debug(F111,"TAPI DoLineCallState","PurgeComm",lReturn);
  1511.  
  1512.           ErrorConnecting:
  1513.             PostTAPIConnectSem() ;
  1514.             debug(F110,"TAPI DoLineCallState","TAPI Connect Sem posted",0);
  1515.  
  1516.             if (lpVarString)
  1517.                 free(lpVarString);
  1518.             break;
  1519.         }
  1520.  
  1521.     case LINECALLSTATE_OFFERING: {
  1522.         int rc;
  1523.         LPLINECALLINFO lpCallInfo = NULL;
  1524.         DWORD          dwSize     = sizeof(LINECALLINFO);
  1525.         LONG           lrc = 0;
  1526.         DWORD          dwMediaMode= LINEMEDIAMODE_UNKNOWN;
  1527.         DWORD          dwNumRings = 0;
  1528.  
  1529.         UpdateStatusBar("Incoming call being offered",1,0);
  1530.         g_hCall = (HCALL) dwDevice;
  1531.  
  1532.         /* Check Media Mode */
  1533.  
  1534.         /* The next four lines prepare a VARSTRING structure to
  1535.         pass to Windows though lineGetID */
  1536.         lpCallInfo = (LPLINECALLINFO) malloc (dwSize);
  1537.         if ( !lpCallInfo ) {
  1538.             cktapidisconnect();
  1539.             return ;
  1540.         }
  1541.         memset(lpCallInfo,0,dwSize);
  1542.         lpCallInfo->dwTotalSize = dwSize;
  1543.  
  1544.         do {
  1545.             /* get modem handle associated with the line */
  1546.             lrc = (*cklineGetCallInfo)(g_hCall, lpCallInfo);
  1547.             if ( ( lrc == LINEERR_STRUCTURETOOSMALL || lrc == 0 ) &&
  1548.                  (lpCallInfo->dwTotalSize < lpCallInfo->dwNeededSize) ) {
  1549.                 /* the next six lines reallocate the VARSTRING */
  1550.                 dwSize = lpCallInfo->dwNeededSize ;
  1551.                 free(lpCallInfo);
  1552.                 lpCallInfo = (LPLINECALLINFO) malloc(dwSize);
  1553.                 if ( !lpCallInfo ) {
  1554.                     cktapidisconnect();
  1555.                     return;
  1556.                 }
  1557.                 memset(lpCallInfo,0,dwSize);
  1558.                 lpCallInfo->dwTotalSize = dwSize ;
  1559.             }
  1560.             else if ( lrc ) {
  1561.                 /* some kind of TAPI error */
  1562.                 OutputDebugLastError(lrc,"lineGetCallInfo:");
  1563.                 free(lpCallInfo);
  1564.                 cktapidisconnect();
  1565.                 return;
  1566.             }
  1567.             else
  1568.                 break;  /* success */
  1569.         } while ( TRUE );
  1570.  
  1571.         dwMediaMode = lpCallInfo->dwMediaMode;
  1572.         free(lpCallInfo);
  1573.  
  1574. #ifdef BETADEBUG
  1575.         /* what is the media mode */
  1576.         if ( dwMediaMode & LINEMEDIAMODE_UNKNOWN )
  1577.             printf("  MediaMode is UNKNOWN (it may be one of the following)\n");
  1578.         if ( dwMediaMode & LINEMEDIAMODE_INTERACTIVEVOICE )
  1579.             printf("  MediaMode is Interactive Voice\n");
  1580.         if ( dwMediaMode & LINEMEDIAMODE_AUTOMATEDVOICE )
  1581.             printf("  MediaMode is Automated Voice\n");
  1582.         if ( dwMediaMode & LINEMEDIAMODE_TDD )
  1583.             printf("  MediaMode is TDD\n");
  1584.         if ( dwMediaMode & LINEMEDIAMODE_DIGITALDATA )
  1585.             printf("  MediaMode is Digital Data\n");
  1586.         if ( dwMediaMode & LINEMEDIAMODE_TELETEX )
  1587.             printf("  MediaMode is TeleTex\n");
  1588.         if ( dwMediaMode & LINEMEDIAMODE_VIDEOTEX )
  1589.             printf("  MediaMode is VideoTex\n");
  1590.         if ( dwMediaMode & LINEMEDIAMODE_MIXED )
  1591.             printf("  MediaMode is Mixed\n");
  1592.         if ( dwMediaMode & LINEMEDIAMODE_ADSI )
  1593.             printf("  MediaMode is ADSI\n");
  1594.         if ( dwMediaMode & LINEMEDIAMODE_VOICEVIEW )
  1595.             printf("  MediaMode is VoiceView\n");
  1596.         if ( dwMediaMode & LINEMEDIAMODE_DATAMODEM )
  1597.             printf("  MediaMode is DataModem\n");
  1598.         if ( dwMediaMode & LINEMEDIAMODE_G3FAX )
  1599.             printf("  MediaMode is G3Fax\n");
  1600.         if ( dwMediaMode & LINEMEDIAMODE_G4FAX )
  1601.             printf("  MediaMode is G4Fax\n");
  1602.         if ( dwMediaMode > LAST_LINEMEDIAMODE*2-1 )
  1603.             printf("  MediaMode is %x\n", dwMediaMode );
  1604. #endif /* BETADEBUG */
  1605.  
  1606. #ifdef COMMENT
  1607.         /* Activate Media Mode Monitoring by the Service Provider */
  1608.         (*cklineMonitorMedia)( g_hCall,
  1609.                                dwMediaMode & ~LINEMEDIAMODE_UNKNOWN );
  1610. #endif /* COMMENT */
  1611.  
  1612. #ifdef BETADEBUG
  1613.         (*cklineGetNumRings)(g_hLine,0,&dwNumRings);
  1614.         printf("  User requests we wait %d rings before answering.\n",
  1615.                 dwNumRings);
  1616. #endif /* BETADEBUG */
  1617.  
  1618.         /* Get the hCall */
  1619.         if ( dwParam3 == LINECALLPRIVILEGE_OWNER ) {
  1620.  
  1621.             /* Need to check the Bearer Mode of the call */
  1622.  
  1623.             /* are we even answering calls? */
  1624.             if ( g_bAnswering )
  1625.                 PostTAPIAnswerSem();
  1626.             else {
  1627.                 rc = (*cklineHandoff)(g_hCall, NULL, LINEMEDIAMODE_DATAMODEM);
  1628.                 OutputDebugLastError(rc,"lineHandoff:");
  1629.                 rc = (*cklineDeallocateCall)(g_hCall);
  1630.                 OutputDebugLastError(rc,"lineDeallocateCall:");
  1631.                 if ( rc < 0 ) {
  1632.                     cktapidisconnect();
  1633.                 }
  1634.                 else {
  1635.                     g_hCall = (HCALL)0;
  1636.                 }
  1637.             }
  1638.         }
  1639.         else /* if ( dwParam3 == LINECALLPRIVILEGE_MONITOR ) */ {
  1640.             if ( g_bAnswering &&
  1641.                  !(dwMediaMode & ~(LINEMEDIAMODE_DATAMODEM | LINEMEDIAMODE_UNKNOWN))
  1642.                  ) {
  1643.                 rc = (*cklineSetCallPrivilege)( g_hCall, LINECALLPRIVILEGE_OWNER );
  1644.                 OutputDebugLastError(rc,"lineSetCallPrivilege:");
  1645.                 if ( !rc ) {
  1646.                     PostTAPIAnswerSem();
  1647.                 }
  1648.                 else {
  1649.                     rc = (*cklineDeallocateCall)(g_hCall);
  1650.                     OutputDebugLastError(rc,"lineDeallocateCall:");
  1651.                     g_hCall = (HCALL)0;
  1652.                 }
  1653.             }
  1654.             else {
  1655.                 rc = (*cklineDeallocateCall)(g_hCall);
  1656.                 OutputDebugLastError(rc,"lineDeallocateCall:");
  1657.                 g_hCall = (HCALL)0;
  1658.             }
  1659.         }
  1660.         break;
  1661.     }
  1662.  
  1663.     case LINECALLSTATE_ACCEPTED:
  1664.         UpdateStatusBar("Incoming call has been accepted",1,0);
  1665.         break;
  1666.  
  1667.     default:
  1668.         UpdateStatusBar("?Unhandled LINECALLSTATE message",1,0);
  1669.         break;
  1670.     }
  1671. }
  1672.  
  1673. void
  1674. CALLBACK
  1675. cklineCallbackFunc( DWORD dwDevice, DWORD dwMsg,
  1676.                     DWORD dwCallbackInstance,
  1677.                     DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
  1678. {
  1679.  
  1680.     OutputDebugLineCallback(
  1681.         dwDevice, dwMsg, dwCallbackInstance,
  1682.         dwParam1, dwParam2, dwParam3);
  1683.  
  1684.     // All we do is dispatch the dwMsg to the correct handler.
  1685.     switch(dwMsg)
  1686.     {
  1687.     case LINE_CALLSTATE:
  1688.         debug(F110,"TAPI Callback","Line Callstate",0);
  1689. #ifdef BETADEBUG
  1690.         printf("TAPI Callback - Line Callstate %x,%x,%x\n",
  1691.                 dwParam1, dwParam2, dwParam3);
  1692. #endif
  1693.         DoLineCallState(dwDevice, dwMsg, dwCallbackInstance,
  1694.                          dwParam1, dwParam2, dwParam3);
  1695.         break;
  1696.  
  1697.         case LINE_CLOSE:
  1698.         debug(F110,"TAPI Callback","Line Close",0);
  1699. #ifdef BETADEBUG
  1700.         printf("TAPI Callback - Line Close\n");
  1701. #endif
  1702.         DoLineClose(dwDevice, dwMsg, dwCallbackInstance,
  1703.                      dwParam1, dwParam2, dwParam3);
  1704.         break;
  1705.  
  1706.         case LINE_LINEDEVSTATE:
  1707.         debug(F110,"TAPI Callback","Line LineDevState",0);
  1708. #ifdef BETADEBUG
  1709.         printf("TAPI Callback - Line LineDevState %x,%x,%x\n",
  1710.                 dwParam1, dwParam2, dwParam3);
  1711. #endif
  1712.         DoLineDevState(dwDevice, dwMsg, dwCallbackInstance,
  1713.                         dwParam1, dwParam2, dwParam3);
  1714.         break;
  1715.  
  1716.         case LINE_REPLY:
  1717.         debug(F110,"TAPI Callback","Line Reply",0);
  1718. #ifdef BETADEBUG
  1719.         printf("TAPI Callback - Line Reply %x,%x,%x\n",
  1720.                 dwParam1, dwParam2, dwParam3);
  1721. #endif
  1722.         DoLineReply(dwDevice, dwMsg, dwCallbackInstance,
  1723.                      dwParam1, dwParam2, dwParam3);
  1724.         break;
  1725.  
  1726.         case LINE_CREATE:
  1727.         debug(F110,"TAPI Callback","Line Create",0);
  1728. #ifdef BETADEBUG
  1729.         printf("TAPI Callback - Line Create\n");
  1730. #endif
  1731.         DoLineCreate(dwDevice, dwMsg, dwCallbackInstance,
  1732.                       dwParam1, dwParam2, dwParam3);
  1733.         break;
  1734.  
  1735.         default:
  1736.         debug(F110,"TAPI Callback","default",0);
  1737. #ifdef BETADEBUG
  1738.         printf("TAPI Callback - default\n");
  1739. #endif
  1740.         break;
  1741.     }
  1742.  
  1743.     return;
  1744.  
  1745. }
  1746.  
  1747. BOOL
  1748. HandleLineErr(long lLineErr)
  1749. {
  1750.     debug(F101,"TAPI HandleLineErr","",lLineErr);
  1751.     if ( lLineErr )
  1752.         return FALSE;
  1753.     else
  1754.         return TRUE ;
  1755. }
  1756.  
  1757. BOOL
  1758. HandleNoDevicesInstalled(void)
  1759. {
  1760.     return FALSE;
  1761. }
  1762.  
  1763. BOOL g_bLineInitialized = FALSE;
  1764. void
  1765. wintapiinit( void )
  1766. {
  1767.     long lReturn;
  1768.     BOOL bTryReInit = TRUE ;
  1769.  
  1770.     // Initialize TAPI
  1771.     do
  1772.     {
  1773.         debug(F111,"TAPI wintapiinit","g_hLineApp",g_hLineApp);
  1774.         debug(F111,"TAPI wintapiinit","hInst",hInst);
  1775.         debug(F111,"TAPI wintapiinit","cklineCallbackFunc",cklineCallbackFunc);
  1776.         debug(F111,"TAPI wintapiinit","g_dwNumDevs",g_dwNumDevs);
  1777.  
  1778.         lReturn = (*cklineInitialize)(&g_hLineApp, hInst,
  1779.              cklineCallbackFunc, "Kermit-95", &g_dwNumDevs);
  1780.         OutputDebugLastError(lReturn,"lineInitialize:");
  1781.  
  1782.         // If we get this error, its because some other app has yet
  1783.         // to respond to the REINIT message.  Wait 5 seconds and try
  1784.         // again.  If it still doesn't respond, tell the user.
  1785.         if (lReturn == LINEERR_REINIT)
  1786.         {
  1787.             if (bTryReInit)
  1788.             {
  1789.                 sleep(5);       /* wait 5 secs, try again */
  1790.                 bTryReInit = FALSE;
  1791.                 continue;
  1792.             }
  1793.             else
  1794.             {
  1795.                 MessageBox(g_hDlgParentWindow,
  1796.                     "A change to the system configuration requires that "
  1797.                     "all Telephony applications relinquish their use of "
  1798.                     "Telephony before any can progress.  "
  1799.                     "Some have not yet done so."
  1800.                     ,"Warning",MB_OK);
  1801.                 g_bInitializing = FALSE;
  1802.                 PostTAPIInitSem();
  1803.                 return;
  1804.             }
  1805.         }
  1806.  
  1807.         if (lReturn == LINEERR_NODEVICE)
  1808.         {
  1809.             if (HandleNoDevicesInstalled())
  1810.                 continue;
  1811.             else
  1812.             {
  1813.                 printf("No devices installed.\n");
  1814.                 g_bInitializing = FALSE;
  1815.                 PostTAPIInitSem();
  1816.                 return;
  1817.             }
  1818.         }
  1819.  
  1820.         if (HandleLineErr(lReturn))
  1821.             continue;
  1822.         else
  1823.         {
  1824.             OutputDebugLineError(lReturn,
  1825.                 "lineInitialize unhandled error: ");
  1826.             g_bInitializing = FALSE;
  1827.             PostTAPIInitSem();
  1828.             return;
  1829.         }
  1830.     }
  1831.     while(lReturn != SUCCESS);
  1832.  
  1833.     debug(F111,"TAPI wintapiinit SUCCESS","g_hLineApp",g_hLineApp);
  1834.     debug(F111,"TAPI wintapiinit SUCCESS","hInst",hInst);
  1835.     debug(F111,"TAPI wintapiinit SUCCESS","cklineCallbackFunc",cklineCallbackFunc);
  1836.     debug(F111,"TAPI wintapiinit SUCCESS","g_dwNumDevs",g_dwNumDevs);
  1837.  
  1838.     g_bLineInitialized = TRUE;
  1839.     PostTAPIInitSem();
  1840.     debug(F111,"TAPI wintapiinit SUCCESS","g_bLineInitialized",g_bLineInitialized);
  1841. }
  1842.  
  1843. void
  1844. wintapishutdown(void)
  1845. {
  1846.     DWORD rc ;
  1847.     debug(F101,"wintapishutdown","",g_hLineApp);
  1848.     rc = (*cklineShutdown)( g_hLineApp ) ;
  1849.     OutputDebugLastError(rc,"lineShutdown:");
  1850.     g_hLineApp = (HLINEAPP)0 ;
  1851.     PostTAPIInitSem();
  1852. }
  1853. int
  1854. cktapiopen(void)
  1855. {
  1856.     debug(F111,"TAPI cktapiopen","tapiopen",tapiopen);
  1857.     if ( g_bClosing ) {
  1858.         int n=0;
  1859.         if ( dialdpy )
  1860.             printf("Waiting for previous Close request to complete...\n");
  1861.         debug(F110,"TAPI cktapiopen","Close in progress",0);
  1862.         while ( g_bClosing && n++ < 30)
  1863.             msleep(500);
  1864.         if ( n >= 30 ) {
  1865.             debug(F110,"TAPI cktapiopen","Close never completed",0);
  1866.             printf("?ERROR in Windows Telephony: close never completed.\n");
  1867.             bleep(BP_FAIL);
  1868.             return(FALSE);
  1869.         }
  1870.     }
  1871.     if ( tapiopen )
  1872.     {
  1873.         tapiopen++ ;
  1874.         debug(F111,"TAPI cktapiopen","tapiopen",tapiopen);
  1875.         return TRUE ;
  1876.     }
  1877.  
  1878.     debug(F110,"TAPI cktapiopen","sending OPT_TAPI_INIT",0);
  1879.     g_bLineInitialized = FALSE;
  1880.     ResetTAPIInitSem();
  1881.     PostMessage( hwndGUI, OPT_TAPI_INIT, 0, 0 ) ;
  1882.     /* Wait for completion */
  1883.     if (!WaitAndResetTAPIInitSem(60000))
  1884.     {
  1885.         debug(F110,"TAPI cktapiopen","TAPIInitSem never completed",0);
  1886.         return FALSE;
  1887.     }
  1888.  
  1889.     if ( !g_bLineInitialized ) {
  1890.         debug(F110,"TAPI cktapiopen","Line not Initialized",0);
  1891.         return FALSE;
  1892.     }
  1893.  
  1894.     tapiopen++;
  1895.     debug(F111,"TAPI cktapiopen","tapiopen",tapiopen);
  1896.     return TRUE;
  1897. }
  1898.  
  1899. int
  1900. cktapidevenum( void )
  1901. {
  1902.     int i = 0 ;
  1903.     DWORD dwAPIVersion ;
  1904.     LINEEXTENSIONID ExtensionID ;
  1905.     int datalines = 0 ;
  1906.     LONG rc;
  1907.  
  1908.     debug(F111,"TAPI Enumerate Devices","g_dwNumDevs",g_dwNumDevs);
  1909.  
  1910.     /* Free existing LineDevCaps */
  1911.     for ( i = 0 ; i < g_dwNumDevs ; i++ )
  1912.     {
  1913.         if ( g_lpLineDevCaps[i] )
  1914.         {
  1915.             free( g_lpLineDevCaps[i] ) ;
  1916.             g_lpLineDevCaps[i] = NULL ;
  1917.         }
  1918.     }
  1919.  
  1920.     /* Enumerate current LineDevCaps */
  1921.     for ( i=0 ; i < g_dwNumDevs ; i++ )
  1922.     {
  1923.         g_lpLineDevCaps[i] = (LPLINEDEVCAPS) malloc (sizeof(LINEDEVCAPS)) ;
  1924.         if ( g_lpLineDevCaps[i] == NULL ) {
  1925.             debug(F111,"TAPI cktapidevenum",
  1926.                    "unable to allocate memory for Device Caps",i);
  1927.             continue;
  1928.         }
  1929.         g_lpLineDevCaps[i]->dwTotalSize = sizeof(LINEDEVCAPS) ;
  1930.         if ( rc = (*cklineNegotiateAPIVersion)(g_hLineApp, i,
  1931.                                            TAPI_CURRENT_VERSION,
  1932.                                            TAPI_CURRENT_VERSION,
  1933.                                            &dwAPIVersion, &ExtensionID))
  1934.         {
  1935.             OutputDebugLastError(rc,"lineNegotiateAPIVersion:");
  1936.             free(g_lpLineDevCaps[i]);
  1937.             g_lpLineDevCaps[i] = NULL ;
  1938.             continue;
  1939.         }
  1940.         if (rc = (*cklineGetDevCaps)(g_hLineApp, i,
  1941.                                  dwAPIVersion, 0, g_lpLineDevCaps[i]))
  1942.         {
  1943.             OutputDebugLastError(rc,"lineGetDevCaps:");
  1944.             free(g_lpLineDevCaps[i]);
  1945.             g_lpLineDevCaps[i] = NULL ;
  1946.             continue;
  1947.         }
  1948.  
  1949.         if ( g_lpLineDevCaps[i]->dwNeededSize > g_lpLineDevCaps[i]->dwTotalSize )
  1950.         {
  1951.             DWORD NeededSize = g_lpLineDevCaps[i]->dwNeededSize;
  1952.             free(g_lpLineDevCaps[i]) ;
  1953.             g_lpLineDevCaps[i] = (LPLINEDEVCAPS) malloc (NeededSize) ;
  1954.             g_lpLineDevCaps[i]->dwTotalSize = NeededSize ;
  1955.  
  1956.             if ((*cklineGetDevCaps)(g_hLineApp, i,
  1957.                                dwAPIVersion, 0, g_lpLineDevCaps[i]))
  1958.             {
  1959.                 OutputDebugLastError(rc,"lineGetDevCaps:");
  1960.                 free(g_lpLineDevCaps[i]);
  1961.                 g_lpLineDevCaps[i] = NULL ;
  1962.                 continue;
  1963.             }
  1964.         }
  1965.  
  1966.       /* We now have a successful LineDevCaps structure */
  1967.         if ( g_lpLineDevCaps[i]->dwMediaModes & LINEMEDIAMODE_DATAMODEM )
  1968.         {
  1969.          /* then this is a valid line to use for data connections */
  1970.             datalines++ ;
  1971.         }
  1972.     }
  1973.     debug(F111,"TAPI Enumerate Devices","datalines",datalines);
  1974.     return datalines ;
  1975. }
  1976.  
  1977. int
  1978. cktapihangup( void )
  1979. {
  1980.     int rc;
  1981.  
  1982.     if ( g_bHangingUp )
  1983.     {
  1984.         int n=0;
  1985.         debug(F110,"TAPI Hangup","already in progress",0);
  1986.         while (g_bHangingUp && n++ < 30) {
  1987.             msleep(500);
  1988.         }
  1989.         if (n < 30) {
  1990.             debug(F110,"TAPI Hangup","previous hangup request completed",0);
  1991.             return TRUE;
  1992.         }
  1993.         else {
  1994.             debug(F110,"TAPI Hangup","previous hangup request didn't complete",0);
  1995.             g_bHangingUp = FALSE;
  1996.         }
  1997.     }
  1998.  
  1999.     debug(F111,"TAPI Hangup","hCall",g_hCall);
  2000.     if ( g_hCall )
  2001.     {
  2002. #ifdef BETADEBUG
  2003.         if ( tapipass )
  2004.             printf( "TAPI: Closing the line\n");
  2005.         else
  2006.             printf("TAPI: Hanging up call\n");
  2007. #endif
  2008.         g_bReplyReceived = FALSE;
  2009.         g_lAsyncReply = SUCCESS;
  2010.         g_bHangingUp     = TRUE;
  2011.  
  2012.         if ( tapipass ) {
  2013.             /* lineSetCallParams */
  2014.             g_dwRequestedID = 0;
  2015.             rc = g_dwRequestedID =
  2016.                 (cklineSetCallParams)(g_hCall,LINEBEARERMODE_VOICE,3100,3100,NULL);
  2017.             OutputDebugLastError(rc,"lineSetCallParams:");
  2018.             if ( rc > 0 ) {
  2019.                 int x=0;
  2020.                 /* Wait for LineReply */
  2021.                 while ( !g_bReplyReceived ) {
  2022.                     msleep(100);
  2023.                     x += 100;
  2024.                     if ( x == 5000 ) {
  2025.                         debug(F110,"TAPI Hangup","lineSetCallParams reply never received",0);
  2026.                         break;
  2027.                     }
  2028.                 }
  2029.                 if ( x < 5000 )
  2030.                     OutputDebugLastError(g_lAsyncReply,"lineSetCallParams (Async):");
  2031.             }
  2032.         }
  2033.  
  2034.         if ( dialdpy && !tapipass )
  2035.             printf("Dropping the call, wait...\n");
  2036.         g_bReplyReceived = FALSE;
  2037.         g_lAsyncReply = SUCCESS;
  2038.         g_dwRequestedID = 0;
  2039.         rc = g_dwRequestedID = (*cklineDrop)(g_hCall, NULL, 0 );
  2040.         OutputDebugLastError(rc,"lineDrop:");
  2041.  
  2042.         if ( rc > 0 ) {
  2043.             int x=0;
  2044.             /* Wait for LineReply */
  2045.             while ( !g_bReplyReceived && g_hCall != (HCALL)0 ) {
  2046.                 msleep(100);
  2047.                 x += 100;
  2048.                 if ( x == 30000 ) {
  2049.                     debug(F110,"TAPI Hangup","lineDrop reply never received",0);
  2050.                     g_bHangingUp = FALSE;
  2051.                     if ( !g_bClosing ) {
  2052.                         return cktapiclose();
  2053.                     }
  2054.                     return FALSE;
  2055.                 }
  2056.             }
  2057.             OutputDebugLastError(g_lAsyncReply,"lineDrop (Async):");
  2058.  
  2059.             if ( g_hCall != (HCALL)0 ) {
  2060.                 rc = (*cklineDeallocateCall)(g_hCall);
  2061.                 OutputDebugLastError(rc,"TAPI Hangup - lineDeallocateCall:");
  2062.                 g_hCall = (HCALL)0;
  2063.             }
  2064.         }
  2065.         else {
  2066.             // g_hCall = NULL;
  2067.             g_bHangingUp     = FALSE;
  2068.             return FALSE;
  2069.         }
  2070.         g_bHangingUp     = FALSE;
  2071.     }
  2072.  
  2073.     if ( g_hLine != (HLINE)0 ) {
  2074.         debug(F111,"TAPI Hangup","ttyfd",ttyfd);
  2075.         if ( ttyfd != -1 && ttyfd != -2 )
  2076.         {
  2077.             rc = CloseHandle( (HANDLE) ttyfd );
  2078.             debug(F111,"TAPI Debug Last Error",
  2079.                    rc?"CloseHandle: Success" : "CloseHandle: Failure",
  2080.                    rc?0:GetLastError());
  2081.             ttyfd = -2;
  2082.         }
  2083.     }
  2084.     return TRUE;
  2085. }
  2086.  
  2087.  
  2088. int
  2089. cktapiclose(void)
  2090. {
  2091.     DWORD rc ;
  2092.  
  2093.     debug(F111,"TAPI cktapiclose","g_bClosing",g_bClosing);
  2094.     if ( g_bClosing ) {
  2095.         int n=0;
  2096.         debug(F110,"TAPI Close","already in progress",0);
  2097.         while ( g_bClosing && n++ < 30 )
  2098.             msleep(500);
  2099.         if ( n >= 30 ) {
  2100.             debug(F110,"TAPI Close","Previous Close never completed",0);
  2101.             return FALSE;
  2102.         }
  2103.         return TRUE;
  2104.     }
  2105.  
  2106.     debug(F111,"TAPI cktapiclose","tapiopen",tapiopen);
  2107.     if ( tapiopen > 0 )
  2108.     {
  2109.         tapiopen-- ;
  2110.         if ( tapiopen == 1 ) {
  2111.             g_bClosing = TRUE;
  2112.             debug(F100,"TAPI Close","",0);
  2113.             cktapihangup();
  2114.             if ( g_hLine )
  2115.             {
  2116.                 debug(F101,"Calling TAPI lineClose","",g_hLine);
  2117.                 rc = (*cklineClose)( g_hLine );
  2118.                 OutputDebugLastError(rc,"lineClose:");
  2119.                 g_hLine = (HLINE)0 ;
  2120.                 ttyfd = -1;
  2121.             }
  2122.         }
  2123.         if ( tapiopen == 0 ) {
  2124.             ResetTAPIInitSem();
  2125.             PostMessage( hwndGUI, OPT_TAPI_SHUTDOWN, 0, 0 ) ;
  2126.             /* Wait for completion */
  2127.             if (!WaitAndResetTAPIInitSem(60000))
  2128.             {
  2129.                 debug(F100,"TAPIInitSem never completed","",0);
  2130.                 return FALSE;
  2131.             }
  2132.         }
  2133.         g_bClosing = FALSE;
  2134.     }
  2135.     debug(F100,"TAPI Close successful","",0);
  2136.     return TRUE;
  2137. }
  2138.  
  2139. int
  2140. cktapiconfigline()
  2141. {
  2142.     LPDEVCFG        lpDevCfg = NULL;
  2143.     LPCOMMCONFIG    lpCommConfig = NULL;
  2144.     LPMODEMSETTINGS lpModemSettings = NULL;
  2145.     DCB *           lpDCB = NULL;
  2146.  
  2147.     if (!cktapiGetModemSettings( &lpDevCfg,
  2148.                                  &lpModemSettings,
  2149.                                  &lpCommConfig,
  2150.                                  &lpDCB )) {
  2151.         return FALSE;
  2152.     }
  2153.  
  2154.     if ( !tapiusecfg ) {
  2155.         /* we need to set TAPI values for
  2156.          tapilights;
  2157.          tapipreterm;
  2158.          tapipostterm;
  2159.          tapimanual;
  2160.          tapiinactivity;
  2161.          tapibong;
  2162.          */
  2163.  
  2164.         lpDevCfg->dfgHdr.fwOptions = (tapilights ? 8 : 0)
  2165.         + (tapipreterm ? 1 : 0)
  2166.             + (tapipostterm ? 2 : 0)
  2167.                 + (tapimanual ? 4 : 0) ;
  2168.         lpDevCfg->dfgHdr.wWaitBong = tapibong;
  2169.         lpModemSettings->dwCallSetupFailTimer = waitct;
  2170.         lpModemSettings->dwInactivityTimeout = tapiinactivity;
  2171.  
  2172.         lpDCB->BaudRate = speed;
  2173.  
  2174.         lpDCB->fBinary = TRUE ;
  2175.         lpDCB->fErrorChar = FALSE ;
  2176.         lpDCB->fAbortOnError = FALSE ;
  2177.         lpDCB->ErrorChar = '?' ;
  2178.         lpDCB->Parity = NOPARITY ;
  2179.         lpDCB->fParity = TRUE ;    /* Tell Win32 not to perform any Parity checking at all */
  2180.         lpDCB->ByteSize = 8 ;
  2181.         lpDCB->StopBits = ONESTOPBIT ;
  2182.  
  2183.         lpDCB->fDsrSensitivity = FALSE ;
  2184.         lpDCB->fDtrControl = DTR_CONTROL_ENABLE ;
  2185.  
  2186. #ifndef NODIAL
  2187.         if ( dialec )
  2188.             lpModemSettings->dwPreferredModemOptions |= MDM_ERROR_CONTROL;
  2189.         else
  2190.             lpModemSettings->dwPreferredModemOptions &= ~MDM_ERROR_CONTROL;
  2191.  
  2192.         if ( dialdc )
  2193.             lpModemSettings->dwPreferredModemOptions |= MDM_COMPRESSION;
  2194.         else
  2195.             lpModemSettings->dwPreferredModemOptions &= ~MDM_COMPRESSION;
  2196.  
  2197. #ifdef COMMENT
  2198.         if ( mdmspd )
  2199.             lpModemSettings->dwPreferredModemOptions |= MDM_SPEED_ADJUST;
  2200.         else
  2201.             lpModemSettings->dwPreferredModemOptions &= ~MDM_SPEED_ADJUST;
  2202. #endif /* COMMENT */
  2203.  
  2204.         if ( dialidt )
  2205.             lpModemSettings->dwPreferredModemOptions |= MDM_BLIND_DIAL;
  2206.         else
  2207.             lpModemSettings->dwPreferredModemOptions &= ~MDM_BLIND_DIAL;
  2208.  
  2209.         if ( dialmth == XYDM_T ) {
  2210.             lpModemSettings->dwPreferredModemOptions |= MDM_TONE_DIAL;
  2211.             dialmauto = 0;
  2212.         } else if ( dialmth == XYDM_D ) {
  2213.             lpModemSettings->dwPreferredModemOptions &= ~MDM_TONE_DIAL;
  2214.             dialmauto = 0;
  2215.         }
  2216.  
  2217.         if ( dialfc == FLO_XONX ) {
  2218.             lpModemSettings->dwPreferredModemOptions &= ~MDM_FLOWCONTROL_HARD;
  2219.             lpModemSettings->dwPreferredModemOptions |= MDM_FLOWCONTROL_SOFT;
  2220.         }
  2221.         else if ( dialfc == FLO_RTSC ) {
  2222.             lpModemSettings->dwPreferredModemOptions |= MDM_FLOWCONTROL_HARD;
  2223.             lpModemSettings->dwPreferredModemOptions &= ~MDM_FLOWCONTROL_SOFT;
  2224.         }
  2225.         else if ( dialfc == FLO_NONE ) {
  2226.             lpModemSettings->dwPreferredModemOptions &= ~MDM_FLOWCONTROL_HARD;
  2227.             lpModemSettings->dwPreferredModemOptions &= ~MDM_FLOWCONTROL_SOFT;
  2228.         }
  2229. #endif /* NODIAL */
  2230.  
  2231.         switch(flow) {
  2232.         case FLO_XONX:
  2233.             lpDCB->fOutX = TRUE ;
  2234.             lpDCB->fInX = TRUE ;
  2235.             lpDCB->fRtsControl = RTS_CONTROL_ENABLE ;
  2236.             lpDCB->fOutxCtsFlow = FALSE ;
  2237.             lpDCB->fTXContinueOnXoff = FALSE ;
  2238. #ifndef NODIAL
  2239.             if ( dialfc == FLO_AUTO ) 
  2240. #endif /* NODIAL */
  2241.             {
  2242.                 lpModemSettings->dwPreferredModemOptions &= ~MDM_FLOWCONTROL_HARD;
  2243.                 lpModemSettings->dwPreferredModemOptions |= MDM_FLOWCONTROL_SOFT;
  2244.             }
  2245.             break;
  2246.         case FLO_RTSC:
  2247.             lpDCB->fOutX = FALSE ;
  2248.             lpDCB->fInX = FALSE ;
  2249.             lpDCB->fRtsControl = RTS_CONTROL_HANDSHAKE ;
  2250.             lpDCB->fOutxCtsFlow = TRUE ;
  2251.             lpDCB->fTXContinueOnXoff = TRUE ;
  2252. #ifndef NODIAL
  2253.             if ( dialfc == FLO_AUTO )
  2254. #endif /* NODIAL */
  2255.             {
  2256.                 lpModemSettings->dwPreferredModemOptions |= MDM_FLOWCONTROL_HARD;
  2257.                 lpModemSettings->dwPreferredModemOptions &= ~MDM_FLOWCONTROL_SOFT;
  2258.             }
  2259.             break;
  2260.         case FLO_KEEP:
  2261.             /* leave things exactly as they are */
  2262.             break;
  2263.         case FLO_NONE:
  2264.             /* turn off all flow control completely */
  2265.             lpDCB->fOutX = FALSE ;
  2266.             lpDCB->fInX = FALSE ;
  2267.             lpDCB->fRtsControl = RTS_CONTROL_ENABLE ;
  2268.             lpDCB->fOutxCtsFlow = FALSE ;
  2269.             lpDCB->fTXContinueOnXoff = TRUE ;
  2270. #ifndef NODIAL
  2271.             if ( dialfc == FLO_AUTO ) 
  2272. #endif /* NODIAL */
  2273.             {
  2274.                 lpModemSettings->dwPreferredModemOptions &= ~MDM_FLOWCONTROL_HARD;
  2275.                 lpModemSettings->dwPreferredModemOptions &= ~MDM_FLOWCONTROL_SOFT;
  2276.             }
  2277.             break;
  2278.         }
  2279.  
  2280. #ifndef NODIAL
  2281.         /* Speaker settings */
  2282.         lpModemSettings->dwSpeakerMode   = mdmspk;
  2283.         lpModemSettings->dwSpeakerVolume = mdmvol-1;
  2284. #endif /* NODIAL */
  2285.  
  2286.         lpDCB->XonChar = 0x11 ;
  2287.         lpDCB->XoffChar = 0x13;
  2288.         lpDCB->XonLim = 10 ;
  2289.         lpDCB->XoffLim = 10 ;
  2290.     }
  2291.  
  2292.     if (!cktapiSetModemSettings(lpDevCfg,lpCommConfig)) {
  2293.         return FALSE;
  2294.     }
  2295.  
  2296.     return (TRUE);
  2297.  
  2298. }
  2299.  
  2300. #ifndef NODIAL
  2301. int
  2302. cktapidial(char * number)
  2303. {
  2304.     LINECALLPARAMS lcp;
  2305.     int rc=0;
  2306.  
  2307.     fail_code = 0;
  2308.     if ( tapipass ) {
  2309.         debug(F110,"cktapidial - should never have been called",number,0);
  2310.         return FALSE;
  2311.     }
  2312.  
  2313.     debug(F110,"cktapidial",number,0);
  2314.  
  2315.     g_bReplyReceived = FALSE;
  2316.     g_bConnected = FALSE;
  2317.     g_bDialing = TRUE;
  2318.     g_lAsyncReply = SUCCESS;
  2319.     ResetTAPIConnectSem();
  2320.  
  2321.     if ( g_hCall == (HCALL)0 ) {
  2322.         cktapiconfigline();
  2323.  
  2324.         memset(&lcp,0,sizeof(LINECALLPARAMS));
  2325.         lcp.dwBearerMode = LINEBEARERMODE_VOICE;
  2326.         lcp.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
  2327.         lcp.dwTotalSize = sizeof(LINECALLPARAMS);
  2328.         lcp.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE | LINECALLPARAMFLAGS_SECURE;
  2329. #ifdef COMMENT
  2330.         lcp.dwNoAnswerTimeout = waitct; /* TAPI 2.0 */
  2331. #endif /* COMMENT */
  2332.         g_dwRequestedID = 0;
  2333.         rc = g_dwRequestedID = (*cklineMakeCall)( g_hLine, &g_hCall, number, 0, &lcp ) ;
  2334.         OutputDebugLastError(rc,"lineMakeCall:");
  2335.     }
  2336.     else {
  2337.         g_dwRequestedID = 0;
  2338.         rc = g_dwRequestedID = (*cklineDial)( g_hCall, number, 0 ) ;
  2339.         OutputDebugLastError(rc,"lineDial:");
  2340.     }
  2341.     if ( rc < 0 )
  2342.     {
  2343.        if ( rc == LINEERR_CALLUNAVAIL ||
  2344.             rc == LINEERR_INUSE ||
  2345.             rc == LINEERR_NODEVICE ) {
  2346.            fail_code = F_MINIT;
  2347.        }
  2348.  
  2349. #ifdef BETADEBUG
  2350.         printf("lineMakeCall failed rc=%x\n",rc ) ;
  2351. #endif
  2352.         if ( dialdpy )
  2353.             printf("Call failed: %s\n",cktapiErrorString(rc));
  2354.         g_hCall = (HCALL)0;
  2355.         cktapiclose();
  2356.         g_bDialing = FALSE;
  2357.         return FALSE;
  2358.     }
  2359.     else {
  2360.         int x = 0;
  2361. #ifdef BETADEBUG
  2362.         printf("lineMakeCall successful\n");
  2363. #endif
  2364.         /* Wait for LineReply */
  2365.         while ( !g_bReplyReceived && fail_code == 0 ) {
  2366.             msleep(100);
  2367.             x += 100;
  2368.             if ( x == 5000 ) {
  2369.                 debug(F110,"cktapidial",
  2370.                        "lineMakeCall/Dial Reply never received",0);
  2371.                 break;
  2372.             }
  2373.         }
  2374.  
  2375.         if ( fail_code == 0 )
  2376.             OutputDebugLastError(g_lAsyncReply,
  2377.                                   "lineMakeCall/Dial (Async):");
  2378.         else
  2379.             debug(F111,"cktapidial","fail_code",fail_code);
  2380.  
  2381.         if ( fail_code == F_INT ||
  2382.              fail_code == F_MINIT ) {     /* Catch early if possible */
  2383.             cktapihangup();
  2384.             g_bDialing = FALSE;
  2385.             return FALSE;
  2386.         }
  2387.  
  2388.         if ( g_lAsyncReply != SUCCESS )
  2389.         {
  2390. #ifdef BETADEBUG
  2391.             printf("lineMakeCall failed (Async Reply) rc=%x\n",g_lAsyncReply ) ;
  2392. #endif
  2393.             if ( dialdpy )
  2394.                 printf("Call failed: %s\n",cktapiErrorString(g_lAsyncReply));
  2395.             g_hCall = (HCALL)0;
  2396.             cktapiclose();
  2397.             g_bDialing = FALSE;
  2398.             return FALSE;
  2399.         }
  2400.  
  2401.         /* Are we partial dialing? */
  2402.         if ( number[strlen(number)-1] == ';' )
  2403.             return TRUE;
  2404.  
  2405.         /* Wait for Success or Failure of Connection */
  2406.         if (!WaitAndResetTAPIConnectSem(waitct*1000))
  2407.         {
  2408.             debug(F101,"TAPI Connect Timeout","",waitct);
  2409. #ifdef BETADEBUG
  2410.             printf("TAPI connect semaphore never posted\n");
  2411. #endif
  2412.             if ( dialdpy )
  2413.                 printf("Call failed: Timeout\n");
  2414.             g_bDialing = FALSE;
  2415.             return FALSE;
  2416.         }
  2417.         if ( fail_code == F_INT ||
  2418.              fail_code == F_MINIT ) {
  2419.             cktapihangup();
  2420.             g_bDialing = FALSE;
  2421.             return FALSE;
  2422.         }
  2423.     }
  2424.  
  2425.     if ( !g_bConnected ) {
  2426.         cktapihangup();
  2427.         g_bDialing = FALSE;
  2428.         return FALSE;
  2429.     }
  2430.  
  2431.     if ( ttyfd == -1 || ttyfd == -2 ) {
  2432.         /* if we did not get the Comm handle via the CONNECT message */
  2433.         /* then get it now                                           */
  2434.         ttyfd = (int) GetModemHandleFromLine( g_hLine );
  2435.         SetCommMask( (HANDLE) ttyfd, EV_RXCHAR ) ;
  2436.         SetupComm( (HANDLE) ttyfd, 20000, 20000 ) ;
  2437.         PurgeComm( (HANDLE) ttyfd,
  2438.                    PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR ) ;
  2439.     }
  2440.     if ( !ttyfd || ttyfd == -1 ) {
  2441.         ttyfd = -2 ;
  2442.         g_bDialing = FALSE;
  2443.         return FALSE;
  2444.     }
  2445. #ifdef BETADEBUG
  2446.         DisplayCommProperties((HANDLE)ttyfd);
  2447. #endif /* BETADEBUG */
  2448.  
  2449.     g_bDialing = FALSE;
  2450.     return TRUE;
  2451. }
  2452.  
  2453. int
  2454. cktapianswer( void )
  2455. {
  2456.     int rc=0,x=0;
  2457.     extern int dialatmo;
  2458.     char * filename=NULL, *p=NULL;
  2459.  
  2460.     filename = GetLoadPath();
  2461.     if ( filename && *filename ) {
  2462.         p = filename + strlen(filename);
  2463.         while ( p != filename ) {
  2464.             if ( *p == '\\' || *p == '/' )
  2465.             {
  2466.                 filename = p + 1 ;
  2467.                 break;
  2468.             }
  2469.             p--;
  2470.         }
  2471.         if ( filename >= p ) {
  2472.             rc = (*cklineSetAppPriority)(filename,LINEMEDIAMODE_DATAMODEM,
  2473.                                      NULL,0,NULL,1);
  2474.             OutputDebugLastError(rc,"lineSetAppPriority:");
  2475. #ifdef BETADEBUG
  2476.             printf("  lineSetAppPriority rc=0x%x\n",rc);
  2477. #endif
  2478.         }
  2479.     }
  2480.  
  2481.     /* Wait for LINECALLSTATE_OFFERING to get the hCall */
  2482.     fail_code = 0;
  2483.     g_bAnswering = TRUE;
  2484.     ResetTAPIAnswerSem();
  2485.     rc = WaitAndResetTAPIAnswerSem(dialatmo<=0?INFINITE:dialatmo*1000);
  2486.  
  2487.     if ( !rc ) {
  2488. #ifdef BETADEBUG
  2489.         printf("TAPI Answer Sem never SET\n",rc ) ;
  2490. #endif
  2491.         if ( dialdpy )
  2492.             printf("Answer failed: Timeout\n");
  2493.         return FALSE;
  2494.     }
  2495.     if ( fail_code == F_INT ) {
  2496.         g_bAnswering = FALSE;
  2497.         cktapihangup();
  2498.         return FALSE;
  2499.     }
  2500.  
  2501.     /* Then use lineAnswer() to CONNECT to the call */
  2502.     g_bReplyReceived = FALSE;
  2503.     g_lAsyncReply = SUCCESS;
  2504.     g_bConnected = FALSE;
  2505.     ResetTAPIConnectSem();
  2506.  
  2507.     g_dwRequestedID = 0;
  2508.     rc = g_dwRequestedID = (*cklineAccept)( g_hCall, NULL, 0) ;
  2509.     OutputDebugLastError(rc,"lineAccept:");
  2510.     if ( rc < 0 )
  2511.     {
  2512. #ifdef BETADEBUG
  2513.         printf("lineAccept failed rc=%x\n",rc ) ;
  2514. #endif
  2515.         if ( dialdpy )
  2516.             printf("Answer failed: %s\n",cktapiErrorString(rc));
  2517.         g_bAnswering = FALSE;
  2518.         cktapihangup();
  2519.         return FALSE;
  2520.     }
  2521.  
  2522.     /* Wait for LineReply */
  2523.     while ( !g_bReplyReceived && fail_code == 0 ) {
  2524.         msleep(100);
  2525.         x += 100;
  2526.         if ( x == 5000 ) {
  2527.             debug(F110,"cktapianswer",
  2528.                    "lineAccept Reply never received",0);
  2529.             if ( dialdpy )
  2530.                 printf("Answer failed: required TAPI reply never received.\n");
  2531.             g_bAnswering = FALSE;
  2532.             cktapihangup();
  2533.             return FALSE;
  2534.         }
  2535.     }
  2536.  
  2537.     if ( g_lAsyncReply != SUCCESS && g_lAsyncReply != LINEERR_OPERATIONUNAVAIL)
  2538.     {
  2539. #ifdef BETADEBUG
  2540.         printf("lineAccept failed (Async Reply) rc=%x\n",g_lAsyncReply ) ;
  2541. #endif
  2542.         if ( dialdpy )
  2543.             printf("Answer failed: %s\n",cktapiErrorString(g_lAsyncReply));
  2544.         g_bAnswering = FALSE;
  2545.         cktapihangup();
  2546.         return FALSE;
  2547.     }
  2548. #ifdef BETADEBUG
  2549.     printf("lineAccept successful\n");
  2550. #endif
  2551.  
  2552.     g_bReplyReceived = FALSE;
  2553.     g_lAsyncReply = SUCCESS;
  2554.     g_dwRequestedID = 0;
  2555.     rc = g_dwRequestedID = (*cklineAnswer)( g_hCall, NULL, 0) ;
  2556.     OutputDebugLastError(rc,"lineAnswer:");
  2557.     if ( rc < 0 )
  2558.     {
  2559. #ifdef BETADEBUG
  2560.         printf("lineAnswer failed rc=%x\n",rc ) ;
  2561. #endif
  2562.         if ( dialdpy )
  2563.             printf("Answer failed: %s\n",cktapiErrorString(rc));
  2564.         g_bAnswering = FALSE;
  2565.         cktapihangup();
  2566.         return FALSE;
  2567.     }
  2568.  
  2569.     /* Wait for LineReply */
  2570.     while ( !g_bReplyReceived && fail_code == 0 ) {
  2571.         msleep(100);
  2572.         x += 100;
  2573.         if ( x == waitct*1000 ) {
  2574.             debug(F110,"cktapianswer",
  2575.                    "lineAnswer Reply never received",0);
  2576.             if ( dialdpy )
  2577.                 printf("Answer failed: required TAPI reply never received.\n");
  2578.             g_bAnswering = FALSE;
  2579.             cktapihangup();
  2580.             return FALSE;
  2581.         }
  2582.     }
  2583.  
  2584.     OutputDebugLastError(g_lAsyncReply,"lineAnswer (Async):");
  2585.  
  2586.     if ( g_lAsyncReply  != SUCCESS )
  2587.     {
  2588. #ifdef BETADEBUG
  2589.         printf("lineAnswer failed (Async Reply) rc=%x\n",g_lAsyncReply ) ;
  2590. #endif
  2591.         if ( dialdpy )
  2592.             printf("Answer failed: %s\n",cktapiErrorString(g_lAsyncReply));
  2593.         g_bAnswering = FALSE;
  2594.         cktapihangup();
  2595.         return FALSE;
  2596.     }
  2597.  
  2598. #ifdef BETADEBUG
  2599.     printf("lineAnswer successful\n");
  2600. #endif
  2601.  
  2602.     /* Wait for Success or Failure of Connection */
  2603.     if (!WaitAndResetTAPIConnectSem(waitct>0?waitct*1000:60000))
  2604.     {
  2605. #ifdef BETADEBUG
  2606.         printf("TAPI connect semaphore never posted\n");
  2607. #endif
  2608.         if ( dialdpy )
  2609.             printf("Answer failed: Carrier Detect Timeout\n");
  2610.         g_bAnswering = FALSE;
  2611.         cktapihangup();
  2612.         return FALSE;
  2613.     }
  2614.     if ( fail_code == F_INT || !g_bConnected ) {
  2615.         g_bAnswering = FALSE;
  2616.         cktapihangup();
  2617.         return FALSE;
  2618.     }
  2619.  
  2620. #ifdef BETADEBUG
  2621.     /* But is the call of the correct Media Mode? */
  2622.     {
  2623.         LPLINECALLINFO lpCallInfo = NULL;
  2624.         DWORD          dwSize     = sizeof(LINECALLINFO);
  2625.         LONG           lrc = 0;
  2626.  
  2627.         lpCallInfo = (LPLINECALLINFO) malloc (dwSize);
  2628.         if ( !lpCallInfo ) {
  2629.             g_bAnswering = FALSE;
  2630.             cktapihangup();
  2631.             return FALSE;
  2632.         }
  2633.         memset(lpCallInfo,0,dwSize);
  2634.         lpCallInfo->dwTotalSize = dwSize;
  2635.  
  2636.         do {
  2637.             /* get modem handle associated with the line */
  2638.             lrc = (*cklineGetCallInfo)(g_hCall, lpCallInfo);
  2639.             if ( ( lrc == LINEERR_STRUCTURETOOSMALL || lrc == 0 ) &&
  2640.                  (lpCallInfo->dwTotalSize < lpCallInfo->dwNeededSize) ) {
  2641.                 /* the next six lines reallocate the VARSTRING */
  2642.                 dwSize = lpCallInfo->dwNeededSize ;
  2643.                 free(lpCallInfo);
  2644.                 lpCallInfo = (LPLINECALLINFO) malloc(dwSize);
  2645.                 if ( !lpCallInfo ) {
  2646.                     g_bAnswering = FALSE;
  2647.                     cktapihangup();
  2648.                     return FALSE;
  2649.                 }
  2650.                 memset(lpCallInfo,0,dwSize);
  2651.                 lpCallInfo->dwTotalSize = dwSize ;
  2652.             }
  2653.             else if ( lrc ) {
  2654.                 /* some kind of TAPI error */
  2655.                 OutputDebugLastError(lrc,"lineGetCallInfo:");
  2656.                 free(lpCallInfo);
  2657.                 g_bAnswering = FALSE;
  2658.                 cktapihangup();
  2659.                 return FALSE;
  2660.             }
  2661.             else
  2662.                 break;  /* success */
  2663.         } while ( TRUE );
  2664.  
  2665.         /* what is the media mode */
  2666.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_UNKNOWN )
  2667.             printf("  MediaMode is UNKNOWN (it may be one of the following)\n");
  2668.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_INTERACTIVEVOICE )
  2669.             printf("  MediaMode is Interactive Voice\n");
  2670.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_AUTOMATEDVOICE )
  2671.             printf("  MediaMode is Automated Voice\n");
  2672.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_TDD )
  2673.             printf("  MediaMode is TDD\n");
  2674.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_DIGITALDATA )
  2675.             printf("  MediaMode is Digital Data\n");
  2676.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_TELETEX )
  2677.             printf("  MediaMode is TeleTex\n");
  2678.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_VIDEOTEX )
  2679.             printf("  MediaMode is VideoTex\n");
  2680.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_MIXED )
  2681.             printf("  MediaMode is Mixed\n");
  2682.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_ADSI )
  2683.             printf("  MediaMode is ADSI\n");
  2684.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_VOICEVIEW )
  2685.             printf("  MediaMode is VoiceView\n");
  2686.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_DATAMODEM )
  2687.             printf("  MediaMode is DataModem\n");
  2688.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_G3FAX )
  2689.             printf("  MediaMode is G3Fax\n");
  2690.         if ( lpCallInfo->dwMediaMode & LINEMEDIAMODE_G4FAX )
  2691.             printf("  MediaMode is G4Fax\n");
  2692.         if ( lpCallInfo->dwMediaMode > LAST_LINEMEDIAMODE*2-1 )
  2693.             printf("  MediaMode is %x\n", lpCallInfo->dwMediaMode );
  2694.         free(lpCallInfo);
  2695.     }
  2696. #endif /* BETADEBUG */
  2697.  
  2698.     if ( ttyfd == -1 || ttyfd == -2 ) {
  2699.         /* if we did not get the Comm handle via the CONNECT message */
  2700.         /* then get it now                                           */
  2701.         ttyfd = (int) GetModemHandleFromLine( g_hLine );
  2702.         SetCommMask( (HANDLE) ttyfd, EV_RXCHAR ) ;
  2703.         SetupComm( (HANDLE) ttyfd, 20000, 20000 ) ;
  2704.         PurgeComm( (HANDLE) ttyfd,
  2705.                    PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR ) ;
  2706.     }
  2707.     if ( !ttyfd || ttyfd == -1 ) {
  2708.         ttyfd = -2 ;
  2709.         g_bAnswering = FALSE;
  2710.         return FALSE;
  2711.     }
  2712.  
  2713. #ifdef BETADEBUG
  2714.     DisplayCommProperties((HANDLE)ttyfd);
  2715. #endif /* BETADEBUG */
  2716.  
  2717.     /* turn off media montoring since we have already accepted the call */
  2718.     /* as a data modem call                                             */
  2719.     (*cklineMonitorMedia)(g_hCall,0);
  2720.     g_bAnswering = FALSE;
  2721.     return TRUE;
  2722. }
  2723. #endif /* NODIAL */
  2724.  
  2725. int
  2726. cktapiBuildLineTable( struct keytab ** pTable, struct keytab ** pTable2, int * pN )
  2727. {
  2728.     int i, n ;
  2729.     if ( *pTable )
  2730.     {
  2731.         for ( i=0 ; i < *pN ; i++ )
  2732.             free( (*pTable)[i].kwd ) ;
  2733.         free ( *pTable )  ;
  2734.     }
  2735.  
  2736.     if ( *pTable2 )
  2737.     {
  2738.         for ( i=0 ; i < *pN ; i++ )
  2739.             free( (*pTable2)[i].kwd ) ;
  2740.         free ( *pTable2 )  ;
  2741.     }
  2742.  
  2743.     *pTable = NULL ;
  2744.     *pTable2 = NULL ;
  2745.     *pN = 0 ;
  2746.  
  2747.     if (!TAPIAvail)
  2748.         return(0);
  2749.  
  2750.     cktapiopen() ;
  2751.     n = cktapidevenum() ;
  2752.     cktapiclose() ;
  2753.  
  2754.     debug(F100,"TAPI cktapiBuildLineTable","",0);
  2755.     if ( n )
  2756.     {
  2757.         *pTable = malloc( sizeof(struct keytab) * n ) ;
  2758.         *pTable2 = malloc( sizeof(struct keytab) * n ) ;
  2759.  
  2760.         for ( i=0 ; i < g_dwNumDevs ; i++ ) {
  2761.             if ( g_lpLineDevCaps[i] == NULL )
  2762.             {
  2763.                 debug(F111,"TAPI LineDevCaps entry is NULL","i",i);
  2764.             }
  2765.             else if ( g_lpLineDevCaps[i]->dwMediaModes & LINEMEDIAMODE_DATAMODEM )
  2766.             {
  2767.                char * newstr = _strdup( ((char *)(g_lpLineDevCaps[i]))+g_lpLineDevCaps[i]->dwLineNameOffset) ;
  2768.                char * newstr2 = _strdup( ((char *)(g_lpLineDevCaps[i]))+g_lpLineDevCaps[i]->dwLineNameOffset) ;
  2769.                int    newval = i;
  2770.                int j = 0, len = 0;
  2771.  
  2772.                debug(F111,"TAPI LINEMEDIAMODE_DATAMODEM",newstr,i);
  2773.  
  2774.                /* Make a version that uses Underscores instead of spaces */
  2775.                len = strlen(newstr2);
  2776.                for ( j=0 ; j<len ; j++) {
  2777.                    switch ( newstr2[j] ) {
  2778.                    case ' ':
  2779.                        newstr2[j] = '_';
  2780.                        break;
  2781.                    case ',':
  2782.                        newstr2[j] = '.';
  2783.                        break;
  2784.                    case ';':
  2785.                        newstr2[j] = ':';
  2786.                        break;
  2787.                    case '\\':
  2788.                        newstr2[j] = '/';
  2789.                        break;
  2790.                    case '?':
  2791.                        newstr2[j] = '!';
  2792.                        break;
  2793.                    case '{':
  2794.                        newstr2[j] = '[';
  2795.                        break;
  2796.                    case '}':
  2797.                        newstr2[j] = ']';
  2798.                        break;
  2799.                    }
  2800.                }
  2801.  
  2802.                for ( j=0 ; j < (*pN) ; j++ ) {
  2803.                    int tempval=0;
  2804.                    char * tempstr=NULL,*tempstr2=NULL;
  2805.  
  2806.                    if ( _stricmp( (*pTable)[j].kwd, newstr ) > 0 )
  2807.                    {
  2808.                        tempval = (*pTable)[j].kwval;
  2809.                        tempstr = (*pTable)[j].kwd;
  2810.                        tempstr2 = (*pTable2)[j].kwd;
  2811.                        (*pTable)[j].kwd = newstr ;
  2812.                        (*pTable)[j].kwval = newval;
  2813.                        (*pTable2)[j].kwd = newstr2 ;
  2814.                        (*pTable2)[j].kwval = newval;
  2815.                        newval = tempval;
  2816.                        newstr = tempstr;
  2817.                        (*pTable)[j].flgs = 0;
  2818.                        newstr2 = tempstr2;
  2819.                        (*pTable2)[j].flgs = 0;
  2820.                    }
  2821.                }
  2822.                (*pTable)[*pN].kwd = newstr ;
  2823.                (*pTable)[*pN].kwval = newval;
  2824.                (*pTable)[*pN].flgs = 0 ;
  2825.                (*pTable2)[*pN].kwd = newstr2 ;
  2826.                (*pTable2)[*pN].kwval = newval;
  2827.                (*pTable2)[*pN].flgs = 0 ;
  2828.                (*pN)++ ;
  2829.            }
  2830.             else
  2831.             {
  2832.                debug(F111,"TAPI ~LINEMEDIAMODE_DATAMODEM",
  2833.                       ((char *)(g_lpLineDevCaps[i]))+g_lpLineDevCaps[i]->dwLineNameOffset,
  2834.                       i);
  2835.             }
  2836.        }
  2837.  
  2838.        if ( *pN == 0 ) {
  2839.            /* TAPI Devices exist, but none can be used by Kermit */
  2840.            free ( *pTable )  ;
  2841.            free ( *pTable2 )  ;
  2842.            *pTable = NULL;
  2843.            *pTable2 = NULL;
  2844.        }
  2845.    }
  2846.     return(1);
  2847. }
  2848.  
  2849.  
  2850. int
  2851. cktapiBuildLocationTable( struct keytab ** pTable, int * pN )
  2852. {
  2853.    LPLINETRANSLATECAPS lpTranslateCaps = NULL;
  2854.    DWORD dwSizeofTranslateCaps = sizeof(LINETRANSLATECAPS);
  2855.    long lReturn = 0;
  2856.    DWORD dwCounter;
  2857.    LPLINELOCATIONENTRY lpLocationEntry;
  2858.    LPLINECARDENTRY lpLineCardEntry = NULL;
  2859.    int i = 0 ;
  2860.  
  2861.    if ( *pTable )
  2862.    {
  2863.       for ( i=0 ; i < *pN ; i++ )
  2864.          free( (*pTable)[i].kwd ) ;
  2865.       free ( *pTable )  ;
  2866.    }
  2867.    *pTable = NULL ;
  2868.    *pN = 0 ;
  2869.  
  2870.     if (!TAPIAvail)
  2871.         return(0);
  2872.  
  2873.     cktapiopen() ;
  2874.  
  2875.    // First, get the TRANSLATECAPS
  2876.    do
  2877.    {
  2878.       lpTranslateCaps = (LPLINETRANSLATECAPS) CheckAndReAllocBuffer(
  2879.                  (LPVOID) lpTranslateCaps, dwSizeofTranslateCaps,
  2880.                  "cktapiBuildLocationTable");
  2881.  
  2882.       if (lpTranslateCaps == NULL)
  2883.       {
  2884.          cktapiclose();
  2885.          return 0;
  2886.       }
  2887.  
  2888.       lReturn = (*cklineGetTranslateCaps)(g_hLineApp, TAPI_CURRENT_VERSION,
  2889.                                       lpTranslateCaps);
  2890.  
  2891.       if (HandleLineErr(lReturn))
  2892.          ;
  2893.       else
  2894.       {
  2895.          OutputDebugLineError(lReturn,
  2896.                                "lineGetTranslateCaps unhandled error: ");
  2897.          LocalFree(lpTranslateCaps);
  2898.          cktapiclose();
  2899.          return 0;
  2900.       }
  2901.  
  2902.       if ((lpTranslateCaps -> dwNeededSize) >
  2903.            (lpTranslateCaps -> dwTotalSize))
  2904.       {
  2905.          dwSizeofTranslateCaps = lpTranslateCaps ->dwNeededSize;
  2906.          lReturn = -1; // Lets loop again.
  2907.       }
  2908.    }
  2909.    while(lReturn != SUCCESS);
  2910.  
  2911.    cktapiclose() ;
  2912.  
  2913.     debug(F100,"TAPI cktapiBuildLocationTable","",0);
  2914.    // Find the location information in the TRANSLATECAPS
  2915.    lpLocationEntry = (LPLINELOCATIONENTRY)
  2916.       (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset);
  2917.  
  2918.  
  2919.    if ( lpTranslateCaps->dwNumLocations > 0 )
  2920.    {
  2921.       *pTable = malloc( sizeof(struct keytab) * lpTranslateCaps->dwNumLocations ) ;
  2922.  
  2923.       // enumerate all the locations
  2924.       for(dwCounter = 0;
  2925.            dwCounter < lpTranslateCaps -> dwNumLocations;
  2926.            dwCounter++)
  2927.       {
  2928.          // Put each one into the keytab
  2929.           char * newstr = _strdup((((LPBYTE) lpTranslateCaps) +
  2930.                                         lpLocationEntry[dwCounter].dwLocationNameOffset)) ;
  2931.           int    newval = lpLocationEntry[dwCounter].dwPermanentLocationID;
  2932.           int j = 0, len = 0;
  2933.  
  2934.           debug(F111,"TAPI lpLocationEntry.dwLocationName",newstr,i);
  2935.  
  2936.           /* Use Underscores instead of spaces */
  2937.           len = strlen(newstr);
  2938.           for ( j=0;j<len;j++ )
  2939.           {
  2940.               switch ( newstr[j] ) {
  2941.               case ' ':
  2942.                   newstr[j] = '_';
  2943.                   break;
  2944.               case ',':
  2945.                   newstr[j] = '.';
  2946.                   break;
  2947.               case ';':
  2948.                   newstr[j] = ':';
  2949.                   break;
  2950.               case '\\':
  2951.                   newstr[j] = '/';
  2952.                   break;
  2953.               case '?':
  2954.                   newstr[j] = '!';
  2955.                   break;
  2956.               case '{':
  2957.                   newstr[j] = '[';
  2958.                   break;
  2959.               case '}':
  2960.                   newstr[j] = ']';
  2961.                   break;
  2962.               }
  2963.           }
  2964.  
  2965.           for ( j=0 ; j < dwCounter ; j++ ) {
  2966.               int tempval=0;
  2967.               char * tempstr=NULL;
  2968.  
  2969.               if ( _stricmp( (*pTable)[j].kwd, newstr ) > 0 )
  2970.               {
  2971.                   tempval = (*pTable)[j].kwval;
  2972.                   tempstr = (*pTable)[j].kwd;
  2973.                   (*pTable)[j].kwd = newstr ;
  2974.                   (*pTable)[j].kwval = newval;
  2975.                   newval = tempval;
  2976.                   newstr = tempstr;
  2977.                   (*pTable)[j].flgs = 0;
  2978.               }
  2979.           }
  2980.           (*pTable)[*pN].kwd = newstr;
  2981.           (*pTable)[*pN].kwval = newval ;
  2982.           (*pTable)[*pN].flgs = 0 ;
  2983.           (*pN)++ ;
  2984.       }
  2985.     }
  2986.     LocalFree(lpTranslateCaps);
  2987.     return(1);
  2988. }
  2989.  
  2990. int
  2991. cktapiGetCurrentLocationID( void )
  2992. {
  2993.     LPLINETRANSLATECAPS lpTranslateCaps = NULL;
  2994.     DWORD dwSizeofTranslateCaps = sizeof(LINETRANSLATECAPS);
  2995.     long lReturn;
  2996.     int  locationID=-1;
  2997.  
  2998.     debug(F100,"cktapiGetCurrentLocationID","",0);
  2999.  
  3000.     // First, get the TRANSLATECAPS
  3001.     do
  3002.     {
  3003.         lpTranslateCaps =
  3004.             (LPLINETRANSLATECAPS) CheckAndReAllocBuffer((LPVOID) lpTranslateCaps,
  3005.                                                          dwSizeofTranslateCaps,
  3006.                                                          "cktapiGetCurrentLocationID");
  3007.  
  3008.         if (lpTranslateCaps == NULL) {
  3009.             debug(F110,"cktapiGetCurrentLocationID","lpTranslateCaps == NULL",0);
  3010.             return -1;
  3011.         }
  3012.  
  3013.  
  3014.         lReturn = (*cklineGetTranslateCaps)(g_hLineApp, TAPI_CURRENT_VERSION,
  3015.                                              lpTranslateCaps);
  3016.         debug(F111,"cktapiGetCurrentLocationID","cklineGetTranslateCaps returns",lReturn);
  3017.  
  3018.         if (!HandleLineErr(lReturn))
  3019.         {
  3020.             OutputDebugLineError(lReturn,
  3021.                                   "lineGetTranslateCaps unhandled error: ");
  3022.             LocalFree(lpTranslateCaps);
  3023.             return -1;
  3024.         }
  3025.  
  3026.         if ((lpTranslateCaps -> dwNeededSize) >
  3027.              (lpTranslateCaps -> dwTotalSize))
  3028.         {
  3029.             dwSizeofTranslateCaps = lpTranslateCaps ->dwNeededSize;
  3030.             lReturn = -1; // Lets loop again.
  3031.         }
  3032.     }
  3033.     while(lReturn != SUCCESS);
  3034.  
  3035.     locationID = lpTranslateCaps->dwCurrentLocationID;
  3036.  
  3037.     LocalFree(lpTranslateCaps);
  3038.     debug(F111,"cktapiGetCurrentLocationID","locationID",locationID);
  3039.     return locationID;
  3040. }
  3041.  
  3042. void
  3043. cktapiDisplayTapiLocationInfo( void )
  3044. {
  3045.     printf("TAPI Location (%d): %s\n", tapilocid, tapiloc );
  3046.     printf("  Country ID         = %d\n", tapiCountryID);
  3047.     printf("  CountryCode        = %d\n", tapiCountryCode);
  3048.     printf("   CountryName       = %s\n", tapiCountryName);
  3049.     printf("   SameAreaRule      = %s\n", tapiSameAreaRule);
  3050.     printf("   LongDistanceRule  = %s\n", tapiLongDistanceRule);
  3051.     printf("   InternationalRule = %s\n", tapiInternationalRule);
  3052.     printf("  AreaCode           = %s\n", tapiAreaCode);
  3053.     printf("  PreferredCardID    = %d\n", tapiPreferredCardID);
  3054.     printf("  LocalAccessCode    = %s\n", tapiLocalAccessCode);
  3055.     printf("  LongDistAccessCode = %s\n", tapiLongDistAccessCode);
  3056.     printf("  TollPrefixList     = %s\n", tapiTollPrefixList);
  3057.     printf("  CancelCallWaiting  = %s\n", tapiCancelCallWaiting);
  3058.     printf("  Options            = %d\n", tapiOptions);
  3059. }
  3060.  
  3061. void
  3062. SaveTapiLocationInfo( LPLINETRANSLATECAPS lpTranslateCaps,
  3063.                       LPLINELOCATIONENTRY lpLocationEntry )
  3064. {
  3065.     LPLINECOUNTRYLIST  lpCountryList  = NULL;
  3066.     LPLINECOUNTRYENTRY lpCountryEntry = NULL;
  3067.     DWORD dwSizeofCountryList = sizeof(LINECOUNTRYLIST);
  3068.     long lReturn=0;
  3069.     int i=0;
  3070.  
  3071.     debug(F111,"SaveTapiLocationInfo","lpTranslateCaps",lpTranslateCaps);
  3072.     debug(F111,"SaveTapiLocationInfo","lpLocationEntry",lpLocationEntry);
  3073.  
  3074.     tapilocid = lpLocationEntry->dwPermanentLocationID;
  3075.     tapiCountryID = lpLocationEntry->dwCountryID;
  3076.     tapiCountryCode = lpLocationEntry->dwCountryCode;
  3077.     strncpy(tapiloc,
  3078.              (((LPSTR) lpTranslateCaps) +
  3079.                lpLocationEntry->dwLocationNameOffset),
  3080.              lpLocationEntry->dwLocationNameSize >= 256 ? 256 :
  3081.              lpLocationEntry->dwLocationNameSize);
  3082.     tapiloc[256]='\0';
  3083.     debug(F111,"SaveTapiLocationInfo",tapiloc,lpLocationEntry->dwLocationNameSize);
  3084.  
  3085.     do
  3086.     {
  3087.         lpCountryList =
  3088.             (LPLINECOUNTRYLIST) CheckAndReAllocBuffer((LPVOID) lpCountryList,
  3089.                                                          dwSizeofCountryList,
  3090.                                                          "SaveTapiLocationInfo");
  3091.  
  3092.         if (lpCountryList == NULL)
  3093.             return;
  3094.  
  3095.         /* Win95 doesn't return anything is CountryID is 1 */
  3096.         lReturn = (*cklineGetCountry)(isWin95()?0:tapiCountryID, TAPI_CURRENT_VERSION, lpCountryList);
  3097.  
  3098.         if (HandleLineErr(lReturn))
  3099.             ;
  3100.         else
  3101.         {
  3102.             OutputDebugLineError(lReturn,
  3103.                                   "lineGetCountry unhandled error: ");
  3104.             LocalFree(lpCountryList);
  3105.             return;
  3106.         }
  3107.  
  3108.         if ((lpCountryList -> dwNeededSize) >
  3109.              (lpCountryList -> dwTotalSize))
  3110.         {
  3111.             dwSizeofCountryList = lpCountryList ->dwNeededSize;
  3112.             lReturn = -1; // Lets loop again.
  3113.         }
  3114.     }
  3115.     while(lReturn != SUCCESS);
  3116.  
  3117.     for ( i=0; i<lpCountryList->dwNumCountries; i++)
  3118.     {
  3119.         lpCountryEntry = (LPLINECOUNTRYENTRY) ((BYTE *)lpCountryList +
  3120.                                                 lpCountryList->dwCountryListOffset +
  3121.                                                 (i * sizeof(LINECOUNTRYENTRY)));
  3122.         if ( lpCountryEntry->dwCountryID == tapiCountryID )
  3123.             break;
  3124.     }
  3125.     if ( i == lpCountryList->dwNumCountries )
  3126.         lpCountryEntry = NULL;
  3127.  
  3128.     if ( lpCountryEntry ) {
  3129.         /* 'E' = Country Code */
  3130.         /* 'F' = Area Code    */
  3131.         /* 'G' = Local Number */
  3132.         strncpy(tapiCountryName,
  3133.                  ((LPSTR) lpCountryList +
  3134.                    lpCountryEntry->dwCountryNameOffset),
  3135.                  lpCountryEntry->dwCountryNameSize >= 64 ? 64 :
  3136.                  lpCountryEntry->dwCountryNameSize);
  3137.         tapiCountryName[64]='\0';
  3138.  
  3139.         strncpy(tapiSameAreaRule,((LPSTR) lpCountryList +
  3140.                                   lpCountryEntry->dwSameAreaRuleOffset),
  3141.                  lpCountryEntry->dwSameAreaRuleSize >= 64 ? 64 :
  3142.                  lpCountryEntry->dwSameAreaRuleSize);
  3143.         tapiSameAreaRule[64]='\0';
  3144.  
  3145.         strncpy(tapiLongDistanceRule,((LPSTR) lpCountryList +
  3146.                                   lpCountryEntry->dwLongDistanceRuleOffset),
  3147.                  lpCountryEntry->dwLongDistanceRuleSize >= 64 ? 64 :
  3148.                  lpCountryEntry->dwLongDistanceRuleSize);
  3149.         tapiLongDistanceRule[64]='\0';
  3150.  
  3151.         strncpy(tapiInternationalRule,((LPSTR) lpCountryList +
  3152.                                   lpCountryEntry->dwInternationalRuleOffset),
  3153.                  lpCountryEntry->dwInternationalRuleSize >= 64 ? 64 :
  3154.                  lpCountryEntry->dwInternationalRuleSize);
  3155.         tapiInternationalRule[64]='\0';
  3156.     }
  3157.     else {
  3158.         tapiCountryName[0] = '\0';
  3159.         tapiSameAreaRule[0] = '\0';
  3160.         tapiLongDistanceRule[0] = '\0';
  3161.         tapiInternationalRule[0] = '\0';
  3162.     }
  3163.  
  3164.     strncpy(tapiAreaCode,
  3165.              (((LPSTR) lpTranslateCaps) +
  3166.                lpLocationEntry->dwCityCodeOffset),
  3167.              lpLocationEntry->dwCityCodeSize >= 64 ? 64 :
  3168.              lpLocationEntry->dwCityCodeSize);
  3169.     tapiAreaCode[64]='\0';
  3170.  
  3171.     tapiPreferredCardID = lpLocationEntry->dwPreferredCardID;
  3172.  
  3173.     tapiOptions = lpLocationEntry->dwOptions;
  3174.  
  3175.     strncpy(tapiLocalAccessCode,
  3176.              (((LPSTR) lpTranslateCaps) +
  3177.                lpLocationEntry->dwLocalAccessCodeOffset),
  3178.              lpLocationEntry->dwLocalAccessCodeSize >= 64 ? 64 :
  3179.              lpLocationEntry->dwLocalAccessCodeSize);
  3180.     tapiLocalAccessCode[64]='\0';
  3181.  
  3182.     strncpy(tapiLongDistAccessCode,
  3183.              (((LPSTR) lpTranslateCaps) +
  3184.                lpLocationEntry->dwLongDistanceAccessCodeOffset),
  3185.              lpLocationEntry->dwLongDistanceAccessCodeSize >= 64 ? 64 :
  3186.              lpLocationEntry->dwLongDistanceAccessCodeSize);
  3187.     tapiLongDistAccessCode[64]='\0';
  3188.  
  3189.     strncpy(tapiTollPrefixList,
  3190.              (((LPSTR) lpTranslateCaps) +
  3191.                lpLocationEntry->dwTollPrefixListOffset),
  3192.              lpLocationEntry->dwTollPrefixListSize >= 4096 ? 4096 :
  3193.              lpLocationEntry->dwTollPrefixListSize);
  3194.     tapiTollPrefixList[4096]='\0';
  3195.  
  3196.     strncpy(tapiCancelCallWaiting,
  3197.              (((LPSTR) lpTranslateCaps) +
  3198.                lpLocationEntry->dwCancelCallWaitingOffset),
  3199.              lpLocationEntry->dwCancelCallWaitingSize >= 64 ? 64 :
  3200.              lpLocationEntry->dwCancelCallWaitingSize);
  3201.     tapiCancelCallWaiting[64]='\0';
  3202.  
  3203. #ifdef BETADEBUG
  3204.     cktapiDisplayTapiLocationInfo();
  3205. #endif /* BETADEBUG */
  3206.  
  3207.     LocalFree(lpCountryList);
  3208. }
  3209.  
  3210. int
  3211. cktapiFetchLocationInfoByName( char * CurrentLocation )
  3212. {
  3213.     LPLINETRANSLATECAPS lpTranslateCaps = NULL;
  3214.     DWORD dwSizeofTranslateCaps = sizeof(LINETRANSLATECAPS);
  3215.     long lReturn;
  3216.     DWORD dwCounter;
  3217.     LPLINELOCATIONENTRY lpLocationEntry;
  3218.     LPLINECARDENTRY lpLineCardEntry = NULL;
  3219.  
  3220.     /* If no name specified, use Current Location */
  3221.     if ( !CurrentLocation || !CurrentLocation[0] ) {
  3222.         int ID = cktapiGetCurrentLocationID();
  3223.         return cktapiFetchLocationInfoByID( ID );
  3224.     }
  3225.  
  3226.     // First, get the TRANSLATECAPS
  3227.     do
  3228.     {
  3229.         lpTranslateCaps = (LPLINETRANSLATECAPS) CheckAndReAllocBuffer(
  3230.                  (LPVOID) lpTranslateCaps, dwSizeofTranslateCaps,
  3231.                  "cktapiFetchLocationInfoByName");
  3232.  
  3233.         if (lpTranslateCaps == NULL)
  3234.             return FALSE;
  3235.  
  3236.         lReturn = (*cklineGetTranslateCaps)(g_hLineApp, TAPI_CURRENT_VERSION,
  3237.                                       lpTranslateCaps);
  3238.  
  3239.         if (HandleLineErr(lReturn))
  3240.             ;
  3241.         else
  3242.         {
  3243.             OutputDebugLineError(lReturn,
  3244.                                   "lineGetTranslateCaps unhandled error: ");
  3245.             LocalFree(lpTranslateCaps);
  3246.             return FALSE;
  3247.         }
  3248.  
  3249.         if ((lpTranslateCaps -> dwNeededSize) >
  3250.              (lpTranslateCaps -> dwTotalSize))
  3251.         {
  3252.             dwSizeofTranslateCaps = lpTranslateCaps ->dwNeededSize;
  3253.             lReturn = -1; // Lets loop again.
  3254.         }
  3255.     }
  3256.     while(lReturn != SUCCESS);
  3257.  
  3258.     // Find the location information in the TRANSLATECAPS
  3259.     lpLocationEntry = (LPLINELOCATIONENTRY)
  3260.         (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset);
  3261.     debug(F110,"cktapiFetchLocationInfoByName","lpLocationEntry",lpLocationEntry);
  3262.  
  3263.     // loop through all locations, looking for a location match
  3264.     for(dwCounter = 0;
  3265.          dwCounter < lpTranslateCaps -> dwNumLocations;
  3266.          dwCounter++)
  3267.     {
  3268.         if (_stricmp((((LPSTR) lpTranslateCaps) +
  3269.                        lpLocationEntry[dwCounter].dwLocationNameOffset),
  3270.                       CurrentLocation)
  3271.              == 0)
  3272.         {
  3273.             // Found it!  Set the current location, if necessary.
  3274.             int ID = cktapiGetCurrentLocationID();
  3275.             if ( ID != lpLocationEntry[dwCounter].dwPermanentLocationID )
  3276.             {
  3277.                 lReturn =
  3278.                     (*cklineSetCurrentLocation)(g_hLineApp,
  3279.                         lpLocationEntry[dwCounter].dwPermanentLocationID);
  3280.                 OutputDebugLastError(lReturn,"lineSetCurrentLocation:");
  3281.             }
  3282.             break;
  3283.         }
  3284.     }
  3285.  
  3286.     if ( dwCounter == lpTranslateCaps -> dwNumLocations ) {
  3287.         debug(F110,"cktapiFetchLocationInfoByName","LocationEntry not found",0);
  3288.         LocalFree(lpTranslateCaps);
  3289.         return FALSE;
  3290.     }
  3291.  
  3292.     // Was a match for lpszCurrentLocation found?
  3293.     if (lpLocationEntry[dwCounter].dwPreferredCardID == MAXDWORD)
  3294.     {
  3295.         debug(F110,"cktapiFetchLocationInfoByName","LocationEntry not found",0);
  3296.         LocalFree(lpTranslateCaps);
  3297.         return FALSE;
  3298.     }
  3299.  
  3300.     SaveTapiLocationInfo( lpTranslateCaps, &lpLocationEntry[dwCounter] );
  3301.     LocalFree(lpTranslateCaps);
  3302.     return TRUE;
  3303. }
  3304.  
  3305. int
  3306. cktapiFetchLocationInfoByID( int LocationID )
  3307. {
  3308.     LPLINETRANSLATECAPS lpTranslateCaps = NULL;
  3309.     DWORD dwSizeofTranslateCaps = sizeof(LINETRANSLATECAPS);
  3310.     long lReturn;
  3311.     DWORD dwCounter;
  3312.     LPLINELOCATIONENTRY lpLocationEntry;
  3313.     LPLINECARDENTRY lpLineCardEntry = NULL;
  3314.  
  3315.    // First, get the TRANSLATECAPS
  3316.    do
  3317.    {
  3318.       lpTranslateCaps = (LPLINETRANSLATECAPS) CheckAndReAllocBuffer(
  3319.                  (LPVOID) lpTranslateCaps, dwSizeofTranslateCaps,
  3320.                  "cktapiFetchLocationInfoByID");
  3321.  
  3322.       if (lpTranslateCaps == NULL)
  3323.          return FALSE;
  3324.  
  3325.       lReturn = (*cklineGetTranslateCaps)(g_hLineApp, TAPI_CURRENT_VERSION,
  3326.                                       lpTranslateCaps);
  3327.  
  3328.       if (HandleLineErr(lReturn))
  3329.          ;
  3330.       else
  3331.       {
  3332.          OutputDebugLineError(lReturn,
  3333.                                "lineGetTranslateCaps unhandled error: ");
  3334.          LocalFree(lpTranslateCaps);
  3335.          return FALSE;
  3336.       }
  3337.  
  3338.       if ((lpTranslateCaps -> dwNeededSize) >
  3339.            (lpTranslateCaps -> dwTotalSize))
  3340.       {
  3341.          dwSizeofTranslateCaps = lpTranslateCaps ->dwNeededSize;
  3342.          lReturn = -1; // Lets loop again.
  3343.       }
  3344.    }
  3345.    while(lReturn != SUCCESS);
  3346.  
  3347.    // Find the location information in the TRANSLATECAPS
  3348.    lpLocationEntry = (LPLINELOCATIONENTRY)
  3349.       (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset);
  3350.  
  3351.     debug(F110,"cktapiFetchLocationInfoByID","lpLocationEntry",lpLocationEntry);
  3352.  
  3353.     // If lpszCurrentLocation, then make that location 'current'
  3354.     if (LocationID == -1)
  3355.     {
  3356.         LocationID = cktapiGetCurrentLocationID();
  3357.     }
  3358.  
  3359.     // loop through all locations, looking for a location match
  3360.     for(dwCounter = 0;
  3361.          dwCounter < lpTranslateCaps -> dwNumLocations;
  3362.          dwCounter++)
  3363.     {
  3364.         if ( LocationID == lpLocationEntry[dwCounter].dwPermanentLocationID )
  3365.         {
  3366.             // Found it!  Set the current location, if necessary.
  3367.             int ID = cktapiGetCurrentLocationID();
  3368.             if ( ID != lpLocationEntry[dwCounter].dwPermanentLocationID )
  3369.             {
  3370.                 lReturn =
  3371.                     (*cklineSetCurrentLocation)(g_hLineApp,
  3372.                         lpLocationEntry[dwCounter].dwPermanentLocationID);
  3373.                 OutputDebugLastError(lReturn,"lineSetCurrentLocation:");
  3374.             }
  3375.             break;
  3376.         }
  3377.     }
  3378.  
  3379.     if ( dwCounter == lpTranslateCaps -> dwNumLocations ) {
  3380.         debug(F110,"cktapiFetchLocationInfoByID","LocationEntry not found",0);
  3381.         LocalFree(lpTranslateCaps);
  3382.         return FALSE;
  3383.     }
  3384.  
  3385.     // Was a match for lpszCurrentLocation found?
  3386.     if (lpLocationEntry[dwCounter].dwPreferredCardID == MAXDWORD)
  3387.     {
  3388.         debug(F110,"cktapiFetchLocationInfoByID","PreferredCardID == MAXDWORD",0);
  3389.         LocalFree(lpTranslateCaps);
  3390.         return FALSE;
  3391.     }
  3392.  
  3393.     SaveTapiLocationInfo( lpTranslateCaps, &lpLocationEntry[dwCounter] );
  3394.     LocalFree(lpTranslateCaps);
  3395.     return TRUE;
  3396. }
  3397.  
  3398. #ifndef NODIAL
  3399. void
  3400. CopyTapiLocationInfoToKermitDialCmd( void )
  3401. {
  3402.     extern char *dialnpr;               /* DIAL PREFIX */
  3403.     extern char *diallac;               /* DIAL LOCAL-AREA-CODE */
  3404.     extern char *diallcc;               /* DIAL LOCAL-COUNTRY-CODE */
  3405.     extern char *dialixp;               /* DIAL INTL-PREFIX */
  3406.     extern char *dialixs;               /* DIAL INTL-SUFFIX */
  3407.     extern char *diallcp;               /* DIAL LOCAL-PREFIX */
  3408.     extern char *diallcs;               /* DIAL LOCAL-SUFFIX */
  3409.     extern char *dialldp;               /* DIAL LD-PREFIX */
  3410.     extern char *diallds;               /* DIAL LD-SUFFIX */
  3411.     extern char *dialpxx;               /* DIAL PBX-EXCHANGE */
  3412.     extern char *dialpxi;               /* DIAL INTERNAL-PREFIX */
  3413.     extern char *dialpxo;               /* DIAL OUTSIDE-PREFIX */
  3414.     extern char *dialsfx;               /* DIAL SUFFIX */
  3415.     extern char *dialtfp;               /* DIAL TOLL-FREE-PREFIX */
  3416.     extern int dialmth;                 /* DIAL METHOD TONE/PULSE */
  3417.     char * p = NULL;
  3418.  
  3419.     debug(F111,"CopyTapiLocationInfoToKermitDialCmd","tapilocid",tapilocid);
  3420.  
  3421.     /* Make sure there are valid values */
  3422.     if ( tapilocid == -1 ) {
  3423.         tapilocid = cktapiGetCurrentLocationID();
  3424.         if ( tapilocid == -1 ) {
  3425.             debug(F111,"CopyTapiLocationInfoToKermitDialCmd",
  3426.                    "tapilocid still -1",tapilocid);
  3427.             return;
  3428.         }
  3429.         cktapiFetchLocationInfoByID( tapilocid );
  3430.     }
  3431.  
  3432.     debug(F110,"CopyTapiLocationInfoToKermitDialCmd",
  3433.            "copying string values",0);
  3434.  
  3435.     /* Local Country Code */
  3436.     if ( diallcc )
  3437.         free( diallcc );
  3438.     diallcc = (char *) malloc( 20 ) ;
  3439.     if ( !diallcc )
  3440.         return;
  3441.     _itoa( tapiCountryCode, diallcc, 10 );
  3442.  
  3443.     /* Local Area Code */
  3444.     if ( diallac )
  3445.         free(diallac);
  3446.     diallac = strdup( tapiAreaCode );
  3447.  
  3448.     /* Long Distance Prefix */
  3449.     if ( dialldp )
  3450.         free(dialldp);
  3451.     /* The true Long Distance Prefix is the tapiLongDistAccessCode */
  3452.     /* plus the prefix portion of the tapiLongDistanceRule         */
  3453.     dialldp = (char *) malloc(strlen(tapiLongDistAccessCode) +
  3454.                                strlen(tapiLongDistanceRule) + 1);
  3455.     if ( dialldp ) {
  3456.         strcpy(dialldp,tapiLongDistAccessCode);
  3457.         p = dialldp;
  3458.         /* find the beginning of the prefix  */
  3459.         while ( *p == ' ' || *p == 'N' || *p == 'S' ) {
  3460.             *p = ' ';
  3461.             p++;
  3462.         }
  3463.         /* find the end of the prefix and null terminate it */
  3464.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G' )
  3465.             p++;
  3466.         *p = '\0';
  3467.         strcpy(p,tapiLongDistanceRule);
  3468.         /* find the beginning of the prefix  */
  3469.         while ( *p == ' ' || *p == 'N' || *p == 'S' ) {
  3470.             *p = ' ';
  3471.             p++;
  3472.         }
  3473.         /* find the end of the prefix and null terminate it */
  3474.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G' )
  3475.             p++;
  3476.         *p = '\0';
  3477.     }
  3478.  
  3479.     /* The Long Distance Suffix is the suffix portion of the       */
  3480.     /* tapiLongDistanceRule (if any)                               */
  3481.     if ( diallds )
  3482.         free(diallds);
  3483.     diallds = strdup( tapiLongDistanceRule );
  3484.     if ( diallds ) {
  3485.         p = diallds;
  3486.         /* blank out the prefix */
  3487.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G') {
  3488.             *p = ' ';
  3489.             p++;
  3490.         }
  3491.         /* and then the dialing rule */
  3492.         while ( *p == 'E' || *p == 'F' || *p == 'G' ) {
  3493.             *p = ' ';
  3494.             p++;
  3495.         }
  3496.         if ( *p == '\0' ) {
  3497.             free(diallds);
  3498.             diallds = NULL;
  3499.         }
  3500.     }
  3501.  
  3502.     /* Toll Free Prefix */
  3503.     if ( dialtfp )
  3504.         free(dialtfp);
  3505.     /* The true Toll Free Prefix is the tapiLongDistAccessCode */
  3506.     /* plus the prefix portion of the tapiLongDistanceRule         */
  3507.     dialtfp = (char *) malloc(strlen(tapiLongDistAccessCode) +
  3508.                                strlen(tapiLongDistanceRule) + 1);
  3509.     if ( dialtfp ) {
  3510.         strcpy(dialtfp,tapiLongDistAccessCode);
  3511.         p = dialtfp;
  3512.         /* find the beginning of the prefix  */
  3513.         while ( *p == ' ' || *p == 'N' || *p == 'S' ) {
  3514.             *p = ' ';
  3515.             p++;
  3516.         }
  3517.         /* find the end of the prefix and null terminate it */
  3518.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G' )
  3519.             p++;
  3520.         *p = '\0';
  3521.         strcpy(p,tapiLongDistanceRule);
  3522.         /* find the beginning of the prefix  */
  3523.         while ( *p == ' ' || *p == 'N' || *p == 'S' ) {
  3524.             *p = ' ';
  3525.             p++;
  3526.         }
  3527.         /* find the end of the prefix and null terminate it */
  3528.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G' )
  3529.             p++;
  3530.         *p = '\0';
  3531.     }
  3532.  
  3533.     /* The International Prefix is the prefix portion of the       */
  3534.     /* tapiInternationalRule         */
  3535.     if ( dialixp )
  3536.         free(dialixp);
  3537.     /* The true International Prefix is the tapiLongDistAccessCode */
  3538.     /* plus the prefix portion of the tapiInternationalRule        */
  3539.     dialixp = (char *) malloc(strlen(tapiLongDistAccessCode) +
  3540.                                strlen(tapiInternationalRule) + 1);
  3541.     if ( dialixp ) {
  3542.         strcpy(dialixp,tapiLongDistAccessCode);
  3543.         p = dialixp;
  3544.         /* find the beginning of the prefix  */
  3545.         while ( *p == ' ' || *p == 'N' || *p == 'S' ) {
  3546.             *p = ' ';
  3547.             p++;
  3548.         }
  3549.         /* find the end of the prefix and null terminate it */
  3550.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G' )
  3551.             p++;
  3552.         *p = '\0';
  3553.         strcpy(p,tapiInternationalRule);
  3554.         /* find the beginning of the prefix  */
  3555.         while ( *p == ' ' || *p == 'N' || *p == 'S' ) {
  3556.             *p = ' ';
  3557.             p++;
  3558.         }
  3559.         /* find the end of the prefix and null terminate it */
  3560.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G' )
  3561.             p++;
  3562.         *p = '\0';
  3563.     }
  3564.  
  3565.     /* The International Suffix is the suffix portion of the       */
  3566.     /* tapiInternationalRule (if any)                              */
  3567.     if ( dialixs )
  3568.         free(dialixs);
  3569.     dialixs = strdup( tapiInternationalRule );
  3570.     if ( dialixs ) {
  3571.         p = dialixs;
  3572.         /* blank out the prefix */
  3573.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G') {
  3574.             *p = ' ';
  3575.             p++;
  3576.         }
  3577.         /* and then the dialing rule */
  3578.         while ( *p == 'E' || *p == 'F' || *p == 'G' ) {
  3579.             *p = ' ';
  3580.             p++;
  3581.         }
  3582.         if ( *p == '\0' ) {
  3583.             free(dialixs);
  3584.             dialixs = NULL;
  3585.         }
  3586.     }
  3587.  
  3588.     /* Local Prefix */
  3589.     if ( diallcp )
  3590.         free(diallcp);
  3591.     /* The true Local Prefix is the tapiLocalAccessCode */
  3592.     /* plus the prefix portion of the tapiSameAreaRule         */
  3593.     diallcp = (char *) malloc(strlen(tapiLocalAccessCode) +
  3594.                                strlen(tapiSameAreaRule) + 1);
  3595.     if ( diallcp ) {
  3596.         strcpy(diallcp,tapiLocalAccessCode);
  3597.         p = diallcp;
  3598.         /* find the beginning of the prefix  */
  3599.         while ( *p == ' ' || *p == 'N' || *p == 'S' ) {
  3600.             *p = ' ';
  3601.             p++;
  3602.         }
  3603.         /* find the end of the prefix and null terminate it */
  3604.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G' )
  3605.             p++;
  3606.         *p = '\0';
  3607.         strcpy(p,tapiSameAreaRule);
  3608.         /* find the beginning of the prefix  */
  3609.         while ( *p == ' ' || *p == 'N' || *p == 'S' ) {
  3610.             *p = ' ';
  3611.             p++;
  3612.         }
  3613.         /* find the end of the prefix and null terminate it */
  3614.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G' )
  3615.             p++;
  3616.         *p = '\0';
  3617.     }
  3618.  
  3619.     /* The Local Access Suffix is the suffix portion of the       */
  3620.     /* tapiLocalAccessRule (if any)                                */
  3621.     if ( diallcs )
  3622.         free(diallcs);
  3623.     diallcs = strdup( tapiSameAreaRule );
  3624.     if ( diallcs ) {
  3625.         p = diallcs;
  3626.         /* blank out the prefix */
  3627.         while ( *p && *p != 'E' && *p != 'F' && *p != 'G') {
  3628.             *p = ' ';
  3629.             p++;
  3630.         }
  3631.         /* and then the dialing rule */
  3632.         while ( *p == 'E' || *p == 'F' || *p == 'G' ) {
  3633.             *p = ' ';
  3634.             p++;
  3635.         }
  3636.         if ( *p == '\0' ) {
  3637.             free(diallcs);
  3638.             diallcs = NULL;
  3639.         }
  3640.     }
  3641.  
  3642.     /* All purpose Prefix */
  3643.     if ( dialnpr )
  3644.         free( dialnpr );
  3645.     dialnpr = strdup( tapiCancelCallWaiting );
  3646.  
  3647.     /* Pulse Dialing? */
  3648.     if ( tapiOptions & LINELOCATIONOPTION_PULSEDIAL )
  3649.         dialmth = XYDM_P;
  3650.     else
  3651.         dialmth = XYDM_T;
  3652.  
  3653.     debug(F110,"CopyTapiLocationInfoToKermitDialCmd","done",0);
  3654. }
  3655. #endif /* NODIAL */
  3656.  
  3657. typedef struct tagCommID {
  3658.     HANDLE hModem ;
  3659.     char szModemName[1] ;
  3660. } CommID ;
  3661.  
  3662. HANDLE
  3663. GetModemHandleFromLine( HLINE hLine )
  3664. {
  3665.     CommID * cid;
  3666.     VARSTRING *vs;
  3667.     ULONG lrc ;
  3668.     DWORD dwSize;
  3669.     HANDLE hModem ;
  3670.  
  3671.     if ( hLine == (HLINE) 0 )
  3672.         hLine = g_hLine;
  3673.  
  3674.     if ( hLine == (HLINE) 0 )
  3675.         return NULL;
  3676.  
  3677.     /* The next four lines prepare a VARSTRING structure to
  3678.     pass to Windows though lineGetID */
  3679.     vs = (VARSTRING *) malloc (1024);
  3680.     if ( !vs )
  3681.         return NULL;
  3682.     memset(vs,0,1024);
  3683.     vs->dwTotalSize = 1024;
  3684.  
  3685.     do {
  3686.         /* get modem handle associated with the line */
  3687.         lrc = (*cklineGetID)(hLine, 0L, (HCALL)0,
  3688.                               LINECALLSELECT_LINE,
  3689.                               vs, "comm/datamodem") ;
  3690.         if ( ( lrc == LINEERR_STRUCTURETOOSMALL || lrc == 0 ) &&
  3691.              (vs->dwTotalSize < vs->dwNeededSize) ) {
  3692.             /* the next six lines reallocate the VARSTRING */
  3693.             dwSize = vs->dwNeededSize ;
  3694.             free(vs);
  3695.             vs = (VARSTRING *) malloc(dwSize);
  3696.             if ( !vs )
  3697.                 return NULL;
  3698.             memset(vs,0,sizeof(vs));
  3699.             vs->dwTotalSize = dwSize ;
  3700.         }
  3701.         else if ( lrc ) {
  3702.             /* some kind of TAPI error */
  3703.             OutputDebugLastError(lrc,"lineGetID:");
  3704.             free(vs);
  3705.             return NULL;
  3706.         }
  3707.         else
  3708.             break;  /* success */
  3709.     } while ( TRUE );
  3710.  
  3711.     cid = (CommID *) ((LPSTR)vs + vs->dwStringOffset);
  3712.  
  3713.     if ( !cid->hModem ) {
  3714.         SECURITY_ATTRIBUTES security ;
  3715.  
  3716.         security.nLength = sizeof(SECURITY_ATTRIBUTES);
  3717.         security.lpSecurityDescriptor = NULL ;
  3718.         security.bInheritHandle = TRUE ;
  3719.         strcpy( szModemName, "\\\\.\\" ) ;
  3720.         strcat( szModemName, &cid->szModemName[0] ) ;
  3721.         hModem = CreateFile( szModemName,
  3722.                              GENERIC_READ | GENERIC_WRITE,
  3723.                              TRUE, /* do not share */
  3724.                              &security,
  3725.                              OPEN_EXISTING,
  3726.                              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  3727.                              NULL);
  3728.     }
  3729.     else {
  3730.         lstrcpy( szModemName, &cid->szModemName[0] ) ;
  3731.         hModem = cid->hModem ;
  3732.     }
  3733.  
  3734.     free(vs);
  3735.     return hModem;
  3736. }
  3737.  
  3738. void
  3739. cktapiConfigureLine( int lineID )
  3740. {
  3741.     LPVARSTRING lpVarString = NULL;
  3742.     DWORD dwSizeofVarString = sizeof(VARSTRING) + 1024;
  3743.     LPCSTR binaryConfigString=NULL;
  3744.     LONG lReturn=-1;
  3745.  
  3746.     if ( !cktapiopen() )
  3747.         return;
  3748.  
  3749.     if ( lineID == -1 )
  3750.         lineID = LineDeviceId;
  3751.  
  3752.     debug(F111,"TAPI Configure Line Dialog","lineID",lineID);
  3753.     (*cklineConfigDialog)( lineID, hwndConsole, NULL );
  3754.  
  3755.     do
  3756.     {
  3757.         if ( lpVarString != NULL )
  3758.             free(lpVarString);
  3759.  
  3760.         // Allocate the VARSTRING structure
  3761.         lpVarString = malloc( dwSizeofVarString ) ;
  3762.         if (lpVarString == NULL)
  3763.             goto ErrorConfiguring;
  3764.         lpVarString->dwTotalSize = dwSizeofVarString;
  3765.  
  3766.         // Fill the VARSTRING structure
  3767.         lReturn = (*cklineGetDevConfig)( lineID, lpVarString, "comm/datamodem" );
  3768.         OutputDebugLastError(lReturn,"lineGetDevConfig:");
  3769.  
  3770.         if (HandleLineErr(lReturn))
  3771.             ; // Still need to check if structure was big enough.
  3772.             else
  3773.             {
  3774.                 OutputDebugLineError(lReturn,
  3775.                                       "lineGetDevConfig unhandled error: ");
  3776.                 goto ErrorConfiguring;
  3777.             }
  3778.  
  3779.         // If the VARSTRING wasn't big enough, loop again.
  3780.         if ((lpVarString -> dwNeededSize) > (lpVarString -> dwTotalSize))
  3781.         {
  3782.             dwSizeofVarString = lpVarString -> dwNeededSize;
  3783.             lReturn = -1; // Lets loop again.
  3784.         }
  3785.     }
  3786.     while(lReturn != SUCCESS);
  3787.  
  3788.     /* See cktapiGetModemSettings; we may know the format of this string */
  3789.     binaryConfigString = ((LPCSTR)((LPBYTE)lpVarString +
  3790.                                     lpVarString->dwStringOffset));
  3791.  
  3792.     ErrorConfiguring:
  3793.     if (lpVarString)
  3794.         free(lpVarString);
  3795.  
  3796.     cktapiclose();
  3797. }
  3798.  
  3799. void
  3800. cktapiDialingProp( void )
  3801. {
  3802.     DWORD dwAPIVersion ;
  3803.     LINEEXTENSIONID ExtensionID ;
  3804.     LONG rc;
  3805.  
  3806.     if ( !cktapiopen() )
  3807.         return;
  3808.  
  3809.     debug(F111,"TAPI Dialing Properties Dialog","device ID",LineDeviceId);
  3810.     rc = (*cklineNegotiateAPIVersion)(g_hLineApp,
  3811.                                        LineDeviceId == -1 ? 0 : LineDeviceId,
  3812.                                        TAPI_CURRENT_VERSION,
  3813.                                        TAPI_CURRENT_VERSION,
  3814.                                        &dwAPIVersion, &ExtensionID);
  3815.     rc = (*cklineTranslateDialog)( g_hLineApp,
  3816.                                    LineDeviceId == -1 ? 0 : LineDeviceId,
  3817.                                    dwAPIVersion, hwndConsole, NULL );
  3818.  
  3819.     tapilocid = -1;
  3820. #ifndef NODIAL
  3821.     CopyTapiLocationInfoToKermitDialCmd();
  3822. #endif /* NODIAL */
  3823.     cktapiclose();
  3824. }
  3825.  
  3826. int
  3827. cktapiConvertPhoneNumber(char * source, char ** converted)
  3828. {
  3829.     DWORD dwAPIVersion ;
  3830.     LINEEXTENSIONID ExtensionID ;
  3831.     DWORD dwCard=0;
  3832.     DWORD dwTranslateOptions=LINETRANSLATEOPTION_CANCELCALLWAITING;
  3833.     LPLINETRANSLATEOUTPUT lplineTranslateOutput=NULL;
  3834.     DWORD dwSize=0;
  3835.     LONG rc = 0;
  3836.  
  3837.     if ( !cktapiopen() )
  3838.         return FALSE;
  3839.  
  3840.     rc = (*cklineNegotiateAPIVersion)(g_hLineApp,
  3841.                                        LineDeviceId == -1 ? 0 : LineDeviceId,
  3842.                                        TAPI_CURRENT_VERSION,
  3843.                                        TAPI_CURRENT_VERSION,
  3844.                                        &dwAPIVersion, &ExtensionID);
  3845.     if ( rc ) {
  3846.         cktapiclose();
  3847.         return FALSE;
  3848.     }
  3849.     dwSize = sizeof(LINETRANSLATEOUTPUT);
  3850.     lplineTranslateOutput = (LPLINETRANSLATEOUTPUT) malloc( dwSize ) ;
  3851.     if ( !lplineTranslateOutput ) {
  3852.         cktapiclose();
  3853.         return FALSE;
  3854.     }
  3855.     memset(lplineTranslateOutput,0,dwSize);
  3856.     lplineTranslateOutput->dwTotalSize = dwSize ;
  3857.  
  3858.     do {
  3859.         rc = (*cklineTranslateAddress)(g_hLineApp,
  3860.                                         LineDeviceId == -1 ? 0 : LineDeviceId,
  3861.                                         dwAPIVersion,
  3862.                                         source,
  3863.                                         dwCard,
  3864.                                         dwTranslateOptions,
  3865.                                         lplineTranslateOutput
  3866.                                         );
  3867.         if ( ( rc == LINEERR_STRUCTURETOOSMALL || rc == 0 ) &&
  3868.              (lplineTranslateOutput->dwTotalSize < lplineTranslateOutput->dwNeededSize) ) {
  3869.             /* the next six lines reallocate the LINETRANSLATEOUTPUT struct */
  3870.             dwSize = lplineTranslateOutput->dwNeededSize ;
  3871.             free(lplineTranslateOutput);
  3872.             lplineTranslateOutput = (LPLINETRANSLATEOUTPUT) malloc( dwSize ) ;
  3873.             if ( !lplineTranslateOutput ) {
  3874.                 cktapiclose();
  3875.                 return FALSE;
  3876.             }
  3877.             memset(lplineTranslateOutput,0,dwSize);
  3878.             lplineTranslateOutput->dwTotalSize = dwSize ;
  3879.         }
  3880.         else if ( rc ) {
  3881.             /* some kind of TAPI error */
  3882.             OutputDebugLastError(rc,"lineTranslateAddress:");
  3883.             free(lplineTranslateOutput);
  3884.             cktapiclose();
  3885.             return FALSE;
  3886.         }
  3887.         else
  3888.             break;  /* success */
  3889.     } while ( TRUE );
  3890.  
  3891.     /* we now have the result, lets do something with it */
  3892.     *converted = (char *) malloc( lplineTranslateOutput->dwDialableStringSize+1);
  3893.     strncpy( *converted, (LPCSTR) lplineTranslateOutput +
  3894.                          lplineTranslateOutput->dwDialableStringOffset,
  3895.              lplineTranslateOutput->dwDialableStringSize);
  3896.     (*converted)[lplineTranslateOutput->dwDialableStringSize]='\0';
  3897.  
  3898.     free(lplineTranslateOutput);
  3899.     cktapiclose();
  3900.  
  3901.     return TRUE;
  3902. }
  3903.  
  3904. int
  3905. tapi_open( char * devicename )
  3906. {
  3907.     extern struct keytab * tapilinetab ;
  3908.     extern int ntapiline ;
  3909.     int i ;
  3910.     LINEEXTENSIONID ExtId ;
  3911.     int rc ;
  3912.     LPDEVCFG        lpDevCfg = NULL;
  3913.     LPCOMMCONFIG    lpCommConfig = NULL;
  3914.     LPMODEMSETTINGS lpModemSettings = NULL;
  3915.     DCB *           lpDCB = NULL;
  3916.  
  3917.     debug(F110,"tapi_open devicename",devicename,0);
  3918.     if ( !cktapiopen() )
  3919.     {
  3920.         debug(F100,"tapi_open !cktapiopen()","",0);
  3921.         printf("TAPI Open fails\n");
  3922.         return -1;
  3923.     }
  3924.  
  3925.     /* Find the Line ID */
  3926.     for ( i=0 ; i<ntapiline ; i++ )
  3927.     {
  3928.         // printf("%s == %d\n",tapilinetab[i].kwd, tapilinetab[i].kwval);
  3929.         if ( !strcmp( devicename, tapilinetab[i].kwd ) )
  3930.         {
  3931.             LineDeviceId = tapilinetab[i].kwval ;
  3932.             // printf("LineDeviceId == %d\n",LineDeviceId);
  3933.             break;
  3934.         }
  3935.     }
  3936.  
  3937.     if ( i == ntapiline )
  3938.     {
  3939.         debug(F100,"tapi_open device not found","",0);
  3940.         printf("%s not in TAPI Device Table\n",devicename);
  3941.         cktapiclose();
  3942.         return -1 ;
  3943.     }
  3944.  
  3945.     /* Negotiate API Version for the Line Device */
  3946.     {
  3947.         rc = (*cklineNegotiateAPIVersion)( g_hLineApp, LineDeviceId,
  3948.                                            TAPI_CURRENT_VERSION, TAPI_CURRENT_VERSION,
  3949.                                            &LineDeviceAPIVersion,
  3950.                                            &ExtId ) ;
  3951.         if ( rc < 0 ) {
  3952.             debug(F101,"tapi_open cklineNegotiateAPIVersion() failed","",rc);
  3953.             printf("Error negotiating LineDevice API Version\n");
  3954.             cktapiclose();
  3955.             return -1;
  3956.         }
  3957.     }
  3958.  
  3959.     /* Get Addresses and Media modes */
  3960.     LineAddressCount = g_lpLineDevCaps[LineDeviceId]->dwNumAddresses ;
  3961.     LineMediaModes = g_lpLineDevCaps[LineDeviceId]->dwMediaModes ;
  3962.  
  3963.     if ( g_hLine == (HLINE)0 ) {        /* Call lineOpen() */
  3964.         rc = -1 ;
  3965.         while ( rc < 0 )
  3966.         {
  3967.             rc = (*cklineOpen)( g_hLineApp, LineDeviceId, &g_hLine,
  3968.                                 LineDeviceAPIVersion, 0,
  3969.                                 (DWORD) hInstance,
  3970.                                 LINECALLPRIVILEGE_OWNER | LINECALLPRIVILEGE_MONITOR,
  3971.                                 LINEMEDIAMODE_DATAMODEM,
  3972.                                 NULL);
  3973.             OutputDebugLastError(rc,"lineOpen:");
  3974.             switch ( rc ) {
  3975.             case LINEERR_ALLOCATED:
  3976.                 printf("TAPI Device already in use by a non-TAPI application.\n");
  3977.                 cktapiclose();
  3978.                 return -1;
  3979.  
  3980.             default:
  3981.                 if ( HandleLineErr(rc) )
  3982.                 {
  3983.                     continue;
  3984.                 }
  3985.                 else
  3986.                 {
  3987.                     debug(F111,"TAPI lineOpen","g_hLine",g_hLine);
  3988.                     printf("Error opening Line Device: %s\n",cktapiErrorString(rc));
  3989.                     g_hLine = (HLINE)0;
  3990.                     cktapiclose();
  3991.                     return -1;
  3992.                 }
  3993.             }
  3994.         }
  3995.     }
  3996.  
  3997.     /* Specify which event messages we are interested in */
  3998.     rc = (*cklineSetStatusMessages)(g_hLine,
  3999.                                      LINEDEVSTATE_CONNECTED |
  4000.                                      LINEDEVSTATE_DISCONNECTED |
  4001.                                      LINEDEVSTATE_OUTOFSERVICE |
  4002.                                      LINEDEVSTATE_MAINTENANCE |
  4003.                                      LINEDEVSTATE_OPEN |
  4004.                                      LINEDEVSTATE_CLOSE |
  4005.                                      LINEDEVSTATE_RINGING |
  4006.                                      LINEDEVSTATE_OTHER |
  4007.                                      LINEDEVSTATE_REINIT,
  4008.                                      0);
  4009.     OutputDebugLastError(rc,"lineSetStatusMessages:");
  4010.     if ( rc )
  4011.     {
  4012.         cktapiclose();
  4013.         return -1 ;
  4014.     }
  4015.  
  4016.  
  4017.     if ( tapipass ) {
  4018.         /* Try to make a call without specifying an address */
  4019.         LINECALLPARAMS lcp;
  4020.         memset(&lcp,0,sizeof(LINECALLPARAMS));
  4021.         lcp.dwBearerMode = LINEBEARERMODE_PASSTHROUGH;
  4022.         lcp.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
  4023.         lcp.dwTotalSize = sizeof(LINECALLPARAMS);
  4024.         lcp.dwMinRate = lcp.dwMaxRate = 3100 ;
  4025.         lcp.dwAddressMode = LINEADDRESSMODE_ADDRESSID ;
  4026.         lcp.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE | LINECALLPARAMFLAGS_SECURE ;
  4027.  
  4028. #ifndef NODIAL
  4029.         fail_code = 0;
  4030. #endif /* NODIAL */
  4031.         g_bReplyReceived = FALSE;
  4032.         g_lAsyncReply = SUCCESS;
  4033.         g_bConnected = FALSE;
  4034.         g_bDialing = TRUE;
  4035.         ResetTAPIConnectSem();
  4036.         g_dwRequestedID = 0;
  4037.         rc = g_dwRequestedID = (*cklineMakeCall)( g_hLine, &g_hCall, NULL, 0, &lcp) ;
  4038.         OutputDebugLastError(rc,"lineMakeCall:");
  4039.         if ( rc < 0 )
  4040.         {
  4041. #ifdef BETADEBUG
  4042.             printf("lineMakeCall failed rc=%x\n",rc ) ;
  4043. #endif
  4044.             if ( dialdpy )
  4045.                 printf("Open failed: %s\n",cktapiErrorString(rc));
  4046.             g_hCall = (HCALL)0;
  4047.             cktapiclose();
  4048.             g_bDialing = FALSE;
  4049.             return -1;
  4050.         }
  4051.         else {
  4052.             int x = 0;
  4053.  
  4054.             /* Wait for LineReply */
  4055.             while ( !g_bReplyReceived
  4056. #ifndef NODIAL
  4057.                     && fail_code == 0
  4058. #endif /* NODIAL */
  4059.                     ) {
  4060.                 msleep(100);
  4061.                 x += 100;
  4062.                 if ( x == 5000 ) {
  4063.                     debug(F110,"tapi_open",
  4064.                            "lineMakeCall Reply never received",0);
  4065.                     if ( dialdpy )
  4066.                         printf("Open failed: required TAPI reply never received.\n");
  4067.                     g_hCall = (HCALL)0;
  4068.                     cktapiclose();
  4069.                     g_bDialing = FALSE;
  4070.                     return -1;
  4071.                 }
  4072.             }
  4073.  
  4074.             OutputDebugLastError(g_lAsyncReply,"lineMakeCall (Async):");
  4075.  
  4076.             if ( g_lAsyncReply  != SUCCESS )
  4077.             {
  4078. #ifdef BETADEBUG
  4079.                 printf("lineMakeCall failed rc=%x\n",g_lAsyncReply ) ;
  4080. #endif
  4081.                 if ( dialdpy )
  4082.                     printf("Open failed: %s\n",cktapiErrorString(g_lAsyncReply));
  4083.                 g_hCall = (HCALL)0;
  4084.                 cktapiclose();
  4085.                 g_bDialing = FALSE;
  4086.                 return -1;
  4087.             }
  4088.  
  4089.             /* Wait for Success or Failure of Connection */
  4090.             if (!WaitAndResetTAPIConnectSem(10000))
  4091.             {
  4092.                 debug(F111,"TAPI Connect Timeout","seconds",10);
  4093. #ifdef BETADEBUG
  4094.                 printf("TAPI connect semaphore never posted\n");
  4095. #endif
  4096.                 if ( dialdpy )
  4097.                     printf("Open failed: Timeout\n");
  4098.                 cktapiclose();
  4099.                 g_bDialing = FALSE;
  4100.                 return -1;
  4101.             }
  4102. #ifndef NODIAL
  4103.             if ( fail_code == F_INT ) {
  4104.                 cktapiclose();
  4105.                 g_bDialing = FALSE;
  4106.                 return FALSE;
  4107.             }
  4108. #endif /* NODIAL */
  4109.         }
  4110.  
  4111.         if ( ttyfd == -1 || ttyfd == -2 ) {
  4112.             /* if we did not get the Comm handle via the CONNECT message */
  4113.             /* then get it now                                           */
  4114.             ttyfd = (int) GetModemHandleFromLine( g_hLine );
  4115.             SetCommMask( (HANDLE) ttyfd, EV_RXCHAR ) ;
  4116.             SetupComm( (HANDLE) ttyfd, 20000, 20000 ) ;
  4117.             PurgeComm( (HANDLE) ttyfd,
  4118.                        PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR ) ;
  4119.         }
  4120.         if ( !ttyfd || ttyfd == -1 ) {
  4121.             ttyfd = -1 ;
  4122.             cktapiclose();
  4123.             g_bDialing = FALSE;
  4124.             return -1;
  4125.         }
  4126. #ifdef BETADEBUG
  4127.         DisplayCommProperties((HANDLE)ttyfd);
  4128. #endif /* BETADEBUG */
  4129.         g_bDialing = FALSE;
  4130.     }
  4131.     else {                              /* Use TAPI based dialing */
  4132.         ttyfd = -2;                     /* We don't have a real handle yet */
  4133.  
  4134.         /* Do this just to set the name of the Modem */
  4135.         CloseHandle( GetModemHandleFromLine( g_hLine ) );
  4136.     }
  4137.  
  4138. #ifndef NODIAL
  4139.     modemp[n_TAPI] = cktapiGetModemInf(LineDeviceId,(HANDLE)ttyfd);
  4140.     if ( !modemp[n_TAPI] )
  4141.         modemp[n_TAPI] = &GENERIC;
  4142. #endif /* NODIAL */
  4143.  
  4144.     rc = cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,&lpCommConfig,&lpDCB);
  4145.     debug(F101,"tapi_open cktapiGetModemSettings()","",rc);
  4146.     if ( rc )
  4147.     {
  4148.         extern long speed;
  4149.         extern int parity, flow;
  4150.         extern int ttmdm;                   /* Modem or Direct */
  4151. #ifndef NODIAL
  4152.         extern int
  4153.             dialec,                         /* DIAL ERROR-CORRECTION */
  4154.             dialdc,                         /* DIAL COMPRESSION  */
  4155.             dialfc,                         /* DIAL FLOW-CONTROL */
  4156.             dialmth,                        /* DIAL METHOD */
  4157.             mdmspd,                         /* SPEED-MATCHING */
  4158.             mdmspk,                         /* SPEAKER ON/OFF */
  4159.             mdmvol;                         /* SPEAKER VOLUME */
  4160.         extern int dialtmo;                 /* DIAL TIMEOUT */
  4161. #endif /* NODIAL */
  4162.  
  4163.         speed   = lpDCB->BaudRate;
  4164.         parity  = lpDCB->Parity;
  4165. #ifndef NODIAL
  4166.         dialtmo = lpModemSettings->dwCallSetupFailTimer;
  4167.         dialec  = lpModemSettings->dwPreferredModemOptions & MDM_ERROR_CONTROL;
  4168.         dialdc  = lpModemSettings->dwPreferredModemOptions & MDM_COMPRESSION;
  4169. #ifdef COMMENT
  4170.         mdmspd  = lpModemSettings->dwPreferredModemOptions & MDM_SPEED_ADJUST;
  4171. #endif /* COMMENT */
  4172.         dialmth = (lpModemSettings->dwPreferredModemOptions & MDM_TONE_DIAL) ?
  4173.                   XYDM_T : XYDM_D ;
  4174.         dialfc = FLO_AUTO;
  4175.         if ( lpModemSettings->dwPreferredModemOptions & MDM_FLOWCONTROL_HARD )
  4176.             flow = FLO_RTSC;
  4177.         else if ( lpModemSettings->dwPreferredModemOptions & MDM_FLOWCONTROL_SOFT )
  4178.             flow = FLO_XONX;
  4179.         else
  4180.             flow = FLO_NONE;
  4181.  
  4182.         mdmspk = lpModemSettings->dwSpeakerMode;
  4183.         mdmvol = lpModemSettings->dwSpeakerVolume+1;
  4184.  
  4185.         debug(F111,"tapi_open","dialtmo",dialtmo);
  4186.         debug(F111,"tapi_open","speed",speed);
  4187.         debug(F111,"tapi_open","parity",parity);
  4188.         debug(F111,"tapi_open","dialec",dialec);
  4189.         debug(F111,"tapi_open","dialdc",dialdc);
  4190.         debug(F111,"tapi_open","dialmth",dialmth);
  4191.         debug(F111,"tapi_open","dialfc",dialfc);
  4192.         debug(F111,"tapi_open","flow",flow);
  4193.         debug(F111,"tapi_open","mdmspk",mdmspk);
  4194.         debug(F111,"tapi_open","mdmvol",mdmvol);
  4195. #endif /* NODIAL */
  4196.         if ( !tapipass ) {
  4197.             if ( cktapiIsModem() )
  4198.                 ttmdm = 38;     /* ckudia.c */
  4199.             else 
  4200.                 ttmdm = 0;
  4201.         }
  4202. #ifdef BETADEBUG
  4203.         cktapiDisplayModemSettings(lpDevCfg,lpModemSettings,lpCommConfig,lpDCB);
  4204. #endif
  4205.     }
  4206.     return 0;
  4207. }
  4208.  
  4209.  
  4210. int
  4211. tapi_clos( void )
  4212. {
  4213.    cktapiclose() ;
  4214.    return -1;
  4215. }
  4216.  
  4217. int
  4218. cktapiCallInProgress( void )
  4219. {
  4220.     LPLINEDEVSTATUS lpLineDevStatus=NULL;
  4221.     DWORD dwSizeofLineDevStatus = sizeof(LINEDEVSTATUS);
  4222.     LONG lReturn;
  4223.     int InProgress = TRUE;
  4224.  
  4225.     if ( g_hCall != (HCALL)0 )
  4226.         return FALSE;
  4227.  
  4228.     if ( g_hLine == (HLINE)0 )
  4229.         return TRUE;
  4230.  
  4231.     do
  4232.     {
  4233.         lpLineDevStatus =
  4234.             (LPLINEDEVSTATUS) CheckAndReAllocBuffer((LPVOID) lpLineDevStatus,
  4235.                                                      dwSizeofLineDevStatus,
  4236.                                                      "cktapiCallInProgress");
  4237.         if (lpLineDevStatus == NULL)
  4238.         {
  4239.             return TRUE;
  4240.         }
  4241.  
  4242.         lReturn = (*cklineGetLineDevStatus)(g_hLine, lpLineDevStatus);
  4243.         if (HandleLineErr(lReturn))
  4244.             ;
  4245.         else
  4246.         {
  4247.             OutputDebugLineError(lReturn,
  4248.                                   "lineGetDevStatus unhandled error: ");
  4249.             LocalFree(lpLineDevStatus);
  4250.             return TRUE;
  4251.         }
  4252.  
  4253.         if ((lpLineDevStatus -> dwNeededSize) >
  4254.              (lpLineDevStatus -> dwTotalSize))
  4255.         {
  4256.             dwSizeofLineDevStatus = lpLineDevStatus ->dwNeededSize;
  4257.             lReturn = -1; // Lets loop again.
  4258.         }
  4259.     }
  4260.     while(lReturn != SUCCESS);
  4261.  
  4262.     InProgress = lpLineDevStatus->dwNumActiveCalls
  4263.         + lpLineDevStatus->dwNumOnHoldCalls
  4264.             + lpLineDevStatus->dwNumOnHoldPendCalls
  4265.                 - (g_hCall!=(HCALL)0?1:0);
  4266.  
  4267.     LocalFree( lpLineDevStatus );
  4268.     return InProgress;
  4269. }
  4270.  
  4271. int
  4272. cktapiIsModem(void)
  4273. {
  4274.     LPCSTR lpModemKey;
  4275.     HKEY  hkModemKey=0;
  4276.     HKEY  hkSubKey=0;
  4277.     CHAR  lpszKeyValue[256];
  4278.     DWORD dwType=0;
  4279.     DWORD dwSize=0;
  4280.     CHAR *lpszValueName=NULL;
  4281.     int   modem = 0;
  4282.  
  4283.     if ( LineDeviceId == (DWORD) -1 || g_lpLineDevCaps[LineDeviceId]->dwDevSpecificSize == 0 ) 
  4284.         return 0;
  4285.     
  4286.     lpModemKey = ((char *)g_lpLineDevCaps[LineDeviceId] + g_lpLineDevCaps[LineDeviceId]->dwDevSpecificOffset + 8);
  4287.  
  4288.     if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpModemKey, 0, KEY_READ, &hkModemKey) )
  4289.         return 0;         /* failed */
  4290.  
  4291.     if ( !RegOpenKeyEx(hkModemKey, "Answer", 0, KEY_READ, &hkSubKey) )
  4292.     {
  4293.         dwSize = sizeof(lpszKeyValue);
  4294.         lpszValueName = "1";
  4295.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4296.                                lpszKeyValue, &dwSize ))
  4297.         {
  4298.             modem = strcmp("CLIENTSERVER",lpszKeyValue);
  4299.         }
  4300.         RegCloseKey( hkSubKey );
  4301.     }
  4302.  
  4303.     if ( !RegOpenKeyEx(hkModemKey, "Settings", 0,
  4304.                         KEY_READ, &hkSubKey) )
  4305.     {
  4306.         dwSize = sizeof(lpszKeyValue);
  4307.         lpszValueName = "DialPrefix";
  4308.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4309.                                lpszKeyValue, &dwSize ))
  4310.         {
  4311.             modem &= strcmp("CLIENT",lpszKeyValue);
  4312.         }
  4313.         RegCloseKey( hkSubKey );
  4314.     }
  4315.     RegCloseKey( hkModemKey );
  4316.  
  4317.     return modem;
  4318. }
  4319.  
  4320. int
  4321. cktapiDisplayModemSettings( LPDEVCFG lpDevCfg,
  4322.                             LPMODEMSETTINGS lpModemSettings,
  4323.                             LPCOMMCONFIG lpCommConfig,
  4324.                             DCB *     lpDCB )
  4325. {
  4326.     printf("TAPI UniModem Configuration:\n");
  4327.     printf("  Modem Name: %s\n", szModemName );
  4328.     if ( LineDeviceId != (DWORD) -1 &&
  4329.          g_lpLineDevCaps[LineDeviceId]->dwDevSpecificSize ) {
  4330.         printf("  Registry Key: %s\n",
  4331.                 (char *)g_lpLineDevCaps[LineDeviceId]
  4332.                 + g_lpLineDevCaps[LineDeviceId]->dwDevSpecificOffset + 8);
  4333.         cktapiDisplayRegistryModemInfo((char *)g_lpLineDevCaps[LineDeviceId]
  4334.                 + g_lpLineDevCaps[LineDeviceId]->dwDevSpecificOffset + 8);
  4335.     }
  4336.  
  4337.     if ( lpDevCfg ) {
  4338.         printf("  Version                 = %x\n",lpDevCfg->dfgHdr.dwVersion);
  4339.         if ( lpDevCfg->dfgHdr.fwOptions == 0 )
  4340.             printf("  No Unimodem options\n");
  4341.         else {
  4342.             printf("  Unimodem options:\n");
  4343.             if ( lpDevCfg->dfgHdr.fwOptions & 1 )
  4344.                 printf("    Pre-dial Terminal Screen\n");
  4345.             if ( lpDevCfg->dfgHdr.fwOptions & 2 )
  4346.                 printf("    Post-dial Terminal Screen\n");
  4347.             if ( lpDevCfg->dfgHdr.fwOptions & 4 )
  4348.                 printf("    Manual Dialing\n");
  4349.             if ( lpDevCfg->dfgHdr.fwOptions & 8 )
  4350.                 printf("    Display Launch Lights (modem tray icon)\n");
  4351.         }
  4352.         printf("  Wait for bong           = %d seconds\n",lpDevCfg->dfgHdr.wWaitBong);
  4353.     }
  4354.     if ( lpModemSettings ) {
  4355.         printf("  Modem Settings (read/write):\n");
  4356.         printf("    CallSetupFailTimer    = %d seconds\n",
  4357.                 lpModemSettings->dwCallSetupFailTimer);
  4358.         printf("    InactivityTimeout     = %d seconds\n",
  4359.                 lpModemSettings->dwInactivityTimeout);
  4360.         printf("    SpeakerVolume         = %d (0-Low,1-Medium,2-High)\n",
  4361.                 lpModemSettings->dwSpeakerVolume);
  4362.         printf("    SpeakerMode           = %d (0-Off,1-Dial,2-On,3-CallSetup)\n",
  4363.                 lpModemSettings->dwSpeakerMode);
  4364.         if ( lpModemSettings->dwPreferredModemOptions == 0 )
  4365.             printf("    No Preferred Modem Options\n");
  4366.         else {
  4367.             printf("    Preferred Modem Options:\n");
  4368.             if ( lpModemSettings->dwPreferredModemOptions & MDM_COMPRESSION )
  4369.                 printf("      Modem Compression\n");
  4370.             if ( lpModemSettings->dwPreferredModemOptions & MDM_ERROR_CONTROL )
  4371.                 printf("      Error Control\n");
  4372.             if ( lpModemSettings->dwPreferredModemOptions & MDM_FORCED_EC )
  4373.                 printf("      Forced Error Control\n");
  4374.             if ( lpModemSettings->dwPreferredModemOptions & MDM_CELLULAR )
  4375.                 printf("      Cellular\n");
  4376.             if ( lpModemSettings->dwPreferredModemOptions & MDM_FLOWCONTROL_HARD )
  4377.                 printf("      Hardware Flow Control\n");
  4378.             if ( lpModemSettings->dwPreferredModemOptions & MDM_FLOWCONTROL_SOFT )
  4379.                 printf("      Xon/Xoff Flow Control\n");
  4380.             if ( lpModemSettings->dwPreferredModemOptions & MDM_CCITT_OVERRIDE )
  4381.                 printf("      CCITT Override\n");
  4382.             if ( lpModemSettings->dwPreferredModemOptions & MDM_SPEED_ADJUST )
  4383.                 printf("      Speed Adjust (Modulation)\n");
  4384.             if ( lpModemSettings->dwPreferredModemOptions & MDM_TONE_DIAL )
  4385.                 printf("      Tone Dial\n");
  4386.             if ( lpModemSettings->dwPreferredModemOptions & MDM_BLIND_DIAL )
  4387.                 printf("      Blind Dial\n");
  4388.             if ( lpModemSettings->dwPreferredModemOptions & MDM_V23_OVERRIDE )
  4389.                 printf("      V.23 Override\n");
  4390.         }
  4391.         printf("  Modem Settings (read only) from current call (if any):\n");
  4392.         if ( lpModemSettings->dwNegotiatedModemOptions == 0 )
  4393.             printf("    No Negotiated Modem Options\n");
  4394.         else {
  4395.             printf("    Negotiated Modem Options:\n");
  4396.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_COMPRESSION )
  4397.                 printf("      Modem Compression\n");
  4398.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_ERROR_CONTROL )
  4399.                 printf("      Error Control\n");
  4400.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_FORCED_EC )
  4401.                 printf("      Forced Error Control\n");
  4402.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_CELLULAR )
  4403.                 printf("      Cellular\n");
  4404.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_FLOWCONTROL_HARD )
  4405.                 printf("      Hardware Flow Control\n");
  4406.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_FLOWCONTROL_SOFT )
  4407.                 printf("      Xon/Xoff Flow Control\n");
  4408.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_CCITT_OVERRIDE )
  4409.                 printf("      CCITT Override\n");
  4410.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_SPEED_ADJUST )
  4411.                 printf("      Speed Adjust (modulation)\n");
  4412.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_TONE_DIAL )
  4413.                 printf("      Tone Dial\n");
  4414.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_BLIND_DIAL )
  4415.                 printf("      Blind Dial\n");
  4416.             if ( lpModemSettings->dwNegotiatedModemOptions & MDM_V23_OVERRIDE )
  4417.                 printf("      V.23 Override\n");
  4418.         }
  4419.         printf("    NegotiatedDCERate     = %d bits/s\n",lpModemSettings->dwNegotiatedDCERate);
  4420.     }
  4421.     if ( lpCommConfig ) {
  4422.         printf("  Communication Settings:\n");
  4423.         printf("    ProviderSubType       = ");
  4424.         switch ( lpCommConfig->dwProviderSubType ) {
  4425.         case PST_UNSPECIFIED     :
  4426.             printf("Unspecified");
  4427.             break;
  4428.         case PST_RS232           :
  4429.             printf("RS232");
  4430.             break;
  4431.         case PST_PARALLELPORT    :
  4432.             printf("Parallel Port");
  4433.             break;
  4434.         case PST_RS422           :
  4435.             printf("RS422");
  4436.             break;
  4437.         case PST_RS423           :
  4438.             printf("RS423");
  4439.             break;
  4440.         case PST_RS449           :
  4441.             printf("RS449");
  4442.             break;
  4443.         case PST_MODEM           :
  4444.             printf("Modem");
  4445.             break;
  4446.         case PST_FAX             :
  4447.             printf("Fax");
  4448.             break;
  4449.         case PST_SCANNER         :
  4450.             printf("Scanner");
  4451.         case PST_NETWORK_BRIDGE  :
  4452.             printf("Network Bridge");
  4453.             break;
  4454.         case PST_LAT             :
  4455.             printf("LAT");
  4456.             break;
  4457.         case PST_TCPIP_TELNET    :
  4458.             printf("TCP/IP Telnet");
  4459.             break;
  4460.         case PST_X25             :
  4461.             printf("X.25");
  4462.             break;
  4463.         default:
  4464.             printf("Unknown");
  4465.         }
  4466.         printf("\n");
  4467.     }
  4468.     if ( lpDCB ) {
  4469.         printf("    BaudRate                     = %d\n",lpDCB->BaudRate);
  4470.         printf("    Binary Mode (no EOF check)   = %d\n",lpDCB->fBinary);
  4471.         printf("    Enable Parity Checking       = %d\n",lpDCB->fParity);
  4472.         printf("    CTS Handshaking on output    = %d\n",lpDCB->fOutxCtsFlow);
  4473.         printf("    DSR Handshaking on output    = %d\n",lpDCB->fOutxDsrFlow);
  4474.         printf("    DTR Flow Control             = %d\n",lpDCB->fDtrControl);
  4475.         printf("    DSR Sensitivity              = %d\n",lpDCB->fDsrSensitivity);
  4476.         printf("    Continue TX when Xoff sent   = %d\n",lpDCB->fTXContinueOnXoff);
  4477.         printf("    Enable output X-ON/X-OFF     = %d\n",lpDCB->fOutX);
  4478.         printf("    Enable input X-ON/X-OFF      = %d\n",lpDCB->fInX);
  4479.         printf("    Enable Err Replacement       = %d\n",lpDCB->fErrorChar);
  4480.         printf("    Enable Null stripping        = %d\n",lpDCB->fNull);
  4481.         printf("    RTS flow control             = %d\n",lpDCB->fRtsControl);
  4482.         printf("    Abort all I/O on Error       = %d\n",lpDCB->fAbortOnError);
  4483.         printf("    Transmit X-ON threshold      = %d\n",lpDCB->XonLim);
  4484.         printf("    Transmit X-OFF threshold     = %d\n",lpDCB->XoffLim);
  4485.         printf("    Num of bits/byte, 4-8        = %d\n",lpDCB->ByteSize);
  4486.         printf("    Parity (0-4=N,O,E,M,S)       = %d\n",lpDCB->Parity);
  4487.         printf("    StopBits (0,1,2 = 1, 1.5, 2) = %d\n",lpDCB->StopBits);
  4488.         printf("    Tx and Rx X-ON character     = %d\n",lpDCB->XonChar);
  4489.         printf("    Tx and Rx X-OFF character    = %d\n",lpDCB->XoffChar);
  4490.         printf("    Error replacement char       = %d\n",lpDCB->ErrorChar);
  4491.         printf("    End of Input character       = %d\n",lpDCB->EofChar);
  4492.         printf("    Received Event character     = %d\n",lpDCB->EvtChar);
  4493.         printf("\n");
  4494.     }
  4495.     return TRUE;
  4496. }
  4497.  
  4498. int
  4499. cktapiGetModemSettings( LPDEVCFG * lppDevCfg,
  4500.                         LPMODEMSETTINGS * lppModemSettings,
  4501.                         LPCOMMCONFIG * lppCommConfig,
  4502.                         DCB **     lppDCB )
  4503. {
  4504.     static VARSTRING *vs=NULL;
  4505.     DWORD dwSize=0;
  4506.     ULONG lrc=0 ;
  4507.     LPDEVCFG        lpDevCfg = NULL;
  4508.     LPCOMMCONFIG    lpCommConfig = NULL;
  4509.     LPMODEMSETTINGS lpModemSettings = NULL;
  4510.     DCB *           lpDCB = NULL;
  4511.  
  4512.     if ( lppDevCfg )
  4513.         *lppDevCfg = NULL;
  4514.     if ( lppCommConfig )
  4515.         *lppCommConfig = NULL;
  4516.     if ( lppDCB )
  4517.         *lppDCB = NULL;
  4518.     if ( lppModemSettings )
  4519.         *lppModemSettings = NULL;
  4520.  
  4521.     if ( vs != NULL ) {                 /* free previous VARSTRING */
  4522.         free(vs);
  4523.         vs = NULL;
  4524.     }
  4525.  
  4526.     if ( g_hLine == (HLINE)0 ) {
  4527.         debug(F100,"cktapiGetModemSettings g_hLine == NULL","",0);
  4528.         return FALSE;
  4529.     }
  4530.  
  4531.     /* The next four lines prepare a VARSTRING structure to
  4532.     pass to Windows though lineGetID */
  4533.     vs = (VARSTRING *) malloc (1024);
  4534.     if ( !vs ) {
  4535.         debug(F100,"cktapiGetModemSettings malloc failed","",0);
  4536.         return FALSE;
  4537.     }
  4538.     memset(vs,0,1024);
  4539.     vs->dwTotalSize = 1024;
  4540.  
  4541.     do {
  4542.         /* get Modem Device Configuration */
  4543.         lrc = (*cklineGetDevConfig)( LineDeviceId, vs, "comm/datamodem" );
  4544.         if ( ( lrc == LINEERR_STRUCTURETOOSMALL || lrc == 0 ) &&
  4545.              (vs->dwTotalSize < vs->dwNeededSize) ) {
  4546.             /* the next six lines reallocate the VARSTRING */
  4547.             dwSize = vs->dwNeededSize ;
  4548.             free(vs);
  4549.             vs = (VARSTRING *) malloc(dwSize);
  4550.             if ( !vs ) {
  4551.                 debug(F100,"cktapiGetModemSettings malloc 2 failed","",0);
  4552.                 return FALSE;
  4553.             }
  4554.             memset(vs,0,sizeof(vs));
  4555.             vs->dwTotalSize = dwSize ;
  4556.         }
  4557.         else if ( lrc ) {
  4558.             /* some kind of TAPI error */
  4559.             OutputDebugLastError(lrc,"lineGetDevConfig:");
  4560.             free(vs);
  4561.             debug(F101,"cktapiGetModemSettings tapi error","",lrc);
  4562.             return FALSE;
  4563.         }
  4564.         else
  4565.             break;  /* success */
  4566.     } while ( TRUE );
  4567.  
  4568.     lpDevCfg     = (LPDEVCFG) ((LPSTR)vs + vs->dwStringOffset);
  4569.     if ( lpDevCfg == NULL ) {
  4570.         debug(F100,"cktapiGetModemSettings lpDevCfg == NULL","",0);
  4571.         free(vs);
  4572.         return FALSE;
  4573.     }
  4574.  
  4575.     lpCommConfig = (LPCOMMCONFIG) &lpDevCfg->commconfig;
  4576.  
  4577.     lpDCB = &lpCommConfig->dcb;
  4578.  
  4579.     lpModemSettings = (LPMODEMSETTINGS)((LPSTR)lpCommConfig +
  4580.                                          lpCommConfig->dwProviderOffset);
  4581.  
  4582.     if ( lppDevCfg )
  4583.         *lppDevCfg = lpDevCfg;
  4584.     if ( lppCommConfig )
  4585.         *lppCommConfig = lpCommConfig;
  4586.     if ( lppDCB )
  4587.         *lppDCB = lpDCB;
  4588.     if ( lppModemSettings )
  4589.         *lppModemSettings = lpModemSettings;
  4590.     return TRUE;
  4591. }
  4592.  
  4593. int
  4594. cktapiSetModemSettings( LPDEVCFG lpDevCfg, LPCOMMCONFIG lpCommConfig )
  4595. {
  4596.     LONG lrc=0 ;
  4597.     HANDLE hModem = NULL;
  4598.  
  4599.     if ( lpDevCfg == NULL )
  4600.         return FALSE;
  4601.  
  4602.     /* First try with a Modem Handle */
  4603.     hModem = GetModemHandleFromLine((HLINE)0);
  4604.     if ( hModem )
  4605.     {
  4606.         lrc = SetCommConfig( hModem, lpCommConfig, lpCommConfig->dwSize );
  4607.         CloseHandle(hModem);
  4608.         hModem = NULL;
  4609.         if ( lrc )
  4610.             return(TRUE);
  4611.  
  4612.         lrc = GetLastError();
  4613.         debug(F111,"cktapiSetModemSettings","SetCommConfig",lrc);
  4614.     }
  4615.  
  4616.     lrc = (*cklineSetDevConfig)( LineDeviceId,
  4617.                                  lpDevCfg,
  4618.                                  lpDevCfg->dfgHdr.dwSize,
  4619.                                  "comm/datamodem" );
  4620.     OutputDebugLastError(lrc,"lineSetDevConfig:");
  4621.     if ( lrc < 0 )
  4622.     {
  4623.         debug(F111,"cktapiSetModemSettings","lineSetDevConfig",lrc);
  4624. #ifdef BETADEBUG
  4625.         printf("cktapiSetModemSettings rc=%x\n",lrc);
  4626. #endif /* BETADEBUG */
  4627.         return(FALSE);
  4628.     }
  4629.     return(TRUE);
  4630. }
  4631.  
  4632.  
  4633. int
  4634. cktapidisconnect( void )
  4635. {
  4636.     int i=5;
  4637.     if ( !g_bHangingUp && !g_bClosing ) {
  4638.         _beginthread( cktapihangup, 65535, 0 );
  4639.     }
  4640.     do {
  4641.         msleep(50);
  4642.     } while ( (g_bHangingUp || g_bClosing) && i-- );
  4643.     return !(g_bHangingUp || g_bClosing) ;
  4644. }
  4645.  
  4646. int
  4647. cktapicloseasync( void )
  4648. {
  4649.     int i=5;
  4650.     if ( !g_bClosing ) {
  4651.         _beginthread( cktapiclose, 65535, 0 );
  4652.     }
  4653.     do {
  4654.         msleep(50);
  4655.     } while ( g_bClosing && i-- );
  4656.     return !g_bClosing;
  4657. }
  4658.  
  4659. #ifndef NODIAL
  4660. _PROTOTYP (int getok, (int,int) );
  4661. struct mdminf *
  4662. cktapiGetModemInf( DWORD LineID, HANDLE hModem )
  4663. {
  4664.     LPCSTR lpModemKey = (char *)g_lpLineDevCaps[LineID]
  4665.         + g_lpLineDevCaps[LineID]->dwDevSpecificOffset + 8;
  4666.     HKEY  hkModemKey=0;
  4667.     HKEY  hkSubKey=0;
  4668.     CHAR  lpszKeyValue[256]="", lpszBlindOff[256]="";
  4669.     CHAR  lpszPrefix[16]="";
  4670.     CHAR  lpszPostfix[16]="";
  4671.     CHAR  lpszBuf[256]="";
  4672.     DWORD dwType=0;
  4673.     DWORD dwSize=0;
  4674.     CHAR *lpszValueName=NULL;
  4675.     COMMPROP *     lpCommProp = NULL;
  4676.     LPMODEMDEVCAPS lpModemDevCaps = NULL;
  4677.     int i=0,j=0,rc=0;
  4678.     static struct mdminf mdmInf = {
  4679.         NULL, NULL, NULL, 0, NULL, 0, NULL, 0,
  4680.         NULL, NULL, NULL, NULL, 0, 0, 0,
  4681.         NULL, NULL, NULL, NULL, NULL, NULL,
  4682.         NULL, NULL, NULL, NULL, NULL, NULL,
  4683.         NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  4684.         0, 0, getok
  4685.     };
  4686.  
  4687.     /* initialize the MDMINF structure */
  4688.     if ( mdmInf.name ) {
  4689.         free(mdmInf.name);
  4690.         mdmInf.name = NULL;
  4691.     }
  4692.     if ( mdmInf.pulse ) {
  4693.         free(mdmInf.pulse);
  4694.         mdmInf.pulse = NULL;
  4695.     }
  4696.     if ( mdmInf.tone ) {
  4697.         free(mdmInf.tone);
  4698.         mdmInf.tone = NULL;
  4699.     }
  4700.     mdmInf.dial_time = 0;
  4701.     if ( mdmInf.pause_chars ) {
  4702.         free(mdmInf.pause_chars);
  4703.         mdmInf.pause_chars = NULL;
  4704.     }
  4705.     mdmInf.pause_time = 0;
  4706.     if ( mdmInf.wake_str ) {
  4707.         free(mdmInf.wake_str);
  4708.         mdmInf.wake_str = NULL;
  4709.     }
  4710.     mdmInf.wake_rate=0;
  4711.     if ( mdmInf.dmode_str ) {
  4712.         free(mdmInf.dmode_str);
  4713.         mdmInf.dmode_str = NULL;
  4714.     }
  4715.     if ( mdmInf.dmode_prompt ) {
  4716.         free(mdmInf.dmode_prompt);
  4717.         mdmInf.dmode_prompt = NULL;
  4718.     }
  4719.     if ( mdmInf.dial_str ) {
  4720.         free(mdmInf.dial_str);
  4721.         mdmInf.dial_str = NULL;
  4722.     }
  4723.     mdmInf.dial_rate = 0;
  4724.     mdmInf.esc_time = 0;
  4725.     mdmInf.esc_char = 0;
  4726.     if ( mdmInf.hup_str ) {
  4727.         free(mdmInf.hup_str);
  4728.         mdmInf.hup_str = NULL;
  4729.     }
  4730.     if ( mdmInf.hwfc_str ) {
  4731.         free(mdmInf.hwfc_str);
  4732.         mdmInf.hwfc_str = NULL;
  4733.     }
  4734.     if ( mdmInf.swfc_str ) {
  4735.         free(mdmInf.swfc_str);
  4736.         mdmInf.swfc_str = NULL;
  4737.     }
  4738.     if ( mdmInf.nofc_str ) {
  4739.         free(mdmInf.nofc_str);
  4740.         mdmInf.nofc_str = NULL;
  4741.     }
  4742.     if ( mdmInf.ec_on_str ) {
  4743.         free(mdmInf.ec_on_str);
  4744.         mdmInf.ec_on_str = NULL;
  4745.     }
  4746.     if ( mdmInf.ec_off_str ) {
  4747.         free(mdmInf.ec_off_str);
  4748.         mdmInf.ec_off_str = NULL;
  4749.     }
  4750.     if ( mdmInf.dc_on_str ) {
  4751.         free(mdmInf.dc_on_str);
  4752.         mdmInf.dc_on_str = NULL;
  4753.     }
  4754.     if ( mdmInf.dc_off_str ) {
  4755.         free(mdmInf.dc_off_str);
  4756.         mdmInf.dc_off_str = NULL;
  4757.     }
  4758.     if ( mdmInf.aa_on_str ) {
  4759.         free(mdmInf.aa_on_str);
  4760.         mdmInf.aa_on_str = NULL;
  4761.     }
  4762.     if ( mdmInf.aa_off_str ) {
  4763.         free(mdmInf.aa_off_str);
  4764.         mdmInf.aa_off_str = NULL;
  4765.     }
  4766.     if ( mdmInf.sb_on_str ) {
  4767.         free(mdmInf.sb_on_str);
  4768.         mdmInf.sb_on_str = NULL;
  4769.     }
  4770.     if ( mdmInf.sb_off_str ) {
  4771.         free(mdmInf.sb_off_str);
  4772.         mdmInf.sb_off_str = NULL;
  4773.     }
  4774.     if ( mdmInf.sp_on_str ) {
  4775.         free(mdmInf.sp_on_str);
  4776.         mdmInf.sp_on_str = NULL;
  4777.     }
  4778.     if ( mdmInf.sp_off_str ) {
  4779.         free(mdmInf.sp_off_str);
  4780.         mdmInf.sp_off_str = NULL;
  4781.     }
  4782.     if ( mdmInf.vol1_str ) {
  4783.         free(mdmInf.vol1_str);
  4784.         mdmInf.vol1_str = NULL;
  4785.     }
  4786.     if ( mdmInf.vol2_str ) {
  4787.         free(mdmInf.vol2_str);
  4788.         mdmInf.vol2_str = NULL;
  4789.     }
  4790.     if ( mdmInf.vol3_str ) {
  4791.         free(mdmInf.vol3_str);
  4792.         mdmInf.vol3_str = NULL;
  4793.     }
  4794.     if ( mdmInf.ignoredt ) {
  4795.         free(mdmInf.ignoredt);
  4796.         mdmInf.ignoredt = NULL;
  4797.     }
  4798.     if ( mdmInf.ini2 ) {
  4799.         free(mdmInf.ini2);
  4800.         mdmInf.ini2 = NULL;
  4801.     }
  4802.     mdmInf.max_speed=0;
  4803.     mdmInf.capas=0;
  4804.  
  4805.     if ( LineDeviceId == (DWORD) -1 ||
  4806.          g_lpLineDevCaps[LineDeviceId]->dwDevSpecificSize == 0 )
  4807.         return NULL;
  4808.  
  4809.     if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpModemKey, 0,
  4810.                         KEY_READ, &hkModemKey) )
  4811.         return NULL;            /* failed */
  4812.  
  4813.     dwSize = sizeof(lpszKeyValue);
  4814.     lpszValueName = "FriendlyName";
  4815.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  4816.                            lpszKeyValue, &dwSize ))
  4817.     {
  4818.         mdmInf.name = strdup(lpszKeyValue);
  4819.     } else {
  4820.         dwSize = sizeof(lpszKeyValue);
  4821.         lpszValueName = "Model";
  4822.         if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  4823.                                lpszKeyValue, &dwSize ))
  4824.         {
  4825.             mdmInf.name = strdup(lpszKeyValue);
  4826.         }
  4827.     }
  4828.  
  4829. #ifdef COMMENT
  4830.     /* There is no place appropriate to place this stuff */
  4831.     dwSize = sizeof(lpszKeyValue);
  4832.     lpszValueName = "Reset";
  4833.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  4834.                            lpszKeyValue, &dwSize ))
  4835.     {
  4836.         for ( i=0,j=0;j<dwSize;i++,j++ )
  4837.         {
  4838.             if ( lpszKeyValue[j] == '<' ) {
  4839.                 if ( !strncmp( "<cr>", &lpszKeyValue[j], 4 ) ) {
  4840.                     lpszBuf[i] = '\015' ;
  4841.                     j += 3;
  4842.                 }
  4843.                 else if ( !strncmp( "<#>", &lpszKeyValue[j], 3 ) ) {
  4844.                     lpszBuf[i] = '0' ;
  4845.                     j += 2;
  4846.                 }
  4847.                 else lpszBuf[i] = lpszKeyValue[j];
  4848.             }
  4849.             else {
  4850.                 lpszBuf[i] = lpszKeyValue[j];
  4851.             }
  4852.         }
  4853.         mdmInf.?????_str = strdup(lpszBuf);
  4854.     }
  4855. #endif /* COMMENT */
  4856.  
  4857.     if ( !RegOpenKeyEx(hkModemKey, "Settings", 0,
  4858.                         KEY_READ, &hkSubKey) )
  4859.     {
  4860.         dwSize = sizeof(lpszKeyValue);
  4861.         lpszValueName = "Prefix";
  4862.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4863.                                lpszKeyValue, &dwSize ))
  4864.         {
  4865.             for ( i=0,j=0;j<dwSize;i++,j++ )
  4866.             {
  4867.                 if ( lpszKeyValue[j] == '<' ) {
  4868.                     if ( !strncmp( "<cr>", &lpszKeyValue[j], 4 ) ) {
  4869.                         lpszPrefix[i] = '\015' ;
  4870.                         j += 3;
  4871.                     }
  4872.                     else if ( !strncmp( "<#>", &lpszKeyValue[j], 3 ) ) {
  4873.                         lpszPrefix[i] = '0' ;
  4874.                         j += 2;
  4875.                     }
  4876.                     else lpszPrefix[i] = lpszKeyValue[j];
  4877.                 }
  4878.                 else {
  4879.                     lpszPrefix[i] = lpszKeyValue[j];
  4880.                 }
  4881.             }
  4882.         }
  4883. #ifdef COMMENT
  4884.         else strcpy(lpszPrefix,"AT");
  4885. #endif
  4886.         dwSize = sizeof(lpszKeyValue);
  4887.         lpszValueName = "Terminator";
  4888.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4889.                                lpszKeyValue, &dwSize ))
  4890.         {
  4891.             for ( i=0,j=0;j<dwSize;i++,j++ )
  4892.             {
  4893.                 if ( lpszKeyValue[j] == '<' ) {
  4894.                     if ( !strncmp( "<cr>", &lpszKeyValue[j], 4 ) ) {
  4895.                         lpszPostfix[i] = '\015' ;
  4896.                         j += 3;
  4897.                     }
  4898.                     else if ( !strncmp( "<#>", &lpszKeyValue[j], 3 ) ) {
  4899.                         lpszPostfix[i] = '0' ;
  4900.                         j += 2;
  4901.                     }
  4902.                     else lpszPostfix[i] = lpszKeyValue[j];
  4903.                 }
  4904.                 else {
  4905.                     lpszPostfix[i] = lpszKeyValue[j];
  4906.                 }
  4907.             }
  4908.         }
  4909. #ifdef COMMENT
  4910.         else strcpy(lpszPostfix,"\015");
  4911. #endif /* COMMENT */
  4912.  
  4913.         dwSize = sizeof(lpszKeyValue);
  4914.         lpszValueName = "DialPrefix";
  4915.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4916.                                lpszKeyValue, &dwSize ))
  4917.         {
  4918.             sprintf(lpszBuf,"%s%s%s%s",lpszPrefix,lpszKeyValue,"%s",lpszPostfix);
  4919.             mdmInf.dial_str = strdup(lpszBuf);
  4920.         }
  4921.         else mdmInf.dial_str = strdup("ATD%s\015");
  4922.  
  4923.         dwSize = sizeof(lpszKeyValue);
  4924.         lpszValueName = "FlowControl_Hard";
  4925.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4926.                                lpszKeyValue, &dwSize ))
  4927.         {
  4928.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  4929.             mdmInf.hwfc_str = strdup(lpszBuf);
  4930.         }
  4931.         else mdmInf.hwfc_str = strdup("");
  4932.  
  4933.         dwSize = sizeof(lpszKeyValue);
  4934.         lpszValueName = "FlowControl_Soft";
  4935.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4936.                                lpszKeyValue, &dwSize ))
  4937.         {
  4938.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  4939.             mdmInf.swfc_str = strdup(lpszBuf);
  4940.         }
  4941.         else mdmInf.swfc_str = strdup("");
  4942.  
  4943.         dwSize = sizeof(lpszKeyValue);
  4944.         lpszValueName = "FlowControl_Off";
  4945.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4946.                                lpszKeyValue, &dwSize ))
  4947.         {
  4948.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  4949.             mdmInf.nofc_str = strdup(lpszBuf);
  4950.         }
  4951.         else mdmInf.nofc_str = strdup("");
  4952.  
  4953.         dwSize = sizeof(lpszKeyValue);
  4954.         lpszValueName = "ErrorControl_On";
  4955.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4956.                                lpszKeyValue, &dwSize ))
  4957.         {
  4958.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  4959.             mdmInf.ec_on_str = strdup(lpszBuf);
  4960.         }
  4961.         else mdmInf.ec_on_str = strdup("");
  4962.  
  4963.         dwSize = sizeof(lpszKeyValue);
  4964.         lpszValueName = "ErrorControl_Off";
  4965.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4966.                                lpszKeyValue, &dwSize ))
  4967.         {
  4968.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  4969.             mdmInf.ec_off_str = strdup(lpszBuf);
  4970.         }
  4971.         else mdmInf.ec_off_str = strdup("");
  4972.  
  4973.         dwSize = sizeof(lpszKeyValue);
  4974.         lpszValueName = "Compression_On";
  4975.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4976.                                lpszKeyValue, &dwSize ))
  4977.         {
  4978.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  4979.             mdmInf.dc_on_str = strdup(lpszBuf);
  4980.         }
  4981.         else mdmInf.dc_on_str = strdup("");
  4982.  
  4983.         dwSize = sizeof(lpszKeyValue);
  4984.         lpszValueName = "Compression_Off";
  4985.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4986.                                lpszKeyValue, &dwSize ))
  4987.         {
  4988.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  4989.             mdmInf.dc_off_str = strdup(lpszBuf);
  4990.         }
  4991.         else mdmInf.dc_off_str = strdup("");
  4992.  
  4993.         dwSize = sizeof(lpszKeyValue);
  4994.         lpszValueName = "SpeakerMode_Dial";
  4995.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  4996.                                lpszKeyValue, &dwSize ))
  4997.         {
  4998.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  4999.             mdmInf.sp_on_str = strdup(lpszBuf);
  5000.         }
  5001.         else mdmInf.sp_on_str = strdup("");
  5002.  
  5003.         dwSize = sizeof(lpszKeyValue);
  5004.         lpszValueName = "SpeakerMode_Off";
  5005.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5006.                                lpszKeyValue, &dwSize ))
  5007.         {
  5008.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  5009.             mdmInf.sp_off_str = strdup(lpszBuf);
  5010.         }
  5011.         else mdmInf.sp_off_str = strdup("");
  5012.  
  5013.         dwSize = sizeof(lpszKeyValue);
  5014.         lpszValueName = "SpeakerVolume_Low";
  5015.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5016.                                lpszKeyValue, &dwSize ))
  5017.         {
  5018.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  5019.             mdmInf.vol1_str = strdup(lpszBuf);
  5020.         }
  5021.         else mdmInf.vol1_str = strdup("");
  5022.  
  5023.         dwSize = sizeof(lpszKeyValue);
  5024.         lpszValueName = "SpeakerVolume_Med";
  5025.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5026.                                lpszKeyValue, &dwSize ))
  5027.         {
  5028.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  5029.             mdmInf.vol2_str = strdup(lpszBuf);
  5030.         }
  5031.         else mdmInf.vol2_str = strdup("");
  5032.  
  5033.         dwSize = sizeof(lpszKeyValue);
  5034.         lpszValueName = "SpeakerVolume_High";
  5035.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5036.                                lpszKeyValue, &dwSize ))
  5037.         {
  5038.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  5039.             mdmInf.vol3_str = strdup(lpszBuf);
  5040.         }
  5041.         else mdmInf.vol3_str = strdup("");
  5042.  
  5043.         dwSize = sizeof(lpszKeyValue);
  5044.         lpszValueName = "Pulse";
  5045.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5046.                                lpszKeyValue, &dwSize ))
  5047.         {
  5048.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  5049.             mdmInf.pulse = strdup(lpszBuf);
  5050.         }
  5051.         else mdmInf.pulse = strdup("");
  5052.  
  5053.         dwSize = sizeof(lpszKeyValue);
  5054.         lpszValueName = "Tone";
  5055.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5056.                                lpszKeyValue, &dwSize ))
  5057.         {
  5058.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  5059.             mdmInf.tone = strdup(lpszBuf);
  5060.         }
  5061.         else mdmInf.tone = strdup("");
  5062.  
  5063.         /* We save Blind_Off and then append it to the Init string */
  5064.         dwSize = sizeof(lpszKeyValue);
  5065.         lpszValueName = "Blind_Off";
  5066.         RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5067.                                lpszBlindOff, &dwSize );
  5068.  
  5069.         dwSize = sizeof(lpszKeyValue);
  5070.         lpszValueName = "Blind_On";
  5071.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5072.                                lpszKeyValue, &dwSize ))
  5073.         {
  5074.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  5075.             mdmInf.ignoredt = strdup(lpszBuf);
  5076.         }
  5077.  
  5078.         dwSize = sizeof(lpszKeyValue);
  5079.         lpszValueName = "SpeedNegotiation_On";
  5080.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5081.                                lpszKeyValue, &dwSize ))
  5082.         {
  5083.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  5084.             mdmInf.sb_on_str = strdup(lpszBuf);
  5085.         }
  5086.         else
  5087.             mdmInf.sb_on_str = strdup("");
  5088.  
  5089.         dwSize = sizeof(lpszKeyValue);
  5090.         lpszValueName = "SpeedNegotiation_Off";
  5091.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5092.                                lpszKeyValue, &dwSize ))
  5093.         {
  5094.             sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  5095.             mdmInf.sb_off_str = strdup(lpszBuf);
  5096.         }
  5097.         else
  5098.             mdmInf.sb_off_str = strdup("");
  5099.  
  5100.         RegCloseKey( hkSubKey );
  5101.     }
  5102.  
  5103.     if ( !RegOpenKeyEx(hkModemKey, "Hangup", 0,
  5104.                         KEY_READ, &hkSubKey) )
  5105.     {
  5106.         dwSize = sizeof(lpszKeyValue);
  5107.         lpszValueName = "1";
  5108.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5109.                                lpszKeyValue, &dwSize ))
  5110.         {
  5111.             for ( i=0,j=0;j<dwSize;i++,j++ )
  5112.             {
  5113.                 if ( lpszKeyValue[j] == '<' ) {
  5114.                     if ( !strncmp( "<cr>", &lpszKeyValue[j], 4 ) ) {
  5115.                         lpszBuf[i] = '\015' ;
  5116.                         j += 3;
  5117.                     }
  5118.                     else if ( !strncmp( "<#>", &lpszKeyValue[j], 3 ) ) {
  5119.                         lpszBuf[i] = '0' ;
  5120.                         j += 2;
  5121.                     }
  5122.                     else lpszBuf[i] = lpszKeyValue[j];
  5123.                 }
  5124.                 else {
  5125.                     lpszBuf[i] = lpszKeyValue[j];
  5126.                 }
  5127.             }
  5128.             mdmInf.hup_str = strdup(lpszBuf);
  5129.         }
  5130.         RegCloseKey( hkSubKey );
  5131.     }
  5132.  
  5133.     if ( !RegOpenKeyEx(hkModemKey, "Init", 0,
  5134.                         KEY_READ, &hkSubKey) )
  5135.     {
  5136.         dwSize = sizeof(lpszKeyValue);
  5137.         lpszValueName = "1";
  5138.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5139.                                lpszKeyValue, &dwSize ))
  5140.         {
  5141.             if ( ckstrcmp(lpszKeyValue,"None",-1,0) == 0 ) {
  5142.                 lpszBuf[0] = '\0';
  5143.                 i++;
  5144.             } else {
  5145.             for ( i=0,j=0;j<dwSize;i++,j++ )
  5146.             {
  5147.                 if ( lpszKeyValue[j] == '<' ) {
  5148.                     if ( !strncmp( "<cr>", &lpszKeyValue[j], 4 ) ) {
  5149.                         lpszBuf[i] = '\015' ;
  5150.                         j += 3;
  5151.                     }
  5152.                     else if ( !strncmp( "<#>", &lpszKeyValue[j], 3 ) ) {
  5153.                         lpszBuf[i] = '0' ;
  5154.                         j += 2;
  5155.                     }
  5156.                     else lpszBuf[i] = lpszKeyValue[j];
  5157.                 }
  5158.                 else if ( lpszKeyValue[j] == ' ' ) {
  5159.                     i--;        /* skip the space */
  5160.                 }
  5161.                 else {
  5162.                     lpszBuf[i] = lpszKeyValue[j];
  5163.                 }
  5164.             }
  5165.             }
  5166.         }
  5167.  
  5168.         dwSize = sizeof(lpszKeyValue);
  5169.         lpszValueName = "2";
  5170.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5171.                                lpszKeyValue, &dwSize ))
  5172.         {
  5173.             if ( ckstrcmp(lpszKeyValue,"NoResponse",-1,0) != 0 ) {
  5174.                 i--;
  5175.                 j=0;
  5176.  
  5177.                 /* Remove Postfix if necessary */
  5178.                 if ( !strcmp(&lpszBuf[i-strlen(lpszPostfix)],lpszPostfix) )
  5179.                 {
  5180.                     i -= strlen(lpszPostfix);
  5181.                 }
  5182.  
  5183.                 if ( !strncmp(lpszKeyValue,lpszPrefix,strlen(lpszPrefix)) )
  5184.                 {
  5185.                     /* skip the prefix */
  5186.                     j += strlen(lpszPrefix);
  5187.                 }
  5188.                 for ( ;j<dwSize;i++,j++ )
  5189.                 {
  5190.                     if ( lpszKeyValue[j] == '<' ) {
  5191.                         if ( !strncmp( "<cr>", &lpszKeyValue[j], 4 ) ) {
  5192.                             lpszBuf[i] = '\015' ;
  5193.                             j += 3;
  5194.                         }
  5195.                         else if ( !strncmp( "<#>", &lpszKeyValue[j], 3 ) ) {
  5196.                             lpszBuf[i] = '0' ;
  5197.                             j += 2;
  5198.                         }
  5199.                         else lpszBuf[i] = lpszKeyValue[j];
  5200.                     }
  5201.                     else if ( lpszKeyValue[j] == ' ' ) {
  5202.                         i--;        /* skip the space */
  5203.                     }
  5204.                     else {
  5205.                         lpszBuf[i] = lpszKeyValue[j];
  5206.                     }
  5207.                 }
  5208.             }
  5209.         }
  5210.         RegCloseKey( hkSubKey );
  5211.  
  5212.         if ( lpszBlindOff[0] ) {
  5213.             i--;
  5214.             /* Remove Postfix if necessary */
  5215.             if ( !strcmp(&lpszBuf[i-strlen(lpszPostfix)],lpszPostfix) )
  5216.             {
  5217.                 i -= strlen(lpszPostfix);
  5218.             }
  5219.             strcpy(&lpszBuf[i],lpszBlindOff);
  5220.             i += strlen(lpszBlindOff);
  5221.             strcpy(&lpszBuf[i],lpszPostfix);
  5222.             i += strlen(lpszPostfix);
  5223.             i++;
  5224.         }
  5225.         mdmInf.wake_str = strdup(lpszBuf);
  5226.  
  5227.         dwSize = sizeof(lpszKeyValue);
  5228.         lpszValueName = "UserInit";
  5229.         if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5230.                                lpszKeyValue, &dwSize ))
  5231.         {
  5232.             if ( lpszKeyValue[0] ) {
  5233.                 sprintf(lpszBuf,"%s%s%s",lpszPrefix,lpszKeyValue,lpszPostfix);
  5234.                 mdmInf.ini2 = strdup(lpszBuf);
  5235.             }
  5236.         }
  5237.     }
  5238.     RegCloseKey( hkModemKey );
  5239.  
  5240.     /* Things we just set to default values */
  5241.     mdmInf.dial_time = 60;
  5242.     mdmInf.pause_chars = strdup(",$@W");
  5243.     mdmInf.pause_time = 2;
  5244.     mdmInf.wake_rate = 0;
  5245.     mdmInf.wake_prompt = strdup("OK\015");
  5246.     mdmInf.dmode_prompt = strdup("");
  5247.     mdmInf.dial_rate = 0;
  5248.     mdmInf.esc_time = 1100;
  5249.     mdmInf.esc_char = 43;
  5250.     mdmInf.aa_on_str = strdup("ATS0=1\015");
  5251.     mdmInf.aa_off_str = strdup("ATS0=0\015");
  5252.  
  5253.     /* leave enough room for provider specific information */
  5254.     lpCommProp = (COMMPROP *) malloc( 1024 );
  5255.     if ( lpCommProp != NULL ) {
  5256.         memset( lpCommProp, 0, 1024 );
  5257.         lpCommProp->wPacketLength = 1024;
  5258.         lpCommProp->dwProvSpec1 = COMMPROP_INITIALIZED;
  5259.  
  5260.         rc = GetCommProperties( hModem, lpCommProp );
  5261.     }
  5262.     else
  5263.         rc = 0;
  5264.     if ( rc &&
  5265.          lpCommProp->dwProvSubType == PST_MODEM &&
  5266.          lpCommProp->wcProvChar[0]) {
  5267.         lpModemDevCaps = (LPMODEMDEVCAPS) lpCommProp->wcProvChar;
  5268.         mdmInf.max_speed = lpModemDevCaps->dwMaxDTERate;
  5269.         mdmInf.capas =
  5270.             (!_stricmp("AT",lpszPrefix) ? CKD_AT : 0) |
  5271.             (lpModemDevCaps->dwModemOptions & MDM_FLOWCONTROL_HARD ? CKD_HW : 0) |
  5272.             (lpModemDevCaps->dwModemOptions & MDM_FLOWCONTROL_SOFT ? CKD_SW : 0) |
  5273.             (lpModemDevCaps->dwModemOptions & MDM_SPEED_ADJUST ? 0 : CKD_SB) |
  5274.             (lpModemDevCaps->dwModemOptions & MDM_COMPRESSION ? CKD_DC : 0) |
  5275.             (lpModemDevCaps->dwModemOptions & MDM_ERROR_CONTROL ? CKD_EC : 0);
  5276.     }
  5277.     else {
  5278.         mdmInf.max_speed=115200;
  5279.  
  5280.         /* Define the modem capabilities */
  5281.         mdmInf.capas =
  5282.             (!_stricmp("AT",lpszPrefix) ? CKD_AT : 0) |
  5283.             ((mdmInf.sb_on_str[0] ||
  5284.                mdmInf.ec_on_str[0] && mdmInf.dc_on_str[0]) ? CKD_SB : 0) |
  5285.             (mdmInf.ec_on_str[0] ? CKD_EC : 0) |
  5286.             (mdmInf.dc_on_str[0] ? CKD_DC : 0) |
  5287.             (mdmInf.hwfc_str[0]  ? CKD_HW : 0) |
  5288.             (mdmInf.swfc_str[0]  ? CKD_SW : 0) ;
  5289.     }
  5290.  
  5291.     if ( lpCommProp )
  5292.         free(lpCommProp);
  5293.     return &mdmInf;
  5294. }
  5295. #endif /* NODIAL */
  5296.  
  5297. void
  5298. cktapiDisplayRegistryModemInfo(LPCSTR lpModemKey )
  5299. {
  5300.     HKEY  hkModemKey=0;
  5301.     HKEY  hkSubKey=0;
  5302.     CHAR  lpszKeyValue[256];
  5303.     DWORD dwType=0;
  5304.     DWORD dwSize=0;
  5305.     CHAR *lpszValueName=NULL;
  5306.  
  5307.     printf("  Modem Registry Info:\n");
  5308.     if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpModemKey, 0,
  5309.                         KEY_READ, &hkModemKey) )
  5310.         return;         /* failed */
  5311.  
  5312.     dwSize = sizeof(lpszKeyValue);
  5313.     lpszValueName = "AttachedTo";
  5314.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5315.                            lpszKeyValue, &dwSize ))
  5316.     {
  5317.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5318.     }
  5319.  
  5320.     dwSize = sizeof(lpszKeyValue);
  5321.     lpszValueName = "FriendlyName";
  5322.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5323.                            lpszKeyValue, &dwSize ))
  5324.     {
  5325.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5326.     }
  5327.  
  5328.     dwSize = sizeof(lpszKeyValue);
  5329.     lpszValueName = "Manufacturer";
  5330.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5331.                            lpszKeyValue, &dwSize ))
  5332.     {
  5333.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5334.     }
  5335.  
  5336.     dwSize = sizeof(lpszKeyValue);
  5337.     lpszValueName = "Model";
  5338.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5339.                            lpszKeyValue, &dwSize ))
  5340.     {
  5341.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5342.     }
  5343.  
  5344.     dwSize = sizeof(lpszKeyValue);
  5345.     lpszValueName = "Reset";
  5346.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5347.                            lpszKeyValue, &dwSize ))
  5348.     {
  5349.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5350.     }
  5351.  
  5352.     dwSize = sizeof(lpszKeyValue);
  5353.     lpszValueName = "PortDriver";
  5354.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5355.                            lpszKeyValue, &dwSize ))
  5356.     {
  5357.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5358.     }
  5359.  
  5360.     dwSize = sizeof(lpszKeyValue);
  5361.     lpszValueName = "InfPath";
  5362.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5363.                            lpszKeyValue, &dwSize ))
  5364.     {
  5365.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5366.     }
  5367.  
  5368.     dwSize = sizeof(lpszKeyValue);
  5369.     lpszValueName = "InfSection";
  5370.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5371.                            lpszKeyValue, &dwSize ))
  5372.     {
  5373.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5374.     }
  5375.  
  5376.     dwSize = sizeof(lpszKeyValue);
  5377.     lpszValueName = "ProviderName";
  5378.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5379.                            lpszKeyValue, &dwSize ))
  5380.     {
  5381.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5382.     }
  5383.  
  5384.     dwSize = sizeof(lpszKeyValue);
  5385.     lpszValueName = "DriverDesc";
  5386.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5387.                            lpszKeyValue, &dwSize ))
  5388.     {
  5389.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5390.     }
  5391.  
  5392.     dwSize = sizeof(lpszKeyValue);
  5393.     lpszValueName = "ResponsesKeyName";
  5394.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5395.                            lpszKeyValue, &dwSize ))
  5396.     {
  5397.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5398.     }
  5399.  
  5400.     if ( !RegOpenKeyEx(hkModemKey, "EnableCallerID", 0,
  5401.                         KEY_READ, &hkSubKey) )
  5402.     {
  5403.         printf("    EnableCallerID:\n");
  5404.         dwSize = sizeof(lpszKeyValue);
  5405.         lpszValueName = "1";
  5406.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5407.                                lpszKeyValue, &dwSize ))
  5408.         {
  5409.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5410.         }
  5411.         RegCloseKey( hkSubKey );
  5412.     }
  5413.  
  5414.     if ( !RegOpenKeyEx(hkModemKey, "Answer", 0,
  5415.                         KEY_READ, &hkSubKey) )
  5416.     {
  5417.         printf("    Answer:\n");
  5418.         dwSize = sizeof(lpszKeyValue);
  5419.         lpszValueName = "1";
  5420.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5421.                                lpszKeyValue, &dwSize ))
  5422.         {
  5423.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5424.         }
  5425.         RegCloseKey( hkSubKey );
  5426.     }
  5427.  
  5428.     if ( !RegOpenKeyEx(hkModemKey, "Hangup", 0,
  5429.                         KEY_READ, &hkSubKey) )
  5430.     {
  5431.         printf("    Hangup:\n");
  5432.         dwSize = sizeof(lpszKeyValue);
  5433.         lpszValueName = "1";
  5434.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5435.                                lpszKeyValue, &dwSize ))
  5436.         {
  5437.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5438.         }
  5439.         RegCloseKey( hkSubKey );
  5440.     }
  5441.  
  5442.     if ( !RegOpenKeyEx(hkModemKey, "Init", 0,
  5443.                         KEY_READ, &hkSubKey) )
  5444.     {
  5445.         printf("    Init:\n");
  5446.         dwSize = sizeof(lpszKeyValue);
  5447.         lpszValueName = "1";
  5448.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5449.                                lpszKeyValue, &dwSize ))
  5450.         {
  5451.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5452.         }
  5453.  
  5454.         dwSize = sizeof(lpszKeyValue);
  5455.         lpszValueName = "2";
  5456.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5457.                                lpszKeyValue, &dwSize ))
  5458.         {
  5459.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5460.         }
  5461.         RegCloseKey( hkSubKey );
  5462.     }
  5463.  
  5464.     if ( !RegOpenKeyEx(hkModemKey, "Monitor", 0,
  5465.                         KEY_READ, &hkSubKey) )
  5466.     {
  5467.         printf("    Monitor:\n");
  5468.         dwSize = sizeof(lpszKeyValue);
  5469.         lpszValueName = "1";
  5470.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5471.                                lpszKeyValue, &dwSize ))
  5472.         {
  5473.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5474.         }
  5475.  
  5476.         dwSize = sizeof(lpszKeyValue);
  5477.         lpszValueName = "2";
  5478.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5479.                                lpszKeyValue, &dwSize ))
  5480.         {
  5481.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5482.         }
  5483.         RegCloseKey( hkSubKey );
  5484.     }
  5485.  
  5486.     if ( !RegOpenKeyEx(hkModemKey, "Settings", 0,
  5487.                         KEY_READ, &hkSubKey) )
  5488.     {
  5489.         printf("    Settings:\n");
  5490.         dwSize = sizeof(lpszKeyValue);
  5491.         lpszValueName = "Prefix";
  5492.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5493.                                lpszKeyValue, &dwSize ))
  5494.         {
  5495.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5496.         }
  5497.  
  5498.         dwSize = sizeof(lpszKeyValue);
  5499.         lpszValueName = "Terminator";
  5500.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5501.                                lpszKeyValue, &dwSize ))
  5502.         {
  5503.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5504.         }
  5505.  
  5506.         dwSize = sizeof(lpszKeyValue);
  5507.         lpszValueName = "DialPrefix";
  5508.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5509.                                lpszKeyValue, &dwSize ))
  5510.         {
  5511.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5512.         }
  5513.  
  5514.         dwSize = sizeof(lpszKeyValue);
  5515.         lpszValueName = "DialSuffix";
  5516.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5517.                                lpszKeyValue, &dwSize ))
  5518.         {
  5519.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5520.         }
  5521.  
  5522.         dwSize = sizeof(lpszKeyValue);
  5523.         lpszValueName = "SpeakerVolume_Low";
  5524.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5525.                                lpszKeyValue, &dwSize ))
  5526.         {
  5527.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5528.         }
  5529.  
  5530.         dwSize = sizeof(lpszKeyValue);
  5531.         lpszValueName = "SpeakerVolume_Med";
  5532.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5533.                                lpszKeyValue, &dwSize ))
  5534.         {
  5535.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5536.         }
  5537.  
  5538.         dwSize = sizeof(lpszKeyValue);
  5539.         lpszValueName = "SpeakerVolume_High";
  5540.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5541.                                lpszKeyValue, &dwSize ))
  5542.         {
  5543.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5544.         }
  5545.  
  5546.         dwSize = sizeof(lpszKeyValue);
  5547.         lpszValueName = "SpeakerMode_Off";
  5548.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5549.                                lpszKeyValue, &dwSize ))
  5550.         {
  5551.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5552.         }
  5553.  
  5554.         dwSize = sizeof(lpszKeyValue);
  5555.         lpszValueName = "SpeakerMode_Dial";
  5556.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5557.                                lpszKeyValue, &dwSize ))
  5558.         {
  5559.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5560.         }
  5561.  
  5562.         dwSize = sizeof(lpszKeyValue);
  5563.         lpszValueName = "SpeakerMode_On";
  5564.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5565.                                lpszKeyValue, &dwSize ))
  5566.         {
  5567.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5568.         }
  5569.  
  5570.         dwSize = sizeof(lpszKeyValue);
  5571.         lpszValueName = "SpeakerMode_Setup";
  5572.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5573.                                lpszKeyValue, &dwSize ))
  5574.         {
  5575.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5576.         }
  5577.  
  5578.         dwSize = sizeof(lpszKeyValue);
  5579.         lpszValueName = "FlowControl_Hard";
  5580.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5581.                                lpszKeyValue, &dwSize ))
  5582.         {
  5583.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5584.         }
  5585.  
  5586.         dwSize = sizeof(lpszKeyValue);
  5587.         lpszValueName = "FlowControl_Off";
  5588.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5589.                                lpszKeyValue, &dwSize ))
  5590.         {
  5591.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5592.         }
  5593.  
  5594.         dwSize = sizeof(lpszKeyValue);
  5595.         lpszValueName = "FlowControl_Soft";
  5596.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5597.                                lpszKeyValue, &dwSize ))
  5598.         {
  5599.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5600.         }
  5601.  
  5602.         dwSize = sizeof(lpszKeyValue);
  5603.         lpszValueName = "ErrorControl_On";
  5604.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5605.                                lpszKeyValue, &dwSize ))
  5606.         {
  5607.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5608.         }
  5609.  
  5610.         dwSize = sizeof(lpszKeyValue);
  5611.         lpszValueName = "ErrorControl_Off";
  5612.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5613.                                lpszKeyValue, &dwSize ))
  5614.         {
  5615.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5616.         }
  5617.  
  5618.         dwSize = sizeof(lpszKeyValue);
  5619.         lpszValueName = "ErrorControl_Forced";
  5620.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5621.                                lpszKeyValue, &dwSize ))
  5622.         {
  5623.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5624.         }
  5625.  
  5626.         dwSize = sizeof(lpszKeyValue);
  5627.         lpszValueName = "Compression_On";
  5628.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5629.                                lpszKeyValue, &dwSize ))
  5630.         {
  5631.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5632.         }
  5633.  
  5634.         dwSize = sizeof(lpszKeyValue);
  5635.         lpszValueName = "Compression_Off";
  5636.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5637.                                lpszKeyValue, &dwSize ))
  5638.         {
  5639.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5640.         }
  5641.  
  5642.         dwSize = sizeof(lpszKeyValue);
  5643.         lpszValueName = "Modulation_CCITT";
  5644.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5645.                                lpszKeyValue, &dwSize ))
  5646.         {
  5647.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5648.         }
  5649.  
  5650.         dwSize = sizeof(lpszKeyValue);
  5651.         lpszValueName = "Modulation_Bell";
  5652.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5653.                                lpszKeyValue, &dwSize ))
  5654.         {
  5655.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5656.         }
  5657.  
  5658.         dwSize = sizeof(lpszKeyValue);
  5659.         lpszValueName = "Pulse";
  5660.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5661.                                lpszKeyValue, &dwSize ))
  5662.         {
  5663.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5664.         }
  5665.  
  5666.         dwSize = sizeof(lpszKeyValue);
  5667.         lpszValueName = "Tone";
  5668.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5669.                                lpszKeyValue, &dwSize ))
  5670.         {
  5671.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5672.         }
  5673.  
  5674.         dwSize = sizeof(lpszKeyValue);
  5675.         lpszValueName = "Blind_Off";
  5676.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5677.                                lpszKeyValue, &dwSize ))
  5678.         {
  5679.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5680.         }
  5681.  
  5682.         dwSize = sizeof(lpszKeyValue);
  5683.         lpszValueName = "Blind_On";
  5684.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5685.                                lpszKeyValue, &dwSize ))
  5686.         {
  5687.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5688.         }
  5689.  
  5690.         dwSize = sizeof(lpszKeyValue);
  5691.         lpszValueName = "CallSetupFailTimer";
  5692.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5693.                                lpszKeyValue, &dwSize ))
  5694.         {
  5695.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5696.         }
  5697.  
  5698.         dwSize = sizeof(lpszKeyValue);
  5699.         lpszValueName = "InactivityTimeout";
  5700.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5701.                                lpszKeyValue, &dwSize ))
  5702.         {
  5703.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5704.         }
  5705.  
  5706.         dwSize = sizeof(lpszKeyValue);
  5707.         lpszValueName = "SpeedNegotiation_Off";
  5708.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5709.                                lpszKeyValue, &dwSize ))
  5710.         {
  5711.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5712.         }
  5713.  
  5714.         dwSize = sizeof(lpszKeyValue);
  5715.         lpszValueName = "SpeedNegotiation_On";
  5716.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5717.                                lpszKeyValue, &dwSize ))
  5718.         {
  5719.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5720.         }
  5721.  
  5722.         RegCloseKey( hkSubKey );
  5723.     }
  5724.  
  5725.     dwSize = sizeof(lpszKeyValue);
  5726.     lpszValueName = "UserInit";
  5727.     if ( !RegQueryValueEx( hkModemKey, lpszValueName, NULL, &dwType,
  5728.                            lpszKeyValue, &dwSize ))
  5729.     {
  5730.         printf("    %s: %s\n", lpszValueName, lpszKeyValue);
  5731.     }
  5732.  
  5733.     if ( !RegOpenKeyEx(hkModemKey, "Settings\\Init", 0,
  5734.                         KEY_READ, &hkSubKey) )
  5735.     {
  5736.         printf("\n    Settings\\Init:\n");
  5737.         dwSize = sizeof(lpszKeyValue);
  5738.         lpszValueName = "1";
  5739.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5740.                                lpszKeyValue, &dwSize ))
  5741.         {
  5742.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5743.         }
  5744.         dwSize = sizeof(lpszKeyValue);
  5745.         lpszValueName = "2";
  5746.         if ( !RegQueryValueEx( hkSubKey, lpszValueName, NULL, &dwType,
  5747.                                lpszKeyValue, &dwSize ))
  5748.         {
  5749.             printf("        %s: %s\n", lpszValueName, lpszKeyValue);
  5750.         }
  5751.         RegCloseKey( hkSubKey );
  5752.     }
  5753.  
  5754.     RegCloseKey( hkModemKey );
  5755.     printf("\n");
  5756.     return;
  5757. }
  5758. #endif /* CK_TAPI */
  5759.