HRESULT FakeDevice::FindNext( const DWORD dwNumObjectsRequested, _In_ WpdObjectEnumeratorContext* pEnumContext, _In_ IPortableDevicePropVariantCollection* pObjectIDCollection, _Out_opt_ DWORD* pdwNumObjectsEnumerated) { HRESULT hr = S_OK; DWORD NumObjectsEnumerated = 0; if ((pEnumContext == NULL) || (pObjectIDCollection == NULL)) { hr = E_POINTER; CHECK_HR(hr, "Cannot have NULL parameter"); return hr; } if (pdwNumObjectsEnumerated) { *pdwNumObjectsEnumerated = 0; } // If the enumeration context reports that their are more objects to return, then continue, if not, // return an empty results set. if (pEnumContext->HasMoreChildrenToEnumerate()) { if (pEnumContext->m_strParentObjectID.CompareNoCase(L"") == 0) { // We are being asked for the device hr = AddStringValueToPropVariantCollection(pObjectIDCollection, m_DeviceContent.ObjectID); 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 { FakeContent* pContent = NULL; HRESULT hrGet = GetContent(pEnumContext->m_Scope, pEnumContext->m_strParentObjectID, &pContent); CHECK_HR(hrGet, "Failed to get content '%ws'", pEnumContext->m_strParentObjectID); if (hrGet == S_OK) { DWORD dwStartIndex = pEnumContext->m_ChildrenEnumerated; for (DWORD i=0; i<dwNumObjectsRequested; i++) { FakeContent* pChild = NULL; if (pContent->FindNext(pEnumContext->m_Scope, dwStartIndex, &pChild)) { hr = AddStringValueToPropVariantCollection(pObjectIDCollection, pChild->ObjectID); CHECK_HR(hr, "Failed to add object [%ws]", pChild->ObjectID); if (hr == S_OK) { // Update the the number of children we are returning for this enumeration call dwStartIndex++; NumObjectsEnumerated++; } } else { // no more children break; } } } } } if (hr == S_OK && pdwNumObjectsEnumerated) { *pdwNumObjectsEnumerated = NumObjectsEnumerated; } 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; }