home *** CD-ROM | disk | FTP | other *** search
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- // PARTICULAR PURPOSE.
- //
- // Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
- //
- // MODULE: TapiCode.c
- //
- // PURPOSE: Handles all the TAPI routines for TapiComm.
- //
- //
- // EXPORTED FUNCTIONS: These functions are for use by other modules.
- //
- // InitializeTAPI - Initialize this app with TAPI.
- // ShutdownTAPI - Shutdown this app from TAPI.
- // DialCall - Dial a Call.
- // HangupCall - Hangup an existing Call.
- // PostHangupCall - Posts a HangupCall message to the main window.
- //
- // INTERNAL FUNCTIONS: These functions are for this module only.
- //
- // DialCallInParts - Actually Dial the call.
- //
- // lineCallbackFunc - TAPI callback for async messages.
- //
- // CheckAndReAllocBuffer - Helper function for I_ wrappers functions.
- //
- // I_lineNegotiateAPIVersion - Wrapper for lineNegotiateAPIVersion.
- // I_lineGetDevCaps - Wrapper for lineGetDevCaps.
- // I_lineGetAddressStatus - Wrapper for lineGetAddressStatus.
- // I_lineTranslateAddress - Wrapper for lineTranslateAddress.
- // I_lineGetCallStatus - Wrapper for lineGetCallStatus.
- // I_lineGetAddressCaps - Wrapper for lineGetAddressCaps.
- //
- // WaitForCallState - Resynchronize by Waiting for a CallState.
- // WaitForReply - Resynchronize by Waiting for a LINE_REPLY.
- //
- // DoLineReply - Handle asynchronous LINE_REPLY.
- // DoLineClose - Handle asynchronous LINE_CLOSE.
- // DoLineDevState - Handle asynchronous LINE_LINEDEVSTATE.
- // DoLineCallState - Handle asynchronous LINE_CALLSTATE.
- // DoLineCreate - Handle asynchronous LINE_CREATE.
- //
- // HandleLineErr - Handler for most LINEERR errors.
- //
- // HandleIniFileCorrupt - LINEERR handler for INIFILECORRUPT.
- // HandleNoDriver - LINEERR handler for NODRIVER.
- // HandleNoDevicesInstalled - LINEERR handler for NODEVICE.
- // HandleReInit - LINEERR handler for REINIT.
- // HandleNoMultipleInstance - LINEERR handler for NOMULTIPLEINSTANCE.
- // HandleNoMem - LINEERR handler for NOMEM.
- // HandleOperationFailed - LINEERR handler for OPERATIONFAILED.
- // HandleResourceUnavail - LINEERR handler for RESOURCEUNAVAIL.
- //
- // LaunchModemControlPanelAdd - Launches the Modem Control Panel.
- //
- // WarningBox - Warn user if a line in use is removed.
- //
- // GetAddressToDial - Launches a GetAddressToDial dialog.
- // DialDialogProc - Dialog Proc for the GetAddressToDial API.
- //
- // I_lineNegotiateLegacyAPIVersion - Wrapper to negoitiate with legacy TSPs
- // VerifyUsableLine - Verify that a line device is usable
- // FillTAPILine - Fill a combobox with TAPI Device names
- // VerifyAndWarnUsableLine - Verify and warn if a line device is usable
- // FillCountryCodeList - Fill a combobox with country codes
- // FillLocationInfo - Fill a combobox with current TAPI locations
- // UseDialingRules - Enable/Disable dialing rules controls
- // DisplayPhoneNumber - Create and display a valid phone number
- // PreConfigureDevice - Preconfigure a device line
-
-
- #include <tapi.h>
- #include <windows.h>
- #include <string.h>
- #include "globals.h"
- #include "TapiInfo.h"
- #include "TapiCode.h"
- #include "CommCode.h"
- #include "resource.h"
- #include "statbar.h"
- #include "toolbar.h"
-
-
- // All TAPI line functions return 0 for SUCCESS, so define it.
- #define SUCCESS 0
-
- // Possible return error for resynchronization functions.
- #define WAITERR_WAITABORTED 1
- #define WAITERR_WAITTIMEDOUT 2
-
- // Reasons why a line device might not be usable by TapiComm.
- #define LINENOTUSEABLE_ERROR 1
- #define LINENOTUSEABLE_NOVOICE 2
- #define LINENOTUSEABLE_NODATAMODEM 3
- #define LINENOTUSEABLE_NOMAKECALL 4
- #define LINENOTUSEABLE_ALLOCATED 5
- #define LINENOTUSEABLE_INUSE 6
- #define LINENOTUSEABLE_NOCOMMDATAMODEM 7
-
- // Constant used in WaitForCallState when any new
- // callstate message is acceptable.
- #define I_LINECALLSTATE_ANY 0
-
- // Wait up to 30 seconds for an async completion.
- #define WAITTIMEOUT 30000
-
- // TAPI version that this sample is designed to use.
- #define SAMPLE_TAPI_VERSION 0x00010004
-
-
- // Global TAPI variables.
- HWND g_hWndMainWindow = NULL; // Apps main window.
- HWND g_hDlgParentWindow = NULL; // This will be the parent of all dialogs.
- HLINEAPP g_hLineApp = NULL;
- DWORD g_dwNumDevs = 0;
-
- // Global variable that holds the handle to a TAPI dialog
- // that needs to be dismissed if line conditions change.
- HWND g_hDialog = NULL;
-
- // Global flags to prevent re-entrancy problems.
- BOOL g_bShuttingDown = FALSE;
- BOOL g_bStoppingCall = FALSE;
- BOOL g_bInitializing = FALSE;
-
-
- // This sample only supports one call in progress at a time.
- BOOL g_bTapiInUse = FALSE;
-
-
- // Data needed per call. This sample only supports one call.
- HCALL g_hCall = NULL;
- HLINE g_hLine = NULL;
- DWORD g_dwDeviceID = 0;
- DWORD g_dwAPIVersion = 0;
- DWORD g_dwCallState = 0;
- char g_szDisplayableAddress[1024] = "";
- char g_szDialableAddress[1024] = "";
- BOOL g_bConnected = FALSE;
- LPVOID g_lpDeviceConfig = NULL;
- DWORD g_dwSizeDeviceConfig;
-
- // Global variables to allow us to do various waits.
- BOOL g_bReplyRecieved;
- DWORD g_dwRequestedID;
- long g_lAsyncReply;
- BOOL g_bCallStateReceived;
-
- // Structures needed to handle special non-dialable characters.
- #define g_sizeofNonDialable (sizeof(g_sNonDialable)/sizeof(g_sNonDialable[0]))
-
- typedef struct {
- LONG lError;
- DWORD dwDevCapFlag;
- LPSTR szToken;
- LPSTR szMsg;
- } NONDIALTOKENS;
-
- NONDIALTOKENS g_sNonDialable[] = {
- {LINEERR_DIALBILLING, LINEDEVCAPFLAGS_DIALBILLING, "$",
- "Wait for the credit card bong tone" },
- {LINEERR_DIALDIALTONE, LINEDEVCAPFLAGS_DIALDIALTONE, "W",
- "Wait for the second dial tone" },
- {LINEERR_DIALDIALTONE, LINEDEVCAPFLAGS_DIALDIALTONE, "w",
- "Wait for the second dial tone" },
- {LINEERR_DIALQUIET, LINEDEVCAPFLAGS_DIALQUIET, "@",
- "Wait for the remote end to answer" },
- {LINEERR_DIALPROMPT, 0, "?",
- "Press OK when you are ready to continue dialing"},
- };
-
- // "Dial" dialog controls and their associated help page IDs
- DWORD g_adwSampleMenuHelpIDs[] =
- {
- IDC_COUNTRYCODE , IDC_COUNTRYCODE,
- IDC_STATICCOUNTRYCODE , IDC_COUNTRYCODE,
- IDC_AREACODE , IDC_AREACODE,
- IDC_STATICAREACODE , IDC_AREACODE,
- IDC_PHONENUMBER , IDC_PHONENUMBER,
- IDC_STATICPHONENUMBER , IDC_PHONENUMBER,
- IDC_USEDIALINGRULES , IDC_USEDIALINGRULES,
- IDC_LOCATION , IDC_LOCATION,
- IDC_STATICLOCATION , IDC_LOCATION,
- IDC_CALLINGCARD , IDC_CALLINGCARD,
- IDC_STATICCALLINGCARD , IDC_CALLINGCARD,
- IDC_DIALINGPROPERTIES , IDC_DIALINGPROPERTIES,
- IDC_TAPILINE , IDC_TAPILINE,
- IDC_STATICTAPILINE , IDC_TAPILINE,
- IDC_CONFIGURELINE , IDC_CONFIGURELINE,
- IDC_CANONICALNUMBER , IDC_CANONICALNUMBER,
- IDC_STATICCANONICAL , IDC_CANONICALNUMBER,
- IDC_DIALABLENUMBER , IDC_DIALABLENUMBER,
- IDC_STATICDIALABLE , IDC_DIALABLENUMBER,
- IDC_DISPLAYABLENUMBER , IDC_DISPLAYABLENUMBER,
- IDC_STATICDISPLAYABLE , IDC_DISPLAYABLENUMBER,
- IDC_DIAL , IDC_DIAL,
- IDC_LINEICON , IDC_LINEICON,
- //IDC_STATICWHERETODIAL , IDC_STATICWHERETODIAL,
- //IDC_STATICHOWTODIAL , IDC_STATICHOWTODIAL,
- //IDC_STATICCONNECTUSING , IDC_STATICCONNECTUSING,
- //IDC_STATICPHONENUMBER , IDC_PHONENUMBER,
- 0,0
- };
-
- //**************************************************
- // Prototypes for functions used only in this module.
- //**************************************************
-
- BOOL DialCallInParts (
- LPLINEDEVCAPS lpLineDevCaps,
- LPCSTR lpszAddress,
- LPCSTR lpszDisplayableAddress);
-
- LPLINECALLPARAMS CreateCallParams (
- LPLINECALLPARAMS lpCallParams,
- LPCSTR lpszDisplayableAddress);
-
- DWORD I_lineNegotiateAPIVersion (
- DWORD dwDeviceID);
-
- LPVOID CheckAndReAllocBuffer(
- LPVOID lpBuffer, size_t sizeBufferMinimum,
- LPCSTR szApiPhrase);
-
- LPLINEDEVCAPS I_lineGetDevCaps (
- LPLINEDEVCAPS lpLineDevCaps,
- DWORD dwDeviceID,
- DWORD dwAPIVersion);
-
- LPLINEADDRESSSTATUS I_lineGetAddressStatus (
- LPLINEADDRESSSTATUS lpLineAddressStatus,
- HLINE hLine,
- DWORD dwAddressID);
-
- LPLINETRANSLATEOUTPUT I_lineTranslateAddress (
- LPLINETRANSLATEOUTPUT lpLineTranslateOutput,
- DWORD dwDeviceID,
- DWORD dwAPIVersion,
- LPCSTR lpszDialAddress);
-
- LPLINECALLSTATUS I_lineGetCallStatus (
- LPLINECALLSTATUS lpLineCallStatus,
- HCALL hCall);
-
- LPLINEADDRESSCAPS I_lineGetAddressCaps (
- LPLINEADDRESSCAPS lpLineAddressCaps,
- DWORD dwDeviceID, DWORD dwAddressID,
- DWORD dwAPIVersion, DWORD dwExtVersion);
-
- long WaitForCallState (DWORD dwNewCallState);
-
- long WaitForReply (long lRequestID);
-
- void CALLBACK lineCallbackFunc(
- DWORD hDevice, DWORD dwMsg, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
-
- void DoLineReply(
- DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
- void DoLineClose(
- DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
- void DoLineDevState(
- DWORD dwDevice, DWORD dwsg, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
- void DoLineCallState(
- DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
- void DoLineCreate(
- DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
-
- BOOL HandleLineErr(long lLineErr);
-
- BOOL HandleIniFileCorrupt();
- BOOL HandleNoDriver();
- BOOL HandleNoDevicesInstalled();
- BOOL HandleReInit();
- BOOL HandleNoMultipleInstance();
- BOOL HandleNoMem();
- BOOL HandleOperationFailed();
- BOOL HandleResourceUnavail();
-
- BOOL LaunchModemControlPanelAdd();
-
- void WarningBox(LPCSTR lpszMessage);
-
- BOOL CALLBACK DialDialogProc(
- HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-
- BOOL GetAddressToDial();
-
- DWORD I_lineNegotiateLegacyAPIVersion(DWORD dwDeviceID);
- long VerifyUsableLine(DWORD dwDeviceID);
- void FillTAPILine(HWND hwndDlg);
- BOOL VerifyAndWarnUsableLine(HWND hwndDlg);
- void FillCountryCodeList(HWND hwndDlg, DWORD dwDefaultCountryID);
- void FillLocationInfo(HWND hwndDlg, LPSTR lpszCurrentLocation,
- LPDWORD lpdwCountryID, LPSTR lpszAreaCode);
- void UseDialingRules(HWND hwndDlg);
- void DisplayPhoneNumber(HWND hwndDlg);
- void PreConfigureDevice(HWND hwndDlg, DWORD dwDeviceID);
-
-
- //**************************************************
- // Entry points from the UI
- //**************************************************
-
-
- //
- // FUNCTION: BOOL InitializeTAPI(HWND)
- //
- // PURPOSE: Initializes TAPI
- //
- // PARAMETERS:
- // hWndParent - Window to use as parent of any dialogs.
- //
- // RETURN VALUE:
- // Always returns 0 - command handled.
- //
- // COMMENTS:
- //
- // This is the API that initializes the app with TAPI.
- // If NULL is passed for the hWndParent, then its assumed
- // that re-initialization has occurred and the previous hWnd
- // is used.
- //
- //
-
- BOOL InitializeTAPI(HWND hWndParent)
- {
- long lReturn;
- BOOL bTryReInit = TRUE;
-
- // If we're already initialized, then initialization succeeds.
- if (g_hLineApp)
- return TRUE;
-
- // If we're in the middle of initializing, then fail, we're not done.
- if (g_bInitializing)
- return FALSE;
-
- g_bInitializing = TRUE;
-
- // Initialize TAPI
- do
- {
- lReturn = lineInitialize(&g_hLineApp, hInst,
- lineCallbackFunc, "TapiComm", &g_dwNumDevs);
-
- // If we get this error, its because some other app has yet
- // to respond to the REINIT message. Wait 5 seconds and try
- // again. If it still doesn't respond, tell the user.
- if (lReturn == LINEERR_REINIT)
- {
- if (bTryReInit)
- {
- MSG msg;
- DWORD dwTimeStarted;
-
- dwTimeStarted = GetTickCount();
-
- while(GetTickCount() - dwTimeStarted < 5000)
- {
- if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
- bTryReInit = FALSE;
- continue;
- }
- else
- {
- MessageBox(g_hDlgParentWindow,
- "A change to the system configuration requires that "
- "all Telephony applications relinquish their use of "
- "Telephony before any can progress. "
- "Some have not yet done so."
- ,"Warning",MB_OK);
- g_bInitializing = FALSE;
- return FALSE;
- }
- }
-
- if (lReturn == LINEERR_NODEVICE)
- {
- if (HandleNoDevicesInstalled())
- continue;
- else
- {
- OutputDebugString("No devices installed.\n");
- g_bInitializing = FALSE;
- return FALSE;
- }
- }
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineInitialize unhandled error: ");
- g_bInitializing = FALSE;
- return FALSE;
- }
- }
- while(lReturn != SUCCESS);
-
- // if hWndParent is a valid hWnd, we keep it as the parent for
- // all dialogs.
- if (IsWindow(hWndParent))
- {
- g_hDlgParentWindow = g_hWndMainWindow = hWndParent;
- }
- else
- {
- // Has the old g_hWndMainWindow gone away?
- if (!IsWindow(g_hWndMainWindow))
- {
- OutputDebugString("Main window unavailable.\n");
- g_hDlgParentWindow = g_hWndMainWindow = NULL;
- }
- }
-
- g_hCall = NULL;
- g_hLine = NULL;
-
- OutputDebugString("Tapi initialized.\n");
- g_bInitializing = FALSE;
- return TRUE;
- }
-
-
- //
- // FUNCTION: BOOL ShutdownTAPI()
- //
- // PURPOSE: Shuts down all use of TAPI
- //
- // PARAMETERS:
- // None
- //
- // RETURN VALUE:
- // True if TAPI successfully shut down.
- //
- // COMMENTS:
- //
- // If ShutdownTAPI fails, then its likely either a problem
- // with the service provider (and might require a system
- // reboot to correct) or the application ran out of memory.
- //
- //
-
- BOOL ShutdownTAPI()
- {
- long lReturn;
-
- // If we aren't initialized, then Shutdown is unnecessary.
- if (g_hLineApp == NULL)
- return TRUE;
-
- // Prevent ShutdownTAPI re-entrancy problems.
- if (g_bShuttingDown)
- return TRUE;
-
- g_bShuttingDown = TRUE;
-
- HangupCall();
-
- do
- {
- lReturn = lineShutdown(g_hLineApp);
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn, "lineShutdown unhandled error: ");
- break;
- }
- }
- while(lReturn != SUCCESS);
-
- g_bTapiInUse = FALSE;
- g_bConnected = FALSE;
- g_hLineApp = NULL;
- g_hCall = NULL;
- g_hLine = NULL;
- g_bShuttingDown = FALSE;
- OutputDebugString("TAPI uninitialized.\n");
- return TRUE;
- }
-
-
-
- //
- // FUNCTION: BOOL HangupCall()
- //
- // PURPOSE: Hangup the call in progress if it exists.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE if call hung up successfully.
- //
- // COMMENTS:
- //
- // If HangupCall fails, then its likely either a problem
- // with the service provider (and might require a system
- // reboot to correct) or the application ran out of memory.
- //
- //
-
- BOOL HangupCall()
- {
- LPLINECALLSTATUS pLineCallStatus = NULL;
- long lReturn;
-
- // Prevent HangupCall re-entrancy problems.
- if (g_bStoppingCall)
- return TRUE;
-
- // if the 'Call' dialog is up, dismiss it.
- if (g_hDialog)
- PostMessage(g_hDialog, WM_COMMAND, IDCANCEL, 0);
-
- // If Tapi is not being used right now, then the call is hung up.
- if (!g_bTapiInUse)
- return TRUE;
-
- g_bStoppingCall = TRUE;
- OutputDebugString("Stopping Call in progress\n");
-
- // Disable the 'hangup call' user interface.
- EnableHangupCall(g_hWndMainWindow, FALSE);
-
- // Stop any data communications on the comm port.
- StopComm();
-
- // If there is a call in progress, drop and deallocate it.
- if (g_hCall)
- {
- // I_lineGetCallStatus returns a LocalAlloc()d buffer
- pLineCallStatus = I_lineGetCallStatus(pLineCallStatus, g_hCall);
- if (pLineCallStatus == NULL)
- {
- ShutdownTAPI();
- g_bStoppingCall = FALSE;
- return FALSE;
- }
-
- // Only drop the call when the line is not IDLE.
- if (!((pLineCallStatus -> dwCallState) & LINECALLSTATE_IDLE))
- {
- do
- {
- lReturn = WaitForReply(lineDrop(g_hCall, NULL, 0));
-
- if (lReturn == WAITERR_WAITTIMEDOUT)
- {
- OutputDebugString("Call timed out in WaitForReply.\n");
- break;
- }
-
- if (lReturn == WAITERR_WAITABORTED)
- {
- OutputDebugString("lineDrop: WAITERR_WAITABORTED.\n");
- break;
- }
-
- // Was the call already in IDLE?
- if (lReturn == LINEERR_INVALCALLSTATE)
- break;
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineDrop unhandled error: ");
- break;
- }
- }
- while(lReturn != SUCCESS);
-
- // Wait for the dropped call to go IDLE before continuing.
- lReturn = WaitForCallState(LINECALLSTATE_IDLE);
-
- if (lReturn == WAITERR_WAITTIMEDOUT)
- OutputDebugString("Call timed out waiting for IDLE state.\n");
-
- if (lReturn == WAITERR_WAITABORTED)
- OutputDebugString(
- "WAITERR_WAITABORTED while waiting for IDLE state.\n");
-
- OutputDebugString("Call Dropped.\n");
- }
-
- // The call is now idle. Deallocate it!
- do
- {
- lReturn = lineDeallocateCall(g_hCall);
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineDeallocateCall unhandled error: ");
- break;
- }
- }
- while(lReturn != SUCCESS);
-
- OutputDebugString("Call Deallocated.\n");
- }
-
-
- // if we have a line open, close it.
- if (g_hLine)
- {
- do
- {
- lReturn = lineClose(g_hLine);
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineClose unhandled error: ");
- break;
- }
- }
- while(lReturn != SUCCESS);
-
- OutputDebugString("Line Closed.\n");
- }
-
- // Call and Line are taken care of. Finish cleaning up.
-
- // If there is device configuration information, free the memory.
- if (g_lpDeviceConfig)
- LocalFree(g_lpDeviceConfig);
- g_lpDeviceConfig = NULL;
-
- g_hCall = NULL;
- g_hLine = NULL;
- g_bConnected = FALSE;
-
- g_bTapiInUse = FALSE;
- g_bStoppingCall = FALSE; // allow HangupCall to be called again.
- OutputDebugString("Call stopped\n");
-
- // Update the user interface.
- UpdateStatusBar("Ready to make a call.",1,0);
- EnableMakeCall(g_hWndMainWindow, TRUE);
-
- // Need to free LocalAlloc()d buffer returned from I_lineGetCallStatus
- if (pLineCallStatus)
- LocalFree(pLineCallStatus);
-
- return TRUE;
- }
-
-
- //
- // FUNCTION: PostHangupCall()
- //
- // PURPOSE: Posts a message to the main TAPI thread to hangup the call.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // TAPI is thread specific, meaning that only the thread that does the
- // lineInitialize can get asynchronous messages through the callback.
- // Since the HangupCall can potentially go into a loop waiting for
- // specific events, any other threads that call HangupCall can cause
- // timing confusion. Best to just have other threads 'ask' the main thread
- // to hangup the call.
- //
-
- void PostHangupCall()
- {
- PostMessage(g_hWndMainWindow, WM_COMMAND, IDM_HANGUPCALL, 0);
- }
-
-
-
- //
- // FUNCTION: DialCall()
- //
- // PURPOSE: Get a number from the user and dial it.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE if able to get a number, find a line, and dial successfully.
- //
- // COMMENTS:
- //
- // This function makes several assumptions:
- // - The number dialed will always explicitly come from the user.
- // - There will only be one outgoing address per line.
- //
-
- BOOL DialCall()
- {
- long lReturn;
- LPLINEADDRESSSTATUS lpLineAddressStatus = NULL;
- LPLINEDEVCAPS lpLineDevCaps = NULL;
-
- if (g_bTapiInUse)
- {
- OutputDebugString("A call is already being handled\n");
- return FALSE;
- }
-
- // If TAPI isn't initialized, its either because we couldn't initialize
- // at startup (and this might have been corrected by now), or because
- // a REINIT event was received. In either case, try to init now.
-
- if (!g_hLineApp)
- {
- if (!InitializeTAPI(NULL))
- return FALSE;
- }
-
- // If there are no line devices installed on the machine, lets give
- // the user the opportunity to install one.
- if (g_dwNumDevs < 1)
- {
- if (!HandleNoDevicesInstalled())
- return FALSE;
- }
-
- // We now have a call active. Prevent future calls.
- g_bTapiInUse = TRUE;
- EnableMakeCall(g_hWndMainWindow, FALSE);
-
-
- // Get a phone number from the user.
- // Phone number will be placed in global variables if successful
- if (!GetAddressToDial())
- {
- HangupCall();
- goto DeleteBuffers;
- }
-
- // Negotiate the API version to use for this device.
- g_dwAPIVersion = I_lineNegotiateAPIVersion(g_dwDeviceID);
- if (g_dwAPIVersion == 0)
- {
- MessageBox(g_hDlgParentWindow,
- "Line Version unsupported by this Sample",
- "Unable to Use Line",MB_OK);
- HangupCall();
- goto DeleteBuffers;
- }
-
- // Need to check the DevCaps to make sure this line is usable.
- // The 'Dial' dialog checks also, but better safe than sorry.
- lpLineDevCaps = I_lineGetDevCaps(lpLineDevCaps,
- g_dwDeviceID, g_dwAPIVersion);
- if (lpLineDevCaps == NULL)
- {
- HangupCall();
- MessageBox(g_hDlgParentWindow,
- "Error on Requested line",
- "Unable to Use Line",MB_OK);
- goto DeleteBuffers;
- }
-
- if (!(lpLineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE ))
- {
- HangupCall();
- MessageBox(g_hDlgParentWindow,
- "Error on Requested line",
- "The selected line doesn't support VOICE capabilities",
- MB_OK);
- goto DeleteBuffers;
- }
-
- if (!(lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM))
- {
- HangupCall();
- MessageBox(g_hDlgParentWindow,
- "Error on Requested line",
- "The selected line doesn't support DATAMODEM capabilities",
- MB_OK);
- goto DeleteBuffers;
- }
-
- // Does this line have the capability to make calls?
- // It is possible that some lines can't make outbound calls.
- if (!(lpLineDevCaps->dwLineFeatures & LINEFEATURE_MAKECALL))
- {
- HangupCall();
- MessageBox(g_hDlgParentWindow,
- "Error on Requested line",
- "The selected line doesn't support MAKECALL capabilities",
- MB_OK);
- goto DeleteBuffers;
- }
-
- // Open the Line for an outgoing DATAMODEM call.
- do
- {
- lReturn = lineOpen(g_hLineApp, g_dwDeviceID, &g_hLine,
- g_dwAPIVersion, 0, 0,
- LINECALLPRIVILEGE_NONE, LINEMEDIAMODE_DATAMODEM,
- 0);
-
- if(lReturn == LINEERR_ALLOCATED)
- {
- HangupCall();
- MessageBox(g_hDlgParentWindow,
- "Line is already in use by a non-TAPI application "
- "or by another TAPI Service Provider.",
- "Unable to Use Line",MB_OK);
- goto DeleteBuffers;
- }
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn, "lineOpen unhandled error: ");
- MessageBox(g_hDlgParentWindow,
- "Error on Requested line",
- "Unable to Use Line",MB_OK);
- HangupCall();
- goto DeleteBuffers;
- }
- }
- while(lReturn != SUCCESS);
-
- // Tell the service provider that we want all notifications that
- // have anything to do with this line.
- do
- {
- // Set the messages we are interested in.
-
- // Note that while most applications aren't really interested
- // in dealing with all of the possible messages, its interesting
- // to see which come through the callback for testing purposes.
-
- lReturn = lineSetStatusMessages(g_hLine,
- LINEDEVSTATE_OTHER |
- LINEDEVSTATE_RINGING |
- LINEDEVSTATE_CONNECTED | // Important state!
- LINEDEVSTATE_DISCONNECTED | // Important state!
- LINEDEVSTATE_MSGWAITON |
- LINEDEVSTATE_MSGWAITOFF |
- LINEDEVSTATE_INSERVICE |
- LINEDEVSTATE_OUTOFSERVICE | // Important state!
- LINEDEVSTATE_MAINTENANCE | // Important state!
- LINEDEVSTATE_OPEN |
- LINEDEVSTATE_CLOSE |
- LINEDEVSTATE_NUMCALLS |
- LINEDEVSTATE_NUMCOMPLETIONS |
- LINEDEVSTATE_TERMINALS |
- LINEDEVSTATE_ROAMMODE |
- LINEDEVSTATE_BATTERY |
- LINEDEVSTATE_SIGNAL |
- LINEDEVSTATE_DEVSPECIFIC |
- LINEDEVSTATE_REINIT | // Not allowed to disable this.
- LINEDEVSTATE_LOCK |
- LINEDEVSTATE_CAPSCHANGE |
- LINEDEVSTATE_CONFIGCHANGE |
- LINEDEVSTATE_COMPLCANCEL ,
-
- LINEADDRESSSTATE_OTHER |
- LINEADDRESSSTATE_DEVSPECIFIC|
- LINEADDRESSSTATE_INUSEZERO |
- LINEADDRESSSTATE_INUSEONE |
- LINEADDRESSSTATE_INUSEMANY |
- LINEADDRESSSTATE_NUMCALLS |
- LINEADDRESSSTATE_FORWARD |
- LINEADDRESSSTATE_TERMINALS |
- LINEADDRESSSTATE_CAPSCHANGE);
-
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- // If we do get an unhandled problem, we don't care.
- // We just won't get notifications.
- OutputDebugLineError(lReturn,
- "lineSetStatusMessages unhandled error: ");
- break;
- }
- }
- while(lReturn != SUCCESS);
-
-
- // Get LineAddressStatus so we can make sure the line
- // isn't already in use by a TAPI application.
- lpLineAddressStatus =
- I_lineGetAddressStatus(lpLineAddressStatus, g_hLine, 0);
-
- if (lpLineAddressStatus == NULL)
- {
- HangupCall();
- MessageBox(g_hDlgParentWindow,
- "Error on Requested line",
- "Unable to Use Line",MB_OK);
- goto DeleteBuffers;
- }
-
- // MAKECALL will be set if there are any available call appearances
- if ( ! ((lpLineAddressStatus -> dwAddressFeatures) &
- LINEADDRFEATURE_MAKECALL) )
- {
- OutputDebugString("This line is not available to place a call.\n");
- HangupCall();
- MessageBox(g_hDlgParentWindow,
- "Requested line is already in use",
- "Unable to Use Line",MB_OK);
- goto DeleteBuffers;
- }
-
- // If the line was configured in the 'Dial' dialog, then
- // we need to actually complete the configuration.
- if (g_lpDeviceConfig)
- lineSetDevConfig(g_dwDeviceID, g_lpDeviceConfig,
- g_dwSizeDeviceConfig, "comm/datamodem");
-
- // Start dialing the number
- if (DialCallInParts(lpLineDevCaps, g_szDialableAddress,
- g_szDisplayableAddress))
- {
- OutputDebugString("DialCallInParts succeeded.\n");
- }
- else
- {
- OutputDebugString("DialCallInParts failed.\n");
- HangupCall();
- goto DeleteBuffers;
- }
-
- DeleteBuffers:
-
- if (lpLineAddressStatus)
- LocalFree(lpLineAddressStatus);
- if (lpLineDevCaps)
- LocalFree(lpLineDevCaps);
- if (g_bTapiInUse)
- EnableHangupCall(g_hWndMainWindow, TRUE);
-
- return g_bTapiInUse;
- }
-
-
- //**************************************************
- // These APIs are specific to this module
- //**************************************************
-
-
-
- //
- // FUNCTION: DialCallInParts(LPLINEDEVCAPS, LPCSTR, LPCSTR)
- //
- // PURPOSE: Dials the call, handling special characters.
- //
- // PARAMETERS:
- // lpLineDevCaps - LINEDEVCAPS for the line to be used.
- // lpszAddress - Address to Dial.
- // lpszDisplayableAddress - Displayable Address.
- //
- // RETURN VALUE:
- // Returns TRUE if we successfully Dial.
- //
- // COMMENTS:
- //
- // This function dials the Address and handles any
- // special characters in the address that the service provider
- // can't handle. It requires input from the user to handle
- // these characters; this can cause problems for fully automated
- // dialing.
- //
- // Note that we can return TRUE, even if we don't reach a
- // CONNECTED state. DIalCallInParts returns as soon as the
- // Address is fully dialed or when an error occurs.
- //
- //
-
- BOOL DialCallInParts(LPLINEDEVCAPS lpLineDevCaps,
- LPCSTR lpszAddress, LPCSTR lpszDisplayableAddress)
- {
- LPLINECALLPARAMS lpCallParams = NULL;
- LPLINEADDRESSCAPS lpAddressCaps = NULL;
- LPLINECALLSTATUS lpLineCallStatus = NULL;
-
- long lReturn;
- int i;
- DWORD dwDevCapFlags;
- char szFilter[1+sizeof(g_sNonDialable)] = "";
- BOOL bFirstDial = TRUE;
-
- // Variables to handle Dialable Substring dialing.
- LPSTR lpDS; // This is just so we can free lpszDialableSubstring later.
- LPSTR lpszDialableSubstring;
- int nAddressLength = 0;
- int nCurrentAddress = 0;
- char chUnhandledCharacter;
-
- // Get the capabilities for the line device we're going to use.
- lpAddressCaps = I_lineGetAddressCaps(lpAddressCaps,
- g_dwDeviceID, 0, g_dwAPIVersion, 0);
- if (lpAddressCaps == NULL)
- return FALSE;
-
- // Setup our CallParams for DATAMODEM settings.
- lpCallParams = CreateCallParams (lpCallParams, lpszDisplayableAddress);
- if (lpCallParams == NULL)
- return FALSE;
-
- // Determine which special characters the service provider
- // does *not* handle so we can handle them manually.
- // Keep list of unhandled characters in szFilter.
-
- dwDevCapFlags = lpLineDevCaps -> dwDevCapFlags; // SP handled characters.
- for (i = 0; i < g_sizeofNonDialable ; i++)
- {
- if ((dwDevCapFlags & g_sNonDialable[i].dwDevCapFlag) == 0)
- {
- strcat(szFilter, g_sNonDialable[i].szToken);
- }
- }
-
- // szFilter now contains the set of tokens which delimit dialable substrings
-
- // Setup the strings for substring dialing.
-
- nAddressLength = strlen(lpszAddress);
- lpDS = lpszDialableSubstring = (LPSTR) LocalAlloc(LPTR, nAddressLength + 1);
- if (lpszDialableSubstring == NULL)
- {
- OutputDebugLastError(GetLastError(), "LocalAlloc failed: ");
- HandleNoMem();
- goto errExit;
- }
-
- // Lets start dialing substrings!
- while (nCurrentAddress < nAddressLength)
- {
- retryAfterError:
-
- // Find the next undialable character
- i = strcspn(&lpszAddress[nCurrentAddress], szFilter);
-
- // Was there one before the end of the Address string?
- if (i + nCurrentAddress < nAddressLength)
- {
- // Make sure this device can handle partial dial.
- if (! (lpAddressCaps -> dwAddrCapFlags &
- LINEADDRCAPFLAGS_PARTIALDIAL))
- {
- MessageBox(g_hDlgParentWindow,
- "This line doesn't support partial dialing.\n",
- "Warning",MB_OK);
- goto errExit;
- }
- // Remember what the unhandled character is so we can handle it.
- chUnhandledCharacter = lpszAddress[nCurrentAddress+i];
-
- // Copy the dialable string to the Substring.
- memcpy(lpszDialableSubstring, &lpszAddress[nCurrentAddress], i);
-
- // Terminate the substring with a ';' to signify the partial dial.
- lpszDialableSubstring[i] = ';';
- lpszDialableSubstring[i+1] = '\0';
-
- // Increment the address for next iteration.
- nCurrentAddress += i + 1;
- }
- else // No more partial dials. Dial the rest of the Address.
- {
- lpszDialableSubstring = (LPSTR) &lpszAddress[nCurrentAddress];
- chUnhandledCharacter = 0;
- nCurrentAddress = nAddressLength;
- }
-
- do
- {
- if (bFirstDial)
- lReturn = WaitForReply(
- lineMakeCall(g_hLine, &g_hCall, lpszDialableSubstring,
- 0, lpCallParams) );
- else
- lReturn = WaitForReply(
- lineDial(g_hCall, lpszDialableSubstring, 0) );
-
- switch(lReturn)
- {
- // We should not have received these errors because of the
- // prefiltering strategy, but there may be some ill-behaved
- // service providers which do not correctly set their
- // devcapflags. Add the character corresponding to the error
- // to the filter set and retry dialing.
- //
- case LINEERR_DIALBILLING:
- case LINEERR_DIALDIALTONE:
- case LINEERR_DIALQUIET:
- case LINEERR_DIALPROMPT:
- {
- OutputDebugString("Service Provider incorrectly sets dwDevCapFlags\n");
-
- for (i = 0; i < g_sizeofNonDialable; i++)
- if (lReturn == g_sNonDialable[i].lError)
- {
- strcat(szFilter, g_sNonDialable[i].szToken);
- }
-
- goto retryAfterError;
- }
-
- case WAITERR_WAITABORTED:
- OutputDebugString("While Dialing, WaitForReply aborted.\n");
- goto errExit;
-
- }
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- if (bFirstDial)
- OutputDebugLineError(lReturn, "lineMakeCall unhandled error: ");
- else
- OutputDebugLineError(lReturn, "lineDial unhandled error: ");
-
- goto errExit;
- }
-
- }
- while (lReturn != SUCCESS);
-
- bFirstDial = FALSE;
-
- // The dial was successful; now handle characters the service
- // provider didn't (if any).
- if (chUnhandledCharacter)
- {
- LPSTR lpMsg = "";
-
- // First, wait until we know we can continue dialing. While the
- // last string is still pending to be dialed, we can't dial another.
-
- while(TRUE)
- {
-
- lpLineCallStatus = I_lineGetCallStatus(lpLineCallStatus, g_hCall);
- if (lpLineCallStatus == NULL)
- goto errExit;
-
- // Does CallStatus say we can dial now?
- if ((lpLineCallStatus->dwCallFeatures) & LINECALLFEATURE_DIAL)
- {
- OutputDebugString("Ok to continue dialing.\n");
- break;
- }
-
- // We can't dial yet, so wait for a CALLSTATE message
- OutputDebugString("Waiting for dialing to be enabled.\n");
-
- if (WaitForCallState(I_LINECALLSTATE_ANY) != SUCCESS)
- goto errExit;
- }
-
- for (i = 0; i < g_sizeofNonDialable; i++)
- if (chUnhandledCharacter == g_sNonDialable[i].szToken[0])
- lpMsg = g_sNonDialable[i].szMsg;
-
- MessageBox(g_hDlgParentWindow, lpMsg, "Dialing Paused", MB_OK);
- }
-
- } // continue dialing until we dial all Dialable Substrings.
-
- LocalFree(lpCallParams);
- LocalFree(lpDS);
- LocalFree(lpAddressCaps);
- if (lpLineCallStatus)
- LocalFree(lpLineCallStatus);
-
- return TRUE;
-
- errExit:
- // if lineMakeCall has already been successfully called, there's a call in progress.
- // let the invoking routine shut down the call.
- // if the invoker did not clean up the call, it should be done here.
-
- if (lpLineCallStatus)
- LocalFree(lpLineCallStatus);
- if (lpDS)
- LocalFree(lpDS);
- if (lpCallParams)
- LocalFree(lpCallParams);
- if (lpAddressCaps)
- LocalFree(lpAddressCaps);
-
- return FALSE;
- }
-
-
- //
- // FUNCTION: CreateCallParams(LPLINECALLPARAMS, LPCSTR)
- //
- // PURPOSE: Allocates and fills a LINECALLPARAMS structure
- //
- // PARAMETERS:
- // lpCallParams -
- // lpszDisplayableAddress -
- //
- // RETURN VALUE:
- // Returns a LPLINECALLPARAMS ready to use for dialing DATAMODEM calls.
- // Returns NULL if unable to allocate the structure.
- //
- // COMMENTS:
- //
- // If a non-NULL lpCallParams is passed in, it must have been allocated
- // with LocalAlloc, and can potentially be freed and reallocated. It must
- // also have the dwTotalSize field correctly set.
- //
- //
-
- LPLINECALLPARAMS CreateCallParams (
- LPLINECALLPARAMS lpCallParams, LPCSTR lpszDisplayableAddress)
- {
- size_t sizeDisplayableAddress;
-
- if (lpszDisplayableAddress == NULL)
- lpszDisplayableAddress = "";
-
- sizeDisplayableAddress = strlen(lpszDisplayableAddress) + 1;
-
- lpCallParams = (LPLINECALLPARAMS) CheckAndReAllocBuffer(
- (LPVOID) lpCallParams,
- sizeof(LINECALLPARAMS) + sizeDisplayableAddress,
- "CreateCallParams: ");
-
- if (lpCallParams == NULL)
- return NULL;
-
- // This is where we configure the line for DATAMODEM usage.
- lpCallParams -> dwBearerMode = LINEBEARERMODE_VOICE;
- lpCallParams -> dwMediaMode = LINEMEDIAMODE_DATAMODEM;
-
- // This specifies that we want to use only IDLE calls and
- // don't want to cut into a call that might not be IDLE (ie, in use).
- lpCallParams -> dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
-
- // if there are multiple addresses on line, use first anyway.
- // It will take a more complex application than a simple tty app
- // to use multiple addresses on a line anyway.
- lpCallParams -> dwAddressMode = LINEADDRESSMODE_ADDRESSID;
- lpCallParams -> dwAddressID = 0;
-
- // Since we don't know where we originated, leave these blank.
- lpCallParams -> dwOrigAddressSize = 0;
- lpCallParams -> dwOrigAddressOffset = 0;
-
- // Unimodem ignores these values.
- (lpCallParams -> DialParams) . dwDialSpeed = 0;
- (lpCallParams -> DialParams) . dwDigitDuration = 0;
- (lpCallParams -> DialParams) . dwDialPause = 0;
- (lpCallParams -> DialParams) . dwWaitForDialtone = 0;
-
- // Address we are dialing.
- lpCallParams -> dwDisplayableAddressOffset = sizeof(LINECALLPARAMS);
- lpCallParams -> dwDisplayableAddressSize = sizeDisplayableAddress;
- strcpy((LPSTR)lpCallParams + sizeof(LINECALLPARAMS),
- lpszDisplayableAddress);
-
- return lpCallParams;
- }
-
-
- //
- // FUNCTION: long WaitForReply(long)
- //
- // PURPOSE: Resynchronize by waiting for a LINE_REPLY
- //
- // PARAMETERS:
- // lRequestID - The asynchronous request ID that we're
- // on a LINE_REPLY for.
- //
- // RETURN VALUE:
- // - 0 if LINE_REPLY responded with a success.
- // - LINEERR constant if LINE_REPLY responded with a LINEERR
- // - 1 if the line was shut down before LINE_REPLY is received.
- //
- // COMMENTS:
- //
- // This function allows us to resynchronize an asynchronous
- // TAPI line call by waiting for the LINE_REPLY message. It
- // waits until a LINE_REPLY is received or the line is shut down.
- //
- // Note that this could cause re-entrancy problems as
- // well as mess with any message preprocessing that might
- // occur on this thread (such as TranslateAccelerator).
- //
- // This function should to be called from the thread that did
- // lineInitialize, or the PeekMessage is on the wrong thread
- // and the synchronization is not guaranteed to work. Also note
- // that if another PeekMessage loop is entered while waiting,
- // this could also cause synchronization problems.
- //
- // One more note. This function can potentially be re-entered
- // if the call is dropped for any reason while waiting. If this
- // happens, just drop out and assume the wait has been canceled.
- // This is signaled by setting bReentered to FALSE when the function
- // is entered and TRUE when it is left. If bReentered is ever TRUE
- // during the function, then the function was re-entered.
- //
- // This function times out and returns WAITERR_WAITTIMEDOUT
- // after WAITTIMEOUT milliseconds have elapsed.
- //
- //
-
-
- long WaitForReply (long lRequestID)
- {
- static BOOL bReentered;
- bReentered = FALSE;
-
- if (lRequestID > SUCCESS)
- {
- MSG msg;
- DWORD dwTimeStarted;
-
- g_bReplyRecieved = FALSE;
- g_dwRequestedID = (DWORD) lRequestID;
-
- // Initializing this just in case there is a bug
- // that sets g_bReplyRecieved without setting the reply value.
- g_lAsyncReply = LINEERR_OPERATIONFAILED;
-
- dwTimeStarted = GetTickCount();
-
- while(!g_bReplyRecieved)
- {
- if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- // This should only occur if the line is shut down while waiting.
- if (!g_bTapiInUse || bReentered)
- {
- bReentered = TRUE;
- return WAITERR_WAITABORTED;
- }
-
- // Its a really bad idea to timeout a wait for a LINE_REPLY.
- // If we are execting a LINE_REPLY, we should wait till we get
- // it; it might take a long time to dial (for example).
-
- // If 5 seconds go by without a reply, it might be a good idea
- // to display a dialog box to tell the user that a
- // wait is in progress and to give the user the capability to
- // abort the wait.
- }
-
- bReentered = TRUE;
- return g_lAsyncReply;
- }
-
- bReentered = TRUE;
- return lRequestID;
- }
-
-
- //
- // FUNCTION: long WaitForCallState(DWORD)
- //
- // PURPOSE: Wait for the line to reach a specific CallState.
- //
- // PARAMETERS:
- // dwDesiredCallState - specific CallState to wait for.
- //
- // RETURN VALUE:
- // Returns 0 (SUCCESS) when we reach the Desired CallState.
- // Returns WAITERR_WAITTIMEDOUT if timed out.
- // Returns WAITERR_WAITABORTED if call was closed while waiting.
- //
- // COMMENTS:
- //
- // This function allows us to synchronously wait for a line
- // to reach a specific LINESTATE or until the line is shut down.
- //
- // Note that this could cause re-entrancy problems as
- // well as mess with any message preprocessing that might
- // occur on this thread (such as TranslateAccelerator).
- //
- // One more note. This function can potentially be re-entered
- // if the call is dropped for any reason while waiting. If this
- // happens, just drop out and assume the wait has been canceled.
- // This is signaled by setting bReentered to FALSE when the function
- // is entered and TRUE when it is left. If bReentered is ever TRUE
- // during the function, then the function was re-entered.
- //
- // This function should to be called from the thread that did
- // lineInitialize, or the PeekMessage is on the wrong thread
- // and the synchronization is not guaranteed to work. Also note
- // that if another PeekMessage loop is entered while waiting,
- // this could also cause synchronization problems.
- //
- // If the constant value I_LINECALLSTATE_ANY is used for the
- // dwDesiredCallState, then WaitForCallState will return SUCCESS
- // upon receiving any CALLSTATE messages.
- //
- //
- //
-
- long WaitForCallState(DWORD dwDesiredCallState)
- {
- MSG msg;
- DWORD dwTimeStarted;
- static BOOL bReentered;
-
- bReentered = FALSE;
-
- dwTimeStarted = GetTickCount();
-
- g_bCallStateReceived = FALSE;
-
- while ((dwDesiredCallState == I_LINECALLSTATE_ANY) ||
- (g_dwCallState != dwDesiredCallState))
- {
- if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- // If we are waiting for any call state and get one, succeed.
- if ((dwDesiredCallState == I_LINECALLSTATE_ANY) &&
- g_bCallStateReceived)
- {
- break;
- }
-
- // This should only occur if the line is shut down while waiting.
- if (!g_bTapiInUse || bReentered)
- {
- bReentered = TRUE;
- OutputDebugString("WAITABORTED\n");
- return WAITERR_WAITABORTED;
- }
-
- // If we don't get the reply in a reasonable time, we time out.
- if (GetTickCount() - dwTimeStarted > WAITTIMEOUT)
- {
- bReentered = TRUE;
- OutputDebugString("WAITTIMEDOUT\n");
- return WAITERR_WAITTIMEDOUT;
- }
-
- }
-
- bReentered = TRUE;
- return SUCCESS;
- }
-
- //**************************************************
- // lineCallback Function and Handlers.
- //**************************************************
-
-
- //
- // FUNCTION: lineCallbackFunc(..)
- //
- // PURPOSE: Receive asynchronous TAPI events
- //
- // PARAMETERS:
- // dwDevice - Device associated with the event, if any
- // dwMsg - TAPI event that occurred.
- // dwCallbackInstance - User defined data supplied when opening the line.
- // dwParam1 - dwMsg specific information
- // dwParam2 - dwMsg specific information
- // dwParam3 - dwMsg specific information
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- // This is the function where all asynchronous events will come.
- // Almost all events will be specific to an open line, but a few
- // will be general TAPI events (such as LINE_REINIT).
- //
- // Its important to note that this callback will *ALWAYS* be
- // called in the context of the thread that does the lineInitialize.
- // Even if another thread (such as the COMM threads) calls the API
- // that would result in the callback being called, it will be called
- // in the context of the main thread (since in this sample, the main
- // thread does the lineInitialize).
- //
- //
-
-
- void CALLBACK lineCallbackFunc(
- DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
- {
-
- OutputDebugLineCallback(
- dwDevice, dwMsg, dwCallbackInstance,
- dwParam1, dwParam2, dwParam3);
-
- // All we do is dispatch the dwMsg to the correct handler.
- switch(dwMsg)
- {
- case LINE_CALLSTATE:
- DoLineCallState(dwDevice, dwMsg, dwCallbackInstance,
- dwParam1, dwParam2, dwParam3);
- break;
-
- case LINE_CLOSE:
- DoLineClose(dwDevice, dwMsg, dwCallbackInstance,
- dwParam1, dwParam2, dwParam3);
- break;
-
- case LINE_LINEDEVSTATE:
- DoLineDevState(dwDevice, dwMsg, dwCallbackInstance,
- dwParam1, dwParam2, dwParam3);
- break;
-
- case LINE_REPLY:
- DoLineReply(dwDevice, dwMsg, dwCallbackInstance,
- dwParam1, dwParam2, dwParam3);
- break;
-
- case LINE_CREATE:
- DoLineCreate(dwDevice, dwMsg, dwCallbackInstance,
- dwParam1, dwParam2, dwParam3);
- break;
-
- default:
- OutputDebugString("lineCallbackFunc message ignored\n");
- break;
-
- }
-
- return;
-
- }
-
-
- //
- // FUNCTION: DoLineReply(..)
- //
- // PURPOSE: Handle LINE_REPLY asynchronous messages.
- //
- // PARAMETERS:
- // dwDevice - Line Handle associated with this LINE_REPLY.
- // dwMsg - Should always be LINE_REPLY.
- // dwCallbackInstance - Unused by this sample.
- // dwParam1 - Asynchronous request ID.
- // dwParam2 - success or LINEERR error value.
- // dwParam3 - Unused.
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // All line API calls that return an asynchronous request ID
- // will eventually cause a LINE_REPLY message. Handle it.
- //
- // This sample assumes only one call at time, and that we wait
- // for a LINE_REPLY before making any other line API calls.
- //
- // The only exception to the above is that we might shut down
- // the line before receiving a LINE_REPLY.
- //
- //
-
- void DoLineReply(
- DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
- {
- if ((long) dwParam2 != SUCCESS)
- OutputDebugLineError((long) dwParam2, "LINE_REPLY error: ");
- else
- OutputDebugString("LINE_REPLY: successfully replied.\n");
-
- // If we are currently waiting for this async Request ID
- // then set the global variables to acknowledge it.
- if (g_dwRequestedID == dwParam1)
- {
- g_bReplyRecieved = TRUE;
- g_lAsyncReply = (long) dwParam2;
- }
- }
-
-
- //
- // FUNCTION: DoLineClose(..)
- //
- // PURPOSE: Handle LINE_CLOSE asynchronous messages.
- //
- // PARAMETERS:
- // dwDevice - Line Handle that was closed.
- // dwMsg - Should always be LINE_CLOSE.
- // dwCallbackInstance - Unused by this sample.
- // dwParam1 - Unused.
- // dwParam2 - Unused.
- // dwParam3 - Unused.
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // This message is sent when something outside our app shuts
- // down a line in use.
- //
- // The hLine (and any hCall on this line) are no longer valid.
- //
- //
-
- void DoLineClose(
- DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
- {
- // Line has been shut down. Clean up our internal variables.
- g_hLine = NULL;
- g_hCall = NULL;
- UpdateStatusBar("Call was shut down.",1,0);
- MessageBox(g_hDlgParentWindow,
- "Call was shut down.","Warning",MB_OK);
- HangupCall();
- }
-
-
- //
- // FUNCTION: DoLineDevState(..)
- //
- // PURPOSE: Handle LINE_LINEDEVSTATE asynchronous messages.
- //
- // PARAMETERS:
- // dwDevice - Line Handle that was closed.
- // dwMsg - Should always be LINE_LINEDEVSTATE.
- // dwCallbackInstance - Unused by this sample.
- // dwParam1 - LINEDEVSTATE constant.
- // dwParam2 - Depends on dwParam1.
- // dwParam3 - Depends on dwParam1.
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // The LINE_LINEDEVSTATE message is received if the state of the line
- // changes. Examples are RINGING, MAINTENANCE, MSGWAITON. Very few of
- // these are relevant to this sample.
- //
- // Assuming that any LINEDEVSTATE that removes the line from use by TAPI
- // will also send a LINE_CLOSE message.
- //
- //
-
- void DoLineDevState(
- DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
- {
- switch(dwParam1)
- {
- case LINEDEVSTATE_RINGING:
- UpdateStatusBar("Line Ringing",1,0);
- OutputDebugString("Line Ringing.\n");
- break;
-
- case LINEDEVSTATE_REINIT:
- // This is an important case! Usually means that a service provider
- // has changed in such a way that requires TAPI to REINIT.
- // Note that there are both 'soft' REINITs and 'hard' REINITs.
- // Soft REINITs don't actually require a full shutdown but is instead
- // just an informational change that historically required a REINIT
- // to force the application to deal with. TAPI API Version 1.3 apps
- // will still need to do a full REINIT for both hard and soft REINITs.
-
- switch(dwParam2)
- {
- // This is the hard REINIT. No reason given, just REINIT.
- // TAPI is waiting for everyone to shutdown.
- // Our response is to immediately shutdown any calls,
- // shutdown our use of TAPI and notify the user.
- case 0:
- ShutdownTAPI();
- WarningBox("Tapi line configuration has changed.");
- break;
-
- case LINE_CREATE:
- OutputDebugString("Soft REINIT: LINE_CREATE.\n");
- DoLineCreate(dwDevice, dwParam2, dwCallbackInstance,
- dwParam3, 0, 0);
- break;
-
- case LINE_LINEDEVSTATE:
- OutputDebugString("Soft REINIT: LINE_LINEDEVSTATE.\n");
- DoLineDevState(dwDevice, dwParam2, dwCallbackInstance,
- dwParam3, 0, 0);
- break;
-
- // There might be other reasons to send a soft reinit.
- // No need to to shutdown for these.
- default:
- OutputDebugString("Ignoring soft REINIT\n");
- break;
- }
- break;
-
- case LINEDEVSTATE_OUTOFSERVICE:
- WarningBox("Line selected is now Out of Service.");
- HangupCall();
- break;
-
- case LINEDEVSTATE_DISCONNECTED:
- WarningBox("Line selected is now disconnected.");
- HangupCall();
- break;
-
- case LINEDEVSTATE_MAINTENANCE:
- WarningBox("Line selected is now out for maintenance.");
- HangupCall();
- break;
-
- case LINEDEVSTATE_TRANSLATECHANGE:
- if (g_hDialog)
- PostMessage(g_hDialog, WM_COMMAND, IDC_CONFIGURATIONCHANGED, 0);
- break;
-
- case LINEDEVSTATE_REMOVED:
- OutputDebugString("A Line device has been removed;"
- " no action taken.\n");
- break;
-
- default:
- OutputDebugString("Unhandled LINEDEVSTATE message\n");
- }
- }
-
-
- //
- // FUNCTION: DoLineCreate(..)
- //
- // PURPOSE: Handle LINE_LINECREATE asynchronous messages.
- //
- // PARAMETERS:
- // dwDevice - Unused.
- // dwMsg - Should always be LINE_CREATE.
- // dwCallbackInstance - Unused.
- // dwParam1 - dwDeviceID of new Line created.
- // dwParam2 - Unused.
- // dwParam3 - Unused.
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // This message is new for Windows 95. It is sent when a new line is
- // added to the system. This allows us to handle new lines without having
- // to REINIT. This allows for much more graceful Plug and Play.
- //
- // This sample just changes the number of devices available and can use
- // it next time a call is made. It also tells the "Dial" dialog.
- //
- //
-
- void DoLineCreate(
- DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
- {
- // dwParam1 is the Device ID of the new line.
- // Add one to get the number of total devices.
- if (g_dwNumDevs <= dwParam1)
- g_dwNumDevs = dwParam1+1;
- if (g_hDialog)
- PostMessage(g_hDialog, WM_COMMAND, IDC_LINECREATE, 0);
-
- }
-
-
- //
- // FUNCTION: DoLineCallState(..)
- //
- // PURPOSE: Handle LINE_CALLSTATE asynchronous messages.
- //
- // PARAMETERS:
- // dwDevice - Handle to Call who's state is changing.
- // dwMsg - Should always be LINE_CALLSTATE.
- // dwCallbackInstance - Unused by this sample.
- // dwParam1 - LINECALLSTATE constant specifying state change.
- // dwParam2 - Specific to dwParam1.
- // dwParam3 - LINECALLPRIVILEGE change, if any.
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // This message is received whenever a call changes state. Lots of
- // things we do, ranging from notifying the user to closing the line
- // to actually connecting to the target of our phone call.
- //
- // What we do is usually obvious based on the call state change.
- //
-
- void DoLineCallState(
- DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance,
- DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
- {
-
- // Error if this CALLSTATE doesn't apply to our call in progress.
- if ((HCALL) dwDevice != g_hCall)
- {
- OutputDebugPrintf("LINE_CALLSTATE: Unknown device ID '0x%lx'.",
- dwDevice);
- return;
- }
-
- // This sets the global g_dwCallState variable so if we are waiting
- // for a specific call state change, we will know when it happens.
- g_dwCallState = dwParam1;
- g_bCallStateReceived = TRUE;
-
- // dwParam3 contains changes to LINECALLPRIVILEGE, if there are any.
- switch (dwParam3)
- {
- case 0:
- break; // no change to call state
-
- // close line if we are made monitor. Shouldn't happen!
- case LINECALLPRIVILEGE_MONITOR:
- OutputDebugString("line given monitor privilege; closing\n");
- HangupCall();
- return;
-
- // close line if we are made owner. Shouldn't happen!
- case LINECALLPRIVILEGE_OWNER:
- OutputDebugString("line given owner privilege; closing\n");
- HangupCall();
- break;
-
- default: // Shouldn't happen! All cases handled.
- OutputDebugString("Unknown LINECALLPRIVILEGE message: closing\n");
- HangupCall();
- return;
- }
-
- // dwParam1 is the specific CALLSTATE change that is occurring.
- switch (dwParam1)
- {
- case LINECALLSTATE_DIALTONE:
- UpdateStatusBar("Dial Tone",1,0);
- OutputDebugString("Dial Tone\n");
- break;
-
- case LINECALLSTATE_DIALING:
- UpdateStatusBar("Dialing Call",1,0);
- OutputDebugString("Dialing\n");
- break;
-
- case LINECALLSTATE_PROCEEDING:
- UpdateStatusBar("Call is Proceeding",1,0);
- OutputDebugString("Proceeding\n");
- break;
-
- case LINECALLSTATE_RINGBACK:
- UpdateStatusBar("RingBack",1,0);
- OutputDebugString("RingBack\n");
- break;
-
- case LINECALLSTATE_BUSY:
- UpdateStatusBar("Line is busy",1,0);
- OutputDebugString("Line busy, shutting down\n");
- HangupCall();
- break;
-
- case LINECALLSTATE_IDLE:
- UpdateStatusBar("Line is idle",1,0);
- OutputDebugString("Line idle\n");
- HangupCall();
- break;
-
- case LINECALLSTATE_SPECIALINFO:
- UpdateStatusBar(
- "Special Info, probably couldn't dial number",1,0);
- OutputDebugString(
- "Special Info, probably couldn't dial number\n");
- HangupCall();
- break;
-
- case LINECALLSTATE_DISCONNECTED:
- {
- LPSTR pszReasonDisconnected;
-
- switch (dwParam2)
- {
- case LINEDISCONNECTMODE_NORMAL:
- pszReasonDisconnected = "Remote Party Disconnected";
- break;
-
- case LINEDISCONNECTMODE_UNKNOWN:
- pszReasonDisconnected = "Disconnected: Unknown reason";
- break;
-
- case LINEDISCONNECTMODE_REJECT:
- pszReasonDisconnected = "Remote Party rejected call";
- break;
-
- case LINEDISCONNECTMODE_PICKUP:
- pszReasonDisconnected =
- "Disconnected: Local phone picked up";
- break;
-
- case LINEDISCONNECTMODE_FORWARDED:
- pszReasonDisconnected = "Disconnected: Forwarded";
- break;
-
- case LINEDISCONNECTMODE_BUSY:
- pszReasonDisconnected = "Disconnected: Busy";
- break;
-
- case LINEDISCONNECTMODE_NOANSWER:
- pszReasonDisconnected = "Disconnected: No Answer";
- break;
-
- case LINEDISCONNECTMODE_BADADDRESS:
- pszReasonDisconnected = "Disconnected: Bad Address";
- break;
-
- case LINEDISCONNECTMODE_UNREACHABLE:
- pszReasonDisconnected = "Disconnected: Unreachable";
- break;
-
- case LINEDISCONNECTMODE_CONGESTION:
- pszReasonDisconnected = "Disconnected: Congestion";
- break;
-
- case LINEDISCONNECTMODE_INCOMPATIBLE:
- pszReasonDisconnected = "Disconnected: Incompatible";
- break;
-
- case LINEDISCONNECTMODE_UNAVAIL:
- pszReasonDisconnected = "Disconnected: Unavail";
- break;
-
- case LINEDISCONNECTMODE_NODIALTONE:
- pszReasonDisconnected = "Disconnected: No Dial Tone";
- break;
-
- default:
- pszReasonDisconnected =
- "Disconnected: LINECALLSTATE; Bad Reason";
- break;
-
- }
-
- UpdateStatusBar(pszReasonDisconnected,1,0);
- OutputDebugString(pszReasonDisconnected);
- OutputDebugString("\n");
- HangupCall();
- break;
- }
-
-
- case LINECALLSTATE_CONNECTED: // CONNECTED!!!
- {
- LPVARSTRING lpVarString = NULL;
- DWORD dwSizeofVarString = sizeof(VARSTRING) + 1024;
- HANDLE hCommFile = NULL;
- long lReturn;
-
- // Very first, make sure this isn't a duplicated message.
- // A CALLSTATE message can be sent whenever there is a
- // change to the capabilities of a line, meaning that it is
- // possible to receive multiple CONNECTED messages per call.
- // The CONNECTED CALLSTATE message is the only one in TapiComm
- // where it would cause problems if it where sent more
- // than once.
-
- if (g_bConnected)
- break;
-
- g_bConnected = TRUE;
-
- // Get the handle to the comm port from the driver so we can start
- // communicating. This is returned in a LPVARSTRING structure.
- do
- {
- // Allocate the VARSTRING structure
- lpVarString = CheckAndReAllocBuffer((LPVOID) lpVarString,
- dwSizeofVarString,"lineGetID: ");
-
- if (lpVarString == NULL)
- goto ErrorConnecting;
-
- // Fill the VARSTRING structure
- lReturn = lineGetID(0, 0, g_hCall, LINECALLSELECT_CALL,
- lpVarString, "comm/datamodem");
-
- if (HandleLineErr(lReturn))
- ; // Still need to check if structure was big enough.
- else
- {
- OutputDebugLineError(lReturn,
- "lineGetID unhandled error: ");
- goto ErrorConnecting;
- }
-
- // If the VARSTRING wasn't big enough, loop again.
- if ((lpVarString -> dwNeededSize) > (lpVarString -> dwTotalSize))
- {
- dwSizeofVarString = lpVarString -> dwNeededSize;
- lReturn = -1; // Lets loop again.
- }
- }
- while(lReturn != SUCCESS);
-
- OutputDebugString("Connected! Starting communications!\n");
-
- // Again, the handle to the comm port is contained in a
- // LPVARSTRING structure. Thus, the handle is the very first
- // thing after the end of the structure. Note that the name of
- // the comm port is right after the handle, but I don't want it.
- hCommFile =
- *((LPHANDLE)((LPBYTE)lpVarString +
- lpVarString -> dwStringOffset));
-
- // Started communications!
- if (StartComm(hCommFile))
- {
- char szBuff[300];
-
- wsprintf(szBuff,"Connected to '%s'",g_szDisplayableAddress);
- UpdateStatusBar(szBuff, 1, 0);
-
- LocalFree(lpVarString);
- break;
- }
-
- // Couldn't start communications. Clean up instead.
- ErrorConnecting:
-
- // Its very important that we close all Win32 handles.
- // The CommCode module is responsible for closing the hCommFile
- // handle if it succeeds in starting communications.
- if (hCommFile)
- CloseHandle(hCommFile);
-
- HangupCall();
- {
- char szBuff[300];
- wsprintf(szBuff,"Failed to Connect to '%s'",
- g_szDisplayableAddress);
- UpdateStatusBar(szBuff, 1, 0);
- }
-
- if (lpVarString)
- LocalFree(lpVarString);
-
- break;
- }
-
- default:
- OutputDebugString("Unhandled LINECALLSTATE message\n");
- break;
- }
- }
-
- //**************************************************
- // line API Wrapper Functions.
- //**************************************************
-
-
- //
- // FUNCTION: LPVOID CheckAndReAllocBuffer(LPVOID, size_t, LPCSTR)
- //
- // PURPOSE: Checks and ReAllocates a buffer if necessary.
- //
- // PARAMETERS:
- // lpBuffer - Pointer to buffer to be checked. Can be NULL.
- // sizeBufferMinimum - Minimum size that lpBuffer should be.
- // szApiPhrase - Phrase to print if an error occurs.
- //
- // RETURN VALUE:
- // Returns a pointer to a valid buffer that is guarenteed to be
- // at least sizeBufferMinimum size.
- // Returns NULL if an error occured.
- //
- // COMMENTS:
- //
- // This function is a helper function intended to make all of the
- // line API Wrapper Functions much simplier. It allocates (or
- // reallocates) a buffer of the requested size.
- //
- // The returned pointer has been allocated with LocalAlloc,
- // so LocalFree has to be called on it when you're finished with it,
- // or there will be a memory leak.
- //
- // Similarly, if a pointer is passed in, it *must* have been allocated
- // with LocalAlloc and it could potentially be LocalFree()d.
- //
- // If lpBuffer == NULL, then a new buffer is allocated. It is
- // normal to pass in NULL for this parameter the first time and only
- // pass in a pointer if the buffer needs to be reallocated.
- //
- // szApiPhrase is used only for debugging purposes.
- //
- // It is assumed that the buffer returned from this function will be used
- // to contain a variable sized structure. Thus, the dwTotalSize field
- // is always filled in before returning the pointer.
- //
- //
-
- LPVOID CheckAndReAllocBuffer(
- LPVOID lpBuffer, size_t sizeBufferMinimum, LPCSTR szApiPhrase)
- {
- size_t sizeBuffer;
-
- if (lpBuffer == NULL) // Allocate the buffer if necessary.
- {
- sizeBuffer = sizeBufferMinimum;
- lpBuffer = (LPVOID) LocalAlloc(LPTR, sizeBuffer);
-
- if (lpBuffer == NULL)
- {
- OutputDebugString(szApiPhrase);
- OutputDebugLastError(GetLastError(),"LocalAlloc : ");
- HandleNoMem();
- return NULL;
- }
- }
- else // If the structure already exists, make sure its good.
- {
- sizeBuffer = LocalSize((HLOCAL) lpBuffer);
-
- if (sizeBuffer == 0) // Bad pointer?
- {
- OutputDebugString(szApiPhrase);
- OutputDebugLastError(GetLastError(),"LocalSize : ");
- return NULL;
- }
-
- // Was the buffer big enough for the structure?
- if (sizeBuffer < sizeBufferMinimum)
- {
- OutputDebugString(szApiPhrase);
- OutputDebugString("Reallocating structure\n");
- LocalFree(lpBuffer);
- return CheckAndReAllocBuffer(NULL, sizeBufferMinimum, szApiPhrase);
- }
-
- // Lets zero the buffer out.
- memset(lpBuffer, 0, sizeBuffer);
- }
-
- ((LPVARSTRING) lpBuffer ) -> dwTotalSize = (DWORD) sizeBuffer;
- return lpBuffer;
- }
-
-
-
- //
- // FUNCTION: DWORD I_lineNegotiateAPIVersion(DWORD)
- //
- // PURPOSE: Negotiate an API Version to use for a specific device.
- //
- // PARAMETERS:
- // dwDeviceID - device to negotiate an API Version for.
- //
- // RETURN VALUE:
- // Returns the API Version to use for this line if successful.
- // Returns 0 if negotiations fall through.
- //
- // COMMENTS:
- //
- // This wrapper function not only negotiates the API, but handles
- // LINEERR errors that can occur while negotiating.
- //
- //
-
- DWORD I_lineNegotiateAPIVersion(DWORD dwDeviceID)
- {
- LINEEXTENSIONID LineExtensionID;
- long lReturn;
- DWORD dwLocalAPIVersion;
-
- do
- {
- lReturn = lineNegotiateAPIVersion(g_hLineApp, dwDeviceID,
- SAMPLE_TAPI_VERSION, SAMPLE_TAPI_VERSION,
- &dwLocalAPIVersion, &LineExtensionID);
-
- if (lReturn == LINEERR_INCOMPATIBLEAPIVERSION)
- {
- OutputDebugString(
- "lineNegotiateAPIVersion, INCOMPATIBLEAPIVERSION.\n");
- return 0;
- }
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineNegotiateAPIVersion unhandled error: ");
- return 0;
- }
- }
- while(lReturn != SUCCESS);
-
- return dwLocalAPIVersion;
- }
-
-
- //
- // FUNCTION: I_lineGetDevCaps(LPLINEDEVCAPS, DWORD , DWORD)
- //
- // PURPOSE: Retrieve a LINEDEVCAPS structure for the specified line.
- //
- // PARAMETERS:
- // lpLineDevCaps - Pointer to a LINEDEVCAPS structure to use.
- // dwDeviceID - device to get the DevCaps for.
- // dwAPIVersion - API Version to use while getting DevCaps.
- //
- // RETURN VALUE:
- // Returns a pointer to a LINEDEVCAPS structure if successful.
- // Returns NULL if unsuccessful.
- //
- // COMMENTS:
- //
- // This function is a wrapper around lineGetDevCaps to make it easy
- // to handle the variable sized structure and any errors received.
- //
- // The returned structure has been allocated with LocalAlloc,
- // so LocalFree has to be called on it when you're finished with it,
- // or there will be a memory leak.
- //
- // Similarly, if a lpLineDevCaps structure is passed in, it *must*
- // have been allocated with LocalAlloc and it could potentially be
- // LocalFree()d.
- //
- // If lpLineDevCaps == NULL, then a new structure is allocated. It is
- // normal to pass in NULL for this parameter unless you want to use a
- // lpLineDevCaps that has been returned by a previous I_lineGetDevCaps
- // call.
- //
- //
-
- LPLINEDEVCAPS I_lineGetDevCaps(
- LPLINEDEVCAPS lpLineDevCaps,
- DWORD dwDeviceID, DWORD dwAPIVersion)
- {
- size_t sizeofLineDevCaps = sizeof(LINEDEVCAPS) + 1024;
- long lReturn;
-
- // Continue this loop until the structure is big enough.
- while(TRUE)
- {
- // Make sure the buffer exists, is valid and big enough.
- lpLineDevCaps =
- (LPLINEDEVCAPS) CheckAndReAllocBuffer(
- (LPVOID) lpLineDevCaps, // Pointer to existing buffer, if any
- sizeofLineDevCaps, // Minimum size the buffer should be
- "lineGetDevCaps"); // Phrase to tag errors, if any.
-
- if (lpLineDevCaps == NULL)
- return NULL;
-
- // Make the call to fill the structure.
- do
- {
- lReturn =
- lineGetDevCaps(g_hLineApp,
- dwDeviceID, dwAPIVersion, 0, lpLineDevCaps);
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineGetDevCaps unhandled error: ");
- LocalFree(lpLineDevCaps);
- return NULL;
- }
- }
- while (lReturn != SUCCESS);
-
- // If the buffer was big enough, then succeed.
- if ((lpLineDevCaps -> dwNeededSize) <= (lpLineDevCaps -> dwTotalSize))
- return lpLineDevCaps;
-
- // Buffer wasn't big enough. Make it bigger and try again.
- sizeofLineDevCaps = lpLineDevCaps -> dwNeededSize;
- }
- }
-
-
- //
- // FUNCTION: I_lineGetAddressStatus(LPLINEADDRESSSTATUS, HLINE, DWORD)
- //
- // PURPOSE: Retrieve a LINEADDRESSSTATUS structure for the specified line.
-
-
- //
- // PARAMETERS:
- // lpLineAddressStatus - Pointer to a LINEADDRESSSTATUS structure to use.
- // hLine - Handle of line to get the AddressStatus of.
- // dwAddressID - Address ID on the hLine to be used.
- //
- // RETURN VALUE:
- // Returns a pointer to a LINEADDRESSSTATUS structure if successful.
- // Returns NULL if unsuccessful.
- //
- // COMMENTS:
- //
- // This function is a wrapper around lineGetAddressStatus to make it easy
- // to handle the variable sized structure and any errors received.
- //
- // The returned structure has been allocated with LocalAlloc,
- // so LocalFree has to be called on it when you're finished with it,
- // or there will be a memory leak.
- //
- // Similarly, if a lpLineAddressStatus structure is passed in, it *must*
- // have been allocated with LocalAlloc and it could potentially be
- // LocalFree()d.
- //
- // If lpLineAddressStatus == NULL, then a new structure is allocated. It
- // is normal to pass in NULL for this parameter unless you want to use a
- // lpLineAddressStatus that has been returned by previous
- // I_lineGetAddressStatus call.
- //
- //
-
- LPLINEADDRESSSTATUS I_lineGetAddressStatus(
- LPLINEADDRESSSTATUS lpLineAddressStatus,
- HLINE hLine, DWORD dwAddressID)
- {
- size_t sizeofLineAddressStatus = sizeof(LINEADDRESSSTATUS) + 1024;
- long lReturn;
-
- // Continue this loop until the structure is big enough.
- while(TRUE)
- {
- // Make sure the buffer exists, is valid and big enough.
- lpLineAddressStatus =
- (LPLINEADDRESSSTATUS) CheckAndReAllocBuffer(
- (LPVOID) lpLineAddressStatus,
- sizeofLineAddressStatus,
- "lineGetAddressStatus");
-
- if (lpLineAddressStatus == NULL)
- return NULL;
-
- // Make the call to fill the structure.
- do
- {
- lReturn =
- lineGetAddressStatus(hLine, dwAddressID, lpLineAddressStatus);
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineGetAddressStatus unhandled error: ");
- LocalFree(lpLineAddressStatus);
- return NULL;
- }
- }
- while (lReturn != SUCCESS);
-
- // If the buffer was big enough, then succeed.
- if ((lpLineAddressStatus -> dwNeededSize) <=
- (lpLineAddressStatus -> dwTotalSize))
- {
- return lpLineAddressStatus;
- }
-
- // Buffer wasn't big enough. Make it bigger and try again.
- sizeofLineAddressStatus = lpLineAddressStatus -> dwNeededSize;
- }
- }
-
-
- //
- // FUNCTION: I_lineGetCallStatus(LPLINECALLSTATUS, HCALL)
- //
- // PURPOSE: Retrieve a LINECALLSTATUS structure for the specified line.
- //
- // PARAMETERS:
- // lpLineCallStatus - Pointer to a LINECALLSTATUS structure to use.
- // hCall - Handle of call to get the CallStatus of.
- //
- // RETURN VALUE:
- // Returns a pointer to a LINECALLSTATUS structure if successful.
- // Returns NULL if unsuccessful.
- //
- // COMMENTS:
- //
- // This function is a wrapper around lineGetCallStatus to make it easy
- // to handle the variable sized structure and any errors received.
- //
- // The returned structure has been allocated with LocalAlloc,
- // so LocalFree has to be called on it when you're finished with it,
- // or there will be a memory leak.
- //
- // Similarly, if a lpLineCallStatus structure is passed in, it *must*
- // have been allocated with LocalAlloc and it could potentially be
- // LocalFree()d.
- //
- // If lpLineCallStatus == NULL, then a new structure is allocated. It
- // is normal to pass in NULL for this parameter unless you want to use a
- // lpLineCallStatus that has been returned by previous I_lineGetCallStatus
- // call.
- //
- //
-
- LPLINECALLSTATUS I_lineGetCallStatus(
- LPLINECALLSTATUS lpLineCallStatus,
- HCALL hCall)
- {
- size_t sizeofLineCallStatus = sizeof(LINECALLSTATUS) + 1024;
- long lReturn;
-
- // Continue this loop until the structure is big enough.
- while(TRUE)
- {
- // Make sure the buffer exists, is valid and big enough.
- lpLineCallStatus =
- (LPLINECALLSTATUS) CheckAndReAllocBuffer(
- (LPVOID) lpLineCallStatus,
- sizeofLineCallStatus,
- "lineGetCallStatus");
-
- if (lpLineCallStatus == NULL)
- return NULL;
-
- // Make the call to fill the structure.
- do
- {
- lReturn =
- lineGetCallStatus(hCall, lpLineCallStatus);
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineGetCallStatus unhandled error: ");
- LocalFree(lpLineCallStatus);
- return NULL;
- }
- }
- while (lReturn != SUCCESS);
-
- // If the buffer was big enough, then succeed.
- if ((lpLineCallStatus -> dwNeededSize) <=
- (lpLineCallStatus -> dwTotalSize))
- {
- return lpLineCallStatus;
- }
-
- // Buffer wasn't big enough. Make it bigger and try again.
- sizeofLineCallStatus = lpLineCallStatus -> dwNeededSize;
- }
- }
-
-
- //
- // FUNCTION: I_lineTranslateAddress
- // (LPLINETRANSLATEOUTPUT, DWORD, DWORD, LPCSTR)
- //
- // PURPOSE: Retrieve a LINECALLSTATUS structure for the specified line.
- //
- // PARAMETERS:
- // lpLineTranslateOutput - Pointer to a LINETRANSLATEOUTPUT structure.
- // dwDeviceID - Device that we're translating for.
- // dwAPIVersion - API Version to use.
- // lpszDialAddress - pointer to the DialAddress string to translate.
- //
- // RETURN VALUE:
- // Returns a pointer to a LINETRANSLATEOUTPUT structure if successful.
- // Returns NULL if unsuccessful.
- //
- // COMMENTS:
- //
- // This function is a wrapper around lineGetTranslateOutput to make it
- // easy to handle the variable sized structure and any errors received.
- //
- // The returned structure has been allocated with LocalAlloc,
- // so LocalFree has to be called on it when you're finished with it,
- // or there will be a memory leak.
- //
- // Similarly, if a lpLineTranslateOutput structure is passed in, it
- // *must* have been allocated with LocalAlloc and it could potentially be
- // LocalFree()d.
- //
- // If lpLineTranslateOutput == NULL, then a new structure is allocated.
- // It is normal to pass in NULL for this parameter unless you want to use
- // a lpLineTranslateOutput that has been returned by previous
- // I_lineTranslateOutput call.
- //
- //
-
- LPLINETRANSLATEOUTPUT I_lineTranslateAddress(
- LPLINETRANSLATEOUTPUT lpLineTranslateOutput,
- DWORD dwDeviceID, DWORD dwAPIVersion,
- LPCSTR lpszDialAddress)
- {
- size_t sizeofLineTranslateOutput = sizeof(LINETRANSLATEOUTPUT) + 1024;
- long lReturn;
-
- // Continue this loop until the structure is big enough.
- while(TRUE)
- {
- // Make sure the buffer exists, is valid and big enough.
- lpLineTranslateOutput =
- (LPLINETRANSLATEOUTPUT) CheckAndReAllocBuffer(
- (LPVOID) lpLineTranslateOutput,
- sizeofLineTranslateOutput,
- "lineTranslateOutput");
-
- if (lpLineTranslateOutput == NULL)
- return NULL;
-
- // Make the call to fill the structure.
- do
- {
- // Note that CALLWAITING is disabled
- // (assuming the service provider can disable it)
- lReturn =
- lineTranslateAddress(g_hLineApp, dwDeviceID, dwAPIVersion,
- lpszDialAddress, 0,
- LINETRANSLATEOPTION_CANCELCALLWAITING,
- lpLineTranslateOutput);
-
- // If the address isn't translatable, notify the user.
- if (lReturn == LINEERR_INVALADDRESS)
- MessageBox(g_hDlgParentWindow,
- "Unable to translate phone number","Warning",MB_OK);
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineTranslateOutput unhandled error: ");
- LocalFree(lpLineTranslateOutput);
- return NULL;
- }
- }
- while (lReturn != SUCCESS);
-
- // If the buffer was big enough, then succeed.
- if ((lpLineTranslateOutput -> dwNeededSize) <=
- (lpLineTranslateOutput -> dwTotalSize))
- {
- return lpLineTranslateOutput;
- }
-
- // Buffer wasn't big enough. Make it bigger and try again.
- sizeofLineTranslateOutput = lpLineTranslateOutput -> dwNeededSize;
- }
- }
-
-
- //
- // FUNCTION: I_lineGetAddressCaps(LPLINEADDRESSCAPS, ..)
- //
- // PURPOSE: Retrieve a LINEADDRESSCAPS structure for the specified line.
- //
- // PARAMETERS:
- // lpLineAddressCaps - Pointer to a LINEADDRESSCAPS, or NULL.
- // dwDeviceID - Device to get the address caps for.
- // dwAddressID - This sample always assumes the first address.
- // dwAPIVersion - API version negotiated for the device.
- // dwExtVersion - Always 0 for this sample.
- //
- // RETURN VALUE:
- // Returns a pointer to a LINEADDRESSCAPS structure if successful.
- // Returns NULL if unsuccessful.
- //
- // COMMENTS:
- //
- // This function is a wrapper around lineGetAddressCaps to make it easy
- // to handle the variable sized structure and any errors received.
- //
- // The returned structure has been allocated with LocalAlloc,
- // so LocalFree has to be called on it when you're finished with it,
- // or there will be a memory leak.
- //
- // Similarly, if a lpLineAddressCaps structure is passed in, it *must*
- // have been allocated with LocalAlloc and it could potentially be
- // LocalFree()d. It also *must* have the dwTotalSize field set.
- //
- // If lpLineAddressCaps == NULL, then a new structure is allocated. It
- // is normal to pass in NULL for this parameter unless you want to use a
- // lpLineCallStatus that has been returned by previous I_lineGetAddressCaps
- // call.
- //
- //
-
- LPLINEADDRESSCAPS I_lineGetAddressCaps (
- LPLINEADDRESSCAPS lpLineAddressCaps,
- DWORD dwDeviceID, DWORD dwAddressID,
- DWORD dwAPIVersion, DWORD dwExtVersion)
- {
- size_t sizeofLineAddressCaps = sizeof(LINEADDRESSCAPS) + 1024;
- long lReturn;
-
- // Continue this loop until the structure is big enough.
- while(TRUE)
- {
- // Make sure the buffer exists, is valid and big enough.
- lpLineAddressCaps =
- (LPLINEADDRESSCAPS) CheckAndReAllocBuffer(
- (LPVOID) lpLineAddressCaps,
- sizeofLineAddressCaps,
- "lineGetAddressCaps");
-
- if (lpLineAddressCaps == NULL)
- return NULL;
-
- // Make the call to fill the structure.
- do
- {
- lReturn =
- lineGetAddressCaps(g_hLineApp,
- dwDeviceID, dwAddressID, dwAPIVersion, dwExtVersion,
- lpLineAddressCaps);
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineGetAddressCaps unhandled error: ");
- LocalFree(lpLineAddressCaps);
- return NULL;
- }
- }
- while (lReturn != SUCCESS);
-
- // If the buffer was big enough, then succeed.
- if ((lpLineAddressCaps -> dwNeededSize) <=
- (lpLineAddressCaps -> dwTotalSize))
- {
- return lpLineAddressCaps;
- }
-
- // Buffer wasn't big enough. Make it bigger and try again.
- sizeofLineAddressCaps = lpLineAddressCaps -> dwNeededSize;
- }
- }
-
-
-
- //**************************************************
- // LINEERR Error Handlers
- //**************************************************
-
-
- //
- // FUNCTION: HandleLineErr(long)
- //
- // PURPOSE: Handle several standard LINEERR errors
- //
- // PARAMETERS:
- // lLineErr - Error code to be handled.
- //
- // RETURN VALUE:
- // Return TRUE if lLineErr wasn't an error, or if the
- // error was successfully handled and cleared up.
- // Return FALSE if lLineErr was an unhandled error.
- //
- // COMMENTS:
- //
- // This is the main error handler for all TAPI line APIs.
- // It handles (by correcting or just notifying the user)
- // most of the errors that can occur while using TAPI line APIs.
- //
- // Note that many errors still return FALSE (unhandled) even
- // if a dialog is displayed. Often, the dialog is just notifying
- // the user why the action was canceled.
- //
- //
- //
-
- BOOL HandleLineErr(long lLineErr)
- {
- // lLineErr is really an async request ID, not an error.
- if (lLineErr > SUCCESS)
- return FALSE;
-
- // All we do is dispatch the correct error handler.
- switch(lLineErr)
- {
- case SUCCESS:
- return TRUE;
-
- case LINEERR_INVALCARD:
- case LINEERR_INVALLOCATION:
- case LINEERR_INIFILECORRUPT:
- return HandleIniFileCorrupt();
-
- case LINEERR_NODRIVER:
- return HandleNoDriver();
-
- case LINEERR_REINIT:
- return HandleReInit();
-
- case LINEERR_NOMULTIPLEINSTANCE:
- return HandleNoMultipleInstance();
-
- case LINEERR_NOMEM:
- return HandleNoMem();
-
- case LINEERR_OPERATIONFAILED:
- return HandleOperationFailed();
-
- case LINEERR_RESOURCEUNAVAIL:
- return HandleResourceUnavail();
-
- // Unhandled errors fail.
- default:
- return FALSE;
- }
- }
-
-
-
- //
- // FUNCTION: HandleIniFileCorrupt
- //
- // PURPOSE: Handle INIFILECORRUPT error.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE - error was corrected.
- // FALSE - error was not corrected.
- //
- // COMMENTS:
- //
- // This error shouldn't happen under Windows 95 anymore. The TAPI.DLL
- // takes care of correcting this problem. If it does happen, just
- // notify the user.
- //
-
- BOOL HandleIniFileCorrupt()
- {
- if (IDCANCEL == MessageBox(g_hDlgParentWindow,
- "Configuration information relating to Telephony "
- "services appears to be corrupt.\n"
- "This could be the first time you have used the Telephony services.\n"
- "Would you like to configure the Telephony services?",
- "Warning",MB_OKCANCEL))
- {
- return FALSE;
- }
-
- lineTranslateDialog(g_hLineApp, 0, SAMPLE_TAPI_VERSION,
- g_hDlgParentWindow, NULL);
-
- return TRUE;
- }
-
-
- //
- // FUNCTION: HandleNoDriver
- //
- // PURPOSE: Handle NODRIVER error.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE - error was corrected.
- // FALSE - error was not corrected.
- //
- // COMMENTS:
- //
- //
-
- BOOL HandleNoDriver()
- {
- int mbRet;
- mbRet = MessageBox(g_hDlgParentWindow,
- "One of the components of the Telephony device driver is missing.\n"
- "Use the Control Panel to set up the driver properly.",
- "Warning",MB_OK);
-
- return FALSE;
- }
-
-
- //
- // FUNCTION: HandleNoMultipleInstance
- //
- // PURPOSE: Handle NOMULTIPLEINSTANCE error.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE - error was corrected.
- // FALSE - error was not corrected.
- //
- // COMMENTS:
- //
- //
-
- BOOL HandleNoMultipleInstance()
- {
- MessageBox(g_hDlgParentWindow,
- "You have two copies of the same Telephony driver installed.\n"
- "Use the Control Panel to remove one of the copies.",
- "Warning",MB_OK);
-
- return FALSE;
- }
-
-
- //
- // FUNCTION: HandleReInit
- //
- // PURPOSE: Handle REINIT error.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE - error was corrected.
- // FALSE - error was not corrected.
- //
- // COMMENTS:
- //
- //
-
- BOOL HandleReInit()
- {
- ShutdownTAPI();
- return FALSE;
- }
-
-
- //
- // FUNCTION: HandleNoMem
- //
- // PURPOSE: Handle NOMEM error.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE - error was corrected.
- // FALSE - error was not corrected.
- //
- // COMMENTS:
- // This is also called if I run out of memory for LocalAlloc()s
- //
- //
-
- BOOL HandleNoMem()
- {
- MessageBox(g_hDlgParentWindow,
- "Out of Memory error, canceling action.","Error", MB_OK);
- return FALSE;
- }
-
-
- //
- // FUNCTION: HandleOperationFailed
- //
- // PURPOSE: Handle OPERATIONFAILED error.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE - error was corrected.
- // FALSE - error was not corrected.
- //
- // COMMENTS:
- //
- //
-
- BOOL HandleOperationFailed()
- {
- MessageBox(g_hDlgParentWindow,
- "TAPI Operation Failed for unknown reasons.",
- "Error", MB_OK);
- return FALSE;
- }
-
-
- //
- // FUNCTION: HandleResourceUnavail
- //
- // PURPOSE: Handle RESOURCEUNAVAIL error.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE - error was corrected.
- // FALSE - error was not corrected.
- //
- // COMMENTS:
- //
- //
-
- BOOL HandleResourceUnavail()
- {
- int mbRet;
-
- mbRet = MessageBox(g_hDlgParentWindow,
- "A Telephony resource is temporarily unavaiable. "
- "This could mean a short wait is necessary or "
- "that a non-TAPI application is using the line.",
- "Warning",MB_RETRYCANCEL);
-
- if (mbRet == IDRETRY)
- return TRUE;
-
- return FALSE;
- }
-
-
- //
- // FUNCTION: HandleNoDevicesInstalled
- //
- // PURPOSE: Handle cases when we know NODEVICE error
- // is returned because there are no devices installed.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE - error was corrected.
- // FALSE - error was not corrected.
- //
- // COMMENTS:
- //
- // This function is not part of standard error handling
- // but is only used when we know that the NODEVICE error
- // means that no devices are installed.
- //
- //
-
- BOOL HandleNoDevicesInstalled()
- {
- int mbRet;
- mbRet = MessageBox(g_hDlgParentWindow,
- "There are no devices configured for Telephony use.\n"
- "Would you like to run the Modem Control Panel to add a modem driver?",
- "Warning",MB_YESNO);
-
- if (mbRet == IDYES)
- {
- if (LaunchModemControlPanelAdd())
- return TRUE;
- }
-
- return FALSE;
- }
-
-
- //
- // FUNCTION: LaunchModemControlPanelAdd
- //
- // PURPOSE: Launch Add Modem Control Panel applet.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE - Control Panel launched successfully.
- // FALSE - It didn't.
- //
- // COMMENTS:
- //
- //
-
- BOOL LaunchModemControlPanelAdd()
- {
- PROCESS_INFORMATION piProcInfo;
- STARTUPINFO siStartupInfo;
-
- siStartupInfo.cb = sizeof(STARTUPINFO);
- siStartupInfo.lpReserved = NULL;
- siStartupInfo.lpDesktop = NULL;
- siStartupInfo.lpTitle = NULL;
- siStartupInfo.dwFlags = STARTF_USESHOWWINDOW;
- siStartupInfo.wShowWindow = SW_SHOWNORMAL;
- siStartupInfo.cbReserved2 = 0;
- siStartupInfo.lpReserved2 = NULL;
-
- // The string to launch the modem control panel is *VERY* likely
- // to change on NT. If nothing else, this is 'contrl32' on NT
- // instead of 'control'.
- if (CreateProcess(
- NULL,
- "CONTROL.EXE MODEM.CPL,,ADD",
- NULL, NULL, FALSE,
- NORMAL_PRIORITY_CLASS,
- NULL, NULL,
- &siStartupInfo,
- &piProcInfo))
- {
- CloseHandle(piProcInfo.hThread);
-
-
- // Control panel 'Add New Modem' has been launched. Now we should
- // wait for it to go away before continueing.
-
- // If we WaitForSingleObject for the control panel to exit, then we
- // get into a deadlock situation if we need to respond to any messages
- // from the control panel.
-
- // If we use a PeekMessage loop to wait, we run into
- // message re-entrancy problems. (The user can get back to our UI
- // and click 'dial' again).
-
- // Instead, we take the easy way out and return FALSE to abort
- // the current operation.
-
- CloseHandle(piProcInfo.hProcess);
- }
- else
- {
- OutputDebugLastError(GetLastError(),
- "Unable to LaunchModemControlPanelAdd: ");
- MessageBox(g_hDlgParentWindow,
- "Unable to launch the Modem Control Panel",
- "Warning", MB_OK);
- }
-
- return FALSE;
- }
-
-
- //
- // FUNCTION: WarningBox(LPCSTR)
- //
- // PURPOSE: Prints a warning box when conditions remove a line in use.
- //
- // PARAMETERS:
- // lpszMessage - String that specifies why the line was removed form use.
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // If there is a call in progress on the line removed, then display a message
- // specifying why the line was removed and that the call is being canceled.
- //
- //
-
- void WarningBox(LPCSTR lpszMessage)
- {
- char szBuff[1024];
-
- strcpy(szBuff, lpszMessage);
-
- // If there is a call open, tell user we're going to close it.
- if (g_hCall)
- strcat(szBuff, "\nClosing existing call.");
-
- MessageBox(g_hDlgParentWindow, szBuff, "Warning", MB_OK);
-
- strcat(szBuff, "\r\n");
- OutputDebugString(szBuff);
- }
-
-
- //**************************************************
- //
- // All the functions from this point on are used solely by the "Dial" dialog.
- // This dialog is used to get both the 'phone number' address,
- // the line device to be used as well as allow the user to configure
- // dialing properties and the line device.
- //
- //**************************************************
-
- //
- // FUNCTION: DWORD I_lineNegotiateLegacyAPIVersion(DWORD)
- //
- // PURPOSE: Negotiate an API Version to use for a specific device.
- //
- // PARAMETERS:
- // dwDeviceID - device to negotiate an API Version for.
- //
- // RETURN VALUE:
- // Returns the API Version to use for this line if successful.
- // Returns 0 if negotiations fall through.
- //
- // COMMENTS:
- //
- // This wrapper is slightly different from the I_lineNegotiateAPIVersion.
- // This wrapper allows TapiComm to negotiate an API version between
- // 1.3 and SAMPLE_TAPI_VERSION. Normally, this sample is specific to
- // API Version SAMPLE_TAPI_VERSION. However, there are a few times when
- // TapiComm needs to get information from a service provider, but also knows
- // that a lower API Version would be ok. This allows TapiComm to recognize
- // legacy service providers even though it can't use them. 1.3 is the
- // lowest API Version a legacy service provider should support.
- //
- //
-
- DWORD I_lineNegotiateLegacyAPIVersion(DWORD dwDeviceID)
- {
- LINEEXTENSIONID LineExtensionID;
- long lReturn;
- DWORD dwLocalAPIVersion;
-
- do
- {
- lReturn = lineNegotiateAPIVersion(g_hLineApp, dwDeviceID,
- 0x00010003, SAMPLE_TAPI_VERSION,
- &dwLocalAPIVersion, &LineExtensionID);
-
- if (lReturn == LINEERR_INCOMPATIBLEAPIVERSION)
- {
- OutputDebugString("INCOMPATIBLEAPIVERSION in Dial Dialog.\n");
- return 0;
- }
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineNegotiateAPIVersion in Dial Dialog unhandled error: ");
- return 0;
- }
- }
- while(lReturn != SUCCESS);
-
- return dwLocalAPIVersion;
- }
-
-
- //
- // FUNCTION: long VerifyUsableLine(DWORD)
- //
- // PURPOSE: Verifies that a specific line device is useable by TapiComm.
- //
- // PARAMETERS:
- // dwDeviceID - The ID of the line device to be verified
- //
- // RETURN VALUE:
- // Returns SUCCESS if dwDeviceID is a usable line device.
- // Returns a LINENOTUSEABLE_ constant otherwise.
- //
- // COMMENTS:
- //
- // VerifyUsableLine takes the give device ID and verifies step by step
- // that the device supports all the features that TapiComm requires.
- //
- //
-
- long VerifyUsableLine(DWORD dwDeviceID)
- {
- LPLINEDEVCAPS lpLineDevCaps = NULL;
- LPLINEADDRESSSTATUS lpLineAddressStatus = NULL;
- LPVARSTRING lpVarString = NULL;
- DWORD dwAPIVersion;
- long lReturn;
- long lUsableLine = SUCCESS;
- HLINE hLine = 0;
-
- OutputDebugPrintf("Testing Line ID '0x%lx'",dwDeviceID);
-
- // The line device must support an API Version that TapiComm does.
- dwAPIVersion = I_lineNegotiateAPIVersion(dwDeviceID);
- if (dwAPIVersion == 0)
- return LINENOTUSEABLE_ERROR;
-
- lpLineDevCaps = I_lineGetDevCaps(lpLineDevCaps,
- dwDeviceID, dwAPIVersion);
-
- if (lpLineDevCaps == NULL)
- return LINENOTUSEABLE_ERROR;
-
- // Must support LINEBEARERMODE_VOICE
- if (!(lpLineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE ))
- {
- lUsableLine = LINENOTUSEABLE_NOVOICE;
- OutputDebugString("LINEBEARERMODE_VOICE not supported\n");
- goto DeleteBuffers;
- }
-
- // Must support LINEMEDIAMODE_DATAMODEM
- if (!(lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM))
- {
- lUsableLine = LINENOTUSEABLE_NODATAMODEM;
- OutputDebugString("LINEMEDIAMODE_DATAMODEM not supported\n");
- goto DeleteBuffers;
- }
-
- // Must be able to make calls
- if (!(lpLineDevCaps->dwLineFeatures & LINEFEATURE_MAKECALL))
- {
- lUsableLine = LINENOTUSEABLE_NOMAKECALL;
- OutputDebugString("LINEFEATURE_MAKECALL not supported\n");
- goto DeleteBuffers;
- }
-
- // It is necessary to open the line so we can check if
- // there are any call appearances available. Other TAPI
- // applications could be using all call appearances.
- // Opening the line also checks for other possible problems.
- do
- {
- lReturn = lineOpen(g_hLineApp, dwDeviceID, &hLine,
- dwAPIVersion, 0, 0,
- LINECALLPRIVILEGE_NONE, LINEMEDIAMODE_DATAMODEM,
- 0);
-
- if(lReturn == LINEERR_ALLOCATED)
- {
- OutputDebugString(
- "Line is already in use by a non-TAPI app or"
- " another Service Provider.\n");
- lUsableLine = LINENOTUSEABLE_ALLOCATED;
- goto DeleteBuffers;
- }
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn, "lineOpen unhandled error: ");
- lUsableLine = LINENOTUSEABLE_ERROR;
- goto DeleteBuffers;
- }
- }
- while(lReturn != SUCCESS);
-
- // Get LineAddressStatus to make sure the line isn't already in use.
- lpLineAddressStatus =
- I_lineGetAddressStatus(lpLineAddressStatus, hLine, 0);
-
- if (lpLineAddressStatus == NULL)
- {
- lUsableLine = LINENOTUSEABLE_ERROR;
- goto DeleteBuffers;
- }
-
- // Are there any available call appearances (ie: is it in use)?
- if ( !((lpLineAddressStatus -> dwAddressFeatures) &
- LINEADDRFEATURE_MAKECALL) )
- {
- OutputDebugString("LINEADDRFEATURE_MAKECALL not available\n");
- lUsableLine = LINENOTUSEABLE_INUSE;
- goto DeleteBuffers;
- }
-
- // Make sure the "comm/datamodem" device class is supported
- // Note that we don't want any of the 'extra' information
- // normally returned in the VARSTRING structure. All we care
- // about is if lineGetID succeeds.
- do
- {
- lpVarString = CheckAndReAllocBuffer((LPVOID) lpVarString,
- sizeof(VARSTRING),"VerifyUsableLine:lineGetID: ");
-
- if (lpVarString == NULL)
- {
- lUsableLine = LINENOTUSEABLE_ERROR;
- goto DeleteBuffers;
- }
-
- lReturn = lineGetID(hLine, 0, 0, LINECALLSELECT_LINE,
- lpVarString, "comm/datamodem");
-
- if (HandleLineErr(lReturn))
- continue;
- else
- {
- OutputDebugLineError(lReturn,
- "lineGetID unhandled error: ");
- lUsableLine = LINENOTUSEABLE_NOCOMMDATAMODEM;
- goto DeleteBuffers;
- }
- }
- while(lReturn != SUCCESS);
-
- OutputDebugString("Line is suitable and available for use.\n");
-
- DeleteBuffers:
-
- if (hLine)
- lineClose(hLine);
- if (lpLineAddressStatus)
- LocalFree(lpLineAddressStatus);
- if (lpLineDevCaps)
- LocalFree(lpLineDevCaps);
- if (lpVarString)
- LocalFree(lpVarString);
-
- return lUsableLine;
- }
-
-
- //
- // FUNCTION: void FillTAPILine(HWND)
- //
- // PURPOSE: Fills the 'TAPI Line' control with the available line devices.
- //
- // PARAMETERS:
- // hwndDlg - handle to the current "Dial" dialog
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // This function enumerates through all the TAPI line devices and
- // queries each for the device name. The device name is then put into
- // the 'TAPI Line' control. These device names are kept in order rather
- // than sorted. This allows "Dial" to know which device ID the user
- // selected just by the knowing the index of the selected string.
- //
- // There are default values if there isn't a device name, if there is
- // an error on the device, or if the device name is an empty string.
- // The device name is also checked to make sure it is null terminated.
- //
- // Note that a Legacy API Version is negotiated. Since the fields in
- // the LINEDEVCAPS structure that we are interested in haven't moved, we
- // can negotiate a lower API Version than this sample is designed for
- // and still be able to access the necessary structure members.
- //
- // The first line that is usable by TapiComm is selected as the 'default'
- // line. Also note that if there was a previously selected line, this
- // remains the default line. This would likely only occur if this
- // function is called after the dialog has initialized once; for example,
- // if a new line is added.
- //
- //
-
- void FillTAPILine(HWND hwndDlg)
- {
- DWORD dwDeviceID;
- DWORD dwAPIVersion;
- LPLINEDEVCAPS lpLineDevCaps = NULL;
- char szLineUnavail[] = "Line Unavailable";
- char szLineUnnamed[] = "Line Unnamed";
- char szLineNameEmpty[] = "Line Name is Empty";
- LPSTR lpszLineName;
- long lReturn;
- DWORD dwDefaultDevice = MAXDWORD;
-
- // Make sure the control is empty. If it isn't,
- // hold onto the currently selected ID and then reset it.
- if (SendDlgItemMessage(hwndDlg, IDC_TAPILINE, CB_GETCOUNT, 0, 0))
- {
- dwDefaultDevice = SendDlgItemMessage(hwndDlg, IDC_TAPILINE,
- CB_GETCURSEL, 0, 0);
- SendDlgItemMessage(hwndDlg, IDC_TAPILINE, CB_RESETCONTENT, 0, 0);
- }
-
- for (dwDeviceID = 0; dwDeviceID < g_dwNumDevs; dwDeviceID ++)
- {
- dwAPIVersion = I_lineNegotiateLegacyAPIVersion(dwDeviceID);
- if (dwAPIVersion)
- {
- lpLineDevCaps = I_lineGetDevCaps(lpLineDevCaps,
- dwDeviceID, dwAPIVersion);
- if (lpLineDevCaps)
- {
- if ((lpLineDevCaps -> dwLineNameSize) &&
- (lpLineDevCaps -> dwLineNameOffset) &&
- (lpLineDevCaps -> dwStringFormat == STRINGFORMAT_ASCII))
- {
- // This is the name of the device.
- lpszLineName = ((char *) lpLineDevCaps) +
- lpLineDevCaps -> dwLineNameOffset;
-
- if (lpszLineName[0] != '\0')
- {
- // Reverse indented to make this fit
-
- // Make sure the device name is null terminated.
- if (lpszLineName[lpLineDevCaps->dwLineNameSize -1] != '\0')
- {
- // If the device name is not null terminated, null
- // terminate it. Yes, this looses the end character.
- // Its a bug in the service provider.
- lpszLineName[lpLineDevCaps->dwLineNameSize-1] = '\0';
- OutputDebugPrintf(
- "Device name for device 0x%lx is not null terminated.\n",
- dwDeviceID);
- }
- }
- else // Line name started with a NULL.
- lpszLineName = szLineNameEmpty;
- }
- else // DevCaps doesn't have a valid line name. Unnamed.
- lpszLineName = szLineUnnamed;
- }
- else // Couldn't GetDevCaps. Line is unavail.
- lpszLineName = szLineUnavail;
- }
- else // Couldn't NegotiateAPIVersion. Line is unavail.
- lpszLineName = szLineUnavail;
-
- // Put the device name into the control
- lReturn = SendDlgItemMessage(hwndDlg, IDC_TAPILINE,
- CB_ADDSTRING, 0, (LPARAM) (LPCTSTR) lpszLineName);
-
- // If this line is usable and we don't have a default initial
- // line yet, make this the initial line.
- if ((lpszLineName != szLineUnavail) &&
- (dwDefaultDevice == MAXDWORD) &&
- (VerifyUsableLine(dwDeviceID) == SUCCESS))
- {
- dwDefaultDevice = dwDeviceID;
- }
- }
-
- if (lpLineDevCaps)
- LocalFree(lpLineDevCaps);
-
- if (dwDefaultDevice == MAXDWORD)
- dwDefaultDevice = 0;
-
- // Set the initial default line
- SendDlgItemMessage(hwndDlg, IDC_TAPILINE,
- CB_SETCURSEL, dwDefaultDevice, 0);
- }
-
-
- //
- // FUNCTION: BOOL VerifyAndWarnUsableLine(HWND)
- //
- // PURPOSE: Verifies the line device selected by the user.
- //
- // PARAMETERS:
- // hwndDlg - The handle to the current "Dial" dialog.
- //
- // RETURN VALUE:
- // Returns TRUE if the currently selected line device is useable
- // by TapiComm. Returns FALSE if it isn't.
- //
- // COMMENTS:
- //
- // This function is very specific to the "Dial" dialog. It gets
- // the device selected by the user from the 'TAPI Line' control and
- // VerifyUsableLine to make sure this line device is usable. If the
- // line isn't useable, it notifies the user and disables the 'Dial'
- // button so that the user can't initiate a call with this line.
- //
- // This function is also responsible for filling in the line specific
- // icon found on the "Dial" dialog.
- //
- //
-
- BOOL VerifyAndWarnUsableLine(HWND hwndDlg)
- {
- DWORD dwDeviceID;
- long lReturn;
- HICON hIcon = 0;
- HWND hControlWnd;
-
- // Get the selected line device.
- dwDeviceID = SendDlgItemMessage(hwndDlg, IDC_TAPILINE,
- CB_GETCURSEL, 0, 0);
-
- // Get the "comm" device icon associated with this line device.
- lReturn = lineGetIcon(dwDeviceID, "comm", &hIcon);
-
- if (lReturn == SUCCESS)
- SendDlgItemMessage(hwndDlg, IDC_LINEICON, STM_SETICON,
- (WPARAM) hIcon, 0);
- else
- // Any failure to get an icon makes us use the default icon.
- SendDlgItemMessage(hwndDlg, IDC_LINEICON, WM_SETTEXT,
- 0, (LPARAM) (LPCTSTR) "TapiComm");
-
- /* // It turns out that TAPI will always return an icon, even if
- // the device class isn't supported by the TSP or even if the TSP
- // doesn't return any icons at all. This code is unnecessary.
- // The only reason lineGetIcon would fail is due to resource problems.
-
- else
- {
- // If the line doesn't have a "comm" device icon, use its default one.
- lReturn = lineGetIcon(dwDeviceID, NULL, &hIcon);
- if (lReturn == SUCCESS)
- {
- OutputDebugString("Line doesn't support a \"comm\" icon.\n");
- SendDlgItemMessage(hwndDlg, IDC_LINEICON, STM_SETICON,
- (WPARAM) hIcon, 0);
- }
- else
- {
- // If lineGetIcon fails, just use TapiComms icon.
- OutputDebugLineError(lReturn, "lineGetIcon: ");
- SendDlgItemMessage(hwndDlg, IDC_LINEICON, WM_SETTEXT,
- 0, (LPARAM) (LPCTSTR) "TapiComm");
- }
- }
- */
-
- // Verify if the device is usable by TapiComm.
- lReturn = VerifyUsableLine(dwDeviceID);
-
- // Enable or disable the 'Dial' button, depending on if the line is ok.
- // Make sure there is a number to dial before enabling the button.
- hControlWnd = GetDlgItem(hwndDlg, IDC_DIAL);
- if (SendDlgItemMessage(hwndDlg, IDC_CANONICALNUMBER,
- WM_GETTEXTLENGTH, 0, 0) == 0)
- {
- EnableWindow(hControlWnd, FALSE);
- }
- else
- EnableWindow(hControlWnd, (lReturn == SUCCESS));
-
- // Any errors on this line prevent us from configuring it
- // or using dialing properties.
- if (lReturn == LINENOTUSEABLE_ERROR)
- {
- EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGURELINE), FALSE);
- EnableWindow(GetDlgItem(hwndDlg, IDC_DIALINGPROPERTIES), FALSE);
- }
- else
- {
- EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGURELINE), TRUE);
- if (SendDlgItemMessage(hwndDlg, IDC_USEDIALINGRULES, BM_GETCHECK, 0, 0))
- EnableWindow(GetDlgItem(hwndDlg, IDC_DIALINGPROPERTIES), TRUE);
- }
-
- switch(lReturn)
- {
- case SUCCESS:
- g_dwDeviceID = dwDeviceID;
- return TRUE;
-
- case LINENOTUSEABLE_ERROR:
- MessageBox(hwndDlg,
- "The selected line is incompatible with the TapiComm sample",
- "Warning",MB_OK);
- break;
- case LINENOTUSEABLE_NOVOICE:
- MessageBox(hwndDlg,
- "The selected line doesn't support VOICE capabilities",
- "Warning",MB_OK);
- break;
- case LINENOTUSEABLE_NODATAMODEM:
- MessageBox(hwndDlg,
- "The selected line doesn't support DATAMODEM capabilities",
- "Warning",MB_OK);
- break;
- case LINENOTUSEABLE_NOMAKECALL:
- MessageBox(hwndDlg,
- "The selected line doesn't support MAKECALL capabilities",
- "Warning",MB_OK);
- break;
- case LINENOTUSEABLE_ALLOCATED:
- MessageBox(hwndDlg,
- "The selected line is already in use by a non-TAPI application",
- "Warning",MB_OK);
- break;
- case LINENOTUSEABLE_INUSE:
- MessageBox(hwndDlg,
- "The selected line is already in use by a TAPI application",
- "Warning",MB_OK);
- break;
-
- case LINENOTUSEABLE_NOCOMMDATAMODEM:
- MessageBox(hwndDlg,
- "The selected line doesn't support the COMM/DATAMODEM device class",
- "Warning",MB_OK);
- break;
- }
-
- // g_dwDeviceID == MAXDWORD mean the selected device isn't usable.
- g_dwDeviceID = MAXDWORD;
- return FALSE;
- }
-
-
- //
- // FUNCTION: void FillCountryCodeList(HWND, DWORD)
- //
- // PURPOSE: Fill the 'Country Code' control
- //
- // PARAMETERS:
- // hwndDlg - handle to the current "Dial" dialog
- // dwDefaultCountryID - ID of the 'default' country to be selected
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // This function fills the 'Country Code' control with country names.
- // The country code is appended to the end of the name and the names
- // are added to the control sorted. Because the country code is
- // embedded in the string along with the country name, there is no need
- // for any of the country information structures to be kept around. The
- // country code can be extracted from the selected string at any time.
- //
- //
-
- void FillCountryCodeList(HWND hwndDlg, DWORD dwDefaultCountryID)
- {
- LPLINECOUNTRYLIST lpLineCountryList = NULL;
- DWORD dwSizeofCountryList = sizeof(LINECOUNTRYLIST);
- long lReturn;
- DWORD dwCountry;
- LPLINECOUNTRYENTRY lpLineCountryEntries;
- char szRenamedCountry[256];
-
- // Get the country information stored in TAPI
- do
- {
- lpLineCountryList = (LPLINECOUNTRYLIST) CheckAndReAllocBuffer(
- (LPVOID) lpLineCountryList, dwSizeofCountryList,
- "FillCountryCodeList");
-
- if (lpLineCountryList == NULL)
- return;
-
- lReturn = lineGetCountry (0, SAMPLE_TAPI_VERSION, lpLineCountryList);
-
- if (HandleLineErr(lReturn))
- ;
- else
- {
- OutputDebugLineError(lReturn, "lineGetCountry unhandled error: ");
- LocalFree(lpLineCountryList);
- return;
- }
-
- if ((lpLineCountryList -> dwNeededSize) >
- (lpLineCountryList -> dwTotalSize))
- {
- dwSizeofCountryList = lpLineCountryList ->dwNeededSize;
- lReturn = -1; // Lets loop again.
- }
- }
- while (lReturn != SUCCESS);
-
- // Find the first country entry
- lpLineCountryEntries = (LPLINECOUNTRYENTRY)
- (((LPBYTE) lpLineCountryList)
- + lpLineCountryList -> dwCountryListOffset);
-
- // Now enumerate through all the countries
- for (dwCountry = 0;
- dwCountry < lpLineCountryList -> dwNumCountries;
- dwCountry++)
- {
- // append the country code to the country name
- wsprintf(szRenamedCountry,"%s (%lu)",
- (((LPSTR) lpLineCountryList) +
- lpLineCountryEntries[dwCountry].dwCountryNameOffset),
- lpLineCountryEntries[dwCountry].dwCountryCode);
-
- // Now put this country name / code string into the combobox
- lReturn = SendDlgItemMessage(hwndDlg, IDC_COUNTRYCODE, CB_ADDSTRING,
- 0, (LPARAM) (LPCTSTR) szRenamedCountry);
-
- // If this country is the default country, select it.
- if (lpLineCountryEntries[dwCountry].dwCountryID
- == dwDefaultCountryID)
- {
- SendDlgItemMessage(hwndDlg, IDC_COUNTRYCODE, CB_SETCURSEL, lReturn, 0);
- }
- }
-
- LocalFree(lpLineCountryList);
- return;
- }
-
-
- //
- // FUNCTION: void FillLocationInfo(HWND, LPSTR, LPDWORD, LPSTR)
- //
- // PURPOSE: Fill (or refill) the 'Your Location' control
- //
- // PARAMETERS:
- // hwndDlg - handle to the current "Dial" dialog
- // lpszCurrentLocation - Name of current location, or NULL
- // lpdwCountryID - location to store the current country ID or NULL
- // lpszAreaCode - location to store the current area code or NULL
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // This function is moderately multipurpose.
- //
- // If lpszCurrentLocation is NULL, then the 'Your Location' control
- // is filled with all the locations stored in TAPI and the TAPI 'default'
- // location is selected. This is done during initialization and
- // also after the 'Dialing Properties' dialog has been displayed.
- // This last is done because the user can change the current location
- // or add and delete locations while in the 'Dialing Properties' dialog.
- //
- // If lpszCurrentLocation is a valid string pointer, then it is assumed
- // that the 'Your Location' control is already filled and that the user
- // is selecting a specific location. In this case, all of the existing
- // TAPI locations are enumerated until the specified location is found.
- // At this point, the specified location is set to the current location.
- //
- // In either case, if lpdwCountryID is not NULL, it is filled with the
- // country ID for the current location. If lpszAreaCode is not NULL, it
- // is filled with the area code defined for the current location. These
- // values can be used later to initialize other "Dial" controls.
- //
- // This function also fills the 'Calling Card' control based on
- // the information stored in the current location.
- //
- //
-
- void FillLocationInfo(HWND hwndDlg, LPSTR lpszCurrentLocation,
- LPDWORD lpdwCountryID, LPSTR lpszAreaCode)
- {
- LPLINETRANSLATECAPS lpTranslateCaps = NULL;
- DWORD dwSizeofTranslateCaps = sizeof(LINETRANSLATECAPS);
- long lReturn;
- DWORD dwCounter;
- LPLINELOCATIONENTRY lpLocationEntry;
- LPLINECARDENTRY lpLineCardEntry = NULL;
- DWORD dwPreferredCardID = MAXDWORD;
-
- // First, get the TRANSLATECAPS
- do
- {
- lpTranslateCaps = (LPLINETRANSLATECAPS) CheckAndReAllocBuffer(
- (LPVOID) lpTranslateCaps, dwSizeofTranslateCaps,
- "FillLocationInfo");
-
- if (lpTranslateCaps == NULL)
- return;
-
- lReturn = lineGetTranslateCaps(g_hLineApp, SAMPLE_TAPI_VERSION,
- lpTranslateCaps);
-
- if (HandleLineErr(lReturn))
- ;
- else
- {
- OutputDebugLineError(lReturn,
- "lineGetTranslateCaps unhandled error: ");
- LocalFree(lpTranslateCaps);
- return;
- }
-
- if ((lpTranslateCaps -> dwNeededSize) >
- (lpTranslateCaps -> dwTotalSize))
- {
- dwSizeofTranslateCaps = lpTranslateCaps ->dwNeededSize;
- lReturn = -1; // Lets loop again.
- }
- }
- while(lReturn != SUCCESS);
-
- // Find the location information in the TRANSLATECAPS
- lpLocationEntry = (LPLINELOCATIONENTRY)
- (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset);
-
- // If lpszCurrentLocation, then make that location 'current'
- if (lpszCurrentLocation)
- {
- // loop through all locations, looking for a location match
- for(dwCounter = 0;
- dwCounter < lpTranslateCaps -> dwNumLocations;
- dwCounter++)
- {
- if (strcmp((((LPSTR) lpTranslateCaps) +
- lpLocationEntry[dwCounter].dwLocationNameOffset),
- lpszCurrentLocation)
- == 0)
- {
- // Found it! Set the current location.
- lineSetCurrentLocation(g_hLineApp,
- lpLocationEntry[dwCounter].dwPermanentLocationID);
-
- // Set the return values.
- if (lpdwCountryID)
- *lpdwCountryID = lpLocationEntry[dwCounter].dwCountryID;
-
- if (lpszAreaCode)
- strcpy(lpszAreaCode, (((LPSTR) lpTranslateCaps) +
- lpLocationEntry[dwCounter].dwCityCodeOffset));
-
- // Store the preferred card ID for later use.
- dwPreferredCardID = lpLocationEntry[dwCounter].dwPreferredCardID;
- break;
- }
- }
-
- // Was a match for lpszCurrentLocation found?
- if (dwPreferredCardID == MAXDWORD)
- {
- OutputDebugString("lpszCurrentLocation not found\n");
- SendDlgItemMessage(hwndDlg, IDC_CALLINGCARD, WM_SETTEXT, 0,
- (LPARAM) (LPCSTR) "Invalid Location Selected");
- LocalFree(lpTranslateCaps);
- return;
- }
- }
- else // fill the combobox and use the TAPI 'current' location.
- {
- // First empty the combobox
- SendDlgItemMessage(hwndDlg, IDC_LOCATION, CB_RESETCONTENT, 0, 0);
-
- // enumerate all the locations
- for(dwCounter = 0;
- dwCounter < lpTranslateCaps -> dwNumLocations;
- dwCounter++)
- {
- // Put each one into the combobox
- lReturn = SendDlgItemMessage(hwndDlg, IDC_LOCATION, CB_ADDSTRING,
- 0, (LPARAM) (((LPBYTE) lpTranslateCaps) +
- lpLocationEntry[dwCounter].dwLocationNameOffset));
-
- // Is this location the 'current' location?
- if (lpLocationEntry[dwCounter].dwPermanentLocationID ==
- lpTranslateCaps->dwCurrentLocationID)
- {
- // Return the requested information
- if (lpdwCountryID)
- *lpdwCountryID = lpLocationEntry[dwCounter].dwCountryID;
-
- if (lpszAreaCode)
- strcpy(lpszAreaCode, (((LPSTR) lpTranslateCaps) +
- lpLocationEntry[dwCounter].dwCityCodeOffset));
-
- // Set this to be the active location.
- SendDlgItemMessage(hwndDlg, IDC_LOCATION, CB_SETCURSEL, lReturn, 0);
- dwPreferredCardID = lpLocationEntry[dwCounter].dwPreferredCardID;
- }
- }
- }
-
- // Now locate the prefered card and display it.
-
- lpLineCardEntry = (LPLINECARDENTRY)
- (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwCardListOffset);
-
- for(dwCounter = 0;
- dwCounter < lpTranslateCaps -> dwNumCards;
- dwCounter++)
- {
- if (lpLineCardEntry[dwCounter].dwPermanentCardID == dwPreferredCardID)
- {
- SendDlgItemMessage(hwndDlg, IDC_CALLINGCARD, WM_SETTEXT, 0,
- (LPARAM) (((LPBYTE) lpTranslateCaps) +
- lpLineCardEntry[dwCounter].dwCardNameOffset));
- break;
- }
- }
-
- LocalFree(lpTranslateCaps);
- }
-
-
-
- //
- // FUNCTION: void UseDialingRules(HWND)
- //
- // PURPOSE: Enable/disable Dialing Rule controls
- //
- // PARAMETERS:
- // hwndDlg - handle to the current "Dial" dialog
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // The sole purpose of this function is to enable or disable
- // the controls that apply to dialing rules if the
- // "Use Country Code and Area Code" checkbox is checked or unchecked,
- // as appropriate.
- //
- //
-
- void UseDialingRules(HWND hwndDlg)
- {
- HWND hControl;
- BOOL bEnableWindow;
-
- bEnableWindow = SendDlgItemMessage(hwndDlg,
- IDC_USEDIALINGRULES, BM_GETCHECK, 0, 0);
-
- hControl = GetDlgItem(hwndDlg, IDC_STATICCOUNTRYCODE);
- EnableWindow(hControl, bEnableWindow);
-
- hControl = GetDlgItem(hwndDlg, IDC_COUNTRYCODE);
- EnableWindow(hControl, bEnableWindow);
-
- hControl = GetDlgItem(hwndDlg, IDC_STATICAREACODE);
- EnableWindow(hControl, bEnableWindow);
-
- hControl = GetDlgItem(hwndDlg, IDC_AREACODE);
- EnableWindow(hControl, bEnableWindow);
-
- hControl = GetDlgItem(hwndDlg, IDC_STATICLOCATION);
- EnableWindow(hControl, bEnableWindow);
-
- hControl = GetDlgItem(hwndDlg, IDC_LOCATION);
- EnableWindow(hControl, bEnableWindow);
-
- hControl = GetDlgItem(hwndDlg, IDC_STATICCALLINGCARD);
- EnableWindow(hControl, bEnableWindow);
-
- hControl = GetDlgItem(hwndDlg, IDC_CALLINGCARD);
- EnableWindow(hControl, bEnableWindow);
-
- if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CONFIGURELINE)))
- {
- hControl = GetDlgItem(hwndDlg, IDC_DIALINGPROPERTIES);
- EnableWindow(hControl, bEnableWindow);
- }
- }
-
-
- //
- // FUNCTION: void DisplayPhoneNumber(HWND)
- //
- // PURPOSE: Create, Translate and Display the Phone Number
- //
- // PARAMETERS:
- // hwndDlg - handle to the current "Dial" dialog
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // This function uses the information stored in many other controls
- // to build the phone number, translate it, and display it. Also
- // makes sure the Dial button is enabled or disabled, based on if the
- // number can be dialed or not.
- //
- // There are actually three phone numbers generated during this
- // process: canonical, dialable and displayable. Normally, only the
- // displayable number is shown to the user; the other two numbers are
- // to be used by the program internally. However, for demonstration
- // purposes (and because it is cool for developers to see these numbers),
- // all three numbers are displayed.
- //
-
- void DisplayPhoneNumber(HWND hwndDlg)
- {
- char szPreTranslatedNumber[1024] = "";
- int nPreTranslatedSize = 0;
- char szTempBuffer[512];
- int i;
- DWORD dwDeviceID;
- LPLINETRANSLATEOUTPUT lpLineTranslateOutput = NULL;
-
- // Disable the 'dial' button if there isn't a number to dial
- if (0 == SendDlgItemMessage(hwndDlg, IDC_PHONENUMBER,
- WM_GETTEXTLENGTH, 0, 0))
- {
- SendDlgItemMessage(hwndDlg, IDC_CANONICALNUMBER, WM_SETTEXT, 0,
- (LPARAM) NULL);
- SendDlgItemMessage(hwndDlg, IDC_DIALABLENUMBER, WM_SETTEXT, 0,
- (LPARAM) NULL);
- SendDlgItemMessage(hwndDlg, IDC_DISPLAYABLENUMBER, WM_SETTEXT, 0,
- (LPARAM) (LPCTSTR) "No Phone Number");
-
- EnableWindow(GetDlgItem(hwndDlg, IDC_DIAL), FALSE);
- return;
- }
-
- // If we use the dialing rules, lets make canonical format.
- // Canonical format is explained in the TAPI documentation and the
- // string format needs to be followed very strictly.
- if (SendDlgItemMessage(hwndDlg, IDC_USEDIALINGRULES,
- BM_GETCHECK, 0, 0))
- {
- // First character *has* to be the plus sign.
- szPreTranslatedNumber[0] = '+';
- nPreTranslatedSize = 1;
-
- // The country code *has* to be next.
- // Country code was stored in the string with the country
- // name and needs to be extracted at this point.
- i = SendDlgItemMessage(hwndDlg, IDC_COUNTRYCODE,
- CB_GETCURSEL, 0, 0);
- SendDlgItemMessage(hwndDlg, IDC_COUNTRYCODE,
- CB_GETLBTEXT, (WPARAM) i, (LPARAM) (LPCTSTR) szTempBuffer);
-
- // Country code is at the end of the string, surounded by parens.
- // This makes it easy to identify the country code.
- i = strlen(szTempBuffer);
- while(szTempBuffer[--i] != '(');
-
- while(szTempBuffer[++i] != ')')
- szPreTranslatedNumber[nPreTranslatedSize++] = szTempBuffer[i];
-
- // Next is the area code.
- i = SendDlgItemMessage(hwndDlg, IDC_AREACODE, WM_GETTEXT,
- 510, (LPARAM) (LPCTSTR) szTempBuffer);
-
- // Note that the area code is optional. If it is included,
- // then it has to be preceeded by *exactly* one space and it
- // *has* to be surrounded by parens.
- if (i)
- nPreTranslatedSize +=
- wsprintf(&szPreTranslatedNumber[nPreTranslatedSize],
- " (%s)", szTempBuffer);
-
- // There has to be *exactly* one space before the rest of the number.
- szPreTranslatedNumber[nPreTranslatedSize++] = ' ';
-
- // At this point, the phone number is appended to the
- // canonical number. The next step is the same whether canonical
- // format is used or not; just the prepended area code and
- // country code are different.
- }
-
- SendDlgItemMessage(hwndDlg, IDC_PHONENUMBER, WM_GETTEXT,
- 510, (LPARAM) (LPCTSTR) szTempBuffer);
-
- strcat(&szPreTranslatedNumber[nPreTranslatedSize], szTempBuffer);
-
- dwDeviceID = SendDlgItemMessage(hwndDlg, IDC_TAPILINE,
- CB_GETCURSEL, 0, 0);
-
- // Translate the address!
- lpLineTranslateOutput = I_lineTranslateAddress(
- lpLineTranslateOutput, dwDeviceID, SAMPLE_TAPI_VERSION,
- szPreTranslatedNumber);
-
- // Unable to translate it?
- if (lpLineTranslateOutput == NULL)
- {
- SendDlgItemMessage(hwndDlg, IDC_CANONICALNUMBER, WM_SETTEXT, 0,
- (LPARAM) NULL);
- SendDlgItemMessage(hwndDlg, IDC_DIALABLENUMBER, WM_SETTEXT, 0,
- (LPARAM) NULL);
- SendDlgItemMessage(hwndDlg, IDC_DISPLAYABLENUMBER, WM_SETTEXT, 0,
- (LPARAM) (LPCTSTR) "Invalid Phone Number or Area Code");
-
- EnableWindow(GetDlgItem(hwndDlg, IDC_DIAL), FALSE);
- return;
- }
-
- // Is the selected device useable with TapiComm?
- if (g_dwDeviceID != MAXDWORD)
- EnableWindow(GetDlgItem(hwndDlg, IDC_DIAL), TRUE);
-
- // Fill the appropriate phone number controls.
- SendDlgItemMessage(hwndDlg, IDC_CANONICALNUMBER, WM_SETTEXT, 0,
- (LPARAM) (LPCTSTR) szPreTranslatedNumber);
-
- SendDlgItemMessage(hwndDlg, IDC_DIALABLENUMBER, WM_SETTEXT, 0,
- (LPARAM) ((LPSTR) lpLineTranslateOutput +
- lpLineTranslateOutput -> dwDialableStringOffset));
-
- SendDlgItemMessage(hwndDlg, IDC_DISPLAYABLENUMBER, WM_SETTEXT, 0,
- (LPARAM) ((LPSTR) lpLineTranslateOutput +
- lpLineTranslateOutput -> dwDisplayableStringOffset));
-
- LocalFree(lpLineTranslateOutput);
-
- }
-
-
- //
- // FUNCTION: void PreConfigureDevice(HWND, DWORD)
- //
- // PURPOSE:
- //
- // PARAMETERS:
- // hwndDlg - handle to the current "Dial" dialog
- // dwDeviceID - line device to be configured
- //
- // RETURN VALUE:
- // none
- //
- // COMMENTS:
- //
- // At one point, PreConfigureDevice used lineConfigDialog to
- // configure the device. This has the unfortunate effect of configuring
- // the device immediately, even if it is in use by another TAPI app.
- // This can be really bad if data communications are already in
- // progress (like with RAS).
- //
- // Now, PreConfigureDevice uses lineConfigDialogEdit to give the
- // user the configuration UI, but it doesn't actually do anything to
- // the line device. TapiComm stores the configuration information so
- // that it can be set later, just before making the call.
- //
- //
-
- void PreConfigureDevice(HWND hwndDlg, DWORD dwDeviceID)
- {
- long lReturn;
- LPVARSTRING lpVarString = NULL;
- DWORD dwSizeofVarString = sizeof(VARSTRING);
-
- // If there isn't already any device configuration information,
- // then we need to get some.
- if (g_lpDeviceConfig == NULL)
- {
- do
- {
- lpVarString = (LPVARSTRING) CheckAndReAllocBuffer(
- (LPVOID) lpVarString, dwSizeofVarString,
- "PreConfigureDevice - lineGetDevConfig: ");
-
- if (lpVarString == NULL)
- return;
-
- lReturn = lineGetDevConfig(dwDeviceID, lpVarString,
- "comm/datamodem");
-
- if (HandleLineErr(lReturn))
- ;
- else
- {
- OutputDebugLineError(lReturn,
- "lineGetDevCaps unhandled error: ");
- LocalFree(lpVarString);
- return;
- }
-
- if ((lpVarString -> dwNeededSize) > (lpVarString -> dwTotalSize))
- {
- dwSizeofVarString = lpVarString -> dwNeededSize;
- lReturn = -1; // Lets loop again.
- }
- }
- while (lReturn != SUCCESS);
-
- g_dwSizeDeviceConfig = lpVarString -> dwStringSize;
-
- // The extra byte allocated is in case dwStringSize is 0.
- g_lpDeviceConfig = CheckAndReAllocBuffer(
- g_lpDeviceConfig, g_dwSizeDeviceConfig+1,
- "PreConfigureDevice - Allocate device config: ");
-
- if (!g_lpDeviceConfig)
- {
- LocalFree(lpVarString);
- return;
- }
-
- memcpy(g_lpDeviceConfig,
- ((LPBYTE) lpVarString + lpVarString -> dwStringOffset),
- g_dwSizeDeviceConfig);
- }
-
- // Next make the lineConfigDialogEdit call.
-
- // Note that we determine the initial size of the VARSTRING
- // structure based on the known size of the existing configuration
- // information. I make the assumption that this configuration
- // information is very unlikely to grow by more than 5K or by
- // more than 5 times. This is a *very* conservative number.
- // We do *not* want lineConfigDialogEdit to fail just because there
- // wasn't enough room to stored the data. This would require the user
- // to go through configuration again and that would be annoying.
-
- dwSizeofVarString = 5 * g_dwSizeDeviceConfig + 5000;
-
- do
- {
- lpVarString = (LPVARSTRING) CheckAndReAllocBuffer(
- (LPVOID) lpVarString, dwSizeofVarString,
- "PreConfigureDevice - lineConfigDialogEdit: ");
-
- if (lpVarString == NULL)
- return;
-
- lReturn = lineConfigDialogEdit(dwDeviceID, hwndDlg, "comm/datamodem",
- g_lpDeviceConfig, g_dwSizeDeviceConfig, lpVarString);
-
- if (HandleLineErr(lReturn))
- ;
- else
- {
- OutputDebugLineError(lReturn,
- "lineConfigDialogEdit unhandled error: ");
- LocalFree(lpVarString);
- return;
- }
-
- if ((lpVarString -> dwNeededSize) > (lpVarString -> dwTotalSize))
- {
- // We had been conservative about making sure the structure was
- // big enough. Unfortunately, not conservative enough. Hopefully,
- // this will not happen a second time because we are *DOUBLING*
- // the NeededSize.
- MessageBox(hwndDlg,
- "Internal Error: Unable to set line configuration.\n"
- "Please try again.",
- "Oops", MB_OK);
- dwSizeofVarString = (lpVarString -> dwNeededSize) * 2;
- lReturn = -1; // Lets loop again.
- }
- }
- while (lReturn != SUCCESS);
-
- // Store the configuration information into a global structure
- // so it can be set at a later time.
- g_dwSizeDeviceConfig = lpVarString -> dwStringSize;
- g_lpDeviceConfig = CheckAndReAllocBuffer(
- g_lpDeviceConfig, g_dwSizeDeviceConfig+1,
- "PreConfigureDevice - Reallocate device config: ");
-
- if (!g_lpDeviceConfig)
- {
- LocalFree(lpVarString);
- return;
- }
-
- memcpy(g_lpDeviceConfig,
- ((LPBYTE) lpVarString + lpVarString -> dwStringOffset),
- g_dwSizeDeviceConfig);
-
- LocalFree(lpVarString);
- }
-
-
- //
- // FUNCTION: BOOL GetAddressToDial
- //
- // PURPOSE: Get an address to dial from the user.
- //
- // PARAMETERS:
- // none
- //
- // RETURN VALUE:
- // TRUE if a valid device and phone number have been entered by
- // the user. FALSE if the user canceled the dialing process.
- //
- // COMMENTS:
- //
- // All this function does is launch the "Dial" dialog.
- //
- //
-
- BOOL GetAddressToDial()
- {
- BOOL bRet;
-
- UpdateStatusBar("Getting Number to Dial",1,0);
- bRet = DialogBoxParam(hInst, "DialDialog", g_hDlgParentWindow,
- DialDialogProc, 0);
- g_hDialog = NULL;
- g_hDlgParentWindow = g_hWndMainWindow;
-
- if (bRet == FALSE)
- UpdateStatusBar("Dial aborted",1,0);
-
- return bRet;
- }
-
-
- //
- // FUNCTION: DialDialogProc(HWND, UINT, WPARAM, LPARAM)
- //
- // PURPOSE: Dialog callback procedure for the dialing dialog
- //
- // PARAMETERS:
- // hwndDlg - Dialog calling the callback.
- // uMsg - Dialog message.
- // wParam - uMsg specific.
- // lParam - uMsg specific.
- //
- // RETURN VALUE:
- // returns 0 - command handled.
- // returns non-0 - command unhandled
- //
- // COMMENTS:
- //
- // This is the dialog to get the phone number and line device
- // from the user. All the relavent information is stored in global
- // variables to be used later if the dialog returns successfully.
- //
- //
-
-
- BOOL CALLBACK DialDialogProc(
- HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- // Static variables to store the information from last time the
- // "Dial" dialog was displayed. That way the phone number can be
- // typed once but used several times.
-
- static char szCountryName[512] = "";
- static char szAreaCode[256] = "Not Valid";
- static char szPhoneNumber[512] = "Not Valid";
- static DWORD dwUsedDeviceID = MAXDWORD;
- static BOOL bUsedCountryAndArea = FALSE;
- static BOOL bHistoryValid = FALSE;
-
- switch(uMsg)
- {
- case WM_INITDIALOG:
- {
- DWORD dwCountryID = 0;
-
- // Store the Dialog Window so it can be dismissed if necessary
- g_hDialog = hwndDlg;
-
- // This dialog should be parent to all dialogs.
- g_hDlgParentWindow = hwndDlg;
-
- // Initialize the Dialog Box. Lots to do here.
-
- FillTAPILine(hwndDlg);
- if (g_lpDeviceConfig)
- {
- LocalFree(g_lpDeviceConfig);
- g_lpDeviceConfig = NULL;
- }
-
- // If there is a valid history, use it to initialize the controls.
- if (bHistoryValid)
- {
- FillLocationInfo(hwndDlg, NULL, NULL, NULL);
- FillCountryCodeList(hwndDlg, 0);
-
- SendDlgItemMessage(hwndDlg, IDC_COUNTRYCODE, CB_SELECTSTRING,
- (WPARAM) -1, (LPARAM) (LPCTSTR) szCountryName);
-
- SendDlgItemMessage(hwndDlg, IDC_PHONENUMBER, WM_SETTEXT, 0,
- (LPARAM) (LPCTSTR) szPhoneNumber);
-
- SendDlgItemMessage(hwndDlg, IDC_USEDIALINGRULES,
- BM_SETCHECK, (WPARAM) bUsedCountryAndArea, 0);
-
- SendDlgItemMessage(hwndDlg, IDC_TAPILINE, CB_SETCURSEL,
- g_dwDeviceID, 0);
- }
- else
- {
- FillLocationInfo(hwndDlg, NULL, &dwCountryID, szAreaCode);
- FillCountryCodeList(hwndDlg, dwCountryID);
- SendDlgItemMessage(hwndDlg, IDC_USEDIALINGRULES,
- BM_SETCHECK, 1, 0);
- }
-
- SendDlgItemMessage(hwndDlg, IDC_AREACODE, WM_SETTEXT,
- 0, (LPARAM) (LPCTSTR) szAreaCode);
-
- UseDialingRules(hwndDlg);
- DisplayPhoneNumber(hwndDlg);
- VerifyAndWarnUsableLine(hwndDlg);
-
- return TRUE;
- }
-
- case WM_COMMAND:
- {
- switch(LOWORD(wParam))
- {
- case IDC_TAPILINE:
- if (HIWORD(wParam) == CBN_SELENDOK)
- {
- if (g_lpDeviceConfig)
- {
- LocalFree(g_lpDeviceConfig);
- g_lpDeviceConfig = NULL;
- }
- DisplayPhoneNumber(hwndDlg);
- VerifyAndWarnUsableLine(hwndDlg);
- }
- return TRUE;
-
- case IDC_CONFIGURELINE:
- {
- DWORD dwDeviceID;
- dwDeviceID = SendDlgItemMessage(hwndDlg, IDC_TAPILINE,
- CB_GETCURSEL, 0, 0);
- PreConfigureDevice(hwndDlg, dwDeviceID);
- DisplayPhoneNumber(hwndDlg);
- return TRUE;
- }
-
- case IDC_COUNTRYCODE:
- if (HIWORD(wParam) == CBN_SELENDOK)
- DisplayPhoneNumber(hwndDlg);
- return TRUE;
-
- case IDC_AREACODE:
- case IDC_PHONENUMBER:
- if (HIWORD(wParam) == EN_CHANGE)
- DisplayPhoneNumber(hwndDlg);
- return TRUE;
-
- case IDC_USEDIALINGRULES:
- if (HIWORD(wParam) == BN_CLICKED)
- {
- UseDialingRules(hwndDlg);
- DisplayPhoneNumber(hwndDlg);
- }
- return TRUE;
-
- case IDC_LOCATION:
- if (HIWORD(wParam) == CBN_CLOSEUP)
- {
- char szCurrentLocation[1024];
- int nCurrentSelection;
-
- nCurrentSelection = SendDlgItemMessage(hwndDlg,
- IDC_LOCATION, CB_GETCURSEL, 0, 0);
- SendDlgItemMessage(hwndDlg, IDC_LOCATION,
- CB_GETLBTEXT, nCurrentSelection,
- (LPARAM) (LPCTSTR) szCurrentLocation);
-
- // If the user selected a 'location', make it current.
- FillLocationInfo(hwndDlg, szCurrentLocation, NULL, NULL);
- DisplayPhoneNumber(hwndDlg);
- }
- return TRUE;
-
- case IDC_DIALINGPROPERTIES:
- {
- char szAddress[1024];
- DWORD dwDeviceID;
- long lReturn;
-
- dwDeviceID = SendDlgItemMessage(hwndDlg, IDC_TAPILINE,
- CB_GETCURSEL, 0, 0);
-
- SendDlgItemMessage(hwndDlg, IDC_CANONICALNUMBER,
- WM_GETTEXT, 1023, (LPARAM) (LPCTSTR) szAddress);
-
- lReturn = lineTranslateDialog(g_hLineApp, dwDeviceID,
- SAMPLE_TAPI_VERSION, hwndDlg, szAddress);
-
- if (lReturn != SUCCESS)
- OutputDebugLineError(lReturn,"lineTranslateDialog: ");
-
- // The user could have changed the default location, or
- // added or removed a location while in the 'Dialing
- // Properties' dialog. Refill the Location Info.
- FillLocationInfo(hwndDlg, NULL, NULL, NULL);
- DisplayPhoneNumber(hwndDlg);
-
- return TRUE;
- }
-
- case IDCANCEL:
- EndDialog(hwndDlg, FALSE);
- return TRUE;
-
- case IDC_DIAL:
- {
- // The Dial button has to be enabled and the line has
- // to be currently usable to continue.
- if (!(IsWindowEnabled((HWND)lParam) &&
- VerifyAndWarnUsableLine(hwndDlg)))
- return TRUE;
-
- DisplayPhoneNumber(hwndDlg);
-
- // Get the displayable and dialable numbers and store
- // them in global variables to be used while dialing.
- SendDlgItemMessage(hwndDlg, IDC_DISPLAYABLENUMBER,
- WM_GETTEXT, 1023, (LPARAM) (LPCTSTR) g_szDisplayableAddress);
-
- SendDlgItemMessage(hwndDlg, IDC_DIALABLENUMBER,
- WM_GETTEXT, 1023, (LPARAM) (LPCTSTR) g_szDialableAddress);
-
- // Store all the relavent information in static
- // variables so they will be available the next time a
- // number is dialed.
- SendDlgItemMessage(hwndDlg, IDC_COUNTRYCODE,
- WM_GETTEXT, 511, (LPARAM) (LPCTSTR) szCountryName);
-
- SendDlgItemMessage(hwndDlg, IDC_AREACODE,
- WM_GETTEXT, 255, (LPARAM) (LPCTSTR) szAreaCode);
-
- SendDlgItemMessage(hwndDlg, IDC_PHONENUMBER,
- WM_GETTEXT, 511, (LPARAM) (LPCTSTR) szPhoneNumber);
-
- bUsedCountryAndArea = (BOOL) SendDlgItemMessage(hwndDlg,
- IDC_USEDIALINGRULES, BM_GETCHECK, 0, 0);
-
- bHistoryValid = TRUE;
-
- EndDialog(hwndDlg, TRUE);
- return TRUE;
- }
-
-
- // This message is actually posted to the dialog from the
- // lineCallbackFunc when it receives a
- // LINEDEVSTATE_TRANSLATECHANGE message. Notify the user and
- // retranslate the number. Also refill the Location Info
- // since this could have been generated by a location change.
- case IDC_CONFIGURATIONCHANGED:
- {
- FillLocationInfo(hwndDlg, NULL, NULL, NULL);
- DisplayPhoneNumber(hwndDlg);
-
- MessageBox(hwndDlg,
- "Location Configuration has been changed.",
- "Warning",MB_OK);
-
- return TRUE;
- }
-
- // If we get a LINE_CREATE message, all that needs to be done
- // is to reset this controls contents. The selected line
- // won't change and no lines will be removed.
- case IDC_LINECREATE:
- {
- FillTAPILine(hwndDlg);
- return TRUE;
- }
-
- default:
- break;
- }
-
- break;
- }
-
- // This dialog has the DS_CONTEXTMENU flag so that the right mouse
- // button will send this message. Bring up the appropriate help page.
- case WM_CONTEXTMENU:
- {
-
- if (hwndDlg != (HWND) wParam)
- WinHelp ((HWND)wParam,
- "TAPICOMM.HLP",
- HELP_CONTEXTMENU,
- (DWORD)(LPVOID) g_adwSampleMenuHelpIDs);
- break;
- }
-
- // Bring up the appropriate help page.
- case WM_HELP:
- {
- LPHELPINFO lphi;
-
- lphi = (LPHELPINFO)lParam;
- if ((lphi->iContextType == HELPINFO_WINDOW) &&
- (hwndDlg != lphi->hItemHandle) &&
- (lphi->iCtrlId < IDC_NOHELPCONTROLS))
- {
- WinHelp (lphi->hItemHandle,
- "TAPICOMM.HLP",
- HELP_WM_HELP,
- (DWORD)(LPVOID) g_adwSampleMenuHelpIDs);
- }
-
- return TRUE;
- }
-
- default:
- break;
- }
-
- return FALSE;
- }
-