Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6798 lines
214 KiB

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