| OLD | NEW |
| (Empty) |
| 1 // Copyright 2010 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 // ======================================================================== | |
| 15 | |
| 16 #include <algorithm> | |
| 17 #include "omaha/base/debug.h" | |
| 18 #include "omaha/base/safe_format.h" | |
| 19 | |
| 20 namespace omaha { | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 // Define a templated wrapper for StringCchVPrintf_() that will call the | |
| 25 // appropriate W/A version based on template parameter. | |
| 26 template <typename CharType> | |
| 27 HRESULT InternalStringCchVPrintf(CharType* dest_buffer, | |
| 28 size_t dest_size, | |
| 29 const CharType* format_str, | |
| 30 va_list arg_list); | |
| 31 | |
| 32 template <> | |
| 33 HRESULT InternalStringCchVPrintf<char>(char* dest_buffer, | |
| 34 size_t dest_size, | |
| 35 const char* format_str, | |
| 36 va_list arg_list) { | |
| 37 return ::StringCchVPrintfA(dest_buffer, dest_size, format_str, arg_list); | |
| 38 } | |
| 39 | |
| 40 template <> | |
| 41 HRESULT InternalStringCchVPrintf<wchar_t>(wchar_t* dest_buffer, | |
| 42 size_t dest_size, | |
| 43 const wchar_t* format_str, | |
| 44 va_list arg_list) { | |
| 45 return ::StringCchVPrintfW(dest_buffer, dest_size, format_str, arg_list); | |
| 46 } | |
| 47 | |
| 48 // Define a templated wrapper for strlen() that will call the appropriate | |
| 49 // W/A version based on template parameter. | |
| 50 template <typename CharType> | |
| 51 size_t InternalStrlen(const CharType* str); | |
| 52 | |
| 53 template <> | |
| 54 size_t InternalStrlen<char>(const char* str) { | |
| 55 return ::strlen(str); | |
| 56 } | |
| 57 | |
| 58 template <> | |
| 59 size_t InternalStrlen<wchar_t>(const wchar_t* str) { | |
| 60 return ::wcslen(str); | |
| 61 } | |
| 62 | |
| 63 // InternalCStringVPrintf() wraps InternalStringCchVPrintf() to accept a | |
| 64 // CStringT as the output parameter and resize it until the latter succeeds | |
| 65 // or we hit the StrSafe.h limit. | |
| 66 template <typename CharType, typename CharTraits> | |
| 67 HRESULT InternalCStringVPrintf( | |
| 68 ATL::CStringT<CharType, CharTraits>& dest_str, | |
| 69 const CharType* format_str, | |
| 70 va_list arg_list) { | |
| 71 size_t buf_length = std::max(InternalStrlen(format_str), | |
| 72 static_cast<size_t>(256)); | |
| 73 | |
| 74 for (;;) { | |
| 75 CStrBufT<CharType> str_buf(dest_str, buf_length); | |
| 76 HRESULT hr = InternalStringCchVPrintf(static_cast<CharType*>(str_buf), | |
| 77 buf_length - 1, | |
| 78 format_str, | |
| 79 arg_list); | |
| 80 if (hr != STRSAFE_E_INSUFFICIENT_BUFFER) { | |
| 81 return hr; | |
| 82 } | |
| 83 if (buf_length >= STRSAFE_MAX_CCH) { | |
| 84 return STRSAFE_E_INVALID_PARAMETER; | |
| 85 } | |
| 86 buf_length = std::min(buf_length * 2, static_cast<size_t>(STRSAFE_MAX_CCH)); | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 // InternalCStringVPrintf() will have an overflow bug if STRSAFE_MAX_CCH ever | |
| 91 // becomes larger than MAX_SIZE_T / 2. Ensure at compile time that this is so. | |
| 92 COMPILE_ASSERT(STRSAFE_MAX_CCH <= SIZE_MAX / 2, strsafe_limit_has_changed); | |
| 93 | |
| 94 } // namespace | |
| 95 | |
| 96 // Define the non-templated API calls. | |
| 97 | |
| 98 void SafeCStringWFormatV(CStringW* dest_str, | |
| 99 LPCWSTR format_str, | |
| 100 va_list arg_list) { | |
| 101 ASSERT1(dest_str); | |
| 102 ASSERT1(format_str); | |
| 103 VERIFY1(SUCCEEDED(InternalCStringVPrintf(*dest_str, format_str, arg_list))); | |
| 104 } | |
| 105 | |
| 106 void SafeCStringAFormatV(CStringA* dest_str, | |
| 107 LPCSTR format_str, | |
| 108 va_list arg_list) { | |
| 109 ASSERT1(dest_str); | |
| 110 ASSERT1(format_str); | |
| 111 VERIFY1(SUCCEEDED(InternalCStringVPrintf(*dest_str, format_str, arg_list))); | |
| 112 } | |
| 113 | |
| 114 void SafeCStringWFormat(CStringW* dest_str, LPCWSTR format_str, ...) { | |
| 115 ASSERT1(dest_str); | |
| 116 ASSERT1(format_str); | |
| 117 | |
| 118 va_list arg_list; | |
| 119 va_start(arg_list, format_str); | |
| 120 VERIFY1(SUCCEEDED(InternalCStringVPrintf(*dest_str, format_str, arg_list))); | |
| 121 va_end(arg_list); | |
| 122 } | |
| 123 | |
| 124 void SafeCStringAFormat(CStringA* dest_str, LPCSTR format_str, ...) { | |
| 125 ASSERT1(dest_str); | |
| 126 ASSERT1(format_str); | |
| 127 | |
| 128 va_list arg_list; | |
| 129 va_start(arg_list, format_str); | |
| 130 VERIFY1(SUCCEEDED(InternalCStringVPrintf(*dest_str, format_str, arg_list))); | |
| 131 va_end(arg_list); | |
| 132 } | |
| 133 | |
| 134 void SafeCStringWAppendFormat(CStringW* dest_str, LPCWSTR format_str, ...) { | |
| 135 ASSERT1(dest_str); | |
| 136 ASSERT1(format_str); | |
| 137 | |
| 138 va_list arg_list; | |
| 139 va_start(arg_list, format_str); | |
| 140 | |
| 141 CStringW append_str; | |
| 142 VERIFY1(SUCCEEDED(InternalCStringVPrintf(append_str, format_str, arg_list))); | |
| 143 dest_str->Append(append_str); | |
| 144 | |
| 145 va_end(arg_list); | |
| 146 } | |
| 147 | |
| 148 void SafeCStringAAppendFormat(CStringA* dest_str, LPCSTR format_str, ...) { | |
| 149 ASSERT1(dest_str); | |
| 150 ASSERT1(format_str); | |
| 151 | |
| 152 va_list arg_list; | |
| 153 va_start(arg_list, format_str); | |
| 154 | |
| 155 CStringA append_str; | |
| 156 VERIFY1(SUCCEEDED(InternalCStringVPrintf(append_str, format_str, arg_list))); | |
| 157 dest_str->Append(append_str); | |
| 158 | |
| 159 va_end(arg_list); | |
| 160 } | |
| 161 | |
| 162 } // namespace omaha | |
| 163 | |
| OLD | NEW |