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