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 WorkerBSTR 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 WorkerBSTR 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 WorkerScopedBstr::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 WorkerScopedBstr::~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 Workervoid 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 WorkerBSTR 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 Workervoid 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 WorkerBSTR* 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 WorkerBSTR 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 WorkerBSTR 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 Workervoid 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 Workersize_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 Workersize_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