// Initialize the enumeration context VOID WpdObjectEnumerator::InitializeEnumerationContext( WpdObjectEnumeratorContext* pEnumeratorContext, CAtlStringW strParentObjectID) { if (pEnumeratorContext == NULL) { return; } // Initialize the enumeration context with the parent object identifier pEnumeratorContext->m_strParentObjectID = strParentObjectID; // Our sample driver has a very simple object structure where we know // how many children are under each parent. // The eumeration context is initialized below with this information. if (strParentObjectID.CompareNoCase(L"") == 0) { // Clients passing an 'empty' string for the parent are asking for the // 'DEVICE' object. We should return 1 child in this case. pEnumeratorContext->m_TotalChildren = 1; } else if (strParentObjectID.CompareNoCase(WPD_DEVICE_OBJECT_ID) == 0) { // The device object contains 1 child (the storage object). pEnumeratorContext->m_TotalChildren = 1; } // If the sensor objects have children, add them here... else { // The sensor object contains 0 children. pEnumeratorContext->m_TotalChildren = 0; } }
HRESULT WpdService::CheckRequestFilename( _In_ LPCWSTR pszRequestFilename) { HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); CAtlStringW strRequestFilename = pszRequestFilename; // For simplicity, the request filename happens to be the same as the service object ID if (strRequestFilename.CompareNoCase(m_pGattService->GetRequestFilename()) == 0) { hr = S_OK; } else { CHECK_HR(hr, "Unknown request filename %ws received", pszRequestFilename); } return hr; }
ACCESS_SCOPE FakeDevice::GetAccessScope( _In_ IPortableDeviceValues* pParams) { ACCESS_SCOPE Scope = FULL_DEVICE_ACCESS; LPWSTR pszFileName = NULL; // For simplicity, our request filename is the same as the the service object ID if (pParams && (pParams->GetStringValue(PRIVATE_SAMPLE_DRIVER_REQUEST_FILENAME, &pszFileName) == S_OK)) { CAtlStringW strRequestFilename = pszFileName; // For simplicity, our request filename is the same as the the service object ID // Case-insensitive comparison is required if (strRequestFilename.CompareNoCase(m_ContactsService.GetRequestFilename()) == 0) { Scope = CONTACTS_SERVICE_ACCESS; } } CoTaskMemFree(pszFileName); return Scope; }
/** * This method is called to populate PROPERTYKEYs found on objects. * * The parameters sent to us are: * wszObjectID - the object whose supported resource keys are being requested * pKeys - An IPortableDeviceKeyCollection to be populated with supported PROPERTYKEYs * * The driver should: * Add PROPERTYKEYs pertaining to the specified object. */ HRESULT WpdObjectResources::GetSupportedResourcesForObject( _In_ LPCWSTR wszObjectID, _In_ IPortableDeviceKeyCollection* pKeys) { HRESULT hr = S_OK; CAtlStringW strObjectID; if ((wszObjectID == NULL) || (pKeys == NULL)) { hr = E_INVALIDARG; return hr; } strObjectID = wszObjectID; if (strObjectID.CompareNoCase(README_FILE_OBJECT_ID) == 0) { hr = pKeys->Add(WPD_RESOURCE_DEFAULT); CHECK_HR(hr, "Failed to set WPD_RESOURCE_DEFAULT"); } return hr; }
/** * This method is called to populate resource attributes found on a particular object * resource. * * The parameters sent to us are: * wszObjectID - the object whose resource attributes are being requested * Key - the resource on the specified object whose attributes are being returned * pAttributes - An IPortableDeviceValues to be populated with resource attributes. * * The driver should: * Add attributes pertaining to the resource on the specified object. */ HRESULT WpdObjectResources::GetResourceAttributesForObject( _In_ LPCWSTR wszObjectID, _In_ REFPROPERTYKEY Key, _In_ IPortableDeviceValues* pAttributes) { HRESULT hr = S_OK; CAtlStringW strObjectID; if ((wszObjectID == NULL) || (pAttributes == NULL)) { hr = E_INVALIDARG; return hr; } strObjectID = wszObjectID; if ((strObjectID.CompareNoCase(README_FILE_OBJECT_ID) == 0) && (IsEqualPropertyKey(Key, WPD_RESOURCE_DEFAULT))) { if (hr == S_OK) { hr = pAttributes->SetBoolValue(WPD_RESOURCE_ATTRIBUTE_CAN_DELETE, FALSE); CHECK_HR(hr, "Failed to set WPD_RESOURCE_ATTRIBUTE_CAN_DELETE"); } if (hr == S_OK) { hr = pAttributes->SetUnsignedLargeIntegerValue(WPD_RESOURCE_ATTRIBUTE_TOTAL_SIZE, GetObjectSize(strObjectID)); CHECK_HR(hr, "Failed to set WPD_RESOURCE_ATTRIBUTE_TOTAL_SIZE"); } if (hr == S_OK) { hr = pAttributes->SetBoolValue(WPD_RESOURCE_ATTRIBUTE_CAN_READ, TRUE); CHECK_HR(hr, "Failed to set WPD_RESOURCE_ATTRIBUTE_CAN_READ"); } if (hr == S_OK) { hr = pAttributes->SetBoolValue(WPD_RESOURCE_ATTRIBUTE_CAN_WRITE, FALSE); CHECK_HR(hr, "Failed to set WPD_RESOURCE_ATTRIBUTE_CAN_WRITE"); } if (hr == S_OK) { hr = pAttributes->SetBoolValue(WPD_RESOURCE_ATTRIBUTE_CAN_DELETE, FALSE); CHECK_HR(hr, "Failed to set WPD_RESOURCE_ATTRIBUTE_CAN_DELETE"); } if (hr == S_OK) { hr = pAttributes->SetGuidValue(WPD_RESOURCE_ATTRIBUTE_FORMAT, GetObjectFormat(strObjectID)); CHECK_HR(hr, "Failed to set WPD_RESOURCE_ATTRIBUTE_FORMAT"); } if (hr == S_OK) { hr = pAttributes->SetUnsignedIntegerValue(WPD_RESOURCE_ATTRIBUTE_OPTIMAL_READ_BUFFER_SIZE, FILE_OPTIMAL_READ_BUFFER_SIZE_VALUE); CHECK_HR(hr, "Failed to set WPD_RESOURCE_ATTRIBUTE_OPTIMAL_READ_BUFFER_SIZE"); } if (hr == S_OK) { hr = pAttributes->SetUnsignedIntegerValue(WPD_RESOURCE_ATTRIBUTE_OPTIMAL_WRITE_BUFFER_SIZE, FILE_OPTIMAL_WRITE_BUFFER_SIZE_VALUE); CHECK_HR(hr, "Failed to set WPD_RESOURCE_ATTRIBUTE_OPTIMAL_WRITE_BUFFER_SIZE"); } } return hr; }
/** * This method is called when we receive a WPD_COMMAND_OBJECT_RESOURCES_OPEN * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_RESOURCES_OBJECT_ID: the object identifier of the * object which contains the specified resource * * - WPD_PROPERTY_OBJECT_RESOURCES_RESOURCE_KEYS: the specified resource * to open * * - WPD_PROPERTY_OBJECT_RESOURCES_ACCESS_MODE: the access mode to which to * open the specified resource * * The driver should: * - Create a new context for this resource operation. * - Return an identifier for the context in WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT. * - Set the optimal transfer size in WPD_PROPERTY_OBJECT_RESOURCES_OPTIMAL_TRANSFER_BUFFER_SIZE * */ HRESULT WpdObjectResources::OnOpenResource( _In_ IPortableDeviceValues* pParams, _In_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR wszObjectID = NULL; PROPERTYKEY Key = WPD_PROPERTY_NULL; DWORD dwMode = STGM_READ; CAtlStringW strStrObjectID; CAtlStringW strResourceContext; ContextMap* pContextMap = NULL; // Get the Object identifier of the object which contains the specified resource hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_OBJECT_ID, &wszObjectID); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_OBJECT_ID"); } // Get the resource key if (hr == S_OK) { hr = pParams->GetKeyValue(WPD_PROPERTY_OBJECT_RESOURCES_RESOURCE_KEYS, &Key); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_RESOURCE_KEYS"); } // Get the access mode if (hr == S_OK) { hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_ACCESS_MODE, &dwMode); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_ACCESS_MODE"); } // Validate whether the params given to us are correct. In this case, we need to check that the object // supports the resource requested, and can be opened in the requested access mode. if (hr == S_OK) { // In this sample, we only have one object (README_FILE_OBJECT_ID) which supports a // resource (WPD_RESOURCE_DEFAULT) for reading only. // So if any other Object ID or any other resource is specified, it must be invalid. strStrObjectID = wszObjectID; if(strStrObjectID.CompareNoCase(README_FILE_OBJECT_ID) != 0) { hr = E_INVALIDARG; CHECK_HR(hr, "Object [%ws] does not support resources", wszObjectID); } if (hr == S_OK) { if (!IsEqualPropertyKey(Key, WPD_RESOURCE_DEFAULT)) { hr = E_INVALIDARG; CHECK_HR(hr, "Only WPD_RESOURCE_DEFAULT is supported in this sample driver"); } } if (hr == S_OK) { if ((dwMode & STGM_WRITE) != 0) { hr = E_ACCESSDENIED; CHECK_HR(hr, "This resource is not available for write access"); } } } // Get the context map which the driver stored in pParams for convenience if (hr == S_OK) { hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap); CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP"); } // Create a new resource operation context, initialize it, and add it to the client context map. if (hr == S_OK) { WpdObjectResourceContext* pResourceContext = new WpdObjectResourceContext(); if (pResourceContext != NULL) { // Initialize the resource context with ... pResourceContext->m_strObjectID = wszObjectID; pResourceContext->m_Resource = Key; pResourceContext->m_BytesTransferred = 0; pResourceContext->m_BytesTotal = GetObjectSize(wszObjectID); // Add the resource context to the context map pContextMap->Add(pResourceContext, strResourceContext); // Release the resource context because it has been AddRef'ed during Add() SAFE_RELEASE(pResourceContext); } else { hr = E_OUTOFMEMORY; CHECK_HR(hr, "Failed to allocate resource context"); } } if (hr == S_OK) { hr = pResults->SetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, strResourceContext); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT"); } // Set the optimal buffer size if (hr == S_OK) { hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_OPTIMAL_TRANSFER_BUFFER_SIZE, FILE_OPTIMAL_READ_BUFFER_SIZE_VALUE); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_OPTIMAL_TRANSFER_BUFFER_SIZE value"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(wszObjectID); SAFE_RELEASE(pContextMap); return hr; }