1// Copyright (c) 2006, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30// string_utils-inl.h: Safer string manipulation on Windows, supporting
31// pre-MSVC8 environments.
32
33#ifndef COMMON_WINDOWS_STRING_UTILS_INL_H_
34#define COMMON_WINDOWS_STRING_UTILS_INL_H_
35
36#include <stdarg.h>
37#include <wchar.h>
38
39#include <string>
40
41// The "ll" printf format size specifier corresponding to |long long| was
42// intrudced in MSVC8.  Earlier versions did not provide this size specifier,
43// but "I64" can be used to print 64-bit types.  Don't use "I64" where "ll"
44// is available, in the event of oddball systems where |long long| is not
45// 64 bits wide.
46#if _MSC_VER >= 1400  // MSVC 2005/8
47#define WIN_STRING_FORMAT_LL "ll"
48#else  // MSC_VER >= 1400
49#define WIN_STRING_FORMAT_LL "I64"
50#endif  // MSC_VER >= 1400
51
52// A nonconforming version of swprintf, without the length argument, was
53// included with the CRT prior to MSVC8.  Although a conforming version was
54// also available via an overload, it is not reliably chosen.  _snwprintf
55// behaves as a standards-confirming swprintf should, so force the use of
56// _snwprintf when using older CRTs.
57#if _MSC_VER < 1400  // MSVC 2005/8
58#define swprintf _snwprintf
59#else
60// For MSVC8 and newer, swprintf_s is the recommended method. Conveniently,
61// it takes the same argument list as swprintf.
62#define swprintf swprintf_s
63#endif  // MSC_VER < 1400
64
65namespace google_breakpad {
66
67using std::string;
68using std::wstring;
69
70class WindowsStringUtils {
71 public:
72  // Roughly equivalent to MSVC8's wcscpy_s, except pre-MSVC8, this does
73  // not fail if source is longer than destination_size.  The destination
74  // buffer is always 0-terminated.
75  static void safe_wcscpy(wchar_t *destination, size_t destination_size,
76                          const wchar_t *source);
77
78  // Roughly equivalent to MSVC8's wcsncpy_s, except that _TRUNCATE cannot
79  // be passed directly, and pre-MSVC8, this will not fail if source or count
80  // are longer than destination_size.  The destination buffer is always
81  // 0-terminated.
82  static void safe_wcsncpy(wchar_t *destination, size_t destination_size,
83                           const wchar_t *source, size_t count);
84
85  // Performs multi-byte to wide character conversion on C++ strings, using
86  // mbstowcs_s (MSVC8) or mbstowcs (pre-MSVC8).  Returns false on failure,
87  // without setting wcs.
88  static bool safe_mbstowcs(const string &mbs, wstring *wcs);
89
90  // The inverse of safe_mbstowcs.
91  static bool safe_wcstombs(const wstring &wcs, string *mbs);
92
93  // Returns the base name of a file, e.g. strips off the path.
94  static wstring GetBaseName(const wstring &filename);
95
96 private:
97  // Disallow instantiation and other object-based operations.
98  WindowsStringUtils();
99  WindowsStringUtils(const WindowsStringUtils&);
100  ~WindowsStringUtils();
101  void operator=(const WindowsStringUtils&);
102};
103
104// static
105inline void WindowsStringUtils::safe_wcscpy(wchar_t *destination,
106                                            size_t destination_size,
107                                            const wchar_t *source) {
108#if _MSC_VER >= 1400  // MSVC 2005/8
109  wcscpy_s(destination, destination_size, source);
110#else  // _MSC_VER >= 1400
111  // Pre-MSVC 2005/8 doesn't have wcscpy_s.  Simulate it with wcsncpy.
112  // wcsncpy doesn't 0-terminate the destination buffer if the source string
113  // is longer than size.  Ensure that the destination is 0-terminated.
114  wcsncpy(destination, source, destination_size);
115  if (destination && destination_size)
116    destination[destination_size - 1] = 0;
117#endif  // _MSC_VER >= 1400
118}
119
120// static
121inline void WindowsStringUtils::safe_wcsncpy(wchar_t *destination,
122                                             size_t destination_size,
123                                             const wchar_t *source,
124                                             size_t count) {
125#if _MSC_VER >= 1400  // MSVC 2005/8
126  wcsncpy_s(destination, destination_size, source, count);
127#else  // _MSC_VER >= 1400
128  // Pre-MSVC 2005/8 doesn't have wcsncpy_s.  Simulate it with wcsncpy.
129  // wcsncpy doesn't 0-terminate the destination buffer if the source string
130  // is longer than size.  Ensure that the destination is 0-terminated.
131  if (destination_size < count)
132    count = destination_size;
133
134  wcsncpy(destination, source, count);
135  if (destination && count)
136    destination[count - 1] = 0;
137#endif  // _MSC_VER >= 1400
138}
139
140}  // namespace google_breakpad
141
142#endif  // COMMON_WINDOWS_STRING_UTILS_INL_H_
143