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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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( 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( 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( 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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( 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( 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 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 3224 RtlUnicodeStringValidate(_In_opt_ PCUNICODE_STRING SourceString) 3225 { 3226 return RtlpUnicodeStringValidate(SourceString, 0); 3227 } 3228 3229 NTSTRSAFEAPI 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 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 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