Mercurial > mm7
comparison lib/legacy_dx/strsafe.h @ 0:9c0607679772
init
author | Ritor1 |
---|---|
date | Sat, 12 Jan 2013 09:45:18 +0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:9c0607679772 |
---|---|
1 /****************************************************************** | |
2 * * | |
3 * strsafe.h -- This module defines safer C library string * | |
4 * routine replacements. These are meant to make C * | |
5 * a bit more safe in reference to security and * | |
6 * robustness * | |
7 * * | |
8 * Copyright (c) Microsoft Corp. All rights reserved. * | |
9 * * | |
10 ******************************************************************/ | |
11 #ifndef _STRSAFE_H_INCLUDED_ | |
12 #define _STRSAFE_H_INCLUDED_ | |
13 #pragma once | |
14 | |
15 #include <stdio.h> // for _vsnprintf, _vsnwprintf, getc, getwc | |
16 #include <string.h> // for memset | |
17 #include <stdarg.h> // for va_start, etc. | |
18 | |
19 | |
20 #ifndef _SIZE_T_DEFINED | |
21 #ifdef _WIN64 | |
22 typedef unsigned __int64 size_t; | |
23 #else | |
24 typedef __w64 unsigned int size_t; | |
25 #endif // !_WIN64 | |
26 #define _SIZE_T_DEFINED | |
27 #endif // !_SIZE_T_DEFINED | |
28 | |
29 #if !defined(_WCHAR_T_DEFINED) && !defined(_NATIVE_WCHAR_T_DEFINED) | |
30 typedef unsigned short wchar_t; | |
31 #define _WCHAR_T_DEFINED | |
32 #endif | |
33 | |
34 #ifndef _HRESULT_DEFINED | |
35 #define _HRESULT_DEFINED | |
36 typedef long HRESULT; | |
37 #endif // !_HRESULT_DEFINED | |
38 | |
39 #ifndef SUCCEEDED | |
40 #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) | |
41 #endif | |
42 | |
43 #ifndef FAILED | |
44 #define FAILED(hr) ((HRESULT)(hr) < 0) | |
45 #endif | |
46 | |
47 #ifndef S_OK | |
48 #define S_OK ((HRESULT)0x00000000L) | |
49 #endif | |
50 | |
51 #ifdef __cplusplus | |
52 #define _STRSAFE_EXTERN_C extern "C" | |
53 #else | |
54 #define _STRSAFE_EXTERN_C extern | |
55 #endif | |
56 | |
57 // If you do not want to use these functions inline (and instead want to link w/ strsafe.lib), then | |
58 // #define STRSAFE_LIB before including this header file. | |
59 #if defined(STRSAFE_LIB) | |
60 #define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall | |
61 #pragma comment(lib, "strsafe.lib") | |
62 #elif defined(STRSAFE_LIB_IMPL) | |
63 #define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall | |
64 #else | |
65 #define STRSAFEAPI __inline HRESULT __stdcall | |
66 #define STRSAFE_INLINE | |
67 #endif | |
68 | |
69 // Some functions always run inline because they use stdin and we want to avoid building multiple | |
70 // versions of strsafe lib depending on if you use msvcrt, libcmt, etc. | |
71 #define STRSAFE_INLINE_API __inline HRESULT __stdcall | |
72 | |
73 // The user can request no "Cb" or no "Cch" fuctions, but not both! | |
74 #if defined(STRSAFE_NO_CB_FUNCTIONS) && defined(STRSAFE_NO_CCH_FUNCTIONS) | |
75 #error cannot specify both STRSAFE_NO_CB_FUNCTIONS and STRSAFE_NO_CCH_FUNCTIONS !! | |
76 #endif | |
77 | |
78 // This should only be defined when we are building strsafe.lib | |
79 #ifdef STRSAFE_LIB_IMPL | |
80 #define STRSAFE_INLINE | |
81 #endif | |
82 | |
83 | |
84 // If both strsafe.h and ntstrsafe.h are included, only use definitions from one. | |
85 #ifndef _NTSTRSAFE_H_INCLUDED_ | |
86 | |
87 #define STRSAFE_MAX_CCH 2147483647 // max # of characters we support (same as INT_MAX) | |
88 | |
89 // Flags for controling the Ex functions | |
90 // | |
91 // STRSAFE_FILL_BYTE(0xFF) 0x000000FF // bottom byte specifies fill pattern | |
92 #define STRSAFE_IGNORE_NULLS 0x00000100 // treat null as TEXT("") -- don't fault on NULL buffers | |
93 #define STRSAFE_FILL_BEHIND_NULL 0x00000200 // fill in extra space behind the null terminator | |
94 #define STRSAFE_FILL_ON_FAILURE 0x00000400 // on failure, overwrite pszDest with fill pattern and null terminate it | |
95 #define STRSAFE_NULL_ON_FAILURE 0x00000800 // on failure, set *pszDest = TEXT('\0') | |
96 #define STRSAFE_NO_TRUNCATION 0x00001000 // instead of returning a truncated result, copy/append nothing to pszDest and null terminate it | |
97 | |
98 #define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION) | |
99 | |
100 // helper macro to set the fill character and specify buffer filling | |
101 #define STRSAFE_FILL_BYTE(x) ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_BEHIND_NULL)) | |
102 #define STRSAFE_FAILURE_BYTE(x) ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_ON_FAILURE)) | |
103 | |
104 #define STRSAFE_GET_FILL_PATTERN(dwFlags) ((int)(dwFlags & 0x000000FF)) | |
105 | |
106 #endif // _NTSTRSAFE_H_INCLUDED_ | |
107 | |
108 // STRSAFE error return codes | |
109 // | |
110 #define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER | |
111 #define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L) // 0x57 = 87L = ERROR_INVALID_PARAMETER | |
112 #define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L) // 0x26 = 38L = ERROR_HANDLE_EOF | |
113 | |
114 // prototypes for the worker functions | |
115 #ifdef STRSAFE_INLINE | |
116 STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc); | |
117 STRSAFEAPI StringCopyWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); | |
118 STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
119 STRSAFEAPI StringCopyExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
120 STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc); | |
121 STRSAFEAPI StringCopyNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc); | |
122 STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
123 STRSAFEAPI StringCopyNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
124 STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc); | |
125 STRSAFEAPI StringCatWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); | |
126 STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
127 STRSAFEAPI StringCatExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
128 STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend); | |
129 STRSAFEAPI StringCatNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend); | |
130 STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
131 STRSAFEAPI StringCatNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
132 STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList); | |
133 STRSAFEAPI StringVPrintfWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList); | |
134 STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); | |
135 STRSAFEAPI StringVPrintfExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList); | |
136 STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch); | |
137 STRSAFEAPI StringLengthWorkerW(const wchar_t* psz, size_t cchMax, size_t* pcch); | |
138 #endif // STRSAFE_INLINE | |
139 | |
140 #ifndef STRSAFE_LIB_IMPL | |
141 // these functions are always inline | |
142 STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
143 STRSAFE_INLINE_API StringGetsExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
144 #endif | |
145 | |
146 #ifdef _NTSTRSAFE_H_INCLUDED_ | |
147 #pragma warning(push) | |
148 #pragma warning(disable : 4995) | |
149 #endif // _NTSTRSAFE_H_INCLUDED_ | |
150 | |
151 | |
152 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
153 /*++ | |
154 | |
155 STDAPI | |
156 StringCchCopy( | |
157 OUT LPTSTR pszDest, | |
158 IN size_t cchDest, | |
159 IN LPCTSTR pszSrc | |
160 ); | |
161 | |
162 Routine Description: | |
163 | |
164 This routine is a safer version of the C built-in function 'strcpy'. | |
165 The size of the destination buffer (in characters) is a parameter and | |
166 this function will not write past the end of this buffer and it will | |
167 ALWAYS null terminate the destination buffer (unless it is zero length). | |
168 | |
169 This routine is not a replacement for strncpy. That function will pad the | |
170 destination string with extra null termination characters if the count is | |
171 greater than the length of the source string, and it will fail to null | |
172 terminate the destination string if the source string length is greater | |
173 than or equal to the count. You can not blindly use this instead of strncpy: | |
174 it is common for code to use it to "patch" strings and you would introduce | |
175 errors if the code started null terminating in the middle of the string. | |
176 | |
177 This function returns a hresult, and not a pointer. It returns | |
178 S_OK if the string was copied without truncation and null terminated, | |
179 otherwise it will return a failure code. In failure cases as much of | |
180 pszSrc will be copied to pszDest as possible, and pszDest will be null | |
181 terminated. | |
182 | |
183 Arguments: | |
184 | |
185 pszDest - destination string | |
186 | |
187 cchDest - size of destination buffer in characters. | |
188 length must be = (_tcslen(src) + 1) to hold all of the | |
189 source including the null terminator | |
190 | |
191 pszSrc - source string which must be null terminated | |
192 | |
193 Notes: | |
194 Behavior is undefined if source and destination strings overlap. | |
195 | |
196 pszDest and pszSrc should not be NULL. See StringCchCopyEx if you require | |
197 the handling of NULL values. | |
198 | |
199 Return Value: | |
200 | |
201 S_OK - if there was source data and it was all copied and the | |
202 resultant dest string was null terminated | |
203 | |
204 failure - you can use the macro HRESULT_CODE() to get a win32 | |
205 error code for all hresult failure cases | |
206 | |
207 STRSAFE_E_INSUFFICIENT_BUFFER / | |
208 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
209 - this return value is an indication that the copy | |
210 operation failed due to insufficient space. When this | |
211 error occurs, the destination buffer is modified to | |
212 contain a truncated version of the ideal result and is | |
213 null terminated. This is useful for situations where | |
214 truncation is ok | |
215 | |
216 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
217 return value of this function. | |
218 | |
219 --*/ | |
220 | |
221 STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc); | |
222 STRSAFEAPI StringCchCopyW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); | |
223 #ifdef UNICODE | |
224 #define StringCchCopy StringCchCopyW | |
225 #else | |
226 #define StringCchCopy StringCchCopyA | |
227 #endif // !UNICODE | |
228 | |
229 #ifdef STRSAFE_INLINE | |
230 STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc) | |
231 { | |
232 HRESULT hr; | |
233 | |
234 if (cchDest > STRSAFE_MAX_CCH) | |
235 { | |
236 hr = STRSAFE_E_INVALID_PARAMETER; | |
237 } | |
238 else | |
239 { | |
240 hr = StringCopyWorkerA(pszDest, cchDest, pszSrc); | |
241 } | |
242 | |
243 return hr; | |
244 } | |
245 | |
246 STRSAFEAPI StringCchCopyW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) | |
247 { | |
248 HRESULT hr; | |
249 | |
250 if (cchDest > STRSAFE_MAX_CCH) | |
251 { | |
252 hr = STRSAFE_E_INVALID_PARAMETER; | |
253 } | |
254 else | |
255 { | |
256 hr = StringCopyWorkerW(pszDest, cchDest, pszSrc); | |
257 } | |
258 | |
259 return hr; | |
260 } | |
261 #endif // STRSAFE_INLINE | |
262 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
263 | |
264 | |
265 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
266 /*++ | |
267 | |
268 STDAPI | |
269 StringCbCopy( | |
270 OUT LPTSTR pszDest, | |
271 IN size_t cbDest, | |
272 IN LPCTSTR pszSrc | |
273 ); | |
274 | |
275 Routine Description: | |
276 | |
277 This routine is a safer version of the C built-in function 'strcpy'. | |
278 The size of the destination buffer (in bytes) is a parameter and this | |
279 function will not write past the end of this buffer and it will ALWAYS | |
280 null terminate the destination buffer (unless it is zero length). | |
281 | |
282 This routine is not a replacement for strncpy. That function will pad the | |
283 destination string with extra null termination characters if the count is | |
284 greater than the length of the source string, and it will fail to null | |
285 terminate the destination string if the source string length is greater | |
286 than or equal to the count. You can not blindly use this instead of strncpy: | |
287 it is common for code to use it to "patch" strings and you would introduce | |
288 errors if the code started null terminating in the middle of the string. | |
289 | |
290 This function returns a hresult, and not a pointer. It returns | |
291 S_OK if the string was copied without truncation and null terminated, | |
292 otherwise it will return a failure code. In failure cases as much of pszSrc | |
293 will be copied to pszDest as possible, and pszDest will be null terminated. | |
294 | |
295 Arguments: | |
296 | |
297 pszDest - destination string | |
298 | |
299 cbDest - size of destination buffer in bytes. | |
300 length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to | |
301 hold all of the source including the null terminator | |
302 | |
303 pszSrc - source string which must be null terminated | |
304 | |
305 Notes: | |
306 Behavior is undefined if source and destination strings overlap. | |
307 | |
308 pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require | |
309 the handling of NULL values. | |
310 | |
311 Return Value: | |
312 | |
313 S_OK - if there was source data and it was all copied and the | |
314 resultant dest string was null terminated | |
315 | |
316 failure - you can use the macro HRESULT_CODE() to get a win32 | |
317 error code for all hresult failure cases | |
318 | |
319 STRSAFE_E_INSUFFICIENT_BUFFER / | |
320 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
321 - this return value is an indication that the copy | |
322 operation failed due to insufficient space. When this | |
323 error occurs, the destination buffer is modified to | |
324 contain a truncated version of the ideal result and is | |
325 null terminated. This is useful for situations where | |
326 truncation is ok | |
327 | |
328 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
329 return value of this function. | |
330 | |
331 --*/ | |
332 | |
333 STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc); | |
334 STRSAFEAPI StringCbCopyW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc); | |
335 #ifdef UNICODE | |
336 #define StringCbCopy StringCbCopyW | |
337 #else | |
338 #define StringCbCopy StringCbCopyA | |
339 #endif // !UNICODE | |
340 | |
341 #ifdef STRSAFE_INLINE | |
342 STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc) | |
343 { | |
344 HRESULT hr; | |
345 size_t cchDest; | |
346 | |
347 // convert to count of characters | |
348 cchDest = cbDest / sizeof(char); | |
349 | |
350 if (cchDest > STRSAFE_MAX_CCH) | |
351 { | |
352 hr = STRSAFE_E_INVALID_PARAMETER; | |
353 } | |
354 else | |
355 { | |
356 hr = StringCopyWorkerA(pszDest, cchDest, pszSrc); | |
357 } | |
358 | |
359 return hr; | |
360 } | |
361 | |
362 STRSAFEAPI StringCbCopyW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc) | |
363 { | |
364 HRESULT hr; | |
365 size_t cchDest; | |
366 | |
367 // convert to count of characters | |
368 cchDest = cbDest / sizeof(wchar_t); | |
369 | |
370 if (cchDest > STRSAFE_MAX_CCH) | |
371 { | |
372 hr = STRSAFE_E_INVALID_PARAMETER; | |
373 } | |
374 else | |
375 { | |
376 hr = StringCopyWorkerW(pszDest, cchDest, pszSrc); | |
377 } | |
378 | |
379 return hr; | |
380 } | |
381 #endif // STRSAFE_INLINE | |
382 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
383 | |
384 | |
385 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
386 /*++ | |
387 | |
388 STDAPI | |
389 StringCchCopyEx( | |
390 OUT LPTSTR pszDest OPTIONAL, | |
391 IN size_t cchDest, | |
392 IN LPCTSTR pszSrc OPTIONAL, | |
393 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
394 OUT size_t* pcchRemaining OPTIONAL, | |
395 IN DWORD dwFlags | |
396 ); | |
397 | |
398 Routine Description: | |
399 | |
400 This routine is a safer version of the C built-in function 'strcpy' with | |
401 some additional parameters. In addition to functionality provided by | |
402 StringCchCopy, this routine also returns a pointer to the end of the | |
403 destination string and the number of characters left in the destination string | |
404 including the null terminator. The flags parameter allows additional controls. | |
405 | |
406 Arguments: | |
407 | |
408 pszDest - destination string | |
409 | |
410 cchDest - size of destination buffer in characters. | |
411 length must be = (_tcslen(pszSrc) + 1) to hold all of | |
412 the source including the null terminator | |
413 | |
414 pszSrc - source string which must be null terminated | |
415 | |
416 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
417 pointer to the end of the destination string. If the | |
418 function copied any data, the result will point to the | |
419 null termination character | |
420 | |
421 pcchRemaining - if pcchRemaining is non-null, the function will return the | |
422 number of characters left in the destination string, | |
423 including the null terminator | |
424 | |
425 dwFlags - controls some details of the string copy: | |
426 | |
427 STRSAFE_FILL_BEHIND_NULL | |
428 if the function succeeds, the low byte of dwFlags will be | |
429 used to fill the uninitialize part of destination buffer | |
430 behind the null terminator | |
431 | |
432 STRSAFE_IGNORE_NULLS | |
433 treat NULL string pointers like empty strings (TEXT("")). | |
434 this flag is useful for emulating functions like lstrcpy | |
435 | |
436 STRSAFE_FILL_ON_FAILURE | |
437 if the function fails, the low byte of dwFlags will be | |
438 used to fill all of the destination buffer, and it will | |
439 be null terminated. This will overwrite any truncated | |
440 string returned when the failure is | |
441 STRSAFE_E_INSUFFICIENT_BUFFER | |
442 | |
443 STRSAFE_NO_TRUNCATION / | |
444 STRSAFE_NULL_ON_FAILURE | |
445 if the function fails, the destination buffer will be set | |
446 to the empty string. This will overwrite any truncated string | |
447 returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. | |
448 | |
449 Notes: | |
450 Behavior is undefined if source and destination strings overlap. | |
451 | |
452 pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag | |
453 is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc | |
454 may be NULL. An error may still be returned even though NULLS are ignored | |
455 due to insufficient space. | |
456 | |
457 Return Value: | |
458 | |
459 S_OK - if there was source data and it was all copied and the | |
460 resultant dest string was null terminated | |
461 | |
462 failure - you can use the macro HRESULT_CODE() to get a win32 | |
463 error code for all hresult failure cases | |
464 | |
465 STRSAFE_E_INSUFFICIENT_BUFFER / | |
466 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
467 - this return value is an indication that the copy | |
468 operation failed due to insufficient space. When this | |
469 error occurs, the destination buffer is modified to | |
470 contain a truncated version of the ideal result and is | |
471 null terminated. This is useful for situations where | |
472 truncation is ok. | |
473 | |
474 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
475 return value of this function | |
476 | |
477 --*/ | |
478 | |
479 STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
480 STRSAFEAPI StringCchCopyExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
481 #ifdef UNICODE | |
482 #define StringCchCopyEx StringCchCopyExW | |
483 #else | |
484 #define StringCchCopyEx StringCchCopyExA | |
485 #endif // !UNICODE | |
486 | |
487 #ifdef STRSAFE_INLINE | |
488 STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
489 { | |
490 HRESULT hr; | |
491 | |
492 if (cchDest > STRSAFE_MAX_CCH) | |
493 { | |
494 hr = STRSAFE_E_INVALID_PARAMETER; | |
495 } | |
496 else | |
497 { | |
498 size_t cbDest; | |
499 | |
500 // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
501 cbDest = cchDest * sizeof(char); | |
502 | |
503 hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); | |
504 } | |
505 | |
506 return hr; | |
507 } | |
508 | |
509 STRSAFEAPI StringCchCopyExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
510 { | |
511 HRESULT hr; | |
512 | |
513 if (cchDest > STRSAFE_MAX_CCH) | |
514 { | |
515 hr = STRSAFE_E_INVALID_PARAMETER; | |
516 } | |
517 else | |
518 { | |
519 size_t cbDest; | |
520 | |
521 // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
522 cbDest = cchDest * sizeof(wchar_t); | |
523 | |
524 hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); | |
525 } | |
526 | |
527 return hr; | |
528 } | |
529 #endif // STRSAFE_INLINE | |
530 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
531 | |
532 | |
533 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
534 /*++ | |
535 | |
536 STDAPI | |
537 StringCbCopyEx( | |
538 OUT LPTSTR pszDest OPTIONAL, | |
539 IN size_t cbDest, | |
540 IN LPCTSTR pszSrc OPTIONAL, | |
541 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
542 OUT size_t* pcbRemaining OPTIONAL, | |
543 IN DWORD dwFlags | |
544 ); | |
545 | |
546 Routine Description: | |
547 | |
548 This routine is a safer version of the C built-in function 'strcpy' with | |
549 some additional parameters. In addition to functionality provided by | |
550 StringCbCopy, this routine also returns a pointer to the end of the | |
551 destination string and the number of bytes left in the destination string | |
552 including the null terminator. The flags parameter allows additional controls. | |
553 | |
554 Arguments: | |
555 | |
556 pszDest - destination string | |
557 | |
558 cbDest - size of destination buffer in bytes. | |
559 length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to | |
560 hold all of the source including the null terminator | |
561 | |
562 pszSrc - source string which must be null terminated | |
563 | |
564 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
565 pointer to the end of the destination string. If the | |
566 function copied any data, the result will point to the | |
567 null termination character | |
568 | |
569 pcbRemaining - pcbRemaining is non-null,the function will return the | |
570 number of bytes left in the destination string, | |
571 including the null terminator | |
572 | |
573 dwFlags - controls some details of the string copy: | |
574 | |
575 STRSAFE_FILL_BEHIND_NULL | |
576 if the function succeeds, the low byte of dwFlags will be | |
577 used to fill the uninitialize part of destination buffer | |
578 behind the null terminator | |
579 | |
580 STRSAFE_IGNORE_NULLS | |
581 treat NULL string pointers like empty strings (TEXT("")). | |
582 this flag is useful for emulating functions like lstrcpy | |
583 | |
584 STRSAFE_FILL_ON_FAILURE | |
585 if the function fails, the low byte of dwFlags will be | |
586 used to fill all of the destination buffer, and it will | |
587 be null terminated. This will overwrite any truncated | |
588 string returned when the failure is | |
589 STRSAFE_E_INSUFFICIENT_BUFFER | |
590 | |
591 STRSAFE_NO_TRUNCATION / | |
592 STRSAFE_NULL_ON_FAILURE | |
593 if the function fails, the destination buffer will be set | |
594 to the empty string. This will overwrite any truncated string | |
595 returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. | |
596 | |
597 Notes: | |
598 Behavior is undefined if source and destination strings overlap. | |
599 | |
600 pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag | |
601 is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc | |
602 may be NULL. An error may still be returned even though NULLS are ignored | |
603 due to insufficient space. | |
604 | |
605 Return Value: | |
606 | |
607 S_OK - if there was source data and it was all copied and the | |
608 resultant dest string was null terminated | |
609 | |
610 failure - you can use the macro HRESULT_CODE() to get a win32 | |
611 error code for all hresult failure cases | |
612 | |
613 STRSAFE_E_INSUFFICIENT_BUFFER / | |
614 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
615 - this return value is an indication that the copy | |
616 operation failed due to insufficient space. When this | |
617 error occurs, the destination buffer is modified to | |
618 contain a truncated version of the ideal result and is | |
619 null terminated. This is useful for situations where | |
620 truncation is ok. | |
621 | |
622 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
623 return value of this function | |
624 | |
625 --*/ | |
626 | |
627 STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); | |
628 STRSAFEAPI StringCbCopyExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); | |
629 #ifdef UNICODE | |
630 #define StringCbCopyEx StringCbCopyExW | |
631 #else | |
632 #define StringCbCopyEx StringCbCopyExA | |
633 #endif // !UNICODE | |
634 | |
635 #ifdef STRSAFE_INLINE | |
636 STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) | |
637 { | |
638 HRESULT hr; | |
639 size_t cchDest; | |
640 size_t cchRemaining = 0; | |
641 | |
642 cchDest = cbDest / sizeof(char); | |
643 | |
644 if (cchDest > STRSAFE_MAX_CCH) | |
645 { | |
646 hr = STRSAFE_E_INVALID_PARAMETER; | |
647 } | |
648 else | |
649 { | |
650 hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags); | |
651 } | |
652 | |
653 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
654 { | |
655 if (pcbRemaining) | |
656 { | |
657 // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
658 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); | |
659 } | |
660 } | |
661 | |
662 return hr; | |
663 } | |
664 | |
665 STRSAFEAPI StringCbCopyExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) | |
666 { | |
667 HRESULT hr; | |
668 size_t cchDest; | |
669 size_t cchRemaining = 0; | |
670 | |
671 cchDest = cbDest / sizeof(wchar_t); | |
672 | |
673 if (cchDest > STRSAFE_MAX_CCH) | |
674 { | |
675 hr = STRSAFE_E_INVALID_PARAMETER; | |
676 } | |
677 else | |
678 { | |
679 hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags); | |
680 } | |
681 | |
682 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
683 { | |
684 if (pcbRemaining) | |
685 { | |
686 // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
687 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); | |
688 } | |
689 } | |
690 | |
691 return hr; | |
692 } | |
693 #endif // STRSAFE_INLINE | |
694 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
695 | |
696 | |
697 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
698 /*++ | |
699 | |
700 STDAPI | |
701 StringCchCopyN( | |
702 OUT LPTSTR pszDest, | |
703 IN size_t cchDest, | |
704 IN LPCTSTR pszSrc, | |
705 IN size_t cchSrc | |
706 ); | |
707 | |
708 Routine Description: | |
709 | |
710 This routine is a safer version of the C built-in function 'strncpy'. | |
711 The size of the destination buffer (in characters) is a parameter and | |
712 this function will not write past the end of this buffer and it will | |
713 ALWAYS null terminate the destination buffer (unless it is zero length). | |
714 | |
715 This routine is meant as a replacement for strncpy, but it does behave | |
716 differently. This function will not pad the destination buffer with extra | |
717 null termination characters if cchSrc is greater than the length of pszSrc. | |
718 | |
719 This function returns a hresult, and not a pointer. It returns | |
720 S_OK if the entire string or the first cchSrc characters were copied | |
721 without truncation and the resultant destination string was null terminated, | |
722 otherwise it will return a failure code. In failure cases as much of pszSrc | |
723 will be copied to pszDest as possible, and pszDest will be null terminated. | |
724 | |
725 Arguments: | |
726 | |
727 pszDest - destination string | |
728 | |
729 cchDest - size of destination buffer in characters. | |
730 length must be = (_tcslen(src) + 1) to hold all of the | |
731 source including the null terminator | |
732 | |
733 pszSrc - source string | |
734 | |
735 cchSrc - maximum number of characters to copy from source string, | |
736 not including the null terminator. | |
737 | |
738 Notes: | |
739 Behavior is undefined if source and destination strings overlap. | |
740 | |
741 pszDest and pszSrc should not be NULL. See StringCchCopyNEx if you require | |
742 the handling of NULL values. | |
743 | |
744 Return Value: | |
745 | |
746 S_OK - if there was source data and it was all copied and the | |
747 resultant dest string was null terminated | |
748 | |
749 failure - you can use the macro HRESULT_CODE() to get a win32 | |
750 error code for all hresult failure cases | |
751 | |
752 STRSAFE_E_INSUFFICIENT_BUFFER / | |
753 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
754 - this return value is an indication that the copy | |
755 operation failed due to insufficient space. When this | |
756 error occurs, the destination buffer is modified to | |
757 contain a truncated version of the ideal result and is | |
758 null terminated. This is useful for situations where | |
759 truncation is ok | |
760 | |
761 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
762 return value of this function. | |
763 | |
764 --*/ | |
765 | |
766 STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc); | |
767 STRSAFEAPI StringCchCopyNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc); | |
768 #ifdef UNICODE | |
769 #define StringCchCopyN StringCchCopyNW | |
770 #else | |
771 #define StringCchCopyN StringCchCopyNA | |
772 #endif // !UNICODE | |
773 | |
774 #ifdef STRSAFE_INLINE | |
775 STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc) | |
776 { | |
777 HRESULT hr; | |
778 | |
779 if ((cchDest > STRSAFE_MAX_CCH) || | |
780 (cchSrc > STRSAFE_MAX_CCH)) | |
781 { | |
782 hr = STRSAFE_E_INVALID_PARAMETER; | |
783 } | |
784 else | |
785 { | |
786 hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc); | |
787 } | |
788 | |
789 return hr; | |
790 } | |
791 | |
792 STRSAFEAPI StringCchCopyNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc) | |
793 { | |
794 HRESULT hr; | |
795 | |
796 if ((cchDest > STRSAFE_MAX_CCH) || | |
797 (cchSrc > STRSAFE_MAX_CCH)) | |
798 { | |
799 hr = STRSAFE_E_INVALID_PARAMETER; | |
800 } | |
801 else | |
802 { | |
803 hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc); | |
804 } | |
805 | |
806 return hr; | |
807 } | |
808 #endif // STRSAFE_INLINE | |
809 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
810 | |
811 | |
812 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
813 /*++ | |
814 | |
815 STDAPI | |
816 StringCbCopyN( | |
817 OUT LPTSTR pszDest, | |
818 IN size_t cbDest, | |
819 IN LPCTSTR pszSrc, | |
820 IN size_t cbSrc | |
821 ); | |
822 | |
823 Routine Description: | |
824 | |
825 This routine is a safer version of the C built-in function 'strncpy'. | |
826 The size of the destination buffer (in bytes) is a parameter and this | |
827 function will not write past the end of this buffer and it will ALWAYS | |
828 null terminate the destination buffer (unless it is zero length). | |
829 | |
830 This routine is meant as a replacement for strncpy, but it does behave | |
831 differently. This function will not pad the destination buffer with extra | |
832 null termination characters if cbSrc is greater than the size of pszSrc. | |
833 | |
834 This function returns a hresult, and not a pointer. It returns | |
835 S_OK if the entire string or the first cbSrc characters were | |
836 copied without truncation and the resultant destination string was null | |
837 terminated, otherwise it will return a failure code. In failure cases as | |
838 much of pszSrc will be copied to pszDest as possible, and pszDest will be | |
839 null terminated. | |
840 | |
841 Arguments: | |
842 | |
843 pszDest - destination string | |
844 | |
845 cbDest - size of destination buffer in bytes. | |
846 length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to | |
847 hold all of the source including the null terminator | |
848 | |
849 pszSrc - source string | |
850 | |
851 cbSrc - maximum number of bytes to copy from source string, | |
852 not including the null terminator. | |
853 | |
854 Notes: | |
855 Behavior is undefined if source and destination strings overlap. | |
856 | |
857 pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require | |
858 the handling of NULL values. | |
859 | |
860 Return Value: | |
861 | |
862 S_OK - if there was source data and it was all copied and the | |
863 resultant dest string was null terminated | |
864 | |
865 failure - you can use the macro HRESULT_CODE() to get a win32 | |
866 error code for all hresult failure cases | |
867 | |
868 STRSAFE_E_INSUFFICIENT_BUFFER / | |
869 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
870 - this return value is an indication that the copy | |
871 operation failed due to insufficient space. When this | |
872 error occurs, the destination buffer is modified to | |
873 contain a truncated version of the ideal result and is | |
874 null terminated. This is useful for situations where | |
875 truncation is ok | |
876 | |
877 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
878 return value of this function. | |
879 | |
880 --*/ | |
881 | |
882 STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc); | |
883 STRSAFEAPI StringCbCopyNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc); | |
884 #ifdef UNICODE | |
885 #define StringCbCopyN StringCbCopyNW | |
886 #else | |
887 #define StringCbCopyN StringCbCopyNA | |
888 #endif // !UNICODE | |
889 | |
890 #ifdef STRSAFE_INLINE | |
891 STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc) | |
892 { | |
893 HRESULT hr; | |
894 size_t cchDest; | |
895 size_t cchSrc; | |
896 | |
897 // convert to count of characters | |
898 cchDest = cbDest / sizeof(char); | |
899 cchSrc = cbSrc / sizeof(char); | |
900 | |
901 if ((cchDest > STRSAFE_MAX_CCH) || | |
902 (cchSrc > STRSAFE_MAX_CCH)) | |
903 { | |
904 hr = STRSAFE_E_INVALID_PARAMETER; | |
905 } | |
906 else | |
907 { | |
908 hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc); | |
909 } | |
910 | |
911 return hr; | |
912 } | |
913 | |
914 STRSAFEAPI StringCbCopyNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc) | |
915 { | |
916 HRESULT hr; | |
917 size_t cchDest; | |
918 size_t cchSrc; | |
919 | |
920 // convert to count of characters | |
921 cchDest = cbDest / sizeof(wchar_t); | |
922 cchSrc = cbSrc / sizeof(wchar_t); | |
923 | |
924 if ((cchDest > STRSAFE_MAX_CCH) || | |
925 (cchSrc > STRSAFE_MAX_CCH)) | |
926 { | |
927 hr = STRSAFE_E_INVALID_PARAMETER; | |
928 } | |
929 else | |
930 { | |
931 hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc); | |
932 } | |
933 | |
934 return hr; | |
935 } | |
936 #endif // STRSAFE_INLINE | |
937 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
938 | |
939 | |
940 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
941 /*++ | |
942 | |
943 STDAPI | |
944 StringCchCopyNEx( | |
945 OUT LPTSTR pszDest OPTIONAL, | |
946 IN size_t cchDest, | |
947 IN LPCTSTR pszSrc OPTIONAL, | |
948 IN size_t cchSrc, | |
949 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
950 OUT size_t* pcchRemaining OPTIONAL, | |
951 IN DWORD dwFlags | |
952 ); | |
953 | |
954 Routine Description: | |
955 | |
956 This routine is a safer version of the C built-in function 'strncpy' with | |
957 some additional parameters. In addition to functionality provided by | |
958 StringCchCopyN, this routine also returns a pointer to the end of the | |
959 destination string and the number of characters left in the destination | |
960 string including the null terminator. The flags parameter allows | |
961 additional controls. | |
962 | |
963 This routine is meant as a replacement for strncpy, but it does behave | |
964 differently. This function will not pad the destination buffer with extra | |
965 null termination characters if cchSrc is greater than the length of pszSrc. | |
966 | |
967 Arguments: | |
968 | |
969 pszDest - destination string | |
970 | |
971 cchDest - size of destination buffer in characters. | |
972 length must be = (_tcslen(pszSrc) + 1) to hold all of | |
973 the source including the null terminator | |
974 | |
975 pszSrc - source string | |
976 | |
977 cchSrc - maximum number of characters to copy from the source | |
978 string | |
979 | |
980 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
981 pointer to the end of the destination string. If the | |
982 function copied any data, the result will point to the | |
983 null termination character | |
984 | |
985 pcchRemaining - if pcchRemaining is non-null, the function will return the | |
986 number of characters left in the destination string, | |
987 including the null terminator | |
988 | |
989 dwFlags - controls some details of the string copy: | |
990 | |
991 STRSAFE_FILL_BEHIND_NULL | |
992 if the function succeeds, the low byte of dwFlags will be | |
993 used to fill the uninitialize part of destination buffer | |
994 behind the null terminator | |
995 | |
996 STRSAFE_IGNORE_NULLS | |
997 treat NULL string pointers like empty strings (TEXT("")). | |
998 this flag is useful for emulating functions like lstrcpy | |
999 | |
1000 STRSAFE_FILL_ON_FAILURE | |
1001 if the function fails, the low byte of dwFlags will be | |
1002 used to fill all of the destination buffer, and it will | |
1003 be null terminated. This will overwrite any truncated | |
1004 string returned when the failure is | |
1005 STRSAFE_E_INSUFFICIENT_BUFFER | |
1006 | |
1007 STRSAFE_NO_TRUNCATION / | |
1008 STRSAFE_NULL_ON_FAILURE | |
1009 if the function fails, the destination buffer will be set | |
1010 to the empty string. This will overwrite any truncated string | |
1011 returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. | |
1012 | |
1013 Notes: | |
1014 Behavior is undefined if source and destination strings overlap. | |
1015 | |
1016 pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag | |
1017 is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc | |
1018 may be NULL. An error may still be returned even though NULLS are ignored | |
1019 due to insufficient space. | |
1020 | |
1021 Return Value: | |
1022 | |
1023 S_OK - if there was source data and it was all copied and the | |
1024 resultant dest string was null terminated | |
1025 | |
1026 failure - you can use the macro HRESULT_CODE() to get a win32 | |
1027 error code for all hresult failure cases | |
1028 | |
1029 STRSAFE_E_INSUFFICIENT_BUFFER / | |
1030 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
1031 - this return value is an indication that the copy | |
1032 operation failed due to insufficient space. When this | |
1033 error occurs, the destination buffer is modified to | |
1034 contain a truncated version of the ideal result and is | |
1035 null terminated. This is useful for situations where | |
1036 truncation is ok. | |
1037 | |
1038 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
1039 return value of this function | |
1040 | |
1041 --*/ | |
1042 | |
1043 STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
1044 STRSAFEAPI StringCchCopyNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
1045 #ifdef UNICODE | |
1046 #define StringCchCopyNEx StringCchCopyNExW | |
1047 #else | |
1048 #define StringCchCopyNEx StringCchCopyNExA | |
1049 #endif // !UNICODE | |
1050 | |
1051 #ifdef STRSAFE_INLINE | |
1052 STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
1053 { | |
1054 HRESULT hr; | |
1055 | |
1056 if ((cchDest > STRSAFE_MAX_CCH) || | |
1057 (cchSrc > STRSAFE_MAX_CCH)) | |
1058 { | |
1059 hr = STRSAFE_E_INVALID_PARAMETER; | |
1060 } | |
1061 else | |
1062 { | |
1063 size_t cbDest; | |
1064 | |
1065 // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
1066 cbDest = cchDest * sizeof(char); | |
1067 | |
1068 hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags); | |
1069 } | |
1070 | |
1071 return hr; | |
1072 } | |
1073 | |
1074 STRSAFEAPI StringCchCopyNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
1075 { | |
1076 HRESULT hr; | |
1077 | |
1078 if ((cchDest > STRSAFE_MAX_CCH) || | |
1079 (cchSrc > STRSAFE_MAX_CCH)) | |
1080 { | |
1081 hr = STRSAFE_E_INVALID_PARAMETER; | |
1082 } | |
1083 else | |
1084 { | |
1085 size_t cbDest; | |
1086 | |
1087 // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
1088 cbDest = cchDest * sizeof(wchar_t); | |
1089 | |
1090 hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags); | |
1091 } | |
1092 | |
1093 return hr; | |
1094 } | |
1095 #endif // STRSAFE_INLINE | |
1096 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
1097 | |
1098 | |
1099 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
1100 /*++ | |
1101 | |
1102 STDAPI | |
1103 StringCbCopyNEx( | |
1104 OUT LPTSTR pszDest OPTIONAL, | |
1105 IN size_t cbDest, | |
1106 IN LPCTSTR pszSrc OPTIONAL, | |
1107 IN size_t cbSrc, | |
1108 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
1109 OUT size_t* pcbRemaining OPTIONAL, | |
1110 IN DWORD dwFlags | |
1111 ); | |
1112 | |
1113 Routine Description: | |
1114 | |
1115 This routine is a safer version of the C built-in function 'strncpy' with | |
1116 some additional parameters. In addition to functionality provided by | |
1117 StringCbCopyN, this routine also returns a pointer to the end of the | |
1118 destination string and the number of bytes left in the destination string | |
1119 including the null terminator. The flags parameter allows additional controls. | |
1120 | |
1121 This routine is meant as a replacement for strncpy, but it does behave | |
1122 differently. This function will not pad the destination buffer with extra | |
1123 null termination characters if cbSrc is greater than the size of pszSrc. | |
1124 | |
1125 Arguments: | |
1126 | |
1127 pszDest - destination string | |
1128 | |
1129 cbDest - size of destination buffer in bytes. | |
1130 length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to | |
1131 hold all of the source including the null terminator | |
1132 | |
1133 pszSrc - source string | |
1134 | |
1135 cbSrc - maximum number of bytes to copy from source string | |
1136 | |
1137 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
1138 pointer to the end of the destination string. If the | |
1139 function copied any data, the result will point to the | |
1140 null termination character | |
1141 | |
1142 pcbRemaining - pcbRemaining is non-null,the function will return the | |
1143 number of bytes left in the destination string, | |
1144 including the null terminator | |
1145 | |
1146 dwFlags - controls some details of the string copy: | |
1147 | |
1148 STRSAFE_FILL_BEHIND_NULL | |
1149 if the function succeeds, the low byte of dwFlags will be | |
1150 used to fill the uninitialize part of destination buffer | |
1151 behind the null terminator | |
1152 | |
1153 STRSAFE_IGNORE_NULLS | |
1154 treat NULL string pointers like empty strings (TEXT("")). | |
1155 this flag is useful for emulating functions like lstrcpy | |
1156 | |
1157 STRSAFE_FILL_ON_FAILURE | |
1158 if the function fails, the low byte of dwFlags will be | |
1159 used to fill all of the destination buffer, and it will | |
1160 be null terminated. This will overwrite any truncated | |
1161 string returned when the failure is | |
1162 STRSAFE_E_INSUFFICIENT_BUFFER | |
1163 | |
1164 STRSAFE_NO_TRUNCATION / | |
1165 STRSAFE_NULL_ON_FAILURE | |
1166 if the function fails, the destination buffer will be set | |
1167 to the empty string. This will overwrite any truncated string | |
1168 returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. | |
1169 | |
1170 Notes: | |
1171 Behavior is undefined if source and destination strings overlap. | |
1172 | |
1173 pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag | |
1174 is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc | |
1175 may be NULL. An error may still be returned even though NULLS are ignored | |
1176 due to insufficient space. | |
1177 | |
1178 Return Value: | |
1179 | |
1180 S_OK - if there was source data and it was all copied and the | |
1181 resultant dest string was null terminated | |
1182 | |
1183 failure - you can use the macro HRESULT_CODE() to get a win32 | |
1184 error code for all hresult failure cases | |
1185 | |
1186 STRSAFE_E_INSUFFICIENT_BUFFER / | |
1187 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
1188 - this return value is an indication that the copy | |
1189 operation failed due to insufficient space. When this | |
1190 error occurs, the destination buffer is modified to | |
1191 contain a truncated version of the ideal result and is | |
1192 null terminated. This is useful for situations where | |
1193 truncation is ok. | |
1194 | |
1195 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
1196 return value of this function | |
1197 | |
1198 --*/ | |
1199 | |
1200 STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); | |
1201 STRSAFEAPI StringCbCopyNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); | |
1202 #ifdef UNICODE | |
1203 #define StringCbCopyNEx StringCbCopyNExW | |
1204 #else | |
1205 #define StringCbCopyNEx StringCbCopyNExA | |
1206 #endif // !UNICODE | |
1207 | |
1208 #ifdef STRSAFE_INLINE | |
1209 STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) | |
1210 { | |
1211 HRESULT hr; | |
1212 size_t cchDest; | |
1213 size_t cchSrc; | |
1214 size_t cchRemaining = 0; | |
1215 | |
1216 cchDest = cbDest / sizeof(char); | |
1217 cchSrc = cbSrc / sizeof(char); | |
1218 | |
1219 if ((cchDest > STRSAFE_MAX_CCH) || | |
1220 (cchSrc > STRSAFE_MAX_CCH)) | |
1221 { | |
1222 hr = STRSAFE_E_INVALID_PARAMETER; | |
1223 } | |
1224 else | |
1225 { | |
1226 hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags); | |
1227 } | |
1228 | |
1229 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
1230 { | |
1231 if (pcbRemaining) | |
1232 { | |
1233 // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
1234 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); | |
1235 } | |
1236 } | |
1237 | |
1238 return hr; | |
1239 } | |
1240 | |
1241 STRSAFEAPI StringCbCopyNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) | |
1242 { | |
1243 HRESULT hr; | |
1244 size_t cchDest; | |
1245 size_t cchSrc; | |
1246 size_t cchRemaining = 0; | |
1247 | |
1248 cchDest = cbDest / sizeof(wchar_t); | |
1249 cchSrc = cbSrc / sizeof(wchar_t); | |
1250 | |
1251 if ((cchDest > STRSAFE_MAX_CCH) || | |
1252 (cchSrc > STRSAFE_MAX_CCH)) | |
1253 { | |
1254 hr = STRSAFE_E_INVALID_PARAMETER; | |
1255 } | |
1256 else | |
1257 { | |
1258 hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags); | |
1259 } | |
1260 | |
1261 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
1262 { | |
1263 if (pcbRemaining) | |
1264 { | |
1265 // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
1266 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); | |
1267 } | |
1268 } | |
1269 | |
1270 return hr; | |
1271 } | |
1272 #endif // STRSAFE_INLINE | |
1273 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
1274 | |
1275 | |
1276 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
1277 /*++ | |
1278 | |
1279 STDAPI | |
1280 StringCchCat( | |
1281 IN OUT LPTSTR pszDest, | |
1282 IN size_t cchDest, | |
1283 IN LPCTSTR pszSrc | |
1284 ); | |
1285 | |
1286 Routine Description: | |
1287 | |
1288 This routine is a safer version of the C built-in function 'strcat'. | |
1289 The size of the destination buffer (in characters) is a parameter and this | |
1290 function will not write past the end of this buffer and it will ALWAYS | |
1291 null terminate the destination buffer (unless it is zero length). | |
1292 | |
1293 This function returns a hresult, and not a pointer. It returns | |
1294 S_OK if the string was concatenated without truncation and null terminated, | |
1295 otherwise it will return a failure code. In failure cases as much of pszSrc | |
1296 will be appended to pszDest as possible, and pszDest will be null | |
1297 terminated. | |
1298 | |
1299 Arguments: | |
1300 | |
1301 pszDest - destination string which must be null terminated | |
1302 | |
1303 cchDest - size of destination buffer in characters. | |
1304 length must be = (_tcslen(pszDest) + _tcslen(pszSrc) + 1) | |
1305 to hold all of the combine string plus the null | |
1306 terminator | |
1307 | |
1308 pszSrc - source string which must be null terminated | |
1309 | |
1310 Notes: | |
1311 Behavior is undefined if source and destination strings overlap. | |
1312 | |
1313 pszDest and pszSrc should not be NULL. See StringCchCatEx if you require | |
1314 the handling of NULL values. | |
1315 | |
1316 Return Value: | |
1317 | |
1318 S_OK - if there was source data and it was all concatenated and | |
1319 the resultant dest string was null terminated | |
1320 | |
1321 failure - you can use the macro HRESULT_CODE() to get a win32 | |
1322 error code for all hresult failure cases | |
1323 | |
1324 STRSAFE_E_INSUFFICIENT_BUFFER / | |
1325 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
1326 - this return value is an indication that the operation | |
1327 failed due to insufficient space. When this error occurs, | |
1328 the destination buffer is modified to contain a truncated | |
1329 version of the ideal result and is null terminated. This | |
1330 is useful for situations where truncation is ok. | |
1331 | |
1332 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
1333 return value of this function | |
1334 | |
1335 --*/ | |
1336 | |
1337 STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc); | |
1338 STRSAFEAPI StringCchCatW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); | |
1339 #ifdef UNICODE | |
1340 #define StringCchCat StringCchCatW | |
1341 #else | |
1342 #define StringCchCat StringCchCatA | |
1343 #endif // !UNICODE | |
1344 | |
1345 #ifdef STRSAFE_INLINE | |
1346 STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc) | |
1347 { | |
1348 HRESULT hr; | |
1349 | |
1350 if (cchDest > STRSAFE_MAX_CCH) | |
1351 { | |
1352 hr = STRSAFE_E_INVALID_PARAMETER; | |
1353 } | |
1354 else | |
1355 { | |
1356 hr = StringCatWorkerA(pszDest, cchDest, pszSrc); | |
1357 } | |
1358 | |
1359 return hr; | |
1360 } | |
1361 | |
1362 STRSAFEAPI StringCchCatW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) | |
1363 { | |
1364 HRESULT hr; | |
1365 | |
1366 if (cchDest > STRSAFE_MAX_CCH) | |
1367 { | |
1368 hr = STRSAFE_E_INVALID_PARAMETER; | |
1369 } | |
1370 else | |
1371 { | |
1372 hr = StringCatWorkerW(pszDest, cchDest, pszSrc); | |
1373 } | |
1374 | |
1375 return hr; | |
1376 } | |
1377 #endif // STRSAFE_INLINE | |
1378 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
1379 | |
1380 | |
1381 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
1382 /*++ | |
1383 | |
1384 STDAPI | |
1385 StringCbCat( | |
1386 IN OUT LPTSTR pszDest, | |
1387 IN size_t cbDest, | |
1388 IN LPCTSTR pszSrc | |
1389 ); | |
1390 | |
1391 Routine Description: | |
1392 | |
1393 This routine is a safer version of the C built-in function 'strcat'. | |
1394 The size of the destination buffer (in bytes) is a parameter and this | |
1395 function will not write past the end of this buffer and it will ALWAYS | |
1396 null terminate the destination buffer (unless it is zero length). | |
1397 | |
1398 This function returns a hresult, and not a pointer. It returns | |
1399 S_OK if the string was concatenated without truncation and null terminated, | |
1400 otherwise it will return a failure code. In failure cases as much of pszSrc | |
1401 will be appended to pszDest as possible, and pszDest will be null | |
1402 terminated. | |
1403 | |
1404 Arguments: | |
1405 | |
1406 pszDest - destination string which must be null terminated | |
1407 | |
1408 cbDest - size of destination buffer in bytes. | |
1409 length must be = ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) | |
1410 to hold all of the combine string plus the null | |
1411 terminator | |
1412 | |
1413 pszSrc - source string which must be null terminated | |
1414 | |
1415 Notes: | |
1416 Behavior is undefined if source and destination strings overlap. | |
1417 | |
1418 pszDest and pszSrc should not be NULL. See StringCbCatEx if you require | |
1419 the handling of NULL values. | |
1420 | |
1421 Return Value: | |
1422 | |
1423 S_OK - if there was source data and it was all concatenated and | |
1424 the resultant dest string was null terminated | |
1425 | |
1426 failure - you can use the macro HRESULT_CODE() to get a win32 | |
1427 error code for all hresult failure cases | |
1428 | |
1429 STRSAFE_E_INSUFFICIENT_BUFFER / | |
1430 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
1431 - this return value is an indication that the operation | |
1432 failed due to insufficient space. When this error occurs, | |
1433 the destination buffer is modified to contain a truncated | |
1434 version of the ideal result and is null terminated. This | |
1435 is useful for situations where truncation is ok. | |
1436 | |
1437 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
1438 return value of this function | |
1439 | |
1440 --*/ | |
1441 | |
1442 STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc); | |
1443 STRSAFEAPI StringCbCatW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc); | |
1444 #ifdef UNICODE | |
1445 #define StringCbCat StringCbCatW | |
1446 #else | |
1447 #define StringCbCat StringCbCatA | |
1448 #endif // !UNICODE | |
1449 | |
1450 #ifdef STRSAFE_INLINE | |
1451 STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc) | |
1452 { | |
1453 HRESULT hr; | |
1454 size_t cchDest; | |
1455 | |
1456 cchDest = cbDest / sizeof(char); | |
1457 | |
1458 if (cchDest > STRSAFE_MAX_CCH) | |
1459 { | |
1460 hr = STRSAFE_E_INVALID_PARAMETER; | |
1461 } | |
1462 else | |
1463 { | |
1464 hr = StringCatWorkerA(pszDest, cchDest, pszSrc); | |
1465 } | |
1466 | |
1467 return hr; | |
1468 } | |
1469 | |
1470 STRSAFEAPI StringCbCatW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc) | |
1471 { | |
1472 HRESULT hr; | |
1473 size_t cchDest; | |
1474 | |
1475 cchDest = cbDest / sizeof(wchar_t); | |
1476 | |
1477 if (cchDest > STRSAFE_MAX_CCH) | |
1478 { | |
1479 hr = STRSAFE_E_INVALID_PARAMETER; | |
1480 } | |
1481 else | |
1482 { | |
1483 hr = StringCatWorkerW(pszDest, cchDest, pszSrc); | |
1484 } | |
1485 | |
1486 return hr; | |
1487 } | |
1488 #endif // STRSAFE_INLINE | |
1489 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
1490 | |
1491 | |
1492 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
1493 /*++ | |
1494 | |
1495 STDAPI | |
1496 StringCchCatEx( | |
1497 IN OUT LPTSTR pszDest OPTIONAL, | |
1498 IN size_t cchDest, | |
1499 IN LPCTSTR pszSrc OPTIONAL, | |
1500 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
1501 OUT size_t* pcchRemaining OPTIONAL, | |
1502 IN DWORD dwFlags | |
1503 ); | |
1504 | |
1505 Routine Description: | |
1506 | |
1507 This routine is a safer version of the C built-in function 'strcat' with | |
1508 some additional parameters. In addition to functionality provided by | |
1509 StringCchCat, this routine also returns a pointer to the end of the | |
1510 destination string and the number of characters left in the destination string | |
1511 including the null terminator. The flags parameter allows additional controls. | |
1512 | |
1513 Arguments: | |
1514 | |
1515 pszDest - destination string which must be null terminated | |
1516 | |
1517 cchDest - size of destination buffer in characters | |
1518 length must be (_tcslen(pszDest) + _tcslen(pszSrc) + 1) | |
1519 to hold all of the combine string plus the null | |
1520 terminator. | |
1521 | |
1522 pszSrc - source string which must be null terminated | |
1523 | |
1524 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
1525 pointer to the end of the destination string. If the | |
1526 function appended any data, the result will point to the | |
1527 null termination character | |
1528 | |
1529 pcchRemaining - if pcchRemaining is non-null, the function will return the | |
1530 number of characters left in the destination string, | |
1531 including the null terminator | |
1532 | |
1533 dwFlags - controls some details of the string copy: | |
1534 | |
1535 STRSAFE_FILL_BEHIND_NULL | |
1536 if the function succeeds, the low byte of dwFlags will be | |
1537 used to fill the uninitialize part of destination buffer | |
1538 behind the null terminator | |
1539 | |
1540 STRSAFE_IGNORE_NULLS | |
1541 treat NULL string pointers like empty strings (TEXT("")). | |
1542 this flag is useful for emulating functions like lstrcat | |
1543 | |
1544 STRSAFE_FILL_ON_FAILURE | |
1545 if the function fails, the low byte of dwFlags will be | |
1546 used to fill all of the destination buffer, and it will | |
1547 be null terminated. This will overwrite any pre-existing | |
1548 or truncated string | |
1549 | |
1550 STRSAFE_NULL_ON_FAILURE | |
1551 if the function fails, the destination buffer will be set | |
1552 to the empty string. This will overwrite any pre-existing or | |
1553 truncated string | |
1554 | |
1555 STRSAFE_NO_TRUNCATION | |
1556 if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest | |
1557 will not contain a truncated string, it will remain unchanged. | |
1558 | |
1559 Notes: | |
1560 Behavior is undefined if source and destination strings overlap. | |
1561 | |
1562 pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag | |
1563 is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc | |
1564 may be NULL. An error may still be returned even though NULLS are ignored | |
1565 due to insufficient space. | |
1566 | |
1567 Return Value: | |
1568 | |
1569 S_OK - if there was source data and it was all concatenated and | |
1570 the resultant dest string was null terminated | |
1571 | |
1572 failure - you can use the macro HRESULT_CODE() to get a win32 | |
1573 error code for all hresult failure cases | |
1574 | |
1575 STRSAFE_E_INSUFFICIENT_BUFFER / | |
1576 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
1577 - this return value is an indication that the operation | |
1578 failed due to insufficient space. When this error | |
1579 occurs, the destination buffer is modified to contain | |
1580 a truncated version of the ideal result and is null | |
1581 terminated. This is useful for situations where | |
1582 truncation is ok. | |
1583 | |
1584 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
1585 return value of this function | |
1586 | |
1587 --*/ | |
1588 | |
1589 STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
1590 STRSAFEAPI StringCchCatExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
1591 #ifdef UNICODE | |
1592 #define StringCchCatEx StringCchCatExW | |
1593 #else | |
1594 #define StringCchCatEx StringCchCatExA | |
1595 #endif // !UNICODE | |
1596 | |
1597 #ifdef STRSAFE_INLINE | |
1598 STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
1599 { | |
1600 HRESULT hr; | |
1601 | |
1602 if (cchDest > STRSAFE_MAX_CCH) | |
1603 { | |
1604 hr = STRSAFE_E_INVALID_PARAMETER; | |
1605 } | |
1606 else | |
1607 { | |
1608 size_t cbDest; | |
1609 | |
1610 // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
1611 cbDest = cchDest * sizeof(char); | |
1612 | |
1613 hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); | |
1614 } | |
1615 | |
1616 return hr; | |
1617 } | |
1618 | |
1619 STRSAFEAPI StringCchCatExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
1620 { | |
1621 HRESULT hr; | |
1622 | |
1623 if (cchDest > STRSAFE_MAX_CCH) | |
1624 { | |
1625 hr = STRSAFE_E_INVALID_PARAMETER; | |
1626 } | |
1627 else | |
1628 { | |
1629 size_t cbDest; | |
1630 | |
1631 // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
1632 cbDest = cchDest * sizeof(wchar_t); | |
1633 | |
1634 hr = StringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); | |
1635 } | |
1636 | |
1637 return hr; | |
1638 } | |
1639 #endif // STRSAFE_INLINE | |
1640 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
1641 | |
1642 | |
1643 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
1644 /*++ | |
1645 | |
1646 STDAPI | |
1647 StringCbCatEx( | |
1648 IN OUT LPTSTR pszDest OPTIONAL, | |
1649 IN size_t cbDest, | |
1650 IN LPCTSTR pszSrc OPTIONAL, | |
1651 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
1652 OUT size_t* pcbRemaining OPTIONAL, | |
1653 IN DWORD dwFlags | |
1654 ); | |
1655 | |
1656 Routine Description: | |
1657 | |
1658 This routine is a safer version of the C built-in function 'strcat' with | |
1659 some additional parameters. In addition to functionality provided by | |
1660 StringCbCat, this routine also returns a pointer to the end of the | |
1661 destination string and the number of bytes left in the destination string | |
1662 including the null terminator. The flags parameter allows additional controls. | |
1663 | |
1664 Arguments: | |
1665 | |
1666 pszDest - destination string which must be null terminated | |
1667 | |
1668 cbDest - size of destination buffer in bytes. | |
1669 length must be ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) | |
1670 to hold all of the combine string plus the null | |
1671 terminator. | |
1672 | |
1673 pszSrc - source string which must be null terminated | |
1674 | |
1675 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
1676 pointer to the end of the destination string. If the | |
1677 function appended any data, the result will point to the | |
1678 null termination character | |
1679 | |
1680 pcbRemaining - if pcbRemaining is non-null, the function will return | |
1681 the number of bytes left in the destination string, | |
1682 including the null terminator | |
1683 | |
1684 dwFlags - controls some details of the string copy: | |
1685 | |
1686 STRSAFE_FILL_BEHIND_NULL | |
1687 if the function succeeds, the low byte of dwFlags will be | |
1688 used to fill the uninitialize part of destination buffer | |
1689 behind the null terminator | |
1690 | |
1691 STRSAFE_IGNORE_NULLS | |
1692 treat NULL string pointers like empty strings (TEXT("")). | |
1693 this flag is useful for emulating functions like lstrcat | |
1694 | |
1695 STRSAFE_FILL_ON_FAILURE | |
1696 if the function fails, the low byte of dwFlags will be | |
1697 used to fill all of the destination buffer, and it will | |
1698 be null terminated. This will overwrite any pre-existing | |
1699 or truncated string | |
1700 | |
1701 STRSAFE_NULL_ON_FAILURE | |
1702 if the function fails, the destination buffer will be set | |
1703 to the empty string. This will overwrite any pre-existing or | |
1704 truncated string | |
1705 | |
1706 STRSAFE_NO_TRUNCATION | |
1707 if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest | |
1708 will not contain a truncated string, it will remain unchanged. | |
1709 | |
1710 Notes: | |
1711 Behavior is undefined if source and destination strings overlap. | |
1712 | |
1713 pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag | |
1714 is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc | |
1715 may be NULL. An error may still be returned even though NULLS are ignored | |
1716 due to insufficient space. | |
1717 | |
1718 Return Value: | |
1719 | |
1720 S_OK - if there was source data and it was all concatenated | |
1721 and the resultant dest string was null terminated | |
1722 | |
1723 failure - you can use the macro HRESULT_CODE() to get a win32 | |
1724 error code for all hresult failure cases | |
1725 | |
1726 STRSAFE_E_INSUFFICIENT_BUFFER / | |
1727 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
1728 - this return value is an indication that the operation | |
1729 failed due to insufficient space. When this error | |
1730 occurs, the destination buffer is modified to contain | |
1731 a truncated version of the ideal result and is null | |
1732 terminated. This is useful for situations where | |
1733 truncation is ok. | |
1734 | |
1735 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
1736 return value of this function | |
1737 | |
1738 --*/ | |
1739 | |
1740 STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); | |
1741 STRSAFEAPI StringCbCatExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); | |
1742 #ifdef UNICODE | |
1743 #define StringCbCatEx StringCbCatExW | |
1744 #else | |
1745 #define StringCbCatEx StringCbCatExA | |
1746 #endif // !UNICODE | |
1747 | |
1748 #ifdef STRSAFE_INLINE | |
1749 STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) | |
1750 { | |
1751 HRESULT hr; | |
1752 size_t cchDest; | |
1753 size_t cchRemaining = 0; | |
1754 | |
1755 cchDest = cbDest / sizeof(char); | |
1756 | |
1757 if (cchDest > STRSAFE_MAX_CCH) | |
1758 { | |
1759 hr = STRSAFE_E_INVALID_PARAMETER; | |
1760 } | |
1761 else | |
1762 { | |
1763 hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags); | |
1764 } | |
1765 | |
1766 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
1767 { | |
1768 if (pcbRemaining) | |
1769 { | |
1770 // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
1771 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); | |
1772 } | |
1773 } | |
1774 | |
1775 return hr; | |
1776 } | |
1777 | |
1778 STRSAFEAPI StringCbCatExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) | |
1779 { | |
1780 HRESULT hr; | |
1781 size_t cchDest; | |
1782 size_t cchRemaining = 0; | |
1783 | |
1784 cchDest = cbDest / sizeof(wchar_t); | |
1785 | |
1786 if (cchDest > STRSAFE_MAX_CCH) | |
1787 { | |
1788 hr = STRSAFE_E_INVALID_PARAMETER; | |
1789 } | |
1790 else | |
1791 { | |
1792 hr = StringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags); | |
1793 } | |
1794 | |
1795 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
1796 { | |
1797 if (pcbRemaining) | |
1798 { | |
1799 // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
1800 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); | |
1801 } | |
1802 } | |
1803 | |
1804 return hr; | |
1805 } | |
1806 #endif // STRSAFE_INLINE | |
1807 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
1808 | |
1809 | |
1810 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
1811 /*++ | |
1812 | |
1813 STDAPI | |
1814 StringCchCatN( | |
1815 IN OUT LPTSTR pszDest, | |
1816 IN size_t cchDest, | |
1817 IN LPCTSTR pszSrc, | |
1818 IN size_t cchMaxAppend | |
1819 ); | |
1820 | |
1821 Routine Description: | |
1822 | |
1823 This routine is a safer version of the C built-in function 'strncat'. | |
1824 The size of the destination buffer (in characters) is a parameter as well as | |
1825 the maximum number of characters to append, excluding the null terminator. | |
1826 This function will not write past the end of the destination buffer and it will | |
1827 ALWAYS null terminate pszDest (unless it is zero length). | |
1828 | |
1829 This function returns a hresult, and not a pointer. It returns | |
1830 S_OK if all of pszSrc or the first cchMaxAppend characters were appended | |
1831 to the destination string and it was null terminated, otherwise it will | |
1832 return a failure code. In failure cases as much of pszSrc will be appended | |
1833 to pszDest as possible, and pszDest will be null terminated. | |
1834 | |
1835 Arguments: | |
1836 | |
1837 pszDest - destination string which must be null terminated | |
1838 | |
1839 cchDest - size of destination buffer in characters. | |
1840 length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1) | |
1841 to hold all of the combine string plus the null | |
1842 terminator. | |
1843 | |
1844 pszSrc - source string | |
1845 | |
1846 cchMaxAppend - maximum number of characters to append | |
1847 | |
1848 Notes: | |
1849 Behavior is undefined if source and destination strings overlap. | |
1850 | |
1851 pszDest and pszSrc should not be NULL. See StringCchCatNEx if you require | |
1852 the handling of NULL values. | |
1853 | |
1854 Return Value: | |
1855 | |
1856 S_OK - if all of pszSrc or the first cchMaxAppend characters | |
1857 were concatenated to pszDest and the resultant dest | |
1858 string was null terminated | |
1859 | |
1860 failure - you can use the macro HRESULT_CODE() to get a win32 | |
1861 error code for all hresult failure cases | |
1862 | |
1863 STRSAFE_E_INSUFFICIENT_BUFFER / | |
1864 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
1865 - this return value is an indication that the operation | |
1866 failed due to insufficient space. When this error | |
1867 occurs, the destination buffer is modified to contain | |
1868 a truncated version of the ideal result and is null | |
1869 terminated. This is useful for situations where | |
1870 truncation is ok. | |
1871 | |
1872 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
1873 return value of this function | |
1874 | |
1875 --*/ | |
1876 | |
1877 STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend); | |
1878 STRSAFEAPI StringCchCatNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend); | |
1879 #ifdef UNICODE | |
1880 #define StringCchCatN StringCchCatNW | |
1881 #else | |
1882 #define StringCchCatN StringCchCatNA | |
1883 #endif // !UNICODE | |
1884 | |
1885 #ifdef STRSAFE_INLINE | |
1886 STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend) | |
1887 { | |
1888 HRESULT hr; | |
1889 | |
1890 if (cchDest > STRSAFE_MAX_CCH) | |
1891 { | |
1892 hr = STRSAFE_E_INVALID_PARAMETER; | |
1893 } | |
1894 else | |
1895 { | |
1896 hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend); | |
1897 } | |
1898 | |
1899 return hr; | |
1900 } | |
1901 | |
1902 STRSAFEAPI StringCchCatNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend) | |
1903 { | |
1904 HRESULT hr; | |
1905 | |
1906 if (cchDest > STRSAFE_MAX_CCH) | |
1907 { | |
1908 hr = STRSAFE_E_INVALID_PARAMETER; | |
1909 } | |
1910 else | |
1911 { | |
1912 hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend); | |
1913 } | |
1914 | |
1915 return hr; | |
1916 } | |
1917 #endif // STRSAFE_INLINE | |
1918 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
1919 | |
1920 | |
1921 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
1922 /*++ | |
1923 | |
1924 STDAPI | |
1925 StringCbCatN( | |
1926 IN OUT LPTSTR pszDest, | |
1927 IN size_t cbDest, | |
1928 IN LPCTSTR pszSrc, | |
1929 IN size_t cbMaxAppend | |
1930 ); | |
1931 | |
1932 Routine Description: | |
1933 | |
1934 This routine is a safer version of the C built-in function 'strncat'. | |
1935 The size of the destination buffer (in bytes) is a parameter as well as | |
1936 the maximum number of bytes to append, excluding the null terminator. | |
1937 This function will not write past the end of the destination buffer and it will | |
1938 ALWAYS null terminate pszDest (unless it is zero length). | |
1939 | |
1940 This function returns a hresult, and not a pointer. It returns | |
1941 S_OK if all of pszSrc or the first cbMaxAppend bytes were appended | |
1942 to the destination string and it was null terminated, otherwise it will | |
1943 return a failure code. In failure cases as much of pszSrc will be appended | |
1944 to pszDest as possible, and pszDest will be null terminated. | |
1945 | |
1946 Arguments: | |
1947 | |
1948 pszDest - destination string which must be null terminated | |
1949 | |
1950 cbDest - size of destination buffer in bytes. | |
1951 length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) | |
1952 to hold all of the combine string plus the null | |
1953 terminator. | |
1954 | |
1955 pszSrc - source string | |
1956 | |
1957 cbMaxAppend - maximum number of bytes to append | |
1958 | |
1959 Notes: | |
1960 Behavior is undefined if source and destination strings overlap. | |
1961 | |
1962 pszDest and pszSrc should not be NULL. See StringCbCatNEx if you require | |
1963 the handling of NULL values. | |
1964 | |
1965 Return Value: | |
1966 | |
1967 S_OK - if all of pszSrc or the first cbMaxAppend bytes were | |
1968 concatenated to pszDest and the resultant dest string | |
1969 was null terminated | |
1970 | |
1971 failure - you can use the macro HRESULT_CODE() to get a win32 | |
1972 error code for all hresult failure cases | |
1973 | |
1974 STRSAFE_E_INSUFFICIENT_BUFFER / | |
1975 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
1976 - this return value is an indication that the operation | |
1977 failed due to insufficient space. When this error | |
1978 occurs, the destination buffer is modified to contain | |
1979 a truncated version of the ideal result and is null | |
1980 terminated. This is useful for situations where | |
1981 truncation is ok. | |
1982 | |
1983 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
1984 return value of this function | |
1985 | |
1986 --*/ | |
1987 | |
1988 STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend); | |
1989 STRSAFEAPI StringCbCatNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend); | |
1990 #ifdef UNICODE | |
1991 #define StringCbCatN StringCbCatNW | |
1992 #else | |
1993 #define StringCbCatN StringCbCatNA | |
1994 #endif // !UNICODE | |
1995 | |
1996 #ifdef STRSAFE_INLINE | |
1997 STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend) | |
1998 { | |
1999 HRESULT hr; | |
2000 size_t cchDest; | |
2001 | |
2002 cchDest = cbDest / sizeof(char); | |
2003 | |
2004 if (cchDest > STRSAFE_MAX_CCH) | |
2005 { | |
2006 hr = STRSAFE_E_INVALID_PARAMETER; | |
2007 } | |
2008 else | |
2009 { | |
2010 size_t cchMaxAppend; | |
2011 | |
2012 cchMaxAppend = cbMaxAppend / sizeof(char); | |
2013 | |
2014 hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend); | |
2015 } | |
2016 | |
2017 return hr; | |
2018 } | |
2019 | |
2020 STRSAFEAPI StringCbCatNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend) | |
2021 { | |
2022 HRESULT hr; | |
2023 size_t cchDest; | |
2024 | |
2025 cchDest = cbDest / sizeof(wchar_t); | |
2026 | |
2027 if (cchDest > STRSAFE_MAX_CCH) | |
2028 { | |
2029 hr = STRSAFE_E_INVALID_PARAMETER; | |
2030 } | |
2031 else | |
2032 { | |
2033 size_t cchMaxAppend; | |
2034 | |
2035 cchMaxAppend = cbMaxAppend / sizeof(wchar_t); | |
2036 | |
2037 hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend); | |
2038 } | |
2039 | |
2040 return hr; | |
2041 } | |
2042 #endif // STRSAFE_INLINE | |
2043 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
2044 | |
2045 | |
2046 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
2047 /*++ | |
2048 | |
2049 STDAPI | |
2050 StringCchCatNEx( | |
2051 IN OUT LPTSTR pszDest OPTIONAL, | |
2052 IN size_t cchDest, | |
2053 IN LPCTSTR pszSrc OPTIONAL, | |
2054 IN size_t cchMaxAppend, | |
2055 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
2056 OUT size_t* pcchRemaining OPTIONAL, | |
2057 IN DWORD dwFlags | |
2058 ); | |
2059 | |
2060 Routine Description: | |
2061 | |
2062 This routine is a safer version of the C built-in function 'strncat', with | |
2063 some additional parameters. In addition to functionality provided by | |
2064 StringCchCatN, this routine also returns a pointer to the end of the | |
2065 destination string and the number of characters left in the destination string | |
2066 including the null terminator. The flags parameter allows additional controls. | |
2067 | |
2068 Arguments: | |
2069 | |
2070 pszDest - destination string which must be null terminated | |
2071 | |
2072 cchDest - size of destination buffer in characters. | |
2073 length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1) | |
2074 to hold all of the combine string plus the null | |
2075 terminator. | |
2076 | |
2077 pszSrc - source string | |
2078 | |
2079 cchMaxAppend - maximum number of characters to append | |
2080 | |
2081 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
2082 pointer to the end of the destination string. If the | |
2083 function appended any data, the result will point to the | |
2084 null termination character | |
2085 | |
2086 pcchRemaining - if pcchRemaining is non-null, the function will return the | |
2087 number of characters left in the destination string, | |
2088 including the null terminator | |
2089 | |
2090 dwFlags - controls some details of the string copy: | |
2091 | |
2092 STRSAFE_FILL_BEHIND_NULL | |
2093 if the function succeeds, the low byte of dwFlags will be | |
2094 used to fill the uninitialize part of destination buffer | |
2095 behind the null terminator | |
2096 | |
2097 STRSAFE_IGNORE_NULLS | |
2098 treat NULL string pointers like empty strings (TEXT("")) | |
2099 | |
2100 STRSAFE_FILL_ON_FAILURE | |
2101 if the function fails, the low byte of dwFlags will be | |
2102 used to fill all of the destination buffer, and it will | |
2103 be null terminated. This will overwrite any pre-existing | |
2104 or truncated string | |
2105 | |
2106 STRSAFE_NULL_ON_FAILURE | |
2107 if the function fails, the destination buffer will be set | |
2108 to the empty string. This will overwrite any pre-existing or | |
2109 truncated string | |
2110 | |
2111 STRSAFE_NO_TRUNCATION | |
2112 if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest | |
2113 will not contain a truncated string, it will remain unchanged. | |
2114 | |
2115 Notes: | |
2116 Behavior is undefined if source and destination strings overlap. | |
2117 | |
2118 pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag | |
2119 is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc | |
2120 may be NULL. An error may still be returned even though NULLS are ignored | |
2121 due to insufficient space. | |
2122 | |
2123 Return Value: | |
2124 | |
2125 S_OK - if all of pszSrc or the first cchMaxAppend characters | |
2126 were concatenated to pszDest and the resultant dest | |
2127 string was null terminated | |
2128 | |
2129 failure - you can use the macro HRESULT_CODE() to get a win32 | |
2130 error code for all hresult failure cases | |
2131 | |
2132 STRSAFE_E_INSUFFICIENT_BUFFER / | |
2133 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
2134 - this return value is an indication that the operation | |
2135 failed due to insufficient space. When this error | |
2136 occurs, the destination buffer is modified to contain | |
2137 a truncated version of the ideal result and is null | |
2138 terminated. This is useful for situations where | |
2139 truncation is ok. | |
2140 | |
2141 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
2142 return value of this function | |
2143 | |
2144 --*/ | |
2145 | |
2146 STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
2147 STRSAFEAPI StringCchCatNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
2148 #ifdef UNICODE | |
2149 #define StringCchCatNEx StringCchCatNExW | |
2150 #else | |
2151 #define StringCchCatNEx StringCchCatNExA | |
2152 #endif // !UNICODE | |
2153 | |
2154 #ifdef STRSAFE_INLINE | |
2155 STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
2156 { | |
2157 HRESULT hr; | |
2158 | |
2159 if (cchDest > STRSAFE_MAX_CCH) | |
2160 { | |
2161 hr = STRSAFE_E_INVALID_PARAMETER; | |
2162 } | |
2163 else | |
2164 { | |
2165 size_t cbDest; | |
2166 | |
2167 // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
2168 cbDest = cchDest * sizeof(char); | |
2169 | |
2170 hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags); | |
2171 } | |
2172 | |
2173 return hr; | |
2174 } | |
2175 | |
2176 STRSAFEAPI StringCchCatNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
2177 { | |
2178 HRESULT hr; | |
2179 | |
2180 if (cchDest > STRSAFE_MAX_CCH) | |
2181 { | |
2182 hr = STRSAFE_E_INVALID_PARAMETER; | |
2183 } | |
2184 else | |
2185 { | |
2186 size_t cbDest; | |
2187 | |
2188 // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
2189 cbDest = cchDest * sizeof(wchar_t); | |
2190 | |
2191 hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags); | |
2192 } | |
2193 | |
2194 return hr; | |
2195 } | |
2196 #endif // STRSAFE_INLINE | |
2197 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
2198 | |
2199 | |
2200 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
2201 /*++ | |
2202 | |
2203 STDAPI | |
2204 StringCbCatNEx( | |
2205 IN OUT LPTSTR pszDest OPTIONAL, | |
2206 IN size_t cbDest, | |
2207 IN LPCTSTR pszSrc OPTIONAL, | |
2208 IN size_t cbMaxAppend, | |
2209 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
2210 OUT size_t* pcchRemaining OPTIONAL, | |
2211 IN DWORD dwFlags | |
2212 ); | |
2213 | |
2214 Routine Description: | |
2215 | |
2216 This routine is a safer version of the C built-in function 'strncat', with | |
2217 some additional parameters. In addition to functionality provided by | |
2218 StringCbCatN, this routine also returns a pointer to the end of the | |
2219 destination string and the number of bytes left in the destination string | |
2220 including the null terminator. The flags parameter allows additional controls. | |
2221 | |
2222 Arguments: | |
2223 | |
2224 pszDest - destination string which must be null terminated | |
2225 | |
2226 cbDest - size of destination buffer in bytes. | |
2227 length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) | |
2228 to hold all of the combine string plus the null | |
2229 terminator. | |
2230 | |
2231 pszSrc - source string | |
2232 | |
2233 cbMaxAppend - maximum number of bytes to append | |
2234 | |
2235 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
2236 pointer to the end of the destination string. If the | |
2237 function appended any data, the result will point to the | |
2238 null termination character | |
2239 | |
2240 pcbRemaining - if pcbRemaining is non-null, the function will return the | |
2241 number of bytes left in the destination string, | |
2242 including the null terminator | |
2243 | |
2244 dwFlags - controls some details of the string copy: | |
2245 | |
2246 STRSAFE_FILL_BEHIND_NULL | |
2247 if the function succeeds, the low byte of dwFlags will be | |
2248 used to fill the uninitialize part of destination buffer | |
2249 behind the null terminator | |
2250 | |
2251 STRSAFE_IGNORE_NULLS | |
2252 treat NULL string pointers like empty strings (TEXT("")) | |
2253 | |
2254 STRSAFE_FILL_ON_FAILURE | |
2255 if the function fails, the low byte of dwFlags will be | |
2256 used to fill all of the destination buffer, and it will | |
2257 be null terminated. This will overwrite any pre-existing | |
2258 or truncated string | |
2259 | |
2260 STRSAFE_NULL_ON_FAILURE | |
2261 if the function fails, the destination buffer will be set | |
2262 to the empty string. This will overwrite any pre-existing or | |
2263 truncated string | |
2264 | |
2265 STRSAFE_NO_TRUNCATION | |
2266 if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest | |
2267 will not contain a truncated string, it will remain unchanged. | |
2268 | |
2269 Notes: | |
2270 Behavior is undefined if source and destination strings overlap. | |
2271 | |
2272 pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag | |
2273 is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc | |
2274 may be NULL. An error may still be returned even though NULLS are ignored | |
2275 due to insufficient space. | |
2276 | |
2277 Return Value: | |
2278 | |
2279 S_OK - if all of pszSrc or the first cbMaxAppend bytes were | |
2280 concatenated to pszDest and the resultant dest string | |
2281 was null terminated | |
2282 | |
2283 failure - you can use the macro HRESULT_CODE() to get a win32 | |
2284 error code for all hresult failure cases | |
2285 | |
2286 STRSAFE_E_INSUFFICIENT_BUFFER / | |
2287 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
2288 - this return value is an indication that the operation | |
2289 failed due to insufficient space. When this error | |
2290 occurs, the destination buffer is modified to contain | |
2291 a truncated version of the ideal result and is null | |
2292 terminated. This is useful for situations where | |
2293 truncation is ok. | |
2294 | |
2295 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
2296 return value of this function | |
2297 | |
2298 --*/ | |
2299 | |
2300 STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); | |
2301 STRSAFEAPI StringCbCatNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); | |
2302 #ifdef UNICODE | |
2303 #define StringCbCatNEx StringCbCatNExW | |
2304 #else | |
2305 #define StringCbCatNEx StringCbCatNExA | |
2306 #endif // !UNICODE | |
2307 | |
2308 #ifdef STRSAFE_INLINE | |
2309 STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) | |
2310 { | |
2311 HRESULT hr; | |
2312 size_t cchDest; | |
2313 size_t cchRemaining = 0; | |
2314 | |
2315 cchDest = cbDest / sizeof(char); | |
2316 | |
2317 if (cchDest > STRSAFE_MAX_CCH) | |
2318 { | |
2319 hr = STRSAFE_E_INVALID_PARAMETER; | |
2320 } | |
2321 else | |
2322 { | |
2323 size_t cchMaxAppend; | |
2324 | |
2325 cchMaxAppend = cbMaxAppend / sizeof(char); | |
2326 | |
2327 hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags); | |
2328 } | |
2329 | |
2330 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
2331 { | |
2332 if (pcbRemaining) | |
2333 { | |
2334 // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
2335 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); | |
2336 } | |
2337 } | |
2338 | |
2339 return hr; | |
2340 } | |
2341 | |
2342 STRSAFEAPI StringCbCatNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) | |
2343 { | |
2344 HRESULT hr; | |
2345 size_t cchDest; | |
2346 size_t cchRemaining = 0; | |
2347 | |
2348 cchDest = cbDest / sizeof(wchar_t); | |
2349 | |
2350 if (cchDest > STRSAFE_MAX_CCH) | |
2351 { | |
2352 hr = STRSAFE_E_INVALID_PARAMETER; | |
2353 } | |
2354 else | |
2355 { | |
2356 size_t cchMaxAppend; | |
2357 | |
2358 cchMaxAppend = cbMaxAppend / sizeof(wchar_t); | |
2359 | |
2360 hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags); | |
2361 } | |
2362 | |
2363 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
2364 { | |
2365 if (pcbRemaining) | |
2366 { | |
2367 // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
2368 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); | |
2369 } | |
2370 } | |
2371 | |
2372 return hr; | |
2373 } | |
2374 #endif // STRSAFE_INLINE | |
2375 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
2376 | |
2377 | |
2378 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
2379 /*++ | |
2380 | |
2381 STDAPI | |
2382 StringCchVPrintf( | |
2383 OUT LPTSTR pszDest, | |
2384 IN size_t cchDest, | |
2385 IN LPCTSTR pszFormat, | |
2386 IN va_list argList | |
2387 ); | |
2388 | |
2389 Routine Description: | |
2390 | |
2391 This routine is a safer version of the C built-in function 'vsprintf'. | |
2392 The size of the destination buffer (in characters) is a parameter and | |
2393 this function will not write past the end of this buffer and it will | |
2394 ALWAYS null terminate the destination buffer (unless it is zero length). | |
2395 | |
2396 This function returns a hresult, and not a pointer. It returns | |
2397 S_OK if the string was printed without truncation and null terminated, | |
2398 otherwise it will return a failure code. In failure cases it will return | |
2399 a truncated version of the ideal result. | |
2400 | |
2401 Arguments: | |
2402 | |
2403 pszDest - destination string | |
2404 | |
2405 cchDest - size of destination buffer in characters | |
2406 length must be sufficient to hold the resulting formatted | |
2407 string, including the null terminator. | |
2408 | |
2409 pszFormat - format string which must be null terminated | |
2410 | |
2411 argList - va_list from the variable arguments according to the | |
2412 stdarg.h convention | |
2413 | |
2414 Notes: | |
2415 Behavior is undefined if destination, format strings or any arguments | |
2416 strings overlap. | |
2417 | |
2418 pszDest and pszFormat should not be NULL. See StringCchVPrintfEx if you | |
2419 require the handling of NULL values. | |
2420 | |
2421 Return Value: | |
2422 | |
2423 S_OK - if there was sufficient space in the dest buffer for | |
2424 the resultant string and it was null terminated. | |
2425 | |
2426 failure - you can use the macro HRESULT_CODE() to get a win32 | |
2427 error code for all hresult failure cases | |
2428 | |
2429 STRSAFE_E_INSUFFICIENT_BUFFER / | |
2430 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
2431 - this return value is an indication that the print | |
2432 operation failed due to insufficient space. When this | |
2433 error occurs, the destination buffer is modified to | |
2434 contain a truncated version of the ideal result and is | |
2435 null terminated. This is useful for situations where | |
2436 truncation is ok. | |
2437 | |
2438 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
2439 return value of this function | |
2440 | |
2441 --*/ | |
2442 | |
2443 STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList); | |
2444 STRSAFEAPI StringCchVPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList); | |
2445 #ifdef UNICODE | |
2446 #define StringCchVPrintf StringCchVPrintfW | |
2447 #else | |
2448 #define StringCchVPrintf StringCchVPrintfA | |
2449 #endif // !UNICODE | |
2450 | |
2451 #ifdef STRSAFE_INLINE | |
2452 STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList) | |
2453 { | |
2454 HRESULT hr; | |
2455 | |
2456 if (cchDest > STRSAFE_MAX_CCH) | |
2457 { | |
2458 hr = STRSAFE_E_INVALID_PARAMETER; | |
2459 } | |
2460 else | |
2461 { | |
2462 hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList); | |
2463 } | |
2464 | |
2465 return hr; | |
2466 } | |
2467 | |
2468 STRSAFEAPI StringCchVPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList) | |
2469 { | |
2470 HRESULT hr; | |
2471 | |
2472 if (cchDest > STRSAFE_MAX_CCH) | |
2473 { | |
2474 hr = STRSAFE_E_INVALID_PARAMETER; | |
2475 } | |
2476 else | |
2477 { | |
2478 hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList); | |
2479 } | |
2480 | |
2481 return hr; | |
2482 } | |
2483 #endif // STRSAFE_INLINE | |
2484 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
2485 | |
2486 | |
2487 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
2488 /*++ | |
2489 | |
2490 STDAPI | |
2491 StringCbVPrintf( | |
2492 OUT LPTSTR pszDest, | |
2493 IN size_t cbDest, | |
2494 IN LPCTSTR pszFormat, | |
2495 IN va_list argList | |
2496 ); | |
2497 | |
2498 Routine Description: | |
2499 | |
2500 This routine is a safer version of the C built-in function 'vsprintf'. | |
2501 The size of the destination buffer (in bytes) is a parameter and | |
2502 this function will not write past the end of this buffer and it will | |
2503 ALWAYS null terminate the destination buffer (unless it is zero length). | |
2504 | |
2505 This function returns a hresult, and not a pointer. It returns | |
2506 S_OK if the string was printed without truncation and null terminated, | |
2507 otherwise it will return a failure code. In failure cases it will return | |
2508 a truncated version of the ideal result. | |
2509 | |
2510 Arguments: | |
2511 | |
2512 pszDest - destination string | |
2513 | |
2514 cbDest - size of destination buffer in bytes | |
2515 length must be sufficient to hold the resulting formatted | |
2516 string, including the null terminator. | |
2517 | |
2518 pszFormat - format string which must be null terminated | |
2519 | |
2520 argList - va_list from the variable arguments according to the | |
2521 stdarg.h convention | |
2522 | |
2523 Notes: | |
2524 Behavior is undefined if destination, format strings or any arguments | |
2525 strings overlap. | |
2526 | |
2527 pszDest and pszFormat should not be NULL. See StringCbVPrintfEx if you | |
2528 require the handling of NULL values. | |
2529 | |
2530 | |
2531 Return Value: | |
2532 | |
2533 S_OK - if there was sufficient space in the dest buffer for | |
2534 the resultant string and it was null terminated. | |
2535 | |
2536 failure - you can use the macro HRESULT_CODE() to get a win32 | |
2537 error code for all hresult failure cases | |
2538 | |
2539 STRSAFE_E_INSUFFICIENT_BUFFER / | |
2540 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
2541 - this return value is an indication that the print | |
2542 operation failed due to insufficient space. When this | |
2543 error occurs, the destination buffer is modified to | |
2544 contain a truncated version of the ideal result and is | |
2545 null terminated. This is useful for situations where | |
2546 truncation is ok. | |
2547 | |
2548 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
2549 return value of this function | |
2550 | |
2551 --*/ | |
2552 | |
2553 STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList); | |
2554 STRSAFEAPI StringCbVPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, va_list argList); | |
2555 #ifdef UNICODE | |
2556 #define StringCbVPrintf StringCbVPrintfW | |
2557 #else | |
2558 #define StringCbVPrintf StringCbVPrintfA | |
2559 #endif // !UNICODE | |
2560 | |
2561 #ifdef STRSAFE_INLINE | |
2562 STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList) | |
2563 { | |
2564 HRESULT hr; | |
2565 size_t cchDest; | |
2566 | |
2567 cchDest = cbDest / sizeof(char); | |
2568 | |
2569 if (cchDest > STRSAFE_MAX_CCH) | |
2570 { | |
2571 hr = STRSAFE_E_INVALID_PARAMETER; | |
2572 } | |
2573 else | |
2574 { | |
2575 hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList); | |
2576 } | |
2577 | |
2578 return hr; | |
2579 } | |
2580 | |
2581 STRSAFEAPI StringCbVPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, va_list argList) | |
2582 { | |
2583 HRESULT hr; | |
2584 size_t cchDest; | |
2585 | |
2586 cchDest = cbDest / sizeof(wchar_t); | |
2587 | |
2588 if (cchDest > STRSAFE_MAX_CCH) | |
2589 { | |
2590 hr = STRSAFE_E_INVALID_PARAMETER; | |
2591 } | |
2592 else | |
2593 { | |
2594 hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList); | |
2595 } | |
2596 | |
2597 return hr; | |
2598 } | |
2599 #endif // STRSAFE_INLINE | |
2600 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
2601 | |
2602 | |
2603 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
2604 /*++ | |
2605 | |
2606 STDAPI | |
2607 StringCchPrintf( | |
2608 OUT LPTSTR pszDest, | |
2609 IN size_t cchDest, | |
2610 IN LPCTSTR pszFormat, | |
2611 ... | |
2612 ); | |
2613 | |
2614 Routine Description: | |
2615 | |
2616 This routine is a safer version of the C built-in function 'sprintf'. | |
2617 The size of the destination buffer (in characters) is a parameter and | |
2618 this function will not write past the end of this buffer and it will | |
2619 ALWAYS null terminate the destination buffer (unless it is zero length). | |
2620 | |
2621 This function returns a hresult, and not a pointer. It returns | |
2622 S_OK if the string was printed without truncation and null terminated, | |
2623 otherwise it will return a failure code. In failure cases it will return | |
2624 a truncated version of the ideal result. | |
2625 | |
2626 Arguments: | |
2627 | |
2628 pszDest - destination string | |
2629 | |
2630 cchDest - size of destination buffer in characters | |
2631 length must be sufficient to hold the resulting formatted | |
2632 string, including the null terminator. | |
2633 | |
2634 pszFormat - format string which must be null terminated | |
2635 | |
2636 ... - additional parameters to be formatted according to | |
2637 the format string | |
2638 | |
2639 Notes: | |
2640 Behavior is undefined if destination, format strings or any arguments | |
2641 strings overlap. | |
2642 | |
2643 pszDest and pszFormat should not be NULL. See StringCchPrintfEx if you | |
2644 require the handling of NULL values. | |
2645 | |
2646 Return Value: | |
2647 | |
2648 S_OK - if there was sufficient space in the dest buffer for | |
2649 the resultant string and it was null terminated. | |
2650 | |
2651 failure - you can use the macro HRESULT_CODE() to get a win32 | |
2652 error code for all hresult failure cases | |
2653 | |
2654 STRSAFE_E_INSUFFICIENT_BUFFER / | |
2655 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
2656 - this return value is an indication that the print | |
2657 operation failed due to insufficient space. When this | |
2658 error occurs, the destination buffer is modified to | |
2659 contain a truncated version of the ideal result and is | |
2660 null terminated. This is useful for situations where | |
2661 truncation is ok. | |
2662 | |
2663 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
2664 return value of this function | |
2665 | |
2666 --*/ | |
2667 | |
2668 STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...); | |
2669 STRSAFEAPI StringCchPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, ...); | |
2670 #ifdef UNICODE | |
2671 #define StringCchPrintf StringCchPrintfW | |
2672 #else | |
2673 #define StringCchPrintf StringCchPrintfA | |
2674 #endif // !UNICODE | |
2675 | |
2676 #ifdef STRSAFE_INLINE | |
2677 STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...) | |
2678 { | |
2679 HRESULT hr; | |
2680 | |
2681 if (cchDest > STRSAFE_MAX_CCH) | |
2682 { | |
2683 hr = STRSAFE_E_INVALID_PARAMETER; | |
2684 } | |
2685 else | |
2686 { | |
2687 va_list argList; | |
2688 | |
2689 va_start(argList, pszFormat); | |
2690 | |
2691 hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList); | |
2692 | |
2693 va_end(argList); | |
2694 } | |
2695 | |
2696 return hr; | |
2697 } | |
2698 | |
2699 STRSAFEAPI StringCchPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, ...) | |
2700 { | |
2701 HRESULT hr; | |
2702 | |
2703 if (cchDest > STRSAFE_MAX_CCH) | |
2704 { | |
2705 hr = STRSAFE_E_INVALID_PARAMETER; | |
2706 } | |
2707 else | |
2708 { | |
2709 va_list argList; | |
2710 | |
2711 va_start(argList, pszFormat); | |
2712 | |
2713 hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList); | |
2714 | |
2715 va_end(argList); | |
2716 } | |
2717 | |
2718 return hr; | |
2719 } | |
2720 #endif // STRSAFE_INLINE | |
2721 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
2722 | |
2723 | |
2724 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
2725 /*++ | |
2726 | |
2727 STDAPI | |
2728 StringCbPrintf( | |
2729 OUT LPTSTR pszDest, | |
2730 IN size_t cbDest, | |
2731 IN LPCTSTR pszFormat, | |
2732 ... | |
2733 ); | |
2734 | |
2735 Routine Description: | |
2736 | |
2737 This routine is a safer version of the C built-in function 'sprintf'. | |
2738 The size of the destination buffer (in bytes) is a parameter and | |
2739 this function will not write past the end of this buffer and it will | |
2740 ALWAYS null terminate the destination buffer (unless it is zero length). | |
2741 | |
2742 This function returns a hresult, and not a pointer. It returns | |
2743 S_OK if the string was printed without truncation and null terminated, | |
2744 otherwise it will return a failure code. In failure cases it will return | |
2745 a truncated version of the ideal result. | |
2746 | |
2747 Arguments: | |
2748 | |
2749 pszDest - destination string | |
2750 | |
2751 cbDest - size of destination buffer in bytes | |
2752 length must be sufficient to hold the resulting formatted | |
2753 string, including the null terminator. | |
2754 | |
2755 pszFormat - format string which must be null terminated | |
2756 | |
2757 ... - additional parameters to be formatted according to | |
2758 the format string | |
2759 | |
2760 Notes: | |
2761 Behavior is undefined if destination, format strings or any arguments | |
2762 strings overlap. | |
2763 | |
2764 pszDest and pszFormat should not be NULL. See StringCbPrintfEx if you | |
2765 require the handling of NULL values. | |
2766 | |
2767 | |
2768 Return Value: | |
2769 | |
2770 S_OK - if there was sufficient space in the dest buffer for | |
2771 the resultant string and it was null terminated. | |
2772 | |
2773 failure - you can use the macro HRESULT_CODE() to get a win32 | |
2774 error code for all hresult failure cases | |
2775 | |
2776 STRSAFE_E_INSUFFICIENT_BUFFER / | |
2777 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
2778 - this return value is an indication that the print | |
2779 operation failed due to insufficient space. When this | |
2780 error occurs, the destination buffer is modified to | |
2781 contain a truncated version of the ideal result and is | |
2782 null terminated. This is useful for situations where | |
2783 truncation is ok. | |
2784 | |
2785 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
2786 return value of this function | |
2787 | |
2788 --*/ | |
2789 | |
2790 STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...); | |
2791 STRSAFEAPI StringCbPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, ...); | |
2792 #ifdef UNICODE | |
2793 #define StringCbPrintf StringCbPrintfW | |
2794 #else | |
2795 #define StringCbPrintf StringCbPrintfA | |
2796 #endif // !UNICODE | |
2797 | |
2798 #ifdef STRSAFE_INLINE | |
2799 STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...) | |
2800 { | |
2801 HRESULT hr; | |
2802 size_t cchDest; | |
2803 | |
2804 cchDest = cbDest / sizeof(char); | |
2805 | |
2806 if (cchDest > STRSAFE_MAX_CCH) | |
2807 { | |
2808 hr = STRSAFE_E_INVALID_PARAMETER; | |
2809 } | |
2810 else | |
2811 { | |
2812 va_list argList; | |
2813 | |
2814 va_start(argList, pszFormat); | |
2815 | |
2816 hr = StringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList); | |
2817 | |
2818 va_end(argList); | |
2819 } | |
2820 | |
2821 return hr; | |
2822 } | |
2823 | |
2824 STRSAFEAPI StringCbPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, ...) | |
2825 { | |
2826 HRESULT hr; | |
2827 size_t cchDest; | |
2828 | |
2829 cchDest = cbDest / sizeof(wchar_t); | |
2830 | |
2831 if (cchDest > STRSAFE_MAX_CCH) | |
2832 { | |
2833 hr = STRSAFE_E_INVALID_PARAMETER; | |
2834 } | |
2835 else | |
2836 { | |
2837 va_list argList; | |
2838 | |
2839 va_start(argList, pszFormat); | |
2840 | |
2841 hr = StringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList); | |
2842 | |
2843 va_end(argList); | |
2844 } | |
2845 | |
2846 return hr; | |
2847 } | |
2848 #endif // STRSAFE_INLINE | |
2849 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
2850 | |
2851 | |
2852 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
2853 /*++ | |
2854 | |
2855 STDAPI | |
2856 StringCchPrintfEx( | |
2857 OUT LPTSTR pszDest OPTIONAL, | |
2858 IN size_t cchDest, | |
2859 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
2860 OUT size_t* pcchRemaining OPTIONAL, | |
2861 IN DWORD dwFlags, | |
2862 IN LPCTSTR pszFormat OPTIONAL, | |
2863 ... | |
2864 ); | |
2865 | |
2866 Routine Description: | |
2867 | |
2868 This routine is a safer version of the C built-in function 'sprintf' with | |
2869 some additional parameters. In addition to functionality provided by | |
2870 StringCchPrintf, this routine also returns a pointer to the end of the | |
2871 destination string and the number of characters left in the destination string | |
2872 including the null terminator. The flags parameter allows additional controls. | |
2873 | |
2874 Arguments: | |
2875 | |
2876 pszDest - destination string | |
2877 | |
2878 cchDest - size of destination buffer in characters. | |
2879 length must be sufficient to contain the resulting | |
2880 formatted string plus the null terminator. | |
2881 | |
2882 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
2883 pointer to the end of the destination string. If the | |
2884 function printed any data, the result will point to the | |
2885 null termination character | |
2886 | |
2887 pcchRemaining - if pcchRemaining is non-null, the function will return | |
2888 the number of characters left in the destination string, | |
2889 including the null terminator | |
2890 | |
2891 dwFlags - controls some details of the string copy: | |
2892 | |
2893 STRSAFE_FILL_BEHIND_NULL | |
2894 if the function succeeds, the low byte of dwFlags will be | |
2895 used to fill the uninitialize part of destination buffer | |
2896 behind the null terminator | |
2897 | |
2898 STRSAFE_IGNORE_NULLS | |
2899 treat NULL string pointers like empty strings (TEXT("")) | |
2900 | |
2901 STRSAFE_FILL_ON_FAILURE | |
2902 if the function fails, the low byte of dwFlags will be | |
2903 used to fill all of the destination buffer, and it will | |
2904 be null terminated. This will overwrite any truncated | |
2905 string returned when the failure is | |
2906 STRSAFE_E_INSUFFICIENT_BUFFER | |
2907 | |
2908 STRSAFE_NO_TRUNCATION / | |
2909 STRSAFE_NULL_ON_FAILURE | |
2910 if the function fails, the destination buffer will be set | |
2911 to the empty string. This will overwrite any truncated string | |
2912 returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. | |
2913 | |
2914 pszFormat - format string which must be null terminated | |
2915 | |
2916 ... - additional parameters to be formatted according to | |
2917 the format string | |
2918 | |
2919 Notes: | |
2920 Behavior is undefined if destination, format strings or any arguments | |
2921 strings overlap. | |
2922 | |
2923 pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS | |
2924 flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and | |
2925 pszFormat may be NULL. An error may still be returned even though NULLS | |
2926 are ignored due to insufficient space. | |
2927 | |
2928 Return Value: | |
2929 | |
2930 S_OK - if there was source data and it was all concatenated and | |
2931 the resultant dest string was null terminated | |
2932 | |
2933 failure - you can use the macro HRESULT_CODE() to get a win32 | |
2934 error code for all hresult failure cases | |
2935 | |
2936 STRSAFE_E_INSUFFICIENT_BUFFER / | |
2937 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
2938 - this return value is an indication that the print | |
2939 operation failed due to insufficient space. When this | |
2940 error occurs, the destination buffer is modified to | |
2941 contain a truncated version of the ideal result and is | |
2942 null terminated. This is useful for situations where | |
2943 truncation is ok. | |
2944 | |
2945 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
2946 return value of this function | |
2947 | |
2948 --*/ | |
2949 | |
2950 STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...); | |
2951 STRSAFEAPI StringCchPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...); | |
2952 #ifdef UNICODE | |
2953 #define StringCchPrintfEx StringCchPrintfExW | |
2954 #else | |
2955 #define StringCchPrintfEx StringCchPrintfExA | |
2956 #endif // !UNICODE | |
2957 | |
2958 #ifdef STRSAFE_INLINE | |
2959 STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...) | |
2960 { | |
2961 HRESULT hr; | |
2962 | |
2963 if (cchDest > STRSAFE_MAX_CCH) | |
2964 { | |
2965 hr = STRSAFE_E_INVALID_PARAMETER; | |
2966 } | |
2967 else | |
2968 { | |
2969 size_t cbDest; | |
2970 va_list argList; | |
2971 | |
2972 // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
2973 cbDest = cchDest * sizeof(char); | |
2974 va_start(argList, pszFormat); | |
2975 | |
2976 hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); | |
2977 | |
2978 va_end(argList); | |
2979 } | |
2980 | |
2981 return hr; | |
2982 } | |
2983 | |
2984 STRSAFEAPI StringCchPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...) | |
2985 { | |
2986 HRESULT hr; | |
2987 | |
2988 if (cchDest > STRSAFE_MAX_CCH) | |
2989 { | |
2990 hr = STRSAFE_E_INVALID_PARAMETER; | |
2991 } | |
2992 else | |
2993 { | |
2994 size_t cbDest; | |
2995 va_list argList; | |
2996 | |
2997 // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
2998 cbDest = cchDest * sizeof(wchar_t); | |
2999 va_start(argList, pszFormat); | |
3000 | |
3001 hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); | |
3002 | |
3003 va_end(argList); | |
3004 } | |
3005 | |
3006 return hr; | |
3007 } | |
3008 #endif // STRSAFE_INLINE | |
3009 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
3010 | |
3011 | |
3012 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
3013 /*++ | |
3014 | |
3015 STDAPI | |
3016 StringCbPrintfEx( | |
3017 OUT LPTSTR pszDest OPTIONAL, | |
3018 IN size_t cbDest, | |
3019 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
3020 OUT size_t* pcbRemaining OPTIONAL, | |
3021 IN DWORD dwFlags, | |
3022 IN LPCTSTR pszFormat OPTIONAL, | |
3023 ... | |
3024 ); | |
3025 | |
3026 Routine Description: | |
3027 | |
3028 This routine is a safer version of the C built-in function 'sprintf' with | |
3029 some additional parameters. In addition to functionality provided by | |
3030 StringCbPrintf, this routine also returns a pointer to the end of the | |
3031 destination string and the number of bytes left in the destination string | |
3032 including the null terminator. The flags parameter allows additional controls. | |
3033 | |
3034 Arguments: | |
3035 | |
3036 pszDest - destination string | |
3037 | |
3038 cbDest - size of destination buffer in bytes. | |
3039 length must be sufficient to contain the resulting | |
3040 formatted string plus the null terminator. | |
3041 | |
3042 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
3043 pointer to the end of the destination string. If the | |
3044 function printed any data, the result will point to the | |
3045 null termination character | |
3046 | |
3047 pcbRemaining - if pcbRemaining is non-null, the function will return | |
3048 the number of bytes left in the destination string, | |
3049 including the null terminator | |
3050 | |
3051 dwFlags - controls some details of the string copy: | |
3052 | |
3053 STRSAFE_FILL_BEHIND_NULL | |
3054 if the function succeeds, the low byte of dwFlags will be | |
3055 used to fill the uninitialize part of destination buffer | |
3056 behind the null terminator | |
3057 | |
3058 STRSAFE_IGNORE_NULLS | |
3059 treat NULL string pointers like empty strings (TEXT("")) | |
3060 | |
3061 STRSAFE_FILL_ON_FAILURE | |
3062 if the function fails, the low byte of dwFlags will be | |
3063 used to fill all of the destination buffer, and it will | |
3064 be null terminated. This will overwrite any truncated | |
3065 string returned when the failure is | |
3066 STRSAFE_E_INSUFFICIENT_BUFFER | |
3067 | |
3068 STRSAFE_NO_TRUNCATION / | |
3069 STRSAFE_NULL_ON_FAILURE | |
3070 if the function fails, the destination buffer will be set | |
3071 to the empty string. This will overwrite any truncated string | |
3072 returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. | |
3073 | |
3074 pszFormat - format string which must be null terminated | |
3075 | |
3076 ... - additional parameters to be formatted according to | |
3077 the format string | |
3078 | |
3079 Notes: | |
3080 Behavior is undefined if destination, format strings or any arguments | |
3081 strings overlap. | |
3082 | |
3083 pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS | |
3084 flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and | |
3085 pszFormat may be NULL. An error may still be returned even though NULLS | |
3086 are ignored due to insufficient space. | |
3087 | |
3088 Return Value: | |
3089 | |
3090 S_OK - if there was source data and it was all concatenated and | |
3091 the resultant dest string was null terminated | |
3092 | |
3093 failure - you can use the macro HRESULT_CODE() to get a win32 | |
3094 error code for all hresult failure cases | |
3095 | |
3096 STRSAFE_E_INSUFFICIENT_BUFFER / | |
3097 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
3098 - this return value is an indication that the print | |
3099 operation failed due to insufficient space. When this | |
3100 error occurs, the destination buffer is modified to | |
3101 contain a truncated version of the ideal result and is | |
3102 null terminated. This is useful for situations where | |
3103 truncation is ok. | |
3104 | |
3105 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
3106 return value of this function | |
3107 | |
3108 --*/ | |
3109 | |
3110 STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...); | |
3111 STRSAFEAPI StringCbPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...); | |
3112 #ifdef UNICODE | |
3113 #define StringCbPrintfEx StringCbPrintfExW | |
3114 #else | |
3115 #define StringCbPrintfEx StringCbPrintfExA | |
3116 #endif // !UNICODE | |
3117 | |
3118 #ifdef STRSAFE_INLINE | |
3119 STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...) | |
3120 { | |
3121 HRESULT hr; | |
3122 size_t cchDest; | |
3123 size_t cchRemaining = 0; | |
3124 | |
3125 cchDest = cbDest / sizeof(char); | |
3126 | |
3127 if (cchDest > STRSAFE_MAX_CCH) | |
3128 { | |
3129 hr = STRSAFE_E_INVALID_PARAMETER; | |
3130 } | |
3131 else | |
3132 { | |
3133 va_list argList; | |
3134 | |
3135 va_start(argList, pszFormat); | |
3136 | |
3137 hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList); | |
3138 | |
3139 va_end(argList); | |
3140 } | |
3141 | |
3142 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
3143 { | |
3144 if (pcbRemaining) | |
3145 { | |
3146 // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
3147 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); | |
3148 } | |
3149 } | |
3150 | |
3151 return hr; | |
3152 } | |
3153 | |
3154 STRSAFEAPI StringCbPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...) | |
3155 { | |
3156 HRESULT hr; | |
3157 size_t cchDest; | |
3158 size_t cchRemaining = 0; | |
3159 | |
3160 cchDest = cbDest / sizeof(wchar_t); | |
3161 | |
3162 if (cchDest > STRSAFE_MAX_CCH) | |
3163 { | |
3164 hr = STRSAFE_E_INVALID_PARAMETER; | |
3165 } | |
3166 else | |
3167 { | |
3168 va_list argList; | |
3169 | |
3170 va_start(argList, pszFormat); | |
3171 | |
3172 hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList); | |
3173 | |
3174 va_end(argList); | |
3175 } | |
3176 | |
3177 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
3178 { | |
3179 if (pcbRemaining) | |
3180 { | |
3181 // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
3182 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); | |
3183 } | |
3184 } | |
3185 | |
3186 return hr; | |
3187 } | |
3188 #endif // STRSAFE_INLINE | |
3189 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
3190 | |
3191 | |
3192 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
3193 /*++ | |
3194 | |
3195 STDAPI | |
3196 StringCchVPrintfEx( | |
3197 OUT LPTSTR pszDest OPTIONAL, | |
3198 IN size_t cchDest, | |
3199 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
3200 OUT size_t* pcchRemaining OPTIONAL, | |
3201 IN DWORD dwFlags, | |
3202 IN LPCTSTR pszFormat OPTIONAL, | |
3203 IN va_list argList | |
3204 ); | |
3205 | |
3206 Routine Description: | |
3207 | |
3208 This routine is a safer version of the C built-in function 'vsprintf' with | |
3209 some additional parameters. In addition to functionality provided by | |
3210 StringCchVPrintf, this routine also returns a pointer to the end of the | |
3211 destination string and the number of characters left in the destination string | |
3212 including the null terminator. The flags parameter allows additional controls. | |
3213 | |
3214 Arguments: | |
3215 | |
3216 pszDest - destination string | |
3217 | |
3218 cchDest - size of destination buffer in characters. | |
3219 length must be sufficient to contain the resulting | |
3220 formatted string plus the null terminator. | |
3221 | |
3222 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
3223 pointer to the end of the destination string. If the | |
3224 function printed any data, the result will point to the | |
3225 null termination character | |
3226 | |
3227 pcchRemaining - if pcchRemaining is non-null, the function will return | |
3228 the number of characters left in the destination string, | |
3229 including the null terminator | |
3230 | |
3231 dwFlags - controls some details of the string copy: | |
3232 | |
3233 STRSAFE_FILL_BEHIND_NULL | |
3234 if the function succeeds, the low byte of dwFlags will be | |
3235 used to fill the uninitialize part of destination buffer | |
3236 behind the null terminator | |
3237 | |
3238 STRSAFE_IGNORE_NULLS | |
3239 treat NULL string pointers like empty strings (TEXT("")) | |
3240 | |
3241 STRSAFE_FILL_ON_FAILURE | |
3242 if the function fails, the low byte of dwFlags will be | |
3243 used to fill all of the destination buffer, and it will | |
3244 be null terminated. This will overwrite any truncated | |
3245 string returned when the failure is | |
3246 STRSAFE_E_INSUFFICIENT_BUFFER | |
3247 | |
3248 STRSAFE_NO_TRUNCATION / | |
3249 STRSAFE_NULL_ON_FAILURE | |
3250 if the function fails, the destination buffer will be set | |
3251 to the empty string. This will overwrite any truncated string | |
3252 returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. | |
3253 | |
3254 pszFormat - format string which must be null terminated | |
3255 | |
3256 argList - va_list from the variable arguments according to the | |
3257 stdarg.h convention | |
3258 | |
3259 Notes: | |
3260 Behavior is undefined if destination, format strings or any arguments | |
3261 strings overlap. | |
3262 | |
3263 pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS | |
3264 flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and | |
3265 pszFormat may be NULL. An error may still be returned even though NULLS | |
3266 are ignored due to insufficient space. | |
3267 | |
3268 Return Value: | |
3269 | |
3270 S_OK - if there was source data and it was all concatenated and | |
3271 the resultant dest string was null terminated | |
3272 | |
3273 failure - you can use the macro HRESULT_CODE() to get a win32 | |
3274 error code for all hresult failure cases | |
3275 | |
3276 STRSAFE_E_INSUFFICIENT_BUFFER / | |
3277 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
3278 - this return value is an indication that the print | |
3279 operation failed due to insufficient space. When this | |
3280 error occurs, the destination buffer is modified to | |
3281 contain a truncated version of the ideal result and is | |
3282 null terminated. This is useful for situations where | |
3283 truncation is ok. | |
3284 | |
3285 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
3286 return value of this function | |
3287 | |
3288 --*/ | |
3289 | |
3290 STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); | |
3291 STRSAFEAPI StringCchVPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList); | |
3292 #ifdef UNICODE | |
3293 #define StringCchVPrintfEx StringCchVPrintfExW | |
3294 #else | |
3295 #define StringCchVPrintfEx StringCchVPrintfExA | |
3296 #endif // !UNICODE | |
3297 | |
3298 #ifdef STRSAFE_INLINE | |
3299 STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList) | |
3300 { | |
3301 HRESULT hr; | |
3302 | |
3303 if (cchDest > STRSAFE_MAX_CCH) | |
3304 { | |
3305 hr = STRSAFE_E_INVALID_PARAMETER; | |
3306 } | |
3307 else | |
3308 { | |
3309 size_t cbDest; | |
3310 | |
3311 // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
3312 cbDest = cchDest * sizeof(char); | |
3313 | |
3314 hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); | |
3315 } | |
3316 | |
3317 return hr; | |
3318 } | |
3319 | |
3320 STRSAFEAPI StringCchVPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList) | |
3321 { | |
3322 HRESULT hr; | |
3323 | |
3324 if (cchDest > STRSAFE_MAX_CCH) | |
3325 { | |
3326 hr = STRSAFE_E_INVALID_PARAMETER; | |
3327 } | |
3328 else | |
3329 { | |
3330 size_t cbDest; | |
3331 | |
3332 // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
3333 cbDest = cchDest * sizeof(wchar_t); | |
3334 | |
3335 hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); | |
3336 } | |
3337 | |
3338 return hr; | |
3339 } | |
3340 #endif // STRSAFE_INLINE | |
3341 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
3342 | |
3343 | |
3344 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
3345 /*++ | |
3346 | |
3347 STDAPI | |
3348 StringCbVPrintfEx( | |
3349 OUT LPTSTR pszDest OPTIONAL, | |
3350 IN size_t cbDest, | |
3351 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
3352 OUT size_t* pcbRemaining OPTIONAL, | |
3353 IN DWORD dwFlags, | |
3354 IN LPCTSTR pszFormat OPTIONAL, | |
3355 IN va_list argList | |
3356 ); | |
3357 | |
3358 Routine Description: | |
3359 | |
3360 This routine is a safer version of the C built-in function 'vsprintf' with | |
3361 some additional parameters. In addition to functionality provided by | |
3362 StringCbVPrintf, this routine also returns a pointer to the end of the | |
3363 destination string and the number of characters left in the destination string | |
3364 including the null terminator. The flags parameter allows additional controls. | |
3365 | |
3366 Arguments: | |
3367 | |
3368 pszDest - destination string | |
3369 | |
3370 cbDest - size of destination buffer in bytes. | |
3371 length must be sufficient to contain the resulting | |
3372 formatted string plus the null terminator. | |
3373 | |
3374 ppszDestEnd - if ppszDestEnd is non-null, the function will return | |
3375 a pointer to the end of the destination string. If the | |
3376 function printed any data, the result will point to the | |
3377 null termination character | |
3378 | |
3379 pcbRemaining - if pcbRemaining is non-null, the function will return | |
3380 the number of bytes left in the destination string, | |
3381 including the null terminator | |
3382 | |
3383 dwFlags - controls some details of the string copy: | |
3384 | |
3385 STRSAFE_FILL_BEHIND_NULL | |
3386 if the function succeeds, the low byte of dwFlags will be | |
3387 used to fill the uninitialize part of destination buffer | |
3388 behind the null terminator | |
3389 | |
3390 STRSAFE_IGNORE_NULLS | |
3391 treat NULL string pointers like empty strings (TEXT("")) | |
3392 | |
3393 STRSAFE_FILL_ON_FAILURE | |
3394 if the function fails, the low byte of dwFlags will be | |
3395 used to fill all of the destination buffer, and it will | |
3396 be null terminated. This will overwrite any truncated | |
3397 string returned when the failure is | |
3398 STRSAFE_E_INSUFFICIENT_BUFFER | |
3399 | |
3400 STRSAFE_NO_TRUNCATION / | |
3401 STRSAFE_NULL_ON_FAILURE | |
3402 if the function fails, the destination buffer will be set | |
3403 to the empty string. This will overwrite any truncated string | |
3404 returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. | |
3405 | |
3406 pszFormat - format string which must be null terminated | |
3407 | |
3408 argList - va_list from the variable arguments according to the | |
3409 stdarg.h convention | |
3410 | |
3411 Notes: | |
3412 Behavior is undefined if destination, format strings or any arguments | |
3413 strings overlap. | |
3414 | |
3415 pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS | |
3416 flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and | |
3417 pszFormat may be NULL. An error may still be returned even though NULLS | |
3418 are ignored due to insufficient space. | |
3419 | |
3420 Return Value: | |
3421 | |
3422 S_OK - if there was source data and it was all concatenated and | |
3423 the resultant dest string was null terminated | |
3424 | |
3425 failure - you can use the macro HRESULT_CODE() to get a win32 | |
3426 error code for all hresult failure cases | |
3427 | |
3428 STRSAFE_E_INSUFFICIENT_BUFFER / | |
3429 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
3430 - this return value is an indication that the print | |
3431 operation failed due to insufficient space. When this | |
3432 error occurs, the destination buffer is modified to | |
3433 contain a truncated version of the ideal result and is | |
3434 null terminated. This is useful for situations where | |
3435 truncation is ok. | |
3436 | |
3437 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
3438 return value of this function | |
3439 | |
3440 --*/ | |
3441 | |
3442 STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); | |
3443 STRSAFEAPI StringCbVPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList); | |
3444 #ifdef UNICODE | |
3445 #define StringCbVPrintfEx StringCbVPrintfExW | |
3446 #else | |
3447 #define StringCbVPrintfEx StringCbVPrintfExA | |
3448 #endif // !UNICODE | |
3449 | |
3450 #ifdef STRSAFE_INLINE | |
3451 STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList) | |
3452 { | |
3453 HRESULT hr; | |
3454 size_t cchDest; | |
3455 size_t cchRemaining = 0; | |
3456 | |
3457 cchDest = cbDest / sizeof(char); | |
3458 | |
3459 if (cchDest > STRSAFE_MAX_CCH) | |
3460 { | |
3461 hr = STRSAFE_E_INVALID_PARAMETER; | |
3462 } | |
3463 else | |
3464 { | |
3465 hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList); | |
3466 } | |
3467 | |
3468 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
3469 { | |
3470 if (pcbRemaining) | |
3471 { | |
3472 // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
3473 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); | |
3474 } | |
3475 } | |
3476 | |
3477 return hr; | |
3478 } | |
3479 | |
3480 STRSAFEAPI StringCbVPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList) | |
3481 { | |
3482 HRESULT hr; | |
3483 size_t cchDest; | |
3484 size_t cchRemaining = 0; | |
3485 | |
3486 cchDest = cbDest / sizeof(wchar_t); | |
3487 | |
3488 if (cchDest > STRSAFE_MAX_CCH) | |
3489 { | |
3490 hr = STRSAFE_E_INVALID_PARAMETER; | |
3491 } | |
3492 else | |
3493 { | |
3494 hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList); | |
3495 } | |
3496 | |
3497 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
3498 { | |
3499 if (pcbRemaining) | |
3500 { | |
3501 // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
3502 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); | |
3503 } | |
3504 } | |
3505 | |
3506 return hr; | |
3507 } | |
3508 #endif // STRSAFE_INLINE | |
3509 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
3510 | |
3511 | |
3512 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
3513 /*++ | |
3514 | |
3515 STDAPI | |
3516 StringCchGets( | |
3517 OUT LPTSTR pszDest, | |
3518 IN size_t cchDest | |
3519 ); | |
3520 | |
3521 Routine Description: | |
3522 | |
3523 This routine is a safer version of the C built-in function 'gets'. | |
3524 The size of the destination buffer (in characters) is a parameter and | |
3525 this function will not write past the end of this buffer and it will | |
3526 ALWAYS null terminate the destination buffer (unless it is zero length). | |
3527 | |
3528 This routine is not a replacement for fgets. That function does not replace | |
3529 newline characters with a null terminator. | |
3530 | |
3531 This function returns a hresult, and not a pointer. It returns | |
3532 S_OK if any characters were read from stdin and copied to pszDest and | |
3533 pszDest was null terminated, otherwise it will return a failure code. | |
3534 | |
3535 Arguments: | |
3536 | |
3537 pszDest - destination string | |
3538 | |
3539 cchDest - size of destination buffer in characters. | |
3540 | |
3541 Notes: | |
3542 pszDest should not be NULL. See StringCchGetsEx if you require the handling | |
3543 of NULL values. | |
3544 | |
3545 cchDest must be > 1 for this function to succeed. | |
3546 | |
3547 Return Value: | |
3548 | |
3549 S_OK - data was read from stdin and copied, and the resultant | |
3550 dest string was null terminated | |
3551 | |
3552 failure - you can use the macro HRESULT_CODE() to get a win32 | |
3553 error code for all hresult failure cases | |
3554 | |
3555 STRSAFE_E_END_OF_FILE / | |
3556 HRESULT_CODE(hr) == ERROR_HANDLE_EOF | |
3557 - this return value indicates an error or end-of-file | |
3558 condition, use feof or ferror to determine which one has | |
3559 occured. | |
3560 | |
3561 STRSAFE_E_INSUFFICIENT_BUFFER / | |
3562 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
3563 - this return value is an indication that there was | |
3564 insufficient space in the destination buffer to copy any | |
3565 data | |
3566 | |
3567 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
3568 return value of this function. | |
3569 | |
3570 --*/ | |
3571 | |
3572 #ifndef STRSAFE_LIB_IMPL | |
3573 STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest); | |
3574 STRSAFE_INLINE_API StringCchGetsW(wchar_t* pszDest, size_t cchDest); | |
3575 #ifdef UNICODE | |
3576 #define StringCchGets StringCchGetsW | |
3577 #else | |
3578 #define StringCchGets StringCchGetsA | |
3579 #endif // !UNICODE | |
3580 | |
3581 STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest) | |
3582 { | |
3583 HRESULT hr; | |
3584 | |
3585 if (cchDest > STRSAFE_MAX_CCH) | |
3586 { | |
3587 hr = STRSAFE_E_INVALID_PARAMETER; | |
3588 } | |
3589 else | |
3590 { | |
3591 size_t cbDest; | |
3592 | |
3593 // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
3594 cbDest = cchDest * sizeof(char); | |
3595 | |
3596 hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, NULL, NULL, 0); | |
3597 } | |
3598 | |
3599 return hr; | |
3600 } | |
3601 | |
3602 STRSAFE_INLINE_API StringCchGetsW(wchar_t* pszDest, size_t cchDest) | |
3603 { | |
3604 HRESULT hr; | |
3605 | |
3606 if (cchDest > STRSAFE_MAX_CCH) | |
3607 { | |
3608 hr = STRSAFE_E_INVALID_PARAMETER; | |
3609 } | |
3610 else | |
3611 { | |
3612 size_t cbDest; | |
3613 | |
3614 // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
3615 cbDest = cchDest * sizeof(wchar_t); | |
3616 | |
3617 hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, NULL, NULL, 0); | |
3618 } | |
3619 | |
3620 return hr; | |
3621 } | |
3622 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
3623 #endif // !STRSAFE_LIB_IMPL | |
3624 | |
3625 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
3626 /*++ | |
3627 | |
3628 STDAPI | |
3629 StringCbGets( | |
3630 OUT LPTSTR pszDest, | |
3631 IN size_t cbDest | |
3632 ); | |
3633 | |
3634 Routine Description: | |
3635 | |
3636 This routine is a safer version of the C built-in function 'gets'. | |
3637 The size of the destination buffer (in bytes) is a parameter and | |
3638 this function will not write past the end of this buffer and it will | |
3639 ALWAYS null terminate the destination buffer (unless it is zero length). | |
3640 | |
3641 This routine is not a replacement for fgets. That function does not replace | |
3642 newline characters with a null terminator. | |
3643 | |
3644 This function returns a hresult, and not a pointer. It returns | |
3645 S_OK if any characters were read from stdin and copied to pszDest | |
3646 and pszDest was null terminated, otherwise it will return a failure code. | |
3647 | |
3648 Arguments: | |
3649 | |
3650 pszDest - destination string | |
3651 | |
3652 cbDest - size of destination buffer in bytes. | |
3653 | |
3654 Notes: | |
3655 pszDest should not be NULL. See StringCbGetsEx if you require the handling | |
3656 of NULL values. | |
3657 | |
3658 cbDest must be > sizeof(TCHAR) for this function to succeed. | |
3659 | |
3660 Return Value: | |
3661 | |
3662 S_OK - data was read from stdin and copied, and the resultant | |
3663 dest string was null terminated | |
3664 | |
3665 failure - you can use the macro HRESULT_CODE() to get a win32 | |
3666 error code for all hresult failure cases | |
3667 | |
3668 STRSAFE_E_END_OF_FILE / | |
3669 HRESULT_CODE(hr) == ERROR_HANDLE_EOF | |
3670 - this return value indicates an error or end-of-file | |
3671 condition, use feof or ferror to determine which one has | |
3672 occured. | |
3673 | |
3674 STRSAFE_E_INSUFFICIENT_BUFFER / | |
3675 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
3676 - this return value is an indication that there was | |
3677 insufficient space in the destination buffer to copy any | |
3678 data | |
3679 | |
3680 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
3681 return value of this function. | |
3682 | |
3683 --*/ | |
3684 | |
3685 #ifndef STRSAFE_LIB_IMPL | |
3686 STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest); | |
3687 STRSAFE_INLINE_API StringCbGetsW(wchar_t* pszDest, size_t cbDest); | |
3688 #ifdef UNICODE | |
3689 #define StringCbGets StringCbGetsW | |
3690 #else | |
3691 #define StringCbGets StringCbGetsA | |
3692 #endif // !UNICODE | |
3693 | |
3694 STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest) | |
3695 { | |
3696 HRESULT hr; | |
3697 size_t cchDest; | |
3698 | |
3699 // convert to count of characters | |
3700 cchDest = cbDest / sizeof(char); | |
3701 | |
3702 if (cchDest > STRSAFE_MAX_CCH) | |
3703 { | |
3704 hr = STRSAFE_E_INVALID_PARAMETER; | |
3705 } | |
3706 else | |
3707 { | |
3708 hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, NULL, NULL, 0); | |
3709 } | |
3710 | |
3711 return hr; | |
3712 } | |
3713 | |
3714 STRSAFE_INLINE_API StringCbGetsW(wchar_t* pszDest, size_t cbDest) | |
3715 { | |
3716 HRESULT hr; | |
3717 size_t cchDest; | |
3718 | |
3719 // convert to count of characters | |
3720 cchDest = cbDest / sizeof(wchar_t); | |
3721 | |
3722 if (cchDest > STRSAFE_MAX_CCH) | |
3723 { | |
3724 hr = STRSAFE_E_INVALID_PARAMETER; | |
3725 } | |
3726 else | |
3727 { | |
3728 hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, NULL, NULL, 0); | |
3729 } | |
3730 | |
3731 return hr; | |
3732 } | |
3733 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
3734 #endif // !STRSAFE_LIB_IMPL | |
3735 | |
3736 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
3737 /*++ | |
3738 | |
3739 STDAPI | |
3740 StringCchGetsEx( | |
3741 OUT LPTSTR pszDest OPTIONAL, | |
3742 IN size_t cchDest, | |
3743 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
3744 OUT size_t* pcchRemaining OPTIONAL, | |
3745 IN DWORD dwFlags | |
3746 ); | |
3747 | |
3748 Routine Description: | |
3749 | |
3750 This routine is a safer version of the C built-in function 'gets' with | |
3751 some additional parameters. In addition to functionality provided by | |
3752 StringCchGets, this routine also returns a pointer to the end of the | |
3753 destination string and the number of characters left in the destination string | |
3754 including the null terminator. The flags parameter allows additional controls. | |
3755 | |
3756 Arguments: | |
3757 | |
3758 pszDest - destination string | |
3759 | |
3760 cchDest - size of destination buffer in characters. | |
3761 | |
3762 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
3763 pointer to the end of the destination string. If the | |
3764 function copied any data, the result will point to the | |
3765 null termination character | |
3766 | |
3767 pcchRemaining - if pcchRemaining is non-null, the function will return the | |
3768 number of characters left in the destination string, | |
3769 including the null terminator | |
3770 | |
3771 dwFlags - controls some details of the string copy: | |
3772 | |
3773 STRSAFE_FILL_BEHIND_NULL | |
3774 if the function succeeds, the low byte of dwFlags will be | |
3775 used to fill the uninitialize part of destination buffer | |
3776 behind the null terminator | |
3777 | |
3778 STRSAFE_IGNORE_NULLS | |
3779 treat NULL string pointers like empty strings (TEXT("")). | |
3780 | |
3781 STRSAFE_FILL_ON_FAILURE | |
3782 if the function fails, the low byte of dwFlags will be | |
3783 used to fill all of the destination buffer, and it will | |
3784 be null terminated. | |
3785 | |
3786 STRSAFE_NO_TRUNCATION / | |
3787 STRSAFE_NULL_ON_FAILURE | |
3788 if the function fails, the destination buffer will be set | |
3789 to the empty string. | |
3790 | |
3791 Notes: | |
3792 pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified. | |
3793 If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be | |
3794 returned even though NULLS are ignored | |
3795 | |
3796 cchDest must be > 1 for this function to succeed. | |
3797 | |
3798 Return Value: | |
3799 | |
3800 S_OK - data was read from stdin and copied, and the resultant | |
3801 dest string was null terminated | |
3802 | |
3803 failure - you can use the macro HRESULT_CODE() to get a win32 | |
3804 error code for all hresult failure cases | |
3805 | |
3806 STRSAFE_E_END_OF_FILE / | |
3807 HRESULT_CODE(hr) == ERROR_HANDLE_EOF | |
3808 - this return value indicates an error or end-of-file | |
3809 condition, use feof or ferror to determine which one has | |
3810 occured. | |
3811 | |
3812 STRSAFE_E_INSUFFICIENT_BUFFER / | |
3813 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
3814 - this return value is an indication that there was | |
3815 insufficient space in the destination buffer to copy any | |
3816 data | |
3817 | |
3818 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
3819 return value of this function. | |
3820 | |
3821 --*/ | |
3822 | |
3823 #ifndef STRSAFE_LIB_IMPL | |
3824 STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
3825 STRSAFE_INLINE_API StringCchGetsExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); | |
3826 #ifdef UNICODE | |
3827 #define StringCchGetsEx StringCchGetsExW | |
3828 #else | |
3829 #define StringCchGetsEx StringCchGetsExA | |
3830 #endif // !UNICODE | |
3831 | |
3832 STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
3833 { | |
3834 HRESULT hr; | |
3835 | |
3836 if (cchDest > STRSAFE_MAX_CCH) | |
3837 { | |
3838 hr = STRSAFE_E_INVALID_PARAMETER; | |
3839 } | |
3840 else | |
3841 { | |
3842 size_t cbDest; | |
3843 | |
3844 // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
3845 cbDest = cchDest * sizeof(char); | |
3846 | |
3847 hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags); | |
3848 } | |
3849 | |
3850 return hr; | |
3851 } | |
3852 | |
3853 STRSAFE_INLINE_API StringCchGetsExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
3854 { | |
3855 HRESULT hr; | |
3856 | |
3857 if (cchDest > STRSAFE_MAX_CCH) | |
3858 { | |
3859 hr = STRSAFE_E_INVALID_PARAMETER; | |
3860 } | |
3861 else | |
3862 { | |
3863 size_t cbDest; | |
3864 | |
3865 // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
3866 cbDest = cchDest * sizeof(wchar_t); | |
3867 | |
3868 hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags); | |
3869 } | |
3870 | |
3871 return hr; | |
3872 } | |
3873 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
3874 #endif // !STRSAFE_LIB_IMPL | |
3875 | |
3876 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
3877 /*++ | |
3878 | |
3879 STDAPI | |
3880 StringCbGetsEx( | |
3881 OUT LPTSTR pszDest OPTIONAL, | |
3882 IN size_t cbDest, | |
3883 OUT LPTSTR* ppszDestEnd OPTIONAL, | |
3884 OUT size_t* pcbRemaining OPTIONAL, | |
3885 IN DWORD dwFlags | |
3886 ); | |
3887 | |
3888 Routine Description: | |
3889 | |
3890 This routine is a safer version of the C built-in function 'gets' with | |
3891 some additional parameters. In addition to functionality provided by | |
3892 StringCbGets, this routine also returns a pointer to the end of the | |
3893 destination string and the number of characters left in the destination string | |
3894 including the null terminator. The flags parameter allows additional controls. | |
3895 | |
3896 Arguments: | |
3897 | |
3898 pszDest - destination string | |
3899 | |
3900 cbDest - size of destination buffer in bytes. | |
3901 | |
3902 ppszDestEnd - if ppszDestEnd is non-null, the function will return a | |
3903 pointer to the end of the destination string. If the | |
3904 function copied any data, the result will point to the | |
3905 null termination character | |
3906 | |
3907 pcbRemaining - if pbRemaining is non-null, the function will return the | |
3908 number of bytes left in the destination string, | |
3909 including the null terminator | |
3910 | |
3911 dwFlags - controls some details of the string copy: | |
3912 | |
3913 STRSAFE_FILL_BEHIND_NULL | |
3914 if the function succeeds, the low byte of dwFlags will be | |
3915 used to fill the uninitialize part of destination buffer | |
3916 behind the null terminator | |
3917 | |
3918 STRSAFE_IGNORE_NULLS | |
3919 treat NULL string pointers like empty strings (TEXT("")). | |
3920 | |
3921 STRSAFE_FILL_ON_FAILURE | |
3922 if the function fails, the low byte of dwFlags will be | |
3923 used to fill all of the destination buffer, and it will | |
3924 be null terminated. | |
3925 | |
3926 STRSAFE_NO_TRUNCATION / | |
3927 STRSAFE_NULL_ON_FAILURE | |
3928 if the function fails, the destination buffer will be set | |
3929 to the empty string. | |
3930 | |
3931 Notes: | |
3932 pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified. | |
3933 If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be | |
3934 returned even though NULLS are ignored | |
3935 | |
3936 cbDest must be > sizeof(TCHAR) for this function to succeed | |
3937 | |
3938 Return Value: | |
3939 | |
3940 S_OK - data was read from stdin and copied, and the resultant | |
3941 dest string was null terminated | |
3942 | |
3943 failure - you can use the macro HRESULT_CODE() to get a win32 | |
3944 error code for all hresult failure cases | |
3945 | |
3946 STRSAFE_E_END_OF_FILE / | |
3947 HRESULT_CODE(hr) == ERROR_HANDLE_EOF | |
3948 - this return value indicates an error or end-of-file | |
3949 condition, use feof or ferror to determine which one has | |
3950 occured. | |
3951 | |
3952 STRSAFE_E_INSUFFICIENT_BUFFER / | |
3953 HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER | |
3954 - this return value is an indication that there was | |
3955 insufficient space in the destination buffer to copy any | |
3956 data | |
3957 | |
3958 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
3959 return value of this function. | |
3960 | |
3961 --*/ | |
3962 | |
3963 #ifndef STRSAFE_LIB_IMPL | |
3964 STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pbRemaining, unsigned long dwFlags); | |
3965 STRSAFE_INLINE_API StringCbGetsExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); | |
3966 #ifdef UNICODE | |
3967 #define StringCbGetsEx StringCbGetsExW | |
3968 #else | |
3969 #define StringCbGetsEx StringCbGetsExA | |
3970 #endif // !UNICODE | |
3971 | |
3972 STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) | |
3973 { | |
3974 HRESULT hr; | |
3975 size_t cchDest; | |
3976 size_t cchRemaining = 0; | |
3977 | |
3978 cchDest = cbDest / sizeof(char); | |
3979 | |
3980 if (cchDest > STRSAFE_MAX_CCH) | |
3981 { | |
3982 hr = STRSAFE_E_INVALID_PARAMETER; | |
3983 } | |
3984 else | |
3985 { | |
3986 hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags); | |
3987 } | |
3988 | |
3989 if (SUCCEEDED(hr) || | |
3990 (hr == STRSAFE_E_INSUFFICIENT_BUFFER) || | |
3991 (hr == STRSAFE_E_END_OF_FILE)) | |
3992 { | |
3993 if (pcbRemaining) | |
3994 { | |
3995 // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
3996 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); | |
3997 } | |
3998 } | |
3999 | |
4000 return hr; | |
4001 } | |
4002 | |
4003 STRSAFE_INLINE_API StringCbGetsExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) | |
4004 { | |
4005 HRESULT hr; | |
4006 size_t cchDest; | |
4007 size_t cchRemaining = 0; | |
4008 | |
4009 cchDest = cbDest / sizeof(wchar_t); | |
4010 | |
4011 if (cchDest > STRSAFE_MAX_CCH) | |
4012 { | |
4013 hr = STRSAFE_E_INVALID_PARAMETER; | |
4014 } | |
4015 else | |
4016 { | |
4017 hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags); | |
4018 } | |
4019 | |
4020 if (SUCCEEDED(hr) || | |
4021 (hr == STRSAFE_E_INSUFFICIENT_BUFFER) || | |
4022 (hr == STRSAFE_E_END_OF_FILE)) | |
4023 { | |
4024 if (pcbRemaining) | |
4025 { | |
4026 // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
4027 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); | |
4028 } | |
4029 } | |
4030 | |
4031 return hr; | |
4032 } | |
4033 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
4034 #endif // !STRSAFE_LIB_IMPL | |
4035 | |
4036 #ifndef STRSAFE_NO_CCH_FUNCTIONS | |
4037 /*++ | |
4038 | |
4039 STDAPI | |
4040 StringCchLength( | |
4041 IN LPCTSTR psz, | |
4042 IN size_t cchMax, | |
4043 OUT size_t* pcch OPTIONAL | |
4044 ); | |
4045 | |
4046 Routine Description: | |
4047 | |
4048 This routine is a safer version of the C built-in function 'strlen'. | |
4049 It is used to make sure a string is not larger than a given length, and | |
4050 it optionally returns the current length in characters not including | |
4051 the null terminator. | |
4052 | |
4053 This function returns a hresult, and not a pointer. It returns | |
4054 S_OK if the string is non-null and the length including the null | |
4055 terminator is less than or equal to cchMax characters. | |
4056 | |
4057 Arguments: | |
4058 | |
4059 psz - string to check the length of | |
4060 | |
4061 cchMax - maximum number of characters including the null terminator | |
4062 that psz is allowed to contain | |
4063 | |
4064 pcch - if the function succeeds and pcch is non-null, the current length | |
4065 in characters of psz excluding the null terminator will be returned. | |
4066 This out parameter is equivalent to the return value of strlen(psz) | |
4067 | |
4068 Notes: | |
4069 psz can be null but the function will fail | |
4070 | |
4071 cchMax should be greater than zero or the function will fail | |
4072 | |
4073 Return Value: | |
4074 | |
4075 S_OK - psz is non-null and the length including the null | |
4076 terminator is less than or equal to cchMax characters | |
4077 | |
4078 failure - you can use the macro HRESULT_CODE() to get a win32 | |
4079 error code for all hresult failure cases | |
4080 | |
4081 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
4082 return value of this function. | |
4083 | |
4084 --*/ | |
4085 | |
4086 STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch); | |
4087 STRSAFEAPI StringCchLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch); | |
4088 #ifdef UNICODE | |
4089 #define StringCchLength StringCchLengthW | |
4090 #else | |
4091 #define StringCchLength StringCchLengthA | |
4092 #endif // !UNICODE | |
4093 | |
4094 #ifdef STRSAFE_INLINE | |
4095 STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch) | |
4096 { | |
4097 HRESULT hr; | |
4098 | |
4099 if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) | |
4100 { | |
4101 hr = STRSAFE_E_INVALID_PARAMETER; | |
4102 } | |
4103 else | |
4104 { | |
4105 hr = StringLengthWorkerA(psz, cchMax, pcch); | |
4106 } | |
4107 | |
4108 return hr; | |
4109 } | |
4110 | |
4111 STRSAFEAPI StringCchLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch) | |
4112 { | |
4113 HRESULT hr; | |
4114 | |
4115 if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) | |
4116 { | |
4117 hr = STRSAFE_E_INVALID_PARAMETER; | |
4118 } | |
4119 else | |
4120 { | |
4121 hr = StringLengthWorkerW(psz, cchMax, pcch); | |
4122 } | |
4123 | |
4124 return hr; | |
4125 } | |
4126 #endif // STRSAFE_INLINE | |
4127 #endif // !STRSAFE_NO_CCH_FUNCTIONS | |
4128 | |
4129 | |
4130 #ifndef STRSAFE_NO_CB_FUNCTIONS | |
4131 /*++ | |
4132 | |
4133 STDAPI | |
4134 StringCbLength( | |
4135 IN LPCTSTR psz, | |
4136 IN size_t cbMax, | |
4137 OUT size_t* pcb OPTIONAL | |
4138 ); | |
4139 | |
4140 Routine Description: | |
4141 | |
4142 This routine is a safer version of the C built-in function 'strlen'. | |
4143 It is used to make sure a string is not larger than a given length, and | |
4144 it optionally returns the current length in bytes not including | |
4145 the null terminator. | |
4146 | |
4147 This function returns a hresult, and not a pointer. It returns | |
4148 S_OK if the string is non-null and the length including the null | |
4149 terminator is less than or equal to cbMax bytes. | |
4150 | |
4151 Arguments: | |
4152 | |
4153 psz - string to check the length of | |
4154 | |
4155 cbMax - maximum number of bytes including the null terminator | |
4156 that psz is allowed to contain | |
4157 | |
4158 pcb - if the function succeeds and pcb is non-null, the current length | |
4159 in bytes of psz excluding the null terminator will be returned. | |
4160 This out parameter is equivalent to the return value of strlen(psz) * sizeof(TCHAR) | |
4161 | |
4162 Notes: | |
4163 psz can be null but the function will fail | |
4164 | |
4165 cbMax should be greater than or equal to sizeof(TCHAR) or the function will fail | |
4166 | |
4167 Return Value: | |
4168 | |
4169 S_OK - psz is non-null and the length including the null | |
4170 terminator is less than or equal to cbMax bytes | |
4171 | |
4172 failure - you can use the macro HRESULT_CODE() to get a win32 | |
4173 error code for all hresult failure cases | |
4174 | |
4175 It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the | |
4176 return value of this function. | |
4177 | |
4178 --*/ | |
4179 | |
4180 STRSAFEAPI StringCbLengthA(const char* psz, size_t cchMax, size_t* pcch); | |
4181 STRSAFEAPI StringCbLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch); | |
4182 #ifdef UNICODE | |
4183 #define StringCbLength StringCbLengthW | |
4184 #else | |
4185 #define StringCbLength StringCbLengthA | |
4186 #endif // !UNICODE | |
4187 | |
4188 #ifdef STRSAFE_INLINE | |
4189 STRSAFEAPI StringCbLengthA(const char* psz, size_t cbMax, size_t* pcb) | |
4190 { | |
4191 HRESULT hr; | |
4192 size_t cchMax; | |
4193 size_t cch = 0; | |
4194 | |
4195 cchMax = cbMax / sizeof(char); | |
4196 | |
4197 if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) | |
4198 { | |
4199 hr = STRSAFE_E_INVALID_PARAMETER; | |
4200 } | |
4201 else | |
4202 { | |
4203 hr = StringLengthWorkerA(psz, cchMax, &cch); | |
4204 } | |
4205 | |
4206 if (SUCCEEDED(hr) && pcb) | |
4207 { | |
4208 // safe to multiply cch * sizeof(char) since cch < STRSAFE_MAX_CCH and sizeof(char) is 1 | |
4209 *pcb = cch * sizeof(char); | |
4210 } | |
4211 | |
4212 return hr; | |
4213 } | |
4214 | |
4215 STRSAFEAPI StringCbLengthW(const wchar_t* psz, size_t cbMax, size_t* pcb) | |
4216 { | |
4217 HRESULT hr; | |
4218 size_t cchMax; | |
4219 size_t cch = 0; | |
4220 | |
4221 cchMax = cbMax / sizeof(wchar_t); | |
4222 | |
4223 if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) | |
4224 { | |
4225 hr = STRSAFE_E_INVALID_PARAMETER; | |
4226 } | |
4227 else | |
4228 { | |
4229 hr = StringLengthWorkerW(psz, cchMax, &cch); | |
4230 } | |
4231 | |
4232 if (SUCCEEDED(hr) && pcb) | |
4233 { | |
4234 // safe to multiply cch * sizeof(wchar_t) since cch < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 | |
4235 *pcb = cch * sizeof(wchar_t); | |
4236 } | |
4237 | |
4238 return hr; | |
4239 } | |
4240 #endif // STRSAFE_INLINE | |
4241 #endif // !STRSAFE_NO_CB_FUNCTIONS | |
4242 | |
4243 | |
4244 // these are the worker functions that actually do the work | |
4245 #ifdef STRSAFE_INLINE | |
4246 STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) | |
4247 { | |
4248 HRESULT hr = S_OK; | |
4249 | |
4250 if (cchDest == 0) | |
4251 { | |
4252 // can not null terminate a zero-byte dest buffer | |
4253 hr = STRSAFE_E_INVALID_PARAMETER; | |
4254 } | |
4255 else | |
4256 { | |
4257 while (cchDest && (*pszSrc != '\0')) | |
4258 { | |
4259 *pszDest++ = *pszSrc++; | |
4260 cchDest--; | |
4261 } | |
4262 | |
4263 if (cchDest == 0) | |
4264 { | |
4265 // we are going to truncate pszDest | |
4266 pszDest--; | |
4267 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4268 } | |
4269 | |
4270 *pszDest= '\0'; | |
4271 } | |
4272 | |
4273 return hr; | |
4274 } | |
4275 | |
4276 STRSAFEAPI StringCopyWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) | |
4277 { | |
4278 HRESULT hr = S_OK; | |
4279 | |
4280 if (cchDest == 0) | |
4281 { | |
4282 // can not null terminate a zero-byte dest buffer | |
4283 hr = STRSAFE_E_INVALID_PARAMETER; | |
4284 } | |
4285 else | |
4286 { | |
4287 while (cchDest && (*pszSrc != L'\0')) | |
4288 { | |
4289 *pszDest++ = *pszSrc++; | |
4290 cchDest--; | |
4291 } | |
4292 | |
4293 if (cchDest == 0) | |
4294 { | |
4295 // we are going to truncate pszDest | |
4296 pszDest--; | |
4297 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4298 } | |
4299 | |
4300 *pszDest= L'\0'; | |
4301 } | |
4302 | |
4303 return hr; | |
4304 } | |
4305 | |
4306 STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
4307 { | |
4308 HRESULT hr = S_OK; | |
4309 char* pszDestEnd = pszDest; | |
4310 size_t cchRemaining = 0; | |
4311 | |
4312 // ASSERT(cbDest == (cchDest * sizeof(char)) || | |
4313 // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); | |
4314 | |
4315 // only accept valid flags | |
4316 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
4317 { | |
4318 hr = STRSAFE_E_INVALID_PARAMETER; | |
4319 } | |
4320 else | |
4321 { | |
4322 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
4323 { | |
4324 if (pszDest == NULL) | |
4325 { | |
4326 if ((cchDest != 0) || (cbDest != 0)) | |
4327 { | |
4328 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
4329 hr = STRSAFE_E_INVALID_PARAMETER; | |
4330 } | |
4331 } | |
4332 | |
4333 if (pszSrc == NULL) | |
4334 { | |
4335 pszSrc = ""; | |
4336 } | |
4337 } | |
4338 | |
4339 if (SUCCEEDED(hr)) | |
4340 { | |
4341 if (cchDest == 0) | |
4342 { | |
4343 pszDestEnd = pszDest; | |
4344 cchRemaining = 0; | |
4345 | |
4346 // only fail if there was actually src data to copy | |
4347 if (*pszSrc != '\0') | |
4348 { | |
4349 if (pszDest == NULL) | |
4350 { | |
4351 hr = STRSAFE_E_INVALID_PARAMETER; | |
4352 } | |
4353 else | |
4354 { | |
4355 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4356 } | |
4357 } | |
4358 } | |
4359 else | |
4360 { | |
4361 pszDestEnd = pszDest; | |
4362 cchRemaining = cchDest; | |
4363 | |
4364 while (cchRemaining && (*pszSrc != '\0')) | |
4365 { | |
4366 *pszDestEnd++= *pszSrc++; | |
4367 cchRemaining--; | |
4368 } | |
4369 | |
4370 if (cchRemaining > 0) | |
4371 { | |
4372 if (dwFlags & STRSAFE_FILL_BEHIND_NULL) | |
4373 { | |
4374 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char))); | |
4375 } | |
4376 } | |
4377 else | |
4378 { | |
4379 // we are going to truncate pszDest | |
4380 pszDestEnd--; | |
4381 cchRemaining++; | |
4382 | |
4383 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4384 } | |
4385 | |
4386 *pszDestEnd = '\0'; | |
4387 } | |
4388 } | |
4389 } | |
4390 | |
4391 if (FAILED(hr)) | |
4392 { | |
4393 if (pszDest) | |
4394 { | |
4395 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
4396 { | |
4397 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
4398 | |
4399 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
4400 { | |
4401 pszDestEnd = pszDest; | |
4402 cchRemaining = cchDest; | |
4403 } | |
4404 else if (cchDest > 0) | |
4405 { | |
4406 pszDestEnd = pszDest + cchDest - 1; | |
4407 cchRemaining = 1; | |
4408 | |
4409 // null terminate the end of the string | |
4410 *pszDestEnd = '\0'; | |
4411 } | |
4412 } | |
4413 | |
4414 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) | |
4415 { | |
4416 if (cchDest > 0) | |
4417 { | |
4418 pszDestEnd = pszDest; | |
4419 cchRemaining = cchDest; | |
4420 | |
4421 // null terminate the beginning of the string | |
4422 *pszDestEnd = '\0'; | |
4423 } | |
4424 } | |
4425 } | |
4426 } | |
4427 | |
4428 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
4429 { | |
4430 if (ppszDestEnd) | |
4431 { | |
4432 *ppszDestEnd = pszDestEnd; | |
4433 } | |
4434 | |
4435 if (pcchRemaining) | |
4436 { | |
4437 *pcchRemaining = cchRemaining; | |
4438 } | |
4439 } | |
4440 | |
4441 return hr; | |
4442 } | |
4443 | |
4444 STRSAFEAPI StringCopyExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
4445 { | |
4446 HRESULT hr = S_OK; | |
4447 wchar_t* pszDestEnd = pszDest; | |
4448 size_t cchRemaining = 0; | |
4449 | |
4450 // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || | |
4451 // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); | |
4452 | |
4453 // only accept valid flags | |
4454 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
4455 { | |
4456 hr = STRSAFE_E_INVALID_PARAMETER; | |
4457 } | |
4458 else | |
4459 { | |
4460 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
4461 { | |
4462 if (pszDest == NULL) | |
4463 { | |
4464 if ((cchDest != 0) || (cbDest != 0)) | |
4465 { | |
4466 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
4467 hr = STRSAFE_E_INVALID_PARAMETER; | |
4468 } | |
4469 } | |
4470 | |
4471 if (pszSrc == NULL) | |
4472 { | |
4473 pszSrc = L""; | |
4474 } | |
4475 } | |
4476 | |
4477 if (SUCCEEDED(hr)) | |
4478 { | |
4479 if (cchDest == 0) | |
4480 { | |
4481 pszDestEnd = pszDest; | |
4482 cchRemaining = 0; | |
4483 | |
4484 // only fail if there was actually src data to copy | |
4485 if (*pszSrc != L'\0') | |
4486 { | |
4487 if (pszDest == NULL) | |
4488 { | |
4489 hr = STRSAFE_E_INVALID_PARAMETER; | |
4490 } | |
4491 else | |
4492 { | |
4493 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4494 } | |
4495 } | |
4496 } | |
4497 else | |
4498 { | |
4499 pszDestEnd = pszDest; | |
4500 cchRemaining = cchDest; | |
4501 | |
4502 while (cchRemaining && (*pszSrc != L'\0')) | |
4503 { | |
4504 *pszDestEnd++= *pszSrc++; | |
4505 cchRemaining--; | |
4506 } | |
4507 | |
4508 if (cchRemaining > 0) | |
4509 { | |
4510 if (dwFlags & STRSAFE_FILL_BEHIND_NULL) | |
4511 { | |
4512 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); | |
4513 } | |
4514 } | |
4515 else | |
4516 { | |
4517 // we are going to truncate pszDest | |
4518 pszDestEnd--; | |
4519 cchRemaining++; | |
4520 | |
4521 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4522 } | |
4523 | |
4524 *pszDestEnd = L'\0'; | |
4525 } | |
4526 } | |
4527 } | |
4528 | |
4529 if (FAILED(hr)) | |
4530 { | |
4531 if (pszDest) | |
4532 { | |
4533 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
4534 { | |
4535 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
4536 | |
4537 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
4538 { | |
4539 pszDestEnd = pszDest; | |
4540 cchRemaining = cchDest; | |
4541 } | |
4542 else if (cchDest > 0) | |
4543 { | |
4544 pszDestEnd = pszDest + cchDest - 1; | |
4545 cchRemaining = 1; | |
4546 | |
4547 // null terminate the end of the string | |
4548 *pszDestEnd = L'\0'; | |
4549 } | |
4550 } | |
4551 | |
4552 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) | |
4553 { | |
4554 if (cchDest > 0) | |
4555 { | |
4556 pszDestEnd = pszDest; | |
4557 cchRemaining = cchDest; | |
4558 | |
4559 // null terminate the beginning of the string | |
4560 *pszDestEnd = L'\0'; | |
4561 } | |
4562 } | |
4563 } | |
4564 } | |
4565 | |
4566 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
4567 { | |
4568 if (ppszDestEnd) | |
4569 { | |
4570 *ppszDestEnd = pszDestEnd; | |
4571 } | |
4572 | |
4573 if (pcchRemaining) | |
4574 { | |
4575 *pcchRemaining = cchRemaining; | |
4576 } | |
4577 } | |
4578 | |
4579 return hr; | |
4580 } | |
4581 | |
4582 STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc) | |
4583 { | |
4584 HRESULT hr = S_OK; | |
4585 | |
4586 if (cchDest == 0) | |
4587 { | |
4588 // can not null terminate a zero-byte dest buffer | |
4589 hr = STRSAFE_E_INVALID_PARAMETER; | |
4590 } | |
4591 else | |
4592 { | |
4593 while (cchDest && cchSrc && (*pszSrc != '\0')) | |
4594 { | |
4595 *pszDest++= *pszSrc++; | |
4596 cchDest--; | |
4597 cchSrc--; | |
4598 } | |
4599 | |
4600 if (cchDest == 0) | |
4601 { | |
4602 // we are going to truncate pszDest | |
4603 pszDest--; | |
4604 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4605 } | |
4606 | |
4607 *pszDest= '\0'; | |
4608 } | |
4609 | |
4610 return hr; | |
4611 } | |
4612 | |
4613 STRSAFEAPI StringCopyNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc) | |
4614 { | |
4615 HRESULT hr = S_OK; | |
4616 | |
4617 if (cchDest == 0) | |
4618 { | |
4619 // can not null terminate a zero-byte dest buffer | |
4620 hr = STRSAFE_E_INVALID_PARAMETER; | |
4621 } | |
4622 else | |
4623 { | |
4624 while (cchDest && cchSrc && (*pszSrc != L'\0')) | |
4625 { | |
4626 *pszDest++= *pszSrc++; | |
4627 cchDest--; | |
4628 cchSrc--; | |
4629 } | |
4630 | |
4631 if (cchDest == 0) | |
4632 { | |
4633 // we are going to truncate pszDest | |
4634 pszDest--; | |
4635 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4636 } | |
4637 | |
4638 *pszDest= L'\0'; | |
4639 } | |
4640 | |
4641 return hr; | |
4642 } | |
4643 | |
4644 STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
4645 { | |
4646 HRESULT hr = S_OK; | |
4647 char* pszDestEnd = pszDest; | |
4648 size_t cchRemaining = 0; | |
4649 | |
4650 // ASSERT(cbDest == (cchDest * sizeof(char)) || | |
4651 // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); | |
4652 | |
4653 // only accept valid flags | |
4654 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
4655 { | |
4656 hr = STRSAFE_E_INVALID_PARAMETER; | |
4657 } | |
4658 else | |
4659 { | |
4660 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
4661 { | |
4662 if (pszDest == NULL) | |
4663 { | |
4664 if ((cchDest != 0) || (cbDest != 0)) | |
4665 { | |
4666 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
4667 hr = STRSAFE_E_INVALID_PARAMETER; | |
4668 } | |
4669 } | |
4670 | |
4671 if (pszSrc == NULL) | |
4672 { | |
4673 pszSrc = ""; | |
4674 } | |
4675 } | |
4676 | |
4677 if (SUCCEEDED(hr)) | |
4678 { | |
4679 if (cchDest == 0) | |
4680 { | |
4681 pszDestEnd = pszDest; | |
4682 cchRemaining = 0; | |
4683 | |
4684 // only fail if there was actually src data to copy | |
4685 if (*pszSrc != '\0') | |
4686 { | |
4687 if (pszDest == NULL) | |
4688 { | |
4689 hr = STRSAFE_E_INVALID_PARAMETER; | |
4690 } | |
4691 else | |
4692 { | |
4693 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4694 } | |
4695 } | |
4696 } | |
4697 else | |
4698 { | |
4699 pszDestEnd = pszDest; | |
4700 cchRemaining = cchDest; | |
4701 | |
4702 while (cchRemaining && cchSrc && (*pszSrc != '\0')) | |
4703 { | |
4704 *pszDestEnd++= *pszSrc++; | |
4705 cchRemaining--; | |
4706 cchSrc--; | |
4707 } | |
4708 | |
4709 if (cchRemaining > 0) | |
4710 { | |
4711 if (dwFlags & STRSAFE_FILL_BEHIND_NULL) | |
4712 { | |
4713 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char))); | |
4714 } | |
4715 } | |
4716 else | |
4717 { | |
4718 // we are going to truncate pszDest | |
4719 pszDestEnd--; | |
4720 cchRemaining++; | |
4721 | |
4722 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4723 } | |
4724 | |
4725 *pszDestEnd = '\0'; | |
4726 } | |
4727 } | |
4728 } | |
4729 | |
4730 if (FAILED(hr)) | |
4731 { | |
4732 if (pszDest) | |
4733 { | |
4734 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
4735 { | |
4736 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
4737 | |
4738 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
4739 { | |
4740 pszDestEnd = pszDest; | |
4741 cchRemaining = cchDest; | |
4742 } | |
4743 else if (cchDest > 0) | |
4744 { | |
4745 pszDestEnd = pszDest + cchDest - 1; | |
4746 cchRemaining = 1; | |
4747 | |
4748 // null terminate the end of the string | |
4749 *pszDestEnd = '\0'; | |
4750 } | |
4751 } | |
4752 | |
4753 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) | |
4754 { | |
4755 if (cchDest > 0) | |
4756 { | |
4757 pszDestEnd = pszDest; | |
4758 cchRemaining = cchDest; | |
4759 | |
4760 // null terminate the beginning of the string | |
4761 *pszDestEnd = '\0'; | |
4762 } | |
4763 } | |
4764 } | |
4765 } | |
4766 | |
4767 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
4768 { | |
4769 if (ppszDestEnd) | |
4770 { | |
4771 *ppszDestEnd = pszDestEnd; | |
4772 } | |
4773 | |
4774 if (pcchRemaining) | |
4775 { | |
4776 *pcchRemaining = cchRemaining; | |
4777 } | |
4778 } | |
4779 | |
4780 return hr; | |
4781 } | |
4782 | |
4783 STRSAFEAPI StringCopyNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
4784 { | |
4785 HRESULT hr = S_OK; | |
4786 wchar_t* pszDestEnd = pszDest; | |
4787 size_t cchRemaining = 0; | |
4788 | |
4789 // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || | |
4790 // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); | |
4791 | |
4792 // only accept valid flags | |
4793 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
4794 { | |
4795 hr = STRSAFE_E_INVALID_PARAMETER; | |
4796 } | |
4797 else | |
4798 { | |
4799 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
4800 { | |
4801 if (pszDest == NULL) | |
4802 { | |
4803 if ((cchDest != 0) || (cbDest != 0)) | |
4804 { | |
4805 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
4806 hr = STRSAFE_E_INVALID_PARAMETER; | |
4807 } | |
4808 } | |
4809 | |
4810 if (pszSrc == NULL) | |
4811 { | |
4812 pszSrc = L""; | |
4813 } | |
4814 } | |
4815 | |
4816 if (SUCCEEDED(hr)) | |
4817 { | |
4818 if (cchDest == 0) | |
4819 { | |
4820 pszDestEnd = pszDest; | |
4821 cchRemaining = 0; | |
4822 | |
4823 // only fail if there was actually src data to copy | |
4824 if (*pszSrc != L'\0') | |
4825 { | |
4826 if (pszDest == NULL) | |
4827 { | |
4828 hr = STRSAFE_E_INVALID_PARAMETER; | |
4829 } | |
4830 else | |
4831 { | |
4832 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4833 } | |
4834 } | |
4835 } | |
4836 else | |
4837 { | |
4838 pszDestEnd = pszDest; | |
4839 cchRemaining = cchDest; | |
4840 | |
4841 while (cchRemaining && cchSrc && (*pszSrc != L'\0')) | |
4842 { | |
4843 *pszDestEnd++= *pszSrc++; | |
4844 cchRemaining--; | |
4845 cchSrc--; | |
4846 } | |
4847 | |
4848 if (cchRemaining > 0) | |
4849 { | |
4850 if (dwFlags & STRSAFE_FILL_BEHIND_NULL) | |
4851 { | |
4852 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); | |
4853 } | |
4854 } | |
4855 else | |
4856 { | |
4857 // we are going to truncate pszDest | |
4858 pszDestEnd--; | |
4859 cchRemaining++; | |
4860 | |
4861 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
4862 } | |
4863 | |
4864 *pszDestEnd = L'\0'; | |
4865 } | |
4866 } | |
4867 } | |
4868 | |
4869 if (FAILED(hr)) | |
4870 { | |
4871 if (pszDest) | |
4872 { | |
4873 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
4874 { | |
4875 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
4876 | |
4877 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
4878 { | |
4879 pszDestEnd = pszDest; | |
4880 cchRemaining = cchDest; | |
4881 } | |
4882 else if (cchDest > 0) | |
4883 { | |
4884 pszDestEnd = pszDest + cchDest - 1; | |
4885 cchRemaining = 1; | |
4886 | |
4887 // null terminate the end of the string | |
4888 *pszDestEnd = L'\0'; | |
4889 } | |
4890 } | |
4891 | |
4892 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) | |
4893 { | |
4894 if (cchDest > 0) | |
4895 { | |
4896 pszDestEnd = pszDest; | |
4897 cchRemaining = cchDest; | |
4898 | |
4899 // null terminate the beginning of the string | |
4900 *pszDestEnd = L'\0'; | |
4901 } | |
4902 } | |
4903 } | |
4904 } | |
4905 | |
4906 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
4907 { | |
4908 if (ppszDestEnd) | |
4909 { | |
4910 *ppszDestEnd = pszDestEnd; | |
4911 } | |
4912 | |
4913 if (pcchRemaining) | |
4914 { | |
4915 *pcchRemaining = cchRemaining; | |
4916 } | |
4917 } | |
4918 | |
4919 return hr; | |
4920 } | |
4921 | |
4922 STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) | |
4923 { | |
4924 HRESULT hr; | |
4925 size_t cchDestCurrent; | |
4926 | |
4927 hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); | |
4928 | |
4929 if (SUCCEEDED(hr)) | |
4930 { | |
4931 hr = StringCopyWorkerA(pszDest + cchDestCurrent, | |
4932 cchDest - cchDestCurrent, | |
4933 pszSrc); | |
4934 } | |
4935 | |
4936 return hr; | |
4937 } | |
4938 | |
4939 STRSAFEAPI StringCatWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) | |
4940 { | |
4941 HRESULT hr; | |
4942 size_t cchDestCurrent; | |
4943 | |
4944 hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); | |
4945 | |
4946 if (SUCCEEDED(hr)) | |
4947 { | |
4948 hr = StringCopyWorkerW(pszDest + cchDestCurrent, | |
4949 cchDest - cchDestCurrent, | |
4950 pszSrc); | |
4951 } | |
4952 | |
4953 return hr; | |
4954 } | |
4955 | |
4956 STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
4957 { | |
4958 HRESULT hr = S_OK; | |
4959 char* pszDestEnd = pszDest; | |
4960 size_t cchRemaining = 0; | |
4961 | |
4962 // ASSERT(cbDest == (cchDest * sizeof(char)) || | |
4963 // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); | |
4964 | |
4965 // only accept valid flags | |
4966 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
4967 { | |
4968 hr = STRSAFE_E_INVALID_PARAMETER; | |
4969 } | |
4970 else | |
4971 { | |
4972 size_t cchDestCurrent; | |
4973 | |
4974 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
4975 { | |
4976 if (pszDest == NULL) | |
4977 { | |
4978 if ((cchDest == 0) && (cbDest == 0)) | |
4979 { | |
4980 cchDestCurrent = 0; | |
4981 } | |
4982 else | |
4983 { | |
4984 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
4985 hr = STRSAFE_E_INVALID_PARAMETER; | |
4986 } | |
4987 } | |
4988 else | |
4989 { | |
4990 hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); | |
4991 | |
4992 if (SUCCEEDED(hr)) | |
4993 { | |
4994 pszDestEnd = pszDest + cchDestCurrent; | |
4995 cchRemaining = cchDest - cchDestCurrent; | |
4996 } | |
4997 } | |
4998 | |
4999 if (pszSrc == NULL) | |
5000 { | |
5001 pszSrc = ""; | |
5002 } | |
5003 } | |
5004 else | |
5005 { | |
5006 hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); | |
5007 | |
5008 if (SUCCEEDED(hr)) | |
5009 { | |
5010 pszDestEnd = pszDest + cchDestCurrent; | |
5011 cchRemaining = cchDest - cchDestCurrent; | |
5012 } | |
5013 } | |
5014 | |
5015 if (SUCCEEDED(hr)) | |
5016 { | |
5017 if (cchDest == 0) | |
5018 { | |
5019 // only fail if there was actually src data to append | |
5020 if (*pszSrc != '\0') | |
5021 { | |
5022 if (pszDest == NULL) | |
5023 { | |
5024 hr = STRSAFE_E_INVALID_PARAMETER; | |
5025 } | |
5026 else | |
5027 { | |
5028 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
5029 } | |
5030 } | |
5031 } | |
5032 else | |
5033 { | |
5034 // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass | |
5035 // those flags through | |
5036 hr = StringCopyExWorkerA(pszDestEnd, | |
5037 cchRemaining, | |
5038 (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), | |
5039 pszSrc, | |
5040 &pszDestEnd, | |
5041 &cchRemaining, | |
5042 dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); | |
5043 } | |
5044 } | |
5045 } | |
5046 | |
5047 if (FAILED(hr)) | |
5048 { | |
5049 if (pszDest) | |
5050 { | |
5051 // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerA() | |
5052 | |
5053 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
5054 { | |
5055 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
5056 | |
5057 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
5058 { | |
5059 pszDestEnd = pszDest; | |
5060 cchRemaining = cchDest; | |
5061 } | |
5062 else | |
5063 if (cchDest > 0) | |
5064 { | |
5065 pszDestEnd = pszDest + cchDest - 1; | |
5066 cchRemaining = 1; | |
5067 | |
5068 // null terminate the end of the string | |
5069 *pszDestEnd = '\0'; | |
5070 } | |
5071 } | |
5072 | |
5073 if (dwFlags & STRSAFE_NULL_ON_FAILURE) | |
5074 { | |
5075 if (cchDest > 0) | |
5076 { | |
5077 pszDestEnd = pszDest; | |
5078 cchRemaining = cchDest; | |
5079 | |
5080 // null terminate the beginning of the string | |
5081 *pszDestEnd = '\0'; | |
5082 } | |
5083 } | |
5084 } | |
5085 } | |
5086 | |
5087 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
5088 { | |
5089 if (ppszDestEnd) | |
5090 { | |
5091 *ppszDestEnd = pszDestEnd; | |
5092 } | |
5093 | |
5094 if (pcchRemaining) | |
5095 { | |
5096 *pcchRemaining = cchRemaining; | |
5097 } | |
5098 } | |
5099 | |
5100 return hr; | |
5101 } | |
5102 | |
5103 STRSAFEAPI StringCatExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
5104 { | |
5105 HRESULT hr = S_OK; | |
5106 wchar_t* pszDestEnd = pszDest; | |
5107 size_t cchRemaining = 0; | |
5108 | |
5109 // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || | |
5110 // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); | |
5111 | |
5112 // only accept valid flags | |
5113 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
5114 { | |
5115 hr = STRSAFE_E_INVALID_PARAMETER; | |
5116 } | |
5117 else | |
5118 { | |
5119 size_t cchDestCurrent; | |
5120 | |
5121 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
5122 { | |
5123 if (pszDest == NULL) | |
5124 { | |
5125 if ((cchDest == 0) && (cbDest == 0)) | |
5126 { | |
5127 cchDestCurrent = 0; | |
5128 } | |
5129 else | |
5130 { | |
5131 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
5132 hr = STRSAFE_E_INVALID_PARAMETER; | |
5133 } | |
5134 } | |
5135 else | |
5136 { | |
5137 hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); | |
5138 | |
5139 if (SUCCEEDED(hr)) | |
5140 { | |
5141 pszDestEnd = pszDest + cchDestCurrent; | |
5142 cchRemaining = cchDest - cchDestCurrent; | |
5143 } | |
5144 } | |
5145 | |
5146 if (pszSrc == NULL) | |
5147 { | |
5148 pszSrc = L""; | |
5149 } | |
5150 } | |
5151 else | |
5152 { | |
5153 hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); | |
5154 | |
5155 if (SUCCEEDED(hr)) | |
5156 { | |
5157 pszDestEnd = pszDest + cchDestCurrent; | |
5158 cchRemaining = cchDest - cchDestCurrent; | |
5159 } | |
5160 } | |
5161 | |
5162 if (SUCCEEDED(hr)) | |
5163 { | |
5164 if (cchDest == 0) | |
5165 { | |
5166 // only fail if there was actually src data to append | |
5167 if (*pszSrc != L'\0') | |
5168 { | |
5169 if (pszDest == NULL) | |
5170 { | |
5171 hr = STRSAFE_E_INVALID_PARAMETER; | |
5172 } | |
5173 else | |
5174 { | |
5175 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
5176 } | |
5177 } | |
5178 } | |
5179 else | |
5180 { | |
5181 // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass | |
5182 // those flags through | |
5183 hr = StringCopyExWorkerW(pszDestEnd, | |
5184 cchRemaining, | |
5185 (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)), | |
5186 pszSrc, | |
5187 &pszDestEnd, | |
5188 &cchRemaining, | |
5189 dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); | |
5190 } | |
5191 } | |
5192 } | |
5193 | |
5194 if (FAILED(hr)) | |
5195 { | |
5196 if (pszDest) | |
5197 { | |
5198 // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerW() | |
5199 | |
5200 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
5201 { | |
5202 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
5203 | |
5204 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
5205 { | |
5206 pszDestEnd = pszDest; | |
5207 cchRemaining = cchDest; | |
5208 } | |
5209 else if (cchDest > 0) | |
5210 { | |
5211 pszDestEnd = pszDest + cchDest - 1; | |
5212 cchRemaining = 1; | |
5213 | |
5214 // null terminate the end of the string | |
5215 *pszDestEnd = L'\0'; | |
5216 } | |
5217 } | |
5218 | |
5219 if (dwFlags & STRSAFE_NULL_ON_FAILURE) | |
5220 { | |
5221 if (cchDest > 0) | |
5222 { | |
5223 pszDestEnd = pszDest; | |
5224 cchRemaining = cchDest; | |
5225 | |
5226 // null terminate the beginning of the string | |
5227 *pszDestEnd = L'\0'; | |
5228 } | |
5229 } | |
5230 } | |
5231 } | |
5232 | |
5233 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
5234 { | |
5235 if (ppszDestEnd) | |
5236 { | |
5237 *ppszDestEnd = pszDestEnd; | |
5238 } | |
5239 | |
5240 if (pcchRemaining) | |
5241 { | |
5242 *pcchRemaining = cchRemaining; | |
5243 } | |
5244 } | |
5245 | |
5246 return hr; | |
5247 } | |
5248 | |
5249 STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend) | |
5250 { | |
5251 HRESULT hr; | |
5252 size_t cchDestCurrent; | |
5253 | |
5254 hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); | |
5255 | |
5256 if (SUCCEEDED(hr)) | |
5257 { | |
5258 hr = StringCopyNWorkerA(pszDest + cchDestCurrent, | |
5259 cchDest - cchDestCurrent, | |
5260 pszSrc, | |
5261 cchMaxAppend); | |
5262 } | |
5263 | |
5264 return hr; | |
5265 } | |
5266 | |
5267 STRSAFEAPI StringCatNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend) | |
5268 { | |
5269 HRESULT hr; | |
5270 size_t cchDestCurrent; | |
5271 | |
5272 hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); | |
5273 | |
5274 if (SUCCEEDED(hr)) | |
5275 { | |
5276 hr = StringCopyNWorkerW(pszDest + cchDestCurrent, | |
5277 cchDest - cchDestCurrent, | |
5278 pszSrc, | |
5279 cchMaxAppend); | |
5280 } | |
5281 | |
5282 return hr; | |
5283 } | |
5284 | |
5285 STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
5286 { | |
5287 HRESULT hr = S_OK; | |
5288 char* pszDestEnd = pszDest; | |
5289 size_t cchRemaining = 0; | |
5290 size_t cchDestCurrent = 0; | |
5291 | |
5292 // ASSERT(cbDest == (cchDest * sizeof(char)) || | |
5293 // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); | |
5294 | |
5295 // only accept valid flags | |
5296 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
5297 { | |
5298 hr = STRSAFE_E_INVALID_PARAMETER; | |
5299 } | |
5300 else | |
5301 { | |
5302 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
5303 { | |
5304 if (pszDest == NULL) | |
5305 { | |
5306 if ((cchDest == 0) && (cbDest == 0)) | |
5307 { | |
5308 cchDestCurrent = 0; | |
5309 } | |
5310 else | |
5311 { | |
5312 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
5313 hr = STRSAFE_E_INVALID_PARAMETER; | |
5314 } | |
5315 } | |
5316 else | |
5317 { | |
5318 hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); | |
5319 | |
5320 if (SUCCEEDED(hr)) | |
5321 { | |
5322 pszDestEnd = pszDest + cchDestCurrent; | |
5323 cchRemaining = cchDest - cchDestCurrent; | |
5324 } | |
5325 } | |
5326 | |
5327 if (pszSrc == NULL) | |
5328 { | |
5329 pszSrc = ""; | |
5330 } | |
5331 } | |
5332 else | |
5333 { | |
5334 hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); | |
5335 | |
5336 if (SUCCEEDED(hr)) | |
5337 { | |
5338 pszDestEnd = pszDest + cchDestCurrent; | |
5339 cchRemaining = cchDest - cchDestCurrent; | |
5340 } | |
5341 } | |
5342 | |
5343 if (SUCCEEDED(hr)) | |
5344 { | |
5345 if (cchDest == 0) | |
5346 { | |
5347 // only fail if there was actually src data to append | |
5348 if (*pszSrc != '\0') | |
5349 { | |
5350 if (pszDest == NULL) | |
5351 { | |
5352 hr = STRSAFE_E_INVALID_PARAMETER; | |
5353 } | |
5354 else | |
5355 { | |
5356 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
5357 } | |
5358 } | |
5359 } | |
5360 else | |
5361 { | |
5362 // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass | |
5363 // those flags through | |
5364 hr = StringCopyNExWorkerA(pszDestEnd, | |
5365 cchRemaining, | |
5366 (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), | |
5367 pszSrc, | |
5368 cchMaxAppend, | |
5369 &pszDestEnd, | |
5370 &cchRemaining, | |
5371 dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); | |
5372 } | |
5373 } | |
5374 } | |
5375 | |
5376 if (FAILED(hr)) | |
5377 { | |
5378 if (pszDest) | |
5379 { | |
5380 // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerA() | |
5381 | |
5382 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
5383 { | |
5384 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
5385 | |
5386 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
5387 { | |
5388 pszDestEnd = pszDest; | |
5389 cchRemaining = cchDest; | |
5390 } | |
5391 else if (cchDest > 0) | |
5392 { | |
5393 pszDestEnd = pszDest + cchDest - 1; | |
5394 cchRemaining = 1; | |
5395 | |
5396 // null terminate the end of the string | |
5397 *pszDestEnd = '\0'; | |
5398 } | |
5399 } | |
5400 | |
5401 if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) | |
5402 { | |
5403 if (cchDest > 0) | |
5404 { | |
5405 pszDestEnd = pszDest; | |
5406 cchRemaining = cchDest; | |
5407 | |
5408 // null terminate the beginning of the string | |
5409 *pszDestEnd = '\0'; | |
5410 } | |
5411 } | |
5412 } | |
5413 } | |
5414 | |
5415 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
5416 { | |
5417 if (ppszDestEnd) | |
5418 { | |
5419 *ppszDestEnd = pszDestEnd; | |
5420 } | |
5421 | |
5422 if (pcchRemaining) | |
5423 { | |
5424 *pcchRemaining = cchRemaining; | |
5425 } | |
5426 } | |
5427 | |
5428 return hr; | |
5429 } | |
5430 | |
5431 STRSAFEAPI StringCatNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
5432 { | |
5433 HRESULT hr = S_OK; | |
5434 wchar_t* pszDestEnd = pszDest; | |
5435 size_t cchRemaining = 0; | |
5436 size_t cchDestCurrent = 0; | |
5437 | |
5438 | |
5439 // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || | |
5440 // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); | |
5441 | |
5442 // only accept valid flags | |
5443 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
5444 { | |
5445 hr = STRSAFE_E_INVALID_PARAMETER; | |
5446 } | |
5447 else | |
5448 { | |
5449 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
5450 { | |
5451 if (pszDest == NULL) | |
5452 { | |
5453 if ((cchDest == 0) && (cbDest == 0)) | |
5454 { | |
5455 cchDestCurrent = 0; | |
5456 } | |
5457 else | |
5458 { | |
5459 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
5460 hr = STRSAFE_E_INVALID_PARAMETER; | |
5461 } | |
5462 } | |
5463 else | |
5464 { | |
5465 hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); | |
5466 | |
5467 if (SUCCEEDED(hr)) | |
5468 { | |
5469 pszDestEnd = pszDest + cchDestCurrent; | |
5470 cchRemaining = cchDest - cchDestCurrent; | |
5471 } | |
5472 } | |
5473 | |
5474 if (pszSrc == NULL) | |
5475 { | |
5476 pszSrc = L""; | |
5477 } | |
5478 } | |
5479 else | |
5480 { | |
5481 hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); | |
5482 | |
5483 if (SUCCEEDED(hr)) | |
5484 { | |
5485 pszDestEnd = pszDest + cchDestCurrent; | |
5486 cchRemaining = cchDest - cchDestCurrent; | |
5487 } | |
5488 } | |
5489 | |
5490 if (SUCCEEDED(hr)) | |
5491 { | |
5492 if (cchDest == 0) | |
5493 { | |
5494 // only fail if there was actually src data to append | |
5495 if (*pszSrc != L'\0') | |
5496 { | |
5497 if (pszDest == NULL) | |
5498 { | |
5499 hr = STRSAFE_E_INVALID_PARAMETER; | |
5500 } | |
5501 else | |
5502 { | |
5503 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
5504 } | |
5505 } | |
5506 } | |
5507 else | |
5508 { | |
5509 // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass | |
5510 // those flags through | |
5511 hr = StringCopyNExWorkerW(pszDestEnd, | |
5512 cchRemaining, | |
5513 (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)), | |
5514 pszSrc, | |
5515 cchMaxAppend, | |
5516 &pszDestEnd, | |
5517 &cchRemaining, | |
5518 dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); | |
5519 } | |
5520 } | |
5521 } | |
5522 | |
5523 if (FAILED(hr)) | |
5524 { | |
5525 if (pszDest) | |
5526 { | |
5527 // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerW() | |
5528 | |
5529 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
5530 { | |
5531 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
5532 | |
5533 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
5534 { | |
5535 pszDestEnd = pszDest; | |
5536 cchRemaining = cchDest; | |
5537 } | |
5538 else if (cchDest > 0) | |
5539 { | |
5540 pszDestEnd = pszDest + cchDest - 1; | |
5541 cchRemaining = 1; | |
5542 | |
5543 // null terminate the end of the string | |
5544 *pszDestEnd = L'\0'; | |
5545 } | |
5546 } | |
5547 | |
5548 if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) | |
5549 { | |
5550 if (cchDest > 0) | |
5551 { | |
5552 pszDestEnd = pszDest; | |
5553 cchRemaining = cchDest; | |
5554 | |
5555 // null terminate the beginning of the string | |
5556 *pszDestEnd = L'\0'; | |
5557 } | |
5558 } | |
5559 } | |
5560 } | |
5561 | |
5562 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
5563 { | |
5564 if (ppszDestEnd) | |
5565 { | |
5566 *ppszDestEnd = pszDestEnd; | |
5567 } | |
5568 | |
5569 if (pcchRemaining) | |
5570 { | |
5571 *pcchRemaining = cchRemaining; | |
5572 } | |
5573 } | |
5574 | |
5575 return hr; | |
5576 } | |
5577 | |
5578 STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList) | |
5579 { | |
5580 HRESULT hr = S_OK; | |
5581 | |
5582 if (cchDest == 0) | |
5583 { | |
5584 // can not null terminate a zero-byte dest buffer | |
5585 hr = STRSAFE_E_INVALID_PARAMETER; | |
5586 } | |
5587 else | |
5588 { | |
5589 int iRet; | |
5590 size_t cchMax; | |
5591 | |
5592 // leave the last space for the null terminator | |
5593 cchMax = cchDest - 1; | |
5594 | |
5595 iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList); | |
5596 // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); | |
5597 | |
5598 if ((iRet < 0) || (((size_t)iRet) > cchMax)) | |
5599 { | |
5600 // need to null terminate the string | |
5601 pszDest += cchMax; | |
5602 *pszDest = '\0'; | |
5603 | |
5604 // we have truncated pszDest | |
5605 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
5606 } | |
5607 else if (((size_t)iRet) == cchMax) | |
5608 { | |
5609 // need to null terminate the string | |
5610 pszDest += cchMax; | |
5611 *pszDest = '\0'; | |
5612 } | |
5613 } | |
5614 | |
5615 return hr; | |
5616 } | |
5617 | |
5618 STRSAFEAPI StringVPrintfWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList) | |
5619 { | |
5620 HRESULT hr = S_OK; | |
5621 | |
5622 if (cchDest == 0) | |
5623 { | |
5624 // can not null terminate a zero-byte dest buffer | |
5625 hr = STRSAFE_E_INVALID_PARAMETER; | |
5626 } | |
5627 else | |
5628 { | |
5629 int iRet; | |
5630 size_t cchMax; | |
5631 | |
5632 // leave the last space for the null terminator | |
5633 cchMax = cchDest - 1; | |
5634 | |
5635 iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList); | |
5636 // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); | |
5637 | |
5638 if ((iRet < 0) || (((size_t)iRet) > cchMax)) | |
5639 { | |
5640 // need to null terminate the string | |
5641 pszDest += cchMax; | |
5642 *pszDest = L'\0'; | |
5643 | |
5644 // we have truncated pszDest | |
5645 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
5646 } | |
5647 else if (((size_t)iRet) == cchMax) | |
5648 { | |
5649 // need to null terminate the string | |
5650 pszDest += cchMax; | |
5651 *pszDest = L'\0'; | |
5652 } | |
5653 } | |
5654 | |
5655 return hr; | |
5656 } | |
5657 | |
5658 STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList) | |
5659 { | |
5660 HRESULT hr = S_OK; | |
5661 char* pszDestEnd = pszDest; | |
5662 size_t cchRemaining = 0; | |
5663 | |
5664 // ASSERT(cbDest == (cchDest * sizeof(char)) || | |
5665 // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); | |
5666 | |
5667 // only accept valid flags | |
5668 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
5669 { | |
5670 hr = STRSAFE_E_INVALID_PARAMETER; | |
5671 } | |
5672 else | |
5673 { | |
5674 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
5675 { | |
5676 if (pszDest == NULL) | |
5677 { | |
5678 if ((cchDest != 0) || (cbDest != 0)) | |
5679 { | |
5680 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
5681 hr = STRSAFE_E_INVALID_PARAMETER; | |
5682 } | |
5683 } | |
5684 | |
5685 if (pszFormat == NULL) | |
5686 { | |
5687 pszFormat = ""; | |
5688 } | |
5689 } | |
5690 | |
5691 if (SUCCEEDED(hr)) | |
5692 { | |
5693 if (cchDest == 0) | |
5694 { | |
5695 pszDestEnd = pszDest; | |
5696 cchRemaining = 0; | |
5697 | |
5698 // only fail if there was actually a non-empty format string | |
5699 if (*pszFormat != '\0') | |
5700 { | |
5701 if (pszDest == NULL) | |
5702 { | |
5703 hr = STRSAFE_E_INVALID_PARAMETER; | |
5704 } | |
5705 else | |
5706 { | |
5707 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
5708 } | |
5709 } | |
5710 } | |
5711 else | |
5712 { | |
5713 int iRet; | |
5714 size_t cchMax; | |
5715 | |
5716 // leave the last space for the null terminator | |
5717 cchMax = cchDest - 1; | |
5718 | |
5719 iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList); | |
5720 // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); | |
5721 | |
5722 if ((iRet < 0) || (((size_t)iRet) > cchMax)) | |
5723 { | |
5724 // we have truncated pszDest | |
5725 pszDestEnd = pszDest + cchMax; | |
5726 cchRemaining = 1; | |
5727 | |
5728 // need to null terminate the string | |
5729 *pszDestEnd = '\0'; | |
5730 | |
5731 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
5732 } | |
5733 else if (((size_t)iRet) == cchMax) | |
5734 { | |
5735 // string fit perfectly | |
5736 pszDestEnd = pszDest + cchMax; | |
5737 cchRemaining = 1; | |
5738 | |
5739 // need to null terminate the string | |
5740 *pszDestEnd = '\0'; | |
5741 } | |
5742 else if (((size_t)iRet) < cchMax) | |
5743 { | |
5744 // there is extra room | |
5745 pszDestEnd = pszDest + iRet; | |
5746 cchRemaining = cchDest - iRet; | |
5747 | |
5748 if (dwFlags & STRSAFE_FILL_BEHIND_NULL) | |
5749 { | |
5750 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char))); | |
5751 } | |
5752 } | |
5753 } | |
5754 } | |
5755 } | |
5756 | |
5757 if (FAILED(hr)) | |
5758 { | |
5759 if (pszDest) | |
5760 { | |
5761 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
5762 { | |
5763 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
5764 | |
5765 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
5766 { | |
5767 pszDestEnd = pszDest; | |
5768 cchRemaining = cchDest; | |
5769 } | |
5770 else if (cchDest > 0) | |
5771 { | |
5772 pszDestEnd = pszDest + cchDest - 1; | |
5773 cchRemaining = 1; | |
5774 | |
5775 // null terminate the end of the string | |
5776 *pszDestEnd = '\0'; | |
5777 } | |
5778 } | |
5779 | |
5780 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) | |
5781 { | |
5782 if (cchDest > 0) | |
5783 { | |
5784 pszDestEnd = pszDest; | |
5785 cchRemaining = cchDest; | |
5786 | |
5787 // null terminate the beginning of the string | |
5788 *pszDestEnd = '\0'; | |
5789 } | |
5790 } | |
5791 } | |
5792 } | |
5793 | |
5794 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
5795 { | |
5796 if (ppszDestEnd) | |
5797 { | |
5798 *ppszDestEnd = pszDestEnd; | |
5799 } | |
5800 | |
5801 if (pcchRemaining) | |
5802 { | |
5803 *pcchRemaining = cchRemaining; | |
5804 } | |
5805 } | |
5806 | |
5807 return hr; | |
5808 } | |
5809 | |
5810 STRSAFEAPI StringVPrintfExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList) | |
5811 { | |
5812 HRESULT hr = S_OK; | |
5813 wchar_t* pszDestEnd = pszDest; | |
5814 size_t cchRemaining = 0; | |
5815 | |
5816 // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || | |
5817 // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); | |
5818 | |
5819 // only accept valid flags | |
5820 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
5821 { | |
5822 hr = STRSAFE_E_INVALID_PARAMETER; | |
5823 } | |
5824 else | |
5825 { | |
5826 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
5827 { | |
5828 if (pszDest == NULL) | |
5829 { | |
5830 if ((cchDest != 0) || (cbDest != 0)) | |
5831 { | |
5832 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
5833 hr = STRSAFE_E_INVALID_PARAMETER; | |
5834 } | |
5835 } | |
5836 | |
5837 if (pszFormat == NULL) | |
5838 { | |
5839 pszFormat = L""; | |
5840 } | |
5841 } | |
5842 | |
5843 if (SUCCEEDED(hr)) | |
5844 { | |
5845 if (cchDest == 0) | |
5846 { | |
5847 pszDestEnd = pszDest; | |
5848 cchRemaining = 0; | |
5849 | |
5850 // only fail if there was actually a non-empty format string | |
5851 if (*pszFormat != L'\0') | |
5852 { | |
5853 if (pszDest == NULL) | |
5854 { | |
5855 hr = STRSAFE_E_INVALID_PARAMETER; | |
5856 } | |
5857 else | |
5858 { | |
5859 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
5860 } | |
5861 } | |
5862 } | |
5863 else | |
5864 { | |
5865 int iRet; | |
5866 size_t cchMax; | |
5867 | |
5868 // leave the last space for the null terminator | |
5869 cchMax = cchDest - 1; | |
5870 | |
5871 iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList); | |
5872 // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); | |
5873 | |
5874 if ((iRet < 0) || (((size_t)iRet) > cchMax)) | |
5875 { | |
5876 // we have truncated pszDest | |
5877 pszDestEnd = pszDest + cchMax; | |
5878 cchRemaining = 1; | |
5879 | |
5880 // need to null terminate the string | |
5881 *pszDestEnd = L'\0'; | |
5882 | |
5883 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
5884 } | |
5885 else if (((size_t)iRet) == cchMax) | |
5886 { | |
5887 // string fit perfectly | |
5888 pszDestEnd = pszDest + cchMax; | |
5889 cchRemaining = 1; | |
5890 | |
5891 // need to null terminate the string | |
5892 *pszDestEnd = L'\0'; | |
5893 } | |
5894 else if (((size_t)iRet) < cchMax) | |
5895 { | |
5896 // there is extra room | |
5897 pszDestEnd = pszDest + iRet; | |
5898 cchRemaining = cchDest - iRet; | |
5899 | |
5900 if (dwFlags & STRSAFE_FILL_BEHIND_NULL) | |
5901 { | |
5902 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); | |
5903 } | |
5904 } | |
5905 } | |
5906 } | |
5907 } | |
5908 | |
5909 if (FAILED(hr)) | |
5910 { | |
5911 if (pszDest) | |
5912 { | |
5913 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
5914 { | |
5915 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
5916 | |
5917 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
5918 { | |
5919 pszDestEnd = pszDest; | |
5920 cchRemaining = cchDest; | |
5921 } | |
5922 else if (cchDest > 0) | |
5923 { | |
5924 pszDestEnd = pszDest + cchDest - 1; | |
5925 cchRemaining = 1; | |
5926 | |
5927 // null terminate the end of the string | |
5928 *pszDestEnd = L'\0'; | |
5929 } | |
5930 } | |
5931 | |
5932 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) | |
5933 { | |
5934 if (cchDest > 0) | |
5935 { | |
5936 pszDestEnd = pszDest; | |
5937 cchRemaining = cchDest; | |
5938 | |
5939 // null terminate the beginning of the string | |
5940 *pszDestEnd = L'\0'; | |
5941 } | |
5942 } | |
5943 } | |
5944 } | |
5945 | |
5946 if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) | |
5947 { | |
5948 if (ppszDestEnd) | |
5949 { | |
5950 *ppszDestEnd = pszDestEnd; | |
5951 } | |
5952 | |
5953 if (pcchRemaining) | |
5954 { | |
5955 *pcchRemaining = cchRemaining; | |
5956 } | |
5957 } | |
5958 | |
5959 return hr; | |
5960 } | |
5961 | |
5962 STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch) | |
5963 { | |
5964 HRESULT hr = S_OK; | |
5965 size_t cchMaxPrev = cchMax; | |
5966 | |
5967 while (cchMax && (*psz != '\0')) | |
5968 { | |
5969 psz++; | |
5970 cchMax--; | |
5971 } | |
5972 | |
5973 if (cchMax == 0) | |
5974 { | |
5975 // the string is longer than cchMax | |
5976 hr = STRSAFE_E_INVALID_PARAMETER; | |
5977 } | |
5978 | |
5979 if (SUCCEEDED(hr) && pcch) | |
5980 { | |
5981 *pcch = cchMaxPrev - cchMax; | |
5982 } | |
5983 | |
5984 return hr; | |
5985 } | |
5986 | |
5987 STRSAFEAPI StringLengthWorkerW(const wchar_t* psz, size_t cchMax, size_t* pcch) | |
5988 { | |
5989 HRESULT hr = S_OK; | |
5990 size_t cchMaxPrev = cchMax; | |
5991 | |
5992 while (cchMax && (*psz != L'\0')) | |
5993 { | |
5994 psz++; | |
5995 cchMax--; | |
5996 } | |
5997 | |
5998 if (cchMax == 0) | |
5999 { | |
6000 // the string is longer than cchMax | |
6001 hr = STRSAFE_E_INVALID_PARAMETER; | |
6002 } | |
6003 | |
6004 if (SUCCEEDED(hr) && pcch) | |
6005 { | |
6006 *pcch = cchMaxPrev - cchMax; | |
6007 } | |
6008 | |
6009 return hr; | |
6010 } | |
6011 #endif // STRSAFE_INLINE | |
6012 | |
6013 #ifndef STRSAFE_LIB_IMPL | |
6014 STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
6015 { | |
6016 HRESULT hr = S_OK; | |
6017 char* pszDestEnd = pszDest; | |
6018 size_t cchRemaining = 0; | |
6019 | |
6020 // ASSERT(cbDest == (cchDest * sizeof(char)) || | |
6021 // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); | |
6022 | |
6023 // only accept valid flags | |
6024 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
6025 { | |
6026 hr = STRSAFE_E_INVALID_PARAMETER; | |
6027 } | |
6028 else | |
6029 { | |
6030 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
6031 { | |
6032 if (pszDest == NULL) | |
6033 { | |
6034 if ((cchDest != 0) || (cbDest != 0)) | |
6035 { | |
6036 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
6037 hr = STRSAFE_E_INVALID_PARAMETER; | |
6038 } | |
6039 } | |
6040 } | |
6041 | |
6042 if (SUCCEEDED(hr)) | |
6043 { | |
6044 if (cchDest <= 1) | |
6045 { | |
6046 pszDestEnd = pszDest; | |
6047 cchRemaining = cchDest; | |
6048 | |
6049 if (cchDest == 1) | |
6050 { | |
6051 *pszDestEnd = '\0'; | |
6052 } | |
6053 | |
6054 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
6055 } | |
6056 else | |
6057 { | |
6058 char ch; | |
6059 | |
6060 pszDestEnd = pszDest; | |
6061 cchRemaining = cchDest; | |
6062 | |
6063 while ((cchRemaining > 1) && (ch = (char)getc(stdin)) != '\n') | |
6064 { | |
6065 if (ch == EOF) | |
6066 { | |
6067 if (pszDestEnd == pszDest) | |
6068 { | |
6069 // we failed to read anything from stdin | |
6070 hr = STRSAFE_E_END_OF_FILE; | |
6071 } | |
6072 break; | |
6073 } | |
6074 | |
6075 *pszDestEnd = ch; | |
6076 | |
6077 pszDestEnd++; | |
6078 cchRemaining--; | |
6079 } | |
6080 | |
6081 if (cchRemaining > 0) | |
6082 { | |
6083 // there is extra room | |
6084 if (dwFlags & STRSAFE_FILL_BEHIND_NULL) | |
6085 { | |
6086 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char))); | |
6087 } | |
6088 } | |
6089 | |
6090 *pszDestEnd = '\0'; | |
6091 } | |
6092 } | |
6093 } | |
6094 | |
6095 if (FAILED(hr)) | |
6096 { | |
6097 if (pszDest) | |
6098 { | |
6099 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
6100 { | |
6101 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
6102 | |
6103 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
6104 { | |
6105 pszDestEnd = pszDest; | |
6106 cchRemaining = cchDest; | |
6107 } | |
6108 else if (cchDest > 0) | |
6109 { | |
6110 pszDestEnd = pszDest + cchDest - 1; | |
6111 cchRemaining = 1; | |
6112 | |
6113 // null terminate the end of the string | |
6114 *pszDestEnd = '\0'; | |
6115 } | |
6116 } | |
6117 | |
6118 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) | |
6119 { | |
6120 if (cchDest > 0) | |
6121 { | |
6122 pszDestEnd = pszDest; | |
6123 cchRemaining = cchDest; | |
6124 | |
6125 // null terminate the beginning of the string | |
6126 *pszDestEnd = '\0'; | |
6127 } | |
6128 } | |
6129 } | |
6130 } | |
6131 | |
6132 if (SUCCEEDED(hr) || | |
6133 (hr == STRSAFE_E_INSUFFICIENT_BUFFER) || | |
6134 (hr == STRSAFE_E_END_OF_FILE)) | |
6135 { | |
6136 if (ppszDestEnd) | |
6137 { | |
6138 *ppszDestEnd = pszDestEnd; | |
6139 } | |
6140 | |
6141 if (pcchRemaining) | |
6142 { | |
6143 *pcchRemaining = cchRemaining; | |
6144 } | |
6145 } | |
6146 | |
6147 return hr; | |
6148 } | |
6149 | |
6150 STRSAFE_INLINE_API StringGetsExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) | |
6151 { | |
6152 HRESULT hr = S_OK; | |
6153 wchar_t* pszDestEnd = pszDest; | |
6154 size_t cchRemaining = 0; | |
6155 | |
6156 // ASSERT(cbDest == (cchDest * sizeof(char)) || | |
6157 // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); | |
6158 | |
6159 // only accept valid flags | |
6160 if (dwFlags & (~STRSAFE_VALID_FLAGS)) | |
6161 { | |
6162 hr = STRSAFE_E_INVALID_PARAMETER; | |
6163 } | |
6164 else | |
6165 { | |
6166 if (dwFlags & STRSAFE_IGNORE_NULLS) | |
6167 { | |
6168 if (pszDest == NULL) | |
6169 { | |
6170 if ((cchDest != 0) || (cbDest != 0)) | |
6171 { | |
6172 // NULL pszDest and non-zero cchDest/cbDest is invalid | |
6173 hr = STRSAFE_E_INVALID_PARAMETER; | |
6174 } | |
6175 } | |
6176 } | |
6177 | |
6178 if (SUCCEEDED(hr)) | |
6179 { | |
6180 if (cchDest <= 1) | |
6181 { | |
6182 pszDestEnd = pszDest; | |
6183 cchRemaining = cchDest; | |
6184 | |
6185 if (cchDest == 1) | |
6186 { | |
6187 *pszDestEnd = L'\0'; | |
6188 } | |
6189 | |
6190 hr = STRSAFE_E_INSUFFICIENT_BUFFER; | |
6191 } | |
6192 else | |
6193 { | |
6194 wchar_t ch; | |
6195 | |
6196 pszDestEnd = pszDest; | |
6197 cchRemaining = cchDest; | |
6198 | |
6199 while ((cchRemaining > 1) && (ch = (wchar_t)getwc(stdin)) != L'\n') | |
6200 { | |
6201 if (ch == EOF) | |
6202 { | |
6203 if (pszDestEnd == pszDest) | |
6204 { | |
6205 // we failed to read anything from stdin | |
6206 hr = STRSAFE_E_END_OF_FILE; | |
6207 } | |
6208 break; | |
6209 } | |
6210 | |
6211 *pszDestEnd = ch; | |
6212 | |
6213 pszDestEnd++; | |
6214 cchRemaining--; | |
6215 } | |
6216 | |
6217 if (cchRemaining > 0) | |
6218 { | |
6219 // there is extra room | |
6220 if (dwFlags & STRSAFE_FILL_BEHIND_NULL) | |
6221 { | |
6222 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); | |
6223 } | |
6224 } | |
6225 | |
6226 *pszDestEnd = L'\0'; | |
6227 } | |
6228 } | |
6229 } | |
6230 | |
6231 if (FAILED(hr)) | |
6232 { | |
6233 if (pszDest) | |
6234 { | |
6235 if (dwFlags & STRSAFE_FILL_ON_FAILURE) | |
6236 { | |
6237 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); | |
6238 | |
6239 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) | |
6240 { | |
6241 pszDestEnd = pszDest; | |
6242 cchRemaining = cchDest; | |
6243 } | |
6244 else if (cchDest > 0) | |
6245 { | |
6246 pszDestEnd = pszDest + cchDest - 1; | |
6247 cchRemaining = 1; | |
6248 | |
6249 // null terminate the end of the string | |
6250 *pszDestEnd = L'\0'; | |
6251 } | |
6252 } | |
6253 | |
6254 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) | |
6255 { | |
6256 if (cchDest > 0) | |
6257 { | |
6258 pszDestEnd = pszDest; | |
6259 cchRemaining = cchDest; | |
6260 | |
6261 // null terminate the beginning of the string | |
6262 *pszDestEnd = L'\0'; | |
6263 } | |
6264 } | |
6265 } | |
6266 } | |
6267 | |
6268 if (SUCCEEDED(hr) || | |
6269 (hr == STRSAFE_E_INSUFFICIENT_BUFFER) || | |
6270 (hr == STRSAFE_E_END_OF_FILE)) | |
6271 { | |
6272 if (ppszDestEnd) | |
6273 { | |
6274 *ppszDestEnd = pszDestEnd; | |
6275 } | |
6276 | |
6277 if (pcchRemaining) | |
6278 { | |
6279 *pcchRemaining = cchRemaining; | |
6280 } | |
6281 } | |
6282 | |
6283 return hr; | |
6284 } | |
6285 #endif // !STRSAFE_LIB_IMPL | |
6286 | |
6287 | |
6288 // Do not call these functions, they are worker functions for internal use within this file | |
6289 #ifdef DEPRECATE_SUPPORTED | |
6290 #pragma deprecated(StringCopyWorkerA) | |
6291 #pragma deprecated(StringCopyWorkerW) | |
6292 #pragma deprecated(StringCopyExWorkerA) | |
6293 #pragma deprecated(StringCopyExWorkerW) | |
6294 #pragma deprecated(StringCatWorkerA) | |
6295 #pragma deprecated(StringCatWorkerW) | |
6296 #pragma deprecated(StringCatExWorkerA) | |
6297 #pragma deprecated(StringCatExWorkerW) | |
6298 #pragma deprecated(StringCatNWorkerA) | |
6299 #pragma deprecated(StringCatNWorkerW) | |
6300 #pragma deprecated(StringCatNExWorkerA) | |
6301 #pragma deprecated(StringCatNExWorkerW) | |
6302 #pragma deprecated(StringVPrintfWorkerA) | |
6303 #pragma deprecated(StringVPrintfWorkerW) | |
6304 #pragma deprecated(StringVPrintfExWorkerA) | |
6305 #pragma deprecated(StringVPrintfExWorkerW) | |
6306 #pragma deprecated(StringLengthWorkerA) | |
6307 #pragma deprecated(StringLengthWorkerW) | |
6308 #else | |
6309 #define StringCopyWorkerA StringCopyWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA; | |
6310 #define StringCopyWorkerW StringCopyWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW; | |
6311 #define StringCopyExWorkerA StringCopyExWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA; | |
6312 #define StringCopyExWorkerW StringCopyExWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW; | |
6313 #define StringCatWorkerA StringCatWorkerA_instead_use_StringCchCatA_or_StringCchCatExA; | |
6314 #define StringCatWorkerW StringCatWorkerW_instead_use_StringCchCatW_or_StringCchCatExW; | |
6315 #define StringCatExWorkerA StringCatExWorkerA_instead_use_StringCchCatA_or_StringCchCatExA; | |
6316 #define StringCatExWorkerW StringCatExWorkerW_instead_use_StringCchCatW_or_StringCchCatExW; | |
6317 #define StringCatNWorkerA StringCatNWorkerA_instead_use_StringCchCatNA_or_StrincCbCatNA; | |
6318 #define StringCatNWorkerW StringCatNWorkerW_instead_use_StringCchCatNW_or_StringCbCatNW; | |
6319 #define StringCatNExWorkerA StringCatNExWorkerA_instead_use_StringCchCatNExA_or_StringCbCatNExA; | |
6320 #define StringCatNExWorkerW StringCatNExWorkerW_instead_use_StringCchCatNExW_or_StringCbCatNExW; | |
6321 #define StringVPrintfWorkerA StringVPrintfWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA; | |
6322 #define StringVPrintfWorkerW StringVPrintfWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW; | |
6323 #define StringVPrintfExWorkerA StringVPrintfExWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA; | |
6324 #define StringVPrintfExWorkerW StringVPrintfExWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW; | |
6325 #define StringLengthWorkerA StringLengthWorkerA_instead_use_StringCchLengthA_or_StringCbLengthA; | |
6326 #define StringLengthWorkerW StringLengthWorkerW_instead_use_StringCchLengthW_or_StringCbLengthW; | |
6327 #endif // !DEPRECATE_SUPPORTED | |
6328 | |
6329 | |
6330 #ifndef STRSAFE_NO_DEPRECATE | |
6331 // Deprecate all of the unsafe functions to generate compiletime errors. If you do not want | |
6332 // this then you can #define STRSAFE_NO_DEPRECATE before including this file. | |
6333 #ifdef DEPRECATE_SUPPORTED | |
6334 | |
6335 // First all the names that are a/w variants (or shouldn't be #defined by now anyway). | |
6336 #pragma deprecated(lstrcpyA) | |
6337 #pragma deprecated(lstrcpyW) | |
6338 #pragma deprecated(lstrcatA) | |
6339 #pragma deprecated(lstrcatW) | |
6340 #pragma deprecated(wsprintfA) | |
6341 #pragma deprecated(wsprintfW) | |
6342 | |
6343 #pragma deprecated(StrCpyW) | |
6344 #pragma deprecated(StrCatW) | |
6345 #pragma deprecated(StrNCatA) | |
6346 #pragma deprecated(StrNCatW) | |
6347 #pragma deprecated(StrCatNA) | |
6348 #pragma deprecated(StrCatNW) | |
6349 #pragma deprecated(wvsprintfA) | |
6350 #pragma deprecated(wvsprintfW) | |
6351 | |
6352 #pragma deprecated(strcpy) | |
6353 #pragma deprecated(wcscpy) | |
6354 #pragma deprecated(strcat) | |
6355 #pragma deprecated(wcscat) | |
6356 #pragma deprecated(sprintf) | |
6357 #pragma deprecated(swprintf) | |
6358 #pragma deprecated(vsprintf) | |
6359 #pragma deprecated(vswprintf) | |
6360 #pragma deprecated(_snprintf) | |
6361 #pragma deprecated(_snwprintf) | |
6362 #pragma deprecated(_vsnprintf) | |
6363 #pragma deprecated(_vsnwprintf) | |
6364 #pragma deprecated(gets) | |
6365 #pragma deprecated(_getws) | |
6366 | |
6367 // Then all the windows.h names - we need to undef and redef based on UNICODE setting | |
6368 #undef lstrcpy | |
6369 #undef lstrcat | |
6370 #undef wsprintf | |
6371 #undef wvsprintf | |
6372 #pragma deprecated(lstrcpy) | |
6373 #pragma deprecated(lstrcat) | |
6374 #pragma deprecated(wsprintf) | |
6375 #pragma deprecated(wvsprintf) | |
6376 #ifdef UNICODE | |
6377 #define lstrcpy lstrcpyW | |
6378 #define lstrcat lstrcatW | |
6379 #define wsprintf wsprintfW | |
6380 #define wvsprintf wvsprintfW | |
6381 #else | |
6382 #define lstrcpy lstrcpyA | |
6383 #define lstrcat lstrcatA | |
6384 #define wsprintf wsprintfA | |
6385 #define wvsprintf wvsprintfA | |
6386 #endif | |
6387 | |
6388 // Then the shlwapi names - they key off UNICODE also. | |
6389 #undef StrCpyA | |
6390 #undef StrCpy | |
6391 #undef StrCatA | |
6392 #undef StrCat | |
6393 #undef StrNCat | |
6394 #undef StrCatN | |
6395 #pragma deprecated(StrCpyA) | |
6396 #pragma deprecated(StrCatA) | |
6397 #pragma deprecated(StrCatN) | |
6398 #pragma deprecated(StrCpy) | |
6399 #pragma deprecated(StrCat) | |
6400 #pragma deprecated(StrNCat) | |
6401 #define StrCpyA lstrcpyA | |
6402 #define StrCatA lstrcatA | |
6403 #define StrCatN StrNCat | |
6404 #ifdef UNICODE | |
6405 #define StrCpy StrCpyW | |
6406 #define StrCat StrCatW | |
6407 #define StrNCat StrNCatW | |
6408 #else | |
6409 #define StrCpy lstrcpyA | |
6410 #define StrCat lstrcatA | |
6411 #define StrNCat StrNCatA | |
6412 #endif | |
6413 | |
6414 // Then all the CRT names - we need to undef/redef based on _UNICODE value. | |
6415 #undef _tcscpy | |
6416 #undef _ftcscpy | |
6417 #undef _tcscat | |
6418 #undef _ftcscat | |
6419 #undef _stprintf | |
6420 #undef _sntprintf | |
6421 #undef _vstprintf | |
6422 #undef _vsntprintf | |
6423 #undef _getts | |
6424 #pragma deprecated(_tcscpy) | |
6425 #pragma deprecated(_ftcscpy) | |
6426 #pragma deprecated(_tcscat) | |
6427 #pragma deprecated(_ftcscat) | |
6428 #pragma deprecated(_stprintf) | |
6429 #pragma deprecated(_sntprintf) | |
6430 #pragma deprecated(_vstprintf) | |
6431 #pragma deprecated(_vsntprintf) | |
6432 #pragma deprecated(_getts) | |
6433 #ifdef _UNICODE | |
6434 #define _tcscpy wcscpy | |
6435 #define _ftcscpy wcscpy | |
6436 #define _tcscat wcscat | |
6437 #define _ftcscat wcscat | |
6438 #define _stprintf swprintf | |
6439 #define _sntprintf _snwprintf | |
6440 #define _vstprintf vswprintf | |
6441 #define _vsntprintf _vsnwprintf | |
6442 #define _getts _getws | |
6443 #else | |
6444 #define _tcscpy strcpy | |
6445 #define _ftcscpy strcpy | |
6446 #define _tcscat strcat | |
6447 #define _ftcscat strcat | |
6448 #define _stprintf sprintf | |
6449 #define _sntprintf _snprintf | |
6450 #define _vstprintf vsprintf | |
6451 #define _vsntprintf _vsnprintf | |
6452 #define _getts gets | |
6453 #endif | |
6454 | |
6455 #else // DEPRECATE_SUPPORTED | |
6456 | |
6457 #undef strcpy | |
6458 #define strcpy strcpy_instead_use_StringCbCopyA_or_StringCchCopyA; | |
6459 | |
6460 #undef wcscpy | |
6461 #define wcscpy wcscpy_instead_use_StringCbCopyW_or_StringCchCopyW; | |
6462 | |
6463 #undef strcat | |
6464 #define strcat strcat_instead_use_StringCbCatA_or_StringCchCatA; | |
6465 | |
6466 #undef wcscat | |
6467 #define wcscat wcscat_instead_use_StringCbCatW_or_StringCchCatW; | |
6468 | |
6469 #undef sprintf | |
6470 #define sprintf sprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA; | |
6471 | |
6472 #undef swprintf | |
6473 #define swprintf swprintf_instead_use_StringCbPrintfW_or_StringCchPrintfW; | |
6474 | |
6475 #undef vsprintf | |
6476 #define vsprintf vsprintf_instead_use_StringCbVPrintfA_or_StringCchVPrintfA; | |
6477 | |
6478 #undef vswprintf | |
6479 #define vswprintf vswprintf_instead_use_StringCbVPrintfW_or_StringCchVPrintfW; | |
6480 | |
6481 #undef _snprintf | |
6482 #define _snprintf _snprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA; | |
6483 | |
6484 #undef _snwprintf | |
6485 #define _snwprintf _snwprintf_instead_use_StringCbPrintfW_or_StringCchPrintfW; | |
6486 | |
6487 #undef _vsnprintf | |
6488 #define _vsnprintf _vsnprintf_instead_use_StringCbVPrintfA_or_StringCchVPrintfA; | |
6489 | |
6490 #undef _vsnwprintf | |
6491 #define _vsnwprintf _vsnwprintf_instead_use_StringCbVPrintfW_or_StringCchVPrintfW; | |
6492 | |
6493 #undef strcpyA | |
6494 #define strcpyA strcpyA_instead_use_StringCbCopyA_or_StringCchCopyA; | |
6495 | |
6496 #undef strcpyW | |
6497 #define strcpyW strcpyW_instead_use_StringCbCopyW_or_StringCchCopyW; | |
6498 | |
6499 #undef lstrcpy | |
6500 #define lstrcpy lstrcpy_instead_use_StringCbCopy_or_StringCchCopy; | |
6501 | |
6502 #undef lstrcpyA | |
6503 #define lstrcpyA lstrcpyA_instead_use_StringCbCopyA_or_StringCchCopyA; | |
6504 | |
6505 #undef lstrcpyW | |
6506 #define lstrcpyW lstrcpyW_instead_use_StringCbCopyW_or_StringCchCopyW; | |
6507 | |
6508 #undef StrCpy | |
6509 #define StrCpy StrCpy_instead_use_StringCbCopy_or_StringCchCopy; | |
6510 | |
6511 #undef StrCpyA | |
6512 #define StrCpyA StrCpyA_instead_use_StringCbCopyA_or_StringCchCopyA; | |
6513 | |
6514 #undef StrCpyW | |
6515 #define StrCpyW StrCpyW_instead_use_StringCbCopyW_or_StringCchCopyW; | |
6516 | |
6517 #undef _tcscpy | |
6518 #define _tcscpy _tcscpy_instead_use_StringCbCopy_or_StringCchCopy; | |
6519 | |
6520 #undef _ftcscpy | |
6521 #define _ftcscpy _ftcscpy_instead_use_StringCbCopy_or_StringCchCopy; | |
6522 | |
6523 #undef lstrcat | |
6524 #define lstrcat lstrcat_instead_use_StringCbCat_or_StringCchCat; | |
6525 | |
6526 #undef lstrcatA | |
6527 #define lstrcatA lstrcatA_instead_use_StringCbCatA_or_StringCchCatA; | |
6528 | |
6529 #undef lstrcatW | |
6530 #define lstrcatW lstrcatW_instead_use_StringCbCatW_or_StringCchCatW; | |
6531 | |
6532 #undef StrCat | |
6533 #define StrCat StrCat_instead_use_StringCbCat_or_StringCchCat; | |
6534 | |
6535 #undef StrCatA | |
6536 #define StrCatA StrCatA_instead_use_StringCbCatA_or_StringCchCatA; | |
6537 | |
6538 #undef StrCatW | |
6539 #define StrCatW StrCatW_instead_use_StringCbCatW_or_StringCchCatW; | |
6540 | |
6541 #undef StrNCat | |
6542 #define StrNCat StrNCat_instead_use_StringCbCatN_or_StringCchCatN; | |
6543 | |
6544 #undef StrNCatA | |
6545 #define StrNCatA StrNCatA_instead_use_StringCbCatNA_or_StringCchCatNA; | |
6546 | |
6547 #undef StrNCatW | |
6548 #define StrNCatW StrNCatW_instead_use_StringCbCatNW_or_StringCchCatNW; | |
6549 | |
6550 #undef StrCatN | |
6551 #define StrCatN StrCatN_instead_use_StringCbCatN_or_StringCchCatN; | |
6552 | |
6553 #undef StrCatNA | |
6554 #define StrCatNA StrCatNA_instead_use_StringCbCatNA_or_StringCchCatNA; | |
6555 | |
6556 #undef StrCatNW | |
6557 #define StrCatNW StrCatNW_instead_use_StringCbCatNW_or_StringCchCatNW; | |
6558 | |
6559 #undef _tcscat | |
6560 #define _tcscat _tcscat_instead_use_StringCbCat_or_StringCchCat; | |
6561 | |
6562 #undef _ftcscat | |
6563 #define _ftcscat _ftcscat_instead_use_StringCbCat_or_StringCchCat; | |
6564 | |
6565 #undef wsprintf | |
6566 #define wsprintf wsprintf_instead_use_StringCbPrintf_or_StringCchPrintf; | |
6567 | |
6568 #undef wsprintfA | |
6569 #define wsprintfA wsprintfA_instead_use_StringCbPrintfA_or_StringCchPrintfA; | |
6570 | |
6571 #undef wsprintfW | |
6572 #define wsprintfW wsprintfW_instead_use_StringCbPrintfW_or_StringCchPrintfW; | |
6573 | |
6574 #undef wvsprintf | |
6575 #define wvsprintf wvsprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf; | |
6576 | |
6577 #undef wvsprintfA | |
6578 #define wvsprintfA wvsprintfA_instead_use_StringCbVPrintfA_or_StringCchVPrintfA; | |
6579 | |
6580 #undef wvsprintfW | |
6581 #define wvsprintfW wvsprintfW_instead_use_StringCbVPrintfW_or_StringCchVPrintfW; | |
6582 | |
6583 #undef _vstprintf | |
6584 #define _vstprintf _vstprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf; | |
6585 | |
6586 #undef _vsntprintf | |
6587 #define _vsntprintf _vsntprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf; | |
6588 | |
6589 #undef _stprintf | |
6590 #define _stprintf _stprintf_instead_use_StringCbPrintf_or_StringCchPrintf; | |
6591 | |
6592 #undef _sntprintf | |
6593 #define _sntprintf _sntprintf_instead_use_StringCbPrintf_or_StringCchPrintf; | |
6594 | |
6595 #undef _getts | |
6596 #define _getts _getts_instead_use_StringCbGets_or_StringCchGets; | |
6597 | |
6598 #undef gets | |
6599 #define gets _gets_instead_use_StringCbGetsA_or_StringCchGetsA; | |
6600 | |
6601 #undef _getws | |
6602 #define _getws _getws_instead_use_StringCbGetsW_or_StringCchGetsW; | |
6603 | |
6604 #endif // !DEPRECATE_SUPPORTED | |
6605 #endif // !STRSAFE_NO_DEPRECATE | |
6606 | |
6607 #ifdef _NTSTRSAFE_H_INCLUDED_ | |
6608 #pragma warning(pop) | |
6609 #endif // _NTSTRSAFE_H_INCLUDED_ | |
6610 | |
6611 #endif // _STRSAFE_H_INCLUDED_ |