• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)21 EnumVariant::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)28 VARIANT* 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)36 HRESULT 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)57 HRESULT 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()66 HRESULT EnumVariant::Reset() {
67   current_index_ = 0;
68   return S_OK;
69 }
70 
Clone(IEnumVARIANT ** out_cloned_object)71 HRESULT 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