2025-11-28 00:35:46 +09:00

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;
}