• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2010 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/scoped_bstr.h"
11 
12 #include <stdint.h>
13 
14 #include <string_view>
15 
16 #include "base/check.h"
17 #include "base/numerics/safe_conversions.h"
18 #include "base/process/memory.h"
19 #include "base/strings/string_util.h"
20 
21 namespace base {
22 namespace win {
23 
24 namespace {
25 
AllocBstrOrDie(std::wstring_view non_bstr)26 BSTR AllocBstrOrDie(std::wstring_view non_bstr) {
27   BSTR result = ::SysAllocStringLen(non_bstr.data(),
28                                     checked_cast<UINT>(non_bstr.length()));
29   if (!result) {
30     base::TerminateBecauseOutOfMemory((non_bstr.length() + 1) *
31                                       sizeof(wchar_t));
32   }
33   return result;
34 }
35 
AllocBstrBytesOrDie(size_t bytes)36 BSTR AllocBstrBytesOrDie(size_t bytes) {
37   BSTR result = ::SysAllocStringByteLen(nullptr, checked_cast<UINT>(bytes));
38   if (!result)
39     base::TerminateBecauseOutOfMemory(bytes + sizeof(wchar_t));
40   return result;
41 }
42 
43 }  // namespace
44 
ScopedBstr(std::wstring_view non_bstr)45 ScopedBstr::ScopedBstr(std::wstring_view non_bstr)
46     : bstr_(AllocBstrOrDie(non_bstr)) {}
47 
~ScopedBstr()48 ScopedBstr::~ScopedBstr() {
49   static_assert(sizeof(ScopedBstr) == sizeof(BSTR), "ScopedBstrSize");
50   ::SysFreeString(bstr_);
51 }
52 
Reset(BSTR bstr)53 void ScopedBstr::Reset(BSTR bstr) {
54   if (bstr != bstr_) {
55     // SysFreeString handles null properly.
56     ::SysFreeString(bstr_);
57     bstr_ = bstr;
58   }
59 }
60 
Release()61 BSTR ScopedBstr::Release() {
62   BSTR bstr = bstr_;
63   bstr_ = nullptr;
64   return bstr;
65 }
66 
Swap(ScopedBstr & bstr2)67 void ScopedBstr::Swap(ScopedBstr& bstr2) {
68   BSTR tmp = bstr_;
69   bstr_ = bstr2.bstr_;
70   bstr2.bstr_ = tmp;
71 }
72 
Receive()73 BSTR* ScopedBstr::Receive() {
74   DCHECK(!bstr_) << "BSTR leak.";
75   return &bstr_;
76 }
77 
Allocate(std::wstring_view str)78 BSTR ScopedBstr::Allocate(std::wstring_view str) {
79   Reset(AllocBstrOrDie(str));
80   return bstr_;
81 }
82 
AllocateBytes(size_t bytes)83 BSTR ScopedBstr::AllocateBytes(size_t bytes) {
84   Reset(AllocBstrBytesOrDie(bytes));
85   return bstr_;
86 }
87 
SetByteLen(size_t bytes)88 void ScopedBstr::SetByteLen(size_t bytes) {
89   DCHECK(bstr_);
90   uint32_t* data = reinterpret_cast<uint32_t*>(bstr_);
91   data[-1] = checked_cast<uint32_t>(bytes);
92 }
93 
Length() const94 size_t ScopedBstr::Length() const {
95   return ::SysStringLen(bstr_);
96 }
97 
ByteLength() const98 size_t ScopedBstr::ByteLength() const {
99   return ::SysStringByteLen(bstr_);
100 }
101 
102 }  // namespace win
103 }  // namespace base
104