Fix and unify function prototypes for ntstrsafe functions taking variadic arguments.
[reactos.git] / sdk / include / ddk / ntstrsafe.h
1 /**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the w64 mingw-runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6 #ifndef _NTSTRSAFE_H_INCLUDED_
7 #define _NTSTRSAFE_H_INCLUDED_
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdarg.h>
12
13 #ifdef _MSC_VER
14 #pragma warning(push)
15 #pragma warning(disable:28719) /* disable banned api usage warning */
16 #endif /* _MSC_VER */
17
18 #ifndef C_ASSERT
19 #ifdef _MSC_VER
20 # define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
21 #else
22 # define C_ASSERT(e) extern void __C_ASSERT__(int [(e)?1:-1])
23 #endif
24 #endif /* C_ASSERT */
25
26 #ifdef __cplusplus
27 #define _STRSAFE_EXTERN_C extern "C"
28 #else
29 #define _STRSAFE_EXTERN_C extern
30 #endif
31
32 #define NTSTRSAFEAPI static __inline NTSTATUS NTAPI
33 #define NTSTRSAFEVAPI static __inline NTSTATUS __cdecl
34 #define NTSTRSAFE_INLINE_API static __inline NTSTATUS NTAPI
35
36 #ifndef NTSTRSAFE_MAX_CCH
37 #define NTSTRSAFE_MAX_CCH 2147483647
38 #endif
39
40 #ifndef NTSTRSAFE_UNICODE_STRING_MAX_CCH
41 #define NTSTRSAFE_UNICODE_STRING_MAX_CCH 32767
42 #endif
43
44 #ifndef _STRSAFE_H_INCLUDED_
45 #define STRSAFE_IGNORE_NULLS 0x00000100
46 #define STRSAFE_FILL_BEHIND_NULL 0x00000200
47 #define STRSAFE_FILL_ON_FAILURE 0x00000400
48 #define STRSAFE_NULL_ON_FAILURE 0x00000800
49 #define STRSAFE_NO_TRUNCATION 0x00001000
50 #define STRSAFE_IGNORE_NULL_UNICODE_STRINGS 0x00010000
51 #define STRSAFE_UNICODE_STRING_DEST_NULL_TERMINATED 0x00020000
52
53 #define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)
54 #define STRSAFE_UNICODE_STRING_VALID_FLAGS (STRSAFE_VALID_FLAGS | STRSAFE_IGNORE_NULL_UNICODE_STRINGS | STRSAFE_UNICODE_STRING_DEST_NULL_TERMINATED)
55
56 #define STRSAFE_FILL_BYTE(x) ((STRSAFE_DWORD)(((x) & 0x000000FF) | STRSAFE_FILL_BEHIND_NULL))
57 #define STRSAFE_FAILURE_BYTE(x) ((STRSAFE_DWORD)(((x) & 0x000000FF) | STRSAFE_FILL_ON_FAILURE))
58
59 #define STRSAFE_GET_FILL_PATTERN(dwFlags) ((int)((dwFlags) & 0x000000FF))
60 #endif
61
62 #define STRSAFE_FILL_BEHIND STRSAFE_FILL_BEHIND_NULL
63 #define STRSAFE_ZERO_LENGTH_ON_FAILURE STRSAFE_NULL_ON_FAILURE
64
65 typedef char *STRSAFE_LPSTR;
66 typedef const char *STRSAFE_LPCSTR;
67 typedef wchar_t *STRSAFE_LPWSTR;
68 typedef const wchar_t *STRSAFE_LPCWSTR;
69
70 typedef _Null_terminated_ char *NTSTRSAFE_PSTR;
71 typedef _Null_terminated_ const char *NTSTRSAFE_PCSTR;
72 typedef _Null_terminated_ wchar_t *NTSTRSAFE_PWSTR;
73 typedef _Null_terminated_ const wchar_t *NTSTRSAFE_PCWSTR;
74
75 typedef ULONG STRSAFE_DWORD;
76
77 NTSTRSAFEAPI RtlStringCopyWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc);
78 NTSTRSAFEAPI RtlStringCopyWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc);
79 NTSTRSAFEAPI RtlStringCopyExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCSTR pszSrc, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
80 NTSTRSAFEAPI RtlStringCopyExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
81 NTSTRSAFEAPI RtlStringCopyNWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc, size_t cchToCopy);
82 NTSTRSAFEAPI RtlStringCopyNWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, size_t cchToCopy);
83 NTSTRSAFEAPI RtlStringCopyNExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCSTR pszSrc, size_t cchToCopy, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
84 NTSTRSAFEAPI RtlStringCopyNExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, size_t cchToCopy, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
85 NTSTRSAFEAPI RtlStringCatWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc);
86 NTSTRSAFEAPI RtlStringCatWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc);
87 NTSTRSAFEAPI RtlStringCatExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCSTR pszSrc, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
88 NTSTRSAFEAPI RtlStringCatExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
89 NTSTRSAFEAPI RtlStringCatNWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc, size_t cchToAppend);
90 NTSTRSAFEAPI RtlStringCatNWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, size_t cchToAppend);
91 NTSTRSAFEAPI RtlStringCatNExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCSTR pszSrc, size_t cchToAppend, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
92 NTSTRSAFEAPI RtlStringCatNExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, size_t cchToAppend, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
93 NTSTRSAFEAPI RtlStringVPrintfWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszFormat, va_list argList);
94 NTSTRSAFEAPI RtlStringVPrintfWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat, va_list argList);
95 NTSTRSAFEAPI RtlStringVPrintfWorkerLenW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat, size_t* pcchDestNewLen, va_list argList);
96 NTSTRSAFEAPI RtlStringVPrintfExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCSTR pszFormat, va_list argList);
97 NTSTRSAFEAPI RtlStringVPrintfExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCWSTR pszFormat, va_list argList);
98 NTSTRSAFEAPI RtlStringVPrintfExWorkerLenW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCWSTR pszFormat, size_t* pcchDestNewLen, va_list argList);
99 NTSTRSAFEAPI RtlUnicodeStringValidate(PCUNICODE_STRING SourceString);
100
101 NTSTRSAFEAPI
102 RtlStringLengthWorkerA(
103 _In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz,
104 _In_ _In_range_(<=, NTSTRSAFE_MAX_CCH) size_t cchMax,
105 _Out_opt_ _Deref_out_range_(<, cchMax) size_t *pcchLength);
106
107 NTSTRSAFEAPI
108 RtlStringLengthWorkerW(
109 _In_reads_or_z_(cchMax) STRSAFE_LPCWSTR psz,
110 _In_ _In_range_(<=, NTSTRSAFE_MAX_CCH) size_t cchMax,
111 _Out_opt_ _Deref_out_range_(<, cchMax) size_t *pcchLength);
112
113 NTSTRSAFEAPI
114 RtlStringCchCopyA(
115 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
116 _In_ size_t cchDest,
117 _In_ NTSTRSAFE_PCSTR pszSrc);
118
119 NTSTRSAFEAPI
120 RtlStringCchCopyW(
121 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
122 _In_ size_t cchDest,
123 _In_ NTSTRSAFE_PCWSTR pszSrc);
124
125 NTSTRSAFEAPI
126 RtlStringCchCopyA(
127 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
128 _In_ size_t cchDest,
129 _In_ NTSTRSAFE_PCSTR pszSrc)
130 {
131 if (cchDest > NTSTRSAFE_MAX_CCH)
132 {
133 if (cchDest > 0)
134 *pszDest = '\0';
135
136 return STATUS_INVALID_PARAMETER;
137 }
138
139 return RtlStringCopyWorkerA(pszDest, cchDest, pszSrc);
140 }
141
142 NTSTRSAFEAPI
143 RtlStringCchCopyW(
144 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
145 _In_ size_t cchDest,
146 _In_ NTSTRSAFE_PCWSTR pszSrc)
147 {
148 if (cchDest > NTSTRSAFE_MAX_CCH)
149 {
150 if (cchDest > 0)
151 *pszDest = '\0';
152
153 return STATUS_INVALID_PARAMETER;
154 }
155
156 return RtlStringCopyWorkerW(pszDest, cchDest, pszSrc);
157 }
158
159 NTSTRSAFEAPI
160 RtlStringCbCopyA(
161 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
162 _In_ size_t cbDest,
163 _In_ NTSTRSAFE_PCSTR pszSrc);
164
165 NTSTRSAFEAPI
166 RtlStringCbCopyW(
167 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
168 _In_ size_t cbDest,
169 _In_ NTSTRSAFE_PCWSTR pszSrc);
170
171 NTSTRSAFEAPI
172 RtlStringCbCopyA(
173 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
174 _In_ size_t cbDest,
175 _In_ NTSTRSAFE_PCSTR pszSrc)
176 {
177 size_t cchDest = cbDest / sizeof(char);
178
179 if (cchDest > NTSTRSAFE_MAX_CCH)
180 {
181 if (cchDest > 0)
182 *pszDest = '\0';
183
184 return STATUS_INVALID_PARAMETER;
185 }
186 return RtlStringCopyWorkerA(pszDest, cbDest, pszSrc);
187 }
188
189 NTSTRSAFEAPI
190 RtlStringCbCopyW(
191 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
192 _In_ size_t cbDest,
193 _In_ NTSTRSAFE_PCWSTR pszSrc)
194 {
195 size_t cchDest = cbDest / sizeof(wchar_t);
196
197 if (cchDest > NTSTRSAFE_MAX_CCH)
198 {
199 if (cchDest > 0)
200 *pszDest = '\0';
201
202 return STATUS_INVALID_PARAMETER;
203 }
204 return RtlStringCopyWorkerW(pszDest, cchDest, pszSrc);
205 }
206
207 NTSTRSAFEAPI
208 RtlStringCchCopyExA(
209 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
210 _In_ size_t cchDest,
211 _In_ NTSTRSAFE_PCSTR pszSrc,
212 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
213 _Out_opt_ size_t *pcchRemaining,
214 _In_ STRSAFE_DWORD dwFlags);
215
216 NTSTRSAFEAPI
217 RtlStringCchCopyExW(
218 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
219 _In_ size_t cchDest,
220 _In_ NTSTRSAFE_PCWSTR pszSrc,
221 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
222 _Out_opt_ size_t *pcchRemaining,
223 _In_ STRSAFE_DWORD dwFlags);
224
225 NTSTRSAFEAPI
226 RtlStringCchCopyExA(
227 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
228 _In_ size_t cchDest,
229 _In_ NTSTRSAFE_PCSTR pszSrc,
230 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
231 _Out_opt_ size_t *pcchRemaining,
232 _In_ STRSAFE_DWORD dwFlags)
233 {
234 if (cchDest > NTSTRSAFE_MAX_CCH)
235 {
236 if (cchDest > 0)
237 *pszDest = '\0';
238
239 return STATUS_INVALID_PARAMETER;
240 }
241
242 return RtlStringCopyExWorkerA(pszDest, cchDest, cchDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
243 }
244
245 NTSTRSAFEAPI
246 RtlStringCchCopyExW(
247 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
248 _In_ size_t cchDest,
249 _In_ NTSTRSAFE_PCWSTR pszSrc,
250 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
251 _Out_opt_ size_t *pcchRemaining,
252 _In_ STRSAFE_DWORD dwFlags)
253 {
254 size_t cbDest = cchDest * sizeof(wchar_t);
255
256 if (cchDest > NTSTRSAFE_MAX_CCH)
257 {
258 if (cchDest > 0)
259 *pszDest = L'\0';
260
261 return STATUS_INVALID_PARAMETER;
262 }
263
264 return RtlStringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
265 }
266
267 NTSTRSAFEAPI
268 RtlStringCbCopyExA(
269 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
270 _In_ size_t cbDest,
271 _In_ NTSTRSAFE_PCSTR pszSrc,
272 _Outptr_opt_result_bytebuffer_(*pcbRemaining) STRSAFE_LPSTR *ppszDestEnd,
273 _Out_opt_ size_t *pcbRemaining,
274 _In_ STRSAFE_DWORD dwFlags);
275
276 NTSTRSAFEAPI
277 RtlStringCbCopyExW(
278 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
279 _In_ size_t cbDest,
280 _In_ NTSTRSAFE_PCWSTR pszSrc,
281 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
282 _Out_opt_ size_t *pcbRemaining,
283 _In_ STRSAFE_DWORD dwFlags);
284
285 NTSTRSAFEAPI
286 RtlStringCbCopyExA(
287 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
288 _In_ size_t cbDest,
289 _In_ NTSTRSAFE_PCSTR pszSrc,
290 _Outptr_opt_result_bytebuffer_(*pcbRemaining) STRSAFE_LPSTR *ppszDestEnd,
291 _Out_opt_ size_t *pcbRemaining,
292 _In_ STRSAFE_DWORD dwFlags)
293 {
294 NTSTATUS Status;
295 size_t cchDest = cbDest / sizeof(char);
296 size_t cchRemaining = 0;
297
298 if (cchDest > NTSTRSAFE_MAX_CCH)
299 {
300 if (cchDest > 0)
301 *pszDest = '\0';
302
303 return STATUS_INVALID_PARAMETER;
304 }
305
306 Status = RtlStringCopyExWorkerA(pszDest, cbDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
307 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
308 {
309 if (pcbRemaining)
310 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
311 }
312 return Status;
313 }
314
315 NTSTRSAFEAPI
316 RtlStringCbCopyExW(
317 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
318 _In_ size_t cbDest,
319 _In_ NTSTRSAFE_PCWSTR pszSrc,
320 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
321 _Out_opt_ size_t *pcbRemaining,
322 _In_ STRSAFE_DWORD dwFlags)
323 {
324 NTSTATUS Status;
325 size_t cchDest = cbDest / sizeof(wchar_t);
326 size_t cchRemaining = 0;
327
328 if (cchDest > NTSTRSAFE_MAX_CCH)
329 {
330 if (cchDest > 0)
331 *pszDest = L'\0';
332
333 return STATUS_INVALID_PARAMETER;
334 }
335
336 Status = RtlStringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
337 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
338 {
339 if (pcbRemaining)
340 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
341 }
342 return Status;
343 }
344
345 NTSTRSAFEAPI
346 RtlStringCchCopyNA(
347 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
348 _In_ size_t cchDest,
349 _In_reads_or_z_(cchToCopy) STRSAFE_LPCSTR pszSrc,
350 _In_ size_t cchToCopy);
351
352 NTSTRSAFEAPI
353 RtlStringCchCopyNW(
354 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
355 _In_ size_t cchDest,
356 _In_reads_or_z_(cchToCopy) STRSAFE_LPCWSTR pszSrc,
357 _In_ size_t cchToCopy);
358
359
360 NTSTRSAFEAPI
361 RtlStringCchCopyNA(
362 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
363 _In_ size_t cchDest,
364 _In_reads_or_z_(cchToCopy) STRSAFE_LPCSTR pszSrc,
365 _In_ size_t cchToCopy)
366 {
367 if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
368 {
369 if (cchDest > 0)
370 *pszDest = '\0';
371
372 return STATUS_INVALID_PARAMETER;
373 }
374
375 return RtlStringCopyNWorkerA(pszDest, cchDest, pszSrc, cchToCopy);
376 }
377
378 NTSTRSAFEAPI
379 RtlStringCchCopyNW(
380 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
381 _In_ size_t cchDest,
382 _In_reads_or_z_(cchToCopy) STRSAFE_LPCWSTR pszSrc,
383 _In_ size_t cchToCopy)
384 {
385 if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
386 {
387 if (cchDest > 0)
388 *pszDest = L'\0';
389
390 return STATUS_INVALID_PARAMETER;
391 }
392
393 return RtlStringCopyNWorkerW(pszDest, cchDest, pszSrc, cchToCopy);
394 }
395
396 NTSTRSAFEAPI
397 RtlStringCbCopyNA(
398 _Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest,
399 _In_ size_t cbDest,
400 _In_reads_bytes_(cbToCopy) STRSAFE_LPCSTR pszSrc,
401 _In_ size_t cbToCopy);
402
403 NTSTRSAFEAPI
404 RtlStringCbCopyNW(
405 _Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
406 _In_ size_t cbDest,
407 _In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc,
408 _In_ size_t cbToCopy);
409
410 NTSTRSAFEAPI
411 RtlStringCbCopyNA(
412 _Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest,
413 _In_ size_t cbDest,
414 _In_reads_bytes_(cbToCopy) STRSAFE_LPCSTR pszSrc,
415 _In_ size_t cbToCopy)
416 {
417 size_t cchDest = cbDest / sizeof(char);
418 size_t cchToCopy = cbToCopy / sizeof(char);
419
420 if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
421 {
422 if (cchDest > 0)
423 *pszDest = '\0';
424
425 return STATUS_INVALID_PARAMETER;
426 }
427
428 return RtlStringCopyNWorkerA(pszDest, cchDest, pszSrc, cchToCopy);
429 }
430
431 NTSTRSAFEAPI
432 RtlStringCbCopyNW(
433 _Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
434 _In_ size_t cbDest,
435 _In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc,
436 _In_ size_t cbToCopy)
437 {
438 size_t cchDest = cbDest / sizeof(wchar_t);
439 size_t cchToCopy = cbToCopy / sizeof(wchar_t);
440
441 if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
442 {
443 if (cchDest > 0)
444 *pszDest = L'\0';
445
446 return STATUS_INVALID_PARAMETER;
447 }
448
449 return RtlStringCopyNWorkerW(pszDest, cchDest, pszSrc, cchToCopy);
450 }
451
452 NTSTRSAFEAPI
453 RtlStringCchCopyNExA(
454 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
455 _In_ size_t cchDest,
456 _In_reads_or_z_(cchToCopy) STRSAFE_LPCSTR pszSrc,
457 _In_ size_t cchToCopy,
458 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
459 _Out_opt_ size_t *pcchRemaining,
460 _In_ STRSAFE_DWORD dwFlags);
461
462 NTSTRSAFEAPI
463 RtlStringCchCopyNExW(
464 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
465 _In_ size_t cchDest,
466 _In_reads_or_z_(cchToCopy) STRSAFE_LPCWSTR pszSrc,
467 _In_ size_t cchToCopy,
468 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
469 _Out_opt_ size_t *pcchRemaining,
470 _In_ STRSAFE_DWORD dwFlags);
471
472 NTSTRSAFEAPI
473 RtlStringCchCopyNExA(
474 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
475 _In_ size_t cchDest,
476 _In_reads_or_z_(cchToCopy) STRSAFE_LPCSTR pszSrc,
477 _In_ size_t cchToCopy,
478 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
479 _Out_opt_ size_t *pcchRemaining,
480 _In_ STRSAFE_DWORD dwFlags)
481 {
482 if (cchDest > NTSTRSAFE_MAX_CCH)
483 {
484 if (cchDest > 0)
485 *pszDest = '\0';
486
487 return STATUS_INVALID_PARAMETER;
488 }
489
490 return RtlStringCopyNExWorkerA(pszDest, cchDest, cchDest, pszSrc, cchToCopy, ppszDestEnd, pcchRemaining, dwFlags);
491 }
492
493 NTSTRSAFEAPI
494 RtlStringCchCopyNExW(
495 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
496 _In_ size_t cchDest,
497 _In_reads_or_z_(cchToCopy) STRSAFE_LPCWSTR pszSrc,
498 _In_ size_t cchToCopy,
499 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
500 _Out_opt_ size_t *pcchRemaining,
501 _In_ STRSAFE_DWORD dwFlags)
502 {
503 if (cchDest > NTSTRSAFE_MAX_CCH)
504 {
505 if (cchDest > 0)
506 *pszDest = L'\0';
507
508 return STATUS_INVALID_PARAMETER;
509 }
510
511 return RtlStringCopyNExWorkerW(pszDest, cchDest, cchDest * sizeof(wchar_t), pszSrc, cchToCopy, ppszDestEnd, pcchRemaining, dwFlags);
512 }
513
514 NTSTRSAFEAPI
515 RtlStringCbCopyNExA(
516 _Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest,
517 _In_ size_t cbDest,
518 _In_reads_bytes_(cbToCopy) STRSAFE_LPCSTR pszSrc,
519 _In_ size_t cbToCopy,
520 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
521 _Out_opt_ size_t *pcbRemaining,
522 _In_ STRSAFE_DWORD dwFlags);
523
524 NTSTRSAFEAPI
525 RtlStringCbCopyNExW(
526 _Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
527 _In_ size_t cbDest,
528 _In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc,
529 _In_ size_t cbToCopy,
530 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
531 _Out_opt_ size_t *pcbRemaining,
532 _In_ STRSAFE_DWORD dwFlags);
533
534 NTSTRSAFEAPI
535 RtlStringCbCopyNExA(
536 _Out_writes_bytes_(cbDest) STRSAFE_LPSTR pszDest,
537 _In_ size_t cbDest,
538 _In_reads_bytes_(cbToCopy) STRSAFE_LPCSTR pszSrc,
539 _In_ size_t cbToCopy,
540 _Outptr_opt_result_bytebuffer_(*pcbRemaining) STRSAFE_LPSTR *ppszDestEnd,
541 _Out_opt_ size_t *pcbRemaining,
542 _In_ STRSAFE_DWORD dwFlags)
543 {
544 NTSTATUS Status;
545 size_t cchRemaining = 0;
546
547 if (cbDest > NTSTRSAFE_MAX_CCH)
548 {
549 if ((pszDest != NULL) && (cbDest > 0))
550 *pszDest = L'\0';
551
552 return STATUS_INVALID_PARAMETER;
553 }
554
555 Status = RtlStringCopyNExWorkerA(pszDest, cbDest, cbDest, pszSrc, cbToCopy, ppszDestEnd, &cchRemaining, dwFlags);
556 if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
557 *pcbRemaining = cchRemaining;
558
559 return Status;
560 }
561
562 NTSTRSAFEAPI
563 RtlStringCbCopyNExW(
564 _Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
565 _In_ size_t cbDest,
566 _In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc,
567 _In_ size_t cbToCopy,
568 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
569 _Out_opt_ size_t *pcbRemaining,
570 _In_ STRSAFE_DWORD dwFlags)
571 {
572 NTSTATUS Status;
573 size_t cchDest = cbDest / sizeof(wchar_t);
574 size_t cchToCopy = cbToCopy / sizeof(wchar_t);
575 size_t cchRemaining = 0;
576
577 if (cchDest > NTSTRSAFE_MAX_CCH)
578 {
579 if ((pszDest != NULL) && (cbDest > 0))
580 *pszDest = L'\0';
581
582 return STATUS_INVALID_PARAMETER;
583 }
584
585 Status = RtlStringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchToCopy, ppszDestEnd, &cchRemaining, dwFlags);
586 if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
587 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
588
589 return Status;
590 }
591
592 NTSTRSAFEAPI
593 RtlStringCchCatA(
594 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
595 _In_ size_t cchDest,
596 _In_ NTSTRSAFE_PCSTR pszSrc);
597
598 NTSTRSAFEAPI
599 RtlStringCchCatW(
600 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
601 _In_ size_t cchDest,
602 _In_ NTSTRSAFE_PCWSTR pszSrc);
603
604 NTSTRSAFEAPI
605 RtlStringCchCatA(
606 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
607 _In_ size_t cchDest,
608 _In_ NTSTRSAFE_PCSTR pszSrc)
609 {
610 if (cchDest > NTSTRSAFE_MAX_CCH)
611 return STATUS_INVALID_PARAMETER;
612
613 return RtlStringCatWorkerA(pszDest, cchDest, pszSrc);
614 }
615
616 NTSTRSAFEAPI
617 RtlStringCchCatW(
618 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
619 _In_ size_t cchDest,
620 _In_ NTSTRSAFE_PCWSTR pszSrc)
621 {
622 if (cchDest > NTSTRSAFE_MAX_CCH)
623 return STATUS_INVALID_PARAMETER;
624
625 return RtlStringCatWorkerW(pszDest, cchDest, pszSrc);
626 }
627
628 NTSTRSAFEAPI
629 RtlStringCbCatA(
630 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
631 _In_ size_t cbDest,
632 _In_ NTSTRSAFE_PCSTR pszSrc);
633
634 NTSTRSAFEAPI
635 RtlStringCbCatW(
636 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
637 _In_ size_t cbDest,
638 _In_ NTSTRSAFE_PCWSTR pszSrc);
639
640 NTSTRSAFEAPI
641 RtlStringCbCatA(
642 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
643 _In_ size_t cbDest,
644 _In_ NTSTRSAFE_PCSTR pszSrc)
645 {
646 if (cbDest > NTSTRSAFE_MAX_CCH)
647 return STATUS_INVALID_PARAMETER;
648 return RtlStringCatWorkerA(pszDest, cbDest, pszSrc);
649 }
650
651 NTSTRSAFEAPI
652 RtlStringCbCatW(
653 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
654 _In_ size_t cbDest,
655 _In_ NTSTRSAFE_PCWSTR pszSrc)
656 {
657 size_t cchDest = cbDest / sizeof(wchar_t);
658
659 if (cchDest > NTSTRSAFE_MAX_CCH)
660 return STATUS_INVALID_PARAMETER;
661
662 return RtlStringCatWorkerW(pszDest, cchDest, pszSrc);
663 }
664
665 NTSTRSAFEAPI
666 RtlStringCchCatExA(
667 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
668 _In_ size_t cchDest,
669 _In_ NTSTRSAFE_PCSTR pszSrc,
670 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
671 _Out_opt_ size_t *pcchRemaining,
672 _In_ STRSAFE_DWORD dwFlags);
673
674 NTSTRSAFEAPI
675 RtlStringCchCatExW(
676 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
677 _In_ size_t cchDest,
678 _In_ NTSTRSAFE_PCWSTR pszSrc,
679 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
680 _Out_opt_ size_t *pcchRemaining,
681 _In_ STRSAFE_DWORD dwFlags);
682
683 NTSTRSAFEAPI
684 RtlStringCchCatExA(
685 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
686 _In_ size_t cchDest,
687 _In_ NTSTRSAFE_PCSTR pszSrc,
688 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
689 _Out_opt_ size_t *pcchRemaining,
690 _In_ STRSAFE_DWORD dwFlags)
691 {
692 if (cchDest > NTSTRSAFE_MAX_CCH)
693 return STATUS_INVALID_PARAMETER;
694
695 return RtlStringCatExWorkerA(pszDest, cchDest, cchDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
696 }
697
698 NTSTRSAFEAPI
699 RtlStringCchCatExW(
700 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
701 _In_ size_t cchDest,
702 _In_ NTSTRSAFE_PCWSTR pszSrc,
703 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
704 _Out_opt_ size_t *pcchRemaining,
705 _In_ STRSAFE_DWORD dwFlags)
706 {
707 size_t cbDest = cchDest * sizeof(wchar_t);
708
709 if (cchDest > NTSTRSAFE_MAX_CCH)
710 return STATUS_INVALID_PARAMETER;
711
712 return RtlStringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
713 }
714
715 NTSTRSAFEAPI
716 RtlStringCbCatExA(
717 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
718 _In_ size_t cbDest,
719 _In_ NTSTRSAFE_PCSTR pszSrc,
720 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
721 _Out_opt_ size_t *pcbRemaining,
722 _In_ STRSAFE_DWORD dwFlags);
723
724 NTSTRSAFEAPI
725 RtlStringCbCatExW(
726 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
727 _In_ size_t cbDest,
728 _In_ NTSTRSAFE_PCWSTR pszSrc,
729 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
730 _Out_opt_ size_t *pcbRemaining,
731 _In_ STRSAFE_DWORD dwFlags);
732
733 NTSTRSAFEAPI
734 RtlStringCbCatExA(
735 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
736 _In_ size_t cbDest,
737 _In_ NTSTRSAFE_PCSTR pszSrc,
738 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
739 _Out_opt_ size_t *pcbRemaining,
740 _In_ STRSAFE_DWORD dwFlags)
741 {
742 NTSTATUS Status;
743 size_t cchRemaining = 0;
744
745 if (cbDest > NTSTRSAFE_MAX_CCH)
746 Status = STATUS_INVALID_PARAMETER;
747 else
748 Status = RtlStringCatExWorkerA(pszDest, cbDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
749
750 if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
751 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
752
753 return Status;
754 }
755
756 NTSTRSAFEAPI
757 RtlStringCbCatExW(
758 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
759 _In_ size_t cbDest,
760 _In_ NTSTRSAFE_PCWSTR pszSrc,
761 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
762 _Out_opt_ size_t *pcbRemaining,
763 _In_ STRSAFE_DWORD dwFlags)
764 {
765 NTSTATUS Status;
766 size_t cchDest = cbDest / sizeof(wchar_t);
767 size_t cchRemaining = 0;
768
769 if (cchDest > NTSTRSAFE_MAX_CCH)
770 Status = STATUS_INVALID_PARAMETER;
771 else
772 Status = RtlStringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
773
774 if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
775 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
776
777 return Status;
778 }
779
780 NTSTRSAFEAPI
781 RtlStringCchCatNA(
782 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
783 _In_ size_t cchDest,
784 _In_reads_or_z_(cchToAppend) STRSAFE_LPCSTR pszSrc,
785 _In_ size_t cchToAppend);
786
787 NTSTRSAFEAPI
788 RtlStringCchCatNW(
789 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
790 _In_ size_t cchDest,
791 _In_reads_or_z_(cchToAppend) STRSAFE_LPCWSTR pszSrc,
792 _In_ size_t cchToAppend);
793
794 NTSTRSAFEAPI
795 RtlStringCchCatNA(
796 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
797 _In_ size_t cchDest,
798 _In_reads_or_z_(cchToAppend) STRSAFE_LPCSTR pszSrc,
799 _In_ size_t cchToAppend)
800 {
801 if (cchDest > NTSTRSAFE_MAX_CCH)
802 return STATUS_INVALID_PARAMETER;
803
804 return RtlStringCatNWorkerA(pszDest, cchDest, pszSrc, cchToAppend);
805 }
806
807 NTSTRSAFEAPI
808 RtlStringCchCatNW(
809 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
810 _In_ size_t cchDest,
811 _In_reads_or_z_(cchToAppend) STRSAFE_LPCWSTR pszSrc,
812 _In_ size_t cchToAppend)
813 {
814 if (cchDest > NTSTRSAFE_MAX_CCH)
815 return STATUS_INVALID_PARAMETER;
816
817 return RtlStringCatNWorkerW(pszDest, cchDest, pszSrc, cchToAppend);
818 }
819
820 NTSTRSAFEAPI
821 RtlStringCbCatNA(
822 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
823 _In_ size_t cbDest,
824 _In_reads_bytes_(cbToAppend) STRSAFE_LPCSTR pszSrc,
825 _In_ size_t cbToAppend);
826
827 NTSTRSAFEAPI
828 RtlStringCbCatNW(
829 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
830 _In_ size_t cbDest,
831 _In_reads_bytes_(cbToAppend) STRSAFE_LPCWSTR pszSrc,
832 _In_ size_t cbToAppend);
833
834 NTSTRSAFEAPI
835 RtlStringCbCatNA(
836 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
837 _In_ size_t cbDest,
838 _In_reads_bytes_(cbToAppend) STRSAFE_LPCSTR pszSrc,
839 _In_ size_t cbToAppend)
840 {
841 if (cbDest > NTSTRSAFE_MAX_CCH)
842 return STATUS_INVALID_PARAMETER;
843
844 return RtlStringCatNWorkerA(pszDest, cbDest, pszSrc, cbToAppend);
845 }
846
847 NTSTRSAFEAPI
848 RtlStringCbCatNW(
849 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
850 _In_ size_t cbDest,
851 _In_reads_bytes_(cbToAppend) STRSAFE_LPCWSTR pszSrc,
852 _In_ size_t cbToAppend)
853 {
854 size_t cchDest = cbDest / sizeof(wchar_t);
855 size_t cchToAppend = cbToAppend / sizeof(wchar_t);
856
857 if (cchDest > NTSTRSAFE_MAX_CCH)
858 return STATUS_INVALID_PARAMETER;
859
860 return RtlStringCatNWorkerW(pszDest, cchDest, pszSrc, cchToAppend);
861 }
862
863 NTSTRSAFEAPI
864 RtlStringCchCatNExA(
865 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
866 _In_ size_t cchDest,
867 _In_reads_or_z_(cchToAppend) STRSAFE_LPCSTR pszSrc,
868 _In_ size_t cchToAppend,
869 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
870 _Out_opt_ size_t *pcchRemaining,
871 _In_ STRSAFE_DWORD dwFlags);
872
873 NTSTRSAFEAPI
874 RtlStringCchCatNExW(
875 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
876 _In_ size_t cchDest,
877 _In_reads_or_z_(cchToAppend) STRSAFE_LPCWSTR pszSrc,
878 _In_ size_t cchToAppend,
879 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
880 _Out_opt_ size_t *pcchRemaining,
881 _In_ STRSAFE_DWORD dwFlags);
882
883 NTSTRSAFEAPI
884 RtlStringCchCatNExA(
885 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
886 _In_ size_t cchDest,
887 _In_reads_or_z_(cchToAppend) STRSAFE_LPCSTR pszSrc,
888 _In_ size_t cchToAppend,
889 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
890 _Out_opt_ size_t *pcchRemaining,
891 _In_ STRSAFE_DWORD dwFlags)
892 {
893 if (cchDest > NTSTRSAFE_MAX_CCH)
894 return STATUS_INVALID_PARAMETER;
895
896 return RtlStringCatNExWorkerA(pszDest, cchDest, cchDest, pszSrc, cchToAppend, ppszDestEnd, pcchRemaining, dwFlags);
897 }
898
899 NTSTRSAFEAPI
900 RtlStringCchCatNExW(
901 _Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
902 _In_ size_t cchDest,
903 _In_reads_or_z_(cchToAppend) STRSAFE_LPCWSTR pszSrc,
904 _In_ size_t cchToAppend,
905 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
906 _Out_opt_ size_t *pcchRemaining,
907 _In_ STRSAFE_DWORD dwFlags)
908 {
909 if (cchDest > NTSTRSAFE_MAX_CCH)
910 return STATUS_INVALID_PARAMETER;
911
912 return RtlStringCatNExWorkerW(pszDest, cchDest, (cchDest * sizeof(wchar_t)), pszSrc, cchToAppend, ppszDestEnd, pcchRemaining, dwFlags);
913 }
914
915 NTSTRSAFEAPI
916 RtlStringCbCatNExA(
917 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
918 _In_ size_t cbDest,
919 _In_reads_bytes_(cbToAppend) STRSAFE_LPCSTR pszSrc,
920 _In_ size_t cbToAppend,
921 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
922 _Out_opt_ size_t *pcbRemaining,
923 _In_ STRSAFE_DWORD dwFlags);
924
925 NTSTRSAFEAPI
926 RtlStringCbCatNExW(
927 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
928 _In_ size_t cbDest,
929 _In_reads_bytes_(cbToAppend) STRSAFE_LPCWSTR pszSrc,
930 _In_ size_t cbToAppend,
931 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
932 _Out_opt_ size_t *pcbRemaining,
933 _In_ STRSAFE_DWORD dwFlags);
934
935 NTSTRSAFEAPI
936 RtlStringCbCatNExA(
937 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
938 _In_ size_t cbDest,
939 _In_reads_bytes_(cbToAppend) STRSAFE_LPCSTR pszSrc,
940 _In_ size_t cbToAppend,
941 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
942 _Out_opt_ size_t *pcbRemaining,
943 _In_ STRSAFE_DWORD dwFlags)
944 {
945 NTSTATUS Status;
946 size_t cchRemaining = 0;
947
948 if (cbDest > NTSTRSAFE_MAX_CCH)
949 Status = STATUS_INVALID_PARAMETER;
950 else
951 Status = RtlStringCatNExWorkerA(pszDest, cbDest, cbDest, pszSrc, cbToAppend, ppszDestEnd, &cchRemaining, dwFlags);
952
953 if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
954 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
955
956 return Status;
957 }
958
959 NTSTRSAFEAPI
960 RtlStringCbCatNExW(
961 _Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
962 _In_ size_t cbDest,
963 _In_reads_bytes_(cbToAppend) STRSAFE_LPCWSTR pszSrc,
964 _In_ size_t cbToAppend,
965 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
966 _Out_opt_ size_t *pcbRemaining,
967 _In_ STRSAFE_DWORD dwFlags)
968 {
969 NTSTATUS Status;
970 size_t cchDest = cbDest / sizeof(wchar_t);
971 size_t cchToAppend = cbToAppend / sizeof(wchar_t);
972 size_t cchRemaining = 0;
973
974 if (cchDest > NTSTRSAFE_MAX_CCH)
975 Status = STATUS_INVALID_PARAMETER;
976 else
977 Status = RtlStringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchToAppend, ppszDestEnd, &cchRemaining, dwFlags);
978
979 if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
980 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
981
982 return Status;
983 }
984
985 NTSTRSAFEAPI
986 RtlStringCchVPrintfA(
987 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
988 _In_ size_t cchDest,
989 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
990 _In_ va_list argList);
991
992 NTSTRSAFEAPI
993 RtlStringCchVPrintfW(
994 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
995 _In_ size_t cchDest,
996 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
997 _In_ va_list argList);
998
999 NTSTRSAFEAPI
1000 RtlStringCchVPrintfA(
1001 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1002 _In_ size_t cchDest,
1003 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1004 _In_ va_list argList)
1005 {
1006 if (cchDest > NTSTRSAFE_MAX_CCH)
1007 {
1008 if (cchDest > 0)
1009 *pszDest = '\0';
1010
1011 return STATUS_INVALID_PARAMETER;
1012 }
1013
1014 return RtlStringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
1015 }
1016
1017 NTSTRSAFEAPI
1018 RtlStringCchVPrintfW(
1019 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1020 _In_ size_t cchDest,
1021 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1022 _In_ va_list argList)
1023 {
1024 if (cchDest > NTSTRSAFE_MAX_CCH)
1025 {
1026 if (cchDest > 0)
1027 *pszDest = L'\0';
1028
1029 return STATUS_INVALID_PARAMETER;
1030 }
1031
1032 return RtlStringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
1033 }
1034
1035 NTSTRSAFEAPI
1036 RtlStringCbVPrintfA(
1037 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1038 _In_ size_t cbDest,
1039 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1040 _In_ va_list argList);
1041
1042 NTSTRSAFEAPI
1043 RtlStringCbVPrintfW(
1044 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1045 _In_ size_t cbDest,
1046 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1047 _In_ va_list argList);
1048
1049 NTSTRSAFEAPI
1050 RtlStringCbVPrintfA(
1051 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1052 _In_ size_t cbDest,
1053 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1054 _In_ va_list argList)
1055 {
1056 if (cbDest > NTSTRSAFE_MAX_CCH)
1057 {
1058 if (cbDest > 0)
1059 *pszDest = '\0';
1060
1061 return STATUS_INVALID_PARAMETER;
1062 }
1063
1064 return RtlStringVPrintfWorkerA(pszDest, cbDest, pszFormat, argList);
1065 }
1066
1067 NTSTRSAFEAPI
1068 RtlStringCbVPrintfW(
1069 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1070 _In_ size_t cbDest,
1071 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1072 _In_ va_list argList)
1073 {
1074 size_t cchDest = cbDest / sizeof(wchar_t);
1075
1076 if (cchDest > NTSTRSAFE_MAX_CCH)
1077 {
1078 if (cchDest > 0)
1079 *pszDest = L'\0';
1080 return STATUS_INVALID_PARAMETER;
1081 }
1082
1083 return RtlStringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
1084 }
1085
1086 NTSTRSAFEVAPI
1087 RtlStringCchPrintfA(
1088 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1089 _In_ size_t cchDest,
1090 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1091 ...);
1092
1093 NTSTRSAFEVAPI
1094 RtlStringCchPrintfW(
1095 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1096 _In_ size_t cchDest,
1097 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1098 ...);
1099
1100 NTSTRSAFEVAPI
1101 RtlStringCchPrintfA(
1102 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1103 _In_ size_t cchDest,
1104 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1105 ...)
1106 {
1107 NTSTATUS Status;
1108 va_list argList;
1109
1110 if (cchDest > NTSTRSAFE_MAX_CCH)
1111 {
1112 if (cchDest > 0)
1113 *pszDest = '\0';
1114
1115 return STATUS_INVALID_PARAMETER;
1116 }
1117
1118 va_start(argList, pszFormat);
1119 Status = RtlStringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
1120 va_end(argList);
1121
1122 return Status;
1123 }
1124
1125 NTSTRSAFEVAPI
1126 RtlStringCchPrintfW(
1127 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1128 _In_ size_t cchDest,
1129 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1130 ...)
1131 {
1132 NTSTATUS Status;
1133 va_list argList;
1134
1135 if (cchDest > NTSTRSAFE_MAX_CCH)
1136 {
1137 if (cchDest > 0)
1138 *pszDest = L'\0';
1139 return STATUS_INVALID_PARAMETER;
1140 }
1141
1142 va_start(argList, pszFormat);
1143 Status = RtlStringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
1144 va_end(argList);
1145
1146 return Status;
1147 }
1148
1149 NTSTRSAFEVAPI
1150 RtlStringCbPrintfA(
1151 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1152 _In_ size_t cbDest,
1153 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1154 ...);
1155
1156 NTSTRSAFEVAPI
1157 RtlStringCbPrintfW(
1158 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1159 _In_ size_t cbDest,
1160 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1161 ...);
1162
1163 NTSTRSAFEVAPI
1164 RtlStringCbPrintfA(
1165 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1166 _In_ size_t cbDest,
1167 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1168 ...)
1169 {
1170 NTSTATUS Status;
1171 va_list argList;
1172
1173 if (cbDest > NTSTRSAFE_MAX_CCH)
1174 {
1175 if (cbDest > 0)
1176 *pszDest = '\0';
1177
1178 return STATUS_INVALID_PARAMETER;
1179 }
1180
1181 va_start(argList, pszFormat);
1182 Status = RtlStringVPrintfWorkerA(pszDest, cbDest, pszFormat, argList);
1183 va_end(argList);
1184
1185 return Status;
1186 }
1187
1188 NTSTRSAFEVAPI
1189 RtlStringCbPrintfW(
1190 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1191 _In_ size_t cbDest,
1192 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1193 ...)
1194 {
1195 NTSTATUS Status;
1196 va_list argList;
1197 size_t cchDest = cbDest / sizeof(wchar_t);
1198
1199 if (cchDest > NTSTRSAFE_MAX_CCH)
1200 {
1201 if (cchDest > 0)
1202 *pszDest = L'\0';
1203 return STATUS_INVALID_PARAMETER;
1204 }
1205
1206 va_start(argList, pszFormat);
1207 Status = RtlStringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
1208 va_end(argList);
1209
1210 return Status;
1211 }
1212
1213 NTSTRSAFEVAPI
1214 RtlStringCchPrintfExA(
1215 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1216 _In_ size_t cchDest,
1217 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
1218 _Out_opt_ size_t *pcchRemaining,
1219 _In_ STRSAFE_DWORD dwFlags,
1220 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1221 ...);
1222
1223 NTSTRSAFEVAPI
1224 RtlStringCchPrintfExW(
1225 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1226 _In_ size_t cchDest,
1227 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
1228 _Out_opt_ size_t *pcchRemaining,
1229 _In_ STRSAFE_DWORD dwFlags,
1230 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1231 ...);
1232
1233 NTSTRSAFEVAPI
1234 RtlStringCchPrintfExA(
1235 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1236 _In_ size_t cchDest,
1237 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
1238 _Out_opt_ size_t *pcchRemaining,
1239 _In_ STRSAFE_DWORD dwFlags,
1240 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1241 ...)
1242 {
1243 NTSTATUS Status;
1244 va_list argList;
1245
1246 if (cchDest > NTSTRSAFE_MAX_CCH)
1247 {
1248 if (cchDest > 0)
1249 *pszDest = '\0';
1250
1251 return STATUS_INVALID_PARAMETER;
1252 }
1253
1254 va_start(argList, pszFormat);
1255 Status = RtlStringVPrintfExWorkerA(pszDest, cchDest, cchDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
1256 va_end(argList);
1257
1258 return Status;
1259 }
1260
1261 NTSTRSAFEVAPI
1262 RtlStringCchPrintfExW(
1263 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1264 _In_ size_t cchDest,
1265 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
1266 _Out_opt_ size_t *pcchRemaining,
1267 _In_ STRSAFE_DWORD dwFlags,
1268 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1269 ...)
1270 {
1271 NTSTATUS Status;
1272 size_t cbDest = cchDest * sizeof(wchar_t);
1273 va_list argList;
1274
1275 if (cchDest > NTSTRSAFE_MAX_CCH)
1276 {
1277 if (cchDest > 0)
1278 *pszDest = L'\0';
1279 return STATUS_INVALID_PARAMETER;
1280 }
1281
1282 va_start(argList, pszFormat);
1283 Status = RtlStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
1284 va_end(argList);
1285
1286 return Status;
1287 }
1288
1289 NTSTRSAFEVAPI
1290 RtlStringCbPrintfExA(
1291 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1292 _In_ size_t cbDest,
1293 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
1294 _Out_opt_ size_t *pcbRemaining,
1295 _In_ STRSAFE_DWORD dwFlags,
1296 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1297 ...);
1298
1299 NTSTRSAFEVAPI
1300 RtlStringCbPrintfExW(
1301 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1302 _In_ size_t cbDest,
1303 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
1304 _Out_opt_ size_t *pcbRemaining,
1305 _In_ STRSAFE_DWORD dwFlags,
1306 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1307 ...);
1308
1309 NTSTRSAFEVAPI
1310 RtlStringCbPrintfExA(
1311 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1312 _In_ size_t cbDest,
1313 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
1314 _Out_opt_ size_t *pcbRemaining,
1315 _In_ STRSAFE_DWORD dwFlags,
1316 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1317 ...)
1318 {
1319 NTSTATUS Status;
1320 size_t cchDest;
1321 size_t cchRemaining = 0;
1322
1323 cchDest = cbDest / sizeof(char);
1324 if (cchDest > NTSTRSAFE_MAX_CCH)
1325 {
1326 if (cchDest > 0)
1327 *pszDest = '\0';
1328
1329 return STATUS_INVALID_PARAMETER;
1330 }
1331
1332 {
1333 va_list argList;
1334 va_start(argList, pszFormat);
1335 Status = RtlStringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
1336 va_end(argList);
1337 }
1338
1339 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
1340 {
1341 if (pcbRemaining)
1342 {
1343 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
1344 }
1345 }
1346
1347 return Status;
1348 }
1349
1350 NTSTRSAFEVAPI
1351 RtlStringCbPrintfExW(
1352 _Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1353 _In_ size_t cbDest,
1354 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
1355 _Out_opt_ size_t *pcbRemaining,
1356 _In_ STRSAFE_DWORD dwFlags,
1357 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1358 ...)
1359 {
1360 NTSTATUS Status;
1361 size_t cchDest;
1362 size_t cchRemaining = 0;
1363 cchDest = cbDest / sizeof(wchar_t);
1364
1365 if (cchDest > NTSTRSAFE_MAX_CCH)
1366 {
1367 if (cchDest > 0)
1368 *pszDest = L'\0';
1369 return STATUS_INVALID_PARAMETER;
1370 }
1371
1372 {
1373 va_list argList;
1374 va_start(argList, pszFormat);
1375 Status = RtlStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
1376 va_end(argList);
1377 }
1378
1379 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
1380 {
1381 if (pcbRemaining)
1382 {
1383 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
1384 }
1385 }
1386 return Status;
1387 }
1388
1389 NTSTRSAFEAPI
1390 RtlStringCchVPrintfExA(
1391 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1392 _In_ size_t cchDest,
1393 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
1394 _Out_opt_ size_t *pcchRemaining,
1395 _In_ STRSAFE_DWORD dwFlags,
1396 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1397 _In_ va_list argList);
1398
1399 NTSTRSAFEAPI
1400 RtlStringCchVPrintfExW(
1401 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1402 _In_ size_t cchDest,
1403 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
1404 _Out_opt_ size_t *pcchRemaining,
1405 _In_ STRSAFE_DWORD dwFlags,
1406 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1407 _In_ va_list argList);
1408
1409 NTSTRSAFEAPI
1410 RtlStringCchVPrintfExA(
1411 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
1412 _In_ size_t cchDest,
1413 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
1414 _Out_opt_ size_t *pcchRemaining,
1415 _In_ STRSAFE_DWORD dwFlags,
1416 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1417 _In_ va_list argList)
1418 {
1419 NTSTATUS Status;
1420
1421 if (cchDest > NTSTRSAFE_MAX_CCH)
1422 {
1423 if (cchDest > 0)
1424 *pszDest = '\0';
1425
1426 return STATUS_INVALID_PARAMETER;
1427 }
1428
1429 {
1430 size_t cbDest;
1431 cbDest = cchDest * sizeof(char);
1432 Status = RtlStringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
1433 }
1434
1435 return Status;
1436 }
1437
1438 NTSTRSAFEAPI
1439 RtlStringCchVPrintfExW(
1440 _Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
1441 _In_ size_t cchDest,
1442 _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
1443 _Out_opt_ size_t *pcchRemaining,
1444 _In_ STRSAFE_DWORD dwFlags,
1445 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1446 _In_ va_list argList)
1447 {
1448 NTSTATUS Status;
1449
1450 if (cchDest > NTSTRSAFE_MAX_CCH)
1451 {
1452 if (cchDest > 0)
1453 *pszDest = L'\0';
1454
1455 return STATUS_INVALID_PARAMETER;
1456 }
1457
1458 {
1459 size_t cbDest;
1460 cbDest = cchDest * sizeof(wchar_t);
1461 Status = RtlStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
1462 }
1463
1464 return Status;
1465 }
1466
1467 NTSTRSAFEAPI
1468 RtlStringCbVPrintfExA(
1469 _Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest,
1470 _In_ size_t cbDest,
1471 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
1472 _Out_opt_ size_t *pcbRemaining,
1473 _In_ STRSAFE_DWORD dwFlags,
1474 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1475 _In_ va_list argList);
1476
1477 NTSTRSAFEAPI
1478 RtlStringCbVPrintfExW(
1479 _Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
1480 _In_ size_t cbDest,
1481 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
1482 _Out_opt_ size_t *pcbRemaining,
1483 _In_ STRSAFE_DWORD dwFlags,
1484 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1485 _In_ va_list argList);
1486
1487 NTSTRSAFEAPI
1488 RtlStringCbVPrintfExA(
1489 _Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest,
1490 _In_ size_t cbDest,
1491 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
1492 _Out_opt_ size_t *pcbRemaining,
1493 _In_ STRSAFE_DWORD dwFlags,
1494 _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
1495 _In_ va_list argList)
1496 {
1497 NTSTATUS Status;
1498 size_t cchDest;
1499 size_t cchRemaining = 0;
1500 cchDest = cbDest / sizeof(char);
1501
1502 if (cchDest > NTSTRSAFE_MAX_CCH)
1503 Status = STATUS_INVALID_PARAMETER;
1504 else
1505 Status = RtlStringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
1506
1507 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
1508 {
1509 if (pcbRemaining)
1510 {
1511 *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
1512 }
1513 }
1514
1515 return Status;
1516 }
1517
1518 NTSTRSAFEAPI
1519 RtlStringCbVPrintfExW(
1520 _Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
1521 _In_ size_t cbDest,
1522 _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
1523 _Out_opt_ size_t *pcbRemaining,
1524 _In_ STRSAFE_DWORD dwFlags,
1525 _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
1526 _In_ va_list argList)
1527 {
1528 NTSTATUS Status;
1529 size_t cchDest;
1530 size_t cchRemaining = 0;
1531 cchDest = cbDest / sizeof(wchar_t);
1532
1533 if (cchDest > NTSTRSAFE_MAX_CCH)
1534 Status = STATUS_INVALID_PARAMETER;
1535 else
1536 Status = RtlStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
1537
1538 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
1539 {
1540 if (pcbRemaining)
1541 {
1542 *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
1543 }
1544 }
1545
1546 return Status;
1547 }
1548
1549
1550 _Must_inspect_result_
1551 NTSTRSAFEAPI
1552 RtlStringCchLengthA(
1553 _In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz,
1554 _In_ _In_range_(1, NTSTRSAFE_MAX_CCH) size_t cchMax,
1555 _Out_opt_ _Deref_out_range_(< , cchMax) _Deref_out_range_(<= , _String_length_(psz)) size_t *pcchLength);
1556
1557 _Must_inspect_result_
1558 NTSTRSAFEAPI
1559 RtlStringCchLengthW(
1560 _In_reads_or_z_(cchMax) STRSAFE_LPCWSTR psz,
1561 _In_ _In_range_(1, NTSTRSAFE_MAX_CCH) size_t cchMax,
1562 _Out_opt_ _Deref_out_range_(< , cchMax) _Deref_out_range_(<= , _String_length_(psz)) size_t *pcchLength);
1563
1564 _Must_inspect_result_
1565 NTSTRSAFEAPI
1566 RtlStringCchLengthA(
1567 _In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz,
1568 _In_ _In_range_(1, NTSTRSAFE_MAX_CCH) size_t cchMax,
1569 _Out_opt_ _Deref_out_range_(< , cchMax) _Deref_out_range_(<= , _String_length_(psz)) size_t *pcchLength)
1570 {
1571 NTSTATUS Status;
1572
1573 if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
1574 Status = STATUS_INVALID_PARAMETER;
1575 else
1576 Status = RtlStringLengthWorkerA(psz, cchMax, pcchLength);
1577
1578 if (!NT_SUCCESS(Status) && pcchLength)
1579 {
1580 *pcchLength = 0;
1581 }
1582
1583 return Status;
1584 }
1585
1586 _Must_inspect_result_
1587 NTSTRSAFEAPI
1588 RtlStringCchLengthW(
1589 _In_reads_or_z_(cchMax) STRSAFE_LPCWSTR psz,
1590 _In_ _In_range_(1, NTSTRSAFE_MAX_CCH) size_t cchMax,
1591 _Out_opt_ _Deref_out_range_(< , cchMax) _Deref_out_range_(<= , _String_length_(psz)) size_t *pcchLength)
1592 {
1593 NTSTATUS Status;
1594
1595 if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
1596 Status = STATUS_INVALID_PARAMETER;
1597 else
1598 Status = RtlStringLengthWorkerW(psz, cchMax, pcchLength);
1599
1600 if (!NT_SUCCESS(Status) && pcchLength)
1601 {
1602 *pcchLength = 0;
1603 }
1604
1605 return Status;
1606 }
1607
1608 _Must_inspect_result_
1609 NTSTRSAFEAPI
1610 RtlStringCbLengthA(
1611 _In_reads_or_z_(cbMax) STRSAFE_LPCSTR psz,
1612 _In_ _In_range_(1, NTSTRSAFE_MAX_CCH * sizeof(char)) size_t cbMax,
1613 _Out_opt_ _Deref_out_range_(< , cbMax) size_t *pcbLength);
1614
1615 _Must_inspect_result_
1616 NTSTRSAFEAPI
1617 RtlStringCbLengthW(
1618 _In_reads_or_z_(cbMax / sizeof(wchar_t)) STRSAFE_LPCWSTR psz,
1619 _In_ _In_range_(1, NTSTRSAFE_MAX_CCH * sizeof(wchar_t)) size_t cbMax,
1620 _Out_opt_ _Deref_out_range_(< , cbMax - 1) size_t *pcbLength);
1621
1622 _Must_inspect_result_
1623 NTSTRSAFEAPI
1624 RtlStringCbLengthA(
1625 _In_reads_or_z_(cbMax) STRSAFE_LPCSTR psz,
1626 _In_ _In_range_(1, NTSTRSAFE_MAX_CCH * sizeof(char)) size_t cbMax,
1627 _Out_opt_ _Deref_out_range_(< , cbMax) size_t *pcbLength)
1628 {
1629 NTSTATUS Status;
1630 size_t cchMax;
1631 size_t cchLength = 0;
1632 cchMax = cbMax / sizeof(char);
1633
1634 if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
1635 Status = STATUS_INVALID_PARAMETER;
1636 else
1637 Status = RtlStringLengthWorkerA(psz, cchMax, &cchLength);
1638
1639 if (pcbLength)
1640 {
1641 if (NT_SUCCESS(Status))
1642 {
1643 *pcbLength = cchLength * sizeof(char);
1644 }
1645 else
1646 {
1647 *pcbLength = 0;
1648 }
1649 }
1650
1651 return Status;
1652 }
1653
1654 _Must_inspect_result_
1655 NTSTRSAFEAPI
1656 RtlStringCbLengthW(
1657 _In_reads_or_z_(cbMax / sizeof(wchar_t)) STRSAFE_LPCWSTR psz,
1658 _In_ _In_range_(1, NTSTRSAFE_MAX_CCH * sizeof(wchar_t)) size_t cbMax,
1659 _Out_opt_ _Deref_out_range_(< , cbMax - 1) size_t *pcbLength)
1660 {
1661 NTSTATUS Status;
1662 size_t cchMax;
1663 size_t cchLength = 0;
1664 cchMax = cbMax / sizeof(wchar_t);
1665
1666 if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
1667 Status = STATUS_INVALID_PARAMETER;
1668 else
1669 Status = RtlStringLengthWorkerW(psz, cchMax, &cchLength);
1670
1671 if (pcbLength)
1672 {
1673 if (NT_SUCCESS(Status))
1674 {
1675 *pcbLength = cchLength * sizeof(wchar_t);
1676 }
1677 else
1678 {
1679 *pcbLength = 0;
1680 }
1681 }
1682
1683 return Status;
1684 }
1685
1686 NTSTRSAFEAPI RtlStringCopyWorkerA(
1687 STRSAFE_LPSTR pszDest,
1688 size_t cchDest,
1689 STRSAFE_LPCSTR pszSrc)
1690 {
1691 NTSTATUS Status = STATUS_SUCCESS;
1692
1693 if (cchDest == 0)
1694 {
1695 Status = STATUS_INVALID_PARAMETER;
1696 }
1697 else
1698 {
1699 while (cchDest && (*pszSrc != '\0'))
1700 {
1701 *pszDest++ = *pszSrc++;
1702 cchDest--;
1703 }
1704
1705 if (cchDest == 0)
1706 {
1707 pszDest--;
1708 Status = STATUS_BUFFER_OVERFLOW;
1709 }
1710
1711 *pszDest = '\0';
1712 }
1713
1714 return Status;
1715 }
1716
1717 NTSTRSAFEAPI RtlStringCopyWorkerW(
1718 STRSAFE_LPWSTR pszDest,
1719 size_t cchDest,
1720 STRSAFE_LPCWSTR pszSrc)
1721 {
1722 NTSTATUS Status = STATUS_SUCCESS;
1723
1724 if (cchDest == 0)
1725 {
1726 Status = STATUS_INVALID_PARAMETER;
1727 }
1728 else
1729 {
1730 while (cchDest && (*pszSrc != L'\0'))
1731 {
1732 *pszDest++ = *pszSrc++;
1733 cchDest--;
1734 }
1735
1736 if (cchDest == 0)
1737 {
1738 pszDest--;
1739 Status = STATUS_BUFFER_OVERFLOW;
1740 }
1741
1742 *pszDest = L'\0';
1743 }
1744
1745 return Status;
1746 }
1747
1748 NTSTRSAFEAPI RtlStringCopyExWorkerA(
1749 STRSAFE_LPSTR pszDest,
1750 size_t cchDest,
1751 size_t cbDest,
1752 STRSAFE_LPCSTR pszSrc,
1753 STRSAFE_LPSTR *ppszDestEnd,
1754 size_t *pcchRemaining,
1755 STRSAFE_DWORD dwFlags)
1756 {
1757 NTSTATUS Status = STATUS_SUCCESS;
1758 STRSAFE_LPSTR pszDestEnd = pszDest;
1759 size_t cchRemaining = 0;
1760
1761 if (dwFlags & (~STRSAFE_VALID_FLAGS))
1762 {
1763 Status = STATUS_INVALID_PARAMETER;
1764 }
1765 else
1766 {
1767 if (dwFlags & STRSAFE_IGNORE_NULLS)
1768 {
1769 if (!pszDest)
1770 {
1771 if ((cchDest != 0) || (cbDest != 0))
1772 Status = STATUS_INVALID_PARAMETER;
1773 }
1774
1775 if (!pszSrc)
1776 pszSrc = "";
1777 }
1778
1779 if (NT_SUCCESS(Status))
1780 {
1781 if (cchDest == 0)
1782 {
1783 pszDestEnd = pszDest;
1784 cchRemaining = 0;
1785
1786 if (*pszSrc != '\0')
1787 {
1788 if (!pszDest)
1789 Status = STATUS_INVALID_PARAMETER;
1790 else
1791 Status = STATUS_BUFFER_OVERFLOW;
1792 }
1793 }
1794 else
1795 {
1796 pszDestEnd = pszDest;
1797 cchRemaining = cchDest;
1798
1799 while (cchRemaining && (*pszSrc != '\0'))
1800 {
1801 *pszDestEnd++ = *pszSrc++;
1802 cchRemaining--;
1803 }
1804
1805 if (cchRemaining > 0)
1806 {
1807 if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
1808 {
1809 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
1810 }
1811 }
1812 else
1813 {
1814 pszDestEnd--;
1815 cchRemaining++;
1816 Status = STATUS_BUFFER_OVERFLOW;
1817 }
1818
1819 *pszDestEnd = '\0';
1820 }
1821 }
1822 }
1823
1824 if (!NT_SUCCESS(Status))
1825 {
1826 if (pszDest)
1827 {
1828 if (dwFlags & STRSAFE_FILL_ON_FAILURE)
1829 {
1830 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
1831 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
1832 {
1833 pszDestEnd = pszDest;
1834 cchRemaining = cchDest;
1835 }
1836 else if (cchDest > 0)
1837 {
1838 pszDestEnd = pszDest + cchDest - 1;
1839 cchRemaining = 1;
1840 *pszDestEnd = '\0';
1841 }
1842 }
1843
1844 if ((dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) && cchDest > 0)
1845 {
1846 pszDestEnd = pszDest;
1847 cchRemaining = cchDest;
1848 *pszDestEnd = '\0';
1849 }
1850 }
1851 }
1852
1853 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
1854 {
1855 if (ppszDestEnd)
1856 *ppszDestEnd = pszDestEnd;
1857
1858 if (pcchRemaining)
1859 *pcchRemaining = cchRemaining;
1860 }
1861
1862 return Status;
1863 }
1864
1865 NTSTRSAFEAPI RtlStringCopyExWorkerW(
1866 STRSAFE_LPWSTR pszDest,
1867 size_t cchDest,
1868 size_t cbDest,
1869 STRSAFE_LPCWSTR pszSrc,
1870 STRSAFE_LPWSTR *ppszDestEnd,
1871 size_t *pcchRemaining,
1872 STRSAFE_DWORD dwFlags)
1873 {
1874 NTSTATUS Status = STATUS_SUCCESS;
1875 STRSAFE_LPWSTR pszDestEnd = pszDest;
1876 size_t cchRemaining = 0;
1877
1878 if (dwFlags & (~STRSAFE_VALID_FLAGS))
1879 {
1880 Status = STATUS_INVALID_PARAMETER;
1881 }
1882 else
1883 {
1884 if (dwFlags & STRSAFE_IGNORE_NULLS)
1885 {
1886 if (!pszDest)
1887 {
1888 if ((cchDest != 0) || (cbDest != 0))
1889 Status = STATUS_INVALID_PARAMETER;
1890 }
1891
1892 if (!pszSrc)
1893 pszSrc = L"";
1894 }
1895
1896 if (NT_SUCCESS(Status))
1897 {
1898 if (cchDest == 0)
1899 {
1900 pszDestEnd = pszDest;
1901 cchRemaining = 0;
1902
1903 if (*pszSrc != L'\0')
1904 {
1905 if (!pszDest)
1906 Status = STATUS_INVALID_PARAMETER;
1907 else
1908 Status = STATUS_BUFFER_OVERFLOW;
1909 }
1910 }
1911 else
1912 {
1913 pszDestEnd = pszDest;
1914 cchRemaining = cchDest;
1915
1916 while (cchRemaining && (*pszSrc != L'\0'))
1917 {
1918 *pszDestEnd++ = *pszSrc++;
1919 cchRemaining--;
1920 }
1921
1922 if (cchRemaining > 0)
1923 {
1924 if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
1925 {
1926 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
1927 }
1928 }
1929 else
1930 {
1931 pszDestEnd--;
1932 cchRemaining++;
1933 Status = STATUS_BUFFER_OVERFLOW;
1934 }
1935
1936 *pszDestEnd = L'\0';
1937 }
1938 }
1939 }
1940
1941 if (!NT_SUCCESS(Status))
1942 {
1943 if (pszDest)
1944 {
1945 if (dwFlags & STRSAFE_FILL_ON_FAILURE)
1946 {
1947 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
1948
1949 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
1950 {
1951 pszDestEnd = pszDest;
1952 cchRemaining = cchDest;
1953 }
1954 else if (cchDest > 0)
1955 {
1956 pszDestEnd = pszDest + cchDest - 1;
1957 cchRemaining = 1;
1958 *pszDestEnd = L'\0';
1959 }
1960 }
1961
1962 if ((dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) && cchDest > 0)
1963 {
1964 pszDestEnd = pszDest;
1965 cchRemaining = cchDest;
1966 *pszDestEnd = L'\0';
1967 }
1968 }
1969 }
1970
1971 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
1972 {
1973 if (ppszDestEnd)
1974 *ppszDestEnd = pszDestEnd;
1975
1976 if (pcchRemaining)
1977 *pcchRemaining = cchRemaining;
1978 }
1979
1980 return Status;
1981 }
1982
1983 NTSTRSAFEAPI RtlStringCopyNWorkerA(
1984 STRSAFE_LPSTR pszDest,
1985 size_t cchDest,
1986 STRSAFE_LPCSTR pszSrc,
1987 size_t cchSrc)
1988 {
1989 NTSTATUS Status = STATUS_SUCCESS;
1990
1991 if (cchDest == 0)
1992 {
1993 Status = STATUS_INVALID_PARAMETER;
1994 }
1995 else
1996 {
1997 while (cchDest && cchSrc && (*pszSrc != '\0'))
1998 {
1999 *pszDest++ = *pszSrc++;
2000 cchDest--;
2001 cchSrc--;
2002 }
2003
2004 if (cchDest == 0)
2005 {
2006 pszDest--;
2007 Status = STATUS_BUFFER_OVERFLOW;
2008 }
2009
2010 *pszDest = '\0';
2011 }
2012
2013 return Status;
2014 }
2015
2016 NTSTRSAFEAPI RtlStringCopyNWorkerW(
2017 STRSAFE_LPWSTR pszDest,
2018 size_t cchDest,
2019 STRSAFE_LPCWSTR pszSrc,
2020 size_t cchToCopy)
2021 {
2022 NTSTATUS Status = STATUS_SUCCESS;
2023
2024 if (cchDest == 0)
2025 {
2026 Status = STATUS_INVALID_PARAMETER;
2027 }
2028 else
2029 {
2030 while (cchDest && cchToCopy && (*pszSrc != L'\0'))
2031 {
2032 *pszDest++ = *pszSrc++;
2033 cchDest--;
2034 cchToCopy--;
2035 }
2036
2037 if (cchDest == 0)
2038 {
2039 pszDest--;
2040 Status = STATUS_BUFFER_OVERFLOW;
2041 }
2042
2043 *pszDest = L'\0';
2044 }
2045
2046 return Status;
2047 }
2048
2049 NTSTRSAFEAPI RtlStringCopyNExWorkerA(
2050 STRSAFE_LPSTR pszDest,
2051 size_t cchDest,
2052 size_t cbDest,
2053 STRSAFE_LPCSTR pszSrc,
2054 size_t cchToCopy,
2055 STRSAFE_LPSTR *ppszDestEnd,
2056 size_t *pcchRemaining,
2057 STRSAFE_DWORD dwFlags)
2058 {
2059 NTSTATUS Status = STATUS_SUCCESS;
2060 STRSAFE_LPSTR pszDestEnd = pszDest;
2061 size_t cchRemaining = 0;
2062
2063 if (dwFlags & (~STRSAFE_VALID_FLAGS))
2064 {
2065 Status = STATUS_INVALID_PARAMETER;
2066 }
2067 else if (cchToCopy > NTSTRSAFE_MAX_CCH)
2068 {
2069 Status = STATUS_INVALID_PARAMETER;
2070 }
2071 else
2072 {
2073 if (dwFlags & STRSAFE_IGNORE_NULLS)
2074 {
2075 if (!pszDest)
2076 {
2077 if ((cchDest != 0) || (cbDest != 0))
2078 Status = STATUS_INVALID_PARAMETER;
2079 }
2080
2081 if (!pszSrc)
2082 pszSrc = "";
2083 }
2084
2085 if (NT_SUCCESS(Status))
2086 {
2087 if (cchDest == 0)
2088 {
2089 pszDestEnd = pszDest;
2090 cchRemaining = 0;
2091
2092 if ((cchToCopy != 0) && (*pszSrc != '\0'))
2093 {
2094 if (!pszDest)
2095 Status = STATUS_INVALID_PARAMETER;
2096 else
2097 Status = STATUS_BUFFER_OVERFLOW;
2098 }
2099 }
2100 else
2101 {
2102 pszDestEnd = pszDest;
2103 cchRemaining = cchDest;
2104
2105 while (cchRemaining && cchToCopy && (*pszSrc != '\0'))
2106 {
2107 *pszDestEnd++ = *pszSrc++;
2108 cchRemaining--;
2109 cchToCopy--;
2110 }
2111
2112 if (cchRemaining > 0)
2113 {
2114 if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
2115 {
2116 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
2117 }
2118 }
2119 else
2120 {
2121 pszDestEnd--;
2122 cchRemaining++;
2123 Status = STATUS_BUFFER_OVERFLOW;
2124 }
2125
2126 *pszDestEnd = '\0';
2127 }
2128 }
2129 }
2130
2131 if (!NT_SUCCESS(Status))
2132 {
2133 if (pszDest)
2134 {
2135 if (dwFlags & STRSAFE_FILL_ON_FAILURE)
2136 {
2137 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
2138 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
2139 {
2140 pszDestEnd = pszDest;
2141 cchRemaining = cchDest;
2142 }
2143 else if (cchDest > 0)
2144 {
2145 pszDestEnd = pszDest + cchDest - 1;
2146 cchRemaining = 1;
2147 *pszDestEnd = '\0';
2148 }
2149 }
2150
2151 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
2152 {
2153 if (cchDest > 0)
2154 {
2155 pszDestEnd = pszDest;
2156 cchRemaining = cchDest;
2157 *pszDestEnd = '\0';
2158 }
2159 }
2160 }
2161 }
2162
2163 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
2164 {
2165 if (ppszDestEnd)
2166 *ppszDestEnd = pszDestEnd;
2167
2168 if (pcchRemaining)
2169 *pcchRemaining = cchRemaining;
2170 }
2171
2172 return Status;
2173 }
2174
2175 NTSTRSAFEAPI RtlStringCopyNExWorkerW(
2176 STRSAFE_LPWSTR pszDest,
2177 size_t cchDest,
2178 size_t cbDest,
2179 STRSAFE_LPCWSTR pszSrc,
2180 size_t cchToCopy,
2181 STRSAFE_LPWSTR *ppszDestEnd,
2182 size_t *pcchRemaining,
2183 STRSAFE_DWORD dwFlags)
2184 {
2185 NTSTATUS Status = STATUS_SUCCESS;
2186 STRSAFE_LPWSTR pszDestEnd = pszDest;
2187 size_t cchRemaining = 0;
2188
2189 if (dwFlags & (~STRSAFE_VALID_FLAGS))
2190 {
2191 Status = STATUS_INVALID_PARAMETER;
2192 }
2193 else if (cchToCopy > NTSTRSAFE_MAX_CCH)
2194 {
2195 Status = STATUS_INVALID_PARAMETER;
2196 }
2197 else
2198 {
2199 if (dwFlags & STRSAFE_IGNORE_NULLS)
2200 {
2201 if (!pszDest)
2202 {
2203 if ((cchDest != 0) || (cbDest != 0))
2204 Status = STATUS_INVALID_PARAMETER;
2205 }
2206
2207 if (!pszSrc)
2208 pszSrc = L"";
2209 }
2210
2211 if (NT_SUCCESS(Status))
2212 {
2213 if (cchDest == 0)
2214 {
2215 pszDestEnd = pszDest;
2216 cchRemaining = 0;
2217
2218 if ((cchToCopy != 0) && (*pszSrc != L'\0'))
2219 {
2220 if (!pszDest)
2221 Status = STATUS_INVALID_PARAMETER;
2222 else
2223 Status = STATUS_BUFFER_OVERFLOW;
2224 }
2225 }
2226 else
2227 {
2228 pszDestEnd = pszDest;
2229 cchRemaining = cchDest;
2230
2231 while (cchRemaining && cchToCopy && (*pszSrc != L'\0'))
2232 {
2233 *pszDestEnd++ = *pszSrc++;
2234 cchRemaining--;
2235 cchToCopy--;
2236 }
2237
2238 if (cchRemaining > 0)
2239 {
2240 if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
2241 {
2242 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
2243 }
2244 }
2245 else
2246 {
2247 pszDestEnd--;
2248 cchRemaining++;
2249 Status = STATUS_BUFFER_OVERFLOW;
2250 }
2251
2252 *pszDestEnd = L'\0';
2253 }
2254 }
2255 }
2256
2257 if (!NT_SUCCESS(Status))
2258 {
2259 if (pszDest)
2260 {
2261 if (dwFlags & STRSAFE_FILL_ON_FAILURE)
2262 {
2263 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
2264 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
2265 {
2266 pszDestEnd = pszDest;
2267 cchRemaining = cchDest;
2268 }
2269 else if (cchDest > 0)
2270 {
2271 pszDestEnd = pszDest + cchDest - 1;
2272 cchRemaining = 1;
2273 *pszDestEnd = L'\0';
2274 }
2275 }
2276 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
2277 {
2278 if (cchDest > 0)
2279 {
2280 pszDestEnd = pszDest;
2281 cchRemaining = cchDest;
2282 *pszDestEnd = L'\0';
2283 }
2284 }
2285 }
2286 }
2287
2288 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
2289 {
2290 if (ppszDestEnd)
2291 *ppszDestEnd = pszDestEnd;
2292
2293 if (pcchRemaining)
2294 *pcchRemaining = cchRemaining;
2295 }
2296
2297 return Status;
2298 }
2299
2300 NTSTRSAFEAPI RtlStringCatWorkerA(
2301 STRSAFE_LPSTR pszDest,
2302 size_t cchDest,
2303 STRSAFE_LPCSTR pszSrc)
2304 {
2305 size_t cchDestLength;
2306 NTSTATUS Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
2307 if (NT_SUCCESS(Status))
2308 Status = RtlStringCopyWorkerA(pszDest + cchDestLength, cchDest - cchDestLength, pszSrc);
2309
2310 return Status;
2311 }
2312
2313 NTSTRSAFEAPI RtlStringCatWorkerW(
2314 STRSAFE_LPWSTR pszDest,
2315 size_t cchDest,
2316 STRSAFE_LPCWSTR pszSrc)
2317 {
2318 size_t cchDestLength;
2319 NTSTATUS Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
2320 if (NT_SUCCESS(Status))
2321 Status = RtlStringCopyWorkerW(pszDest + cchDestLength, cchDest - cchDestLength, pszSrc);
2322
2323 return Status;
2324 }
2325
2326 NTSTRSAFEAPI RtlStringCatExWorkerA(
2327 STRSAFE_LPSTR pszDest,
2328 size_t cchDest,
2329 size_t cbDest,
2330 STRSAFE_LPCSTR pszSrc,
2331 STRSAFE_LPSTR *ppszDestEnd,
2332 size_t *pcchRemaining,
2333 STRSAFE_DWORD dwFlags)
2334 {
2335 NTSTATUS Status = STATUS_SUCCESS;
2336 STRSAFE_LPSTR pszDestEnd = pszDest;
2337 size_t cchRemaining = 0;
2338
2339 if (dwFlags & (~STRSAFE_VALID_FLAGS))
2340 {
2341 Status = STATUS_INVALID_PARAMETER;
2342 }
2343 else
2344 {
2345 size_t cchDestLength;
2346 if (dwFlags & STRSAFE_IGNORE_NULLS)
2347 {
2348 if (!pszDest)
2349 {
2350 if ((cchDest == 0) && (cbDest == 0))
2351 cchDestLength = 0;
2352 else
2353 Status = STATUS_INVALID_PARAMETER;
2354 }
2355 else
2356 {
2357 Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
2358 if (NT_SUCCESS(Status))
2359 {
2360 pszDestEnd = pszDest + cchDestLength;
2361 cchRemaining = cchDest - cchDestLength;
2362 }
2363 }
2364
2365 if (!pszSrc)
2366 pszSrc = "";
2367 }
2368 else
2369 {
2370 Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
2371 if (NT_SUCCESS(Status))
2372 {
2373 pszDestEnd = pszDest + cchDestLength;
2374 cchRemaining = cchDest - cchDestLength;
2375 }
2376 }
2377
2378 if (NT_SUCCESS(Status))
2379 {
2380 if (cchDest == 0)
2381 {
2382 if (*pszSrc != '\0')
2383 {
2384 if (!pszDest)
2385 Status = STATUS_INVALID_PARAMETER;
2386 else
2387 Status = STATUS_BUFFER_OVERFLOW;
2388 }
2389 }
2390 else
2391 {
2392 Status = RtlStringCopyExWorkerA(pszDestEnd, cchRemaining, (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), pszSrc, &pszDestEnd, &cchRemaining, dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
2393 }
2394 }
2395 }
2396
2397 if (!NT_SUCCESS(Status))
2398 {
2399 if (pszDest)
2400 {
2401 if (dwFlags & STRSAFE_FILL_ON_FAILURE)
2402 {
2403 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
2404 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
2405 {
2406 pszDestEnd = pszDest;
2407 cchRemaining = cchDest;
2408 }
2409 else if (cchDest > 0)
2410 {
2411 pszDestEnd = pszDest + cchDest - 1;
2412 cchRemaining = 1;
2413 *pszDestEnd = '\0';
2414 }
2415 }
2416
2417 if ((dwFlags & STRSAFE_NULL_ON_FAILURE) && cchDest > 0)
2418 {
2419 pszDestEnd = pszDest;
2420 cchRemaining = cchDest;
2421 *pszDestEnd = '\0';
2422 }
2423 }
2424 }
2425
2426 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
2427 {
2428 if (ppszDestEnd)
2429 *ppszDestEnd = pszDestEnd;
2430
2431 if (pcchRemaining)
2432 *pcchRemaining = cchRemaining;
2433 }
2434
2435 return Status;
2436 }
2437
2438 NTSTRSAFEAPI RtlStringCatExWorkerW(
2439 STRSAFE_LPWSTR pszDest,
2440 size_t cchDest,
2441 size_t cbDest,
2442 STRSAFE_LPCWSTR pszSrc,
2443 STRSAFE_LPWSTR *ppszDestEnd,
2444 size_t *pcchRemaining,
2445 STRSAFE_DWORD dwFlags)
2446 {
2447 NTSTATUS Status = STATUS_SUCCESS;
2448 STRSAFE_LPWSTR pszDestEnd = pszDest;
2449 size_t cchRemaining = 0;
2450
2451 if (dwFlags & (~STRSAFE_VALID_FLAGS))
2452 {
2453 Status = STATUS_INVALID_PARAMETER;
2454 }
2455 else
2456 {
2457 size_t cchDestLength;
2458 if (dwFlags & STRSAFE_IGNORE_NULLS)
2459 {
2460 if (!pszDest)
2461 {
2462 if ((cchDest == 0) && (cbDest == 0))
2463 cchDestLength = 0;
2464 else
2465 Status = STATUS_INVALID_PARAMETER;
2466 }
2467 else
2468 {
2469 Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
2470 if (NT_SUCCESS(Status))
2471 {
2472 pszDestEnd = pszDest + cchDestLength;
2473 cchRemaining = cchDest - cchDestLength;
2474 }
2475 }
2476
2477 if (!pszSrc)
2478 pszSrc = L"";
2479 }
2480 else
2481 {
2482 Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
2483 if (NT_SUCCESS(Status))
2484 {
2485 pszDestEnd = pszDest + cchDestLength;
2486 cchRemaining = cchDest - cchDestLength;
2487 }
2488 }
2489
2490 if (NT_SUCCESS(Status))
2491 {
2492 if (cchDest == 0)
2493 {
2494 if (*pszSrc != L'\0')
2495 {
2496 if (!pszDest)
2497 Status = STATUS_INVALID_PARAMETER;
2498 else
2499 Status = STATUS_BUFFER_OVERFLOW;
2500 }
2501 }
2502 else
2503 {
2504 Status = RtlStringCopyExWorkerW(pszDestEnd, cchRemaining, (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)), pszSrc, &pszDestEnd, &cchRemaining, dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
2505 }
2506 }
2507 }
2508
2509 if (!NT_SUCCESS(Status))
2510 {
2511 if (pszDest)
2512 {
2513 if (dwFlags & STRSAFE_FILL_ON_FAILURE)
2514 {
2515 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
2516 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
2517 {
2518 pszDestEnd = pszDest;
2519 cchRemaining = cchDest;
2520 }
2521 else if (cchDest > 0)
2522 {
2523 pszDestEnd = pszDest + cchDest - 1;
2524 cchRemaining = 1;
2525 *pszDestEnd = L'\0';
2526 }
2527 }
2528
2529 if ((dwFlags & STRSAFE_NULL_ON_FAILURE) && cchDest > 0)
2530 {
2531 pszDestEnd = pszDest;
2532 cchRemaining = cchDest;
2533 *pszDestEnd = L'\0';
2534 }
2535 }
2536 }
2537
2538 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
2539 {
2540 if (ppszDestEnd)
2541 *ppszDestEnd = pszDestEnd;
2542 if (pcchRemaining)
2543 *pcchRemaining = cchRemaining;
2544 }
2545
2546 return Status;
2547 }
2548
2549 NTSTRSAFEAPI RtlStringCatNWorkerA(
2550 STRSAFE_LPSTR pszDest,
2551 size_t cchDest,
2552 STRSAFE_LPCSTR pszSrc,
2553 size_t cchToAppend)
2554 {
2555 size_t cchDestLength;
2556 NTSTATUS Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
2557 if (NT_SUCCESS(Status))
2558 Status = RtlStringCopyNWorkerA(pszDest + cchDestLength, cchDest - cchDestLength, pszSrc, cchToAppend);
2559
2560 return Status;
2561 }
2562
2563 NTSTRSAFEAPI RtlStringCatNWorkerW(
2564 STRSAFE_LPWSTR pszDest,
2565 size_t cchDest,
2566 STRSAFE_LPCWSTR pszSrc,
2567 size_t cchToAppend)
2568 {
2569 size_t cchDestLength;
2570 NTSTATUS Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
2571 if (NT_SUCCESS(Status))
2572 Status = RtlStringCopyNWorkerW(pszDest + cchDestLength, cchDest - cchDestLength, pszSrc, cchToAppend);
2573
2574 return Status;
2575 }
2576
2577 NTSTRSAFEAPI RtlStringCatNExWorkerA(
2578 STRSAFE_LPSTR pszDest,
2579 size_t cchDest,
2580 size_t cbDest,
2581 STRSAFE_LPCSTR pszSrc,
2582 size_t cchToAppend,
2583 STRSAFE_LPSTR *ppszDestEnd,
2584 size_t *pcchRemaining,
2585 STRSAFE_DWORD dwFlags)
2586 {
2587 NTSTATUS Status = STATUS_SUCCESS;
2588 STRSAFE_LPSTR pszDestEnd = pszDest;
2589 size_t cchRemaining = 0;
2590 size_t cchDestLength = 0;
2591
2592 if (dwFlags & (~STRSAFE_VALID_FLAGS))
2593 {
2594 Status = STATUS_INVALID_PARAMETER;
2595 }
2596 else if (cchToAppend > NTSTRSAFE_MAX_CCH)
2597 {
2598 Status = STATUS_INVALID_PARAMETER;
2599 }
2600 else
2601 {
2602 if (dwFlags & STRSAFE_IGNORE_NULLS)
2603 {
2604 if (!pszDest)
2605 {
2606 if ((cchDest == 0) && (cbDest == 0))
2607 cchDestLength = 0;
2608 else
2609 Status = STATUS_INVALID_PARAMETER;
2610 }
2611 else
2612 {
2613 Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
2614 if (NT_SUCCESS(Status))
2615 {
2616 pszDestEnd = pszDest + cchDestLength;
2617 cchRemaining = cchDest - cchDestLength;
2618 }
2619 }
2620
2621 if (!pszSrc)
2622 pszSrc = "";
2623 }
2624 else
2625 {
2626 Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
2627 if (NT_SUCCESS(Status))
2628 {
2629 pszDestEnd = pszDest + cchDestLength;
2630 cchRemaining = cchDest - cchDestLength;
2631 }
2632 }
2633
2634 if (NT_SUCCESS(Status))
2635 {
2636 if (cchDest == 0)
2637 {
2638 if ((cchToAppend != 0) && (*pszSrc != '\0'))
2639 {
2640 if (!pszDest)
2641 Status = STATUS_INVALID_PARAMETER;
2642 else
2643 Status = STATUS_BUFFER_OVERFLOW;
2644 }
2645 }
2646 else
2647 {
2648 Status = RtlStringCopyNExWorkerA(pszDestEnd, cchRemaining, (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), pszSrc, cchToAppend, &pszDestEnd, &cchRemaining, dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
2649 }
2650 }
2651 }
2652
2653 if (!NT_SUCCESS(Status))
2654 {
2655 if (pszDest)
2656 {
2657 if (dwFlags & STRSAFE_FILL_ON_FAILURE)
2658 {
2659 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
2660 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
2661 {
2662 pszDestEnd = pszDest;
2663 cchRemaining = cchDest;
2664 }
2665 else if (cchDest > 0)
2666 {
2667 pszDestEnd = pszDest + cchDest - 1;
2668 cchRemaining = 1;
2669 *pszDestEnd = '\0';
2670 }
2671 }
2672
2673 if ((dwFlags & STRSAFE_NULL_ON_FAILURE) && cchDest > 0)
2674 {
2675 pszDestEnd = pszDest;
2676 cchRemaining = cchDest;
2677 *pszDestEnd = '\0';
2678 }
2679 }
2680 }
2681
2682 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
2683 {
2684 if (ppszDestEnd)
2685 *ppszDestEnd = pszDestEnd;
2686
2687 if (pcchRemaining)
2688 *pcchRemaining = cchRemaining;
2689 }
2690
2691 return Status;
2692 }
2693
2694 NTSTRSAFEAPI RtlStringCatNExWorkerW(
2695 STRSAFE_LPWSTR pszDest,
2696 size_t cchDest,
2697 size_t cbDest,
2698 STRSAFE_LPCWSTR pszSrc,
2699 size_t cchToAppend,
2700 STRSAFE_LPWSTR *ppszDestEnd,
2701 size_t *pcchRemaining,
2702 STRSAFE_DWORD dwFlags)
2703 {
2704 NTSTATUS Status = STATUS_SUCCESS;
2705 STRSAFE_LPWSTR pszDestEnd = pszDest;
2706 size_t cchRemaining = 0;
2707 size_t cchDestLength = 0;
2708
2709 if (dwFlags & (~STRSAFE_VALID_FLAGS))
2710 {
2711 Status = STATUS_INVALID_PARAMETER;
2712 }
2713 else if (cchToAppend > NTSTRSAFE_MAX_CCH)
2714 {
2715 Status = STATUS_INVALID_PARAMETER;
2716 }
2717 else
2718 {
2719 if (dwFlags & STRSAFE_IGNORE_NULLS)
2720 {
2721 if (!pszDest)
2722 {
2723 if ((cchDest == 0) && (cbDest == 0))
2724 cchDestLength = 0;
2725 else
2726 Status = STATUS_INVALID_PARAMETER;
2727 }
2728 else
2729 {
2730 Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
2731 if (NT_SUCCESS(Status))
2732 {
2733 pszDestEnd = pszDest + cchDestLength;
2734 cchRemaining = cchDest - cchDestLength;
2735 }
2736 }
2737
2738 if (!pszSrc)
2739 pszSrc = L"";
2740 }
2741 else
2742 {
2743 Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
2744 if (NT_SUCCESS(Status))
2745 {
2746 pszDestEnd = pszDest + cchDestLength;
2747 cchRemaining = cchDest - cchDestLength;
2748 }
2749 }
2750
2751 if (NT_SUCCESS(Status))
2752 {
2753 if (cchDest == 0)
2754 {
2755 if ((cchToAppend != 0) && (*pszSrc != L'\0'))
2756 {
2757 if (!pszDest)
2758 Status = STATUS_INVALID_PARAMETER;
2759 else
2760 Status = STATUS_BUFFER_OVERFLOW;
2761 }
2762 }
2763 else
2764 {
2765 Status = RtlStringCopyNExWorkerW(pszDestEnd, cchRemaining, (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)), pszSrc, cchToAppend, &pszDestEnd, &cchRemaining, dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
2766 }
2767 }
2768 }
2769
2770 if (!NT_SUCCESS(Status))
2771 {
2772 if (pszDest)
2773 {
2774 if (dwFlags & STRSAFE_FILL_ON_FAILURE)
2775 {
2776 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
2777
2778 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
2779 {
2780 pszDestEnd = pszDest;
2781 cchRemaining = cchDest;
2782 }
2783 else if (cchDest > 0)
2784 {
2785 pszDestEnd = pszDest + cchDest - 1;
2786 cchRemaining = 1;
2787 *pszDestEnd = L'\0';
2788 }
2789 }
2790
2791 if ((dwFlags & STRSAFE_NULL_ON_FAILURE) && cchDest > 0)
2792 {
2793 pszDestEnd = pszDest;
2794 cchRemaining = cchDest;
2795 *pszDestEnd = L'\0';
2796 }
2797 }
2798 }
2799
2800 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
2801 {
2802 if (ppszDestEnd)
2803 *ppszDestEnd = pszDestEnd;
2804
2805 if (pcchRemaining)
2806 *pcchRemaining = cchRemaining;
2807 }
2808
2809 return Status;
2810 }
2811
2812 NTSTRSAFEAPI RtlStringVPrintfWorkerA(
2813 STRSAFE_LPSTR pszDest,
2814 size_t cchDest,
2815 STRSAFE_LPCSTR pszFormat,
2816 va_list argList)
2817 {
2818 NTSTATUS Status = STATUS_SUCCESS;
2819
2820 if (cchDest == 0)
2821 {
2822 Status = STATUS_INVALID_PARAMETER;
2823 }
2824 else
2825 {
2826 size_t cchMax = cchDest - 1;
2827 int iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList);
2828
2829 if ((iRet < 0) || (((size_t)iRet) > cchMax))
2830 {
2831 pszDest += cchMax;
2832 *pszDest = '\0';
2833 Status = STATUS_BUFFER_OVERFLOW;
2834 }
2835 else if (((size_t)iRet) == cchMax)
2836 {
2837 pszDest += cchMax;
2838 *pszDest = '\0';
2839 }
2840 }
2841
2842 return Status;
2843 }
2844
2845 NTSTRSAFEAPI RtlpStringVPrintfWorkerW(
2846 STRSAFE_LPWSTR pszDest,
2847 size_t cchDest,
2848 STRSAFE_LPCWSTR pszFormat,
2849 size_t* pcchDestNewLen,
2850 va_list argList)
2851 {
2852 NTSTATUS Status = STATUS_SUCCESS;
2853 size_t cchMax = cchDest - 1;
2854 int iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList);
2855
2856 if ((iRet < 0) || (((size_t)iRet) > cchMax))
2857 {
2858 pszDest += cchMax;
2859 *pszDest = L'\0';
2860 Status = STATUS_BUFFER_OVERFLOW;
2861 }
2862 else if (((size_t)iRet) == cchMax)
2863 {
2864 pszDest += cchMax;
2865 *pszDest = L'\0';
2866 }
2867
2868 if (pcchDestNewLen)
2869 *pcchDestNewLen = (iRet == -1) ? cchDest : iRet;
2870
2871 return Status;
2872 }
2873
2874 NTSTRSAFEAPI RtlStringVPrintfWorkerW(
2875 STRSAFE_LPWSTR pszDest,
2876 size_t cchDest,
2877 STRSAFE_LPCWSTR pszFormat,
2878 va_list argList)
2879 {
2880 if (cchDest == 0)
2881 return STATUS_INVALID_PARAMETER;
2882
2883 return RtlpStringVPrintfWorkerW(pszDest, cchDest, pszFormat, NULL, argList);
2884 }
2885
2886 NTSTRSAFEAPI RtlStringVPrintfWorkerLenW(
2887 STRSAFE_LPWSTR pszDest,
2888 size_t cchDest,
2889 STRSAFE_LPCWSTR pszFormat,
2890 size_t* pcchDestNewLen,
2891 va_list argList)
2892 {
2893 if (cchDest == 0 || pcchDestNewLen == 0)
2894 return STATUS_INVALID_PARAMETER;
2895
2896 return RtlpStringVPrintfWorkerW(pszDest, cchDest, pszFormat, pcchDestNewLen, argList);
2897 }
2898
2899 NTSTRSAFEAPI RtlStringVPrintfExWorkerA(
2900 STRSAFE_LPSTR pszDest,
2901 size_t cchDest,
2902 size_t cbDest,
2903 STRSAFE_LPSTR *ppszDestEnd,
2904 size_t *pcchRemaining,
2905 STRSAFE_DWORD dwFlags,
2906 STRSAFE_LPCSTR pszFormat,
2907 va_list argList)
2908 {
2909 NTSTATUS Status = STATUS_SUCCESS;
2910 STRSAFE_LPSTR pszDestEnd = pszDest;
2911 size_t cchRemaining = 0;
2912
2913 if (dwFlags & (~STRSAFE_VALID_FLAGS))
2914 {
2915 Status = STATUS_INVALID_PARAMETER;
2916 }
2917 else
2918 {
2919 if (dwFlags & STRSAFE_IGNORE_NULLS)
2920 {
2921 if (!pszDest)
2922 {
2923 if ((cchDest != 0) || (cbDest != 0))
2924 Status = STATUS_INVALID_PARAMETER;
2925 }
2926
2927 if (!pszFormat)
2928 pszFormat = "";
2929 }
2930 if (NT_SUCCESS(Status))
2931 {
2932 if (cchDest == 0)
2933 {
2934 pszDestEnd = pszDest;
2935 cchRemaining = 0;
2936
2937 if (*pszFormat != '\0')
2938 {
2939 if (!pszDest)
2940 Status = STATUS_INVALID_PARAMETER;
2941 else
2942 Status = STATUS_BUFFER_OVERFLOW;
2943 }
2944 }
2945 else
2946 {
2947 int iRet;
2948 size_t cchMax;
2949 cchMax = cchDest - 1;
2950 iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList);
2951 if ((iRet < 0) || (((size_t)iRet) > cchMax))
2952 {
2953 pszDestEnd = pszDest + cchMax;
2954 cchRemaining = 1;
2955 *pszDestEnd = '\0';
2956 Status = STATUS_BUFFER_OVERFLOW;
2957 }
2958 else if (((size_t)iRet) == cchMax)
2959 {
2960 pszDestEnd = pszDest + cchMax;
2961 cchRemaining = 1;
2962 *pszDestEnd = '\0';
2963 }
2964 else if (((size_t)iRet) < cchMax)
2965 {
2966 pszDestEnd = pszDest + iRet;
2967 cchRemaining = cchDest - iRet;
2968
2969 if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
2970 {
2971 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
2972 }
2973 }
2974 }
2975 }
2976 }
2977
2978 if (!NT_SUCCESS(Status))
2979 {
2980 if (pszDest)
2981 {
2982 if (dwFlags & STRSAFE_FILL_ON_FAILURE)
2983 {
2984 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
2985 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
2986 {
2987 pszDestEnd = pszDest;
2988 cchRemaining = cchDest;
2989 }
2990 else if (cchDest > 0)
2991 {
2992 pszDestEnd = pszDest + cchDest - 1;
2993 cchRemaining = 1;
2994 *pszDestEnd = '\0';
2995 }
2996 }
2997
2998 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
2999 {
3000 if (cchDest > 0)
3001 {
3002 pszDestEnd = pszDest;
3003 cchRemaining = cchDest;
3004 *pszDestEnd = '\0';
3005 }
3006 }
3007 }
3008 }
3009
3010 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
3011 {
3012 if (ppszDestEnd)
3013 *ppszDestEnd = pszDestEnd;
3014
3015 if (pcchRemaining)
3016 *pcchRemaining = cchRemaining;
3017 }
3018
3019 return Status;
3020 }
3021
3022 NTSTRSAFEAPI RtlpStringVPrintfExWorkerW(
3023 STRSAFE_LPWSTR pszDest,
3024 size_t cchDest,
3025 size_t cbDest,
3026 STRSAFE_LPWSTR *ppszDestEnd,
3027 size_t *pcchRemaining,
3028 STRSAFE_DWORD dwFlags,
3029 STRSAFE_LPCWSTR pszFormat,
3030 size_t* pcchDestNewLen,
3031 va_list argList)
3032 {
3033 NTSTATUS Status = STATUS_SUCCESS;
3034 STRSAFE_LPWSTR pszDestEnd = pszDest;
3035 size_t cchRemaining = 0;
3036
3037 if (dwFlags & (~STRSAFE_VALID_FLAGS))
3038 {
3039 Status = STATUS_INVALID_PARAMETER;
3040 }
3041 else
3042 {
3043 if (dwFlags & STRSAFE_IGNORE_NULLS)
3044 {
3045 if (!pszDest)
3046 {
3047 if ((cchDest != 0) || (cbDest != 0))
3048 Status = STATUS_INVALID_PARAMETER;
3049 }
3050
3051 if (!pszFormat)
3052 pszFormat = L"";
3053 }
3054
3055 if (NT_SUCCESS(Status))
3056 {
3057 if (cchDest == 0)
3058 {
3059 pszDestEnd = pszDest;
3060 cchRemaining = 0;
3061 if (*pszFormat != L'\0')
3062 {
3063 if (!pszDest)
3064 Status = STATUS_INVALID_PARAMETER;
3065 else
3066 Status = STATUS_BUFFER_OVERFLOW;
3067 }
3068 }
3069 else
3070 {
3071 int iRet;
3072 size_t cchMax = cchDest - 1;
3073 iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList);
3074 if ((iRet < 0) || (((size_t)iRet) > cchMax))
3075 {
3076 pszDestEnd = pszDest + cchMax;
3077 cchRemaining = 1;
3078 *pszDestEnd = L'\0';
3079 Status = STATUS_BUFFER_OVERFLOW;
3080 }
3081 else if (((size_t)iRet) == cchMax)
3082 {
3083 pszDestEnd = pszDest + cchMax;
3084 cchRemaining = 1;
3085 *pszDestEnd = L'\0';
3086 }
3087 else if (((size_t)iRet) < cchMax)
3088 {
3089 pszDestEnd = pszDest + iRet;
3090 cchRemaining = cchDest - iRet;
3091
3092 if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
3093 {
3094 memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
3095 }
3096 }
3097
3098 if (pcchDestNewLen)
3099 *pcchDestNewLen = iRet == -1 ? cchDest : iRet;
3100 }
3101 }
3102 }
3103
3104 if (!NT_SUCCESS(Status))
3105 {
3106 if (pszDest)
3107 {
3108 if (dwFlags & STRSAFE_FILL_ON_FAILURE)
3109 {
3110 memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
3111 if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
3112 {
3113 pszDestEnd = pszDest;
3114 cchRemaining = cchDest;
3115 }
3116 else if (cchDest > 0)
3117 {
3118 pszDestEnd = pszDest + cchDest - 1;
3119 cchRemaining = 1;
3120 *pszDestEnd = L'\0';
3121 }
3122 }
3123 if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
3124 {
3125 if (cchDest > 0)
3126 {
3127 pszDestEnd = pszDest;
3128 cchRemaining = cchDest;
3129 *pszDestEnd = L'\0';
3130 }
3131 }
3132 }
3133 }
3134
3135 if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
3136 {
3137 if (ppszDestEnd)
3138 *ppszDestEnd = pszDestEnd;
3139
3140 if (pcchRemaining)
3141 *pcchRemaining = cchRemaining;
3142 }
3143
3144 return Status;
3145 }
3146
3147 NTSTRSAFEAPI RtlStringVPrintfExWorkerW(
3148 STRSAFE_LPWSTR pszDest,
3149 size_t cchDest,
3150 size_t cbDest,
3151 STRSAFE_LPWSTR *ppszDestEnd,
3152 size_t *pcchRemaining,
3153 STRSAFE_DWORD dwFlags,
3154 STRSAFE_LPCWSTR pszFormat,
3155 va_list argList)
3156 {
3157 return RtlpStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, NULL, argList);
3158 }
3159
3160 NTSTRSAFEAPI RtlStringVPrintfExWorkerLenW(
3161 STRSAFE_LPWSTR pszDest,
3162 size_t cchDest,
3163 size_t cbDest,
3164 STRSAFE_LPWSTR *ppszDestEnd,
3165 size_t *pcchRemaining,
3166 STRSAFE_DWORD dwFlags,
3167 STRSAFE_LPCWSTR pszFormat,
3168 size_t* pcchDestNewLen,
3169 va_list argList)
3170 {
3171 if (pcchDestNewLen == 0)
3172 return STATUS_INVALID_PARAMETER;
3173
3174 return RtlpStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, pcchDestNewLen, argList);
3175 }
3176
3177
3178 NTSTRSAFEAPI
3179 RtlStringLengthWorkerA(
3180 _In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz,
3181 _In_ _In_range_(<=, NTSTRSAFE_MAX_CCH) size_t cchMax,
3182 _Out_opt_ _Deref_out_range_(<, cchMax) size_t *pcchLength)
3183 {
3184 NTSTATUS Status = STATUS_SUCCESS;
3185 size_t cchMaxPrev = cchMax;
3186
3187 while (cchMax && (*psz != '\0'))
3188 {
3189 psz++;
3190 cchMax--;
3191 }
3192
3193 if (cchMax == 0)
3194 Status = STATUS_INVALID_PARAMETER;
3195
3196 if (pcchLength)
3197 {
3198 if (NT_SUCCESS(Status))
3199 *pcchLength = cchMaxPrev - cchMax;
3200 else
3201 *pcchLength = 0;
3202 }
3203
3204 return Status;
3205 }
3206
3207 NTSTRSAFEAPI
3208 RtlStringLengthWorkerW(
3209 _In_reads_or_z_(cchMax) STRSAFE_LPCWSTR psz,
3210 _In_ _In_range_(<=, NTSTRSAFE_MAX_CCH) size_t cchMax,
3211 _Out_opt_ _Deref_out_range_(<, cchMax) size_t *pcchLength)
3212 {
3213 NTSTATUS Status = STATUS_SUCCESS;
3214 size_t cchMaxPrev = cchMax;
3215
3216 while (cchMax && (*psz != L'\0'))
3217 {
3218 psz++;
3219 cchMax--;
3220 }
3221
3222 if (cchMax == 0)
3223 Status = STATUS_INVALID_PARAMETER;
3224
3225 if (pcchLength)
3226 {
3227 if (NT_SUCCESS(Status))
3228 *pcchLength = cchMaxPrev - cchMax;
3229 else
3230 *pcchLength = 0;
3231 }
3232
3233 return Status;
3234 }
3235
3236 NTSTRSAFEAPI
3237 RtlpUnicodeStringValidate(
3238 _In_opt_ PCUNICODE_STRING SourceString,
3239 _In_ STRSAFE_DWORD dwFlags)
3240 {
3241 if (SourceString)
3242 {
3243 if (SourceString->Length % sizeof(WCHAR) != 0 ||
3244 SourceString->MaximumLength % sizeof(WCHAR) != 0 ||
3245 SourceString->Length > SourceString->MaximumLength ||
3246 SourceString->MaximumLength > NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR) ||
3247 (SourceString->Buffer == NULL && (SourceString->Length != 0 || SourceString->MaximumLength != 0)))
3248 {
3249 return STATUS_INVALID_PARAMETER;
3250 }
3251 }
3252 else
3253 {
3254 if (!(dwFlags & STRSAFE_IGNORE_NULLS))
3255 return STATUS_INVALID_PARAMETER;
3256 }
3257
3258 return STATUS_SUCCESS;
3259 }
3260
3261 NTSTRSAFEAPI
3262 RtlUnicodeStringValidate(_In_opt_ PCUNICODE_STRING SourceString)
3263 {
3264 return RtlpUnicodeStringValidate(SourceString, 0);
3265 }
3266
3267 NTSTRSAFEAPI
3268 RtlUnicodeStringValidateEx(
3269 _In_opt_ PCUNICODE_STRING SourceString,
3270 _In_ STRSAFE_DWORD dwFlags)
3271 {
3272 if (dwFlags & ~(STRSAFE_UNICODE_STRING_VALID_FLAGS))
3273 return STATUS_INVALID_PARAMETER;
3274
3275 return RtlpUnicodeStringValidate(SourceString, dwFlags);
3276 }
3277
3278 NTSTRSAFEVAPI
3279 RtlUnicodeStringPrintf(
3280 _In_ PUNICODE_STRING DestinationString,
3281 _In_ NTSTRSAFE_PCWSTR pszFormat,
3282 ...)
3283 {
3284 NTSTATUS Status;
3285 size_t cchFinalLength;
3286 va_list argList;
3287
3288 if (DestinationString == NULL || pszFormat == NULL || DestinationString->Buffer == NULL)
3289 {
3290 Status = STATUS_INVALID_PARAMETER;
3291 }
3292 else
3293 {
3294 Status = RtlUnicodeStringValidate(DestinationString);
3295 if (NT_SUCCESS(Status))
3296 {
3297 va_start(argList, pszFormat);
3298
3299 Status = RtlStringVPrintfWorkerLenW(DestinationString->Buffer,
3300 DestinationString->MaximumLength / sizeof(WCHAR),
3301 pszFormat,
3302 &cchFinalLength,
3303 argList);
3304
3305 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
3306 {
3307 DestinationString->Length = (USHORT)(cchFinalLength * sizeof(WCHAR));
3308 }
3309
3310 va_end(argList);
3311 }
3312 }
3313
3314 return Status;
3315 }
3316
3317 NTSTRSAFEVAPI
3318 RtlUnicodeStringPrintfEx(
3319 _In_opt_ PUNICODE_STRING DestinationString,
3320 _In_opt_ PUNICODE_STRING RemainingString,
3321 _In_ STRSAFE_DWORD dwFlags,
3322 _In_ NTSTRSAFE_PCWSTR pszFormat, ...)
3323 {
3324 NTSTATUS Status;
3325 size_t cchFinalLength;
3326 size_t cchRemaining;
3327 va_list argList;
3328
3329 va_start(argList, pszFormat);
3330
3331 Status = RtlStringVPrintfExWorkerLenW(DestinationString->Buffer,
3332 DestinationString->MaximumLength / sizeof(WCHAR),
3333 DestinationString->MaximumLength,
3334 &RemainingString->Buffer,
3335 &cchRemaining,
3336 dwFlags,
3337 pszFormat,
3338 &cchFinalLength,
3339 argList);
3340
3341 va_end(argList);
3342
3343 if (Status == STATUS_BUFFER_OVERFLOW || NT_SUCCESS(Status))
3344 {
3345 DestinationString->Length = (USHORT)(cchFinalLength * sizeof(WCHAR));
3346
3347 if (RemainingString)
3348 {
3349 RemainingString->Length = 0;
3350 RemainingString->MaximumLength = (USHORT)cchRemaining * sizeof(WCHAR);
3351 }
3352 }
3353
3354 return Status;
3355 }
3356
3357 #define RtlStringCopyWorkerA RtlStringCopyWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
3358 #define RtlStringCopyWorkerW RtlStringCopyWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
3359 #define RtlStringCopyExWorkerA RtlStringCopyExWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
3360 #define RtlStringCopyExWorkerW RtlStringCopyExWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
3361 #define RtlStringCatWorkerA RtlStringCatWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
3362 #define RtlStringCatWorkerW RtlStringCatWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
3363 #define RtlStringCatExWorkerA RtlStringCatExWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
3364 #define RtlStringCatExWorkerW RtlStringCatExWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
3365 #define RtlStringCatNWorkerA RtlStringCatNWorkerA_instead_use_StringCchCatNA_or_StrincCbCatNA;
3366 #define RtlStringCatNWorkerW RtlStringCatNWorkerW_instead_use_StringCchCatNW_or_StringCbCatNW;
3367 #define RtlStringCatNExWorkerA RtlStringCatNExWorkerA_instead_use_StringCchCatNExA_or_StringCbCatNExA;
3368 #define RtlStringCatNExWorkerW RtlStringCatNExWorkerW_instead_use_StringCchCatNExW_or_StringCbCatNExW;
3369 #define RtlStringVPrintfWorkerA RtlStringVPrintfWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
3370 #define RtlStringVPrintfWorkerW RtlStringVPrintfWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
3371 #define RtlStringVPrintfExWorkerA RtlStringVPrintfExWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
3372 #define RtlStringVPrintfExWorkerW RtlStringVPrintfExWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
3373 #define RtlStringLengthWorkerA RtlStringLengthWorkerA_instead_use_StringCchLengthA_or_StringCbLengthA;
3374 #define RtlStringLengthWorkerW RtlStringLengthWorkerW_instead_use_StringCchLengthW_or_StringCbLengthW;
3375
3376 #ifdef _MSC_VER
3377 #pragma warning(pop)
3378 #endif /* _MSC_VER */
3379
3380 #endif /* _NTSTRSAFE_H_INCLUDED_ */