/** * This method is called when we receive a WPD_COMMAND_OBJECT_RESOURCES_READ * command. * * The parameters sent to us are: * - WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT: the context the driver returned to * the client in OnOpenResource. * - WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ: the number of bytes to * read from the resource. * * The driver should: * - Read data associated with the resource and return it back to the caller in * WPD_PROPERTY_OBJECT_RESOURCES_DATA. * - Report the number of bytes actually read from the resource in * WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ. This number may be smaller * than WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ when reading the last * chunk of data from the resource. */ HRESULT WpdObjectResources::OnReadResource( _In_ IPortableDeviceValues* pParams, _In_ IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR wszResourceContext = NULL; DWORD dwNumBytesToRead = 0; DWORD dwNumBytesRead = 0; BYTE* pBuffer = NULL; DWORD cbBuffer = 0; WpdObjectResourceContext* pResourceContext = NULL; ContextMap* pContextMap = NULL; // Get the enumeration context identifier for this enumeration operation. We will // need this to lookup the specific enumeration context in the client context map. hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, &wszResourceContext); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT"); } // Get the number of bytes to read if (hr == S_OK) { hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ, &dwNumBytesToRead); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ"); } // Get the destination buffer if (hr == S_OK) { hr = pParams->GetBufferValue(WPD_PROPERTY_OBJECT_RESOURCES_DATA, &pBuffer, &cbBuffer); CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_DATA"); } // Get the client context map so we can retrieve the resource context for this resource // operation using the WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT property value obtained above. 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"); } if (hr == S_OK) { pResourceContext = (WpdObjectResourceContext*)pContextMap->GetContext(wszResourceContext); if (pResourceContext == NULL) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing resource context"); } } // Read the next chunk of data for this request if (hr == S_OK && pBuffer != NULL) { hr = ReadDataFromResource(pResourceContext, pBuffer, dwNumBytesToRead, &dwNumBytesRead); CHECK_HR(hr, "Failed to read %d bytes from resource", dwNumBytesToRead); } if (hr == S_OK && pBuffer != NULL) { hr = pResults->SetBufferValue(WPD_PROPERTY_OBJECT_RESOURCES_DATA, pBuffer, dwNumBytesRead); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_DATA"); } if (hr == S_OK) { hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ, dwNumBytesRead); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ"); } // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(wszResourceContext); // Free the memory. CoTaskMemFree ignores NULLs so no need to check. CoTaskMemFree(pBuffer); SAFE_RELEASE(pContextMap); return hr; }
HRESULT WpdObjectEnumerator::OnFindNext(IPortableDeviceValues* pParams, IPortableDeviceValues* pResults) { HRESULT hr = S_OK; LPWSTR wszEnumContext = NULL; DWORD dwNumObjectsRequested = 0; ContextMap* pContextMap = NULL; WpdObjectEnumeratorContext* pEnumeratorContext = NULL; DWORD NumObjectsEnumerated = 0; CComPtr<IPortableDevicePropVariantCollection> pObjectIDCollection; // First get ALL parameters for this command. If we cannot get ALL parameters // then E_INVALIDARG should be returned and no further processing should occur. // Get the enumeration context identifier for this enumeration operation. // The enumeration context identifier is needed to lookup the specific // enumeration context in the client context map for this enumeration operation. // NOTE that more than one enumeration may be in progress. hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, &wszEnumContext); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT"); } // Get the number of objects requested for this enumeration call. // The driver should always attempt to meet this requested value. // If there are fewer children than requested, the driver should return the remaining // children and a return code of S_FALSE. hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_ENUMERATION_NUM_OBJECTS_REQUESTED, &dwNumObjectsRequested); if (hr != S_OK) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_ENUMERATION_NUM_OBJECTS_REQUESTED"); } // Get the client context map so we can retrieve the enumeration context for this enumeration // operation. 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"); } if (hr == S_OK) { pEnumeratorContext = (WpdObjectEnumeratorContext*)pContextMap->GetContext(wszEnumContext); if (pEnumeratorContext == NULL) { hr = E_INVALIDARG; CHECK_HR(hr, "Missing enumeration context"); } } // CoCreate a collection to store the object identifiers being returned for this enumeration call. if (hr == S_OK) { hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL, CLSCTX_INPROC_SERVER, IID_IPortableDevicePropVariantCollection, (VOID**) &pObjectIDCollection); CHECK_HR(hr, "Failed to CoCreate CLSID_PortableDevicePropVariantCollection"); } // If the enumeration context reports that their are more objects to return, then continue, if not, // return an empty results set. if ((hr == S_OK) && (pEnumeratorContext != NULL) && (pEnumeratorContext->HasMoreChildrenToEnumerate() == TRUE)) { if (pEnumeratorContext->m_strParentObjectID.CompareNoCase(L"") == 0) { // We are being asked for the WPD_DEVICE_OBJECT_ID hr = AddStringValueToPropVariantCollection(pObjectIDCollection, WPD_DEVICE_OBJECT_ID); CHECK_HR(hr, "Failed to add 'DEVICE' object ID to enumeration collection"); // Update the the number of children we are returning for this enumeration call NumObjectsEnumerated++; } else if (pEnumeratorContext->m_strParentObjectID.CompareNoCase(WPD_DEVICE_OBJECT_ID) == 0) { // We are being asked for direct children of the WPD_DEVICE_OBJECT_ID switch (m_pBaseDriver->m_SensorType) { case WpdBaseDriver::UNKNOWN: hr = AddStringValueToPropVariantCollection(pObjectIDCollection, SENSOR_OBJECT_ID); break; case WpdBaseDriver::COMPASS: hr = AddStringValueToPropVariantCollection(pObjectIDCollection, COMPASS_SENSOR_OBJECT_ID); break; case WpdBaseDriver::SENSIRON: hr = AddStringValueToPropVariantCollection(pObjectIDCollection, TEMP_SENSOR_OBJECT_ID); break; case WpdBaseDriver::FLEX: hr = AddStringValueToPropVariantCollection(pObjectIDCollection, FLEX_SENSOR_OBJECT_ID); break; case WpdBaseDriver::PING: hr = AddStringValueToPropVariantCollection(pObjectIDCollection, PING_SENSOR_OBJECT_ID); break; case WpdBaseDriver::PIR: hr = AddStringValueToPropVariantCollection(pObjectIDCollection, PIR_SENSOR_OBJECT_ID); break; case WpdBaseDriver::MEMSIC: hr = AddStringValueToPropVariantCollection(pObjectIDCollection, MEMSIC_SENSOR_OBJECT_ID); break; case WpdBaseDriver::QTI: hr = AddStringValueToPropVariantCollection(pObjectIDCollection, QTI_SENSOR_OBJECT_ID); break; case WpdBaseDriver::PIEZO: hr = AddStringValueToPropVariantCollection(pObjectIDCollection, PIEZO_SENSOR_OBJECT_ID); break; case WpdBaseDriver::HITACHI: hr = AddStringValueToPropVariantCollection(pObjectIDCollection, HITACHI_SENSOR_OBJECT_ID); break; default: break; } CHECK_HR(hr, "Failed to add storage object ID to enumeration collection"); // Update the the number of children we are returning for this enumeration call NumObjectsEnumerated++; } } // Set the collection of object identifiers enumerated in the results if (hr == S_OK) { hr = pResults->SetIPortableDevicePropVariantCollectionValue(WPD_PROPERTY_OBJECT_ENUMERATION_OBJECT_IDS, pObjectIDCollection); CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_ENUMERATION_OBJECT_IDS"); } // If the enumeration context reports that their are no more objects to return then return S_FALSE indicating to the // caller that we are finished. if (hr == S_OK) { if (pEnumeratorContext != NULL) { // Update the number of children we have enumerated and returned to the caller pEnumeratorContext->m_ChildrenEnumerated += NumObjectsEnumerated; // Check the number requested against the number enumerated and set the HRESULT // accordingly. if (NumObjectsEnumerated < dwNumObjectsRequested) { // We returned less than the number of objects requested to the caller hr = S_FALSE; } else { // We returned exactly the number of objects requested to the caller hr = S_OK; } } } // Free the memory. CoTaskMemFree(wszEnumContext); wszEnumContext = NULL; SAFE_RELEASE(pContextMap); return hr; }