www.pudn.com > Outgoing.rar > Outgoing.Cpp


/*++ 
 
Copyright (c) 1999 - 2000 Microsoft Corporation.  All Rights Reserved. 
 
--*/ 
 
#define UNICODE 
#include  
#include  
#include  
#include  
#include "resource.h" 
 
////////////////////////////////////////////////////////// 
// T3OUT.EXE 
// 
// Example of making an outgoing call with TAPI 3.0 
// 
// This application will allow a user to make a call 
// by using TAPI 3.0.  The application will simply look 
// for the first TAPI line that support Audio, and can 
// dial a phone number.  It will then use that line to 
// make calls. 
// 
// This application does not handle incoming calls, and 
// does not process incoming messages. 
// 
////////////////////////////////////////////////////////// 
 
////////////////////////////////////////////////////////// 
// Constants 
////////////////////////////////////////////////////////// 
 
const DWORD ADDRESSLENGTH   = 128; 
const DWORD MAXTERMINALS    = 5; 
 
const WCHAR * const gszTapi30           = L"TAPI 3.0 Outgoing Call Sample"; 
 
const WCHAR * const gszConferenceName   = L"Conference Name"; 
const WCHAR * const gszEmailName        = L"Email Name"; 
const WCHAR * const gszMachineName      = L"Machine Name"; 
const WCHAR * const gszPhoneNumber      = L"Phone Number"; 
const WCHAR * const gszIPAddress        = L"IP Address"; 
 
////////////////////////////////////////////////////////// 
// GLOBALS 
////////////////////////////////////////////////////////// 
HINSTANCE               ghInst; 
HWND                    ghDlg = NULL; 
ITTAPI *                gpTapi; 
ITAddress *             gpAddress = NULL; 
ITBasicCallControl *    gpCall; 
 
////////////////////////////////////////////////////////// 
// PROTOTYPES 
////////////////////////////////////////////////////////// 
INT_PTR 
CALLBACK 
MainDialogProc( 
               HWND hDlg, 
               UINT uMsg, 
               WPARAM wParam, 
               LPARAM lParam 
              ); 
 
HRESULT 
FindAnAddress( 
              DWORD dwAddressType, 
              BSTR  * ppName 
             ); 
 
HRESULT 
GetTerminal( 
            ITStream * pStream, 
            ITTerminal ** ppTerminal 
           ); 
 
HRESULT 
GetVideoRenderTerminal( 
                   ITTerminal ** ppTerminal 
                  ); 
 
HRESULT 
MakeTheCall( 
            DWORD dwAddressType, 
            PWCHAR szAddressToCall 
           ); 
 
HRESULT 
DisconnectTheCall(); 
 
void 
DoMessage( 
          LPWSTR pszMessage 
         ); 
 
HRESULT 
InitializeTapi(); 
 
void 
ShutdownTapi(); 
 
void 
EnableButton( 
             HWND hDlg, 
             int ID 
            ); 
void 
DisableButton( 
              HWND hDlg, 
              int ID 
             ); 
 
BOOL 
AddressSupportsMediaType( 
                         ITAddress * pAddress, 
                         long        lMediaType 
                        ); 
 
////////////////////////////////////////////////////////// 
// WinMain 
////////////////////////////////////////////////////////// 
int 
WINAPI 
WinMain( 
        HINSTANCE hInst, 
        HINSTANCE hPrevInst, 
        LPSTR lpCmdLine, 
        int nCmdShow 
       ) 
{ 
    ghInst = hInst; 
 
 
    // need to coinit 
    if ( FAILED( CoInitialize(NULL) ) ) 
    { 
        return 0; 
    } 
 
    if ( FAILED( InitializeTapi() ) ) 
    { 
        return 0; 
    } 
 
    // everything is initialized, so 
    // start the main dialog box 
    DialogBox( 
              ghInst, 
              MAKEINTRESOURCE(IDD_MAINDLG), 
              NULL, 
              MainDialogProc 
             ); 
 
 
    ShutdownTapi(); 
 
    CoUninitialize(); 
 
    return 1; 
} 
 
 
////////////////////////////////////////////////////////////// 
// InitializeTapi 
// 
// Various initializations 
/////////////////////////////////////////////////////////////// 
HRESULT 
InitializeTapi() 
{ 
    HRESULT         hr; 
 
 
    // cocreate the TAPI object 
    hr = CoCreateInstance( 
                          CLSID_TAPI, 
                          NULL, 
                          CLSCTX_INPROC_SERVER, 
                          IID_ITTAPI, 
                          (LPVOID *)&gpTapi 
                         ); 
 
    if ( FAILED(hr) ) 
    { 
        DoMessage(L"CoCreateInstance on TAPI failed"); 
        return hr; 
    } 
 
    // call initialize.  this must be called before 
    // any other tapi functions are called. 
    hr = gpTapi->Initialize(); 
 
    if (S_OK != hr) 
    { 
        DoMessage(L"TAPI failed to initialize"); 
 
        gpTapi->Release(); 
        gpTapi = NULL; 
 
        return hr; 
    } 
 
    return S_OK; 
} 
 
 
/////////////////////////////////////////////////////////////// 
// ShutdownTapi 
/////////////////////////////////////////////////////////////// 
void 
ShutdownTapi() 
{ 
    // if there is still a call, 
    // release it 
    if (NULL != gpCall) 
    { 
        gpCall->Release(); 
        gpCall = NULL; 
    } 
 
    // if we have an address object 
    // release it 
    if (NULL != gpAddress) 
    { 
        gpAddress->Release(); 
        gpAddress = NULL; 
    } 
 
    // release main object. 
    if (NULL != gpTapi) 
    { 
        gpTapi->Shutdown(); 
        gpTapi->Release(); 
        gpTapi = NULL; 
    } 
 
} 
 
/////////////////////////////////////////////////////////////////////////// 
// InitAddressTypeComboBox 
// 
// Put address type string in the combo box 
// and save the addresstype with the string 
// 
/////////////////////////////////////////////////////////////////////////// 
void 
InitAddressTypeComboBox( 
    HWND hComboBox 
    ) 
{ 
    int i; 
 
    i = (int)SendMessage( hComboBox, CB_ADDSTRING, 0, (LONG_PTR)gszConferenceName ); 
 
    SendMessage( 
                hComboBox, 
                CB_SETITEMDATA , 
                i, 
                (LONG_PTR)LINEADDRESSTYPE_SDP 
               ); 
 
 
    i = (int)SendMessage( hComboBox, CB_ADDSTRING, 0, (LONG_PTR)gszEmailName ); 
 
    SendMessage( 
                hComboBox, 
                CB_SETITEMDATA , 
                i, 
                (LONG_PTR)LINEADDRESSTYPE_EMAILNAME 
               ); 
 
 
    i = (int)SendMessage( hComboBox, CB_ADDSTRING, 0, (LONG_PTR)gszMachineName ); 
 
    SendMessage( 
                hComboBox, 
                CB_SETITEMDATA , 
                i, 
                (LONG_PTR)LINEADDRESSTYPE_DOMAINNAME 
               ); 
 
 
    i = (int)SendMessage( hComboBox, CB_ADDSTRING, 0, (LONG_PTR)gszPhoneNumber ); 
 
    SendMessage( 
                hComboBox, 
                CB_SETITEMDATA , 
                i, 
                (LONG_PTR)LINEADDRESSTYPE_PHONENUMBER 
               ); 
 
 
    SendMessage( hComboBox, CB_SETCURSEL, i, 0 ); 
 
    i = (int)SendMessage( hComboBox, CB_ADDSTRING, 0, (LONG_PTR)gszIPAddress ); 
 
    SendMessage( 
                hComboBox, 
                CB_SETITEMDATA , 
                i, 
                (LONG_PTR)LINEADDRESSTYPE_IPADDRESS 
               ); 
 
} 
 
/////////////////////////////////////////////////////////////////////////// 
// MainDlgProc 
/////////////////////////////////////////////////////////////////////////// 
INT_PTR 
CALLBACK 
MainDialogProc( 
               HWND hDlg, 
               UINT uMsg, 
               WPARAM wParam, 
               LPARAM lParam 
              ) 
{ 
    switch (uMsg) 
    { 
        case WM_INITDIALOG: 
        { 
            HWND hComboBox; 
 
 
            // set up dialog 
            ghDlg = hDlg; 
 
            EnableButton( hDlg, IDOK ); 
            DisableButton( hDlg, IDC_DISCONNECT ); 
 
            hComboBox = GetDlgItem( hDlg, IDC_ADDRESSTYPE ); 
 
            InitAddressTypeComboBox(hComboBox); 
 
            SetFocus( hComboBox ); 
 
            return 0; 
        } 
 
        case WM_COMMAND: 
        { 
            if ( LOWORD(wParam) == IDCANCEL ) 
            { 
                // quit 
                EndDialog( hDlg, 0 ); 
 
                return 1; 
            } 
 
            // dial request 
            if ( LOWORD(wParam) == IDOK ) 
            { 
                HWND hComboBox; 
                DWORD dwIndex; 
                DWORD dwAddressType; 
                WCHAR szAddressToCall[ADDRESSLENGTH]; 
 
 
                // get the address type the user selected. 
                hComboBox = GetDlgItem( hDlg, IDC_ADDRESSTYPE ); 
                dwIndex = (DWORD)SendMessage( hComboBox, CB_GETCURSEL, 0, 0 ); 
 
                dwAddressType = (DWORD)SendMessage( 
                                             hComboBox, 
                                             CB_GETITEMDATA, 
                                             dwIndex, 
                                             0 
                                           ); 
 
                // get the address the user wants to call 
                GetDlgItemText( 
                               hDlg, 
                               IDC_ADDRESS, 
                               szAddressToCall, 
                               ADDRESSLENGTH 
                              ); 
 
                // make the call 
                if ( S_OK == MakeTheCall(dwAddressType, szAddressToCall) ) 
                { 
                    EnableButton( hDlg, IDC_DISCONNECT ); 
                    DisableButton( hDlg, IDOK ); 
                } 
                else 
                { 
                    DoMessage(L"The call failed to connect"); 
                } 
 
                return 1; 
            } 
 
            // disconnect request 
            if ( LOWORD( wParam ) == IDC_DISCONNECT ) 
            { 
                // disconnect 
                if (S_OK == DisconnectTheCall()) 
                { 
                    EnableButton( hDlg, IDOK ); 
                    DisableButton( hDlg, IDC_DISCONNECT ); 
                } 
                else 
                { 
                    DoMessage(L"The call failed to disconnect"); 
                } 
 
                return 1; 
            } 
 
            return 0; 
        } 
        default: 
 
            return 0; 
    } 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// FindAnAddress 
// 
// Finds an address object that this application will use to make calls on. 
// 
// This function finds an address that supports the addresstype passed 
// in, as well as the audioin and audioout media types. 
// 
// Return Value 
//          S_OK if it finds an address 
//          E_FAIL if it does not find an address 
//////////////////////////////////////////////////////////////////////// 
HRESULT 
FindAnAddress( 
              DWORD dwAddressType, 
              BSTR  * ppName 
             ) 
{ 
    HRESULT                 hr = S_OK; 
    BOOL                    bFoundAddress = FALSE; 
    IEnumAddress          * pEnumAddress; 
    ITAddress             * pAddress; 
    ITAddressCapabilities * pAddressCaps; 
    long                    lType = 0; 
 
    // if we have an address object 
    // release it 
    if (NULL != gpAddress) 
    { 
        gpAddress->Release(); 
        gpAddress = NULL; 
    } 
 
    // enumerate the addresses 
    hr = gpTapi->EnumerateAddresses( &pEnumAddress ); 
 
    if ( FAILED(hr) ) 
    { 
        return hr; 
    } 
 
    while ( !bFoundAddress ) 
    { 
        // get the next address 
        hr = pEnumAddress->Next( 1, &pAddress, NULL ); 
 
        if (S_OK != hr) 
        { 
            break; 
        } 
 
 
        hr = pAddress->QueryInterface(IID_ITAddressCapabilities, (void**)&pAddressCaps); 
 
        if ( SUCCEEDED(hr) ) 
        { 
 
            hr = pAddressCaps->get_AddressCapability( AC_ADDRESSTYPES, &lType ); 
 
            pAddressCaps->Release(); 
 
            if ( SUCCEEDED(hr) ) 
            { 
                // is the type we are looking for? 
                if ( dwAddressType & lType ) 
                { 
                    // does it support audio? 
                    if ( AddressSupportsMediaType(pAddress, TAPIMEDIATYPE_AUDIO) ) 
                    { 
                        // does it have a name? 
                        if ( SUCCEEDED( pAddress->get_AddressName(ppName) ) ) 
                        { 
                            // save it in the global variable 
                            // since we break out of the loop, this one won't 
                            // get released 
 
                            gpAddress = pAddress; 
 
                            bFoundAddress = TRUE; 
 
                            break; 
                        } 
                    } 
                } 
            } 
        } 
 
        pAddress->Release(); 
 
    } // end while loop 
 
    pEnumAddress->Release(); 
 
    if (!bFoundAddress) 
    { 
        return E_FAIL; 
    } 
 
    return S_OK; 
} 
 
///////////////////////////////////////////////////////////////// 
// IsVideoCaptureStream 
// 
// Returns true if the stream is for video capture 
///////////////////////////////////////////////////////////////// 
 
BOOL 
IsVideoCaptureStream( 
                     ITStream * pStream 
                    ) 
{ 
    TERMINAL_DIRECTION tdStreamDirection; 
    long               lStreamMediaType; 
 
    if ( FAILED( pStream  ->get_Direction(&tdStreamDirection)   ) ) { return FALSE; } 
    if ( FAILED( pStream  ->get_MediaType(&lStreamMediaType)    ) ) { return FALSE; } 
 
    return (tdStreamDirection == TD_CAPTURE) && 
           (lStreamMediaType  == TAPIMEDIATYPE_VIDEO); 
} 
 
///////////////////////////////////////////////////////////////// 
// EnablePreview 
// 
// Selects a video render terminal on a video capture stream, 
// thereby enabling video preview. 
///////////////////////////////////////////////////////////////// 
 
HRESULT 
EnablePreview( 
              ITStream * pStream 
             ) 
{ 
    ITTerminal * pTerminal; 
 
    HRESULT hr = GetVideoRenderTerminal(&pTerminal); 
 
    if ( SUCCEEDED(hr) ) 
    { 
        hr = pStream->SelectTerminal(pTerminal); 
 
        pTerminal->Release(); 
    } 
 
    return hr; 
} 
 
///////////////////////////////////////////////////////////////// 
// SelectTerminalsOnCall 
// 
// Creates and selects terminals for all streams on the given 
// call. 
///////////////////////////////////////////////////////////////// 
 
HRESULT 
SelectTerminalsOnCall( 
                     ITBasicCallControl * pCall 
                     ) 
{ 
    HRESULT hr; 
 
    // 
    // get the ITStreamControl interface for this call 
    // 
 
    ITStreamControl * pStreamControl; 
 
    hr = pCall->QueryInterface(IID_ITStreamControl, 
                               (void **) &pStreamControl); 
 
    if ( SUCCEEDED(hr) ) 
    { 
        // 
        // enumerate the streams 
        // 
 
        IEnumStream * pEnumStreams; 
 
        hr = pStreamControl->EnumerateStreams(&pEnumStreams); 
 
        pStreamControl->Release(); 
 
        if ( SUCCEEDED(hr) ) 
        { 
            // 
            // for each stream 
            // 
 
            ITStream * pStream; 
 
            while ( S_OK == pEnumStreams->Next(1, &pStream, NULL) ) 
            { 
                ITTerminal * pTerminal; 
 
                // 
                // Find out the media type and direction of this stream, 
                // and create the default terminal for this media type and 
                // direction. 
                // 
 
                hr = GetTerminal(pStream, 
                                 &pTerminal); 
 
                if ( SUCCEEDED(hr) ) 
                { 
                    // 
                    // Select the terminal on the stream. 
                    // 
 
                    hr = pStream->SelectTerminal(pTerminal); 
 
                    if ( SUCCEEDED(hr) ) 
                    { 
                        // 
                        // Also enable preview on the video capture stream. 
                        // 
 
                        if ( IsVideoCaptureStream( pStream ) ) 
                        { 
                            EnablePreview( pStream ); 
                        } 
                    } 
 
                    pTerminal->Release(); 
                } 
 
                pStream->Release(); 
 
            } 
 
            pEnumStreams->Release(); 
        } 
    } 
 
    return hr; 
} 
 
 
///////////////////////////////////////////////////////////////// 
// MakeTheCall 
// 
// Sets up and makes a call 
///////////////////////////////////////////////////////////////// 
 
HRESULT 
MakeTheCall( 
            DWORD dwAddressType, 
            PWCHAR szAddressToCall 
           ) 
{ 
    HRESULT                 hr = S_OK; 
    BSTR                    bstrAddressToCall; 
    BSTR                    pAddressName; 
 
 
    // find an address object that 
    // we will use to make calls on 
 
    hr = FindAnAddress(dwAddressType, &pAddressName); 
 
    if ( FAILED(hr) ) 
    { 
        DoMessage(L"Could not find a TAPI address for making calls."); 
 
        return hr; 
    } 
 
    WCHAR pText[200]; 
 
    wsprintf(pText, L"Using address: %s", pAddressName); 
 
    SysFreeString(pAddressName); 
 
    DoMessage(pText); 
 
    // 
    // find out which media types this address supports 
    // 
 
    long lMediaTypes = 0; 
 
    if ( AddressSupportsMediaType(gpAddress, TAPIMEDIATYPE_AUDIO) ) 
    { 
        lMediaTypes |= TAPIMEDIATYPE_AUDIO; // we will use audio 
    } 
 
    if ( AddressSupportsMediaType(gpAddress, TAPIMEDIATYPE_VIDEO) ) 
    { 
        lMediaTypes |= TAPIMEDIATYPE_VIDEO; // we will use video 
    } 
 
    // 
    // Create the call. 
    // 
 
    bstrAddressToCall = SysAllocString( szAddressToCall ); 
 
    hr = gpAddress->CreateCall( bstrAddressToCall, 
                                dwAddressType, 
                                lMediaTypes, 
                                &gpCall); 
 
    SysFreeString ( bstrAddressToCall ); 
 
    if ( FAILED(hr) ) 
    { 
        DoMessage(L"Could not create a call."); 
 
        return hr; 
    } 
 
    // 
    // Select our terminals on the call; if any of the selections fail we 
    // proceed without that terminal. 
    // 
 
    hr = SelectTerminalsOnCall( gpCall ); 
 
    // 
    // We're now ready to call connect. 
    // 
    // the VARIANT_TRUE parameter indicates that this 
    // call is sychronous - that is, it won't 
    // return until the call is in the connected 
    // state (or fails to connect) 
    // Since this is called in the UI thread, 
    // this means that the app will appear 
    // to hang until this function returns. 
    // Some TAPI service providers may take a long 
    // time for a call to reach the connected state. 
    // 
 
    hr = gpCall->Connect( VARIANT_TRUE ); 
 
    if ( FAILED(hr) ) 
    { 
        gpCall->Release(); 
        gpCall = NULL; 
 
        DoMessage(L"Could not connect the call."); 
 
        return hr; 
    } 
 
    return S_OK; 
} 
 
 
///////////////////////////////////////////////////////// 
// GetTerminal 
// 
// Creates the default terminal for the passed-in stream. 
// 
///////////////////////////////////////////////////////// 
HRESULT 
GetTerminal( 
            ITStream * pStream, 
            ITTerminal ** ppTerminal 
           ) 
{ 
    // 
    // Determine the media type and direction of this stream. 
    // 
 
    HRESULT            hr; 
    long               lMediaType; 
    TERMINAL_DIRECTION dir; 
 
    hr = pStream->get_MediaType( &lMediaType ); 
    if ( FAILED(hr) ) return hr; 
 
    hr = pStream->get_Direction( &dir ); 
    if ( FAILED(hr) ) return hr; 
 
    // 
    // Since video render is a dynamic terminal, the procedure for creating 
    // it is different. 
    // 
 
    if ( ( lMediaType == TAPIMEDIATYPE_VIDEO ) && 
         ( dir        == TD_RENDER ) ) 
    { 
        return GetVideoRenderTerminal(ppTerminal); 
    } 
 
    // 
    // For all other terminals we use GetDefaultStaticTerminal. 
    // First, get the terminal support interface. 
    // 
 
    ITTerminalSupport * pTerminalSupport; 
 
    hr = gpAddress->QueryInterface( IID_ITTerminalSupport, 
                                    (void **)&pTerminalSupport); 
 
    if ( SUCCEEDED(hr) ) 
    { 
        // 
        // get the default terminal for this MediaType and direction 
        // 
 
        hr = pTerminalSupport->GetDefaultStaticTerminal(lMediaType, 
                                                        dir, 
                                                        ppTerminal); 
 
        pTerminalSupport->Release(); 
    } 
 
    return hr; 
 
} 
 
///////////////////////////////////////////////////////// 
// GetVideoRenderTerminal 
// 
// Creates a dynamic terminal for the Video Render mediatype / direction 
// 
///////////////////////////////////////////////////////// 
HRESULT 
GetVideoRenderTerminal( 
                   ITTerminal ** ppTerminal 
                  ) 
{ 
    // 
    // Construct a BSTR for the correct IID. 
    // 
 
    LPOLESTR            lpTerminalClass; 
 
    HRESULT             hr; 
 
    hr = StringFromIID(CLSID_VideoWindowTerm, 
                       &lpTerminalClass); 
 
    if ( SUCCEEDED(hr) ) 
    { 
        BSTR                bstrTerminalClass; 
 
        bstrTerminalClass = SysAllocString ( lpTerminalClass ); 
 
        CoTaskMemFree( lpTerminalClass ); 
 
        if ( bstrTerminalClass == NULL ) 
        { 
            hr = E_OUTOFMEMORY; 
        } 
        else 
        { 
 
            // 
            // Get the terminal support interface 
            // 
 
            ITTerminalSupport * pTerminalSupport; 
 
            hr = gpAddress->QueryInterface(IID_ITTerminalSupport, 
                                           (void **)&pTerminalSupport); 
 
            if ( SUCCEEDED(hr) ) 
            { 
                // 
                // Create the video render terminal. 
                // 
 
                hr = pTerminalSupport->CreateTerminal(bstrTerminalClass, 
                                                      TAPIMEDIATYPE_VIDEO, 
                                                      TD_RENDER, 
                                                      ppTerminal); 
 
                pTerminalSupport->Release(); 
 
                if ( SUCCEEDED(hr) ) 
                { 
                    // Get the video window interface for the terminal 
                    IVideoWindow *pVideoWindow = NULL; 
 
                    hr = (*ppTerminal)->QueryInterface(IID_IVideoWindow, 
                                                       (void**)&pVideoWindow); 
 
                    if ( SUCCEEDED(hr) ) 
                    { 
                        // 
                        // Set the AutoShow member to true 
                        // 
                        // Note that the AutoShow property is the only one 
                        // we can use on this terminal's IVideoWindow and 
                        // IBasicVideo interfaces before the CME_STREAM_ACTIVE 
                        // event is received for the stream. All other methods 
                        // will fail until CME_STREAM_ACTIVE has been sent. 
                        // Applications that need to control more about a video 
                        // window than just its visibility must listen for the 
                        // CME_STREAM_ACTIVE event. See the "t3in.exe" sample 
                        // for how to do this. 
                        // 
 
                        hr = pVideoWindow->put_AutoShow( VARIANT_TRUE ); 
 
                        pVideoWindow->Release(); 
                    } 
                } 
            } 
 
            SysFreeString( bstrTerminalClass ); 
        } 
    } 
 
    return hr; 
} 
 
 
////////////////////////////////////////////////////////////////////// 
// DisconnectTheCall 
// 
// Disconnects the call 
////////////////////////////////////////////////////////////////////// 
HRESULT 
DisconnectTheCall() 
{ 
    HRESULT         hr = S_OK; 
 
    if (NULL != gpCall) 
    { 
        hr = gpCall->Disconnect( DC_NORMAL ); 
 
        gpCall->Release(); 
        gpCall = NULL; 
 
        return hr; 
    } 
 
    return S_FALSE; 
} 
 
 
 
/////////////////////////////////////////////////////////////////// 
// 
// HELPER FUNCTIONS 
// 
/////////////////////////////////////////////////////////////////// 
 
 
/////////////////////////////////////////////////////////////////// 
// DoMessage 
/////////////////////////////////////////////////////////////////// 
void 
DoMessage( 
          LPWSTR pszMessage 
         ) 
{ 
    MessageBox( 
               ghDlg, 
               pszMessage, 
               gszTapi30, 
               MB_OK 
              ); 
} 
 
/////////////////////////////////////////////////////////////// 
// EnableButton 
// 
// Enable, make default, and setfocus to a button 
/////////////////////////////////////////////////////////////// 
void 
EnableButton( 
             HWND hDlg, 
             int ID 
            ) 
{ 
    SendDlgItemMessage( 
                       hDlg, 
                       ID, 
                       BM_SETSTYLE, 
                       BS_DEFPUSHBUTTON, 
                       0 
                      ); 
    EnableWindow( 
                 GetDlgItem( hDlg, ID ), 
                 TRUE 
                ); 
    SetFocus( 
             GetDlgItem( hDlg, ID ) 
            ); 
} 
 
////////////////////////////////////////////////////////////// 
// DisableButton 
// 
// Disable a button 
////////////////////////////////////////////////////////////// 
void 
DisableButton( 
              HWND hDlg, 
              int ID 
             ) 
{ 
    SendDlgItemMessage( 
                       hDlg, 
                       ID, 
                       BM_SETSTYLE, 
                       BS_PUSHBUTTON, 
                       0 
                      ); 
    EnableWindow( 
                 GetDlgItem( hDlg, ID ), 
                 FALSE 
                ); 
} 
 
////////////////////////////////////////////////////////////// 
// AddressSupportsMediaType 
// 
// Finds out if the given address supports the given media 
// type, and returns TRUE if it does. 
////////////////////////////////////////////////////////////// 
 
BOOL 
AddressSupportsMediaType( 
                         ITAddress * pAddress, 
                         long        lMediaType 
                        ) 
{ 
    VARIANT_BOOL     bSupport = VARIANT_FALSE; 
    ITMediaSupport * pMediaSupport; 
 
    if ( SUCCEEDED( pAddress->QueryInterface( IID_ITMediaSupport, 
                                              (void **)&pMediaSupport ) ) ) 
    { 
        // does it support this media type? 
        pMediaSupport->QueryMediaType( 
                                      lMediaType, 
                                      &bSupport 
                                     ); 
 
        pMediaSupport->Release(); 
    } 
 
    return (bSupport == VARIANT_TRUE); 
}