ReactOS 0.4.16-dev-401-g45b008d
name.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/fsrtl/name.c
5 * PURPOSE: Provides name parsing and other support routines for FSDs
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Filip Navara (navaraf@reactos.org)
8 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
9 * Aleksey Bragin (aleksey@reactos.org)
10 */
11
12/* INCLUDES ******************************************************************/
13
14#include <ntoskrnl.h>
15#define NDEBUG
16#include <debug.h>
17
18/* PRIVATE FUNCTIONS *********************************************************/
25{
26 USHORT Offset, Position, BackTrackingPosition, OldBackTrackingPosition;
27 USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0};
28 PUSHORT BackTrackingSwap, BackTracking = BackTrackingBuffer, OldBackTracking = OldBackTrackingBuffer;
29 ULONG BackTrackingBufferSize = RTL_NUMBER_OF(BackTrackingBuffer);
30 PVOID AllocatedBuffer = NULL;
31 UNICODE_STRING IntExpression;
32 USHORT ExpressionPosition, NamePosition = 0, MatchingChars = 1;
33 BOOLEAN EndOfName = FALSE;
35 BOOLEAN DontSkipDot;
36 WCHAR CompareChar;
37 PAGED_CODE();
38
39 /* Check if we were given strings at all */
40 if (!Name->Length || !Expression->Length)
41 {
42 /* Return TRUE if both strings are empty, otherwise FALSE */
43 if (!Name->Length && !Expression->Length)
44 return TRUE;
45 else
46 return FALSE;
47 }
48
49 /* Check for a shortcut: just one wildcard */
50 if (Expression->Length == sizeof(WCHAR))
51 {
52 if (Expression->Buffer[0] == L'*')
53 return TRUE;
54 }
55
57
58 /* Another shortcut, wildcard followed by some string */
59 if (Expression->Buffer[0] == L'*')
60 {
61 /* Copy Expression to our local variable */
62 IntExpression = *Expression;
63
64 /* Skip the first char */
65 IntExpression.Buffer++;
66 IntExpression.Length -= sizeof(WCHAR);
67
68 /* Continue only if the rest of the expression does NOT contain
69 any more wildcards */
70 if (!FsRtlDoesNameContainWildCards(&IntExpression))
71 {
72 /* Check for a degenerate case */
73 if (Name->Length < (Expression->Length - sizeof(WCHAR)))
74 return FALSE;
75
76 /* Calculate position */
77 NamePosition = (Name->Length - IntExpression.Length) / sizeof(WCHAR);
78
79 /* Compare */
80 if (!IgnoreCase)
81 {
82 /* We can just do a byte compare */
83 return RtlEqualMemory(IntExpression.Buffer,
84 Name->Buffer + NamePosition,
85 IntExpression.Length);
86 }
87 else
88 {
89 /* Not so easy, need to upcase and check char by char */
90 for (ExpressionPosition = 0; ExpressionPosition < (IntExpression.Length / sizeof(WCHAR)); ExpressionPosition++)
91 {
92 /* Assert that expression is already upcased! */
93 ASSERT(IntExpression.Buffer[ExpressionPosition] == UpcaseTable[IntExpression.Buffer[ExpressionPosition]]);
94
95 /* Now compare upcased name char with expression */
96 if (UpcaseTable[Name->Buffer[NamePosition + ExpressionPosition]] !=
97 IntExpression.Buffer[ExpressionPosition])
98 {
99 return FALSE;
100 }
101 }
102
103 /* It matches */
104 return TRUE;
105 }
106 }
107 }
108
109 /* Name parsing loop */
110 for (; !EndOfName; MatchingChars = BackTrackingPosition, NamePosition++)
111 {
112 /* Reset positions */
113 OldBackTrackingPosition = BackTrackingPosition = 0;
114
115 if (NamePosition >= Name->Length / sizeof(WCHAR))
116 {
117 EndOfName = TRUE;
118 if (MatchingChars && (OldBackTracking[MatchingChars - 1] == Expression->Length * 2))
119 break;
120 }
121
122 while (MatchingChars > OldBackTrackingPosition)
123 {
124 ExpressionPosition = (OldBackTracking[OldBackTrackingPosition++] + 1) / 2;
125
126 /* Expression parsing loop */
127 for (Offset = 0; ExpressionPosition < Expression->Length; Offset = sizeof(WCHAR))
128 {
129 ExpressionPosition += Offset;
130
131 if (ExpressionPosition == Expression->Length)
132 {
133 BackTracking[BackTrackingPosition++] = Expression->Length * 2;
134 break;
135 }
136
137 /* If buffer too small */
138 if (BackTrackingPosition > BackTrackingBufferSize - 3)
139 {
140 /* We should only ever get here once! */
141 ASSERT(AllocatedBuffer == NULL);
142 ASSERT((BackTracking == BackTrackingBuffer) || (BackTracking == OldBackTrackingBuffer));
143 ASSERT((OldBackTracking == BackTrackingBuffer) || (OldBackTracking == OldBackTrackingBuffer));
144
145 /* Calculate buffer size */
146 BackTrackingBufferSize = Expression->Length / sizeof(WCHAR) * 2 + 1;
147
148 /* Allocate memory for both back-tracking buffers */
150 2 * BackTrackingBufferSize * sizeof(USHORT),
151 'nrSF');
152 if (AllocatedBuffer == NULL)
153 {
154 DPRINT1("Failed to allocate BackTracking buffer. BackTrackingBufferSize = =x%lx\n",
155 BackTrackingBufferSize);
156 Result = FALSE;
157 goto Exit;
158 }
159
160 /* Copy BackTracking content. Note that it can point to either BackTrackingBuffer or OldBackTrackingBuffer */
161 RtlCopyMemory(AllocatedBuffer,
162 BackTracking,
163 RTL_NUMBER_OF(BackTrackingBuffer) * sizeof(USHORT));
164
165 /* Place current Backtracking is at the start of the new buffer */
166 BackTracking = AllocatedBuffer;
167
168 /* Copy OldBackTracking content */
169 RtlCopyMemory(&BackTracking[BackTrackingBufferSize],
170 OldBackTracking,
171 RTL_NUMBER_OF(OldBackTrackingBuffer) * sizeof(USHORT));
172
173 /* Place current OldBackTracking after current BackTracking in the buffer */
174 OldBackTracking = &BackTracking[BackTrackingBufferSize];
175 }
176
177 /* Basic check to test if chars are equal */
178 CompareChar = (NamePosition >= Name->Length / sizeof(WCHAR)) ? UNICODE_NULL : (IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] :
179 Name->Buffer[NamePosition]);
180 if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == CompareChar && !EndOfName)
181 {
182 BackTracking[BackTrackingPosition++] = (ExpressionPosition + sizeof(WCHAR)) * 2;
183 }
184 /* Check cases that eat one char */
185 else if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == L'?' && !EndOfName)
186 {
187 BackTracking[BackTrackingPosition++] = (ExpressionPosition + sizeof(WCHAR)) * 2;
188 }
189 /* Test star */
190 else if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == L'*')
191 {
192 BackTracking[BackTrackingPosition++] = ExpressionPosition * 2;
193 BackTracking[BackTrackingPosition++] = (ExpressionPosition * 2) + 3;
194 continue;
195 }
196 /* Check DOS_STAR */
197 else if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == DOS_STAR)
198 {
199 /* Look for last dot */
200 DontSkipDot = TRUE;
201 if (!EndOfName && Name->Buffer[NamePosition] == '.')
202 {
203 for (Position = NamePosition + 1; Position < Name->Length / sizeof(WCHAR); Position++)
204 {
205 if (Name->Buffer[Position] == L'.')
206 {
207 DontSkipDot = FALSE;
208 break;
209 }
210 }
211 }
212
213 if (EndOfName || Name->Buffer[NamePosition] != L'.' || !DontSkipDot)
214 BackTracking[BackTrackingPosition++] = ExpressionPosition * 2;
215
216 BackTracking[BackTrackingPosition++] = (ExpressionPosition * 2) + 3;
217 continue;
218 }
219 /* Check DOS_DOT */
220 else if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == DOS_DOT)
221 {
222 if (EndOfName) continue;
223
224 if (Name->Buffer[NamePosition] == L'.')
225 BackTracking[BackTrackingPosition++] = (ExpressionPosition + sizeof(WCHAR)) * 2;
226 }
227 /* Check DOS_QM */
228 else if (Expression->Buffer[ExpressionPosition / sizeof(WCHAR)] == DOS_QM)
229 {
230 if (EndOfName || Name->Buffer[NamePosition] == L'.') continue;
231
232 BackTracking[BackTrackingPosition++] = (ExpressionPosition + sizeof(WCHAR)) * 2;
233 }
234
235 /* Leave from loop */
236 break;
237 }
238
239 for (Position = 0; MatchingChars > OldBackTrackingPosition && Position < BackTrackingPosition; Position++)
240 {
241 while (MatchingChars > OldBackTrackingPosition &&
242 BackTracking[Position] > OldBackTracking[OldBackTrackingPosition])
243 {
244 ++OldBackTrackingPosition;
245 }
246 }
247 }
248
249 /* Swap pointers */
250 BackTrackingSwap = BackTracking;
251 BackTracking = OldBackTracking;
252 OldBackTracking = BackTrackingSwap;
253 }
254
255 /* Store result value */
256 Result = MatchingChars > 0 && (OldBackTracking[MatchingChars - 1] == (Expression->Length * 2));
257
258Exit:
259
260 /* Frees the memory if necessary */
261 if (AllocatedBuffer != NULL)
262 {
263 ExFreePoolWithTag(AllocatedBuffer, 'nrSF');
264 }
265
266 return Result;
267}
268
269/* PUBLIC FUNCTIONS **********************************************************/
270
271/*++
272 * @name FsRtlAreNamesEqual
273 * @implemented
274 *
275 * Compare two strings to check if they match
276 *
277 * @param Name1
278 * First unicode string to compare
279 *
280 * @param Name2
281 * Second unicode string to compare
282 *
283 * @param IgnoreCase
284 * If TRUE, Case will be ignored when comparing strings
285 *
286 * @param UpcaseTable
287 * Table for upcase letters. If NULL is given, system one will be used
288 *
289 * @return TRUE if the strings are equal
290 *
291 * @remarks From Bo Branten's ntifs.h v25.
292 *
293 *--*/
295NTAPI
300{
301 UNICODE_STRING UpcaseName1;
302 UNICODE_STRING UpcaseName2;
303 BOOLEAN StringsAreEqual, MemoryAllocated = FALSE;
304 USHORT i;
306 PAGED_CODE();
307
308 /* Well, first check their size */
309 if (Name1->Length != Name2->Length) return FALSE;
310
311 /* Check if the caller didn't give an upcase table */
312 if ((IgnoreCase) && !(UpcaseTable))
313 {
314 /* Upcase the string ourselves */
315 Status = RtlUpcaseUnicodeString(&UpcaseName1, Name1, TRUE);
317
318 /* Upcase the second string too */
319 Status = RtlUpcaseUnicodeString(&UpcaseName2, Name2, TRUE);
320 if (!NT_SUCCESS(Status))
321 {
322 RtlFreeUnicodeString(&UpcaseName1);
324 }
325
326 Name1 = &UpcaseName1;
327 Name2 = &UpcaseName2;
328
329 /* Make sure we go through the path below, but free the strings */
332 }
333
334 /* Do a case-sensitive search */
335 if (!IgnoreCase)
336 {
337 /* Use a raw memory compare */
338 StringsAreEqual = RtlEqualMemory(Name1->Buffer,
339 Name2->Buffer,
340 Name1->Length);
341
342 /* Check if we allocated strings */
343 if (MemoryAllocated)
344 {
345 /* Free them */
346 RtlFreeUnicodeString(&UpcaseName1);
347 RtlFreeUnicodeString(&UpcaseName2);
348 }
349
350 /* Return the equality */
351 return StringsAreEqual;
352 }
353 else
354 {
355 /* Case in-sensitive search */
356 for (i = 0; i < Name1->Length / sizeof(WCHAR); i++)
357 {
358 /* Check if the character matches */
359 if (UpcaseTable[Name1->Buffer[i]] != UpcaseTable[Name2->Buffer[i]])
360 {
361 /* Non-match found! */
362 return FALSE;
363 }
364 }
365
366 /* We finished the loop so we are equal */
367 return TRUE;
368 }
369}
370
371/*++
372 * @name FsRtlDissectName
373 * @implemented
374 *
375 * Dissects a given path name into first and remaining part.
376 *
377 * @param Name
378 * Unicode string to dissect.
379 *
380 * @param FirstPart
381 * Pointer to user supplied UNICODE_STRING, that will later point
382 * to the first part of the original name.
383 *
384 * @param RemainingPart
385 * Pointer to user supplied UNICODE_STRING, that will later point
386 * to the remaining part of the original name.
387 *
388 * @return None
389 *
390 * @remarks Example:
391 * Name: \test1\test2\test3
392 * FirstPart: test1
393 * RemainingPart: test2\test3
394 *
395 *--*/
396VOID
397NTAPI
401{
402 USHORT FirstPosition, i;
403 USHORT SkipFirstSlash = 0;
404 PAGED_CODE();
405
406 /* Zero the strings before continuing */
409
410 /* Just quit if the string is empty */
411 if (!Name.Length) return;
412
413 /* Find first backslash */
414 FirstPosition = Name.Length / sizeof(WCHAR) ;
415 for (i = 0; i < Name.Length / sizeof(WCHAR); i++)
416 {
417 /* If we found one... */
418 if (Name.Buffer[i] == L'\\')
419 {
420 /* If it begins string, just notice it and continue */
421 if (i == 0)
422 {
423 SkipFirstSlash = 1;
424 }
425 else
426 {
427 /* Else, save its position and break out of the loop */
428 FirstPosition = i;
429 break;
430 }
431 }
432 }
433
434 /* Set up the first result string */
435 FirstPart->Buffer = Name.Buffer + SkipFirstSlash;
436 FirstPart->Length = (FirstPosition - SkipFirstSlash) * sizeof(WCHAR);
438
439 /* And second one, if necessary */
440 if (FirstPosition < (Name.Length / sizeof(WCHAR)))
441 {
442 RemainingPart->Buffer = Name.Buffer + FirstPosition + 1;
443 RemainingPart->Length = Name.Length - (FirstPosition + 1) * sizeof(WCHAR);
445 }
446}
447
448/*++
449 * @name FsRtlDoesNameContainWildCards
450 * @implemented
451 *
452 * Checks if the given string contains WildCards
453 *
454 * @param Name
455 * Pointer to a UNICODE_STRING containing Name to examine
456 *
457 * @return TRUE if Name contains wildcards, FALSE otherwise
458 *
459 * @remarks From Bo Branten's ntifs.h v12.
460 *
461 *--*/
463NTAPI
465{
466 PWCHAR Ptr;
467 PAGED_CODE();
468
469 /* Loop through every character */
470 if (Name->Length)
471 {
472 Ptr = Name->Buffer + (Name->Length / sizeof(WCHAR)) - 1;
473 while ((Ptr >= Name->Buffer) && (*Ptr != L'\\'))
474 {
475 /* Check for Wildcard */
477 Ptr--;
478 }
479 }
480
481 /* Nothing Found */
482 return FALSE;
483}
484
485/*++
486 * @name FsRtlIsNameInExpression
487 * @implemented
488 *
489 * Check if the Name string is in the Expression string.
490 *
491 * @param Expression
492 * The string in which we've to find Name. It can contain wildcards.
493 * If IgnoreCase is set to TRUE, this string MUST BE uppercase.
494 *
495 * @param Name
496 * The string to find. It cannot contain wildcards
497 *
498 * @param IgnoreCase
499 * If set to TRUE, case will be ignore with upcasing both strings
500 *
501 * @param UpcaseTable
502 * If not NULL, and if IgnoreCase is set to TRUE, it will be used to
503 * upcase the both strings
504 *
505 * @return TRUE if Name is in Expression, FALSE otherwise
506 *
507 * @remarks From Bo Branten's ntifs.h v12. This function should be
508 * rewritten to avoid recursion and better wildcard handling
509 * should be implemented (see FsRtlDoesNameContainWildCards).
510 *
511 *--*/
513NTAPI
518{
521 UNICODE_STRING IntName;
522
523 if (IgnoreCase && !UpcaseTable)
524 {
526 if (!NT_SUCCESS(Status))
527 {
529 }
530 Name = &IntName;
532 }
533 else
534 {
535 IntName.Buffer = NULL;
536 }
537
539
540 if (IntName.Buffer != NULL)
541 {
542 RtlFreeUnicodeString(&IntName);
543 }
544
545 return Result;
546}
#define PAGED_CODE()
PCWSTR Expression
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define IgnoreCase
Definition: cdprocs.h:461
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define DOS_STAR
Definition: env_spec_w32.h:912
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define DOS_QM
Definition: env_spec_w32.h:913
#define DOS_DOT
Definition: env_spec_w32.h:914
#define PagedPool
Definition: env_spec_w32.h:308
_Out_ PANSI_STRING _Out_ PANSI_STRING RemainingPart
Definition: fsrtlfuncs.h:379
_Must_inspect_result_ _In_ PCUNICODE_STRING Name2
Definition: fsrtlfuncs.h:796
_Must_inspect_result_ _In_ PUNICODE_STRING _In_ BOOLEAN _In_opt_ PWCHAR UpcaseTable
Definition: fsrtlfuncs.h:809
#define FsRtlIsUnicodeCharacterWild(C)
Definition: fsrtlfuncs.h:1636
_Out_ PANSI_STRING FirstPart
Definition: fsrtlfuncs.h:378
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
CONST WCHAR * PCWCH
Definition: ntbasedef.h:419
#define UNICODE_NULL
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
BOOLEAN NTAPI FsRtlIsNameInExpression(IN PUNICODE_STRING Expression, IN PUNICODE_STRING Name, IN BOOLEAN IgnoreCase, IN PWCHAR UpcaseTable OPTIONAL)
Definition: name.c:514
BOOLEAN NTAPI FsRtlAreNamesEqual(IN PCUNICODE_STRING Name1, IN PCUNICODE_STRING Name2, IN BOOLEAN IgnoreCase, IN PCWCH UpcaseTable OPTIONAL)
Definition: name.c:296
BOOLEAN NTAPI FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
Definition: name.c:464
VOID NTAPI FsRtlDissectName(IN UNICODE_STRING Name, OUT PUNICODE_STRING FirstPart, OUT PUNICODE_STRING RemainingPart)
Definition: name.c:398
BOOLEAN NTAPI FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression, IN PUNICODE_STRING Name, IN BOOLEAN IgnoreCase, IN PWCHAR UpcaseTable OPTIONAL)
Definition: name.c:21
#define ExRaiseStatus
Definition: ntoskrnl.h:114
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
static void Exit(void)
Definition: sock.c:1330
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
USHORT MaximumLength
Definition: env_spec_w32.h:377
static COORD Position
Definition: mouse.c:34
#define NTAPI
Definition: typedefs.h:36
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
#define POOL_RAISE_IF_ALLOCATION_FAILURE
_Out_ PSECURITY_DESCRIPTOR _Out_ PBOOLEAN MemoryAllocated
Definition: obfuncs.h:24
__wchar_t WCHAR
Definition: xmlstorage.h:180