xref: /aosp_15_r20/external/cronet/base/win/scoped_bstr.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2010 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_bstr.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <string_view>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/process/memory.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace base {
17*6777b538SAndroid Build Coastguard Worker namespace win {
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace {
20*6777b538SAndroid Build Coastguard Worker 
AllocBstrOrDie(std::wstring_view non_bstr)21*6777b538SAndroid Build Coastguard Worker BSTR AllocBstrOrDie(std::wstring_view non_bstr) {
22*6777b538SAndroid Build Coastguard Worker   BSTR result = ::SysAllocStringLen(non_bstr.data(),
23*6777b538SAndroid Build Coastguard Worker                                     checked_cast<UINT>(non_bstr.length()));
24*6777b538SAndroid Build Coastguard Worker   if (!result) {
25*6777b538SAndroid Build Coastguard Worker     base::TerminateBecauseOutOfMemory((non_bstr.length() + 1) *
26*6777b538SAndroid Build Coastguard Worker                                       sizeof(wchar_t));
27*6777b538SAndroid Build Coastguard Worker   }
28*6777b538SAndroid Build Coastguard Worker   return result;
29*6777b538SAndroid Build Coastguard Worker }
30*6777b538SAndroid Build Coastguard Worker 
AllocBstrBytesOrDie(size_t bytes)31*6777b538SAndroid Build Coastguard Worker BSTR AllocBstrBytesOrDie(size_t bytes) {
32*6777b538SAndroid Build Coastguard Worker   BSTR result = ::SysAllocStringByteLen(nullptr, checked_cast<UINT>(bytes));
33*6777b538SAndroid Build Coastguard Worker   if (!result)
34*6777b538SAndroid Build Coastguard Worker     base::TerminateBecauseOutOfMemory(bytes + sizeof(wchar_t));
35*6777b538SAndroid Build Coastguard Worker   return result;
36*6777b538SAndroid Build Coastguard Worker }
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker }  // namespace
39*6777b538SAndroid Build Coastguard Worker 
ScopedBstr(std::wstring_view non_bstr)40*6777b538SAndroid Build Coastguard Worker ScopedBstr::ScopedBstr(std::wstring_view non_bstr)
41*6777b538SAndroid Build Coastguard Worker     : bstr_(AllocBstrOrDie(non_bstr)) {}
42*6777b538SAndroid Build Coastguard Worker 
~ScopedBstr()43*6777b538SAndroid Build Coastguard Worker ScopedBstr::~ScopedBstr() {
44*6777b538SAndroid Build Coastguard Worker   static_assert(sizeof(ScopedBstr) == sizeof(BSTR), "ScopedBstrSize");
45*6777b538SAndroid Build Coastguard Worker   ::SysFreeString(bstr_);
46*6777b538SAndroid Build Coastguard Worker }
47*6777b538SAndroid Build Coastguard Worker 
Reset(BSTR bstr)48*6777b538SAndroid Build Coastguard Worker void ScopedBstr::Reset(BSTR bstr) {
49*6777b538SAndroid Build Coastguard Worker   if (bstr != bstr_) {
50*6777b538SAndroid Build Coastguard Worker     // SysFreeString handles null properly.
51*6777b538SAndroid Build Coastguard Worker     ::SysFreeString(bstr_);
52*6777b538SAndroid Build Coastguard Worker     bstr_ = bstr;
53*6777b538SAndroid Build Coastguard Worker   }
54*6777b538SAndroid Build Coastguard Worker }
55*6777b538SAndroid Build Coastguard Worker 
Release()56*6777b538SAndroid Build Coastguard Worker BSTR ScopedBstr::Release() {
57*6777b538SAndroid Build Coastguard Worker   BSTR bstr = bstr_;
58*6777b538SAndroid Build Coastguard Worker   bstr_ = nullptr;
59*6777b538SAndroid Build Coastguard Worker   return bstr;
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker 
Swap(ScopedBstr & bstr2)62*6777b538SAndroid Build Coastguard Worker void ScopedBstr::Swap(ScopedBstr& bstr2) {
63*6777b538SAndroid Build Coastguard Worker   BSTR tmp = bstr_;
64*6777b538SAndroid Build Coastguard Worker   bstr_ = bstr2.bstr_;
65*6777b538SAndroid Build Coastguard Worker   bstr2.bstr_ = tmp;
66*6777b538SAndroid Build Coastguard Worker }
67*6777b538SAndroid Build Coastguard Worker 
Receive()68*6777b538SAndroid Build Coastguard Worker BSTR* ScopedBstr::Receive() {
69*6777b538SAndroid Build Coastguard Worker   DCHECK(!bstr_) << "BSTR leak.";
70*6777b538SAndroid Build Coastguard Worker   return &bstr_;
71*6777b538SAndroid Build Coastguard Worker }
72*6777b538SAndroid Build Coastguard Worker 
Allocate(std::wstring_view str)73*6777b538SAndroid Build Coastguard Worker BSTR ScopedBstr::Allocate(std::wstring_view str) {
74*6777b538SAndroid Build Coastguard Worker   Reset(AllocBstrOrDie(str));
75*6777b538SAndroid Build Coastguard Worker   return bstr_;
76*6777b538SAndroid Build Coastguard Worker }
77*6777b538SAndroid Build Coastguard Worker 
AllocateBytes(size_t bytes)78*6777b538SAndroid Build Coastguard Worker BSTR ScopedBstr::AllocateBytes(size_t bytes) {
79*6777b538SAndroid Build Coastguard Worker   Reset(AllocBstrBytesOrDie(bytes));
80*6777b538SAndroid Build Coastguard Worker   return bstr_;
81*6777b538SAndroid Build Coastguard Worker }
82*6777b538SAndroid Build Coastguard Worker 
SetByteLen(size_t bytes)83*6777b538SAndroid Build Coastguard Worker void ScopedBstr::SetByteLen(size_t bytes) {
84*6777b538SAndroid Build Coastguard Worker   DCHECK(bstr_);
85*6777b538SAndroid Build Coastguard Worker   uint32_t* data = reinterpret_cast<uint32_t*>(bstr_);
86*6777b538SAndroid Build Coastguard Worker   data[-1] = checked_cast<uint32_t>(bytes);
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker 
Length() const89*6777b538SAndroid Build Coastguard Worker size_t ScopedBstr::Length() const {
90*6777b538SAndroid Build Coastguard Worker   return ::SysStringLen(bstr_);
91*6777b538SAndroid Build Coastguard Worker }
92*6777b538SAndroid Build Coastguard Worker 
ByteLength() const93*6777b538SAndroid Build Coastguard Worker size_t ScopedBstr::ByteLength() const {
94*6777b538SAndroid Build Coastguard Worker   return ::SysStringByteLen(bstr_);
95*6777b538SAndroid Build Coastguard Worker }
96*6777b538SAndroid Build Coastguard Worker 
97*6777b538SAndroid Build Coastguard Worker }  // namespace win
98*6777b538SAndroid Build Coastguard Worker }  // namespace base
99