1 // Copyright 2006 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h> // Must come first
31 #endif
32
33 #include <cassert>
34 #include <vector>
35
36 #include "common/windows/string_utils-inl.h"
37
38 namespace google_breakpad {
39
40 // static
GetBaseName(const wstring & filename)41 wstring WindowsStringUtils::GetBaseName(const wstring& filename) {
42 wstring base_name(filename);
43 size_t slash_pos = base_name.find_last_of(L"/\\");
44 if (slash_pos != wstring::npos) {
45 base_name.erase(0, slash_pos + 1);
46 }
47 return base_name;
48 }
49
50 // static
safe_mbstowcs(const string & mbs,wstring * wcs)51 bool WindowsStringUtils::safe_mbstowcs(const string& mbs, wstring* wcs) {
52 assert(wcs);
53
54 // First, determine the length of the destination buffer.
55 size_t wcs_length;
56
57 #if _MSC_VER >= 1400 // MSVC 2005/8
58 errno_t err;
59 if ((err = mbstowcs_s(&wcs_length, NULL, 0, mbs.c_str(), _TRUNCATE)) != 0) {
60 return false;
61 }
62 assert(wcs_length > 0);
63 #else // _MSC_VER >= 1400
64 if ((wcs_length = mbstowcs(NULL, mbs.c_str(), mbs.length())) == (size_t)-1) {
65 return false;
66 }
67
68 // Leave space for the 0-terminator.
69 ++wcs_length;
70 #endif // _MSC_VER >= 1400
71
72 std::vector<wchar_t> wcs_v(wcs_length);
73
74 // Now, convert.
75 #if _MSC_VER >= 1400 // MSVC 2005/8
76 if ((err = mbstowcs_s(NULL, &wcs_v[0], wcs_length, mbs.c_str(),
77 _TRUNCATE)) != 0) {
78 return false;
79 }
80 #else // _MSC_VER >= 1400
81 if (mbstowcs(&wcs_v[0], mbs.c_str(), mbs.length()) == (size_t)-1) {
82 return false;
83 }
84
85 // Ensure presence of 0-terminator.
86 wcs_v[wcs_length - 1] = '\0';
87 #endif // _MSC_VER >= 1400
88
89 *wcs = &wcs_v[0];
90 return true;
91 }
92
93 // static
safe_wcstombs(const wstring & wcs,string * mbs)94 bool WindowsStringUtils::safe_wcstombs(const wstring& wcs, string* mbs) {
95 assert(mbs);
96
97 // First, determine the length of the destination buffer.
98 size_t mbs_length;
99
100 #if _MSC_VER >= 1400 // MSVC 2005/8
101 errno_t err;
102 if ((err = wcstombs_s(&mbs_length, NULL, 0, wcs.c_str(), _TRUNCATE)) != 0) {
103 return false;
104 }
105 assert(mbs_length > 0);
106 #else // _MSC_VER >= 1400
107 if ((mbs_length = wcstombs(NULL, wcs.c_str(), wcs.length())) == (size_t)-1) {
108 return false;
109 }
110
111 // Leave space for the 0-terminator.
112 ++mbs_length;
113 #endif // _MSC_VER >= 1400
114
115 std::vector<char> mbs_v(mbs_length);
116
117 // Now, convert.
118 #if _MSC_VER >= 1400 // MSVC 2005/8
119 if ((err = wcstombs_s(NULL, &mbs_v[0], mbs_length, wcs.c_str(),
120 _TRUNCATE)) != 0) {
121 return false;
122 }
123 #else // _MSC_VER >= 1400
124 if (wcstombs(&mbs_v[0], wcs.c_str(), wcs.length()) == (size_t)-1) {
125 return false;
126 }
127
128 // Ensure presence of 0-terminator.
129 mbs_v[mbs_length - 1] = '\0';
130 #endif // _MSC_VER >= 1400
131
132 *mbs = &mbs_v[0];
133 return true;
134 }
135
136 } // namespace google_breakpad
137