diff options
Diffstat (limited to 'wpd/WpdWudfSampleDriver/WpdObjectManagement.cpp')
| -rw-r--r-- | wpd/WpdWudfSampleDriver/WpdObjectManagement.cpp | 1160 |
1 files changed, 0 insertions, 1160 deletions
diff --git a/wpd/WpdWudfSampleDriver/WpdObjectManagement.cpp b/wpd/WpdWudfSampleDriver/WpdObjectManagement.cpp deleted file mode 100644 index 9c3d22b2..00000000 --- a/wpd/WpdWudfSampleDriver/WpdObjectManagement.cpp +++ /dev/null @@ -1,1160 +0,0 @@ -#include "stdafx.h" -#include "WpdObjectManagement.tmh" - -WpdObjectManagement::WpdObjectManagement() -{ - -} - -WpdObjectManagement::~WpdObjectManagement() -{ - -} - -HRESULT WpdObjectManagement::Initialize(_In_ FakeDevice *pFakeDevice) -{ - HRESULT hr = S_OK; - - if(pFakeDevice == NULL) - { - hr = E_POINTER; - CHECK_HR(hr, "Cannot have NULL parameter"); - return hr; - } - - m_pFakeDevice = pFakeDevice; - - return hr; -} - -HRESULT WpdObjectManagement::DispatchWpdMessage( - _In_ REFPROPERTYKEY Command, - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - HRESULT hr = S_OK; - - if (hr == S_OK) - { - if (Command.fmtid != WPD_CATEGORY_OBJECT_MANAGEMENT) - { - hr = E_INVALIDARG; - CHECK_HR(hr, "This object does not support this command category %ws",CComBSTR(Command.fmtid)); - } - } - - if (hr == S_OK) - { - if (Command.pid == WPD_COMMAND_OBJECT_MANAGEMENT_DELETE_OBJECTS.pid) - { - hr = OnDelete(pParams, pResults); - CHECK_HR(hr, "Failed to delete object"); - } - else if (Command.pid == WPD_COMMAND_OBJECT_MANAGEMENT_CREATE_OBJECT_WITH_PROPERTIES_ONLY.pid) - { - hr = OnCreateObjectWithPropertiesOnly(pParams, pResults); - CHECK_HR(hr, "Failed to create object"); - } - else if (Command.pid == WPD_COMMAND_OBJECT_MANAGEMENT_CREATE_OBJECT_WITH_PROPERTIES_AND_DATA.pid) - { - hr = OnCreateObjectWithPropertiesAndData(pParams, pResults); - CHECK_HR(hr, "Failed to create object"); - } - else if (Command.pid == WPD_COMMAND_OBJECT_MANAGEMENT_WRITE_OBJECT_DATA.pid) - { - hr = OnWriteObjectData(pParams, pResults); - CHECK_HR(hr, "Failed to write object data"); - } - else if (Command.pid == WPD_COMMAND_OBJECT_MANAGEMENT_COMMIT_OBJECT.pid) - { - hr = OnCommit(pParams, pResults); - CHECK_HR(hr, "Failed to commit object"); - } - else if (Command.pid == WPD_COMMAND_OBJECT_MANAGEMENT_REVERT_OBJECT.pid) - { - hr = OnRevert(pParams, pResults); - CHECK_HR(hr, "Failed to revert object"); - } - else if (Command.pid == WPD_COMMAND_OBJECT_MANAGEMENT_MOVE_OBJECTS.pid) - { - hr = OnMove(pParams, pResults); - CHECK_HR(hr, "Failed to Move objects"); - } - else if (Command.pid == WPD_COMMAND_OBJECT_MANAGEMENT_COPY_OBJECTS.pid) - { - hr = OnCopy(pParams, pResults); - CHECK_HR(hr, "Failed to Copy objects"); - } - else if (Command.pid == WPD_COMMAND_OBJECT_MANAGEMENT_UPDATE_OBJECT_WITH_PROPERTIES_AND_DATA.pid) - { - hr = OnUpdateObjectWithPropertiesAndData(pParams, pResults); - CHECK_HR(hr, "Failed to update object"); - } - else - { - hr = E_NOTIMPL; - CHECK_HR(hr, "This object does not support this command id %d", Command.pid); - } - } - - return hr; -} - -/** - * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_DELETE_OBJECTS - * command. - * - * The parameters sent to us are: - * - WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS: the ObjectIDs, indicating which objects to delete. These may - * contain children. - * - WPD_PROPERTY_OBJECT_MANAGEMENT_DELETE_OPTIONS: Flag parameter indicating delete options. Must be one - * of the following: - * - PORTABLE_DEVICE_DELETE_NO_RECURSION - Deletes the - * object only. This should fail if children exist. - * - PORTABLE_DEVICE_DELETE_WITH_RECURSION - Deletes this - * object and all children. - * - * The driver should: - * - If the flag is PORTABLE_DEVICE_DELETE_NO_RECURSION the driver should delete the - * specified object only. If the object still has children the driver should not delete - * the object and instead return HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION). - * - If the flag is PORTABLE_DEVICE_DELETE_WITH_RECURSION the driver should delete the - * specified object and all of its children. - * - Fill out the operation results in WPD_PROPERTY_OBJECT_MANAGEMENT_DELETE_RESULTS. It contains an IPortableDevicePropVariantCollection of - * VT_ERROR values indicating the success or failure of the operation for that element. - * Order is implicit, i.e. the first element of WPD_PROPERTY_OBJECT_MANAGEMENT_DELETE_RESULTS corresponds to the first element of WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS and so on. - * - The driver should return: - * - S_OK if all objects were deleted successfully. - * - S_FALSE if any object delete failed. - * - An error return indicates that the driver did not delete any objects, and - * WPD_PROPERTY_OBJECT_MANAGEMENT_DELETE_RESULTS is ignored. - */ -HRESULT WpdObjectManagement::OnDelete( - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - HRESULT hr = S_OK; - DWORD dwOptions = PORTABLE_DEVICE_DELETE_NO_RECURSION; - BOOL bDeleteFailed = FALSE; - CComPtr<IPortableDevicePropVariantCollection> pObjectIDs; - CComPtr<IPortableDevicePropVariantCollection> pDeleteResults; - CComPtr<IPortableDeviceValues> pEventParams; - VARTYPE vt = VT_EMPTY; - - if (hr == S_OK) - { - hr = pParams->GetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS, &pObjectIDs); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS"); - } - - // Ensure that this is a collection of VT_LPWSTR - if (hr == S_OK) - { - hr = pObjectIDs->GetType(&vt); - CHECK_HR(hr, "Failed to get the VARTYP of WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS"); - if (hr == S_OK) - { - if (vt != VT_LPWSTR) - { - hr = E_INVALIDARG; - CHECK_HR(hr, "WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS is not a collection of VT_LPWSTR"); - } - } - } - - if (hr == S_OK) - { - hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_MANAGEMENT_DELETE_OPTIONS, &dwOptions); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_DELETE_OPTIONS"); - } - - if (hr == S_OK) - { - hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, - NULL, - CLSCTX_INPROC_SERVER, - IID_IPortableDevicePropVariantCollection, - (VOID**) &pDeleteResults); - CHECK_HR(hr, "Failed to CoCreateInstance CLSID_PortableDevicePropVariantCollection"); - } - - - if (hr == S_OK) - { - DWORD cObjects = 0; - // Loop through the object list and attempt to delete - hr = pObjectIDs->GetCount(&cObjects); - CHECK_HR(hr, "Failed to get number of objects to delete"); - - if (hr == S_OK) - { - for(DWORD dwIndex = 0; dwIndex < cObjects; dwIndex++) - { - HRESULT hrTemp = S_OK; - PROPVARIANT pv = {0}; - - PropVariantInit(&pv); - // Get the next Object to delete - hr = pObjectIDs->GetAt(dwIndex, &pv); - CHECK_HR(hr, "Failed to get next object id at index %d", dwIndex); - if (hr == S_OK) - { - pEventParams = NULL; - // Get the object properties used for sending the event. Ignore errors (these are expected in some cases - // e.g. app is sending object ID that doesn't exist), since this relates to the event, not the delete operation, - // and we return results for the delete (an error posting the event is non-fatal). - hrTemp = m_pFakeDevice->GetObjectPropertiesForEvent(pv.pwszVal, &pEventParams); - CHECK_HR(hrTemp, "Failed to get properties for event on object %ws", pv.pwszVal); - - HRESULT hrDelete = S_OK; - PROPVARIANT pvResult = {0}; - - PropVariantInit(&pvResult); - - hrDelete = m_pFakeDevice->DeleteObject(dwOptions, pv.pwszVal); - CHECK_HR(hrDelete, "Failed to delete object [%ws]", pv.pwszVal); - - if(FAILED(hrDelete)) - { - bDeleteFailed = TRUE; - } - - // Save this result - pvResult.vt = VT_ERROR; - pvResult.scode = hrDelete; - hrTemp = pDeleteResults->Add(&pvResult); - PropVariantClear(&pvResult); - CHECK_HR(hrTemp, "Failed to add result for [%ws] to list of results", pv.pwszVal); - - if ((hrDelete == S_OK) && (hrTemp == S_OK)) - { - HRESULT hrEvent = S_OK; - // Set the event-specific parameters - hrEvent = pEventParams->SetGuidValue(WPD_EVENT_PARAMETER_EVENT_ID, WPD_EVENT_OBJECT_REMOVED); - CHECK_HR(hrEvent, "Failed to add WPD_EVENT_PARAMETER_EVENT_ID"); - - // Send the Event - if (hrEvent == S_OK) - { - PostWpdEvent(pParams, pEventParams); - } - } - PropVariantClear(&pv); - } - else - { - break; - } - } - } - } - - // Set the results - if (hr == S_OK) - { - hr = pResults->SetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_OBJECT_MANAGEMENT_DELETE_RESULTS, pDeleteResults); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_DELETE_RESULTS"); - } - - // If an object failed to delete, make sure we return S_FALSE - if ((hr == S_OK) && (bDeleteFailed)) - { - hr = S_FALSE; - } - - return hr; -} - -/** - * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_MOVE_OBJECTS - * command. - * - * This command will move the specified objects to the destination folder. - * - * The parameters sent to us are: - * - WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS : the ObjectIDs, indicating which objects to move. These may - * be folder objects. - * - WPD_PROPERTY_OBJECT_MANAGEMENT_DESTINATION_FOLDER_OBJECT_ID: Indicates the destination folder for the move operation. - * - * The driver should: - * - Attempt to Move the object specified in WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS to the folder specified in - * WPD_PROPERTY_OBJECT_MANAGEMENT_DESTINATION_FOLDER_OBJECT_ID. - * - Fill out the operation results in WPD_PROPERTY_OBJECT_MANAGEMENT_MOVE_RESULTS. It contains an IportableDevicePropVariantCollection of - * VT_ERROR values indicating the success or failure of the operation for that element. - * Order is implicit, i.e. the first element of WPD_PROPERTY_OBJECT_MANAGEMENT_MOVE_RESULTS corresponds to the first element of WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS and so on. - * - The driver should return: - * - S_OK if all objects were moved successfully. - * - S_FALSE if any object move failed. - * - An error return indicates that the driver did not move any objects, and - * WPD_PROPERTY_OBJECT_MANAGEMENT_MOVE_RESULTS is ignored. - */ -HRESULT WpdObjectManagement::OnMove( - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - HRESULT hr = S_OK; - LPWSTR pszDestFolderObjectID = NULL; - CComPtr<IPortableDevicePropVariantCollection> pObjectIDs; - CComPtr<IPortableDevicePropVariantCollection> pMoveResults; - BOOL bMoveFailed = FALSE; - VARTYPE vt = VT_EMPTY; - - if (hr == S_OK) - { - hr = pParams->GetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS, &pObjectIDs); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS"); - } - - // Ensure that this is a collection of VT_LPWSTR - if (hr == S_OK) - { - hr = pObjectIDs->GetType(&vt); - CHECK_HR(hr, "Failed to get the VARTYP of WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS"); - if (hr == S_OK) - { - if (vt != VT_LPWSTR) - { - hr = E_INVALIDARG; - CHECK_HR(hr, "WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS is not a collection of VT_LPWSTR"); - } - } - } - - if (hr == S_OK) - { - hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_DESTINATION_FOLDER_OBJECT_ID, &pszDestFolderObjectID); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_DESTINATION_FOLDER_OBJECT_ID"); - } - - if (hr == S_OK) - { - hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, - NULL, - CLSCTX_INPROC_SERVER, - IID_IPortableDevicePropVariantCollection, - (VOID**) &pMoveResults); - CHECK_HR(hr, "Failed to CoCreateInstance CLSID_PortableDevicePropVariantCollection"); - } - - - if (hr == S_OK) - { - DWORD cObjects = 0; - // Loop through the object list and attempt to move - hr = pObjectIDs->GetCount(&cObjects); - CHECK_HR(hr, "Failed to get number of objects to move"); - - if (hr == S_OK) - { - for(DWORD dwIndex = 0; dwIndex < cObjects; dwIndex++) - { - HRESULT hrTemp = S_OK; - PROPVARIANT pv = {0}; - - PropVariantInit(&pv); - // Get the next Object to move - hrTemp = pObjectIDs->GetAt(dwIndex, &pv); - CHECK_HR(hr, "Failed to get next object id at index %d", dwIndex); - if (hrTemp == S_OK) - { - // Move this object - hrTemp = m_pFakeDevice->MoveObject(pv.pwszVal, pszDestFolderObjectID); - CHECK_HR(hrTemp, "Failed to move object [%ws] to folder [%ws]", pv.pwszVal, pszDestFolderObjectID); - - if(FAILED(hrTemp)) - { - bMoveFailed = TRUE; - } - - PROPVARIANT pvResult = {0}; - - PropVariantInit(&pvResult); - - // Save this result - pvResult.vt = VT_ERROR; - pvResult.scode = hrTemp; - hrTemp = pMoveResults->Add(&pvResult); - CHECK_HR(hrTemp, "Failed to add result for [%ws] to list of results", pv.pwszVal); - - PropVariantClear(&pvResult); - } - PropVariantClear(&pv); - } - } - } - - // Set the results - if (hr == S_OK) - { - hr = pResults->SetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_OBJECT_MANAGEMENT_MOVE_RESULTS, pMoveResults); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_MOVE_RESULTS"); - } - - CoTaskMemFree(pszDestFolderObjectID); - - // If an object failed to move, make sure we return S_FALSE - if ((hr == S_OK) && (bMoveFailed)) - { - hr = S_FALSE; - } - - return hr; -} - -/** - * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_COPY_OBJECTS - * command. - * - * This command will copy the specified objects to the destination folder. - * - * The parameters sent to us are: - * - WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS : the ObjectIDs, indicating which objects to copy. These may - * be folder objects. - * - WPD_PROPERTY_OBJECT_MANAGEMENT_DESTINATION_FOLDER_OBJECT_ID: Indicates the destination folder for the copy operation. - * - * The driver should: - * - Attempt to copy the object specified in WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS to the folder specified in - * WPD_PROPERTY_OBJECT_MANAGEMENT_DESTINATION_FOLDER_OBJECT_ID. - * - Fill out the operation results in WPD_PROPERTY_OBJECT_MANAGEMENT_COPY_RESULTS. It contains an IPortableDevicePropVariantCollection of - * VT_ERROR values indicating the success or failure of the operation for that element. - * Order is implicit, i.e. the first element of WPD_PROPERTY_OBJECT_MANAGEMENT_COPY_RESULTS corresponds to the first element of WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS and so on. - * - The driver should return: - * - S_OK if all objects were copied successfully. - * - S_FALSE if any object copy failed. - * - An error return indicates that the driver did not copy any objects, and - * WPD_PROPERTY_OBJECT_MANAGEMENT_COPY_RESULTS is ignored. - */ -HRESULT WpdObjectManagement::OnCopy( - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - HRESULT hr = S_OK; - LPWSTR pszDestFolderObjectID = NULL; - CComPtr<IPortableDevicePropVariantCollection> pObjectIDs; - CComPtr<IPortableDevicePropVariantCollection> pCopyResults; - BOOL bCopyFailed = FALSE; - VARTYPE vt = VT_EMPTY; - - hr = pParams->GetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS, &pObjectIDs); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS"); - - // Ensure that this is a collection of VT_LPWSTR - if (SUCCEEDED(hr)) - { - hr = pObjectIDs->GetType(&vt); - CHECK_HR(hr, "Failed to get the VARTYP of WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS"); - if (hr == S_OK) - { - if (vt != VT_LPWSTR) - { - hr = E_INVALIDARG; - CHECK_HR(hr, "WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_IDS is not a collection of VT_LPWSTR"); - } - } - } - - if (SUCCEEDED(hr)) - { - hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_DESTINATION_FOLDER_OBJECT_ID, &pszDestFolderObjectID); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_DESTINATION_FOLDER_OBJECT_ID"); - } - - if (SUCCEEDED(hr)) - { - hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, - NULL, - CLSCTX_INPROC_SERVER, - IID_IPortableDevicePropVariantCollection, - (VOID**) &pCopyResults); - CHECK_HR(hr, "Failed to CoCreateInstance CLSID_PortableDevicePropVariantCollection"); - } - - - if (SUCCEEDED(hr)) - { - DWORD cObjects = 0; - // Loop through the object list and attempt to copy - hr = pObjectIDs->GetCount(&cObjects); - CHECK_HR(hr, "Failed to get number of objects to copy"); - - if (SUCCEEDED(hr)) - { - for(DWORD dwIndex = 0; dwIndex < cObjects; dwIndex++) - { - CComPtr<IPortableDeviceValues> pEventParams; - LPWSTR pszNewObjectID = NULL; - HRESULT hrTemp = S_OK; - PROPVARIANT pv = {0}; - - PropVariantInit(&pv); - // Get the next Object to copy - hrTemp = pObjectIDs->GetAt(dwIndex, &pv); - CHECK_HR(hr, "Failed to get next object id at index %d", dwIndex); - if (SUCCEEDED(hrTemp)) - { - // Copy this object - hrTemp = m_pFakeDevice->CopyObject(pv.pwszVal, pszDestFolderObjectID, &pszNewObjectID); - CHECK_HR(hrTemp, "Failed to copy object [%ws] to folder [%ws]", pv.pwszVal, pszDestFolderObjectID); - - if(FAILED(hrTemp)) - { - bCopyFailed = TRUE; - } - - PROPVARIANT pvResult = {0}; - - PropVariantInit(&pvResult); - - // Save this result - pvResult.vt = VT_ERROR; - pvResult.scode = hrTemp; - hrTemp = pCopyResults->Add(&pvResult); - CHECK_HR(hrTemp, "Failed to add result for [%ws] to list of results", pv.pwszVal); - - PropVariantClear(&pvResult); - - if (SUCCEEDED(hrTemp)) - { - // Send the event - // Get the object properties used for sending the event - hrTemp = m_pFakeDevice->GetObjectPropertiesForEvent(pszNewObjectID, &pEventParams); - CHECK_HR(hrTemp, "Failed to get properties for event on object %ws", pszNewObjectID); - if (SUCCEEDED(hrTemp)) - { - // Set the event-specific parameters - hrTemp = pEventParams->SetGuidValue(WPD_EVENT_PARAMETER_EVENT_ID, WPD_EVENT_OBJECT_ADDED); - CHECK_HR(hrTemp, "Failed to add WPD_EVENT_PARAMETER_EVENT_ID"); - - // Send the Event - if (SUCCEEDED(hrTemp)) - { - PostWpdEvent(pParams, pEventParams); - } - } - } - } - - if (pszNewObjectID != NULL) - { - CoTaskMemFree(pszNewObjectID); - pszNewObjectID = NULL; - } - - PropVariantClear(&pv); - } - } - } - - // Set the results - if (SUCCEEDED(hr)) - { - hr = pResults->SetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_OBJECT_MANAGEMENT_COPY_RESULTS, pCopyResults); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_COPY_RESULTS"); - } - - CoTaskMemFree(pszDestFolderObjectID); - - // If an object failed to copy, make sure we return S_FALSE - if (SUCCEEDED(hr) && bCopyFailed) - { - hr = S_FALSE; - } - - return hr; -} - -/** - * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_CREATE_OBJECT_WITH_PROPERTIES_ONLY - * command. - * - * The parameters sent to us are: - * - WPD_PROPERTY_OBJECT_MANAGEMENT_CREATION_PROPERTIES: Contains an IPortableDeviceValues, describing - * properties of the new object. At the very least, it will contain: - * - WPD_OBJECT_NAME: The object name. - * - WPD_PARENT_ID: Identifies the parent object. The object should be inserted as a child of - * this parent (e.g. this would be the target directory in a file system based device). - * - * The driver should: - * - Create the object, and return its ID in WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID. - */ -HRESULT WpdObjectManagement::OnCreateObjectWithPropertiesOnly( - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - HRESULT hr = S_OK; - LPWSTR pszContext = NULL; - CComPtr<IPortableDeviceValues> pValues; - CComPtr<IPortableDeviceValues> pEventParams; - - // Get the Object Properties - hr = pParams->GetIPortableDeviceValuesValue(WPD_PROPERTY_OBJECT_MANAGEMENT_CREATION_PROPERTIES, &pValues); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_CREATION_PROPERTIES"); - - // Save the object to the device here. - if (SUCCEEDED(hr)) - { - hr = m_pFakeDevice->SaveNewObject(pValues, &pszContext); - CHECK_HR(hr, "Failed to save new (properties only) object to device"); - } - - if (SUCCEEDED(hr)) - { - hr = pResults->SetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID, pszContext); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID"); - } - - if (SUCCEEDED(hr)) - { - // Send the event - HRESULT hrTemp = S_OK; - // Get the object properties used for sending the event - hrTemp = m_pFakeDevice->GetObjectPropertiesForEvent(pszContext, &pEventParams); - CHECK_HR(hrTemp, "Failed to get properties for event on object %ws", pszContext); - if (SUCCEEDED(hrTemp)) - { - // Set the event-specific parameters - hrTemp = pEventParams->SetGuidValue(WPD_EVENT_PARAMETER_EVENT_ID, WPD_EVENT_OBJECT_ADDED); - CHECK_HR(hrTemp, "Failed to add WPD_EVENT_PARAMETER_EVENT_ID"); - - // Send the Event - if (SUCCEEDED(hrTemp)) - { - PostWpdEvent(pParams, pEventParams); - } - } - } - - // Free the memory. CoTaskMemFree ignores NULLs so no need to check. - CoTaskMemFree(pszContext); - - return hr; -} - -/** - * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_CREATE_OBJECT_WITH_PROPERTIES_AND_DATA - * command. - * - * The parameters sent to us are: - * - WPD_PROPERTY_OBJECT_MANAGEMENT_CREATION_PROPERTIES: Contains an IPortableDeviceValues, describing - * properties of the new object. At the very least, it will contain: - * - WPD_OBJECT_NAME: The object name. - * - WPD_PARENT_ID: Identifies the parent object. The object should be inserted as a child of - * this parent (e.g. this would be the target directory in a file system based device). - * - WPD_OBJECT_SIZE: The total size of the object data stream. - * - WPD_OBJECT_FORMAT: The format the object data stream. - * - * The driver should: - * - Create a context for this operation and return it in WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT. - * - Return the optimal transfer buffer size in WPD_PROPERTY_OBJECT_MANAGEMENT_OPTIMAL_TRANSFER_BUFFER_SIZE. - */ -HRESULT WpdObjectManagement::OnCreateObjectWithPropertiesAndData( - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - HRESULT hr = S_OK; - LPWSTR pszContext = NULL; - LPWSTR pszObjectName = NULL; - IUnknown* pContextMap = NULL; - CComPtr<IPortableDeviceValues> pValues; - - // Get the Object Properties - hr = pParams->GetIPortableDeviceValuesValue(WPD_PROPERTY_OBJECT_MANAGEMENT_CREATION_PROPERTIES, &pValues); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_CREATION_PROPERTIES"); - - // Get Object Name from pValues - if (SUCCEEDED(hr)) - { - hr = pValues->GetStringValue(WPD_OBJECT_NAME, &pszObjectName); - CHECK_HR(hr, "Failed to get WPD_OBJECT_NAME"); - } - - // Get the context map - if (SUCCEEDED(hr)) - { - hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, &pContextMap); - CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP"); - } - - if (SUCCEEDED(hr)) - { - // Object data will be provided by the caller. So Create a context identifying this - // creation request, since the actual data will come later, and the object can only be saved - // when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_COMMIT_OBJECT call. - hr = CreateObjectManagementContext((ContextMap*) pContextMap, pszObjectName, pValues, false /*bUpdateRequest*/, &pszContext); - CHECK_HR(hr, "Failed to create object management context"); - } - - if (SUCCEEDED(hr)) - { - hr = pResults->SetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT, pszContext); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT"); - } - - // Set the optimal buffer size - if (SUCCEEDED(hr)) - { - hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_MANAGEMENT_OPTIMAL_TRANSFER_BUFFER_SIZE, OPTIMAL_BUFFER_SIZE); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_OPTIMAL_TRANSFER_BUFFER_SIZE value"); - } - - // Free the memory. CoTaskMemFree ignores NULLs so no need to check. - CoTaskMemFree(pszContext); - // Free the memory. CoTaskMemFree ignores NULLs so no need to check. - CoTaskMemFree(pszObjectName); - - SAFE_RELEASE(pContextMap); - - return hr; -} - -/** - * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_REVERT_OBJECT - * command. - * - * The parameters sent to us are: - * - WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT: identifies the object creation request (driver returned this in - * WPD_COMMAND_OBJECT_MANAGEMENT_CREATE_OBJECT). - * - * The driver should: - * - Free any resources associated with this context/operation. The object should not be saved to the - * device. If a placeholder was created on the device for this operation, it should be removed. - */ -HRESULT WpdObjectManagement::OnRevert( - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - HRESULT hr = S_OK; - LPWSTR pszContext = NULL; - ContextMap* pContextMap = NULL; - - // There are no return parameters for this operation. - UNREFERENCED_PARAMETER(pResults); - - hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT, &pszContext); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID"); - - if (SUCCEEDED(hr)) - { - hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap); - CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP"); - } - - if (SUCCEEDED(hr)) - { - hr = DestroyObjectManagementContext(pContextMap, pszContext); - CHECK_HR(hr, "Failed to revert object identified by context [%ws]", pszContext); - } - - // Free the memory. CoTaskMemFree ignores NULLs so no need to check. - CoTaskMemFree(pszContext); - - SAFE_RELEASE(pContextMap); - - return hr; -} - -/** - * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_COMMIT_OBJECT - * command. - * - * The parameters sent to us are: - * - WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT: identifies the object creation request (driver returned this in - * WPD_COMMAND_OBJECT_MANAGEMENT_CREATE_OBJECT). - * - * The driver should: - * - Commit the object to the device. - * - Return the new/updated ObjectID in WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID. - */ -HRESULT WpdObjectManagement::OnCommit( - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - HRESULT hr = S_OK; - LPWSTR pszContext = NULL; - ObjectManagementContext* pContext = NULL; - ContextMap* pContextMap = NULL; - CComPtr<IPortableDeviceValues> pEventParams; - - hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT, &pszContext); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID"); - - // Get the object management context for this request - if (SUCCEEDED(hr)) - { - hr = GetClientContext(pParams, pszContext, (IUnknown**)&pContext); - CHECK_HR(hr, "Failed to get Object Management Context"); - } - - if (SUCCEEDED(hr)) - { - hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap); - CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP"); - } - - if (SUCCEEDED(hr)) - { - if (pContext->UpdateRequest) - { - // Update the object - hr = UpdateObject(pContext, pParams, pResults); - } - else - { - // Save the new object - hr = CommitNewObject(pContext, pszContext, pParams, pResults); - } - } - - // We're done with the context - SAFE_RELEASE(pContext); - - // Destroy the context associated with this request, since it is no longer needed - if (SUCCEEDED(hr)) - { - hr = DestroyObjectManagementContext(pContextMap, pszContext); - CHECK_HR(hr, "Failed to destroy object identified by context [%ws]", pszContext); - } - - // Free the memory. CoTaskMemFree ignores NULLs so no need to check. - CoTaskMemFree(pszContext); - - SAFE_RELEASE(pContextMap); - - return hr; -} - -/** - * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_WRITE_OBJECT_DATA - * command. - * - * The parameters sent to us are: - * - WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT: identifies the object creation request previsouly started with - * WPD_PROPERTY_OBJECT_MANAGEMENT_CREATE_OBJECT. - * - WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_TO_WRITE: specifies the next number of bytes to write. - * - WPD_PROPERTY_OBJECT_MANAGEMENT_DATA: specifies byte array where the data should be copied from. - * - * The driver should: - * - Write the next WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_TO_WRITE to the resource. - * - Return the number of bytes actually written in WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_WRITTEN. - * It is normally considered an error if this value does not match WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_TO_WRITE. - */ -HRESULT WpdObjectManagement::OnWriteObjectData( - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - HRESULT hr = S_OK; - LPWSTR pszContext = NULL; - DWORD dwNumBytesToWrite = 0; - DWORD dwNumBytesWritten = 0; - BYTE* pBuffer = NULL; - DWORD cbBuffer = 0; - ObjectManagementContext* pContext = NULL; - - // Get the Context string - hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT, &pszContext); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT"); - - // Get the number of bytes to write - if (SUCCEEDED(hr)) - { - hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_TO_WRITE, &dwNumBytesToWrite); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_TO_WRITE"); - } - - // Get the source buffer - if (SUCCEEDED(hr)) - { - hr = pParams->GetBufferValue(WPD_PROPERTY_OBJECT_MANAGEMENT_DATA, &pBuffer, &cbBuffer); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_DATA"); - } - - // Get the resource context for this object creation request - if (SUCCEEDED(hr)) - { - hr = GetClientContext(pParams, pszContext, (IUnknown**)&pContext); - CHECK_HR(hr, "Failed to get Object Management Context"); - } - - // Write the next band of data for this new object request - if (SUCCEEDED(hr)) - { - // TBD: Write bytes to object. This sample driver ignores the data content. - dwNumBytesWritten = dwNumBytesToWrite; - } - - if (SUCCEEDED(hr)) - { - hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_WRITTEN, dwNumBytesWritten); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_NUM_BYTES_WRITTEN"); - } - - // Free the memory. CoTaskMemFree ignores NULLs so no need to check. - CoTaskMemFree(pszContext); - - // Free the memory. CoTaskMemFree ignores NULLs so no need to check. - CoTaskMemFree(pBuffer); - - SAFE_RELEASE(pContext); - - return hr; -} - -/** - * This method is called when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_UPDATE_OBJECT_WITH_PROPERTIES_AND_DATA - * command. - * - * The parameters sent to us are: - * - WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID: Identifies the object to update. - * - WPD_PROPERTY_OBJECT_MANAGEMENT_UPDATE_PROPERTIES: Contains an IPortableDeviceValues, describing - * the updated properties of the object. At the very least, it will contain: - * - WPD_OBJECT_SIZE: The total size of the object data stream. - * - * The driver should: - * - Create a context for this operation and return it in WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT. - * - Return the optimal transfer buffer size in WPD_PROPERTY_OBJECT_MANAGEMENT_OPTIMAL_TRANSFER_BUFFER_SIZE. - */ -HRESULT WpdObjectManagement::OnUpdateObjectWithPropertiesAndData( - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - HRESULT hr = S_OK; - LPWSTR pszContext = NULL; - LPWSTR pszObjectId = NULL; - IUnknown* pContextMap = NULL; - BOOL bUpdatable = NULL; - CComPtr<IPortableDeviceValues> pValues; - - // Get the Object Identifier. - hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID, &pszObjectId); - CHECK_HR(hr, "Failed to get WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID"); - - // Get the Object Properties - if (SUCCEEDED(hr)) - { - hr = pParams->GetIPortableDeviceValuesValue(WPD_PROPERTY_OBJECT_MANAGEMENT_UPDATE_PROPERTIES, &pValues); - CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_MANAGEMENT_CREATION_PROPERTIES"); - } - - // Get the context map - if (SUCCEEDED(hr)) - { - hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, &pContextMap); - CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP"); - } - - // Validate whether this object supports the default resource - if (SUCCEEDED(hr)) - { - hr = m_pFakeDevice->SupportsResource(pszObjectId, WPD_RESOURCE_DEFAULT, &bUpdatable); - CHECK_HR(hr, "Failed to check whether object supports WPD_RESOURCE_DEFAULT"); - - if (SUCCEEDED(hr) && !bUpdatable) - { - hr = E_INVALIDARG; - CHECK_HR(hr, "Object does not support WPD_RESOURCE_DEFAULT"); - } - } - - if (SUCCEEDED(hr)) - { - // Object data will be provided by the caller. So Create a context identifying this - // creation request, since the actual data will come later, and the object can only be saved - // when we receive a WPD_COMMAND_OBJECT_MANAGEMENT_COMMIT_OBJECT call. - hr = CreateObjectManagementContext((ContextMap*) pContextMap, pszObjectId, pValues, true /*bUpdateRequest*/, &pszContext); - CHECK_HR(hr, "Failed to create object management context"); - } - - if (SUCCEEDED(hr)) - { - hr = pResults->SetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT, pszContext); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_CONTEXT"); - } - - // Set the optimal buffer size - if (SUCCEEDED(hr)) - { - hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_MANAGEMENT_OPTIMAL_TRANSFER_BUFFER_SIZE, OPTIMAL_BUFFER_SIZE); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_OPTIMAL_TRANSFER_BUFFER_SIZE value"); - } - - CoTaskMemFree(pszContext); - CoTaskMemFree(pszObjectId); - - SAFE_RELEASE(pContextMap); - - return hr; -} - -HRESULT WpdObjectManagement::CreateObjectManagementContext( - _In_ ContextMap* pContextMap, - _In_ LPCWSTR pszObjectName, - _In_ IPortableDeviceValues* pObjectProperties, - _In_ BOOL bUpdateRequest, - _Outptr_result_nullonfailure_ LPWSTR* ppszObjectManagementContext) -{ - HRESULT hr = S_OK; - GUID guidContext = GUID_NULL; - ObjectManagementContext* pContext = NULL; - CComBSTR bstrContext; - - if((pContextMap == NULL) || - (pObjectProperties == NULL) || - (pszObjectName == NULL) || - (ppszObjectManagementContext == NULL)) - { - hr = E_POINTER; - CHECK_HR(hr, "Cannot have NULL parameter"); - return hr; - } - - *ppszObjectManagementContext = NULL; - - hr = CoCreateGuid(&guidContext); - if (SUCCEEDED(hr)) - { - bstrContext = guidContext; - if(bstrContext.Length() == 0) - { - hr = E_OUTOFMEMORY; - CHECK_HR(hr, "Failed to create BSTR from GUID"); - } - } - - if (SUCCEEDED(hr)) - { - pContext = new ObjectManagementContext(); - if(pContext != NULL) - { - CAtlStringW strKey = bstrContext; - pContext->Name = pszObjectName; - pContext->ObjectProperties = pObjectProperties; - pContext->UpdateRequest = bUpdateRequest; - - hr = pContextMap->Add(strKey, pContext); - CHECK_HR(hr, "Failed to add object creation context to client context map"); - - pContext->Release(); - } - else - { - hr = E_OUTOFMEMORY; - CHECK_HR(hr, "Failed to allocate object creation context"); - } - } - - if (SUCCEEDED(hr)) - { - *ppszObjectManagementContext = AtlAllocTaskWideString(bstrContext); - } - - return hr; -} - -HRESULT WpdObjectManagement::DestroyObjectManagementContext( - _In_ ContextMap* pContextMap, - _In_ LPCWSTR pszObjectManagementContext) -{ - HRESULT hr = S_OK; - - CAtlStringW strKey = pszObjectManagementContext; - pContextMap->Remove(strKey); - - return hr; -} - -HRESULT WpdObjectManagement::CommitNewObject( - _In_ ObjectManagementContext* pContext, - _In_ LPCWSTR pszContext, - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - LPWSTR pszObjectID = NULL; - - // Save the new object - HRESULT hr = m_pFakeDevice->SaveNewObject(pContext->ObjectProperties, &pszObjectID); - CHECK_HR(hr, "Failed to save new object [%ws] to device", pContext->Name); - - // Let the caller know the new object's ID. - if (SUCCEEDED(hr)) - { - hr = pResults->SetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID, pszObjectID); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID"); - } - - if (SUCCEEDED(hr)) - { - // Send the event - HRESULT hrTemp = S_OK; - CComPtr<IPortableDeviceValues> pEventParams; - - // Get the object properties used for sending the event - hrTemp = m_pFakeDevice->GetObjectPropertiesForEvent(pszObjectID, &pEventParams); - CHECK_HR(hrTemp, "Failed to get properties for event on object %ws", pszObjectID); - - if (SUCCEEDED(hrTemp)) - { - // Set the event-specific parameters - hrTemp = pEventParams->SetGuidValue(WPD_EVENT_PARAMETER_EVENT_ID, WPD_EVENT_OBJECT_ADDED); - CHECK_HR(hrTemp, "Failed to add WPD_EVENT_PARAMETER_EVENT_ID"); - - hrTemp = pEventParams->SetStringValue(WPD_EVENT_PARAMETER_OBJECT_CREATION_COOKIE, pszContext); - CHECK_HR(hrTemp, "Failed to add WPD_EVENT_PARAMETER_OBJECT_CREATION_COOKIE"); - - // Send the Event - if (SUCCEEDED(hr)) - { - PostWpdEvent(pParams, pEventParams); - } - } - } - - CoTaskMemFree(pszObjectID); - - return hr; -} - -HRESULT WpdObjectManagement::UpdateObject( - _In_ ObjectManagementContext* pContext, - _In_ IPortableDeviceValues* pParams, - _In_ IPortableDeviceValues* pResults) -{ - // For convenience, the ObjectID was stored in Name for object updates - LPCWSTR pszObjectId = pContext->Name; - - // Update the object - HRESULT hr = m_pFakeDevice->UpdateContentObject(pszObjectId, pContext->ObjectProperties); - CHECK_HR(hr, "Failed to update object [%ws] to device", pszObjectId); - - // Set the object ID. - if (hr == S_OK) - { - hr = pResults->SetStringValue(WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID, pszObjectId); - CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_MANAGEMENT_OBJECT_ID"); - } - - if (hr == S_OK) - { - // Send the event - HRESULT hrTemp = S_OK; - CComPtr<IPortableDeviceValues> pEventParams; - - // Get the object properties used for sending the event - hrTemp = m_pFakeDevice->GetObjectPropertiesForEvent(pContext->Name, &pEventParams); - CHECK_HR(hrTemp, "Failed to get properties for event on object %ws", pszObjectId); - - if (hrTemp == S_OK) - { - // Set the event-specific parameters - hrTemp = pEventParams->SetGuidValue(WPD_EVENT_PARAMETER_EVENT_ID, WPD_EVENT_OBJECT_UPDATED); - CHECK_HR(hrTemp, "Failed to add WPD_EVENT_PARAMETER_EVENT_ID"); - - // Send the Event - if (hrTemp == S_OK) - { - PostWpdEvent(pParams, pEventParams); - } - } - } - - return hr; -} |
