//-----------------------------------------------------------------------------
// Function:    ResolvePnrpNameCommand
// Purpose:     Asynchronously or synchronously resolves a user given peer name
//              using PNRP in a user selected cloud (or clouds).
// Parameters:  None
//
// NOTE: The signature of this function must adhere to the MENU_COMMAND typedef
HRESULT ResolvePeerNameCommand()
{
    HRESULT                 hr = S_OK;
    WCHAR                   wzInputBuffer[MAX_PEERNAME_LENGTH];
    BOOL                    fSynch = TRUE;
    WCHAR                   wzCloudName[MAX_CLOUD_NAME];

    wprintf(L"\nNOTE:  You cannot successfully resolve names registered by this process.\n");
    wprintf(L"       If you wish to test PNRP locally start another instance of this sample\n");
    wprintf(L"       application.\n");

    // Prompts user to select a cloud in which to resolve
    hr = GetCloudName(TRUE, celems(wzCloudName), wzCloudName);

    // Asks user to select a synchronous or asynchronous resolve
    if (SUCCEEDED(hr))
    {
        wprintf(L"Synchronous resolve [no]: ");
        FLUSH_AND_GET_RESPONSE(hr, wzInputBuffer);

        if (_wcsicmp(wzInputBuffer, L"yes") != 0)
        {
            fSynch = FALSE;
        }

        do
        {
            wprintf(L"Peer Name (e.g. 0.myclassifier): ");
            FLUSH_AND_GET_RESPONSE(hr, wzInputBuffer);

            // Peer Name must be non-null.
            if (SUCCEEDED(hr) && wzInputBuffer[0] == L'\0')
            {
                wprintf(L"Peer Name must be non-empty.\n");
            }
        } while (SUCCEEDED(hr) && wzInputBuffer[0] == L'\0');

    }

    if (SUCCEEDED(hr))
    {
        if (fSynch)
        {
            hr = SyncPeerNameResolve(wzInputBuffer, wzCloudName);
        }
        else
        {
            hr = AsyncPeerNameResolve(wzInputBuffer, wzCloudName);
        }
    }
    return hr;
}
Beispiel #2
0
void
TraceMsg (
    _In_ LPWSTR szFormat,
    ...)
{
    static WCHAR szTempBuf[4096];

    va_list arglist;

    va_start(arglist, szFormat);

    StringCchVPrintfW ( szTempBuf,
        celems(szTempBuf),
        szFormat,
        arglist );

    OutputDebugStringW( szTempBuf );

    va_end(arglist);
}
//-----------------------------------------------------------------------------
// Function:    UpdateRegistrationCommand
// Purpose:     Updates peer name registration information
// Parameters:  None
//
// NOTE: The signature of this function must adhere to the MENU_COMMAND typedef
HRESULT UpdateRegistrationCommand()
{
    HRESULT     hr = S_OK;
    //ppRegAddrs is a pointer to an array of pointers to SOCKADDR structures
    SOCKADDR**  ppRegAddrs = NULL;
    ULONG       cAddresses = 0;

    // NOTE: You may not update cAddresses to or from
    // PEER_PNRP_AUTO_ADDRESSES - this can only be specified at the
    // initial registration
    if (g_RegInfo.cAddresses != PEER_PNRP_AUTO_ADDRESSES)
    {
        // Get addresses
        hr = GetAddress(FALSE, &cAddresses, &ppRegAddrs);

        if (SUCCEEDED(hr))
        {
            //Copy in the address count and pointer to the array of pointers
            g_RegInfo.cAddresses = cAddresses;
            g_RegInfo.ppAddresses = ppRegAddrs;
        }
    }

    // Update the comment - since the pointers in the g_RegInfo struct
    // already point to g_wzComment, the comment in g_RegInfo will be
    // implicitly updated
    if (SUCCEEDED(hr))
    {
        hr = GetComment(celems(g_wzComment), g_wzComment);
    }

    // Update the payload.  If no addresses are specified, ensure that the
    // payload is non-empty
    if (SUCCEEDED(hr))
    {
        hr = GetPayload(sizeof(g_PayloadData), (PBYTE)g_PayloadData);
        if ((g_RegInfo.cAddresses == 0) && SUCCEEDED(hr))
        {
            while(PayloadSize(g_PayloadData) == 0 && SUCCEEDED(hr))
            {
                wprintf(L"Payload must be non-empty if no addresses are specified.\n");
                hr = GetPayload(sizeof(g_PayloadData), (PBYTE)g_PayloadData);
            }
        }
    }

    if (SUCCEEDED(hr))
    {
        if (PayloadSize(g_PayloadData) == 0)
        {
            g_RegInfo.payload.cbData = 0;
            g_RegInfo.payload.pbData = NULL;
        }
        else
        {
            g_RegInfo.payload.cbData = PayloadSize(g_PayloadData);
            g_RegInfo.payload.pbData = (PBYTE) g_PayloadData;
        }
    }

    // Perform the update and return the result
    if (SUCCEEDED(hr))
    {
        hr = PeerPnrpUpdateRegistration(g_hRegistration, &g_RegInfo);
    }

    if (SUCCEEDED(hr))
    {
        wprintf(L"Registration successfully updated\n");
    }
    else
    {
        wprintf(L"Error while updating registration.\n");
    }

    if (ppRegAddrs != NULL)
    {
        free(ppRegAddrs);
    }
    return hr;
}
//-----------------------------------------------------------------------------
// Function:    RegisterPeerNameCommand
// Purpose:     Prompts user for registration information, fills out a
//              PEER_PNRP_REGISTRATION_INFO struct, creates a peer name,
//              and calls PeerPnrpRegister to register the peer name
// Parameters:  None
//
// NOTE: The signature of this function must adhere to the MENU_COMMAND typedef
HRESULT RegisterPeerNameCommand()
{
    WCHAR                       wzInputBuffer[256] = {0};
    WCHAR                       wzIdentity[MAX_PEERNAME_LENGTH] = {0};
    WCHAR                       wzClassifier[MAX_CLASSIFIER_LENGTH] = {0};
    HRESULT                     hr = S_OK;
    PWSTR                       pwzPeerName = NULL;
    ULONG                       cAddresses = 0;
    //ppRegAddrs is a pointer to an array of pointers to SOCKADDR structures
    SOCKADDR**                  ppRegAddrs = NULL;

    ZeroMemory(&g_RegInfo, sizeof(PEER_PNRP_REGISTRATION_INFO));

    //Collect Registration Information
    //---------------------------------

    // Addresses
    hr = GetAddress(TRUE, &cAddresses, &ppRegAddrs);
    if (SUCCEEDED(hr))
    {
        // Cloud name
        hr = GetCloudName(cAddresses != 1, celems(g_wzCloudName), g_wzCloudName);
    }

    if (SUCCEEDED(hr))
    {
        // Comment
        hr = GetComment(celems(g_wzComment), g_wzComment);
    }

    if (SUCCEEDED(hr))
    {
        // Payload
        hr = GetPayload(sizeof(g_PayloadData), (PBYTE)g_PayloadData);

        if (cAddresses == 0)
        {
            // If no addresses were specified, the payload must be non-null.
            while (PayloadSize(g_PayloadData) == 0 && SUCCEEDED(hr))
            {
                wprintf(L"Payload must be non-empty if no addresses are specified.\n");
                hr = GetPayload(sizeof(g_PayloadData), (PBYTE)g_PayloadData);
            }
        }
    }

    // Create Peer Name
    //------------------

    // If secure, get identity
    if (SUCCEEDED(hr))
    {
        wprintf(L"Secured peer name [no]: ");
        FLUSH_AND_GET_RESPONSE(hr, wzInputBuffer);

        if (SUCCEEDED(hr) && _wcsicmp(wzInputBuffer, L"yes") == 0)
        {
            hr = GetIdentity(celems(wzIdentity), wzIdentity);
        }
    }
    // Classifier
    if (SUCCEEDED(hr))
    {
        do
        {
            wprintf(L"Classifier: ");
            FLUSH_AND_GET_RESPONSE(hr, wzClassifier);

            // Classifier must be non-null.
            if (SUCCEEDED(hr) && wzClassifier[0] == L'\0')
            {
                wprintf(L"Classifier must be non-empty.\n");
            }
        } while (SUCCEEDED(hr) && wzClassifier[0] == L'\0');
    }

    // Create peer name
    if (SUCCEEDED(hr))
    {
        if (wcslen(wzIdentity) != 0)
        {
            // Create secured peer name
            hr = PeerCreatePeerName(wzIdentity, wzClassifier, &pwzPeerName);
        }
        else
        {
            // Create unsecured peer name
            hr = PeerCreatePeerName(NULL, wzClassifier, &pwzPeerName);
        }
    }

    // Fill out g_RegInfo struct
    // -------------------------
    if (wcslen(g_wzCloudName) == 0)
    {
        g_RegInfo.pwzCloudName = NULL;
    }
    else
    {
        g_RegInfo.pwzCloudName = g_wzCloudName;
    }

    //Copy in the address count and pointer to the array of pointers
    g_RegInfo.cAddresses = cAddresses;
    g_RegInfo.ppAddresses = ppRegAddrs;

    g_RegInfo.pwzComment = g_wzComment;

    if (PayloadSize(g_PayloadData) == 0)
    {
        g_RegInfo.payload.cbData = 0;
        g_RegInfo.payload.pbData = NULL;
    }
    else
    {
        g_RegInfo.payload.cbData = PayloadSize(g_PayloadData);
        g_RegInfo.payload.pbData = (PBYTE) g_PayloadData;
    }

    // Perform registration
    if (SUCCEEDED(hr))
    {
        hr = PeerPnrpRegister(pwzPeerName, &g_RegInfo, &g_hRegistration);
    }

    // Display result
    if (SUCCEEDED(hr))
    {
        wprintf(L"\nSuccessfully registered name: %s\n", pwzPeerName);
    }
    else
    {
        wprintf(L"\nError while registering name.  HRESULT=0x%x\n", hr);
        PrintError(hr);
    }

    if (pwzPeerName != NULL)
    {
        PeerFreeData(pwzPeerName);
    }

    if (ppRegAddrs != NULL)
    {
        free(ppRegAddrs);
    }
    return hr;
}
Beispiel #5
0
HRESULT CMuxVirtualMiniport::ApplyRegistryChanges(ConfigAction eApplyAction)
{
    HKEY                    hkeyAdapterGuid;
    WCHAR                   szAdapterGuid[MAX_PATH+1];
    WCHAR                   szAdapterGuidKey[MAX_PATH+1];
    WCHAR                   szMiniportGuid[MAX_PATH+1];
    LPWSTR                  lpDevice;
    LONG                    lResult = 0;

    TraceMsg( L"-->CMuxVirtualMiniport::ApplyRegistryChanges.\n" );

    switch( eApplyAction ) {

        case eActAdd:         // Virtual miniport added.

            StringFromGUID2( m_guidAdapter,
                             szAdapterGuid,
                             MAX_PATH+1 );

            StringCchPrintfW ( szAdapterGuidKey,
                celems(szAdapterGuidKey),
                L"%s\\%s",
                c_szAdapterList,
                szAdapterGuid );
  
            szAdapterGuidKey[MAX_PATH]='\0';
            lResult = RegCreateKeyExW( HKEY_LOCAL_MACHINE,
                                       szAdapterGuidKey,
                                       0,
                                       NULL,
                                       REG_OPTION_NON_VOLATILE,
                                       KEY_ALL_ACCESS,
                                       NULL,
                                       &hkeyAdapterGuid,
                                       NULL);


            if ( lResult == ERROR_SUCCESS ) {

                StringFromGUID2( m_guidMiniport,
                                 szMiniportGuid,
                                 MAX_PATH+1 );

                lpDevice = AddDevicePrefix( szMiniportGuid );

                if ( lpDevice ) {

#ifndef PASSTHRU_NOTIFY

                    lResult = AddToMultiSzValue( hkeyAdapterGuid,
                                                 lpDevice );
#else

                    lResult = RegSetValueExW( hkeyAdapterGuid,
                                              c_szUpperBindings,
                                              0,
                                              REG_SZ,
                                              (LPBYTE)lpDevice,
                                              (wcslen(lpDevice) + 1) *
                                              sizeof(WCHAR) );


#endif

                    if ( lResult != ERROR_SUCCESS ) {

                        TraceMsg( L"   Failed to save %s at %s\\%s.\n",
                                  lpDevice,
                                  szAdapterGuidKey,
                                  c_szUpperBindings );

                    }

                    free( lpDevice );
                }
                else {
                    lResult = ERROR_NOT_ENOUGH_MEMORY;
                }

                RegCloseKey( hkeyAdapterGuid );
            }
            else {
                TraceMsg( L"   Failed to open the registry key: %s.\n",
                          szAdapterGuidKey );
            }
            break;

        case eActRemove:                  // Virtual miniport removed.

            StringFromGUID2( m_guidAdapter,
                             szAdapterGuid,
                             MAX_PATH+1 );

            StringCchPrintfW( szAdapterGuidKey,
                celems(szAdapterGuidKey),
                L"%s\\%s",
                c_szAdapterList,
                szAdapterGuid );
            szAdapterGuidKey[MAX_PATH]='\0';
            lResult = RegCreateKeyExW( HKEY_LOCAL_MACHINE,
                                        szAdapterGuidKey,
                                        0,
                                        NULL,
                                        REG_OPTION_NON_VOLATILE,
                                        KEY_ALL_ACCESS,
                                        NULL,
                                        &hkeyAdapterGuid,
                                        NULL);


            if ( lResult == ERROR_SUCCESS ) {

                StringFromGUID2( m_guidMiniport,
                                 szMiniportGuid,
                                 MAX_PATH+1 );

                lpDevice = AddDevicePrefix( szMiniportGuid );
                TraceMsg( L"   Deleting %s at %s.\n",
                          lpDevice,
                          szAdapterGuidKey );

                if ( lpDevice ) {

#ifndef PASSTHRU_NOTIFY

                    lResult = DeleteFromMultiSzValue( hkeyAdapterGuid,
                                                      lpDevice );
#else

                    lResult = RegDeleteValueW( hkeyAdapterGuid,
                                               c_szUpperBindings );
#endif

                    if ( lResult != ERROR_SUCCESS ) {

                        TraceMsg( L"   Failed to delete %s at %s\\%s.\n",
                                  lpDevice,
                                  szAdapterGuidKey,
                                  c_szUpperBindings );

                    }

                    free( lpDevice );
                }

                RegCloseKey( hkeyAdapterGuid );
            }
            else {
                TraceMsg( L"   Failed to open the registry key: %s.\n",
                          szAdapterGuidKey );
            }
    }

    TraceMsg( L"<--CMuxVirtualMiniport::ApplyRegistryChanges(HRESULT = %x).\n",
              HRESULT_FROM_WIN32(lResult) );

    return HRESULT_FROM_WIN32(lResult);
}
HRESULT CMuxPhysicalAdapter::LoadConfiguration (VOID)
{
    HKEY                    hkeyAdapterGuid;
    WCHAR                   szAdapterGuidKey[MAX_PATH+1];
    WCHAR                   szAdapterGuid[MAX_PATH+1];
    LPWSTR                  lpMiniportList;
    LPWSTR                  lpMiniport;
    LPWSTR                  lpMiniportGuid;
    DWORD                   dwDisp;
    CMuxVirtualMiniport     *pMiniport;
    GUID                    guidMiniport;
    DWORD                   dwBytes;
    LONG                    lResult;

    TraceMsg( L"-->CMuxPhysicalAdapter::LoadConfiguration.\n" );

    //
    // Build the registry key using the adapter guid under which
    // device IDs of the virtual miniports are stored.
    //

    StringFromGUID2( m_guidAdapter,
                     szAdapterGuid,
                     MAX_PATH+1 );

    StringCchPrintfW ( szAdapterGuidKey,
                       celems(szAdapterGuidKey),
                       L"%s\\%s",
                       c_szAdapterList,
                       szAdapterGuid );

    szAdapterGuidKey[MAX_PATH]='\0';
    lResult = RegCreateKeyExW( HKEY_LOCAL_MACHINE,
                               szAdapterGuidKey,
                               0,
                               NULL,
                               REG_OPTION_NON_VOLATILE,
                               KEY_ALL_ACCESS,
                               NULL,
                               &hkeyAdapterGuid,
                               &dwDisp);

    if ( lResult == ERROR_SUCCESS ) {

        //
        // If dwDisp indicates that a new key is created then, we know there
        // is no virtual miniport currently listed underneath and we simply
        // return.
        //

        if ( dwDisp != REG_CREATED_NEW_KEY ) {

            dwBytes = 0;
            lResult =  RegQueryValueExW(
                           hkeyAdapterGuid,
                           c_szUpperBindings,
                           NULL,
                           NULL,
                           NULL,
                           &dwBytes );
            if(lResult != ERROR_SUCCESS) {
                // you may do something
            }



            //alloc lpMiniportList with dwBytes elements and initialzes each to be 0
            lpMiniportList = (LPWSTR)calloc( dwBytes, 1 );

            if ( lpMiniportList != NULL ) {

                lResult =  RegQueryValueExW(
                               hkeyAdapterGuid,
                               c_szUpperBindings,
                               NULL,
                               NULL,
                               (LPBYTE)lpMiniportList,
                               &dwBytes );

                if ( lResult == ERROR_SUCCESS ) {

                    lpMiniport = lpMiniportList;


#ifndef PASSTHRU_NOTIFY

                    //
                    // In case of mux, c_szUpperBindings is a REG_MULTI_SZ string.
                    //

                    lpMiniport[dwBytes-1] = '\0';
                    while ( wcslen(lpMiniport) ) {

                        lpMiniportGuid = RemoveDevicePrefix( lpMiniport );

                        TraceMsg( L"   Loading configuration for miniport %s...\n",
                                  lpMiniportGuid );

                        if ( lpMiniportGuid != NULL ) {

                            CLSIDFromString( lpMiniportGuid,
                                             &guidMiniport );

                            //
                            // Create an instance representing the virtual miniport.
                            //

#pragma prefast(suppress:8197, "The instance is freed in the destructor")
                            pMiniport = new CMuxVirtualMiniport( m_pnc,
                                                                 &guidMiniport,
                                                                 &m_guidAdapter );

                            if ( pMiniport ) {

                                //
                                // Load any miniport specific configuration.
                                //

                                pMiniport->LoadConfiguration();

                                //
                                // Save the miniport instance in a list.
                                //

                                m_MiniportList.Insert( pMiniport,
                                                       guidMiniport );

                            }

                            free( lpMiniportGuid );
                        }

                        //
                        // Get next miniport guid.
                        //

                        lpMiniport += wcslen(lpMiniport) + 1;
                    }

#else

                    //
                    // In case of the passthru driver, c_szUpperBindings is
                    // a reg_sz string.
                    //

                    lpMiniportGuid = RemoveDevicePrefix( lpMiniport );

                    TraceMsg( L"   Loading configuration for miniport %s...\n",
                              lpMiniportGuid );

                    if ( lpMiniportGuid ) {

                        CLSIDFromString( lpMiniportGuid,
                                         &guidMiniport );

                        //
                        // Create an instance representing the virtual miniport.
                        //

                        pMiniport = new CMuxVirtualMiniport( m_pnc,
                                                             &guidMiniport,
                                                             &m_guidAdapter );

                        if ( pMiniport ) {

                            //
                            // Load any miniport specific configuration.
                            //

                            pMiniport->LoadConfiguration();

                            //
                            // Save the miniport instance in a list.
                            //

                            m_MiniportList.Insert( pMiniport,
                                                   guidMiniport );
                        }

                        free( lpMiniportGuid );
                    }
#endif
                }
                else {
                    TraceMsg( L"   Failed to read the registry value: %s.\n",
                              c_szUpperBindings );
                }

                free( lpMiniportList );
            }
            else {
                lResult = ERROR_NOT_ENOUGH_MEMORY;
            }
        }

        RegCloseKey( hkeyAdapterGuid );
    }
    else {

        TraceMsg( L"   Failed to open the registry key: %s.\n",
                  szAdapterGuidKey );
    }

    TraceMsg( L"<--CMuxPhysicalAdapter::LoadConfiguration(HRESULT = %x).\n",
              HRESULT_FROM_WIN32(lResult) );

    return HRESULT_FROM_WIN32(lResult);
}
//-----------------------------------------------------------------------------
// Function:    PNMEventHandler
// Purpose:     Registers for all event types and prints out the event data
// Parameters:  None
//
HRESULT EventHandler()
{
    HPEEREVENT            hPeerEvent = NULL;
    HRESULT               hr = S_OK;
    PEER_COLLAB_EVENT_REGISTRATION  eventReg[11] = {0};
    HANDLE hEvent[2];
    HANDLE hParentHandle = NULL;

    hr = GetParentProcessHandle(&hParentHandle);

    if (FAILED(hr))
    {
        printf("Failed to get parent process handle.  Aborting event printing process\n");
        hr = E_FAIL;
        goto exit;
    }

    hEvent[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
    hEvent[1] = hParentHandle;

    eventReg[0].eventType = PEER_EVENT_WATCHLIST_CHANGED;
    eventReg[1].eventType = PEER_EVENT_ENDPOINT_CHANGED;
    eventReg[2].eventType = PEER_EVENT_ENDPOINT_PRESENCE_CHANGED;
    eventReg[3].eventType = PEER_EVENT_ENDPOINT_APPLICATION_CHANGED;
    eventReg[4].eventType = PEER_EVENT_ENDPOINT_OBJECT_CHANGED;
    eventReg[5].eventType = PEER_EVENT_MY_ENDPOINT_CHANGED;
    eventReg[6].eventType = PEER_EVENT_MY_PRESENCE_CHANGED;
    eventReg[7].eventType = PEER_EVENT_MY_APPLICATION_CHANGED;
    eventReg[8].eventType = PEER_EVENT_MY_OBJECT_CHANGED;
    eventReg[9].eventType = PEER_EVENT_PEOPLE_NEAR_ME_CHANGED;
    eventReg[10].eventType = PEER_EVENT_REQUEST_STATUS_CHANGED;

    // Register to be notified when the request finishes  
    hr = PeerCollabRegisterEvent(hEvent[0], celems(eventReg), eventReg, &hPeerEvent);  

    if (SUCCEEDED(hr))
    {
        while (WaitForMultipleObjects(2, hEvent, FALSE, INFINITE) == WAIT_OBJECT_0)
        {
            PEER_COLLAB_EVENT_DATA *pEventData = NULL;

            // retrieve all event data 
            while (PeerCollabGetEventData(hPeerEvent, &pEventData) == S_OK)
            {
                switch(pEventData->eventType)
                {
                    case PEER_EVENT_WATCHLIST_CHANGED:
                        wprintf(L"PEER_EVENT_WATCHLIST_CHANGED event signalled\n");
                        break;

                    case PEER_EVENT_ENDPOINT_CHANGED:
                        wprintf(L"PEER_EVENT_ENDPOINT_CHANGED\n");
                        break;

                    case PEER_EVENT_ENDPOINT_PRESENCE_CHANGED:
                        wprintf(L"PEER_EVENT_ENDPOINT_PRESENCE_CHANGED event signalled\n");
                        break;

                    case PEER_EVENT_ENDPOINT_APPLICATION_CHANGED:
                        wprintf(L"PEER_EVENT_ENDPOINT_APPLICATION_CHANGED event signalled\n");
                        break;

                    case PEER_EVENT_ENDPOINT_OBJECT_CHANGED:
                        wprintf(L"PEER_EVENT_ENDPOINT_OBJECT_CHANGED event signalled\n");
                        break;

                    case PEER_EVENT_MY_ENDPOINT_CHANGED:
                        wprintf(L"PEER_EVENT_MY_ENDPOINT_CHANGED event signalled\n");
                        break;

                    case PEER_EVENT_MY_PRESENCE_CHANGED:
                        wprintf(L"PEER_EVENT_MY_PRESENCE_CHANGED event signalled\n");
                        break;

                    case PEER_EVENT_MY_APPLICATION_CHANGED:
                        wprintf(L"PEER_EVENT_MY_APPLICATION_CHANGED event signalled\n");
                        break;

                    case PEER_EVENT_MY_OBJECT_CHANGED:
                        wprintf(L"PEER_EVENT_MY_OBJECT_CHANGED event signalled\n");
                        break;

                    case PEER_EVENT_PEOPLE_NEAR_ME_CHANGED:
                        wprintf(L"PEER_EVENT_PEOPLE_NEAR_ME_CHANGED event signalled\n");
                        break;

                    case PEER_EVENT_REQUEST_STATUS_CHANGED:
                        wprintf(L"PEER_EVENT_REQUEST_STATUS_CHANGED event signalled\n");
                        break;
                }

                switch (pEventData->eventType)
                {
                    case PEER_EVENT_WATCHLIST_CHANGED:
                              DisplayWatchListChanged(&pEventData->watchListChangedData);
                              break;
                    case PEER_EVENT_ENDPOINT_PRESENCE_CHANGED:  //intentional fallthrough
                        case PEER_EVENT_MY_PRESENCE_CHANGED:
                              DisplayPresenceChanged(&pEventData->presenceChangedData);
                              break;
                    case PEER_EVENT_ENDPOINT_APPLICATION_CHANGED:  //intentional fallthrough
                    case PEER_EVENT_MY_APPLICATION_CHANGED:
                              DisplayApplicationChanged(&pEventData->applicationChangedData);
                              break;
                    case PEER_EVENT_ENDPOINT_OBJECT_CHANGED:  //intentional fallthrough
                    case PEER_EVENT_MY_OBJECT_CHANGED:
                              DisplayObjectChanged(&pEventData->objectChangedData);
                              break;
                    case PEER_EVENT_ENDPOINT_CHANGED:  //intentional fallthrough
                    case PEER_EVENT_MY_ENDPOINT_CHANGED:
                              DisplayEndpointChanged(&pEventData->endpointChangedData);
                              break;
                    case PEER_EVENT_PEOPLE_NEAR_ME_CHANGED:
                              DisplayPeopleNearMeChanged(&pEventData->peopleNearMeChangedData);
                              break;
                    case PEER_EVENT_REQUEST_STATUS_CHANGED:
                        DisplayRequestStatusChanged(&pEventData->requestStatusChangedData);
                        break;
                    default: //do nothing
                        break;
                }

                //Print a seperator line
                wprintf(L"--------------------------------\n");

                SAFE_PEER_FREE_DATA(pEventData);
            }
        }
    }
    else
    {
        wprintf(L"PeerCollabRegisterEvent failed.\nHRESULT=0x%x\n", hr);
        PrintError(hr);
    }

    hr = S_OK;

exit:

    if (hPeerEvent != NULL)
    {
        (void) PeerCollabUnregisterEvent(hPeerEvent);
        hPeerEvent = NULL;
    }

    if (hEvent[0] != NULL)
    {
        CloseHandle(hEvent[0]);
        hEvent[0] = NULL;
    }

    if (hEvent[1] != NULL)
    {
        CloseHandle(hEvent[1]);
        hEvent[1] = NULL;
    }

    return hr; 
}