1444 lines
53 KiB
C++
1444 lines
53 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:
|
|
// MyDeviceSyncHandler.cpp
|
|
//
|
|
// Abstract:
|
|
// Implementation of the Sync Center device handler for a device.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "Pch.h"
|
|
#include "MyDeviceSyncHandler.h"
|
|
#include "SetupUI.h"
|
|
#include "Guids.h" // Declare the GUIDs used by this component.
|
|
#include "Resources.h"
|
|
|
|
#include <stdlib.h> // Used for generating random errors
|
|
#include <time.h>
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// class CMyDeviceSyncHandler
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Create an instance of the device handler class.
|
|
//
|
|
// Parameters:
|
|
// punkOuter - Outer IUnknown for aggregation.
|
|
// riid - ID of interface to return pointer to.
|
|
// pDeviceInfo - Info about the device to create the handler for.
|
|
// ppv - Interface pointer.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_OUTOFMEMORY - Error allocating the object.
|
|
// Other HRESULTs - Error querying for requested interface.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CMyDeviceSyncHandler_CreateInstance(
|
|
__in_opt IUnknown *punkOuter,
|
|
__in REFIID riid,
|
|
__in SYNCDEVICEINFO *pDeviceInfo,
|
|
__deref_out void **ppv)
|
|
{
|
|
*ppv = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(punkOuter);
|
|
|
|
CMyDeviceSyncHandler *psh = new CMyDeviceSyncHandler(pDeviceInfo);
|
|
HRESULT hr = (psh != NULL) ? S_OK : E_OUTOFMEMORY;
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = psh->QueryInterface(riid, ppv);
|
|
psh->Release();
|
|
}
|
|
|
|
return hr;
|
|
|
|
} //*** CMyDeviceSyncHandler_CreateInstance
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Constructor.
|
|
//
|
|
// Parameters:
|
|
// pDeviceInfo
|
|
// Structure containing information about the device this handler is for.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CMyDeviceSyncHandler::CMyDeviceSyncHandler(__in const SYNCDEVICEINFO *pDeviceInfo)
|
|
:
|
|
_cRef(1),
|
|
_cItems(0),
|
|
_ppItems(NULL),
|
|
_pszPartnershipName(NULL)
|
|
{
|
|
DllAddRef();
|
|
_nPartnerID = pDeviceInfo->nPartnerID;
|
|
|
|
// Truncate if source string is too long.
|
|
// Space for displaying the name is limited.
|
|
StringCchCopyNW(_szHandlerID, ARRAYSIZE(_szHandlerID), pDeviceInfo->szHandlerID, ARRAYSIZE(pDeviceInfo->szHandlerID));
|
|
StringCchCopyNW(_szDeviceName, ARRAYSIZE(_szDeviceName), pDeviceInfo->szName, ARRAYSIZE(pDeviceInfo->szName));
|
|
|
|
} //*** CMyDeviceSyncHandler::CMyDeviceSyncHandler
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Destructor.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CMyDeviceSyncHandler::~CMyDeviceSyncHandler()
|
|
{
|
|
if (_pszPartnershipName)
|
|
{
|
|
LocalFree(_pszPartnershipName);
|
|
}
|
|
if (_ppItems != NULL)
|
|
{
|
|
for (ULONG iItem = 0; iItem < _cItems; iItem++)
|
|
{
|
|
if (_ppItems[iItem] != NULL)
|
|
{
|
|
_ppItems[iItem]->Release();
|
|
}
|
|
}
|
|
|
|
delete [] _ppItems;
|
|
}
|
|
|
|
DllRelease();
|
|
|
|
} //*** destructor CMyDeviceSyncHandler::~CMyDeviceSyncHandler
|
|
|
|
//----------------------------------------------------------------------------
|
|
// IUnknown (CMyDeviceSyncHandler)
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CMyDeviceSyncHandler::QueryInterface(__in REFIID riid, __deref_out void **ppv)
|
|
{
|
|
static const QITAB qit[] =
|
|
{
|
|
QITABENT(CMyDeviceSyncHandler, ISyncMgrHandler),
|
|
QITABENT(CMyDeviceSyncHandler, ISyncMgrSyncItemContainer),
|
|
QITABENT(CMyDeviceSyncHandler, ISyncMgrHandlerInfo),
|
|
{ 0 },
|
|
};
|
|
|
|
return QISearch(this, qit, riid, ppv);
|
|
|
|
} //*** CMyDeviceSyncHandler::QueryInterface
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CMyDeviceSyncHandler::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement(&_cRef);
|
|
if (cRef == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return cRef;
|
|
|
|
} //*** CMyDeviceSyncHandler::Release
|
|
|
|
//----------------------------------------------------------------------------
|
|
// ISyncMgrHandler (CMyDeviceSyncHandler)
|
|
//----------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to get the name of the handler. This name will
|
|
// be displayed in the main Sync Center folder.
|
|
//
|
|
// Implements: ISyncMgrHandler
|
|
//
|
|
// Parameters:
|
|
// ppszName
|
|
// Name of the handler being returned. Caller will free using
|
|
// CoTaskMemFree().
|
|
//
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetName(__deref_out LPWSTR *ppszName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
*ppszName = NULL;
|
|
|
|
// Construct the name of the partnership from the name of the device and
|
|
// save it for future uses.
|
|
if (_pszPartnershipName == NULL)
|
|
{
|
|
hr = FormatString(g_hmodThisDll, IDS_DEVICE_FORMAT, &_pszPartnershipName, _szDeviceName);
|
|
} // if: partnership name not constructed yet
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SHStrDupW(_pszPartnershipName, ppszName);
|
|
} // if: partnership name loaded successfully
|
|
|
|
return hr;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetName
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to get information about the handler.
|
|
//
|
|
// Parameters:
|
|
// ppHandlerInfo - Interface for getting handler info to return to Sync Center.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetHandlerInfo(__deref_out ISyncMgrHandlerInfo **ppHandlerInfo)
|
|
{
|
|
return QueryInterface(IID_PPV_ARGS(ppHandlerInfo));
|
|
|
|
} //*** CMyDeviceSyncHandler::GetHandlerInfo
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to get an interface pointer for a specific
|
|
// type of object.
|
|
//
|
|
// Implements: ISyncMgrHandler
|
|
//
|
|
// Parameters:
|
|
// rguidObjectID - GUID for the item to get the object for.
|
|
// riid - Interface to get.
|
|
// ppv - Interface returned to Sync Center
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_NOTIMPL - Object not supported by the handler.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetObject(
|
|
__in REFGUID rguidObjectID,
|
|
__in REFIID riid,
|
|
__deref_out void **ppv)
|
|
{
|
|
HRESULT hr = E_NOTIMPL;
|
|
*ppv = NULL;
|
|
|
|
if (rguidObjectID == SYNCMGR_OBJECTID_QueryBeforeActivate)
|
|
{
|
|
hr = CMyDeviceSetupUI_CreateInstance(this, riid, ppv);
|
|
}
|
|
else if (rguidObjectID == SYNCMGR_OBJECTID_BrowseContent)
|
|
{
|
|
hr = CBrowseUI_CreateInstance(FOLDERID_Profile, riid, ppv);
|
|
}
|
|
else if (rguidObjectID == SYNCMGR_OBJECTID_ShowSchedule)
|
|
{
|
|
// Create the Schedule Wizard UI operation and initialize it.
|
|
ISyncMgrScheduleWizardUIOperation *pUIOperation = NULL;
|
|
hr = CoCreateInstance(CLSID_SyncMgrScheduleWizard, NULL, CLSCTX_SERVER, IID_PPV_ARGS(&pUIOperation));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pUIOperation->InitWizard(_szHandlerID);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pUIOperation->QueryInterface(riid, ppv);
|
|
}
|
|
|
|
pUIOperation->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetObject
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to get the mask of capabilities of the handler.
|
|
// The following capabilities are defined:
|
|
//
|
|
// SYNCMGR_HCM_NONE
|
|
// No capabilities are specified.
|
|
//
|
|
// SYNCMGR_HCM_PROVIDES_ICON
|
|
// Indicates that the handler will return a valid object from the
|
|
// GetObject() method when SYNCMGR_OBJECTID_Icon is specified.
|
|
//
|
|
// SYNCMGR_HCM_EVENT_STORE
|
|
// Indicates that the handler will return a valid object from the
|
|
// GetObject() method when SYNCMGR_OBJECTID_EventStore is specified.
|
|
//
|
|
// SYNCMGR_HCM_CONFLICT_STORE
|
|
// Indicates that the handler will return a valid object from the
|
|
// GetObject() method when SYNCMGR_OBJECTID_ConflictStore is
|
|
// specified.
|
|
//
|
|
// SYNCMGR_HCM_CAN_ENABLE
|
|
// Indicates whether the handler wants to allow the user to enable
|
|
// the handler. Typically a handler is enabled if at least one of
|
|
// its items is enabled and it is disabled if all of its items are
|
|
// disabled. Setting this value allows a handler to implement
|
|
// handler-wide enable functionality. If this value is set the
|
|
// Enable task will be shown in the main Sync Center folder when
|
|
// this handler is selected.
|
|
//
|
|
// SYNCMGR_HCM_CAN_DISABLE
|
|
// Indicate whether the handler wants to allow the user to disable
|
|
// the handler. Typically a handler is enabled if at least on of its
|
|
// items Is enabled and it is disabled if all of its items are
|
|
// disabled. Setting this value allows a handler to implement
|
|
// handler-wide disable functionality. It can also be used by a
|
|
// handler to implement support for group policy that forces a
|
|
// handler to always be able to sync. If this value is set the
|
|
// Disable task will be shown in the main Sync Center folder when
|
|
// this handler is selected.
|
|
//
|
|
// SYNCMGR_HCM_CAN_BROWSE_CONTENT
|
|
// Indicates that the handler will return a valid object from the
|
|
// GetObject() method when SYNCMGR_OBJECTID_BrowseContent is
|
|
// specified. If this value is set, the Browse Content task will be
|
|
// added to the context menu for the handler.
|
|
//
|
|
// SYNCMGR_HCM_CAN_SHOW_SCHEDULE
|
|
// Indicates that the handler will return a valid object from the
|
|
// GetObject() method when SYNCMGR_OBJECTID_ShowSchedule is
|
|
// specified. If this value is set, the Show Schedule task will be
|
|
// added to the context menu for the handler.
|
|
//
|
|
// SYNCMGR_HCM_QUERY_BEFORE_ACTIVATE
|
|
// Indicates that the handler will return a valid object from the
|
|
// GetObject() method when SYNCMGR_OBJECTID_QueryBeforeActivate is
|
|
// specified.
|
|
//
|
|
// SYNCMGR_HCM_QUERY_BEFORE_DEACTIVATE
|
|
// Indicates that the handler will return a valid object from the
|
|
// GetObject() method when SYNCMGR_OBJECTID_QueryBeforeDeactivate is
|
|
// specified.
|
|
//
|
|
// SYNCMGR_HCM_QUERY_BEFORE_ENABLE
|
|
// Indicates that the handler will return a valid object from the
|
|
// GetObject() method when SYNCMGR_OBJECTID_QueryBeforeEnable is
|
|
// specified.
|
|
//
|
|
// SYNCMGR_HCM_QUERY_BEFORE_DISABLE
|
|
// Indicates that the handler will return a valid object from the
|
|
// GetObject() method when SYNCMGR_OBJECTID_QueryBeforeDisable is
|
|
// specified.
|
|
//
|
|
//
|
|
// Implements: ISyncMgrHandler
|
|
//
|
|
// Parameters:
|
|
// pmCapabilities - Capabilities mask being returned.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetCapabilities(__out SYNCMGR_HANDLER_CAPABILITIES *pmCapabilities)
|
|
{
|
|
*pmCapabilities = (SYNCMGR_HANDLER_CAPABILITIES) (SYNCMGR_HCM_QUERY_BEFORE_ACTIVATE
|
|
| SYNCMGR_HCM_CAN_SHOW_SCHEDULE
|
|
| SYNCMGR_HCM_CAN_BROWSE_CONTENT);
|
|
return S_OK;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetCapabilities
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to get the mask of policies of the handler.
|
|
// The following policies are defined:
|
|
//
|
|
// SYNCMGR_HPM_NONE
|
|
// No policies are specified.
|
|
//
|
|
// SYNCMGR_HPM_PREVENT_ACTIVATE
|
|
// Indicates that activation of the handler is not supported. This
|
|
// can be used by a handler to implement support for group policy
|
|
// that prevents a handler from being setup. If this value is set,
|
|
// the Setup task will be not shown in the Setup Sync folder when
|
|
// this handler is selected. Most handlers should not set this
|
|
// value.
|
|
//
|
|
// SYNCMGR_HPM_PREVENT_DEACTIVATE
|
|
// Indicates that deactivation of the handler is not supported. This
|
|
// can be used by a handler to implement support for group policy
|
|
// that prevents a handler from being removed from the main Sync
|
|
// Center folder. If this value is set, the Delete task will be not
|
|
// shown in the main Sync Center folder when this handler is
|
|
// selected. Most handlers should not set this value.
|
|
//
|
|
// SYNCMGR_HPM_PREVENT_ENABLE
|
|
// Indicates that enabling the handler is not supported. This can be
|
|
// used by a handler to implement support for group policy that
|
|
// prevents the handler from being enabled. If this value is set the
|
|
// Enable task will not be shown in the main Sync Center folder when
|
|
// this handler is selected. The handler should provide a comment
|
|
// (returned from its implement of the GetComment() method on
|
|
// ISyncMgrHandlerInfo) to let the user know why the Enable task is
|
|
// not available. Most handlers should never set this value.
|
|
//
|
|
// SYNCMGR_HPM_PREVENT_DISABLE
|
|
// Indicates that disabling the handler is not supported. This can
|
|
// be used by a handler to implement support for group policy that
|
|
// forces the handler to always be able to sync. If this value is
|
|
// set the Disable task will not be shown in the main Sync Center
|
|
// folder when this handler is selected. The handler should provide
|
|
// a comment (returned from its implementation of the GetComment()
|
|
// method on ISyncMgrHandlerInfo) to let the user know why the
|
|
// Disable task is not available. Most handlers should never set
|
|
// this value.
|
|
//
|
|
// SYNCMGR_HPM_PREVENT_START_SYNC
|
|
// Indicates that starting a sync through the user interface or
|
|
// through the APIs is not supported. Sync can only be started by
|
|
// an external application that creates a session creator to report
|
|
// progress. If this value is set, the Start Sync task will not be
|
|
// shown in the main Sync Center folder when the handler is selected.
|
|
// Most handlers should not set this value.
|
|
//
|
|
// SYNCMGR_HPM_PREVENT_STOP_SYNC
|
|
// Indicates that stopping a sync through the user interface or
|
|
// through the APIs is not supported. If this value is set, the Stop
|
|
// Sync task will not be shown in the main Sync Center folder when
|
|
// the handler is selected. Most handlers should not set this value.
|
|
//
|
|
// SYNCMGR_HPM_DISABLE_ENABLE
|
|
// Indicates that the enable task should be disabled when it is
|
|
// shown for this handler. With this policy set, the Enable option
|
|
// will appear in the context menu (if SYNCMGR_HPM_PREVENT_ENABLE is
|
|
// not set) but will be disabled.
|
|
//
|
|
// SYNCMGR_HPM_DISABLE_DISABLE
|
|
// Indicates that the disable task should be disabled when it is
|
|
// shown for this handler. With this policy set, the Disable option
|
|
// will appear in the context menu (if SYNCMGR_HPM_PREVENT_DISABLE is
|
|
// not set) but will be disabled.
|
|
//
|
|
// SYNCMGR_HPM_DISABLE_START_SYNC
|
|
// Indicates that the Start Sync task should be disabled when it is
|
|
// shown for this handler. With this policy set, the Start Sync
|
|
// option will appear in the context menu (if
|
|
// SYNCMGR_HPM_PREVENT_START_SYNC not set) but will be disabled.
|
|
//
|
|
// SYNCMGR_HPM_DISABLE_STOP_SYNC
|
|
// Indicates that the Stop Sync task should be disabled when it is
|
|
// shown for this handler. With this policy set, the Stop Sync
|
|
// option will appear in the context menu (if
|
|
// SYNCMGR_HPM_PREVENT_STOP_SYNC not set) but will be disabled.
|
|
//
|
|
// SYNCMGR_HPM_DISABLE_BROWSE
|
|
// Indicates that the Browse task should be disabled when it is shown
|
|
// for this handler. The Browse task will only be shown if the
|
|
// SYNCMGR_HCM_CAN_BROWSE_CONTENT value is returned from the
|
|
// GetCapabilities() method.
|
|
//
|
|
// SYNCMGR_HPM_DISABLE_SCHEDULE
|
|
// Indicates that the Schedule task should be disabled when it is
|
|
// shown for this handler. The Schedule task will only be shown if
|
|
// the SYNCMGR_HCM_CAN_SHOW_SCHEDULE value is returned from the
|
|
// GetCapabilities() method.
|
|
//
|
|
// SYNCMGR_HPM_HIDDEN_BY_DEFAULT
|
|
// Indicates that the handler should be hidden from the user unless
|
|
// the Show Hidden Files option has been enabled. This policy only
|
|
// applies the first time the handler is loaded. After that, the
|
|
// hidden state is maintained by Sync Center and can be changed by
|
|
// the user through the property sheet.
|
|
//
|
|
// SYNCMGR_HPM_BACKGROUND_SYNC_ONLY
|
|
// Equivalent to setting the SYNCMGR_HPM_DISABLE_START_SYNC and
|
|
// SYNCMGR_HPM_DISABLE_STOP_SYNC values.
|
|
//
|
|
// Implements: ISyncMgrHandler
|
|
//
|
|
// Parameters:
|
|
// pmPolicies - Policy mask being returned.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetPolicies(__out SYNCMGR_HANDLER_POLICIES *pmPolicies)
|
|
{
|
|
*pmPolicies = SYNCMGR_HPM_NONE;
|
|
return S_OK;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetPolicies
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center when the user chooses to setup or delete
|
|
// the handler from the Sync Setup folder.
|
|
//
|
|
// Implements: ISyncMgrHandler
|
|
//
|
|
// Return Values:
|
|
// S_OK - Handler changed activation state successfully.
|
|
// Failure HRESULTs - Handler failed to change the activation state.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::Activate(BOOL fActivate)
|
|
{
|
|
// Note that your handler will still be called on IsActive() to
|
|
// to determine its activation state.
|
|
UNREFERENCED_PARAMETER(fActivate);
|
|
return S_OK;
|
|
|
|
} //*** CMyDeviceSyncHandler::Activate
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center when the user chooses to enable or disable the
|
|
// handler from the main Sync Center folder.
|
|
//
|
|
// Implements: ISyncMgrHandler
|
|
//
|
|
// Return Values:
|
|
// S_OK - Handler changed enabled state successfully.
|
|
// Failure HRESULTs - Handler failed to change the enabled state.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::Enable(BOOL fEnable)
|
|
{
|
|
// Note that your handler will still be called on IsEnabled() to
|
|
// determine its enabled state.
|
|
UNREFERENCED_PARAMETER(fEnable);
|
|
return S_OK;
|
|
|
|
} //*** CMyDeviceSyncHandler::Enable
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to perform a synchronization of the specified
|
|
// items.
|
|
//
|
|
// Implements: ISyncMgrHandler
|
|
//
|
|
// Parameters:
|
|
// cItems
|
|
// Number of items to sync.
|
|
//
|
|
// ppszItemIDs
|
|
// Array of items to sync.
|
|
//
|
|
// hwndOwner
|
|
// Owner window handle.
|
|
//
|
|
// pCreator
|
|
// Sync session creator interface.
|
|
//
|
|
// punk
|
|
// IUnknown passed to the StartHandlerSync() or StartItemSync()
|
|
// methods on the ISyncMgrControl interface.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed.
|
|
// Other HRESULT.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CMyDeviceSyncHandler::Synchronize(
|
|
__in_ecount(cItems) LPCWSTR *ppszItemIDs,
|
|
__in ULONG cItems,
|
|
__in HWND hwndOwner,
|
|
__in ISyncMgrSessionCreator *pCreator,
|
|
__in_opt IUnknown *punk)
|
|
{
|
|
// TODO: Replace this sample code with real sync code.
|
|
// Note: If an external application performs the sync, simply signal that
|
|
// application and return. The external application then CoCreates
|
|
// CLSID_SyncMgrClient specifying ISyncMgrSessionCreator and creates a
|
|
// session to report sync progress and state.
|
|
|
|
UNREFERENCED_PARAMETER(hwndOwner);
|
|
UNREFERENCED_PARAMETER(punk);
|
|
|
|
// Seed the random number generator - we will use this to generate some errors.
|
|
// This line should be removed when implementing a real handler.
|
|
srand((unsigned)time(0));
|
|
|
|
// Create a sync session. If sync occurs in an external process, we would
|
|
// instead signal that process and have it create the sync session.
|
|
ISyncMgrSyncCallback *pCallback = NULL;
|
|
HRESULT hr = pCreator->CreateSession(_szHandlerID, ppszItemIDs, cItems, &pCallback);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Loop through each item until we finish or we receive a
|
|
// cancel request.
|
|
SYNCMGR_CANCEL_REQUEST nCancelRequest = SYNCMGR_CR_NONE;
|
|
HRESULT hrSync = S_OK;
|
|
|
|
// Send the initial progress on the handler
|
|
ULONG uCurrentHandlerStep = 1;
|
|
ULONG cMaxHandlerSteps = cItems * 50;
|
|
_SetHandlerProgressText(pCallback, IDS_FILE_SYNC_STEP, &nCancelRequest, 0, cMaxHandlerSteps);
|
|
|
|
for (ULONG iItem = 0; iItem < cItems; iItem++)
|
|
{
|
|
// Find the item.
|
|
PCWSTR pszItemID = ppszItemIDs[iItem];
|
|
CMyDeviceSyncItem *pItem = _FindItem(pszItemID);
|
|
if (pItem == NULL)
|
|
{
|
|
_ReportItemProgress(pCallback, pszItemID, IDS_ITEM_NOT_FOUND, SYNCMGR_PS_FAILED, 0, 0, &nCancelRequest);
|
|
continue;
|
|
} // if: couldn't find requested item
|
|
|
|
// If the handler was canceled, acknowledge the cancel request.
|
|
if (nCancelRequest == SYNCMGR_CR_CANCEL_ALL)
|
|
{
|
|
// Report that this item has been canceled and proceed to
|
|
// the next item. If no progress is reported for an item,
|
|
// Sync Center will mark it as failed.
|
|
_ReportItemProgress(pCallback, pszItemID, 0, SYNCMGR_PS_CANCELED, 0, 0, &nCancelRequest);
|
|
continue;
|
|
}
|
|
|
|
// Send the initial progress report to set the max value.
|
|
ULONG uCurrentStep = 1;
|
|
ULONG cMaxSteps = 50;
|
|
_ReportItemProgress(pCallback, pszItemID, pItem->GetSyncTextID(), SYNCMGR_PS_UPDATING, 0, cMaxSteps, &nCancelRequest);
|
|
if (nCancelRequest == SYNCMGR_CR_NONE)
|
|
{
|
|
int nDocsCompareResult = CompareStringOrdinal(pszItemID, -1, L"Documents", -1, TRUE);
|
|
|
|
for (; (uCurrentStep <= cMaxSteps) && (SUCCEEDED(hrSync)); uCurrentStep++, uCurrentHandlerStep++)
|
|
{
|
|
// Simulate warning for sample purposes only.
|
|
// This will generate a warning on the 40th Documents item.
|
|
if ((nDocsCompareResult == CSTR_EQUAL) && (uCurrentStep == 40))
|
|
{
|
|
GUID guidEventID;
|
|
_ReportEvent(
|
|
pCallback,
|
|
pszItemID,
|
|
IDS_SYNC_WARNING_1,
|
|
IDS_SYNC_WARNING_DESC_1,
|
|
SYNCMGR_EL_WARNING,
|
|
SYNCMGR_EF_NONE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&guidEventID);
|
|
}
|
|
|
|
// Simulate errors for example purposes only.
|
|
// This will generate an error on an item
|
|
// synchronization with 10% probability.
|
|
int nRandError = (rand() % (50 * 10)) + 1;
|
|
if (nRandError == 1)
|
|
{
|
|
GUID guidEventID;
|
|
_ReportEvent(
|
|
pCallback,
|
|
pszItemID,
|
|
IDS_SYNC_ERROR_1,
|
|
IDS_SYNC_ERROR_DESC_1,
|
|
SYNCMGR_EL_ERROR,
|
|
SYNCMGR_EF_NONE,
|
|
NULL /*pszLinkText*/,
|
|
NULL /*pszLinkReference*/,
|
|
NULL /*pszContext*/,
|
|
&guidEventID);
|
|
hrSync = E_FAIL;
|
|
}
|
|
|
|
// Report progress.
|
|
_ReportItemProgress(
|
|
pCallback,
|
|
pszItemID,
|
|
pItem->GetSyncTextID(),
|
|
SYNCMGR_PS_UPDATING,
|
|
uCurrentStep,
|
|
cMaxSteps,
|
|
&nCancelRequest,
|
|
uCurrentStep,
|
|
cMaxSteps);
|
|
if (nCancelRequest != SYNCMGR_CR_NONE)
|
|
{
|
|
// The handler or item has been canceled.
|
|
break;
|
|
}
|
|
|
|
// Update the info text shown for the handler.
|
|
_SetHandlerProgressText(
|
|
pCallback,
|
|
IDS_FILE_SYNC_STEP,
|
|
&nCancelRequest,
|
|
uCurrentHandlerStep,
|
|
cMaxHandlerSteps);
|
|
if (nCancelRequest != SYNCMGR_CR_NONE)
|
|
{
|
|
// The handler has been canceled.
|
|
break;
|
|
}
|
|
|
|
// TODO: Implement synchronization here instead of a call to Sleep().
|
|
Sleep(100);
|
|
|
|
} // for: each sync pass
|
|
} // if: not canceled
|
|
|
|
// We're done synchronizing, but regardless of our current state,
|
|
// we need to send a final progress update to Sync Center so the
|
|
// UI properly reflects the current state of the item.
|
|
if (nCancelRequest == SYNCMGR_CR_NONE)
|
|
{
|
|
// Send the final progress report for this item.
|
|
if (SUCCEEDED(hrSync))
|
|
{
|
|
_ReportItemProgress(pCallback, pszItemID, IDS_ITEM_SYNC_DONE, SYNCMGR_PS_SUCCEEDED, uCurrentStep - 1, cMaxSteps, &nCancelRequest);
|
|
}
|
|
else
|
|
{
|
|
_ReportItemProgress(pCallback, pszItemID, IDS_ITEM_FAILED, SYNCMGR_PS_FAILED, uCurrentStep - 1, cMaxSteps, &nCancelRequest, uCurrentStep - 1, cMaxSteps);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Report that the current item has canceled.
|
|
_ReportItemProgress(pCallback, pszItemID, 0, SYNCMGR_PS_CANCELED, uCurrentStep, cMaxSteps, &nCancelRequest);
|
|
}
|
|
|
|
hrSync = S_OK;
|
|
} // for: each item to sync
|
|
|
|
pCallback->Release();
|
|
} // if: sync session created successfully
|
|
|
|
return hr;
|
|
|
|
} //*** CMyDeviceSyncHandler::Synchronize
|
|
|
|
//----------------------------------------------------------------------------
|
|
// ISyncMgrHandlerInfo (CMyDeviceSyncHandler)
|
|
//----------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to get the handler type value for the handler.
|
|
// The following types are defined:
|
|
//
|
|
// SYNCMGR_HT_UNSPECIFIED
|
|
// All handlers that do not specify or do not fit
|
|
// in the rest of the options should use this value.
|
|
//
|
|
// SYNCMGR_HT_APPLICATION
|
|
// Handler is an application.
|
|
//
|
|
// SYNCMGR_HT_DEVICE
|
|
// Handler syncs with a device.
|
|
//
|
|
// SYNCMGR_HT_FOLDER
|
|
// Handler syncs with local or remote folders.
|
|
//
|
|
// SYNCMGR_HT_SERVICE
|
|
// Handler syncs with a web service.
|
|
//
|
|
// SYNCMGR_HT_COMPUTER
|
|
// Handler syncs with a computer.
|
|
//
|
|
// Implements: ISyncMgrHandlerInfo
|
|
//
|
|
// Parameters:
|
|
// pnType - Type to return to Sync Center.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetType(__out SYNCMGR_HANDLER_TYPE *pnType)
|
|
{
|
|
*pnType = SYNCMGR_HT_DEVICE;
|
|
return S_OK;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetType
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to get a label for the handler type. This is
|
|
// usually used to display the model of the device or some other handler-
|
|
// specific identifying string.
|
|
//
|
|
// Implements: ISyncMgrHandlerInfo
|
|
//
|
|
// Parameters:
|
|
// ppszLabel
|
|
// Pointer to fill with a pointer to a string. Must be allocated
|
|
// with CoTaskMemAlloc(). Sync Center will free this using
|
|
// CoTaskMemFree().
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_OUTOFMEMORY - Error allocating memory for the string buffer.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetTypeLabel(__deref_out LPWSTR *ppszLabel)
|
|
{
|
|
*ppszLabel = NULL;
|
|
|
|
WCHAR wszLabel[MAX_SYNCMGR_NAME];
|
|
|
|
HRESULT hr = E_FAIL;
|
|
// LoadString returns 0 if the string could not be found.
|
|
if (LoadStringW(g_hmodThisDll, IDS_HANDLER_TYPE_LABEL, wszLabel, ARRAYSIZE(wszLabel)) != 0)
|
|
{
|
|
hr = SHStrDupW(wszLabel, ppszLabel);
|
|
} // if: label string loaded successfully
|
|
|
|
return hr;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetTypeLabel
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to get a string to display in the folder in
|
|
// the far right column when a synchronization is not being performed.
|
|
// If no string is provided, a blank string will be displayed.
|
|
//
|
|
// Implements: ISyncMgrHandlerInfo
|
|
//
|
|
// Parameters:
|
|
// ppszComment
|
|
// Pointer to fill with a pointer to a string. Must be allocated
|
|
// with CoTaskMemAlloc(). Sync Center will free this using
|
|
// CoTaskMemFree().
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_OUTOFMEMORY - Error allocating memory for the string buffer.
|
|
// E_NOTIMPL - No comment is provided by the handler.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetComment(__deref_out LPWSTR *ppszComment)
|
|
{
|
|
UNREFERENCED_PARAMETER(ppszComment);
|
|
return E_NOTIMPL;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetComment
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to get the date and time the handler was last
|
|
// synchronized. If a failure is returned, the value calculated from the
|
|
// last synchronization will be used.
|
|
//
|
|
// Implements: ISyncMgrHandlerInfo
|
|
//
|
|
// Parameters:
|
|
// pftLastSync - Last sync time.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_NOTIMPL - No last sync time is provided by the handler.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetLastSyncTime(__out FILETIME *pftLastSync)
|
|
{
|
|
// If your handler does not return the last sync time,
|
|
// Sync Center will manage this state for you.
|
|
UNREFERENCED_PARAMETER(pftLastSync);
|
|
return E_NOTIMPL;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetLastSyncTime
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to determine whether the handler is active or
|
|
// not.
|
|
//
|
|
// If a handler is not active it appears in the Sync Setup folder.
|
|
// Handlers in that folder cannot be synced. To move a handler to the
|
|
// main Sync Center folder, the user selects the Setup task on the
|
|
// context menu or on the command module.
|
|
//
|
|
// If a handler is active it appears in the main Sync Center folder.
|
|
// A handler that is active can be synced by the user or through the
|
|
// ISyncMgrControl interface. To move a handler to the Sync Setup
|
|
// folder, the user selects the Delete task on the context menu or on the
|
|
// command module.
|
|
//
|
|
// If a handler doesn't want to maintain its active state, it can return
|
|
// E_NOTIMPL and Sync Center will maintain it for the handler.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Handler is active.
|
|
// S_FALSE - Handler is not active.
|
|
// E_NOTIMPL - Let Sync Center maintain the enabled state.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::IsActive()
|
|
{
|
|
return E_NOTIMPL;
|
|
|
|
} //*** CMyDeviceSyncHandler::IsActive
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to determine whether the handler is enabled or
|
|
// not.
|
|
//
|
|
// If a handler is disabled, neither it nor any of its items will be
|
|
// synchronized by Sync Center and many of the actions will be removed
|
|
// or disabled in the UI.
|
|
//
|
|
// If a handler doesn't want to maintain its enabled state, it can return
|
|
// E_NOTIMPL and Sync Center will maintain it for the handler.
|
|
//
|
|
// Implements: ISyncMgrHandlerInfo
|
|
//
|
|
// Return Values:
|
|
// S_OK - Handler is enabled.
|
|
// S_FALSE - Handler is not enabled.
|
|
// E_NOTIMPL - Let Sync Center maintain the enabled state.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::IsEnabled()
|
|
{
|
|
return E_NOTIMPL;
|
|
|
|
} //*** CMyDeviceSyncHandler::IsEnabled
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to determine whether the handler is in a
|
|
// connected state or not.
|
|
//
|
|
// If a handler is in a disconnected state, neither it nor any of its
|
|
// items will be synchronized by Sync Center and many of the actions
|
|
// will be removed or disabled in the UI.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Handler is connected.
|
|
// S_FALSE - Handler is disconnected.
|
|
// E_NOTIMPL - Handler doesn't support this state.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::IsConnected()
|
|
{
|
|
return E_NOTIMPL;
|
|
|
|
} //*** CMyDeviceSyncHandler::IsConnected
|
|
|
|
//----------------------------------------------------------------------------
|
|
// ISyncMgrItemContainer (CMyDeviceSyncHandler)
|
|
//----------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Return the specified sync item to Sync Center.
|
|
//
|
|
// Implements: ISyncMgrHandlerInfo
|
|
//
|
|
// Parameters:
|
|
// pszItemID - The ID of the item to return.
|
|
// ppItem - The item being returned.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetSyncItem(__in LPCWSTR pszItemID, __deref_out ISyncMgrSyncItem **ppItem)
|
|
{
|
|
*ppItem = NULL;
|
|
|
|
// Make sure the items have been loaded first.
|
|
HRESULT hr = _LoadItems();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (DWORD iItem = 0; iItem < _cItems; iItem++)
|
|
{
|
|
if ((_ppItems[iItem] != NULL) && (CompareSyncMgrID(_ppItems[iItem]->GetItemIDPointer(), pszItemID) == 0))
|
|
{
|
|
hr = _ppItems[iItem]->QueryInterface(IID_ISyncMgrSyncItem, (void **) ppItem);
|
|
break;
|
|
}
|
|
} // for: each item
|
|
}
|
|
|
|
return hr;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetSyncItem
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to return an enumeration of items managed by
|
|
// this handler.
|
|
//
|
|
// Implements: ISyncMgrHandlerInfo
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetSyncItemEnumerator(__deref_out IEnumSyncMgrSyncItems **ppenum)
|
|
{
|
|
*ppenum = NULL;
|
|
|
|
// Make sure the items have been loaded first.
|
|
HRESULT hr = _LoadItems();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = CEnumSyncMgrItems_CreateInstance(this, IID_PPV_ARGS(ppenum));
|
|
}
|
|
|
|
return hr;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetSyncItemEnumerator
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Called by Sync Center to get the count of items managed by this handler.
|
|
//
|
|
// Implements: ISyncMgrHandlerInfo
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// Other HRESULTs.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CMyDeviceSyncHandler::GetSyncItemCount(__out ULONG *pcItems)
|
|
{
|
|
// Make sure the items have been loaded.
|
|
HRESULT hr = _LoadItems();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*pcItems = _cItems;
|
|
}
|
|
|
|
return hr;
|
|
|
|
} //*** CMyDeviceSyncHandler::GetSyncItemCount
|
|
|
|
//----------------------------------------------------------------------------
|
|
// CMyDeviceSyncHandler Private Methods
|
|
//----------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Load items for the device handler.
|
|
// Model 1 - Single item representing all content.
|
|
// Model 2 - Multiple items representing each type of content.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_OUTOFMEMORY - Error allocating memory for the items.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CMyDeviceSyncHandler::_LoadItems()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (_ppItems == NULL)
|
|
{
|
|
// In this case, we're providing a static array of items that each
|
|
// handler will have. You could also store this information in the
|
|
// registry similar to how handler properties are stored in this sample.
|
|
// Alternatively, if the user has control over which items appear with
|
|
// each handler, this data could be generated dynamically.
|
|
struct DEVICE_ITEM_INFO
|
|
{
|
|
PCWSTR pszItemID;
|
|
UINT nItemNameStringID;
|
|
UINT nItemLabelStringID;
|
|
KNOWNFOLDERID folderID; // Folder which should open when the user browses on the item
|
|
UINT uSyncTextID; // Text to be displayed on the item during syncing ("Document x of X")
|
|
};
|
|
static const DEVICE_ITEM_INFO s_rgItemInfo[] =
|
|
{
|
|
{ L"Documents", IDS_ITEMNAME_DOCUMENTS, IDS_ITEMLABEL_DOCUMENTS, FOLDERID_Documents, IDS_DOC_SYNC_STEP },
|
|
{ L"Music", IDS_ITEMNAME_MUSIC, IDS_ITEMLABEL_MUSIC, FOLDERID_Music, IDS_SONG_SYNC_STEP },
|
|
{ L"Pictures", IDS_ITEMNAME_PICTURES, IDS_ITEMLABEL_PICTURES, FOLDERID_Pictures, IDS_PIC_SYNC_STEP }
|
|
};
|
|
|
|
// Allocate the array of sync item pointers.
|
|
_ppItems = new CMyDeviceSyncItem*[ARRAYSIZE(s_rgItemInfo)]();
|
|
hr = (_ppItems != NULL) ? S_OK : E_OUTOFMEMORY;
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Create each of the sync items.
|
|
_cItems = 0;
|
|
hr = S_OK;
|
|
for (int iItemInfo = 0; (iItemInfo < ARRAYSIZE(s_rgItemInfo)) && SUCCEEDED(hr); iItemInfo++)
|
|
{
|
|
// Retrieve the localized name of the item out of our resource
|
|
PWSTR pszItemName = NULL;
|
|
hr = FormatString(g_hmodThisDll, s_rgItemInfo[iItemInfo].nItemNameStringID, &pszItemName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Retrieve the localized label of the item out of our resource
|
|
PWSTR pszItemLabel = NULL;
|
|
hr = FormatString(g_hmodThisDll, s_rgItemInfo[iItemInfo].nItemLabelStringID, &pszItemLabel);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Create our item with our ID, name, known folder, and label details.
|
|
hr = CMyDeviceSyncItem_CreateInstance(
|
|
s_rgItemInfo[iItemInfo].pszItemID,
|
|
pszItemName,
|
|
pszItemLabel,
|
|
_szHandlerID,
|
|
s_rgItemInfo[iItemInfo].folderID,
|
|
s_rgItemInfo[iItemInfo].uSyncTextID,
|
|
&_ppItems[_cItems]);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Increment our total item count.
|
|
_cItems++;
|
|
}
|
|
|
|
LocalFree(pszItemLabel);
|
|
}
|
|
|
|
LocalFree(pszItemName);
|
|
}
|
|
} // for: each item to create
|
|
} // if: array allocated successfully
|
|
} // if: items not loaded yet
|
|
|
|
return hr;
|
|
|
|
} //*** CMyDeviceSyncHandler::_LoadItems
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Find the item structure for an item ID.
|
|
//
|
|
// Parameters:
|
|
// pszItemID - Item to find.
|
|
//
|
|
// Return Values:
|
|
// The item that was found.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CMyDeviceSyncItem *CMyDeviceSyncHandler::_FindItem(__in LPCWSTR pszItemID)
|
|
{
|
|
if (_cItems == 0)
|
|
{
|
|
_LoadItems();
|
|
}
|
|
CMyDeviceSyncItem *pItem = NULL;
|
|
|
|
for (ULONG iItem = 0; iItem < _cItems; iItem++)
|
|
{
|
|
if (CompareSyncMgrID(_ppItems[iItem]->GetItemIDPointer(), pszItemID) == 0)
|
|
{
|
|
pItem = _ppItems[iItem];
|
|
break;
|
|
}
|
|
} // for: each item
|
|
|
|
return pItem;
|
|
|
|
} //*** CMyDeviceSyncHandler::_FindItem
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Report progress of synchronization.
|
|
//
|
|
// Parameters:
|
|
// pCallback - Callback interface to update progress on.
|
|
// pszItemID - ID of item to report progress on. Can be NULL.
|
|
// nProgressTextID - String resource ID of progress text.
|
|
// nStatus - Status being reported.
|
|
// uCurrentStep - Current step in the progress report.
|
|
// uMaxStep - Total number of steps.
|
|
// pfCanceled - Returns whether user canceled sync for this item.
|
|
// ... - Optional parameters to format into the string.
|
|
//
|
|
// Return Values:
|
|
// Any values from ISyncMgrSyncCallback::ReportProgress().
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void CMyDeviceSyncHandler::_ReportItemProgress(
|
|
__in ISyncMgrSyncCallback *pCallback,
|
|
__in LPCWSTR pszItemID,
|
|
__in UINT nProgressTextID,
|
|
__in SYNCMGR_PROGRESS_STATUS nStatus,
|
|
__in ULONG uCurrentStep,
|
|
__in ULONG uMaxStep,
|
|
__out SYNCMGR_CANCEL_REQUEST *pnCancelRequest,
|
|
...)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
*pnCancelRequest = SYNCMGR_CR_NONE;
|
|
if (pCallback != NULL)
|
|
{
|
|
// Default to clearing the progress if we've stopped unless we have
|
|
// something important to convey to the user. Otherwise, only change
|
|
// the item progress text if we have a new string.
|
|
PWSTR pszProgressText = (nStatus == SYNCMGR_PS_CANCELED) ? L"" : NULL;
|
|
if (nProgressTextID != 0)
|
|
{
|
|
va_list vaParamList;
|
|
va_start(vaParamList, pnCancelRequest);
|
|
hr = FormatStringVA(g_hmodThisDll, nProgressTextID, &pszProgressText, vaParamList);
|
|
va_end(vaParamList);
|
|
assert(SUCCEEDED(hr));
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pCallback->ReportProgress(pszItemID, pszProgressText, nStatus, uCurrentStep, uMaxStep, pnCancelRequest);
|
|
assert(SUCCEEDED(hr));
|
|
|
|
LocalFree(pszProgressText);
|
|
}
|
|
} // if: callback interface was specified
|
|
} //*** CMyDeviceSyncHandler::_ReportItemProgress
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Report progress of synchronization for the handler.
|
|
//
|
|
// Parameters:
|
|
// pCallback - Callback interface to update progress on.
|
|
// nProgressTextID - String resource ID of progress text.
|
|
// pnCancelRequest - Returns whether user canceled sync for this item.
|
|
// ... - Optional parameters to format into the string.
|
|
//
|
|
// Return Values:
|
|
// Any values from ISyncMgrSyncCallback::SetHandlerProgressText().
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void CMyDeviceSyncHandler::_SetHandlerProgressText(
|
|
__in ISyncMgrSyncCallback *pCallback,
|
|
__in UINT nProgressTextID,
|
|
__out SYNCMGR_CANCEL_REQUEST *pnCancelRequest,
|
|
...)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
if (pCallback != NULL)
|
|
{
|
|
PWSTR pszProgressText = NULL;
|
|
if (nProgressTextID != 0)
|
|
{
|
|
va_list vaParamList;
|
|
va_start(vaParamList, pnCancelRequest);
|
|
hr = FormatStringVA(g_hmodThisDll, nProgressTextID, &pszProgressText, vaParamList);
|
|
va_end(vaParamList);
|
|
assert(SUCCEEDED(hr));
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pCallback->SetHandlerProgressText(pszProgressText, pnCancelRequest);
|
|
assert(SUCCEEDED(hr));
|
|
|
|
LocalFree(pszProgressText);
|
|
}
|
|
} // if: callback interface was specified
|
|
} //*** CMyDeviceSyncHandler::_SetHandlerProgressText
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Report a synchronization event
|
|
//
|
|
// Parameters:
|
|
// pCallback - Callback interface to update progress on.
|
|
// pszItemID - ID of item to report progress on. Can be NULL.
|
|
// nEventNameID - String resource ID of the Event Name.
|
|
// nDescriptionTextID - String resource ID of description text.
|
|
// nLevel - Level of the event being reported.
|
|
// nFlags - Additional flags for the event.
|
|
// pszLinkText - Link text for the event. Can be NULL
|
|
// pszLinkReference - Action to shellexecute when the link is activated. Can be NULL.
|
|
// pszContext - Additional data to associate with the event. Can be NULL.
|
|
// ... - Optional parameters to format into the string.
|
|
//
|
|
// Return Values:
|
|
// Any values from ISyncMgrSyncCallback::ReportEvent().
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void CMyDeviceSyncHandler::_ReportEvent(
|
|
__in ISyncMgrSyncCallback *pCallback,
|
|
__in LPCWSTR pszItemID,
|
|
__in UINT nEventNameID,
|
|
__in UINT nDescriptionTextID,
|
|
__in SYNCMGR_EVENT_LEVEL nLevel,
|
|
__in SYNCMGR_EVENT_FLAGS nFlags,
|
|
__in_opt LPCWSTR pszLinkText,
|
|
__in_opt LPCWSTR pszLinkReference,
|
|
__in_opt LPCWSTR pszContext,
|
|
__out GUID *pguidEventID,
|
|
...)
|
|
{
|
|
// We must have a valid name and description for all events.
|
|
assert((nEventNameID != 0) && (nDescriptionTextID != 0));
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
if (pCallback != NULL)
|
|
{
|
|
// Load the localized error name out of our resource.
|
|
WCHAR wszName[MAX_SYNCMGR_NAME];
|
|
PWSTR pszDescription = NULL;
|
|
if (LoadStringW(g_hmodThisDll, nEventNameID, wszName, ARRAYSIZE(wszName)) != 0)
|
|
{
|
|
// Load and format the description string with the optional parameters.
|
|
va_list vaParamList;
|
|
va_start(vaParamList, pguidEventID);
|
|
hr = FormatStringVA(g_hmodThisDll, nDescriptionTextID, &pszDescription, vaParamList);
|
|
va_end(vaParamList);
|
|
assert(SUCCEEDED(hr));
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Report the event to Sync Center.
|
|
hr = pCallback->ReportEvent(pszItemID, nLevel, nFlags, wszName, pszDescription, pszLinkText, pszLinkReference, pszContext, pguidEventID);
|
|
assert(SUCCEEDED(hr));
|
|
|
|
LocalFree(pszDescription);
|
|
}
|
|
} // if: callback interface was specified
|
|
} //*** CMyDeviceSyncHandler::_ReportEvent
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// class CEnumSyncMgrItems
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Description:
|
|
// Create an instance of the enumerator class.
|
|
//
|
|
// Parameters:
|
|
// pDeviceHandler - Device handler to associate this enumerator with.
|
|
// riid - Interface ID to get.
|
|
// ppv - Interface pointer returned to caller.
|
|
//
|
|
// Return Values:
|
|
// S_OK - Operation completed successfully.
|
|
// E_OUTOFMEMORY - Error allocating the object.
|
|
// Other HRESULTs - Error querying for requested interface.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CEnumSyncMgrItems_CreateInstance(
|
|
__inout CMyDeviceSyncHandler *pDeviceHandler,
|
|
__in REFIID riid,
|
|
__deref_out void **ppv)
|
|
{
|
|
*ppv = NULL;
|
|
|
|
// Create an enumerator for the handler GUIDs.
|
|
CEnumSyncMgrItems *penum = new CEnumSyncMgrItems(pDeviceHandler);
|
|
HRESULT hr = (penum != NULL) ? S_OK : E_OUTOFMEMORY;
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = penum->QueryInterface(riid, ppv);
|
|
penum->Release();
|
|
}
|
|
|
|
return hr;
|
|
|
|
} //*** CEnumSyncMgrItems_CreateInstance
|
|
|
|
//----------------------------------------------------------------------------
|
|
// IUnknown (CEnumSyncMgrItems)
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CEnumSyncMgrItems::QueryInterface(__in REFIID riid, __deref_out void **ppv)
|
|
{
|
|
static const QITAB qit[] =
|
|
{
|
|
QITABENT(CEnumSyncMgrItems, IEnumSyncMgrSyncItems),
|
|
{ 0 },
|
|
};
|
|
|
|
return QISearch(this, qit, riid, ppv);
|
|
|
|
} //*** CEnumSyncMgrItems::QueryInterface
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CEnumSyncMgrItems::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement(&_cRef);
|
|
if (cRef == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
return cRef;
|
|
|
|
} //*** CEnumSyncMgrItems::Release
|
|
|
|
//----------------------------------------------------------------------------
|
|
// ISyncMgrEnumItems (CEnumSyncMgrItems)
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CEnumSyncMgrItems::Next(__in ULONG celt, __deref_out_ecount(celt) ISyncMgrSyncItem *rgelt[], __out_opt ULONG *pceltFetched)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG cFetched = 0;
|
|
while ((cFetched < celt) && (_iCur < _pDeviceHandler->_cItems))
|
|
{
|
|
hr = _pDeviceHandler->_ppItems[_iCur]->QueryInterface(IID_ISyncMgrSyncItem, (void **) &rgelt[cFetched]);
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
cFetched++;
|
|
_iCur++;
|
|
} // while: more items
|
|
|
|
// If we failed to QI one item, return the others we already queried.
|
|
|
|
hr = (cFetched == celt) ? S_OK : S_FALSE;
|
|
|
|
if (pceltFetched != NULL)
|
|
{
|
|
*pceltFetched = cFetched;
|
|
}
|
|
|
|
return hr;
|
|
|
|
} //*** CEnumSyncMgrItems::Next
|
|
|