- Get rid of DDK's dependency on windef.h and winnt.h
[reactos.git] / reactos / include / ddk / ntstrsafe.h
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
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 FORCEINLINE
37 NTSTATUS
38 NTAPI
39 RtlStringLengthWorkerA(IN PCHAR 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 FORCEINLINE
70 NTSTATUS
71 NTAPI
72 RtlStringValidateDestA(IN PCHAR 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 FORCEINLINE
99 NTSTATUS
100 NTAPI
101 RtlStringExValidateDestA(IN OUT PCHAR *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 FORCEINLINE
115 NTSTATUS
116 NTAPI
117 RtlStringExValidateSrcA(IN OUT PCCHAR *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 FORCEINLINE
134 NTSTATUS
135 NTAPI
136 RtlStringVPrintfWorkerA(OUT PCHAR Destination,
137 IN SIZE_T Length,
138 OUT PSIZE_T NewLength OPTIONAL,
139 IN PCCHAR Format,
140 IN va_list argList)
141 {
142 NTSTATUS Status = STATUS_SUCCESS;
143 ULONG Return;
144 SIZE_T MaxLength, LocalNewLength = 0;
145
146 MaxLength = Length - 1;
147
148 Return = _vsnprintf(Destination, MaxLength, Format, argList);
149 if ((Return < 0) || (Return > MaxLength))
150 {
151 Destination += MaxLength;
152 *Destination = ANSI_NULL;
153
154 LocalNewLength = MaxLength;
155
156 Status = STATUS_BUFFER_OVERFLOW;
157 }
158 else if (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 FORCEINLINE
175 NTSTATUS
176 NTAPI
177 RtlStringCopyWorkerA(OUT PCHAR Destination,
178 IN SIZE_T Length,
179 OUT PSIZE_T NewLength OPTIONAL,
180 IN PCCHAR 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 NTSTATUS
212 NTAPI
213 RtlStringCbPrintfA(OUT PCHAR Destination,
214 IN SIZE_T Length,
215 IN PCHAR Format,
216 ...)
217 {
218 NTSTATUS Status;
219 SIZE_T CharLength = Length / sizeof(CHAR);
220 va_list argList;
221
222 Status = RtlStringValidateDestA(Destination,
223 CharLength,
224 NULL,
225 NTSTRSAFE_MAX_CCH);
226 if (NT_SUCCESS(Status))
227 {
228 va_start(argList, Format);
229 Status = RtlStringVPrintfWorkerA(Destination,
230 CharLength,
231 NULL,
232 Format,
233 argList);
234 va_end(argList);
235 }
236
237 return Status;
238 }
239
240 NTSTATUS
241 NTAPI
242 RtlStringCbPrintfExA(OUT PCHAR Destination,
243 IN SIZE_T Length,
244 OUT PCHAR *DestinationEnd OPTIONAL,
245 OUT PSIZE_T RemainingSize OPTIONAL,
246 IN DWORD Flags,
247 IN PCCHAR Format,
248 ...)
249 {
250 NTSTATUS Status;
251 SIZE_T CharLength = Length / sizeof(CHAR), Remaining, LocalNewLength = 0;
252 PCHAR LocalDestinationEnd;
253 va_list argList;
254 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
255
256 Status = RtlStringExValidateDestA(&Destination,
257 &CharLength,
258 NULL,
259 NTSTRSAFE_MAX_CCH,
260 Flags);
261 if (NT_SUCCESS(Status))
262 {
263 LocalDestinationEnd = Destination;
264 Remaining = CharLength;
265
266 Status = RtlStringExValidateSrcA(&Format,
267 NULL,
268 NTSTRSAFE_MAX_CCH,
269 Flags);
270 if (NT_SUCCESS(Status))
271 {
272 if (!Length)
273 {
274 if (*Format != ANSI_NULL)
275 {
276 if (!Destination)
277 {
278 Status = STATUS_INVALID_PARAMETER;
279 }
280 else
281 {
282 Status = STATUS_BUFFER_OVERFLOW;
283 }
284 }
285 }
286 else
287 {
288 va_start(argList, Format);
289 Status = RtlStringVPrintfWorkerA(Destination,
290 CharLength,
291 &LocalNewLength,
292 Format,
293 argList);
294 va_end(argList);
295
296 LocalDestinationEnd = Destination + LocalNewLength;
297 Remaining = CharLength - LocalNewLength;
298 }
299 }
300 else
301 {
302 if (Length) *Destination = ANSI_NULL;
303 }
304
305 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
306 {
307 if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
308
309 if (RemainingSize)
310 {
311 *RemainingSize = (Remaining * sizeof(CHAR)) +
312 (Length % sizeof(CHAR));
313 }
314 }
315 }
316
317 return Status;
318 }
319
320 FORCEINLINE
321 NTSTATUS
322 NTAPI
323 RtlStringCbCopyExA(OUT PCHAR Destination,
324 IN SIZE_T Length,
325 IN PCCHAR Source,
326 OUT PCHAR *DestinationEnd OPTIONAL,
327 OUT PSIZE_T RemainingSize OPTIONAL,
328 IN DWORD Flags)
329 {
330 NTSTATUS Status;
331 SIZE_T CharLength = Length / sizeof(CHAR), Copied = 0, Remaining;
332 PCHAR LocalDestinationEnd;
333 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
334
335 Status = RtlStringExValidateDestA(&Destination,
336 &Length,
337 NULL,
338 NTSTRSAFE_MAX_CCH,
339 Flags);
340 if (NT_SUCCESS(Status))
341 {
342 LocalDestinationEnd = Destination;
343 Remaining = CharLength;
344
345 Status = RtlStringExValidateSrcA(&Source,
346 NULL,
347 NTSTRSAFE_MAX_CCH,
348 Flags);
349 if (NT_SUCCESS(Status))
350 {
351 if (!CharLength)
352 {
353 if (*Source != ANSI_NULL)
354 {
355 if (!Destination)
356 {
357 Status = STATUS_INVALID_PARAMETER;
358 }
359 else
360 {
361 Status = STATUS_BUFFER_OVERFLOW;
362 }
363 }
364 }
365 else
366 {
367 Status = RtlStringCopyWorkerA(Destination,
368 CharLength,
369 &Copied,
370 Source,
371 NTSTRSAFE_MAX_LENGTH);
372
373 LocalDestinationEnd = Destination + Copied;
374 Remaining = CharLength - Copied;
375 }
376 }
377 else
378 {
379 if (CharLength) *Destination = ANSI_NULL;
380 }
381
382 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
383 {
384 if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
385
386 if (RemainingSize)
387 {
388 *RemainingSize = (Remaining * sizeof(CHAR)) +
389 (Length % sizeof(CHAR));
390 }
391 }
392 }
393
394 return Status;
395 }
396
397 FORCEINLINE
398 NTSTATUS
399 NTAPI
400 RtlStringCbCatExA(IN OUT PCHAR Destination,
401 IN SIZE_T Length,
402 IN PCCHAR Source,
403 OUT PCHAR *DestinationEnd OPTIONAL,
404 OUT PSIZE_T RemainingSize OPTIONAL,
405 IN DWORD Flags)
406 {
407 NTSTATUS Status;
408 SIZE_T CharLength = Length / sizeof(CHAR);
409 SIZE_T DestinationLength, Remaining, Copied = 0;
410 PCHAR LocalDestinationEnd;
411 ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
412
413 Status = RtlStringExValidateDestA(&Destination,
414 &CharLength,
415 &DestinationLength,
416 NTSTRSAFE_MAX_CCH,
417 Flags);
418 if (NT_SUCCESS(Status))
419 {
420 LocalDestinationEnd = Destination + DestinationLength;
421 Remaining = CharLength - DestinationLength;
422
423 Status = RtlStringExValidateSrcA(&Source,
424 NULL,
425 NTSTRSAFE_MAX_CCH,
426 Flags);
427 if (NT_SUCCESS(Status))
428 {
429 if (Remaining <= 1)
430 {
431 if (*Source != ANSI_NULL)
432 {
433 if (!Destination)
434 {
435 Status = STATUS_INVALID_PARAMETER;
436 }
437 else
438 {
439 Status = STATUS_BUFFER_OVERFLOW;
440 }
441 }
442 }
443 else
444 {
445 Status = RtlStringCopyWorkerA(LocalDestinationEnd,
446 Remaining,
447 &Copied,
448 Source,
449 NTSTRSAFE_MAX_LENGTH);
450
451 LocalDestinationEnd = LocalDestinationEnd + Copied;
452 Remaining = Remaining - Copied;
453 }
454 }
455
456 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
457 {
458 if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
459
460 if (RemainingSize)
461 {
462 *RemainingSize = (Remaining * sizeof(CHAR)) +
463 (Length % sizeof(CHAR));
464 }
465 }
466 }
467
468 return Status;
469 }
470
471 FORCEINLINE
472 NTSTATUS
473 NTAPI
474 RtlStringCbCopyA(OUT PCHAR Destination,
475 IN SIZE_T Length,
476 IN PCCHAR Source)
477 {
478 NTSTATUS Status;
479 SIZE_T CharLength = Length / sizeof(CHAR);
480
481 Status = RtlStringValidateDestA(Destination,
482 CharLength,
483 NULL,
484 NTSTRSAFE_MAX_CCH);
485 if (NT_SUCCESS(Status))
486 {
487 Status = RtlStringCopyWorkerA(Destination,
488 CharLength,
489 NULL,
490 Source,
491 NTSTRSAFE_MAX_LENGTH);
492 }
493
494 return Status;
495 }
496
497 #endif