340 lines
10 KiB
C
340 lines
10 KiB
C
/**********************************************************************
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
PARTICULAR PURPOSE.
|
|
|
|
Copyright (c) Microsoft Corporation. All Rights Reserved.
|
|
|
|
Module Name:
|
|
|
|
PeoplePickerModel.c
|
|
|
|
Abstract:
|
|
|
|
This C file includes sample code for the model associated with the
|
|
People Picker dialog.
|
|
|
|
--********************************************************************/
|
|
|
|
#pragma warning(disable:4201) // nameless struct/union
|
|
|
|
#include "PeoplePickerModel.h"
|
|
|
|
// Forward Declarations
|
|
VOID CALLBACK ProcessUpdateCallBack(LPVOID lpContext, BOOLEAN fTimer);
|
|
HRESULT MonitorPeopleNearMe();
|
|
HRESULT EnumPeopleNearMe();
|
|
|
|
// Variables
|
|
static HPEEREVENT g_hModelPeerEvent = NULL;
|
|
static HANDLE g_hModelWaitObject = NULL;
|
|
static HANDLE g_hModelEvent = NULL;
|
|
static HWND g_hModelDlgOwner = NULL;
|
|
|
|
//-----------------------------------------------------------------------------------
|
|
// Function: InitPeoplePickerDataModel
|
|
//
|
|
// Purpose: Initializes the people picker data model and associates with a dialog
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
HRESULT InitPeoplePickerModel(HWND hDlg)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
g_hModelDlgOwner = hDlg;
|
|
|
|
// Start to monitor people near me
|
|
//
|
|
hr = MonitorPeopleNearMe();
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Enumerate the people near me
|
|
//
|
|
hr = EnumPeopleNearMe();
|
|
return hr;
|
|
}
|
|
|
|
MessageBox(g_hModelDlgOwner, L"Error", L"Error monitoring PNM", MB_OK);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Function: DuplicatePeerPeopleNearMe
|
|
//
|
|
// Purpose: Duplicates a PEER_PEOPLE_NEAR_ME structure
|
|
// It allocates a copy, so the caller needs to free
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
HRESULT DuplicatePeerPeopleNearMe(PEER_PEOPLE_NEAR_ME ** ppPersonDestination, PEER_PEOPLE_NEAR_ME * pPersonSource)
|
|
{
|
|
size_t cbNickName = 0;
|
|
size_t cbEndpointName = 0;
|
|
PEER_PEOPLE_NEAR_ME * pTempDestination = NULL;
|
|
|
|
//Get size of NickName
|
|
//
|
|
cbNickName = (wcslen(pPersonSource->pwzNickName) * sizeof(WCHAR)) + sizeof(WCHAR);
|
|
cbEndpointName = (wcslen(pPersonSource->endpoint.pwzEndpointName) * sizeof(WCHAR)) + sizeof(WCHAR);
|
|
|
|
//Allocate nick name and PEER_PEOPLE_NEAR_ME structure
|
|
//
|
|
pTempDestination = (PEER_PEOPLE_NEAR_ME *) malloc(sizeof(PEER_PEOPLE_NEAR_ME));
|
|
|
|
if (NULL == pTempDestination)
|
|
return E_OUTOFMEMORY;
|
|
|
|
ZeroMemory(pTempDestination, sizeof(PEER_PEOPLE_NEAR_ME));
|
|
|
|
pTempDestination->pwzNickName = (PWSTR) malloc(cbNickName);
|
|
|
|
if (NULL == pTempDestination->pwzNickName)
|
|
{
|
|
// Free the allocated memory if a Nickname cannot be allocated
|
|
//
|
|
PeoplePickerModelFreePerson(pTempDestination);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Assigning the structure, then pointing to newly allocated memory
|
|
// Need to do the structure copy first before the allocation, otherwise we overwrite our pointer
|
|
//
|
|
pTempDestination->endpoint = pPersonSource->endpoint;
|
|
pTempDestination->endpoint.pwzEndpointName = (PWSTR) malloc(cbEndpointName);
|
|
|
|
if (NULL == pTempDestination->endpoint.pwzEndpointName)
|
|
{
|
|
// Free the allocated memory if a endpoint name cannot be allocated
|
|
//
|
|
PeoplePickerModelFreePerson(pTempDestination);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//Copy the relevant fields into the PEER_PEOPLE_NEAR_ME structure
|
|
//
|
|
memcpy(pTempDestination->endpoint.pwzEndpointName, pPersonSource->endpoint.pwzEndpointName, cbEndpointName);
|
|
pTempDestination->id = pPersonSource->id;
|
|
memcpy(pTempDestination->pwzNickName, pPersonSource->pwzNickName, cbNickName);
|
|
|
|
*ppPersonDestination = pTempDestination;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Function: PeoplePickerModelFreePerson
|
|
//
|
|
// Purpose: Frees a PEER_PEOPLE_NEAR_ME structure allocated by the model
|
|
//
|
|
// Returns: VOID
|
|
//
|
|
VOID PeoplePickerModelFreePerson(PEER_PEOPLE_NEAR_ME * pPersonNearMe)
|
|
{
|
|
if (NULL != pPersonNearMe)
|
|
{
|
|
free(pPersonNearMe->pwzNickName);
|
|
free(pPersonNearMe->endpoint.pwzEndpointName);
|
|
free(pPersonNearMe);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Function: PeoplePickerModelDestroy
|
|
//
|
|
// Purpose: Frees up all the resources needed by the model
|
|
//
|
|
// Returns: VOID
|
|
//
|
|
VOID PeoplePickerModelDestroy()
|
|
{
|
|
UnregisterWaitEx(g_hModelWaitObject,INVALID_HANDLE_VALUE);
|
|
PeerCollabUnregisterEvent(g_hModelPeerEvent);
|
|
CloseHandle(g_hModelEvent);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Function: ProcessUpdateCallBack
|
|
//
|
|
// Purpose: Called when PEER_EVENT_PEOPLE_NEAR_ME_CHANGED event is received
|
|
// Reads in event data and displays the type of change
|
|
//
|
|
// Returns: VOID
|
|
//
|
|
VOID CALLBACK ProcessUpdateCallBack(LPVOID lpContext, BOOLEAN fTimer)
|
|
{
|
|
PEER_COLLAB_EVENT_DATA * pEventData = NULL;
|
|
PEER_PEOPLE_NEAR_ME * pPersonNearMe = NULL;
|
|
|
|
//Unreferenced parameters
|
|
lpContext;
|
|
fTimer;
|
|
|
|
while (SUCCEEDED(PeerCollabGetEventData(g_hModelPeerEvent, &pEventData)) && pEventData)
|
|
{
|
|
// NULL for the PPEER_PEOPLE_NEAR_ME means this event is for the local person
|
|
//
|
|
if (pEventData->peopleNearMeChangedData.pPeopleNearMe == NULL)
|
|
{
|
|
// PEER_CHANGED_ADDED on the local person means they have signed into people near me
|
|
//
|
|
if (pEventData->peopleNearMeChangedData.changeType == PEER_CHANGE_ADDED)
|
|
{
|
|
InitPeoplePickerModel(g_hModelDlgOwner);
|
|
}
|
|
|
|
// PEER_CHANGED_ADDED on the local person means they have signed out of people near me
|
|
//
|
|
if (pEventData->peopleNearMeChangedData.changeType == PEER_CHANGE_DELETED)
|
|
{
|
|
PostMessage(g_hModelDlgOwner, WM_CLEARPEOPLE, 0, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Copy the person to give to dialog
|
|
//
|
|
if (SUCCEEDED(DuplicatePeerPeopleNearMe(&pPersonNearMe, pEventData->peopleNearMeChangedData.pPeopleNearMe)))
|
|
{
|
|
// The person was added (signed-in), so tell the dialog to add the person
|
|
//
|
|
if (pEventData->peopleNearMeChangedData.changeType == PEER_CHANGE_ADDED)
|
|
{
|
|
PostMessage(g_hModelDlgOwner, WM_ADDPERSON, 0, (LPARAM) pPersonNearMe);
|
|
}
|
|
|
|
// The person was deleted (signed-out), so tell dialog to remove the person
|
|
//
|
|
if (pEventData->peopleNearMeChangedData.changeType == PEER_CHANGE_DELETED)
|
|
{
|
|
PostMessage(g_hModelDlgOwner, WM_REMOVEPERSON, 0, (LPARAM) pPersonNearMe);
|
|
}
|
|
}
|
|
}
|
|
// Free the used PEER resources
|
|
//
|
|
PeerFreeData(pEventData);
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Function: MonitorPeopleNearMe
|
|
//
|
|
// Purpose: Watches for change events in PeopleNearMe data
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
HRESULT MonitorPeopleNearMe()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PEER_COLLAB_EVENT_REGISTRATION eventReg = {0};
|
|
|
|
// Create the event handle for the model
|
|
//
|
|
g_hModelEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
|
|
if (NULL == g_hModelEvent)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Setup the event registration specifying the type of event to be notified about
|
|
//
|
|
eventReg.eventType = PEER_EVENT_PEOPLE_NEAR_ME_CHANGED;
|
|
eventReg.pInstance = NULL;
|
|
|
|
// Register to be notified when the People Near Me change
|
|
//
|
|
hr = PeerCollabRegisterEvent(g_hModelEvent, 1, &eventReg, &g_hModelPeerEvent);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Registers a wait object that will call ProcessUpdateCallBack
|
|
// whenever a PEER_EVENT_PEOPLE_NEAR_ME_CHANGED is received.
|
|
//
|
|
if (!RegisterWaitForSingleObject(&g_hModelWaitObject,
|
|
g_hModelEvent,
|
|
ProcessUpdateCallBack,
|
|
NULL,
|
|
INFINITE,
|
|
0))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
MessageBox(g_hModelDlgOwner, L"Error", L"Could not initialize People Near Me monitoring.", MB_OK);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Function: EnumPeopleNearMe
|
|
//
|
|
// Purpose: Simple wrapper function that calls PeerCollabEnumPeopleNearMe
|
|
// and displays the results. Setting fPrompt flag prompts user
|
|
// to select an endpoint for further information.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
HRESULT EnumPeopleNearMe()
|
|
{
|
|
PEER_PEOPLE_NEAR_ME ** ppPeopleNearMe = NULL;
|
|
PEER_PEOPLE_NEAR_ME * pPersonNearMe = NULL;
|
|
HRESULT hr = S_OK;
|
|
HPEERENUM hEnum = NULL;
|
|
ULONG count = 0;
|
|
ULONG index = 0;
|
|
|
|
// Enumerate the people near me and setup the enumeration
|
|
//
|
|
hr = PeerCollabEnumPeopleNearMe(&hEnum);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = PeerGetItemCount(hEnum, &count);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (count == 0)
|
|
{
|
|
PeerEndEnumeration(hEnum);
|
|
return hr;
|
|
}
|
|
hr = PeerGetNextItem(hEnum, &count, (PVOID **) &ppPeopleNearMe);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Add people to dialog
|
|
//
|
|
while (index < count)
|
|
{
|
|
if (SUCCEEDED(DuplicatePeerPeopleNearMe(&pPersonNearMe, ppPeopleNearMe[index])))
|
|
{
|
|
//Add the person to the Listview
|
|
//
|
|
PostMessage(g_hModelDlgOwner, WM_ADDPERSON, 0, (LPARAM) pPersonNearMe);
|
|
}
|
|
index++;
|
|
}
|
|
// Free the used PEER resources
|
|
//
|
|
PeerFreeData(ppPeopleNearMe);
|
|
}
|
|
|
|
// End the PEER enumeration
|
|
//
|
|
PeerEndEnumeration(hEnum);
|
|
}
|
|
return hr;
|
|
}
|
|
|