/*++ Copyright (c) 1996 Microsoft Corporation Module Name: dialer.c --*/ #include "dialer.h" #include "string.h" #include "tchar.h" #include "stdlib.h" #include "shellapi.h" #define DIALER_REGISTRY_PATH TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Dialer") #define DIALER_REGISTRY_ROOT HKEY_CURRENT_USER #define ISDIGIT(x) (((x) - TEXT('0')) >= 0) && (((x) - TEXT('0')) <= 9) enum NumberTypes { LOCAL_NUMBER = 7, EXTENDED_LOCAL_NUMBER, LONG_DISTANCE_NUMBER = 10, EXTENDED_LONG_DISTANCE_NUMBER }; // structs typedef struct tagLINEINFO { DWORD nAddr; // Number of avail. addresses on the line BOOL fVoiceLine; // Is this a voice line? DWORD dwAPIVersion; // API version which the line supports HLINE hLine; // line handle returned by lineOpen DWORD dwPermanentLineID; // Permanent line ID retreived from devcaps TCHAR szLineName[MAXBUFSIZE]; // the line's name } LINEINFO, *LPLINEINFO; // Global variables // window/instance variables HWND ghWndMain; HWND ghWndDialing = NULL; HINSTANCE ghInst = 0; // file name vars. static TCHAR gszAppName[64]; static TCHAR gszINIfilename [] = TEXT("DIALER.INI";) static TCHAR gszHELPfilename [] = TEXT("DIALER.HLP"); static TCHAR gszDialerClassName[] = TEXT("DialerClass"); TCHAR const gszNULL[] = TEXT(""); // window item variables HLINEAPP ghLineApp = 0; // Dialer's usage handle (regist. w/TAPI) HCALL ghCall = 0; // call handle for Dialer's call LPTSTR gszCurrentNumber = NULL; // number of destination of current call LPTSTR gszCurrentName = NULL; // name of destination of current call BOOL gfRegistered; // was lineRegisterRequestRecipient() // successful? BOOL gfNeedToReinit = FALSE; // does Dialer need to re-initialize? BOOL gfCallRequest = FALSE; // Does a Simple TAPI app want a call? BOOL gfCurrentLineAvail = TRUE; // Simple TAPI requests are only carried // out if the current chosen line is avail. BOOL gfMakeCallReplyPending = FALSE; LONG gMakeCallRequestID = 0; // request ID returned by async TAPI fns. LONG gDropCallRequestID = 0; // request ID returned by async TAPI fns. DWORD gnAvailDevices = 0; // # of line devices avail. to Dialer LINEINFO gCurrentLineInfo; DWORD * gnAddr; // global to remember where the cursor is in the edit control DWORD gdwStartSel; DWORD gdwEndSel; DWORD * gdwPLID; // current line's permanent line ID DWORD giCurrentLine = (DWORD)-1; // the line selected by the user DWORD giCurrentAddress = 0; // the address selected by the user // + 1 so we can work 1-based rather than 0-based (for convenience only) // global varibles to hold the names and address of the TCHAR gszSDNumber[ NSPEEDDIALS + 1 ][ TAPIMAXDESTADDRESSSIZE ] = {0}; // Function declarations // button related functions VOID DisableDialButtons(BOOL fDisable); VOID FitTextToButton( HWND, INT, LPTSTR ); // Callback functions INT_PTR CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK DialingProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK AboutProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ConnectUsingProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK LineInUseProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK SpeedDial1Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK SpeedDial2Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); VOID CALLBACK tapiCallback ( DWORD hDevice, DWORD dwMsg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3 ); // tapi related functions VOID ManageAssistedTelephony(VOID); VOID InitiateCall(LPCTSTR szNumber, LPCTSTR szName); VOID DialerLineClose(VOID); VOID DialerCleanup(VOID); VOID CloseTAPI(VOID); DWORD GetLineInfo(DWORD iLine, LPLINEINFO lpLineInfo); VOID GetLineInfoFailed ( DWORD iLine, LPLINEDEVCAPS lpDevCaps, LPLINEINFO lpLineInfo ); LPTSTR GetAddressName(DWORD iLine, DWORD iAddress); BOOL MakeCanonicalNumber( LPCTSTR szName, LPTSTR szCanNumber ); // misc. helper functions VOID ReadINI(VOID); int errString(HWND hWnd, UINT errCode, UINT uFlags); VOID AddToRedialList(LPCTSTR szNumber); BOOL InitializeLineBox(HWND hwndLineBox); BOOL InitializeAddressBox(HWND hwndLineBox, HWND hwndAddressBox); BOOL Is911 ( LPLINETRANSLATEOUTPUT lpTransOut ); VOID AmpersandCompensate( LPCTSTR lpszSrc, LPTSTR lpszDst ); VOID AmpersandDeCompensate( LPCTSTR lpszSrc, LPTSTR lpszDst ); // Dialer memory management functions LPVOID DialerAlloc(size_t cbToAlloc); LPVOID DialerFree(LPVOID lpMem); // Function definitions //*************************************************************************** //*************************************************************************** //*************************************************************************** DWORD InitializeTAPI (VOID) { INT cvLine; DWORD iLine; DWORD dwPreferredPLID, dwID = (DWORD) -1; MSG msg; LPLINEINFO lpLineInfo = NULL; // LINEINFO for each available line DWORD errCode; DWORD tc = GetTickCount(); DWORD dwReturn = ERR_NONE; TCHAR szBuffer[MAXBUFSIZE]; // to read in dwPreferredPLID as a string first DWORD dwTapiVersion = TAPI_CURRENT_VERSION; LINEINITIALIZEEXPARAMS lip = {sizeof (LINEINITIALIZEEXPARAMS), sizeof (LINEINITIALIZEEXPARAMS), sizeof (LINEINITIALIZEEXPARAMS), LINEINITIALIZEEXOPTION_USEHIDDENWINDOW}; HKEY hKey = NULL; DWORD dwSize; errCode = lineInitializeEx ( &ghLineApp, ghInst, (LINECALLBACK) tapiCallback, gszAppName, &gnAvailDevices, &dwTapiVersion, &lip ); if ( errCode == LINEERR_REINIT ) { // take away dialer functionality EnableWindow( ghWndMain, FALSE ); DisableDialButtons(TRUE); // keep trying until the user cancels // or we stop getting LINEERR_REINIT while ( ( errCode = lineInitializeEx ( &ghLineApp, ghInst, (LINECALLBACK)tapiCallback, gszAppName, &gnAvailDevices, &dwTapiVersion, &lip ) ) == LINEERR_REINIT ) { // flush queue & yield while ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } // bring up the box if 5 seconds have passed since if(GetTickCount() > 5000 + tc) { if ( errString( ghWndMain, ikszWarningTapiReInit, MB_RETRYCANCEL ) == IDCANCEL ) { break; } // reset the relative counter tc = GetTickCount(); } } // give back dialer functionality DisableDialButtons( FALSE ); EnableWindow( ghWndMain, TRUE ); } if ( errCode ) { dwReturn = errCode; goto tapiinit_exit; } RegOpenKeyEx (DIALER_REGISTRY_ROOT, DIALER_REGISTRY_PATH, 0, KEY_READ, &hKey); // retrieve preferred line info from INI file dwSize = sizeof (szBuffer); szBuffer[0] = 0; if (ERROR_SUCCESS == RegQueryValueEx (hKey, TEXT("Preferred Line"), NULL, NULL, (LPBYTE)szBuffer, &dwSize)) { dwPreferredPLID = (DWORD) _ttoi( szBuffer ); } else { dwPreferredPLID = (DWORD) -1; } // -1 default - tells us if it ever gets set giCurrentLine = (DWORD) -1; // allocate buffer for storing LINEINFO for all of the available lines // always allocate space for at least one line if ( gnAvailDevices == 0 ) { gnAddr = (DWORD *) DialerAlloc( sizeof( DWORD ) ); gdwPLID = (DWORD *) DialerAlloc( sizeof( DWORD ) ); lpLineInfo = (LPLINEINFO) DialerAlloc( sizeof( LINEINFO ) ); } else { gnAddr = (DWORD *) DialerAlloc( sizeof( DWORD ) * (int)gnAvailDevices); gdwPLID = (DWORD *) DialerAlloc( sizeof( DWORD ) * (int)gnAvailDevices); lpLineInfo = (LPLINEINFO) DialerAlloc( sizeof( LINEINFO ) * (int)gnAvailDevices ); } // if no space was set aside... if ( lpLineInfo == NULL || gnAddr == NULL ) { dwReturn = LINEERR_NOMEM; goto tapiinit_exit; } // fill lpLineInfo[] and open each line for ( iLine = 0, cvLine = 0; iLine < gnAvailDevices; ++iLine ) { // skip remaining processing for this if it didn't open if ( GetLineInfo( iLine, &lpLineInfo[iLine] ) != ERR_NONE ) continue; gnAddr [ iLine ] = lpLineInfo[iLine].nAddr; gdwPLID[ iLine ] = lpLineInfo[iLine].dwPermanentLineID; if ( lpLineInfo[iLine].dwPermanentLineID == dwPreferredPLID ) giCurrentLine = iLine; // note number of lines with Interactive voice caps. // used to select a preferred line by default if ( lpLineInfo [ iLine ].fVoiceLine ) { cvLine++; dwID = iLine; } } // if we couldn't find the preferred line, // try and assign one by default // else bring up connect using dialog if ( giCurrentLine == (DWORD)-1 ) { // check if there is only one line // that has interactive voice caps, // make it default line if ( cvLine == 1 ) { giCurrentLine = dwID; // if the preferred address read from the INI file // was different i.e we are changing setting, inform // the user if ( dwPreferredPLID != -1 ) { errString( ghWndMain, ERR_NEWDEFAULT, MB_ICONEXCLAMATION | MB_OK ); } } else { gCurrentLineInfo = lpLineInfo[0]; if ( DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_CONNECTUSING), ghWndMain, ConnectUsingProc, INVALID_LINE ) == -1) { dwReturn = (DWORD) -1; } else { dwReturn = ERR_NONE; } goto tapiinit_exit; } } gCurrentLineInfo = lpLineInfo[ giCurrentLine ]; // select default address giCurrentAddress = 0; // get the name of the preferred address from ini file dwSize = sizeof (szBuffer); szBuffer[0] = 0; if (ERROR_SUCCESS == RegQueryValueEx (hKey, TEXT("Preferred Address"), NULL, NULL, (LPBYTE)szBuffer, &dwSize)) { giCurrentAddress = (DWORD) _ttoi( szBuffer ); // if the address is invalid, set default if ( giCurrentAddress >= gCurrentLineInfo.nAddr ) giCurrentAddress = 0; } tapiinit_exit: if (NULL != hKey) { RegCloseKey (hKey); } if (lpLineInfo) { DialerFree(lpLineInfo); } return dwReturn;; } //*************************************************************************** //*************************************************************************** //*************************************************************************** int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { HACCEL hAccel; MSG msg; DWORD errCode; HANDLE hImHere; ghInst = GetModuleHandle( NULL ); LoadString( ghInst, ikszAppFriendlyName, gszAppName, sizeof(gszAppName)/sizeof(TCHAR) ); // // Now, let's see if we've already got an instance of ourself hImHere = CreateMutex(NULL, TRUE, TEXT("DialersIveBeenStartedMutex")); // // Is there another one of us already here? if ( ERROR_ALREADY_EXISTS == GetLastError() ) { HWND hDialerWnd; hDialerWnd = FindWindow(gszDialerClassName, NULL); SetForegroundWindow(hDialerWnd); CloseHandle( hImHere ); return 0; } { WNDCLASS wc; wc.style = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW; wc.lpfnWndProc = DefDlgProc; wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; wc.hInstance = ghInst; wc.hIcon = LoadIcon(ghInst, MAKEINTRESOURCE(IDI_DIALER) ); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject (COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = gszDialerClassName; RegisterClass(&wc); } // create the dialog box and set it with info // from the .INI file ghWndMain = CreateDialog ( ghInst, MAKEINTRESOURCE(IDD_DIALER), (HWND)NULL, MainWndProc ); ReadINI(); ShowWindow(ghWndMain, SW_SHOW); UpdateWindow(ghWndMain); // limit text in Number field to TAPIMAXDESTADDRESSSIZE SendDlgItemMessage ( ghWndMain, IDD_DCOMBO, CB_LIMITTEXT, (WPARAM)TAPIMAXDESTADDRESSSIZE, 0 ); // 0 (ERR_NONE) error code registers success - otherwise terminate errCode = InitializeTAPI(); if(errCode) { errString(ghWndMain, errCode, MB_APPLMODAL | MB_ICONEXCLAMATION ); DialerCleanup(); return errCode; } errCode = lineRegisterRequestRecipient ( ghLineApp, 0, // registration instance LINEREQUESTMODE_MAKECALL, TRUE ); if(errCode) { gfRegistered = FALSE; errString(ghWndMain, errCode, MB_ICONEXCLAMATION | MB_OK ); } else { gfRegistered = TRUE; } hAccel = LoadAccelerators(ghInst, gszAppName); while ( GetMessage( &msg, NULL, 0, 0 ) ) { if ( ghWndMain == NULL || !IsDialogMessage( ghWndMain, &msg ) ) { if(!TranslateAccelerator(ghWndMain, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } // If: 1) Dialer is a call manager (if not, ignore requests) // 2) the currently chosen line is available // 3) there is a Simple TAPI request // Then: process the request if ( gfCurrentLineAvail && gfCallRequest ) { ManageAssistedTelephony(); } } DialerCleanup(); CloseHandle( hImHere ); return (int)msg.wParam; } //*************************************************************************** //*************************************************************************** //*************************************************************************** LPVOID DialerAlloc(size_t cbToAlloc) { return LocalAlloc(LPTR, cbToAlloc); } LPVOID DialerFree(LPVOID lpMem) { return LocalFree( lpMem ); } //*************************************************************************** //*************************************************************************** //*************************************************************************** VOID ReadINI( VOID ) { WORD cSDEntry, cLastDialed; POINT ptLeftTop; TCHAR szName[ TAPIMAXCALLEDPARTYSIZE ] = {0}; TCHAR szTemp[ TAPIMAXCALLEDPARTYSIZE ]; TCHAR szNum[TAPIMAXDESTADDRESSSIZE]; TCHAR szFieldName[MAXBUFSIZE]; TCHAR *p; HKEY hKey = NULL; DWORD dwSize; RegOpenKeyEx (DIALER_REGISTRY_ROOT, DIALER_REGISTRY_PATH, 0, KEY_READ, &hKey); // get speed dial settings from INI file for(cSDEntry = 1; cSDEntry <= NSPEEDDIALS; ++cSDEntry) { wsprintf(szFieldName, TEXT("Number%d"), cSDEntry); *szNum = 0; dwSize = sizeof (szNum); RegQueryValueEx (hKey, szFieldName, NULL, NULL, (LPBYTE)szNum, &dwSize); for (p = szNum; *p == TEXT(' '); p++); if (0 == *p) { continue; } lstrcpyn (gszSDNumber[cSDEntry], p, sizeof(gszSDNumber[cSDEntry])/sizeof(TCHAR)); wsprintf(szFieldName, TEXT("Name%d"), cSDEntry); dwSize = sizeof (szName); RegQueryValueEx (hKey, szFieldName, NULL, NULL, (LPBYTE)szName, &dwSize); if (0 == *szName) { lstrcpyn( szName, gszSDNumber[ cSDEntry ], sizeof(szName)/sizeof(szName[0]) ); } FitTextToButton( ghWndMain, IDD_DSPEEDDIAL1 + cSDEntry - 1, szName ); AmpersandCompensate( szName, szTemp ); SetDlgItemText ( ghWndMain, IDD_DSPEEDDIAL1 + cSDEntry - 1, (LPCTSTR)szTemp ); // Label the speed dial button } // set up last dialed numbers in combo box (read from INI) for(cLastDialed = 1; cLastDialed <= NLASTDIALED; ++cLastDialed) { wsprintf(szFieldName, TEXT("Last dialed %d"), cLastDialed); dwSize = sizeof (szNum); szNum[0] = 0; RegQueryValueEx (hKey, szFieldName, NULL, NULL, (LPBYTE)szNum, &dwSize); if (0 != szNum[0]) { SendDlgItemMessage( ghWndMain, IDD_DCOMBO, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)szNum ); } } // set defaults ptLeftTop.x = 100; ptLeftTop.y = 100; // set the window position based on the INI data dwSize = sizeof (ptLeftTop); RegQueryValueEx (hKey, TEXT("Main Window Left/Top"), NULL, NULL, (LPBYTE)&ptLeftTop, &dwSize); if ( ptLeftTop.x < 0 || ptLeftTop.x + 50 >= GetSystemMetrics(SM_CXSCREEN) || ptLeftTop.y < 0 || ptLeftTop.y + 50 >= GetSystemMetrics(SM_CYSCREEN) ) { ptLeftTop.x = 100; // set defaults if the box is off of the screen ptLeftTop.y = 100; // set defaults if the box is off of the screen } SetWindowPos ( ghWndMain, NULL, ptLeftTop.x, ptLeftTop.y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOZORDER ); RegCloseKey (hKey); } //*************************************************************************** //*************************************************************************** //*************************************************************************** VOID DisableDialButtons(BOOL fDisable) { int IDD; // Disable/enable Dial button EnableWindow( GetDlgItem( ghWndMain, IDD_DDIAL ),!fDisable) ; // Disable/enable Speed dial buttons for ( IDD = IDD_DSPEEDDIAL1; IDD <= IDD_DSPEEDDIAL8; ++IDD ) { EnableWindow(GetDlgItem(ghWndMain, IDD),!fDisable); } } //*************************************************************************** //*************************************************************************** //*************************************************************************** VOID DialerCleanup(VOID) { RECT rc; WORD cItem; // count of numbers in combo box DWORD cLastDialed; TCHAR szNumber[TAPIMAXDESTADDRESSSIZE]; TCHAR szFieldName[MAXBUFSIZE]; HKEY hKey = NULL; DWORD dwSize; RegCreateKeyEx (DIALER_REGISTRY_ROOT, DIALER_REGISTRY_PATH, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); CloseTAPI(); // unregister and line close if(!IsIconic(ghWndMain)) // if the window is not minimized, record position { GetWindowRect(ghWndMain, &rc); RegSetValueEx (hKey, TEXT("Main Window Left/Top"), 0, REG_BINARY, (LPBYTE)&rc, sizeof(POINT)); } cItem = (WORD)SendDlgItemMessage(ghWndMain, IDD_DCOMBO, CB_GETCOUNT, 0, 0); // write out last dialed numbers from combo box (write to INI) for(cLastDialed = 1; cLastDialed <= NLASTDIALED; ++cLastDialed) { if(cLastDialed <= cItem) SendDlgItemMessage( ghWndMain, IDD_DCOMBO, CB_GETLBTEXT, cLastDialed - 1, // it's a zero-based count (LPARAM)szNumber); else szNumber[0] = 0; wsprintf(szFieldName, TEXT("Last dialed %d"), cLastDialed); RegSetValueEx (hKey, szFieldName, 0, REG_SZ, (LPBYTE)szNumber, (lstrlen(szNumber)+1)*sizeof(TCHAR)); } RegCloseKey (hKey); WinHelp(ghWndMain, gszHELPfilename, HELP_QUIT, 0); // unload help DestroyWindow(ghWndMain); ghWndMain = NULL; } //*************************************************************************** //*************************************************************************** //*************************************************************************** // unregister and line close VOID CloseTAPI(VOID) { // unregister as call manager lineRegisterRequestRecipient ( ghLineApp, 0, // registration instance LINEREQUESTMODE_MAKECALL, FALSE ); if ( gCurrentLineInfo.hLine ) { lineClose ( gCurrentLineInfo.hLine ); gfCurrentLineAvail = FALSE; gCurrentLineInfo.hLine = 0; } lineShutdown(ghLineApp); } //*************************************************************************** //*************************************************************************** //*************************************************************************** INT_PTR CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static HICON hIcon; static const DWORD aMenuHelpIDs[] = { IDD_DSPEEDDIALGRP, (DWORD)-1, IDD_DNUMTODIAL, IDH_DIALER_DIAL_NUMBER, IDD_DCOMBO, IDH_DIALER_DIAL_NUMBER, IDD_DDIAL, IDH_DIALER_DIAL_BUTTON, IDD_DSPEEDDIAL1, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIAL2, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIAL3, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIAL4, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIAL5, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIAL6, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIAL7, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIAL8, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIALTEXT1, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIALTEXT2, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIALTEXT3, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIALTEXT4, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIALTEXT5, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIALTEXT6, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIALTEXT7, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DSPEEDDIALTEXT8, IDH_DIALER_DIAL_SPEED_CHOOSE, IDD_DBUTTON1, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTON2, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTON3, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTON4, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTON5, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTON6, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTON7, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTON8, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTON9, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTONSTAR, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTON0, IDH_DIALER_DIAL_KEYPAD, IDD_DBUTTONPOUND, IDH_DIALER_DIAL_KEYPAD, 0, 0 }; switch (msg) { case WM_INITDIALOG: hIcon = LoadIcon( ghInst, MAKEINTRESOURCE( IDI_DIALER ) ); return TRUE; case WM_SYSCOMMAND: switch( (DWORD) wParam ) { case SC_CLOSE: PostQuitMessage(0); } break; // processes clicks on controls when // context mode help is selected case WM_HELP: WinHelp ( ( (LPHELPINFO) lParam)->hItemHandle, gszHELPfilename, HELP_WM_HELP, (ULONG_PTR) aMenuHelpIDs ); return TRUE; // processes right-clicks on controls case WM_CONTEXTMENU: WinHelp ( (HWND)wParam, gszHELPfilename, HELP_CONTEXTMENU, (ULONG_PTR)aMenuHelpIDs ); return TRUE; case WM_INITMENUPOPUP: // if edit menu if ( LOWORD(lParam) == 1 ) { UINT wEnable; if ( GetParent( GetFocus() ) != GetDlgItem( ghWndMain, IDD_DCOMBO ) ) { wEnable = MF_GRAYED; } else { LRESULT lSelect = SendDlgItemMessage ( ghWndMain, IDD_DCOMBO, CB_GETEDITSEL, 0, 0 ); if ( HIWORD( lSelect ) != LOWORD( lSelect ) ) wEnable = MF_ENABLED; else wEnable = MF_GRAYED; } EnableMenuItem((HMENU)wParam, IDM_EDIT_CUT, wEnable); EnableMenuItem((HMENU)wParam, IDM_EDIT_COPY, wEnable); EnableMenuItem((HMENU)wParam, IDM_EDIT_DELETE, wEnable); // enable paste option is there is data // in the clipboard if ( IsClipboardFormatAvailable( CF_TEXT ) ) { if ( GetClipboardData ( CF_TEXT ) ) { wEnable = MF_ENABLED; } else { wEnable = MF_GRAYED; } } else { wEnable = MF_GRAYED; } } break; case WM_COMMAND: { TCHAR szName[TAPIMAXCALLEDPARTYSIZE] = {0}; TCHAR szNumber[TAPIMAXDESTADDRESSSIZE] = {TEXT('\0')}; switch( LOWORD( (DWORD)wParam ) ) { // FILE menu case IDM_EXIT: PostQuitMessage(0); return TRUE; // EDIT menu case IDM_EDIT_CUT: SendDlgItemMessage(ghWndMain, IDD_DCOMBO, WM_CUT, 0, 0); return TRUE; case IDM_EDIT_COPY: SendDlgItemMessage(ghWndMain, IDD_DCOMBO, WM_COPY, 0, 0); return TRUE; case IDM_EDIT_PASTE: SendDlgItemMessage(ghWndMain, IDD_DCOMBO, WM_PASTE, 0, 0); return TRUE; case IDM_EDIT_DELETE: SendDlgItemMessage(ghWndMain, IDD_DCOMBO, WM_CLEAR, 0, 0); return TRUE; case IDM_EDIT_SPEEDDIAL: DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_SD1), ghWndMain, SpeedDial1Proc, 0 ); SetFocus(GetDlgItem(ghWndMain, IDD_DDIAL)); return TRUE; // TOOLS menu case IDM_CONNECTUSING: DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_CONNECTUSING), ghWndMain, ConnectUsingProc, MENU_CHOICE ); return TRUE; case IDM_LOCATION: { TCHAR szCanNumber[ TAPIMAXDESTADDRESSSIZE ] = TEXT(""); // fetch the number to be dialed if ( GetDlgItemText ( ghWndMain, IDD_DCOMBO, szNumber, TAPIMAXDESTADDRESSSIZE ) ) { // if a number exists, convert it to // its canonical form. if ( !MakeCanonicalNumber ( szNumber, szCanNumber ) ) { lstrcpy( szCanNumber, szNumber ); } } lineTranslateDialog ( ghLineApp, 0, TAPI_CURRENT_VERSION, ghWndMain, szCanNumber ); return TRUE; } // HELP menu case IDM_HELP_CONTENTS: WinHelp(ghWndMain, gszHELPfilename, HELP_CONTENTS, 0); return TRUE; case IDM_HELP_WHATSTHIS: PostMessage(ghWndMain, WM_SYSCOMMAND, SC_CONTEXTHELP, 0); return TRUE; case IDM_ABOUT: #ifdef SDKRELEASE DialogBoxParam( ghInst, MAKEINTRESOURCE(IDD_ABOUT), ghWndMain, AboutProc, 0 ); #else ShellAbout( ghWndMain, gszAppName, gszNULL, LoadIcon(ghInst, MAKEINTRESOURCE(IDI_DIALER)) ); #endif return TRUE; // Accelerator processing case IDM_ACCEL_NUMTODIAL: if(GetActiveWindow() == ghWndMain) SetFocus(GetDlgItem(ghWndMain, IDD_DCOMBO)); return TRUE; // Buttons case IDD_DDIAL: { DWORD cSDEntry; TCHAR szSDNumber[TAPIMAXDESTADDRESSSIZE]; TCHAR szFieldName[MAXBUFSIZE]; HKEY hKey = NULL; DWORD dwSize; // check if number entered is dialable if ( SendMessage ( GetDlgItem(ghWndMain, IDD_DCOMBO), WM_GETTEXTLENGTH, 0, 0 ) > 0 ) { // get the number to be dialed GetDlgItemText ( ghWndMain, IDD_DCOMBO, szNumber, TAPIMAXDESTADDRESSSIZE ); // check if it is a speed dial number. // If so choose the name to be displayed. RegOpenKeyEx (DIALER_REGISTRY_ROOT, DIALER_REGISTRY_PATH, 0, KEY_READ, &hKey); for( cSDEntry = 1; cSDEntry <= NSPEEDDIALS; ++cSDEntry) { wsprintf(szFieldName, TEXT("Number%d"), cSDEntry); dwSize = sizeof (szSDNumber); if (ERROR_SUCCESS == RegQueryValueEx (hKey, szFieldName, NULL, NULL, (LPBYTE)szSDNumber, &dwSize)) { if ( lstrcmp(szSDNumber, szNumber) == 0 ) { wsprintf( szFieldName, TEXT("Name%d"), cSDEntry); dwSize = sizeof (szName); RegQueryValueEx (hKey, szFieldName, NULL, NULL, (LPBYTE)szName, &dwSize); break; } } } RegCloseKey (hKey); SetFocus( GetDlgItem( ghWndMain, IDD_DDIAL ) ); // once the currentline has been set // using the connect proc // the user must hit dial again if ( giCurrentLine == (DWORD)-1 ) { DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_CONNECTUSING), ghWndMain, ConnectUsingProc, INVALID_LINE ); } else { AddToRedialList(szNumber); InitiateCall(szNumber, szName); } } return TRUE; } case IDD_DBUTTON1: case IDD_DBUTTON2: case IDD_DBUTTON3: case IDD_DBUTTON4: case IDD_DBUTTON5: case IDD_DBUTTON6: case IDD_DBUTTON7: case IDD_DBUTTON8: case IDD_DBUTTON9: case IDD_DBUTTON0: case IDD_DBUTTONSTAR: case IDD_DBUTTONPOUND: { int i; TCHAR szBuffer[TAPIMAXDESTADDRESSSIZE+1]; static const TCHAR digits[] = { TEXT('1'), TEXT('2'), TEXT('3'), TEXT('4'), TEXT('5'), TEXT('6'), TEXT('7'), TEXT('8'), TEXT('9'), TEXT('0'), TEXT('*'), TEXT('#') }; i = (int)SendDlgItemMessage(ghWndMain, IDD_DCOMBO, WM_GETTEXT, (WPARAM)TAPIMAXDESTADDRESSSIZE+1, (LPARAM)szBuffer); if (i < TAPIMAXDESTADDRESSSIZE) { MoveMemory(szBuffer+gdwStartSel+1, szBuffer+gdwEndSel, (i - ( gdwEndSel ) + 1)*sizeof(TCHAR) ); szBuffer[gdwStartSel] = digits[LOWORD(wParam) - IDD_DBUTTON1]; SendDlgItemMessage(ghWndMain, IDD_DCOMBO, WM_SETTEXT, 0, (LPARAM)szBuffer); gdwStartSel++; gdwEndSel = gdwStartSel; } SetFocus(GetDlgItem(ghWndMain, IDD_DDIAL)); EnableWindow(GetDlgItem(ghWndMain, IDD_DDIAL), TRUE); return TRUE; } case IDD_DCOMBO: if (HIWORD(wParam) == CBN_SELENDOK) { EnableWindow( GetDlgItem(ghWndMain, IDD_DDIAL), TRUE ); } if ((HIWORD(wParam) == CBN_SELENDOK) || (HIWORD(wParam) == CBN_SELENDCANCEL)) { (DWORD)SendDlgItemMessage(ghWndMain, IDD_DCOMBO, CB_GETEDITSEL, (WPARAM)&gdwStartSel, (LPARAM)&gdwEndSel); return FALSE; } if ( HIWORD( wParam ) == CBN_EDITCHANGE ) { EnableWindow ( GetDlgItem( ghWndMain, IDD_DDIAL ), (BOOL) GetWindowTextLength ( GetDlgItem ( ghWndMain, IDD_DCOMBO ) ) ); return TRUE; } break; case IDD_DSPEEDDIAL1: case IDD_DSPEEDDIAL2: case IDD_DSPEEDDIAL3: case IDD_DSPEEDDIAL4: case IDD_DSPEEDDIAL5: case IDD_DSPEEDDIAL6: case IDD_DSPEEDDIAL7: case IDD_DSPEEDDIAL8: { DWORD cSDEntry = LOWORD( (DWORD) wParam) - IDD_DSPEEDDIAL1 + 1; TCHAR szFieldName [MAXBUFSIZE]; TCHAR szNum[TAPIMAXDESTADDRESSSIZE] ={0}; TCHAR *p; HKEY hKey = NULL; DWORD dwSize; // get information for the speed dial button // from the INI file RegOpenKeyEx (DIALER_REGISTRY_ROOT, DIALER_REGISTRY_PATH, 0, KEY_READ, &hKey); wsprintf(szFieldName, TEXT("Name%d"), cSDEntry); dwSize = sizeof (szName); RegQueryValueEx (hKey, szFieldName, NULL, NULL, (LPBYTE)szName, &dwSize); wsprintf(szFieldName, TEXT("%s%d"), TEXT("Number"), cSDEntry); dwSize = sizeof (szNum);//gszSDNumber[cSDEntry]); RegQueryValueEx (hKey, szFieldName, NULL, NULL, (LPBYTE)szNum, &dwSize); RegCloseKey (hKey); for (p = szNum; *p == TEXT(' '); p++); lstrcpyn (gszSDNumber[cSDEntry], p, sizeof(gszSDNumber[cSDEntry])/sizeof(TCHAR)); // entry not set yet if( gszSDNumber[cSDEntry][0] == 0 ) { DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_SD2), ghWndMain, SpeedDial2Proc, MAKELPARAM(wParam,0) ); } // no line open // once the currentline has been set // using the connect proc // the user must hit dial again else if ( giCurrentLine == (DWORD)-1) { DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_CONNECTUSING), ghWndMain, ConnectUsingProc, INVALID_LINE ); } // entry is set and valid voice line is open else { // add number to list box combo. AddToRedialList( gszSDNumber[cSDEntry] ); InitiateCall( gszSDNumber[cSDEntry], szName ); } break; } } // end switch (LOWORD((DWORD)wParam)) { ... } break; // end case WM_COMMAND } case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(ghWndMain, &ps); if(IsIconic(ghWndMain)) DrawIcon(ps.hdc, 0, 0, hIcon); else { HBRUSH hBrush; hBrush = GetSysColorBrush( COLOR_3DFACE ); // FillRect(ps.hdc, &ps.rcPaint, GetStockObject(LTGRAY_BRUSH)); FillRect(ps.hdc, &ps.rcPaint, hBrush); } EndPaint(ghWndMain, &ps); return TRUE; } case WM_CTLCOLORLISTBOX: case WM_CTLCOLORBTN: case WM_CTLCOLORSTATIC: SetBkColor((HDC)wParam, GetSysColor(COLOR_BTNFACE)); return (INT_PTR)GetSysColorBrush( COLOR_3DFACE ); default: ; // return DefDlgProc( hwnd, msg, wParam, lParam ); // return DefWindowProc( hwnd, msg, wParam, lParam ); } // switch (msg) { ... } return FALSE; } //*************************************************************************** //*************************************************************************** //*************************************************************************** VOID AddToRedialList( LPCTSTR szNumber ) { // NLASTDIALED == 10 WORD cNum; HWND hWndCombo = GetDlgItem(ghWndMain, IDD_DCOMBO); DWORD nMatch; // if valid number if ( szNumber[0] ) { // if list box has entries, check if this number // is already present. If so delete old entry cNum = (WORD) SendMessage(hWndCombo, CB_GETCOUNT, 0, 0); if ( cNum != 0 ) { nMatch = (int)SendMessage ( hWndCombo, CB_FINDSTRING, 0, (LPARAM)szNumber ); if ( nMatch != CB_ERR ) { SendMessage(hWndCombo, CB_DELETESTRING, nMatch, 0); } else { // if the list is full, remove oldest if ( cNum == NLASTDIALED ) { SendMessage( hWndCombo, CB_DELETESTRING, NLASTDIALED - 1, 0 ); } } } SendMessage(hWndCombo, CB_INSERTSTRING, 0, (LPARAM)szNumber); SendMessage(hWndCombo, CB_SETCURSEL, 0, 0L); EnableWindow ( GetDlgItem( ghWndMain, IDD_DDIAL ), TRUE ); } } //*************************************************************************** //*************************************************************************** //*************************************************************************** VOID InitiateCall ( LPCTSTR szNumber, LPCTSTR szName ) { HLINE hLine = 0; DWORD errCode; // struct size info DWORD dwLTPSize = sizeof ( LINETRANSLATEOUTPUT ); DWORD dwNameLen = lstrlen( szName ) + 1; DWORD dwLCPSize = sizeof( LINECALLPARAMS ); LPLINETRANSLATEOUTPUT lpTransOut = NULL; LPLINECALLPARAMS lpLineCallParams = NULL; TCHAR szCanNumber[ TAPIMAXDESTADDRESSSIZE ]; // Open a line errCode = lineOpen ( ghLineApp, giCurrentLine, &hLine, gCurrentLineInfo.dwAPIVersion, 0, 0, LINECALLPRIVILEGE_NONE, 0, NULL ); if (errCode) { errString ( ghWndMain, errCode, MB_ICONEXCLAMATION | MB_OK ); goto error; } // call translate address before dialing do { lpTransOut = (LPLINETRANSLATEOUTPUT) DialerAlloc( dwLTPSize ); if ( !lpTransOut ) { errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK ); goto error; } lpTransOut-> dwTotalSize = dwLTPSize; if ( !MakeCanonicalNumber( szNumber, szCanNumber ) ) { lstrcpy( szCanNumber, szNumber ); } errCode = lineTranslateAddress ( ghLineApp, giCurrentLine, gCurrentLineInfo.dwAPIVersion, szCanNumber, 0, 0, lpTransOut ); if ( ((LONG)errCode) < 0 ) { errString( ghWndMain, errCode, MB_ICONEXCLAMATION | MB_OK ); goto error; } if ( lpTransOut-> dwNeededSize <= lpTransOut->dwTotalSize ) { // ok we are done break; } else { dwLTPSize = lpTransOut-> dwNeededSize; DialerFree ( lpTransOut ); lpTransOut = NULL; } } while ( TRUE ); // if number dialed is 911, bring up a warning if ( Is911( lpTransOut) ) { INT nRes = errString ( ghWndMain, ERR_911WARN, MB_ICONSTOP | MB_YESNO ); if ( nRes == IDNO ) { goto error; } } // set call parameters dwLCPSize += dwNameLen + lpTransOut-> dwDisplayableStringSize; lpLineCallParams = (LPLINECALLPARAMS) DialerAlloc( dwLCPSize ); if ( !lpLineCallParams ) { errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK ); goto error; } lpLineCallParams->dwTotalSize = dwLCPSize; lpLineCallParams->dwBearerMode = LINEBEARERMODE_VOICE; lpLineCallParams->dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE; lpLineCallParams->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE; lpLineCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID; lpLineCallParams->dwAddressID = giCurrentAddress; if ( szName[ 0 ] ) { lpLineCallParams->dwCalledPartySize = dwNameLen; lpLineCallParams->dwCalledPartyOffset = sizeof( LINECALLPARAMS ); lstrcpy ((LPTSTR)((char*)lpLineCallParams + sizeof(LINECALLPARAMS)), szName); } lpLineCallParams-> dwDisplayableAddressSize = lpTransOut-> dwDisplayableStringSize; lpLineCallParams-> dwDisplayableAddressOffset = sizeof( LINECALLPARAMS ) + dwNameLen; lstrcpy ( (LPTSTR) ((char*)lpLineCallParams + sizeof(LINECALLPARAMS) + dwNameLen), (LPTSTR) ((char*)lpTransOut + lpTransOut-> dwDisplayableStringOffset) ); // save dialing information // Free old allocs. if ( gszCurrentName ) { DialerFree ( gszCurrentName ); } if ( gszCurrentNumber ) { DialerFree ( gszCurrentNumber ); } // save new stuff gszCurrentName = (LPTSTR) DialerAlloc( dwNameLen*sizeof(TCHAR) ); if ( !gszCurrentName ) { errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK ); goto error; } lstrcpy ( gszCurrentName, szName ); gszCurrentNumber = (LPTSTR) DialerAlloc( lpTransOut->dwDisplayableStringSize); if ( !gszCurrentNumber ) { errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK ); goto error; } lstrcpy ( gszCurrentNumber, (LPTSTR) ((char*)lpTransOut + lpTransOut-> dwDisplayableStringOffset) ); gCurrentLineInfo.hLine = hLine; ghCall = 0; // finally make the call. gMakeCallRequestID = 0; gMakeCallRequestID = lineMakeCall ( hLine, &ghCall, (LPTSTR) ((char*)lpTransOut + lpTransOut-> dwDialableStringOffset), 0, lpLineCallParams ); // async request ID // - the call is going out if ( (LONG) gMakeCallRequestID > 0 ) { gfCurrentLineAvail = FALSE; gfMakeCallReplyPending = TRUE; DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_DIALING), ghWndMain, DialingProc, 0 ); } else { if ( gMakeCallRequestID == LINEERR_CALLUNAVAIL ) { DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_CALLFAILED), ghWndMain, LineInUseProc, 0 ); } else { errString( ghWndMain, gMakeCallRequestID, MB_ICONEXCLAMATION | MB_OK ); } DialerLineClose(); gfCurrentLineAvail = TRUE; } error : if ( lpLineCallParams ) { DialerFree( lpLineCallParams ); } if ( lpTransOut ) { DialerFree( lpTransOut ); } // if makecall did not succeed but line // was opened, close it. if ( ( gMakeCallRequestID <= 0 ) && ( gCurrentLineInfo.hLine ) ) { DialerLineClose (); gfCurrentLineAvail = TRUE; } SetFocus( GetDlgItem( ghWndMain, IDD_DCOMBO ) ); return; } //*************************************************************************** //*************************************************************************** //*************************************************************************** DWORD GetLineInfo ( DWORD iLine, LPLINEINFO lpLineInfo ) { DWORD errCode = 0; DWORD dwNeededSize = 0; LINEEXTENSIONID ExtensionID; LPTSTR pszLineName = NULL; LPLINEDEVCAPS lpDevCaps = NULL; int lineNameLen; errCode = lineNegotiateAPIVersion ( ghLineApp, iLine, TAPI_VERSION_1_0, TAPI_CURRENT_VERSION, &( lpLineInfo->dwAPIVersion ), &ExtensionID ); if ( errCode ) { GetLineInfoFailed( iLine, lpDevCaps, lpLineInfo ); goto error; } dwNeededSize = sizeof( LINEDEVCAPS ); do { lpDevCaps = ( LPLINEDEVCAPS ) DialerAlloc( dwNeededSize ); if ( !lpDevCaps ) { GetLineInfoFailed( iLine, lpDevCaps, lpLineInfo ); errCode = LINEERR_NOMEM; goto error; } lpDevCaps->dwTotalSize = dwNeededSize; errCode = lineGetDevCaps ( ghLineApp, iLine, lpLineInfo->dwAPIVersion, 0, lpDevCaps ); if ( errCode ) { GetLineInfoFailed( iLine, lpDevCaps, lpLineInfo ); goto error; } if ( lpDevCaps-> dwNeededSize <= lpDevCaps-> dwTotalSize ) { break; } dwNeededSize = lpDevCaps->dwNeededSize; DialerFree( lpDevCaps ); lpDevCaps = NULL; } while ( TRUE ); lpLineInfo->nAddr = lpDevCaps->dwNumAddresses; lpLineInfo->fVoiceLine = ( (lpDevCaps->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE) != 0 ); pszLineName = (LPTSTR) DialerAlloc( MAXBUFSIZE*sizeof(TCHAR) ); if ( !pszLineName ) { errCode = LINEERR_NOMEM; goto error; } if ( lpDevCaps->dwLineNameSize > 0 ) { lineNameLen = 1 + (lpDevCaps->dwLineNameSize / sizeof (TCHAR)); if (lineNameLen > MAXBUFSIZE) { lstrcpyn ( pszLineName, (LPTSTR) ((char*)lpDevCaps + lpDevCaps->dwLineNameOffset), MAXBUFSIZE ); } else { lstrcpyn ( pszLineName, (LPTSTR) ((char*)lpDevCaps + lpDevCaps->dwLineNameOffset), lineNameLen); } } else { wsprintf ( pszLineName, TEXT("Line %d"), iLine ); } lstrcpy( lpLineInfo->szLineName, pszLineName ); lpLineInfo->dwPermanentLineID = lpDevCaps->dwPermanentLineID; error: if ( lpDevCaps ) DialerFree( lpDevCaps ); if ( pszLineName ) DialerFree( pszLineName ); return errCode; } //*************************************************************************** //*************************************************************************** //*************************************************************************** VOID GetLineInfoFailed ( DWORD iLine, LPLINEDEVCAPS lpDevCaps, LPLINEINFO lpLineInfo ) { if ( lpDevCaps ) DialerFree(lpDevCaps); lpLineInfo->nAddr = 0; lpLineInfo->fVoiceLine = FALSE; lpLineInfo->dwAPIVersion = 0; lpLineInfo->hLine = (HLINE)0; lpLineInfo->dwPermanentLineID = 0; lpLineInfo->szLineName[0] = 0; } //*************************************************************************** //*************************************************************************** //*************************************************************************** LPTSTR GetAddressName(DWORD iLine, DWORD iAddress) { DWORD errCode = 0; DWORD dwNeededSize = 0; LPTSTR pszAddressName = NULL; LPLINEADDRESSCAPS lpAddressCaps = NULL; // allocate space for lineGetAddressCaps data dwNeededSize = sizeof( LINEADDRESSCAPS ); do { lpAddressCaps = ( LPLINEADDRESSCAPS )DialerAlloc( dwNeededSize ); if ( !lpAddressCaps ) { goto error; } lpAddressCaps->dwTotalSize = dwNeededSize; errCode = lineGetAddressCaps ( ghLineApp, iLine, iAddress, gCurrentLineInfo.dwAPIVersion, 0, lpAddressCaps ); if ( errCode ) { errString (NULL, errCode, MB_ICONSTOP | MB_OK ); goto error; } if ( lpAddressCaps-> dwNeededSize <= lpAddressCaps-> dwTotalSize ) { break; } dwNeededSize = lpAddressCaps->dwNeededSize; DialerFree( lpAddressCaps ); lpAddressCaps = NULL; } while( TRUE ); // get the address name pszAddressName = DialerAlloc( MAXBUFSIZE * sizeof(TCHAR)); if ( !pszAddressName ) { goto error; } if ( lpAddressCaps-> dwAddressSize > 0 ) { // keep string length bounded if ( lpAddressCaps-> dwAddressSize > (MAXBUFSIZE - 1 ) ) { lstrcpyn( pszAddressName, (LPTSTR) ((char*)lpAddressCaps + lpAddressCaps->dwAddressOffset), MAXBUFSIZE ); pszAddressName[ MAXBUFSIZE - 1] = '\0'; } else { lstrcpy ( pszAddressName, (LPTSTR) ((char*)lpAddressCaps + lpAddressCaps->dwAddressOffset) ); } } else // use default name { wsprintf(pszAddressName, TEXT("Address %d"), iAddress); } error: if ( lpAddressCaps ) { DialerFree( lpAddressCaps ); } return pszAddressName; } //*************************************************************************** //*************************************************************************** //*************************************************************************** INT_PTR CALLBACK DialingProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { TCHAR szTemp[ TAPIMAXCALLEDPARTYSIZE ]; case WM_INITDIALOG: // set global handle to window ghWndDialing = hwnd; AmpersandCompensate( gszCurrentName, szTemp ); SetDlgItemText(hwnd, IDD_DGNUMBERTEXT, gszCurrentNumber); SetDlgItemText(hwnd, IDD_DGNAMETEXT, szTemp ); break; case WM_COMMAND: switch ( LOWORD( (DWORD)wParam ) ) { // hang up case IDCANCEL: // if lineMakeCall has completed // only then drop call. if (!gfMakeCallReplyPending && ghCall ) { if ( ( gDropCallRequestID = lineDrop ( ghCall, NULL, 0 ) ) < 0 ) { errString ( ghWndDialing, gDropCallRequestID, MB_ICONSTOP | MB_OK ); } } else { DialerLineClose(); gfCurrentLineAvail = TRUE; gfMakeCallReplyPending = FALSE; } ghWndDialing = NULL; EndDialog(hwnd, FALSE); return TRUE; // something else terminated the call // all we have to do is terminate this dialog box case IDOK: ghWndDialing = NULL; EndDialog(hwnd, TRUE); return TRUE; } break; default: ; } return FALSE; } //*************************************************************************** //*************************************************************************** //*************************************************************************** INT_PTR CALLBACK AboutProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_INITDIALOG: { TCHAR sz[MAXBUFSIZE]; TCHAR szLabel[MAXBUFSIZE]; // sets up the version number for Windows GetDlgItemText(hwnd, IDD_ATEXTTITLE, sz, MAXBUFSIZE); wsprintf( szLabel, sz, LOWORD(GetVersion()) & 0xFF, HIBYTE(LOWORD(GetVersion)) == 10 ? 1 : 0 ); SetDlgItemText(hwnd, IDD_ATEXTTITLE, szLabel); return TRUE; } case WM_COMMAND: if(LOWORD((DWORD)wParam) == IDOK) { EndDialog(hwnd, TRUE); return TRUE; } break; } return FALSE; } //*************************************************************************** //*************************************************************************** //*************************************************************************** INT_PTR CALLBACK ConnectUsingProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { static const DWORD aMenuHelpIDs[] = { IDD_CUTEXTLINE, IDH_DIALER_OPTIONS_LINE, IDD_CULISTLINE, IDH_DIALER_OPTIONS_LINE, IDD_CUTEXTADDRESS, IDH_DIALER_OPTIONS_ADDRESS, IDD_CULISTADDRESS, IDH_DIALER_OPTIONS_ADDRESS, IDD_CUSIMPLETAPICHKBOX, IDH_DIALER_OPTIONS_VOICE, IDD_CUPROPERTIES, IDH_DIALER_OPTIONS_PROPERTIES, 0, 0 }; switch(msg) { case WM_HELP: // processes clicks on controls when // context mode help is selected WinHelp ( ((LPHELPINFO)lParam)->hItemHandle, gszHELPfilename, HELP_WM_HELP, (ULONG_PTR)aMenuHelpIDs ); return TRUE; case WM_CONTEXTMENU: // processes right-clicks on controls WinHelp ( (HWND)wParam, gszHELPfilename, HELP_CONTEXTMENU, (ULONG_PTR)aMenuHelpIDs ); return TRUE; case WM_INITDIALOG: { BOOL fEnable; DWORD dwPriority; // // Is there any point in even showing this dialog box? if ( gnAvailDevices == 0 ) { // Nope. Let's tell the user what we don't like. errString ( ghWndMain, ERR_NOLINES, MB_ICONEXCLAMATION | MB_OK ); EndDialog(hwnd, FALSE); return TRUE; } // if not brought up by InitializeTAPI() if ( lParam != INVALID_LINE ) { // hide error text EnableWindow( GetDlgItem( hwnd, IDD_CUERRORTEXT ), FALSE ); } // get list of lines into the line list box. fEnable = InitializeLineBox( GetDlgItem(hwnd, IDD_CULISTLINE) ); EnableWindow( GetDlgItem( hwnd, IDD_CULISTLINE ), fEnable); // get list of addresses into the address list box. fEnable = fEnable && InitializeAddressBox ( GetDlgItem(hwnd, IDD_CULISTLINE), GetDlgItem(hwnd, IDD_CULISTADDRESS) ); EnableWindow( GetDlgItem( hwnd, IDD_CULISTADDRESS ), fEnable ); EnableWindow( GetDlgItem( hwnd, IDOK ), fEnable ); EnableWindow( GetDlgItem( hwnd, IDD_CUPROPERTIES ), fEnable ); lineGetAppPriority ( TEXT("DIALER.EXE"), 0, // checking app priority for Assisted Telephony requests NULL, LINEREQUESTMODE_MAKECALL, NULL, &dwPriority ); CheckDlgButton(hwnd, IDD_CUSIMPLETAPICHKBOX, (dwPriority == 1)); // if dwPriority == 1, we're supporting Assisted Telephony AND // have the highest priority. EnableWindow ( GetDlgItem(hwnd, IDD_CUSIMPLETAPICHKBOX), gfRegistered ); return FALSE; } case WM_COMMAND: { switch ( LOWORD( (DWORD)wParam ) ) { case IDD_CULISTLINE: if ( HIWORD( wParam ) == CBN_SELENDOK ) // update address box InitializeAddressBox ( GetDlgItem(hwnd, IDD_CULISTLINE), GetDlgItem(hwnd, IDD_CULISTADDRESS) ); break; case IDD_CUPROPERTIES: { HWND hW = GetDlgItem(hwnd, IDD_CULISTLINE); lineConfigDialog ( // device ID (DWORD) SendMessage ( hW, CB_GETITEMDATA, (WORD) SendMessage(hW, CB_GETCURSEL, 0, 0), 0 ), hwnd, NULL ); break; } case IDOK: { HWND hwndBox; TCHAR szBuffer[MAXBUFSIZE]; DWORD dwPriority; HKEY hKey = NULL; DWORD dwSize; RegCreateKeyEx (DIALER_REGISTRY_ROOT, DIALER_REGISTRY_PATH, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); // Update line hwndBox = GetDlgItem( hwnd, IDD_CULISTLINE ); giCurrentLine = (int) SendMessage ( hwndBox, CB_GETITEMDATA, SendMessage( hwndBox, CB_GETCURSEL, 0, 0 ), 0 ); // base 10 _itot( gdwPLID[giCurrentLine], szBuffer, 10 ); RegSetValueEx (hKey, TEXT("Preferred Line"), 0, REG_SZ, (LPBYTE)szBuffer, (lstrlen(szBuffer)+1)*sizeof(TCHAR)); // Update address hwndBox = GetDlgItem( hwnd, IDD_CULISTADDRESS ); giCurrentAddress = (int) SendMessage ( hwndBox, CB_GETITEMDATA, SendMessage(hwndBox, CB_GETCURSEL, 0, 0), 0 ); _itot( giCurrentAddress, szBuffer, 10 ); RegSetValueEx (hKey, TEXT("Preferred Address"), 0, REG_SZ, (LPBYTE)szBuffer, (lstrlen(szBuffer)+1)*sizeof(TCHAR)); RegCloseKey (hKey); // Update application priority if ( SendDlgItemMessage ( hwnd, IDD_CUSIMPLETAPICHKBOX, BM_GETCHECK, 0, 0L ) == 0) { dwPriority = 0; } else { dwPriority = 1; } lineSetAppPriority ( TEXT("DIALER.EXE"), 0, NULL, LINEREQUESTMODE_MAKECALL, NULL, dwPriority ); EndDialog(hwnd, TRUE); return TRUE; } case IDCANCEL: EndDialog(hwnd, FALSE); return TRUE; } } default: ; } return FALSE; } //*************************************************************************** //*************************************************************************** //*************************************************************************** INT_PTR CALLBACK LineInUseProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int lNewParam = (int)lParam; PTSTR ptStr; switch(msg) { case WM_INITDIALOG: { switch(lParam) { case LINEDISCONNECTMODE_REJECT: lNewParam = ikszDisconnectedReject; break; case LINEDISCONNECTMODE_BUSY: lNewParam = ikszDisconnectedBusy; break; case LINEDISCONNECTMODE_NOANSWER: lNewParam = ikszDisconnectedNoAnswer; break; case LINEDISCONNECTMODE_CONGESTION: lNewParam = ikszDisconnectedNetwork; break; case LINEDISCONNECTMODE_INCOMPATIBLE: lNewParam = ikszDisconnectedIncompatible; break; case LINEDISCONNECTMODE_NODIALTONE: lNewParam = ikszDisconnectedNoDialTone; break; default: lNewParam = ikszDisconnectedCantDo; break; } ptStr = DialerAlloc( MAXBUFSIZE*sizeof(TCHAR) ); LoadString( ghInst, lNewParam, ptStr, MAXBUFSIZE ); SetDlgItemText (hwnd, IDD_CFTEXT, ptStr); DialerFree( ptStr ); return TRUE; } case WM_COMMAND: if(LOWORD((DWORD)wParam) == IDOK) { EndDialog(hwnd, TRUE); return TRUE; } break; } return FALSE; } //*************************************************************************** //*************************************************************************** //*************************************************************************** INT_PTR CALLBACK SpeedDial1Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static DWORD nCurrentSpeedDial; static const DWORD aMenuHelpIDs[] = { IDOK, IDH_DIALER_SPEED_SAVE, IDD_SD1SPEEDDIAL1, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIAL2, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIAL3, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIAL4, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIAL5, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIAL6, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIAL7, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIAL8, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIALTEXT1, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIALTEXT2, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIALTEXT3, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIALTEXT4, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIALTEXT5, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIALTEXT6, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIALTEXT7, IDH_DIALER_BUTTONS, IDD_SD1SPEEDDIALTEXT8, IDH_DIALER_BUTTONS, IDD_SD1TEXTNAME, IDH_DIALER_SPEED_NAME, IDD_SD1EDITNAME, IDH_DIALER_SPEED_NAME, IDD_SD1TEXTNUMBER, IDH_DIALER_SPEED_NUMBER, IDD_SD1EDITNUMBER, IDH_DIALER_SPEED_NUMBER, IDD_SD1TEXTCHOOSE, (DWORD)-1, IDD_SD1TEXTENTER, (DWORD)-1, 0, 0 }; // buffer to store speed dial names till they are saved. static TCHAR szSDName[NSPEEDDIALS + 1][TAPIMAXCALLEDPARTYSIZE] = {0}; switch(msg) { case WM_HELP: // processes clicks on controls when // context mode help is selected WinHelp( ((LPHELPINFO)lParam)->hItemHandle, gszHELPfilename, HELP_WM_HELP, (ULONG_PTR)aMenuHelpIDs ); return TRUE; case WM_CONTEXTMENU: // processes right-clicks on controls WinHelp( (HWND)wParam, gszHELPfilename, HELP_CONTEXTMENU, (ULONG_PTR)aMenuHelpIDs ); return TRUE; case WM_INITDIALOG: { DWORD cSDEntry; DWORD idFirstEmpty = (DWORD) -1; TCHAR szName[TAPIMAXCALLEDPARTYSIZE] = {0}; TCHAR szTemp[TAPIMAXCALLEDPARTYSIZE]; TCHAR szFieldName[MAXBUFSIZE]; HKEY hKey = NULL; DWORD dwSize; // Retrieve speed dial info from INI file RegOpenKeyEx (DIALER_REGISTRY_ROOT, DIALER_REGISTRY_PATH, 0, KEY_READ, &hKey); for(cSDEntry = 1; cSDEntry <= NSPEEDDIALS; ++cSDEntry) { wsprintf(szFieldName, TEXT("Name%d"), cSDEntry); dwSize = sizeof (szSDName[ cSDEntry ]); RegQueryValueEx (hKey, szFieldName, NULL, NULL, (LPBYTE)szSDName[cSDEntry], &dwSize); // set the first empty speed dial button if ( idFirstEmpty == -1 && szSDName[ cSDEntry ][0] == '\0' && gszSDNumber[ cSDEntry ][ 0 ] == '\0' ) idFirstEmpty = cSDEntry; wsprintf(szFieldName, TEXT("Number%d"), cSDEntry); dwSize = sizeof (gszSDNumber[cSDEntry]); RegQueryValueEx (hKey, szFieldName, NULL, NULL, (LPBYTE)gszSDNumber[cSDEntry], &dwSize); // get a copy of the name for editing // if name is empty, use the number as the // name. if (0 != szSDName[ cSDEntry][0]) { lstrcpyn( szName, szSDName[ cSDEntry], sizeof(szName)/sizeof(szName[0])); } else { lstrcpyn( szName, gszSDNumber[ cSDEntry ], sizeof(szName)/sizeof(szName[0]) ); } FitTextToButton( hwnd, IDD_SD1SPEEDDIAL1 + cSDEntry - 1, szName ); AmpersandCompensate( szName, szTemp ); SetDlgItemText ( hwnd, IDD_SD1SPEEDDIAL1 + cSDEntry - 1, (LPCTSTR) szTemp ); } RegCloseKey (hKey); // for the edit speed dial dialog // limit the lengths of text SendDlgItemMessage ( hwnd, IDD_SD1EDITNAME, EM_LIMITTEXT, (WPARAM)(TAPIMAXCALLEDPARTYSIZE - 1), 0 ); SendDlgItemMessage ( hwnd, IDD_SD1EDITNUMBER, EM_LIMITTEXT, (WPARAM)(TAPIMAXDESTADDRESSSIZE - 1), 0 ); // select the first empty button // nothing empty, then edit #1 if ( -1 == idFirstEmpty ) { nCurrentSpeedDial = 1; SetDlgItemText( hwnd, IDD_SD1EDITNAME, (LPCTSTR) szSDName[ 1 ] ); SetDlgItemText( hwnd, IDD_SD1EDITNUMBER, (LPCTSTR) gszSDNumber[ 1 ] ); } else { nCurrentSpeedDial = idFirstEmpty; } SetFocus( GetDlgItem( hwnd, IDD_SD1EDITNAME ) ); return FALSE; } case WM_COMMAND: { TCHAR szName[TAPIMAXCALLEDPARTYSIZE]; TCHAR szTemp[ TAPIMAXCALLEDPARTYSIZE ]; switch( LOWORD( (DWORD) wParam ) ) { case IDOK: { DWORD cSDEntry; TCHAR szFieldName[MAXBUFSIZE]; HKEY hKey = NULL; // save new speed dial settings RegCreateKeyEx (DIALER_REGISTRY_ROOT, DIALER_REGISTRY_PATH, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); for ( cSDEntry = 1; cSDEntry <= NSPEEDDIALS; ++cSDEntry ) { wsprintf(szFieldName, TEXT("Name%d"), cSDEntry); RegSetValueEx (hKey, szFieldName, 0, REG_SZ, (LPBYTE)(szSDName[cSDEntry]), (lstrlen(szSDName[cSDEntry])+1)*sizeof(TCHAR)); wsprintf(szFieldName, TEXT("Number%d"), cSDEntry); RegSetValueEx (hKey, szFieldName, 0, REG_SZ, (LPBYTE)(gszSDNumber[cSDEntry]), (lstrlen(gszSDNumber[cSDEntry])+1)*sizeof(TCHAR)); // set the text for the corresponding // main window button if ( szSDName[ cSDEntry ][ 0 ] == TEXT('\0') ) { lstrcpyn( szName, gszSDNumber[ cSDEntry ], sizeof(szName)/sizeof(szName[0]) ); } else { lstrcpyn( szName, szSDName[ cSDEntry ], sizeof(szName)/sizeof(szName[0]) ); } FitTextToButton( ghWndMain, IDD_DSPEEDDIAL1 + cSDEntry - 1, szName ); AmpersandCompensate( szName, szTemp ); SetDlgItemText ( ghWndMain, IDD_DSPEEDDIAL1 + cSDEntry - 1, (LPCTSTR) szTemp ); } RegCloseKey (hKey); EndDialog(hwnd, TRUE); return TRUE; } case IDCANCEL: EndDialog(hwnd, FALSE); return TRUE; case IDD_SD1SPEEDDIAL1: case IDD_SD1SPEEDDIAL2: case IDD_SD1SPEEDDIAL3: case IDD_SD1SPEEDDIAL4: case IDD_SD1SPEEDDIAL5: case IDD_SD1SPEEDDIAL6: case IDD_SD1SPEEDDIAL7: case IDD_SD1SPEEDDIAL8: nCurrentSpeedDial = LOWORD( (DWORD) wParam ) - IDD_SD1SPEEDDIAL1 + 1; SetDlgItemText ( hwnd, IDD_SD1EDITNAME, szSDName [ nCurrentSpeedDial ] ); SetDlgItemText ( hwnd, IDD_SD1EDITNUMBER, gszSDNumber[nCurrentSpeedDial] ); SetFocus( GetDlgItem( hwnd, IDD_SD1EDITNAME ) ); SendDlgItemMessage( hwnd, IDD_SD1EDITNAME, EM_SETSEL, 0, MAKELPARAM(0, -1) ); break; case IDD_SD1EDITNAME: if ( HIWORD( wParam ) == EN_CHANGE ) { TCHAR *p; GetDlgItemText ( hwnd, IDD_SD1EDITNAME, szName, TAPIMAXCALLEDPARTYSIZE ); for (p = szName; *p == TEXT(' '); p++); // if there is no name, label the button with // the number if ( *p == TEXT('\0') ) { szSDName[ nCurrentSpeedDial ][ 0 ] = TEXT('\0'); lstrcpyn( szName, gszSDNumber[ nCurrentSpeedDial ], sizeof(szName)/sizeof(szName[0]) ); p = szName; } else { lstrcpy( szSDName[ nCurrentSpeedDial ], p ); } FitTextToButton ( hwnd, IDD_SD1SPEEDDIAL1 + nCurrentSpeedDial - 1, szName ); AmpersandCompensate( p, szTemp ); SetDlgItemText ( hwnd, IDD_SD1SPEEDDIAL1 + nCurrentSpeedDial - 1, szTemp ); } break; case IDD_SD1EDITNUMBER: if ( HIWORD( wParam ) == EN_CHANGE ) { GetDlgItemText ( hwnd, IDD_SD1EDITNUMBER, gszSDNumber[nCurrentSpeedDial], TAPIMAXDESTADDRESSSIZE ); if ( gszSDNumber[ nCurrentSpeedDial ][ 0 ] == '\0' ) { GetDlgItemText ( hwnd, IDD_SD1EDITNAME, szName, TAPIMAXDESTADDRESSSIZE ); if ( szName[ 0 ] == TEXT('\0') ) { SetDlgItemText ( hwnd, IDD_SD1SPEEDDIAL1 + nCurrentSpeedDial - 1, szName ); } } } break; } // switch(LOWORD((DWORD)wParam)) break; } // case WM_COMMAND: default: ; } // switch(msg) return FALSE; } //*************************************************************************** //*************************************************************************** //*************************************************************************** INT_PTR CALLBACK SpeedDial2Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static DWORD nCurrentSpeedDial; static const DWORD aMenuHelpIDs[] = { IDOK, IDH_DIALER_SPEED_SAVE, IDD_SD2SAVEANDDIAL, IDH_DIALER_SPEED_SAVE_DIAL, IDD_SD2TEXTNAME, IDH_DIALER_SPEED_NAME, IDD_SD2EDITNAME, IDH_DIALER_SPEED_NAME, IDD_SD2TEXTNUMBER, IDH_DIALER_SPEED_NUMBER, IDD_SD2EDITNUMBER, IDH_DIALER_SPEED_NUMBER, 0, 0 }; switch(msg) { case WM_HELP: // processes clicks on controls when // context mode help is selected WinHelp ( ((LPHELPINFO)lParam)->hItemHandle, gszHELPfilename, HELP_WM_HELP, (ULONG_PTR)aMenuHelpIDs ); return TRUE; case WM_CONTEXTMENU: // processes right-clicks on controls WinHelp ( (HWND)wParam, gszHELPfilename, HELP_CONTEXTMENU, (ULONG_PTR)aMenuHelpIDs ); return TRUE; case WM_INITDIALOG: { TCHAR szFieldName [MAXBUFSIZE]; TCHAR szName [TAPIMAXCALLEDPARTYSIZE] = {0}; HKEY hKey = NULL; DWORD dwSize; nCurrentSpeedDial = LOWORD( lParam ) - IDD_DSPEEDDIAL1 + 1; // retrieve speed dial button info RegOpenKeyEx (DIALER_REGISTRY_ROOT, DIALER_REGISTRY_PATH, 0, KEY_READ, &hKey); wsprintf(szFieldName, TEXT("Name%d"), nCurrentSpeedDial); dwSize = sizeof (szName); RegQueryValueEx (hKey, szFieldName, NULL, NULL, (LPBYTE)szName, &dwSize); RegCloseKey (hKey); SetDlgItemText ( hwnd, IDD_SD2EDITNAME, szName ); SetDlgItemText ( hwnd, IDD_SD2EDITNUMBER, gszSDNumber[nCurrentSpeedDial] ); // limit the lengths of the texts SendDlgItemMessage ( hwnd, IDD_SD2EDITNAME, EM_LIMITTEXT, (WPARAM)(TAPIMAXCALLEDPARTYSIZE - 1), 0 ); SendDlgItemMessage ( hwnd, IDD_SD2EDITNUMBER, EM_LIMITTEXT, (WPARAM)(TAPIMAXDESTADDRESSSIZE - 1), 0 ); SetFocus( GetDlgItem( hwnd, IDD_SD2EDITNAME ) ); SendDlgItemMessage ( hwnd, IDD_SD2EDITNAME, EM_SETSEL, 0, MAKELPARAM(0, -1) ); return FALSE; } case WM_COMMAND: { TCHAR szName[ TAPIMAXDESTADDRESSSIZE ]; TCHAR szTemp[ TAPIMAXCALLEDPARTYSIZE ]; TCHAR szFieldName[MAXBUFSIZE]; TCHAR *p; switch ( LOWORD( (DWORD) wParam ) ) { case IDOK: case IDD_SD2SAVEANDDIAL: { HKEY hKey = NULL; RegCreateKeyEx (DIALER_REGISTRY_ROOT, DIALER_REGISTRY_PATH, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); GetDlgItemText ( hwnd, IDD_SD2EDITNUMBER, (LPTSTR) szName, TAPIMAXDESTADDRESSSIZE ); for (p = szName; *p == TEXT(' '); p++); if (0 == *p) { wsprintf (szFieldName, TEXT("Name%d"), nCurrentSpeedDial); RegDeleteValue (hKey, szFieldName); wsprintf (szFieldName, TEXT("Number%d"), nCurrentSpeedDial); RegDeleteValue (hKey, szFieldName); } else { lstrcpyn (gszSDNumber[nCurrentSpeedDial], p, sizeof(gszSDNumber[nCurrentSpeedDial])/sizeof(TCHAR)); GetDlgItemText ( hwnd, IDD_SD2EDITNAME, szName, TAPIMAXCALLEDPARTYSIZE ); for (p = szName; *p == TEXT(' '); p++); wsprintf ( szFieldName, TEXT("Name%d"), nCurrentSpeedDial ); RegSetValueEx (hKey, szFieldName, 0, REG_SZ, (LPBYTE)p, (lstrlen(p)+1)*sizeof(TCHAR)); wsprintf ( szFieldName, TEXT("Number%d"), nCurrentSpeedDial ); RegSetValueEx (hKey, szFieldName, 0, REG_SZ, (LPBYTE)(gszSDNumber[nCurrentSpeedDial]), (lstrlen(gszSDNumber[nCurrentSpeedDial])+1)*sizeof(TCHAR)); // update main window buttons // is only number has been entered, label button with it. if ( *p == TEXT('\0') ) { lstrcpyn( szName, gszSDNumber[ nCurrentSpeedDial ], sizeof(szName)/sizeof(szName[0]) ); p = szName; } FitTextToButton ( ghWndMain, IDD_DSPEEDDIAL1 + nCurrentSpeedDial - 1, p ); AmpersandCompensate( p, szTemp ); SetDlgItemText ( ghWndMain, IDD_DSPEEDDIAL1 + nCurrentSpeedDial - 1, szTemp ); // if save and dial, then post dial message to main window if ( LOWORD( (DWORD) wParam ) == IDD_SD2SAVEANDDIAL ) { PostMessage ( ghWndMain, WM_COMMAND, MAKEWPARAM ( nCurrentSpeedDial + IDD_DSPEEDDIAL1 - 1, BN_CLICKED ), (LPARAM) GetDlgItem ( ghWndMain, nCurrentSpeedDial + IDD_DSPEEDDIAL1 - 1 ) ); } } RegCloseKey (hKey); EndDialog(hwnd, TRUE); return TRUE; } case IDCANCEL: EndDialog(hwnd, FALSE); return TRUE; case IDD_SD2EDITNAME: case IDD_SD2EDITNUMBER: if ( HIWORD( wParam ) == EN_CHANGE) { EnableWindow ( GetDlgItem( hwnd, IDD_SD2SAVEANDDIAL ), GetWindowTextLength ( GetDlgItem( hwnd, IDD_SD2EDITNUMBER ) ) > 0 ); } break; } // switch(LOWORD((DWORD)wParam)) break; } default: ; } // switch(msg) return FALSE; } //*************************************************************************** //*************************************************************************** //*************************************************************************** VOID CALLBACK tapiCallback ( DWORD hDevice, DWORD dwMsg, DWORD dwCBInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3 ) { switch (dwMsg) { INT errCode; case LINE_ADDRESSSTATE: break; case LINE_CALLINFO: break; case LINE_CALLSTATE: if ( (HCALL)hDevice != ghCall ) return; switch ( dwParam1 ) // new state { case LINECALLSTATE_IDLE: // tell "Dialing" window to terminate if ( ghWndDialing ) { SendMessage ( ghWndDialing, WM_COMMAND, MAKEWPARAM( IDOK, 0 ), 0 ); } // tapi call cleanup if ( !gfMakeCallReplyPending && ghCall ) { if ( ( errCode = lineDeallocateCall( ghCall ) ) < 0 ) { errString ( ghWndMain, errCode, MB_ICONSTOP | MB_OK ); } ghCall = 0; } DialerLineClose(); gfCurrentLineAvail = TRUE; // update main window DisableDialButtons( FALSE ); break; case LINECALLSTATE_BUSY: tapiCallback ( hDevice, dwMsg, dwCBInstance, LINECALLSTATE_DISCONNECTED, LINEDISCONNECTMODE_BUSY, dwParam3 ); break; case LINECALLSTATE_SPECIALINFO: tapiCallback ( hDevice, dwMsg, dwCBInstance, LINECALLSTATE_DISCONNECTED, LINEDISCONNECTMODE_UNREACHABLE, dwParam3 ); break; case LINECALLSTATE_DISCONNECTED: { BOOL fCallOK; DWORD LineDisconnectMode; if ( dwParam2 == 0 ) LineDisconnectMode = LINEDISCONNECTMODE_NORMAL; else LineDisconnectMode = dwParam2; fCallOK = ( LineDisconnectMode == LINEDISCONNECTMODE_NORMAL || LineDisconnectMode == LINEDISCONNECTMODE_UNKNOWN || LineDisconnectMode == LINEDISCONNECTMODE_PICKUP || LineDisconnectMode == LINEDISCONNECTMODE_FORWARDED || LineDisconnectMode == LINEDISCONNECTMODE_UNAVAIL ); if ( !gfMakeCallReplyPending && ghCall ) { //gfDropping = TRUE; if ( ( gDropCallRequestID = lineDrop ( ghCall, NULL, 0 ) ) < 0 ) { errString ( ghWndMain, gDropCallRequestID, MB_ICONSTOP | MB_OK ); } } if ( !fCallOK ) DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_CALLFAILED), ghWndMain, LineInUseProc, LineDisconnectMode ); break; } } break; case LINE_CLOSE: if ( gCurrentLineInfo.hLine == (HLINE)hDevice ) { errString(ghWndMain, ERR_LINECLOSE, MB_ICONEXCLAMATION | MB_OK ); gCurrentLineInfo.hLine = 0; gfCurrentLineAvail = FALSE; DisableDialButtons(FALSE); } break; case LINE_CREATE: // dwParam1 is the new device's ID if ( dwParam1 >= gnAvailDevices ) { DWORD* gnAddrTemp; DWORD iLine; LINEINFO LineInfo; // we record new device's address count. // we are assuming here that we're just adding a new // line and it's sequential and it's the last one gnAvailDevices = dwParam1 + 1; gnAddrTemp = (DWORD *) DialerAlloc ( sizeof(DWORD) * (int)(gnAvailDevices) ); for ( iLine = 0; iLine < (gnAvailDevices-1); ++iLine ) gnAddrTemp[iLine] = gnAddr[iLine]; DialerFree( gnAddr ); // we have effectively added one more // space in the gnAddr array gnAddr = gnAddrTemp; if ( GetLineInfo( dwParam1, &LineInfo ) != ERR_NONE ) break; gnAddr[dwParam1] = LineInfo.nAddr; } break; case LINE_DEVSPECIFIC: break; case LINE_DEVSPECIFICFEATURE: break; case LINE_GATHERDIGITS: break; case LINE_GENERATE: break; case LINE_LINEDEVSTATE: if ( dwParam1 & LINEDEVSTATE_REINIT ) { if(dwParam2 != 0) { // this is another msg translated into REINIT tapiCallback( hDevice, dwParam2, dwCBInstance, dwParam3, 0, 0 ); } else { // Re-initialize TAPI gfNeedToReinit = TRUE; } } if ( dwParam1 & LINEDEVSTATE_REMOVED ) { DialerLineClose(); tapiCallback(hDevice, LINE_CLOSE, dwCBInstance, 0, 0, 0); // is this needed? } break; case LINE_MONITORDIGITS: break; case LINE_MONITORMEDIA: break; case LINE_MONITORTONE: break; // async reply from lineMakeCall() or lineDrop() case LINE_REPLY: // reply for lineMakeCall if ( (LONG) dwParam1 == gMakeCallRequestID ) { // error on make call if ( dwParam2 != ERR_NONE ) { // Get rid of the Dialing Dialog box if it's up if ( ghWndDialing ) { SendMessage( ghWndDialing, WM_COMMAND, MAKEWPARAM(IDOK,0), 0 ); } if ( dwParam2 == LINEERR_CALLUNAVAIL ) { DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_CALLFAILED), ghWndMain, LineInUseProc, 0 ); } else { errString ( ghWndMain, dwParam2, MB_ICONEXCLAMATION | MB_OK ); } ghCall = 0; DialerLineClose(); gfCurrentLineAvail = TRUE; } gfMakeCallReplyPending = FALSE; } // reply from lineDrop() if ( (LONG) dwParam1 == gDropCallRequestID ) { // tell "Dialing" window to terminate if ( ghWndDialing ) { SendMessage ( ghWndDialing, WM_COMMAND, MAKEWPARAM( IDOK,0 ), 0 ); } // tapi call cleanup if ( dwParam2 == ERR_NONE ) { if ( !gfMakeCallReplyPending && ghCall ) { if ( ( errCode = lineDeallocateCall( ghCall ) ) < 0 ) { errString ( ghWndMain, errCode, MB_ICONSTOP | MB_OK ); } ghCall = 0; } } DialerLineClose (); gfCurrentLineAvail = TRUE; } break; case LINE_REQUEST: // Simple TAPI request if ( dwParam1 == LINEREQUESTMODE_MAKECALL ) { gfCallRequest = TRUE; } break; } } //*************************************************************************** //*************************************************************************** //*************************************************************************** BOOL InitializeLineBox(HWND hwndLineBox) { DWORD iLine, iItem, iItemCurrent = (DWORD)-1; DWORD errCode; LPLINEINFO lpLineInfo = NULL; // allocate buffer for storing LINEINFO for all of // the available lines. Always allocate space for // at least one line if ( gnAvailDevices == 0 ) { lpLineInfo = (LPLINEINFO) DialerAlloc( sizeof(LINEINFO) ); } else { lpLineInfo = (LPLINEINFO) DialerAlloc ( sizeof(LINEINFO) * (int)gnAvailDevices ); } // if no space was set aside... if ( lpLineInfo == NULL ) return LINEERR_NOMEM; // fill lpLineInfo[] and open each line for ( iLine = 0; iLine < gnAvailDevices; ++iLine ) { // skip remaining processing for this line if it didn't open if ( GetLineInfo( iLine, &lpLineInfo[iLine] ) != ERR_NONE ) { continue; } iItem = (int) SendMessage ( hwndLineBox, CB_ADDSTRING, 0, (LPARAM)(lpLineInfo[iLine].szLineName) ); // error, bail out. if ( iItem == CB_ERR || iItem == CB_ERRSPACE ) { if (lpLineInfo) { DialerFree(lpLineInfo); } return FALSE; } errCode = (int) SendMessage ( hwndLineBox, CB_SETITEMDATA, (WPARAM)iItem, (LPARAM)iLine ); if ( iLine == giCurrentLine ) { iItemCurrent = iItem; } else if ( iItemCurrent != -1 && iItem <= iItemCurrent ) { // if the item we are putting is before the // "current" item, we must increment iItemCurrent // to reflect that something is being placed before // it, due to sorting ++iItemCurrent; } } if ( iItemCurrent == (DWORD)-1 ) iItemCurrent = 0; if ( SendMessage( hwndLineBox, CB_GETCOUNT, 0, 0) != 0 ) { SendMessage( hwndLineBox, CB_SETCURSEL, (WPARAM)iItemCurrent, 0 ); return TRUE; } DialerFree(lpLineInfo); return FALSE; } //*************************************************************************** //*************************************************************************** //*************************************************************************** BOOL InitializeAddressBox( HWND hwndLineBox, HWND hwndAddressBox ) { DWORD errCode; DWORD iAddress, iItem, iItemCurrent = (DWORD)-1; DWORD iLineBoxCurrent; LPTSTR pszAddressName; if ( SendMessage( hwndLineBox, CB_GETCOUNT, 0, 0 ) == 0 ) { return FALSE; } // select current entry in line box iLineBoxCurrent = (int) SendMessage ( hwndLineBox, CB_GETITEMDATA, SendMessage( hwndLineBox, CB_GETCURSEL, 0, 0 ), 0 ); // empty address list box SendMessage ( hwndAddressBox, CB_RESETCONTENT, 0, 0); // get all the address for this line for ( iAddress = 0; iAddress < gnAddr[iLineBoxCurrent]; ++iAddress ) { pszAddressName = GetAddressName (iLineBoxCurrent, iAddress ); // if this address if fails, try the next one if ( !pszAddressName ) continue; iItem = (int) SendMessage ( hwndAddressBox, CB_ADDSTRING, 0, (LPARAM)pszAddressName ); // error, bail out if ( iItem == CB_ERR || iItem == CB_ERRSPACE ) return FALSE; errCode = (int)SendMessage ( hwndAddressBox, CB_SETITEMDATA, (WPARAM) iItem, (LPARAM) iAddress ); if ( iLineBoxCurrent == giCurrentLine ) { if(iAddress == giCurrentAddress) { iItemCurrent = iItem; } else { // if the item we are putting is before the // "current" item, we must increment iItemCur // to reflect that something is being placed // before it, due to sorting if ( iItemCurrent != -1 && iItem <= iItemCurrent ) { ++iItemCurrent; } } } DialerFree( pszAddressName ); } if ( iLineBoxCurrent != giCurrentLine ) { // if we're not looking at the current line // then highlight address 0 iItemCurrent = 0; } SendMessage ( hwndAddressBox, CB_SETCURSEL, iItemCurrent, 0 ); return TRUE; } //*************************************************************************** //*************************************************************************** //*************************************************************************** VOID ManageAssistedTelephony(VOID) { DWORD errCode; LINEREQMAKECALL *lpRequestBuffer; lpRequestBuffer = (LINEREQMAKECALL*) DialerAlloc( sizeof( LINEREQMAKECALL ) ); if ( !lpRequestBuffer ) { goto error; } // bring window to front SetForegroundWindow(ghWndMain); // get next queued request. errCode = lineGetRequest ( ghLineApp, LINEREQUESTMODE_MAKECALL, lpRequestBuffer ); if ( errCode ) { // if no more call requests pending, reset flag. if ( errCode == LINEERR_NOREQUEST ) { gfCallRequest = FALSE; } else { errString ( ghWndMain, errCode, MB_ICONEXCLAMATION | MB_OK ); } goto error; } // if a line has not been selected if ( giCurrentLine == (DWORD)-1 ) { if (!DialogBoxParam ( ghInst, MAKEINTRESOURCE(IDD_CONNECTUSING), ghWndMain, ConnectUsingProc, INVALID_LINE )) { // failed to get a line goto error; } } // make the reuested call. InitiateCall ( lpRequestBuffer->szDestAddress, lpRequestBuffer->szCalledParty ); error : if ( lpRequestBuffer ) { DialerFree( lpRequestBuffer ); } return; } //*************************************************************************** //*************************************************************************** //*************************************************************************** VOID DialerLineClose() { DWORD errCode; if ( gCurrentLineInfo.hLine ) { if ( errCode = lineClose ( gCurrentLineInfo.hLine ) ) { errString ( ghWndMain, errCode, MB_ICONSTOP | MB_OK ); } gCurrentLineInfo.hLine = 0; } // re-initialize TAPI if it needs to be re-initialized if ( gfNeedToReinit ) { CloseTAPI(); errCode = InitializeTAPI(); if(errCode) { errString(ghWndMain, errCode, MB_APPLMODAL | MB_ICONEXCLAMATION ); DialerCleanup(); // terminate program if we can't init return; } errCode = lineRegisterRequestRecipient ( ghLineApp, 0, LINEREQUESTMODE_MAKECALL, TRUE ); if (errCode) { errString(ghWndMain, errCode, MB_ICONEXCLAMATION | MB_OK ); } gfNeedToReinit = FALSE; } } //*************************************************************************** //*************************************************************************** //*************************************************************************** int errString( HWND hWndOwner, UINT errCode, UINT uFlags ) { PTSTR ptStrTitle; PTSTR ptStrError; int nResult; BOOL bDefault = FALSE; ptStrTitle = DialerAlloc( MAXBUFSIZE*sizeof(TCHAR) ); if ( NULL == ptStrTitle ) { // Now, _this_ is a problem. return 0; } ptStrError = DialerAlloc( MAXBUFSIZE*sizeof(TCHAR) ); if ( NULL == ptStrError ) { // Now, _this_ is a problem. DialerFree( ptStrTitle); return 0; } switch(errCode) { case ERR_NOLINES: errCode = ikszErrNoVoiceLine; break; case ERR_NOVOICELINE: errCode = ikszErrNoVoiceLine; break; case ERR_LINECLOSE: errCode = ikszErrLineClose; break; case ERR_911WARN: errCode = ikszWarningFor911; break; case ERR_NEWDEFAULT: errCode = ikszWarningNewDefault; break; case LINEERR_NODRIVER: errCode = ikszErrLineInitNoDriver; break; case LINEERR_NODEVICE: errCode = ikszErrLineInitNoDevice; break; case LINEERR_INIFILECORRUPT: errCode = ikszErrLineInitBadIniFile ; break; case LINEERR_NOMEM: errCode = ikszErrOOM; break; case LINEERR_INCOMPATIBLEAPIVERSION: errCode = ikszErrLineInitWrongDrivers ; break; case LINEERR_OPERATIONFAILED: errCode = ikszErrTAPI; break; case LINEERR_INVALADDRESS: errCode = ikszErrInvalAddress; break; case LINEERR_ADDRESSBLOCKED: errCode = ikszErrAddrBlocked; break; case LINEERR_BILLINGREJECTED: errCode = ikszErrBillingRejected; break; case LINEERR_RESOURCEUNAVAIL: case LINEERR_ALLOCATED: case LINEERR_INUSE: errCode = ikszErrResUnavail; break; case LINEERR_NOMULTIPLEINSTANCE: errCode = ikszErrNoMultipleInstance; break; case LINEERR_INVALCALLSTATE: errCode = ikszErrInvalCallState; break; case LINEERR_INVALCOUNTRYCODE: errCode = ikszErrInvalidCountryCode; break; case LINEERR_INVALCALLPARAMS: errCode = ikszDisconnectedCantDo; break; default: bDefault = TRUE; break; } if (bDefault) { // if using default error, get TAPI's // error message from FormatError() if (!FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, (LPCVOID)GetModuleHandle(TEXT("TAPI32.DLL")), (DWORD)TAPIERROR_FORMATMESSAGE(errCode), 0, (LPTSTR)ptStrError, MAXBUFSIZE, NULL)) { // if this fails, fall back on default LoadString( ghInst, ikszErrDefault, ptStrError, MAXBUFSIZE); } } else // not the default error message { if ( 0 == LoadString( ghInst, errCode, ptStrError, MAXBUFSIZE ) ) { LoadString( ghInst, ikszErrDefault, ptStrError, MAXBUFSIZE ); } } LoadString( ghInst, ikszWarningTitle, ptStrTitle, MAXBUFSIZE ); nResult = MessageBox( hWndOwner, ptStrError, ptStrTitle, uFlags ); DialerFree( ptStrTitle ); DialerFree( ptStrError ); return nResult; } /* * Name : * FitTextToButton * * Arguements : * hDlg handle for the dialog in which this button is embedded * nButtonID button id of this button * szName Name to fit on the button. Max size TAPIMAXCALLEDPARTYSIZE * * Return : * None * * Comments : * Function first checks to see if the button text specified fits in the * button. If it does not it truncates it appropriately and adds trailing * ellipses. */ VOID FitTextToButton ( HWND hDlg, INT nButtonID, LPTSTR szName ) { HDC hDC; HFONT hFont, hOldFont; HWND hWnd; do { // calculate number of chars. that can fit on // the button int nLen; RECT rect; SIZE size; POINT pt; TCHAR buf [TAPIMAXCALLEDPARTYSIZE + 1]; // get button dimensions hWnd = GetDlgItem( hDlg, nButtonID ); if ( hWnd == NULL ) break; if ( !GetClientRect( hWnd, &rect ) ) break; // get character dimensions hDC = GetDC( hWnd ); if ( hDC == NULL ) break; hFont = (HFONT) SendMessage( hWnd, WM_GETFONT, 0, 0 ); if ( hFont == NULL ) hOldFont = SelectObject( hDC, GetStockObject( SYSTEM_FONT ) ); else hOldFont = SelectObject( hDC, hFont ); // add an extra char at the end to compensate for // leading space, lstrcpy ( buf, szName ); nLen = lstrlen( buf ); buf [ nLen ] = TEXT('X'); buf [ nLen + 1 ] = TEXT('\0'); if ( !GetTextExtentPoint32( hDC, buf, nLen + 1, &size ) ) break; pt.x = size.cx; if ( !LPtoDP( hDC, &pt, 1 ) ) break; // check if name fits on button if ( pt.x > rect.right ) { // find how much of the name fits int i = 0; nLen = lstrlen( szName ); for ( i = 0; i < nLen; i++ ) { buf[ i ] = szName[ i ]; // an extra char is stuffed to compensate for the // leading space left by the left alignment buf [ i + 1 ] = TEXT('X'); buf [ i + 2 ] = TEXT('\0'); // break out in cases of error condition if ( !GetTextExtentPoint32( hDC, buf, i + 2, &size ) ) { i = nLen; break; } pt.x = size.cx; if ( !LPtoDP( hDC, &pt, 1 ) ) { i = nLen; break; } if ( pt.x > rect.right ) break; } // error if ( i >= nLen ) break; // name is too long. truncate and add ellipses szName [i - 3] = TEXT('\0'); lstrcat( szName, TEXT("...") ); } } while( FALSE ); if ( hDC ) { SelectObject( hDC, hOldFont ); ReleaseDC( hWnd, hDC ); } return; } /* * Name : * Is911 * * Arguements : * lpTransOut - Translated address contained the dialable string * * Returns * TRUE - If number to be dialed (in the US) is prefixed by 911 * FALSE - Otherwise * * Comments * */ BOOL Is911 ( LPLINETRANSLATEOUTPUT lpTransOut ) { DWORD i = 0, j = 0; LPTSTR lpDialDigits = (LPTSTR)((char*)lpTransOut + lpTransOut-> dwDialableStringOffset); TCHAR sz3Pref [ 4 ] = TEXT(""); // if this is not the US if ( lpTransOut-> dwCurrentCountry != 1 ) return FALSE; // skip non digit characters and extract // the first 3 digits in the dialable number for ( i = 0, j = 0; i < lpTransOut-> dwDialableStringSize ; i++ ) { if ( ISDIGIT( lpDialDigits[i] ) ) { sz3Pref[ j++ ] = lpDialDigits [ i ]; sz3Pref[ j ] = TEXT('\0'); if ( j == 3 ) break; } } if ( !lstrcmp( sz3Pref, TEXT("911") ) ) { return TRUE; } return FALSE; } /* * Name : * MakeCanonicalNumber * * Arguements : * szNumber Number to convert into canonical form. Max size TAPIMAXDESTADDRESSSIZE * szCanNumber Canonical representation of number specified in szNumber * * Return : * TRUE If the conversion was successful. * FALSE otherwise * * Comments : * Function first checks if given number is already in canonical form. * If it is, it returns. If it is not, then it performs the conversion. */ BOOL MakeCanonicalNumber ( LPCTSTR szNumber, LPTSTR szCanNumber ) { TCHAR szDigits [ TAPIMAXDESTADDRESSSIZE ]; TCHAR szPref [ TAPIMAXDESTADDRESSSIZE ]; BOOL bRes = FALSE; BOOL bTryAgain = TRUE; INT errCode = -1; INT nLenPref, nLenDigits, cPos, i; DWORD dwSize = 0; DWORD dwInd = 0; LPLINETRANSLATEOUTPUT lpTransOut = NULL; LPLINETRANSLATECAPS lpTransCaps = NULL; dwSize = sizeof ( LINETRANSLATEOUTPUT ); do { lpTransOut = ( LPLINETRANSLATEOUTPUT ) DialerAlloc ( dwSize ); if ( !lpTransOut ) { errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK ); goto error; } while (TRUE) { lpTransOut-> dwTotalSize = dwSize; errCode = lineTranslateAddress ( ghLineApp, giCurrentLine, gCurrentLineInfo.dwAPIVersion, szNumber, 0, 0, lpTransOut ); if ( (LINEERR_INIFILECORRUPT != errCode) || (FALSE == bTryAgain) ) { break; } bTryAgain = FALSE; errCode = lineTranslateDialog ( ghLineApp, giCurrentLine, TAPI_VERSION_1_4, NULL, szNumber ); if (NO_ERROR != errCode) { break; } } if (errCode) { goto error; } if ( lpTransOut-> dwNeededSize <= lpTransOut-> dwTotalSize ) break; dwSize = lpTransOut-> dwNeededSize; DialerFree( lpTransOut ); } while (TRUE); // check if input number is already in // canonical form. if ( lpTransOut-> dwTranslateResults & LINETRANSLATERESULT_CANONICAL ) goto error; // ensure country is the USA. if ( lpTransOut-> dwCurrentCountry != 1 ) goto error; // Extract the digits from given string // allowed formatting characters that are ignored are // space, (, ), -, . // presence of other characters will render the string invalid. // find the prefix of the address upto the | mark. // the rest of the string can be ignored nLenPref = _tcscspn ( szNumber, TEXT("|") ); lstrcpyn( szPref, szNumber, nLenPref+1 ); szPref[ nLenPref ] = TEXT('\0'); // if string is not composed entirely of digits // and allowable formating characters, quit conversion if ( _tcsspn( szPref, TEXT(" 0123456789()-.") ) != (size_t) nLenPref ) goto error; // collect digits ignoring formating characters. szDigits[ 0 ] = TEXT('\0'); for ( i = 0, nLenDigits = 0; i < nLenPref; i++ ) { if ( ISDIGIT( szNumber[ i ] ) ) { szDigits[ nLenDigits++ ] = szNumber[ i ]; } } szDigits[ nLenDigits ] = TEXT('\0'); // if "internal" number if ( nLenDigits < LOCAL_NUMBER ) goto error; switch ( nLenDigits ) { // Local number ( 7 digits) preceeded by a 0/1 // Strip leading 0/1 and treat as a local number case EXTENDED_LOCAL_NUMBER: if ( szDigits[ 0 ] == TEXT('0') || szDigits[ 0 ] == TEXT('1') ) { nLenDigits--; memmove( szDigits, &(szDigits[1]), nLenDigits*sizeof(TCHAR) ); szDigits[ nLenDigits ] = TEXT('\0'); cPos = _tcscspn( szPref, TEXT("01") ); nLenPref--; memmove( &(szPref[ cPos ]), &(szPref[ cPos + 1 ]), (nLenPref - cPos)*sizeof(TCHAR) ); szPref[ nLenPref ] = TEXT('\0'); } else { goto error; } case LOCAL_NUMBER : { LPLINELOCATIONENTRY lpLocLst; // if leading digit is 0 or 1, it is // illegal in the US if ( szDigits[ 0 ] == TEXT('0') || szDigits[ 0 ] == TEXT('1') ) { goto error; } // get area code nformation for local number dwSize = sizeof( LINETRANSLATECAPS ); do { lpTransCaps = (LPLINETRANSLATECAPS) DialerAlloc( dwSize ); if ( !lpTransCaps ) { errString( ghWndMain, LINEERR_NOMEM, MB_ICONSTOP | MB_OK ); goto error; } lpTransCaps-> dwTotalSize = dwSize; errCode = lineGetTranslateCaps ( ghLineApp, gCurrentLineInfo.dwAPIVersion, lpTransCaps ); if ( errCode ) { errString( ghWndMain, errCode, MB_ICONSTOP | MB_OK ); goto error; } if ( lpTransCaps-> dwNeededSize <= lpTransCaps-> dwTotalSize ) { break; } dwSize = lpTransCaps-> dwNeededSize; DialerFree( lpTransCaps ); } while ( TRUE ); // skip entries till you locate information for current location dwSize = sizeof( LINELOCATIONENTRY ); lpLocLst = (LPLINELOCATIONENTRY) ( (LPTSTR) ((char*)lpTransCaps + lpTransCaps-> dwLocationListOffset) ); for ( dwInd = 0; dwInd < lpTransCaps-> dwNumLocations ; dwInd++ ) { if ( lpLocLst[ dwInd ].dwPermanentLocationID == lpTransCaps-> dwCurrentLocationID ) break; } // current location no found ????? // login error if ( dwInd == lpTransCaps-> dwNumLocations ) { goto error; } // construct canonical form as szCanNumber[ 0 ]= TEXT('\0'); lstrcat( szCanNumber, TEXT("+1 (") ); lstrcat( szCanNumber, (LPTSTR) ((char*)lpTransCaps + lpLocLst[ dwInd ].dwCityCodeOffset) ); lstrcat( szCanNumber, TEXT(") ") ); lstrcat( szCanNumber, szDigits ); cPos = _tcscspn( szNumber, TEXT("|") ); if ( cPos != lstrlen( szNumber ) ) { lstrcat( szCanNumber, &(szNumber[ cPos ]) ); } bRes = TRUE; break; } case EXTENDED_LONG_DISTANCE_NUMBER: { // Long distance number ( 10 digits) preceeded by a 0/1 // Strip leading 0/1 and treat as a long distance number if ( szDigits[ 0 ] == TEXT('0') || szDigits[ 0 ] == TEXT('1') ) { nLenDigits--; memmove( szDigits, &(szDigits[1]), nLenDigits*sizeof(TCHAR) ); szDigits[ nLenDigits ] = TEXT('\0'); cPos = _tcscspn( szPref, TEXT("01") ); nLenPref--; memmove( &(szPref[ cPos ]), &(szPref[ cPos + 1 ]), (nLenPref - cPos)*sizeof(TCHAR) ); szPref[ nLenPref ] = TEXT('\0'); } else { goto error; } } case LONG_DISTANCE_NUMBER: { // if first or fourth digit is 0/1, illegal number if ( szDigits[ 0 ] == TEXT('0') || szDigits[ 0 ] == TEXT('1') || szDigits[ 3 ] == TEXT('0') || szDigits[ 3 ] == TEXT('1') ) { goto error; } szCanNumber[ 0 ] = TEXT('\0'); lstrcat( szCanNumber, TEXT("+1 (") ); _tcsncat( szCanNumber, szDigits, 3 ); lstrcat( szCanNumber, TEXT(") ") ); lstrcat( szCanNumber, &(szDigits[ 3 ]) ); bRes = TRUE; } break; default : goto error; } error: if ( lpTransOut ) DialerFree( lpTransOut ); if ( lpTransCaps ) DialerFree( lpTransCaps ); return bRes; } /* * Name : * AmpersandCompensate * * Arguements : * lpszSrc : Src string containing &s * lpszDst : Dest string * * Return : * * Comments : * Copies string pointed to by lpszSrc to lpszDst character by * character. If an & is encountered in this process in lpszSrc * it is copied as && into lpszDst. * Assumes lpszDst and lpszSrc are of size TAPIMAXCALLEDPARTYSIZE */ VOID AmpersandCompensate ( LPCTSTR lpszSrc, LPTSTR lpszDst ) { // check if the name has an & in it. If so replace // it with &&. INT cCnt, cInd; for ( cCnt = 0, cInd = 0; cInd < TAPIMAXCALLEDPARTYSIZE; cInd++, cCnt++ ) { if ( lpszSrc[ cCnt ] == TEXT('&') ) { lpszDst[ cInd++ ] = TEXT('&'); } lpszDst[ cInd ] = lpszSrc[ cCnt ]; if ( lpszSrc[ cCnt ] == TEXT('\0') ) break; } // make sure string is null terminated. lpszDst[ TAPIMAXCALLEDPARTYSIZE - 1 ] = TEXT('\0'); return; } /* * Name : * AmpersandDeCompensate * * Arguements : * lpszSrc : Src string containing &s * lpszDst : Dest string * * Return : * * Comments : * Copies string pointed to by lpszSrc to lpszDst character by * character. If an && is encountered in this process in lpszSrc * it is copied as & into lpszDst. * Assumes lpszDst and lpszSrc are of size TAPIMAXCALLEDPARTYSIZE */ VOID AmpersandDeCompensate ( LPCTSTR lpszSrc, LPTSTR lpszDst ) { // check if the name has an & in it. If so replace // it with &&. INT cCnt, cInd; for ( cCnt = 0, cInd = 0; cInd < TAPIMAXCALLEDPARTYSIZE; cInd++, cCnt++ ) { if ( ( lpszSrc[ cInd ] == TEXT('&') ) && ( lpszSrc[ cInd + 1 ] == TEXT('&') ) ) { cInd++; } lpszDst[ cCnt ] = lpszSrc[ cInd ] ; if ( lpszSrc [ cInd ] == TEXT('\0') ) { break; } } lpszDst[ TAPIMAXCALLEDPARTYSIZE - 1 ] = TEXT('\0'); return; }