[NDK]
[reactos.git] / include / ddk / ntstrsafe.h
1 /*
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)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #ifndef _NTSTRSAFE_H_INCLUDED_
12 #define _NTSTRSAFE_H_INCLUDED_
13
14 //
15 // Dependencies
16 //
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdarg.h>
20
21 //
22 // Maximum limits: allow overriding the maximum
23 //
24 #ifndef NTSTRSAFE_MAX_CCH
25 #define NTSTRSAFE_MAX_CCH 2147483647
26 #endif
27 #define NTSTRSAFE_MAX_LENGTH (NTSTRSAFE_MAX_CCH - 1)
28
29 //
30 // Typedefs
31 //
32 typedef unsigned long DWORD;
33
34 /* PRIVATE FUNCTIONS *********************************************************/
35
36 __inline
37 NTSTATUS
38 NTAPI
39 RtlStringLengthWorkerA(IN LPCSTR String,
40 IN SIZE_T MaxLength,
41 OUT PSIZE_T ReturnLength OPTIONAL)
42 {
43 NTSTATUS Status = STATUS_SUCCESS;
44 SIZE_T LocalMax = MaxLength;
45
46 while (MaxLength && (*String != ANSI_NULL))
47 {
48 String++;
49 MaxLength--;
50 }
51
52 if (!MaxLength) Status = STATUS_INVALID_PARAMETER;
53
54 if (ReturnLength)
55 {
56 if (NT_SUCCESS(Status))
57 {
58 *ReturnLength = LocalMax - MaxLength;
59 }
60 else
61 {
62 *ReturnLength = 0;
63 }
64 }
65
66 return Status;
67 }
68
69 __inline
70 NTSTATUS
71 NTAPI
72 RtlStringValidateDestA(IN LPSTR Destination,
73 IN SIZE_T Length,
74 OUT PSIZE_T ReturnLength OPTIONAL,
75 IN SIZE_T MaxLength)
76 {
77 NTSTATUS Status = STATUS_SUCCESS;
78
79 if (!(Length) || (Length > MaxLength)) Status = STATUS_INVALID_PARAMETER;
80
81 if (ReturnLength)
82 {
83 if (NT_SUCCESS(Status))
84 {
85 Status = RtlStringLengthWorkerA(Destination,
86 Length,
87 ReturnLength);
88 }
89 else
90 {
91 *ReturnLength = 0;
92 }
93 }
94
95 return Status;
96 }
97
98 __inline
99 NTSTATUS
100 NTAPI
101 RtlStringExValidateDestA(IN OUT LPSTR *Destination,
102 IN OUT PSIZE_T DestinationLength,
103 OUT PSIZE_T ReturnLength OPTIONAL,
104 IN SIZE_T MaxLength,
105 IN DWORD Flags)
106 {
107 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
108 return RtlStringValidateDestA(*Destination,
109 *DestinationLength,
110 ReturnLength,
111 MaxLength);
112 }
113
114 __inline
115 NTSTATUS
116 NTAPI
117 RtlStringExValidateSrcA(IN OUT LPCSTR *Source OPTIONAL,
118 IN OUT PSIZE_T ReturnLength OPTIONAL,
119 IN SIZE_T MaxLength,
120 IN DWORD Flags)
121 {
122 NTSTATUS Status = STATUS_SUCCESS;
123 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
124
125 if ((ReturnLength) && (*ReturnLength >= MaxLength))
126 {
127 Status = STATUS_INVALID_PARAMETER;
128 }
129
130 return Status;
131 }
132
133 __inline
134 NTSTATUS
135 NTAPI
136 RtlStringVPrintfWorkerA(OUT LPSTR Destination,
137 IN SIZE_T Length,
138 OUT PSIZE_T NewLength OPTIONAL,
139 IN LPCSTR Format,
140 IN va_list argList)
141 {
142 NTSTATUS Status = STATUS_SUCCESS;
143 LONG Return;
144 SIZE_T MaxLength, LocalNewLength = 0;
145
146 MaxLength = Length - 1;
147
148 Return = _vsnprintf(Destination, MaxLength, Format, argList);
149 if ((Return < 0) || ((SIZE_T)Return > MaxLength))
150 {
151 Destination += MaxLength;
152 *Destination = ANSI_NULL;
153
154 LocalNewLength = MaxLength;
155
156 Status = STATUS_BUFFER_OVERFLOW;
157 }
158 else if ((SIZE_T)Return == MaxLength)
159 {
160 Destination += MaxLength;
161 *Destination = ANSI_NULL;
162
163 LocalNewLength = MaxLength;
164 }
165 else
166 {
167 LocalNewLength = Return;
168 }
169
170 if (NewLength) *NewLength = LocalNewLength;
171 return Status;
172 }
173
174 __inline
175 NTSTATUS
176 NTAPI
177 RtlStringCopyWorkerA(OUT LPSTR Destination,
178 IN SIZE_T Length,
179 OUT PSIZE_T NewLength OPTIONAL,
180 IN LPCSTR Source,
181 IN SIZE_T CopyLength)
182 {
183 NTSTATUS Status = STATUS_SUCCESS;
184 SIZE_T LocalNewLength = 0;
185
186 while ((Length) && (CopyLength) && (*Source != ANSI_NULL))
187 {
188 *Destination++ = *Source++;
189 Length--;
190 CopyLength--;
191
192 LocalNewLength++;
193 }
194
195 if (!Length)
196 {
197 Destination--;
198 LocalNewLength--;
199
200 Status = STATUS_BUFFER_OVERFLOW;
201 }
202
203 *Destination = ANSI_NULL;
204
205 if (NewLength) *NewLength = LocalNewLength;
206 return Status;
207 }
208
209 /* PUBLIC FUNCTIONS **********************************************************/
210
211 __inline
212 NTSTATUS
213 NTAPI
214 RtlStringCchCopyA(IN LPSTR Destination,
215 IN SIZE_T cchDest,
216 IN LPCSTR pszSrc)
217 {
218 ASSERTMSG("RtlStringCchCopyA is UNIMPLEMENTED!\n", FALSE);
219 return STATUS_NOT_IMPLEMENTED;
220 }
221
222 __inline
223 NTSTATUS
224 NTAPI
225 RtlStringCbPrintfA(OUT LPSTR Destination,
226 IN SIZE_T Length,
227 IN LPCSTR Format,
228 ...)
229 {
230 NTSTATUS Status;
231 SIZE_T CharLength = Length / sizeof(CHAR);
232 va_list argList;
233
234 Status = RtlStringValidateDestA(Destination,
235 CharLength,
236 NULL,
237 NTSTRSAFE_MAX_CCH);
238 if (NT_SUCCESS(Status))
239 {
240 va_start(argList, Format);
241 Status = RtlStringVPrintfWorkerA(Destination,
242 CharLength,
243 NULL,
244 Format,
245 argList);
246 va_end(argList);
247 }
248
249 return Status;
250 }
251
252 __inline
253 NTSTATUS
254 NTAPI
255 RtlStringCbPrintfExA(OUT LPSTR Destination,
256 IN SIZE_T Length,
257 OUT LPSTR *DestinationEnd OPTIONAL,
258 OUT PSIZE_T RemainingSize OPTIONAL,
259 IN DWORD Flags,
260 IN LPCSTR Format,
261 ...)
262 {
263 NTSTATUS Status;
264 SIZE_T CharLength = Length / sizeof(CHAR), Remaining, LocalNewLength = 0;
265 PCHAR LocalDestinationEnd;
266 va_list argList;
267 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
268
269 Status = RtlStringExValidateDestA(&Destination,
270 &CharLength,
271 NULL,
272 NTSTRSAFE_MAX_CCH,
273 Flags);
274 if (NT_SUCCESS(Status))
275 {
276 LocalDestinationEnd = Destination;
277 Remaining = CharLength;
278
279 Status = RtlStringExValidateSrcA(&Format,
280 NULL,
281 NTSTRSAFE_MAX_CCH,
282 Flags);
283 if (NT_SUCCESS(Status))
284 {
285 if (!Length)
286 {
287 if (*Format != ANSI_NULL)
288 {
289 if (!Destination)
290 {
291 Status = STATUS_INVALID_PARAMETER;
292 }
293 else
294 {
295 Status = STATUS_BUFFER_OVERFLOW;
296 }
297 }
298 }
299 else
300 {
301 va_start(argList, Format);
302 Status = RtlStringVPrintfWorkerA(Destination,
303 CharLength,
304 &LocalNewLength,
305 Format,
306 argList);
307 va_end(argList);
308
309 LocalDestinationEnd = Destination + LocalNewLength;
310 Remaining = CharLength - LocalNewLength;
311 }
312 }
313 else
314 {
315 if (Length) *Destination = ANSI_NULL;
316 }
317
318 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
319 {
320 if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
321
322 if (RemainingSize)
323 {
324 *RemainingSize = (Remaining * sizeof(CHAR)) +
325 (Length % sizeof(CHAR));
326 }
327 }
328 }
329
330 return Status;
331 }
332
333 __inline
334 NTSTATUS
335 NTAPI
336 RtlStringCbCopyExA(OUT LPSTR Destination,
337 IN SIZE_T Length,
338 IN LPCSTR Source,
339 OUT LPSTR *DestinationEnd OPTIONAL,
340 OUT PSIZE_T RemainingSize OPTIONAL,
341 IN DWORD Flags)
342 {
343 NTSTATUS Status;
344 SIZE_T CharLength = Length / sizeof(CHAR), Copied = 0, Remaining;
345 PCHAR LocalDestinationEnd;
346 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
347
348 Status = RtlStringExValidateDestA(&Destination,
349 &Length,
350 NULL,
351 NTSTRSAFE_MAX_CCH,
352 Flags);
353 if (NT_SUCCESS(Status))
354 {
355 LocalDestinationEnd = Destination;
356 Remaining = CharLength;
357
358 Status = RtlStringExValidateSrcA(&Source,
359 NULL,
360 NTSTRSAFE_MAX_CCH,
361 Flags);
362 if (NT_SUCCESS(Status))
363 {
364 if (!CharLength)
365 {
366 if (*Source != ANSI_NULL)
367 {
368 if (!Destination)
369 {
370 Status = STATUS_INVALID_PARAMETER;
371 }
372 else
373 {
374 Status = STATUS_BUFFER_OVERFLOW;
375 }
376 }
377 }
378 else
379 {
380 Status = RtlStringCopyWorkerA(Destination,
381 CharLength,
382 &Copied,
383 Source,
384 NTSTRSAFE_MAX_LENGTH);
385
386 LocalDestinationEnd = Destination + Copied;
387 Remaining = CharLength - Copied;
388 }
389 }
390 else
391 {
392 if (CharLength) *Destination = ANSI_NULL;
393 }
394
395 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
396 {
397 if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
398
399 if (RemainingSize)
400 {
401 *RemainingSize = (Remaining * sizeof(CHAR)) +
402 (Length % sizeof(CHAR));
403 }
404 }
405 }
406
407 return Status;
408 }
409
410 __inline
411 NTSTATUS
412 NTAPI
413 RtlStringCbPrintfW(
414 LPWSTR pszDest,
415 IN size_t cbDest,
416 IN LPCWSTR pszFormat,
417 ...)
418 {
419 ASSERTMSG("RtlStringCbPrintfW is UNIMPLEMENTED!\n", FALSE);
420 return STATUS_NOT_IMPLEMENTED;
421 }
422
423 __inline
424 NTSTATUS
425 NTAPI
426 RtlStringCbCatExA(IN OUT LPSTR Destination,
427 IN SIZE_T Length,
428 IN LPCSTR Source,
429 OUT LPSTR *DestinationEnd OPTIONAL,
430 OUT PSIZE_T RemainingSize OPTIONAL,
431 IN DWORD Flags)
432 {
433 NTSTATUS Status;
434 SIZE_T CharLength = Length / sizeof(CHAR);
435 SIZE_T DestinationLength, Remaining, Copied = 0;
436 PCHAR LocalDestinationEnd;
437 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
438
439 Status = RtlStringExValidateDestA(&Destination,
440 &CharLength,
441 &DestinationLength,
442 NTSTRSAFE_MAX_CCH,
443 Flags);
444 if (NT_SUCCESS(Status))
445 {
446 LocalDestinationEnd = Destination + DestinationLength;
447 Remaining = CharLength - DestinationLength;
448
449 Status = RtlStringExValidateSrcA(&Source,
450 NULL,
451 NTSTRSAFE_MAX_CCH,
452 Flags);
453 if (NT_SUCCESS(Status))
454 {
455 if (Remaining <= 1)
456 {
457 if (*Source != ANSI_NULL)
458 {
459 if (!Destination)
460 {
461 Status = STATUS_INVALID_PARAMETER;
462 }
463 else
464 {
465 Status = STATUS_BUFFER_OVERFLOW;
466 }
467 }
468 }
469 else
470 {
471 Status = RtlStringCopyWorkerA(LocalDestinationEnd,
472 Remaining,
473 &Copied,
474 Source,
475 NTSTRSAFE_MAX_LENGTH);
476
477 LocalDestinationEnd = LocalDestinationEnd + Copied;
478 Remaining = Remaining - Copied;
479 }
480 }
481
482 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
483 {
484 if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
485
486 if (RemainingSize)
487 {
488 *RemainingSize = (Remaining * sizeof(CHAR)) +
489 (Length % sizeof(CHAR));
490 }
491 }
492 }
493
494 return Status;
495 }
496
497 __inline
498 NTSTATUS
499 NTAPI
500 RtlStringCbCopyA(OUT LPSTR Destination,
501 IN SIZE_T Length,
502 IN LPCSTR Source)
503 {
504 NTSTATUS Status;
505 SIZE_T CharLength = Length / sizeof(CHAR);
506
507 Status = RtlStringValidateDestA(Destination,
508 CharLength,
509 NULL,
510 NTSTRSAFE_MAX_CCH);
511 if (NT_SUCCESS(Status))
512 {
513 Status = RtlStringCopyWorkerA(Destination,
514 CharLength,
515 NULL,
516 Source,
517 NTSTRSAFE_MAX_LENGTH);
518 }
519
520 return Status;
521 }
522
523 #endif