1 // Copyright 2011 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifdef UNSAFE_BUFFERS_BUILD 6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors. 7 #pragma allow_unsafe_buffers 8 #endif 9 10 #include "base/win/enum_variant.h" 11 12 #include <wrl/client.h> 13 14 #include <algorithm> 15 16 #include "base/check_op.h" 17 18 namespace base { 19 namespace win { 20 EnumVariant(ULONG count)21EnumVariant::EnumVariant(ULONG count) : current_index_(0) { 22 for (ULONG i = 0; i < count; ++i) 23 items_.emplace_back(ScopedVariant::kEmptyVariant); 24 } 25 26 EnumVariant::~EnumVariant() = default; 27 ItemAt(ULONG index)28VARIANT* EnumVariant::ItemAt(ULONG index) { 29 DCHECK_LT(index, items_.size()); 30 // This is a hack to return a mutable pointer to the ScopedVariant, even 31 // though the original intent of the AsInput method was to allow only readonly 32 // access to the wrapped variant. 33 return items_[index].AsInput(); 34 } 35 Next(ULONG requested_count,VARIANT * out_elements,ULONG * out_elements_received)36HRESULT EnumVariant::Next(ULONG requested_count, 37 VARIANT* out_elements, 38 ULONG* out_elements_received) { 39 if (!out_elements) 40 return E_INVALIDARG; 41 42 DCHECK_LE(current_index_, items_.size()); 43 ULONG available_count = static_cast<ULONG>(items_.size()) - current_index_; 44 ULONG count = std::min(requested_count, available_count); 45 for (ULONG i = 0; i < count; ++i) 46 out_elements[i] = items_[current_index_ + i].Copy(); 47 current_index_ += count; 48 49 // The caller can choose not to get the number of received elements by setting 50 // |out_elements_received| to nullptr. 51 if (out_elements_received) 52 *out_elements_received = count; 53 54 return (count == requested_count ? S_OK : S_FALSE); 55 } 56 Skip(ULONG skip_count)57HRESULT EnumVariant::Skip(ULONG skip_count) { 58 ULONG count = skip_count; 59 if (current_index_ + count > static_cast<ULONG>(items_.size())) 60 count = static_cast<ULONG>(items_.size()) - current_index_; 61 62 current_index_ += count; 63 return (count == skip_count ? S_OK : S_FALSE); 64 } 65 Reset()66HRESULT EnumVariant::Reset() { 67 current_index_ = 0; 68 return S_OK; 69 } 70 Clone(IEnumVARIANT ** out_cloned_object)71HRESULT EnumVariant::Clone(IEnumVARIANT** out_cloned_object) { 72 if (!out_cloned_object) 73 return E_INVALIDARG; 74 75 size_t count = items_.size(); 76 Microsoft::WRL::ComPtr<EnumVariant> other = 77 Microsoft::WRL::Make<EnumVariant>(static_cast<ULONG>(count)); 78 for (size_t i = 0; i < count; ++i) 79 other->items_[i] = static_cast<const VARIANT&>(items_[i]); 80 81 other->Skip(current_index_); 82 return other.CopyTo(IID_PPV_ARGS(out_cloned_object)); 83 } 84 85 } // namespace win 86 } // namespace base 87