[WIN32K]
[reactos.git] / reactos / 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 static __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 static __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 static __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 static __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 static __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 static __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 static __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 static __inline
223 NTSTATUS
224 RtlStringCbPrintfA(OUT LPSTR Destination,
225 IN SIZE_T Length,
226 IN LPCSTR Format,
227 ...)
228 {
229 NTSTATUS Status;
230 SIZE_T CharLength = Length / sizeof(CHAR);
231 va_list argList;
232
233 Status = RtlStringValidateDestA(Destination,
234 CharLength,
235 NULL,
236 NTSTRSAFE_MAX_CCH);
237 if (NT_SUCCESS(Status))
238 {
239 va_start(argList, Format);
240 Status = RtlStringVPrintfWorkerA(Destination,
241 CharLength,
242 NULL,
243 Format,
244 argList);
245 va_end(argList);
246 }
247
248 return Status;
249 }
250
251 static __inline
252 NTSTATUS
253 RtlStringCbPrintfExA(OUT LPSTR Destination,
254 IN SIZE_T Length,
255 OUT LPSTR *DestinationEnd OPTIONAL,
256 OUT PSIZE_T RemainingSize OPTIONAL,
257 IN DWORD Flags,
258 IN LPCSTR Format,
259 ...)
260 {
261 NTSTATUS Status;
262 SIZE_T CharLength = Length / sizeof(CHAR), Remaining, LocalNewLength = 0;
263 PCHAR LocalDestinationEnd;
264 va_list argList;
265 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
266
267 Status = RtlStringExValidateDestA(&Destination,
268 &CharLength,
269 NULL,
270 NTSTRSAFE_MAX_CCH,
271 Flags);
272 if (NT_SUCCESS(Status))
273 {
274 LocalDestinationEnd = Destination;
275 Remaining = CharLength;
276
277 Status = RtlStringExValidateSrcA(&Format,
278 NULL,
279 NTSTRSAFE_MAX_CCH,
280 Flags);
281 if (NT_SUCCESS(Status))
282 {
283 if (!Length)
284 {
285 if (*Format != ANSI_NULL)
286 {
287 if (!Destination)
288 {
289 Status = STATUS_INVALID_PARAMETER;
290 }
291 else
292 {
293 Status = STATUS_BUFFER_OVERFLOW;
294 }
295 }
296 }
297 else
298 {
299 va_start(argList, Format);
300 Status = RtlStringVPrintfWorkerA(Destination,
301 CharLength,
302 &LocalNewLength,
303 Format,
304 argList);
305 va_end(argList);
306
307 LocalDestinationEnd = Destination + LocalNewLength;
308 Remaining = CharLength - LocalNewLength;
309 }
310 }
311 else
312 {
313 if (Length) *Destination = ANSI_NULL;
314 }
315
316 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
317 {
318 if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
319
320 if (RemainingSize)
321 {
322 *RemainingSize = (Remaining * sizeof(CHAR)) +
323 (Length % sizeof(CHAR));
324 }
325 }
326 }
327
328 return Status;
329 }
330
331 static __inline
332 NTSTATUS
333 NTAPI
334 RtlStringCbCopyExA(OUT LPSTR Destination,
335 IN SIZE_T Length,
336 IN LPCSTR Source,
337 OUT LPSTR *DestinationEnd OPTIONAL,
338 OUT PSIZE_T RemainingSize OPTIONAL,
339 IN DWORD Flags)
340 {
341 NTSTATUS Status;
342 SIZE_T CharLength = Length / sizeof(CHAR), Copied = 0, Remaining;
343 PCHAR LocalDestinationEnd;
344 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
345
346 Status = RtlStringExValidateDestA(&Destination,
347 &Length,
348 NULL,
349 NTSTRSAFE_MAX_CCH,
350 Flags);
351 if (NT_SUCCESS(Status))
352 {
353 LocalDestinationEnd = Destination;
354 Remaining = CharLength;
355
356 Status = RtlStringExValidateSrcA(&Source,
357 NULL,
358 NTSTRSAFE_MAX_CCH,
359 Flags);
360 if (NT_SUCCESS(Status))
361 {
362 if (!CharLength)
363 {
364 if (*Source != ANSI_NULL)
365 {
366 if (!Destination)
367 {
368 Status = STATUS_INVALID_PARAMETER;
369 }
370 else
371 {
372 Status = STATUS_BUFFER_OVERFLOW;
373 }
374 }
375 }
376 else
377 {
378 Status = RtlStringCopyWorkerA(Destination,
379 CharLength,
380 &Copied,
381 Source,
382 NTSTRSAFE_MAX_LENGTH);
383
384 LocalDestinationEnd = Destination + Copied;
385 Remaining = CharLength - Copied;
386 }
387 }
388 else
389 {
390 if (CharLength) *Destination = ANSI_NULL;
391 }
392
393 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
394 {
395 if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
396
397 if (RemainingSize)
398 {
399 *RemainingSize = (Remaining * sizeof(CHAR)) +
400 (Length % sizeof(CHAR));
401 }
402 }
403 }
404
405 return Status;
406 }
407
408 static __inline
409 NTSTATUS
410 RtlStringCbPrintfW(
411 LPWSTR pszDest,
412 IN size_t cbDest,
413 IN LPCWSTR pszFormat,
414 ...)
415 {
416 ASSERTMSG("RtlStringCbPrintfW is UNIMPLEMENTED!\n", FALSE);
417 return STATUS_NOT_IMPLEMENTED;
418 }
419
420 static __inline
421 NTSTATUS
422 NTAPI
423 RtlStringCbCatExA(IN OUT LPSTR Destination,
424 IN SIZE_T Length,
425 IN LPCSTR Source,
426 OUT LPSTR *DestinationEnd OPTIONAL,
427 OUT PSIZE_T RemainingSize OPTIONAL,
428 IN DWORD Flags)
429 {
430 NTSTATUS Status;
431 SIZE_T CharLength = Length / sizeof(CHAR);
432 SIZE_T DestinationLength, Remaining, Copied = 0;
433 PCHAR LocalDestinationEnd;
434 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
435
436 Status = RtlStringExValidateDestA(&Destination,
437 &CharLength,
438 &DestinationLength,
439 NTSTRSAFE_MAX_CCH,
440 Flags);
441 if (NT_SUCCESS(Status))
442 {
443 LocalDestinationEnd = Destination + DestinationLength;
444 Remaining = CharLength - DestinationLength;
445
446 Status = RtlStringExValidateSrcA(&Source,
447 NULL,
448 NTSTRSAFE_MAX_CCH,
449 Flags);
450 if (NT_SUCCESS(Status))
451 {
452 if (Remaining <= 1)
453 {
454 if (*Source != ANSI_NULL)
455 {
456 if (!Destination)
457 {
458 Status = STATUS_INVALID_PARAMETER;
459 }
460 else
461 {
462 Status = STATUS_BUFFER_OVERFLOW;
463 }
464 }
465 }
466 else
467 {
468 Status = RtlStringCopyWorkerA(LocalDestinationEnd,
469 Remaining,
470 &Copied,
471 Source,
472 NTSTRSAFE_MAX_LENGTH);
473
474 LocalDestinationEnd = LocalDestinationEnd + Copied;
475 Remaining = Remaining - Copied;
476 }
477 }
478
479 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
480 {
481 if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
482
483 if (RemainingSize)
484 {
485 *RemainingSize = (Remaining * sizeof(CHAR)) +
486 (Length % sizeof(CHAR));
487 }
488 }
489 }
490
491 return Status;
492 }
493
494 static __inline
495 NTSTATUS
496 NTAPI
497 RtlStringCbCopyA(OUT LPSTR Destination,
498 IN SIZE_T Length,
499 IN LPCSTR Source)
500 {
501 NTSTATUS Status;
502 SIZE_T CharLength = Length / sizeof(CHAR);
503
504 Status = RtlStringValidateDestA(Destination,
505 CharLength,
506 NULL,
507 NTSTRSAFE_MAX_CCH);
508 if (NT_SUCCESS(Status))
509 {
510 Status = RtlStringCopyWorkerA(Destination,
511 CharLength,
512 NULL,
513 Source,
514 NTSTRSAFE_MAX_LENGTH);
515 }
516
517 return Status;
518 }
519
520 #endif /* _NTSTRSAFE_H_INCLUDED_ */