2 * PROJECT: ReactOS Kernel
3 * LICENSE: This file is in the public domain.
4 * FILE: include/ddk/ntstrsafe.h
5 * PURPOSE: Safe String Library for NT Code (Native/Kernel)
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
11 #ifndef _NTSTRSAFE_H_INCLUDED_
12 #define _NTSTRSAFE_H_INCLUDED_
20 #include <windef.h> /* we need DWORD */
23 // Maximum limits: allow overriding the maximum
25 #ifndef NTSTRSAFE_MAX_CCH
26 #define NTSTRSAFE_MAX_CCH 2147483647
28 #define NTSTRSAFE_MAX_LENGTH (NTSTRSAFE_MAX_CCH - 1)
30 /* PRIVATE FUNCTIONS *********************************************************/
35 RtlStringLengthWorkerA(IN LPCSTR String
,
37 OUT PSIZE_T ReturnLength OPTIONAL
)
39 NTSTATUS Status
= STATUS_SUCCESS
;
40 SIZE_T LocalMax
= MaxLength
;
42 while (MaxLength
&& (*String
!= ANSI_NULL
))
48 if (!MaxLength
) Status
= STATUS_INVALID_PARAMETER
;
52 if (NT_SUCCESS(Status
))
54 *ReturnLength
= LocalMax
- MaxLength
;
68 RtlStringLengthWorkerW(IN LPCWSTR String
,
70 OUT PSIZE_T ReturnLength OPTIONAL
)
72 NTSTATUS Status
= STATUS_SUCCESS
;
73 SIZE_T LocalMax
= MaxLength
;
75 while (MaxLength
&& (*String
!= UNICODE_NULL
))
81 if (!MaxLength
) Status
= STATUS_INVALID_PARAMETER
;
85 if (NT_SUCCESS(Status
))
87 *ReturnLength
= LocalMax
- MaxLength
;
101 RtlStringValidateDestA(IN LPSTR Destination
,
103 OUT PSIZE_T ReturnLength OPTIONAL
,
106 NTSTATUS Status
= STATUS_SUCCESS
;
108 if (!(Length
) || (Length
> MaxLength
)) Status
= STATUS_INVALID_PARAMETER
;
112 if (NT_SUCCESS(Status
))
114 Status
= RtlStringLengthWorkerA(Destination
,
130 RtlStringValidateDestW(IN LPWSTR Destination
,
132 OUT PSIZE_T ReturnLength OPTIONAL
,
135 NTSTATUS Status
= STATUS_SUCCESS
;
137 if (!(Length
) || (Length
> MaxLength
)) Status
= STATUS_INVALID_PARAMETER
;
141 if (NT_SUCCESS(Status
))
143 Status
= RtlStringLengthWorkerW(Destination
,
159 RtlStringExValidateDestA(IN OUT LPSTR
*Destination
,
160 IN OUT PSIZE_T DestinationLength
,
161 OUT PSIZE_T ReturnLength OPTIONAL
,
165 ASSERTMSG("We don't support Extended Flags yet!\n", Flags
== 0);
166 return RtlStringValidateDestA(*Destination
,
175 RtlStringExValidateDestW(IN OUT LPWSTR
*Destination
,
176 IN OUT PSIZE_T DestinationLength
,
177 OUT PSIZE_T ReturnLength OPTIONAL
,
181 ASSERTMSG("We don't support Extended Flags yet!\n", Flags
== 0);
182 return RtlStringValidateDestW(*Destination
,
191 RtlStringExValidateSrcA(IN OUT LPCSTR
*Source OPTIONAL
,
192 IN OUT PSIZE_T ReturnLength OPTIONAL
,
196 NTSTATUS Status
= STATUS_SUCCESS
;
197 ASSERTMSG("We don't support Extended Flags yet!\n", Flags
== 0);
199 if ((ReturnLength
) && (*ReturnLength
>= MaxLength
))
201 Status
= STATUS_INVALID_PARAMETER
;
210 RtlStringExValidateSrcW(IN OUT LPCWSTR
*Source OPTIONAL
,
211 IN OUT PSIZE_T ReturnLength OPTIONAL
,
215 NTSTATUS Status
= STATUS_SUCCESS
;
216 ASSERTMSG("We don't support Extended Flags yet!\n", Flags
== 0);
218 if ((ReturnLength
) && (*ReturnLength
>= MaxLength
))
220 Status
= STATUS_INVALID_PARAMETER
;
229 RtlStringVPrintfWorkerA(OUT LPSTR Destination
,
231 OUT PSIZE_T NewLength OPTIONAL
,
235 NTSTATUS Status
= STATUS_SUCCESS
;
237 SIZE_T MaxLength
, LocalNewLength
= 0;
239 MaxLength
= Length
- 1;
241 Return
= _vsnprintf(Destination
, MaxLength
, Format
, argList
);
242 if ((Return
< 0) || ((SIZE_T
)Return
> MaxLength
))
244 Destination
+= MaxLength
;
245 *Destination
= ANSI_NULL
;
247 LocalNewLength
= MaxLength
;
249 Status
= STATUS_BUFFER_OVERFLOW
;
251 else if ((SIZE_T
)Return
== MaxLength
)
253 Destination
+= MaxLength
;
254 *Destination
= ANSI_NULL
;
256 LocalNewLength
= MaxLength
;
260 LocalNewLength
= Return
;
263 if (NewLength
) *NewLength
= LocalNewLength
;
270 RtlStringCopyWorkerA(OUT LPSTR Destination
,
272 OUT PSIZE_T NewLength OPTIONAL
,
274 IN SIZE_T CopyLength
)
276 NTSTATUS Status
= STATUS_SUCCESS
;
277 SIZE_T LocalNewLength
= 0;
279 while ((Length
) && (CopyLength
) && (*Source
!= ANSI_NULL
))
281 *Destination
++ = *Source
++;
293 Status
= STATUS_BUFFER_OVERFLOW
;
296 *Destination
= ANSI_NULL
;
298 if (NewLength
) *NewLength
= LocalNewLength
;
305 RtlStringCopyWorkerW(OUT LPWSTR Destination
,
307 OUT PSIZE_T NewLength OPTIONAL
,
309 IN SIZE_T CopyLength
)
311 NTSTATUS Status
= STATUS_SUCCESS
;
312 SIZE_T LocalNewLength
= 0;
314 while ((Length
) && (CopyLength
) && (*Source
!= UNICODE_NULL
))
316 *Destination
++ = *Source
++;
328 Status
= STATUS_BUFFER_OVERFLOW
;
331 *Destination
= UNICODE_NULL
;
333 if (NewLength
) *NewLength
= LocalNewLength
;
337 /* PUBLIC FUNCTIONS **********************************************************/
342 RtlStringCchCopyA(IN LPSTR Destination
,
346 ASSERTMSG("RtlStringCchCopyA is UNIMPLEMENTED!\n", FALSE
);
347 return STATUS_NOT_IMPLEMENTED
;
353 RtlStringCchCopyW(IN LPWSTR Destination
,
357 ASSERTMSG("RtlStringCchCopyA is UNIMPLEMENTED!\n", FALSE
);
358 return STATUS_NOT_IMPLEMENTED
;
363 RtlStringCbPrintfA(OUT LPSTR Destination
,
369 SIZE_T CharLength
= Length
/ sizeof(CHAR
);
372 Status
= RtlStringValidateDestA(Destination
,
376 if (NT_SUCCESS(Status
))
378 va_start(argList
, Format
);
379 Status
= RtlStringVPrintfWorkerA(Destination
,
392 RtlStringCbPrintfExA(OUT LPSTR Destination
,
394 OUT LPSTR
*DestinationEnd OPTIONAL
,
395 OUT PSIZE_T RemainingSize OPTIONAL
,
401 SIZE_T CharLength
= Length
/ sizeof(CHAR
), Remaining
, LocalNewLength
= 0;
402 PCHAR LocalDestinationEnd
;
404 ASSERTMSG("We don't support Extended Flags yet!\n", Flags
== 0);
406 Status
= RtlStringExValidateDestA(&Destination
,
411 if (NT_SUCCESS(Status
))
413 LocalDestinationEnd
= Destination
;
414 Remaining
= CharLength
;
416 Status
= RtlStringExValidateSrcA(&Format
,
420 if (NT_SUCCESS(Status
))
424 if (*Format
!= ANSI_NULL
)
428 Status
= STATUS_INVALID_PARAMETER
;
432 Status
= STATUS_BUFFER_OVERFLOW
;
438 va_start(argList
, Format
);
439 Status
= RtlStringVPrintfWorkerA(Destination
,
446 LocalDestinationEnd
= Destination
+ LocalNewLength
;
447 Remaining
= CharLength
- LocalNewLength
;
452 if (Length
) *Destination
= ANSI_NULL
;
455 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
457 if (DestinationEnd
) *DestinationEnd
= LocalDestinationEnd
;
461 *RemainingSize
= (Remaining
* sizeof(CHAR
)) +
462 (Length
% sizeof(CHAR
));
473 RtlStringCbCopyExA(OUT LPSTR Destination
,
476 OUT LPSTR
*DestinationEnd OPTIONAL
,
477 OUT PSIZE_T RemainingSize OPTIONAL
,
481 SIZE_T CharLength
= Length
/ sizeof(CHAR
), Copied
= 0, Remaining
;
482 PCHAR LocalDestinationEnd
;
483 ASSERTMSG("We don't support Extended Flags yet!\n", Flags
== 0);
485 Status
= RtlStringExValidateDestA(&Destination
,
490 if (NT_SUCCESS(Status
))
492 LocalDestinationEnd
= Destination
;
493 Remaining
= CharLength
;
495 Status
= RtlStringExValidateSrcA(&Source
,
499 if (NT_SUCCESS(Status
))
503 if (*Source
!= ANSI_NULL
)
507 Status
= STATUS_INVALID_PARAMETER
;
511 Status
= STATUS_BUFFER_OVERFLOW
;
517 Status
= RtlStringCopyWorkerA(Destination
,
521 NTSTRSAFE_MAX_LENGTH
);
523 LocalDestinationEnd
= Destination
+ Copied
;
524 Remaining
= CharLength
- Copied
;
529 if (CharLength
) *Destination
= ANSI_NULL
;
532 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
534 if (DestinationEnd
) *DestinationEnd
= LocalDestinationEnd
;
538 *RemainingSize
= (Remaining
* sizeof(CHAR
)) +
539 (Length
% sizeof(CHAR
));
552 IN LPCWSTR pszFormat
,
555 ASSERTMSG("RtlStringCbPrintfW is UNIMPLEMENTED!\n", FALSE
);
556 return STATUS_NOT_IMPLEMENTED
;
562 RtlStringCbCatExA(IN OUT LPSTR Destination
,
565 OUT LPSTR
*DestinationEnd OPTIONAL
,
566 OUT PSIZE_T RemainingSize OPTIONAL
,
570 SIZE_T CharLength
= Length
/ sizeof(CHAR
);
571 SIZE_T DestinationLength
, Remaining
, Copied
= 0;
572 PCHAR LocalDestinationEnd
;
573 ASSERTMSG("We don't support Extended Flags yet!\n", Flags
== 0);
575 Status
= RtlStringExValidateDestA(&Destination
,
580 if (NT_SUCCESS(Status
))
582 LocalDestinationEnd
= Destination
+ DestinationLength
;
583 Remaining
= CharLength
- DestinationLength
;
585 Status
= RtlStringExValidateSrcA(&Source
,
589 if (NT_SUCCESS(Status
))
593 if (*Source
!= ANSI_NULL
)
597 Status
= STATUS_INVALID_PARAMETER
;
601 Status
= STATUS_BUFFER_OVERFLOW
;
607 Status
= RtlStringCopyWorkerA(LocalDestinationEnd
,
611 NTSTRSAFE_MAX_LENGTH
);
613 LocalDestinationEnd
= LocalDestinationEnd
+ Copied
;
614 Remaining
= Remaining
- Copied
;
618 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
620 if (DestinationEnd
) *DestinationEnd
= LocalDestinationEnd
;
624 *RemainingSize
= (Remaining
* sizeof(CHAR
)) +
625 (Length
% sizeof(CHAR
));
636 RtlStringCbCatExW(IN OUT LPWSTR Destination
,
639 OUT LPWSTR
*DestinationEnd OPTIONAL
,
640 OUT PSIZE_T RemainingSize OPTIONAL
,
644 SIZE_T CharLength
= Length
/ sizeof(WCHAR
);
645 SIZE_T DestinationLength
, Remaining
, Copied
= 0;
646 PWCHAR LocalDestinationEnd
;
647 ASSERTMSG("We don't support Extended Flags yet!\n", Flags
== 0);
649 Status
= RtlStringExValidateDestW(&Destination
,
654 if (NT_SUCCESS(Status
))
656 LocalDestinationEnd
= Destination
+ DestinationLength
;
657 Remaining
= CharLength
- DestinationLength
;
659 Status
= RtlStringExValidateSrcW(&Source
,
663 if (NT_SUCCESS(Status
))
667 if (*Source
!= UNICODE_NULL
)
671 Status
= STATUS_INVALID_PARAMETER
;
675 Status
= STATUS_BUFFER_OVERFLOW
;
681 Status
= RtlStringCopyWorkerW(LocalDestinationEnd
,
685 NTSTRSAFE_MAX_LENGTH
);
687 LocalDestinationEnd
= LocalDestinationEnd
+ Copied
;
688 Remaining
= Remaining
- Copied
;
692 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
694 if (DestinationEnd
) *DestinationEnd
= LocalDestinationEnd
;
698 *RemainingSize
= (Remaining
* sizeof(WCHAR
)) +
699 (Length
% sizeof(WCHAR
));
710 RtlStringCbCopyA(OUT LPSTR Destination
,
715 SIZE_T CharLength
= Length
/ sizeof(CHAR
);
717 Status
= RtlStringValidateDestA(Destination
,
721 if (NT_SUCCESS(Status
))
723 Status
= RtlStringCopyWorkerA(Destination
,
727 NTSTRSAFE_MAX_LENGTH
);
736 RtlStringCbCopyW(OUT LPWSTR Destination
,
741 SIZE_T CharLength
= Length
/ sizeof(WCHAR
);
743 Status
= RtlStringValidateDestW(Destination
,
747 if (NT_SUCCESS(Status
))
749 Status
= RtlStringCopyWorkerW(Destination
,
753 NTSTRSAFE_MAX_LENGTH
);
759 #endif /* _NTSTRSAFE_H_INCLUDED_ */