diff options
Diffstat (limited to 'wpd/WpdServiceSampleDriver/FakeContent.cpp')
| -rw-r--r-- | wpd/WpdServiceSampleDriver/FakeContent.cpp | 635 |
1 files changed, 635 insertions, 0 deletions
diff --git a/wpd/WpdServiceSampleDriver/FakeContent.cpp b/wpd/WpdServiceSampleDriver/FakeContent.cpp new file mode 100644 index 00000000..96139791 --- /dev/null +++ b/wpd/WpdServiceSampleDriver/FakeContent.cpp @@ -0,0 +1,635 @@ +#include "stdafx.h" +#include "FakeContent.tmh" + +HRESULT FakeContent::InitializeContent(_Inout_ DWORD *pdwLastObjectID) +{ + UNREFERENCED_PARAMETER(pdwLastObjectID); + return S_OK; +} + +HRESULT FakeContent::InitializeEnumerationContext( + ACCESS_SCOPE Scope, + _In_ WpdObjectEnumeratorContext* pEnumeratorContext) +{ + HRESULT hr = S_OK; + UNREFERENCED_PARAMETER(Scope); + + if (pEnumeratorContext == NULL) + { + hr = E_POINTER; + CHECK_HR(hr, "Cannot have NULL parameter"); + return hr; + } + + pEnumeratorContext->m_TotalChildren = static_cast<DWORD>(m_Children.GetCount()); + return hr; +} + +HRESULT FakeContent::GetSupportedProperties(_In_ IPortableDeviceKeyCollection *pKeys) +{ + HRESULT hr = S_OK; + + if(pKeys == NULL) + { + hr = E_POINTER; + CHECK_HR(hr, "Cannot have NULL collection parameter"); + return hr; + } + + hr = pKeys->Add(WPD_OBJECT_ID); + CHECK_HR(hr, "Failed to add WPD_OBJECT_ID"); + + if (hr == S_OK) + { + hr = pKeys->Add(WPD_OBJECT_PERSISTENT_UNIQUE_ID); + CHECK_HR(hr, "Failed to add WPD_OBJECT_PERSISTENT_UNIQUE_ID"); + } + + if (hr == S_OK) + { + hr = pKeys->Add(WPD_OBJECT_PARENT_ID); + CHECK_HR(hr, "Failed to add WPD_OBJECT_PARENT_ID"); + } + + if (hr == S_OK) + { + hr = pKeys->Add(WPD_OBJECT_NAME); + CHECK_HR(hr, "Failed to add WPD_OBJECT_NAME"); + } + + if (hr == S_OK) + { + hr = pKeys->Add(WPD_OBJECT_CONTENT_TYPE); + CHECK_HR(hr, "Failed to add WPD_OBJECT_CONTENT_TYPE"); + } + + if (hr == S_OK) + { + hr = pKeys->Add(WPD_OBJECT_FORMAT); + CHECK_HR(hr, "Failed to add WPD_OBJECT_FORMAT"); + } + + if (hr == S_OK) + { + hr = pKeys->Add(WPD_OBJECT_CAN_DELETE); + CHECK_HR(hr, "Failed to add WPD_OBJECT_CAN_DELETE"); + } + + return hr; +} + +HRESULT FakeContent::GetPropertyAttributes( + _In_ REFPROPERTYKEY Key, + _In_ IPortableDeviceValues* pAttributes) +{ + HRESULT hr = S_OK; + + if(pAttributes == NULL) + { + hr = E_POINTER; + CHECK_HR(hr, "Cannot have NULL attributes parameter"); + return hr; + } + + hr = pAttributes->SetBoolValue(WPD_PROPERTY_ATTRIBUTE_CAN_DELETE, FALSE); + CHECK_HR(hr, "Failed to set WPD_PROPERTY_ATTRIBUTE_CAN_DELETE"); + + if (hr == S_OK) + { + hr = pAttributes->SetBoolValue(WPD_PROPERTY_ATTRIBUTE_CAN_READ, TRUE); + CHECK_HR(hr, "Failed to set WPD_PROPERTY_ATTRIBUTE_CAN_READ"); + } + + if (hr == S_OK) + { + if (IsEqualPropertyKey(Key, WPD_OBJECT_NAME)) + { + hr = pAttributes->SetBoolValue(WPD_PROPERTY_ATTRIBUTE_CAN_WRITE, TRUE); + CHECK_HR(hr, "Failed to set WPD_PROPERTY_ATTRIBUTE_CAN_WRITE"); + } + else + { + hr = pAttributes->SetBoolValue(WPD_PROPERTY_ATTRIBUTE_CAN_WRITE, FALSE); + CHECK_HR(hr, "Failed to set WPD_PROPERTY_ATTRIBUTE_CAN_WRITE"); + } + } + + if (hr == S_OK) + { + hr = pAttributes->SetBoolValue(WPD_PROPERTY_ATTRIBUTE_FAST_PROPERTY, TRUE); + CHECK_HR(hr, "Failed to set WPD_PROPERTY_ATTRIBUTE_FAST_PROPERTY"); + } + + if (hr == S_OK) + { + hr = pAttributes->SetUnsignedIntegerValue(WPD_PROPERTY_ATTRIBUTE_FORM, WPD_PROPERTY_ATTRIBUTE_FORM_UNSPECIFIED); + CHECK_HR(hr, "Failed to set WPD_PROPERTY_ATTRIBUTE_FORM"); + } + + return hr; +} + +HRESULT FakeContent::GetValue( + _In_ REFPROPERTYKEY Key, + _In_ IPortableDeviceValues* pStore) +{ + HRESULT hr = S_OK; + PropVariantWrapper pvValue; + + if(pStore == NULL) + { + hr = E_POINTER; + CHECK_HR(hr, "Cannot have NULL parameter"); + return hr; + } + + if (IsEqualPropertyKey(Key, WPD_OBJECT_ID)) + { + // Add WPD_OBJECT_ID + pvValue = ObjectID; + hr = pStore->SetValue(WPD_OBJECT_ID, &pvValue); + CHECK_HR(hr, ("Failed to set WPD_OBJECT_ID")); + } + else if (IsEqualPropertyKey(Key, WPD_OBJECT_PERSISTENT_UNIQUE_ID)) + { + // Add WPD_OBJECT_PERSISTENT_UNIQUE_ID + pvValue = this->PersistentUniqueID; + hr = pStore->SetValue(WPD_OBJECT_PERSISTENT_UNIQUE_ID, &pvValue); + CHECK_HR(hr, ("Failed to set WPD_OBJECT_PERSISTENT_UNIQUE_ID")); + } + else if (IsEqualPropertyKey(Key, WPD_OBJECT_PARENT_ID)) + { + // Add WPD_OBJECT_PARENT_ID + pvValue = ParentID; + hr = pStore->SetValue(WPD_OBJECT_PARENT_ID, &pvValue); + CHECK_HR(hr, ("Failed to set WPD_OBJECT_PARENT_ID")); + } + else if (IsEqualPropertyKey(Key, WPD_OBJECT_NAME)) + { + // Add WPD_OBJECT_NAME + pvValue = Name; + hr = pStore->SetValue(WPD_OBJECT_NAME, &pvValue); + CHECK_HR(hr, ("Failed to set WPD_OBJECT_NAME")); + } + else if (IsEqualPropertyKey(Key, WPD_OBJECT_CONTENT_TYPE)) + { + // Add WPD_OBJECT_CONTENT_TYPE + hr = pStore->SetGuidValue(WPD_OBJECT_CONTENT_TYPE, ContentType); + CHECK_HR(hr, ("Failed to set WPD_OBJECT_CONTENT_TYPE")); + } + else if (IsEqualPropertyKey(Key, WPD_OBJECT_FORMAT)) + { + // Add WPD_OBJECT_FORMAT + hr = pStore->SetGuidValue(WPD_OBJECT_FORMAT, Format); + CHECK_HR(hr, ("Failed to set WPD_OBJECT_FORMAT")); + } + else if (IsEqualPropertyKey(Key, WPD_OBJECT_CAN_DELETE)) + { + // Add WPD_OBJECT_CAN_DELETE + hr = pStore->SetBoolValue(WPD_OBJECT_CAN_DELETE, CanDelete); + CHECK_HR(hr, ("Failed to set WPD_OBJECT_CAN_DELETE")); + } + else + { + hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + CHECK_HR(hr, "Property {%ws}.%d is not supported", CComBSTR(Key.fmtid), Key.pid); + } + return hr; +} + +HRESULT FakeContent::WriteValue( + _In_ REFPROPERTYKEY Key, + _In_ REFPROPVARIANT Value) +{ + HRESULT hr = S_OK; + PropVariantWrapper pvValue; + + if(IsEqualPropertyKey(Key, WPD_OBJECT_NAME)) + { + if(Value.vt == VT_LPWSTR) + { + if (Value.pwszVal != NULL && Value.pwszVal[0] != L'\0') + { + Name = Value.pwszVal; + } + else + { + hr = E_INVALIDARG; + CHECK_HR(hr, "Failed to set WPD_OBJECT_NAME because value was an empty string"); + } + } + else + { + hr = E_INVALIDARG; + CHECK_HR(hr, "Failed to set WPD_OBJECT_NAME because type was not VT_LPWSTR"); + } + } + else + { + hr = E_ACCESSDENIED; + CHECK_HR(hr, "Property %ws.%d on [%ws] does not support set value operation", CComBSTR(Key.fmtid), Key.pid, ObjectID); + } + + return hr; +} + +HRESULT FakeContent::CreatePropertiesOnlyObject( + _In_ IPortableDeviceValues* pObjectProperties, + _Out_ DWORD* pdwLastObjectID, + _Outptr_result_nullonfailure_ FakeContent** ppNewObject) +{ + UNREFERENCED_PARAMETER(pObjectProperties); + UNREFERENCED_PARAMETER(pdwLastObjectID); + *ppNewObject = NULL; + return E_ACCESSDENIED; +} + +HRESULT FakeContent::GetSupportedResources( + _In_ IPortableDeviceKeyCollection* pResources) +{ + UNREFERENCED_PARAMETER(pResources); + return S_OK; +} + +HRESULT FakeContent::GetResourceAttributes( + _In_ REFPROPERTYKEY Resource, + _In_ IPortableDeviceValues* pAttributes) +{ + UNREFERENCED_PARAMETER(Resource); + UNREFERENCED_PARAMETER(pAttributes); + return S_OK; +} + +HRESULT FakeContent::OpenResource( + _In_ REFPROPERTYKEY Resource, + const DWORD dwMode, + _In_ WpdObjectResourceContext* pResourceContext) +{ + UNREFERENCED_PARAMETER(Resource); + UNREFERENCED_PARAMETER(dwMode); + UNREFERENCED_PARAMETER(pResourceContext); + return S_OK; +} + +HRESULT FakeContent::ReadResourceData( + _In_ WpdObjectResourceContext* pResourceContext, + _Out_writes_to_(dwNumBytesToRead, *pdwNumBytesRead) BYTE* pBuffer, + const DWORD dwNumBytesToRead, + _Out_ DWORD* pdwNumBytesRead) +{ + UNREFERENCED_PARAMETER(pResourceContext); + UNREFERENCED_PARAMETER(pBuffer); + UNREFERENCED_PARAMETER(dwNumBytesToRead); + *pdwNumBytesRead = 0; + return S_OK; +} + +bool FakeContent::CanAccess( + ACCESS_SCOPE Scope) +{ + return ((Scope & RequiredScope) == RequiredScope); +} + +HRESULT FakeContent::GetAllValues( + _In_ IPortableDeviceValues* pStore) +{ + HRESULT hr = S_OK; + DWORD cKeys = 0; + CComPtr<IPortableDeviceKeyCollection> pKeys; + + if(pStore == NULL) + { + hr = E_POINTER; + CHECK_HR(hr, "Cannot have NULL parameter"); + return hr; + } + + // CoCreate a collection to store the property keys we are going to use + // to request the property values of. + if (hr == S_OK) + { + hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection, + NULL, + CLSCTX_INPROC_SERVER, + IID_IPortableDeviceKeyCollection, + (VOID**) &pKeys); + CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDeviceKeyCollection"); + } + + if (hr == S_OK) + { + hr = GetSupportedProperties(pKeys); + CHECK_HR(hr, "Failed to get supported properties"); + } + + if (hr == S_OK) + { + hr = pKeys->GetCount(&cKeys); + CHECK_HR(hr, "Failed to get supported properties"); + } + + if (hr == S_OK) + { + for (DWORD i=0; i<cKeys; i++) + { + PROPERTYKEY Key = {0}; + hr = pKeys->GetAt(i, &Key); + CHECK_HR(hr, "Failed to get supported property at index %d", i); + if (hr == S_OK) + { + hr = GetValue(Key, pStore); + CHECK_HR(hr, "Failed to get property value at index %d", i); + } + } + } + + return hr; +} + +HRESULT FakeContent::WriteValues( + _In_ IPortableDeviceValues* pValues, + _In_ IPortableDeviceValues* pResults, + _Out_ bool* pbObjectChanged) +{ + HRESULT hr = S_OK; + DWORD cValues = 0; + bool hasFailedWrite = false; + + if (pValues == NULL || pResults == NULL || pbObjectChanged == NULL) + { + hr = E_POINTER; + CHECK_HR(hr, "Cannot have NULL parameter"); + return hr; + } + + hr = pValues->GetCount(&cValues); + CHECK_HR(hr, "Failed to get total number of values"); + + (*pbObjectChanged) = false; + + for (DWORD dwIndex = 0; dwIndex < cValues; dwIndex++) + { + PROPERTYKEY Key = WPD_PROPERTY_NULL; + PROPVARIANT Value; + PropVariantInit(&Value); + + hr = pValues->GetAt(dwIndex, &Key, &Value); + CHECK_HR(hr, "Failed to get PROPERTYKEY at index %d", dwIndex); + + if (hr == S_OK) + { + HRESULT hrWrite = WriteValue(Key, Value); + if (FAILED(hrWrite)) + { + CHECK_HR(hrWrite, "Failed to write value at index %d", dwIndex); + hasFailedWrite = true; + } + else + { + (*pbObjectChanged) = true; + } + + hr = pResults->SetErrorValue(Key, hrWrite); + CHECK_HR(hr, "Failed to set error result value at index %d", dwIndex); + } + + PropVariantClear(&Value); + } + + // Since we have set failures for the property set operations we must let the application + // know by returning S_FALSE. This will instruct the application to look at the + // property set operation results for failure values. + if ((hr == S_OK) && hasFailedWrite) + { + hr = S_FALSE; + } + + return hr; +} + +_Success_(return) +bool FakeContent::FindNext( + ACCESS_SCOPE Scope, + const DWORD dwIndex, + _Outptr_result_nullonfailure_ FakeContent** ppChild) +{ + HRESULT hr = S_OK; + bool bFound = false; + + if (ppChild == NULL) + { + hr = E_POINTER; + CHECK_HR(hr, "Cannot have NULL parameter"); + return false; + } + + *ppChild = NULL; + + if (dwIndex < m_Children.GetCount()) + { + if (m_Children[dwIndex] && (m_Children[dwIndex]->CanAccess(Scope))) + { + *ppChild = m_Children[dwIndex]; + bFound = true; + } + } + + return bFound; +} + +HRESULT FakeContent::GetContent( + ACCESS_SCOPE Scope, + _In_ LPCWSTR wszObjectID, + _Outptr_result_nullonfailure_ FakeContent** ppContent) +{ + HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); + *ppContent = NULL; + + if (CanAccess(Scope)) + { + if (ObjectID.CompareNoCase(wszObjectID) == 0) + { + hr = S_OK; + *ppContent = this; + } + else + { + DWORD dwIndex = 0; + FakeContent* pChild = NULL; + while (FindNext(Scope, dwIndex, &pChild)) + { + hr = pChild->GetContent(Scope, wszObjectID, ppContent); + if (hr == S_OK || hr == E_ACCESSDENIED) + { + break; + } + dwIndex++; + } + } + } + else + { + hr = E_ACCESSDENIED; + CHECK_HR(hr, "GetContent: '%ws' was found but falls outside scope", wszObjectID); + } + + return hr; +} + +HRESULT FakeContent::GetObjectIDsByFormat( + ACCESS_SCOPE Scope, + _In_ REFGUID guidFormat, + const DWORD dwDepth, + _In_ IPortableDevicePropVariantCollection* pObjectIDs) +{ + HRESULT hr = S_OK; + + if (CanAccess(Scope)) + { + DWORD dwIndex = 0; + FakeContent* pChild = NULL; + + if (Format == guidFormat || guidFormat == WPD_OBJECT_FORMAT_ALL) + { + PROPVARIANT pv = {0}; + PropVariantInit(&pv); + pv.vt = VT_LPWSTR; + pv.pwszVal = ObjectID.GetBuffer(); + hr = pObjectIDs->Add(&pv); + CHECK_HR(hr, "Failed to add '%ws' to the list of object IDs by format", ObjectID); + } + + if (dwDepth > 0) + { + while ((hr == S_OK) && (FindNext(Scope, dwIndex, &pChild))) + { + hr = pChild->GetObjectIDsByFormat(Scope, guidFormat, dwDepth-1, pObjectIDs); + CHECK_HR(hr, "Failed to get object IDs by format for child at index %d", dwIndex); + dwIndex++; + } + } + } + else + { + hr = E_ACCESSDENIED; + } + + return hr; +} + +HRESULT FakeContent::GetObjectIDByPersistentID( + ACCESS_SCOPE Scope, + _In_ LPCWSTR wszPersistentID, + _In_ IPortableDevicePropVariantCollection* pObjectIDs) +{ + HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); + + if (CanAccess(Scope)) + { + if (PersistentUniqueID.CompareNoCase(wszPersistentID) == 0) + { + PROPVARIANT pv = {0}; + PropVariantInit(&pv); + pv.vt = VT_LPWSTR; + pv.pwszVal = ObjectID.GetBuffer(); + + hr = pObjectIDs->Add(&pv); + CHECK_HR(hr, "Failed to add '%ws' to the list of object IDs", ObjectID); + } + else + { + DWORD dwIndex = 0; + FakeContent* pChild = NULL; + while (FindNext(Scope, dwIndex, &pChild)) + { + hr = pChild->GetObjectIDByPersistentID(Scope, wszPersistentID, pObjectIDs); + if (hr == S_OK || hr == E_ACCESSDENIED) + { + // Found the object or was denied access + break; + } + else if (hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + CHECK_HR(hr, "Failed to get object ID for child at index %d", dwIndex); + } + dwIndex++; + } + } + } + else + { + hr = E_ACCESSDENIED; + } + + return hr; +} + +HRESULT FakeContent::MarkForDelete( + const DWORD dwOptions) +{ + HRESULT hr = S_OK; + + if (CanDelete == false) + { + hr = E_ACCESSDENIED; + CHECK_HR(hr, "Object '%ws' is not deletable", ObjectID); + return hr; + } + + if (dwOptions == PORTABLE_DEVICE_DELETE_NO_RECURSION) + { + if (m_Children.GetCount() > 0) + { + hr = HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY); + } + } + else if (dwOptions == PORTABLE_DEVICE_DELETE_WITH_RECURSION) + { + // Mark children for delete + for (size_t Index = 0; Index < m_Children.GetCount(); Index++) + { + if (m_Children[Index]) + { + hr = m_Children[Index]->MarkForDelete(dwOptions); + CHECK_HR(hr, "Failed to mark child '%ws' for deletion", m_Children[Index]->ObjectID); + } + } + } + + if (hr == S_OK) + { + // All successful. Mark self for delete + MarkedForDeletion = true; + } + + return hr; +} + +HRESULT FakeContent::RemoveObjectsMarkedForDeletion( + ACCESS_SCOPE Scope) +{ + HRESULT hr = S_OK; + DWORD dwIndex = 0; + FakeContent* pChild = NULL; + + while (FindNext(Scope, dwIndex, &pChild)) + { + if (pChild != NULL) + { + hr = pChild->RemoveObjectsMarkedForDeletion(Scope); + CHECK_HR(hr, "Failed to remove children marked for deletion for object '%ws'", pChild->ObjectID); + + if ((hr == S_OK) && (pChild->MarkedForDeletion == true)) + { + m_Children.RemoveAt(dwIndex); + delete pChild; + pChild = NULL; + } + } + dwIndex++; + } + + m_Children.FreeExtra(); + + return hr; +} |
