2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/utils.c
5 * PURPOSE: Utility and Support Functions
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
10 /* INCLUDES ******************************************************************/
14 #include "i386/ketypes.h"
15 #elif defined _M_AMD64
16 #include "amd64/ketypes.h"
22 /* GLOBALS ********************************************************************/
24 UNICODE_STRING Restricted
= RTL_CONSTANT_STRING(L
"Restricted");
25 BOOL bIsFileApiAnsi
= TRUE
; // set the file api to ansi or oem
26 PRTL_CONVERT_STRING Basep8BitStringToUnicodeString
= RtlAnsiStringToUnicodeString
;
27 PRTL_CONVERT_STRINGA BasepUnicodeStringTo8BitString
= RtlUnicodeStringToAnsiString
;
28 PRTL_COUNT_STRING BasepUnicodeStringTo8BitSize
= BasepUnicodeStringToAnsiSize
;
29 PRTL_COUNT_STRINGA Basep8BitStringToUnicodeSize
= BasepAnsiStringToUnicodeSize
;
31 /* FUNCTIONS ******************************************************************/
35 BasepUnicodeStringToOemSize(IN PUNICODE_STRING String
)
37 return RtlUnicodeStringToOemSize(String
);
42 BasepOemStringToUnicodeSize(IN PANSI_STRING String
)
44 return RtlOemStringToUnicodeSize(String
);
49 BasepUnicodeStringToAnsiSize(IN PUNICODE_STRING String
)
51 return RtlUnicodeStringToAnsiSize(String
);
56 BasepAnsiStringToUnicodeSize(IN PANSI_STRING String
)
58 return RtlAnsiStringToUnicodeSize(String
);
63 BaseGetNamedObjectDirectory(VOID
)
65 OBJECT_ATTRIBUTES ObjectAttributes
;
67 HANDLE DirHandle
, BnoHandle
, Token
, NewToken
;
69 if (BaseNamedObjectDirectory
) return BaseNamedObjectDirectory
;
71 if (NtCurrentTeb()->IsImpersonating
)
73 Status
= NtOpenThreadToken(NtCurrentThread(),
77 if (!NT_SUCCESS(Status
)) return BaseNamedObjectDirectory
;
80 Status
= NtSetInformationThread(NtCurrentThread(),
81 ThreadImpersonationToken
,
84 if (!NT_SUCCESS (Status
))
87 return BaseNamedObjectDirectory
;
96 if (BaseNamedObjectDirectory
) goto Quickie
;
98 InitializeObjectAttributes(&ObjectAttributes
,
99 &BaseStaticServerData
->NamedObjectDirectory
,
100 OBJ_CASE_INSENSITIVE
,
104 Status
= NtOpenDirectoryObject(&BnoHandle
,
107 DIRECTORY_CREATE_OBJECT
|
108 DIRECTORY_CREATE_SUBDIRECTORY
,
110 if (!NT_SUCCESS(Status
))
112 Status
= NtOpenDirectoryObject(&DirHandle
,
116 if (NT_SUCCESS(Status
))
118 InitializeObjectAttributes(&ObjectAttributes
,
119 (PUNICODE_STRING
)&Restricted
,
120 OBJ_CASE_INSENSITIVE
,
124 Status
= NtOpenDirectoryObject(&BnoHandle
,
127 DIRECTORY_CREATE_OBJECT
|
128 DIRECTORY_CREATE_SUBDIRECTORY
,
135 if (NT_SUCCESS(Status
)) BaseNamedObjectDirectory
= BnoHandle
;
143 NtSetInformationThread(NtCurrentThread(),
144 ThreadImpersonationToken
,
151 return BaseNamedObjectDirectory
;
156 BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry
,
158 OUT BOOLEAN
*StopEnumeration
)
160 /* Make sure we get Entry, Context and valid StopEnumeration pointer */
163 ASSERT(StopEnumeration
);
165 /* If entry is already found - signal to stop */
166 if (BasepExeLdrEntry
)
168 *StopEnumeration
= TRUE
;
172 /* Otherwise keep enumerating until we find a match */
173 if (Entry
->DllBase
== Context
)
175 /* It matches, so remember the ldr entry */
176 BasepExeLdrEntry
= Entry
;
178 /* And stop enumeration */
179 *StopEnumeration
= TRUE
;
184 * Converts an ANSI or OEM String to the TEB StaticUnicodeString
188 Basep8BitStringToStaticUnicodeString(IN LPCSTR String
)
190 PUNICODE_STRING StaticString
= &(NtCurrentTeb()->StaticUnicodeString
);
191 ANSI_STRING AnsiString
;
194 /* Initialize an ANSI String */
195 Status
= RtlInitAnsiStringEx(&AnsiString
, String
);
196 if (!NT_SUCCESS(Status
))
198 Status
= STATUS_BUFFER_OVERFLOW
;
203 Status
= Basep8BitStringToUnicodeString(StaticString
, &AnsiString
, FALSE
);
206 if (NT_SUCCESS(Status
)) return StaticString
;
208 if (Status
== STATUS_BUFFER_OVERFLOW
)
210 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
214 BaseSetLastNTError(Status
);
221 * Allocates space from the Heap and converts an Unicode String into it
225 Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString
,
228 ANSI_STRING AnsiString
;
231 /* Initialize an ANSI String */
232 Status
= RtlInitAnsiStringEx(&AnsiString
, String
);
233 if (!NT_SUCCESS(Status
))
235 Status
= STATUS_BUFFER_OVERFLOW
;
240 Status
= Basep8BitStringToUnicodeString(UnicodeString
, &AnsiString
, TRUE
);
243 if (NT_SUCCESS(Status
)) return TRUE
;
245 if (Status
== STATUS_BUFFER_OVERFLOW
)
247 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
251 BaseSetLastNTError(Status
);
258 * Allocates space from the Heap and converts an Ansi String into it
260 /*NOTE: API IS A HACK */
263 BasepAnsiStringToHeapUnicodeString(IN LPCSTR AnsiString
,
264 OUT LPWSTR
* UnicodeString
)
266 ANSI_STRING AnsiTemp
;
267 UNICODE_STRING UnicodeTemp
;
269 DPRINT("BasepAnsiStringToHeapUnicodeString\n");
271 /* First create the ANSI_STRING */
272 RtlInitAnsiString(&AnsiTemp
, AnsiString
);
274 if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeTemp
,
278 *UnicodeString
= UnicodeTemp
.Buffer
;
282 *UnicodeString
= NULL
;
288 BaseFormatTimeOut(OUT PLARGE_INTEGER Timeout
,
289 IN DWORD dwMilliseconds
)
291 /* Check if this is an infinite wait, which means no timeout argument */
292 if (dwMilliseconds
== INFINITE
) return NULL
;
294 /* Otherwise, convert the time to NT Format */
295 Timeout
->QuadPart
= dwMilliseconds
* -10000LL;
300 * Converts lpSecurityAttributes + Object Name into ObjectAttributes.
304 BaseFormatObjectAttributes(OUT POBJECT_ATTRIBUTES ObjectAttributes
,
305 IN PSECURITY_ATTRIBUTES SecurityAttributes OPTIONAL
,
306 IN PUNICODE_STRING ObjectName
)
309 HANDLE RootDirectory
;
310 PVOID SecurityDescriptor
;
311 DPRINT("BaseFormatObjectAttributes. Security: %p, Name: %p\n",
312 SecurityAttributes
, ObjectName
);
314 /* Get the attributes if present */
315 if (SecurityAttributes
)
317 Attributes
= SecurityAttributes
->bInheritHandle
? OBJ_INHERIT
: 0;
318 SecurityDescriptor
= SecurityAttributes
->lpSecurityDescriptor
;
322 if (!ObjectName
) return NULL
;
324 SecurityDescriptor
= NULL
;
329 Attributes
|= OBJ_OPENIF
;
330 RootDirectory
= BaseGetNamedObjectDirectory();
334 RootDirectory
= NULL
;
337 /* Create the Object Attributes */
338 InitializeObjectAttributes(ObjectAttributes
,
343 DPRINT("Attributes: %lx, RootDirectory: %p, SecurityDescriptor: %p\n",
344 Attributes
, RootDirectory
, SecurityDescriptor
);
345 return ObjectAttributes
;
349 * Creates a stack for a thread or fiber
353 BaseCreateStack(HANDLE hProcess
,
356 PINITIAL_TEB InitialTeb
)
359 PIMAGE_NT_HEADERS Headers
;
362 ULONG PageSize
, Dummy
, AllocationGranularity
;
363 SIZE_T StackReserveHeader
, StackCommitHeader
, GuardPageSize
, GuaranteedStackCommit
;
364 DPRINT("BaseCreateStack (hProcess: %p, Max: %lx, Current: %lx)\n",
365 hProcess
, StackReserve
, StackCommit
);
368 PageSize
= BaseStaticServerData
->SysInfo
.PageSize
;
369 AllocationGranularity
= BaseStaticServerData
->SysInfo
.AllocationGranularity
;
371 /* Get the Image Headers */
372 Headers
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
);
373 if (!Headers
) return STATUS_INVALID_IMAGE_FORMAT
;
375 StackCommitHeader
= Headers
->OptionalHeader
.SizeOfStackCommit
;
376 StackReserveHeader
= Headers
->OptionalHeader
.SizeOfStackReserve
;
378 if (!StackReserve
) StackReserve
= StackReserveHeader
;
382 StackCommit
= StackCommitHeader
;
384 else if (StackCommit
>= StackReserve
)
386 StackReserve
= ROUND_UP(StackCommit
, 1024 * 1024);
389 StackCommit
= ROUND_UP(StackCommit
, PageSize
);
390 StackReserve
= ROUND_UP(StackReserve
, AllocationGranularity
);
392 GuaranteedStackCommit
= NtCurrentTeb()->GuaranteedStackBytes
;
393 if ((GuaranteedStackCommit
) && (StackCommit
< GuaranteedStackCommit
))
395 StackCommit
= GuaranteedStackCommit
;
398 if (StackCommit
>= StackReserve
)
400 StackReserve
= ROUND_UP(StackCommit
, 1024 * 1024);
403 StackCommit
= ROUND_UP(StackCommit
, PageSize
);
404 StackReserve
= ROUND_UP(StackReserve
, AllocationGranularity
);
406 /* Reserve memory for the stack */
408 Status
= NtAllocateVirtualMemory(hProcess
,
414 if (!NT_SUCCESS(Status
))
416 DPRINT1("Failure to reserve stack: %lx\n", Status
);
420 /* Now set up some basic Initial TEB Parameters */
421 InitialTeb
->AllocatedStackBase
= (PVOID
)Stack
;
422 InitialTeb
->StackBase
= (PVOID
)(Stack
+ StackReserve
);
423 InitialTeb
->PreviousStackBase
= NULL
;
424 InitialTeb
->PreviousStackLimit
= NULL
;
426 /* Update the Stack Position */
427 Stack
+= StackReserve
- StackCommit
;
429 /* Check if we will need a guard page */
430 if (StackReserve
> StackCommit
)
433 StackCommit
+= PageSize
;
441 /* Allocate memory for the stack */
442 Status
= NtAllocateVirtualMemory(hProcess
,
448 if (!NT_SUCCESS(Status
))
450 DPRINT1("Failure to allocate stack\n");
452 NtFreeVirtualMemory(hProcess
, (PVOID
*)&Stack
, &GuardPageSize
, MEM_RELEASE
);
456 /* Now set the current Stack Limit */
457 InitialTeb
->StackLimit
= (PVOID
)Stack
;
459 /* Create a guard page */
462 /* Set the guard page */
463 GuardPageSize
= PAGE_SIZE
;
464 Status
= NtProtectVirtualMemory(hProcess
,
467 PAGE_GUARD
| PAGE_READWRITE
,
469 if (!NT_SUCCESS(Status
))
471 DPRINT1("Failure to set guard page\n");
475 /* Update the Stack Limit keeping in mind the Guard Page */
476 InitialTeb
->StackLimit
= (PVOID
)((ULONG_PTR
)InitialTeb
->StackLimit
+
481 return STATUS_SUCCESS
;
486 BaseFreeThreadStack(IN HANDLE hProcess
,
487 IN PINITIAL_TEB InitialTeb
)
492 NtFreeVirtualMemory(hProcess
,
493 &InitialTeb
->AllocatedStackBase
,
499 * Creates the Initial Context for a Thread or Fiber
503 BaseInitializeContext(IN PCONTEXT Context
,
505 IN PVOID StartAddress
,
506 IN PVOID StackAddress
,
507 IN ULONG ContextType
)
511 DPRINT("BaseInitializeContext: %p\n", Context
);
513 /* Setup the Initial Win32 Thread Context */
514 Context
->Eax
= (ULONG
)StartAddress
;
515 Context
->Ebx
= (ULONG
)Parameter
;
516 Context
->Esp
= (ULONG
)StackAddress
;
517 /* The other registers are undefined */
519 /* Setup the Segments */
520 Context
->SegFs
= KGDT_R3_TEB
;
521 Context
->SegEs
= KGDT_R3_DATA
;
522 Context
->SegDs
= KGDT_R3_DATA
;
523 Context
->SegCs
= KGDT_R3_CODE
;
524 Context
->SegSs
= KGDT_R3_DATA
;
527 /* Set the Context Flags */
528 ContextFlags
= Context
->ContextFlags
;
529 Context
->ContextFlags
= CONTEXT_FULL
;
531 /* Give it some room for the Parameter */
532 Context
->Esp
-= sizeof(PVOID
);
535 Context
->EFlags
= 0x3000; /* IOPL 3 */
537 /* What kind of context is being created? */
538 if (ContextType
== 1)
541 Context
->Eip
= (ULONG
)BaseThreadStartupThunk
;
543 else if (ContextType
== 2)
545 /* This is a fiber: make space for the return address */
546 Context
->Esp
-= sizeof(PVOID
);
547 *((PVOID
*)Context
->Esp
) = BaseFiberStartup
;
549 /* Is FPU state required? */
550 Context
->ContextFlags
|= ContextFlags
;
551 if ((ContextFlags
& CONTEXT_FLOATING_POINT
) == CONTEXT_FLOATING_POINT
)
553 /* Set an initial state */
554 Context
->FloatSave
.ControlWord
= 0x27F;
555 Context
->FloatSave
.StatusWord
= 0;
556 Context
->FloatSave
.TagWord
= 0xFFFF;
557 Context
->FloatSave
.ErrorOffset
= 0;
558 Context
->FloatSave
.ErrorSelector
= 0;
559 Context
->FloatSave
.DataOffset
= 0;
560 Context
->FloatSave
.DataSelector
= 0;
561 if (SharedUserData
->ProcessorFeatures
[PF_XMMI_INSTRUCTIONS_AVAILABLE
])
562 Context
->Dr6
= 0x1F80;
567 /* For first thread in a Process */
568 Context
->Eip
= (ULONG
)BaseProcessStartThunk
;
571 #elif defined(_M_AMD64)
572 DPRINT("BaseInitializeContext: %p\n", Context
);
574 /* Setup the Initial Win32 Thread Context */
575 Context
->Rax
= (ULONG_PTR
)StartAddress
;
576 Context
->Rbx
= (ULONG_PTR
)Parameter
;
577 Context
->Rsp
= (ULONG_PTR
)StackAddress
;
578 /* The other registers are undefined */
580 /* Setup the Segments */
581 Context
->SegGs
= KGDT64_R3_DATA
| RPL_MASK
;
582 Context
->SegEs
= KGDT64_R3_DATA
| RPL_MASK
;
583 Context
->SegDs
= KGDT64_R3_DATA
| RPL_MASK
;
584 Context
->SegCs
= KGDT64_R3_CODE
| RPL_MASK
;
585 Context
->SegSs
= KGDT64_R3_DATA
| RPL_MASK
;
586 Context
->SegFs
= KGDT64_R3_CMTEB
| RPL_MASK
;
589 Context
->EFlags
= 0x3000; /* IOPL 3 */
591 if (ContextType
== 1) /* For Threads */
593 Context
->Rip
= (ULONG_PTR
)BaseThreadStartupThunk
;
595 else if (ContextType
== 2) /* For Fibers */
597 Context
->Rip
= (ULONG_PTR
)BaseFiberStartup
;
599 else /* For first thread in a Process */
601 Context
->Rip
= (ULONG_PTR
)BaseProcessStartThunk
;
604 /* Set the Context Flags */
605 Context
->ContextFlags
= CONTEXT_FULL
;
607 /* Give it some room for the Parameter */
608 Context
->Rsp
-= sizeof(PVOID
);
609 #elif defined(_M_ARM)
610 DPRINT("BaseInitializeContext: %p\n", Context
);
612 // FIXME: check if this is correct!
613 /* Setup the Initial Win32 Thread Context */
614 Context
->R0
= (ULONG_PTR
)StartAddress
;
615 Context
->R1
= (ULONG_PTR
)Parameter
;
616 Context
->Sp
= (ULONG_PTR
)StackAddress
;
618 if (ContextType
== 1) /* For Threads */
620 Context
->Pc
= (ULONG_PTR
)BaseThreadStartupThunk
;
622 else if (ContextType
== 2) /* For Fibers */
624 Context
->Pc
= (ULONG_PTR
)BaseFiberStartup
;
626 else /* For first thread in a Process */
628 Context
->Pc
= (ULONG_PTR
)BaseProcessStartThunk
;
631 /* Set the Context Flags */
632 Context
->ContextFlags
= CONTEXT_FULL
;
634 /* Give it some room for the Parameter */
635 Context
->Sp
-= sizeof(PVOID
);
637 #warning Unknown architecture
644 * Checks if the privilege for Real-Time Priority is there
645 * Beware about this function behavior:
646 * - In case Keep is set to FALSE, then the function will only check
647 * whether real time is allowed and won't grant the privilege. In that case
648 * it will return TRUE if allowed, FALSE otherwise. Not a state!
649 * It means you don't have to release privilege when calling with FALSE.
653 BasepIsRealtimeAllowed(IN BOOLEAN Keep
)
655 ULONG Privilege
= SE_INC_BASE_PRIORITY_PRIVILEGE
;
659 Status
= RtlAcquirePrivilege(&Privilege
, 1, 0, &State
);
660 if (!NT_SUCCESS(Status
)) return NULL
;
664 RtlReleasePrivilege(State
);
672 * Maps an image file into a section
676 BasepMapFile(IN LPCWSTR lpApplicationName
,
677 OUT PHANDLE hSection
,
678 IN PUNICODE_STRING ApplicationName
)
680 RTL_RELATIVE_NAME_U RelativeName
;
681 OBJECT_ATTRIBUTES ObjectAttributes
;
684 IO_STATUS_BLOCK IoStatusBlock
;
686 DPRINT("BasepMapFile\n");
688 /* Zero out the Relative Directory */
689 RelativeName
.ContainingDirectory
= NULL
;
691 /* Find the application name */
692 if (!RtlDosPathNameToNtPathName_U(lpApplicationName
,
697 return STATUS_OBJECT_PATH_NOT_FOUND
;
700 DPRINT("ApplicationName %wZ\n", ApplicationName
);
701 DPRINT("RelativeName %wZ\n", &RelativeName
.RelativeName
);
703 /* Did we get a relative name? */
704 if (RelativeName
.RelativeName
.Length
)
706 ApplicationName
= &RelativeName
.RelativeName
;
709 /* Initialize the Object Attributes */
710 InitializeObjectAttributes(&ObjectAttributes
,
712 OBJ_CASE_INSENSITIVE
,
713 RelativeName
.ContainingDirectory
,
716 /* Try to open the executable */
717 Status
= NtOpenFile(&hFile
,
718 SYNCHRONIZE
| FILE_EXECUTE
| FILE_READ_DATA
,
721 FILE_SHARE_DELETE
| FILE_SHARE_READ
,
722 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
723 if (!NT_SUCCESS(Status
))
725 DPRINT1("Failed to open file\n");
726 BaseSetLastNTError(Status
);
730 /* Create a section for this file */
731 Status
= NtCreateSection(hSection
,
741 DPRINT("Section: %p for file: %p\n", *hSection
, hFile
);
750 Wow64EnableWow64FsRedirection(IN BOOLEAN Wow64EnableWow64FsRedirection
)
755 Status
= RtlWow64EnableFsRedirection(Wow64EnableWow64FsRedirection
);
756 if (NT_SUCCESS(Status
))
762 BaseSetLastNTError(Status
);
773 Wow64DisableWow64FsRedirection(IN PVOID
*OldValue
)
778 Status
= RtlWow64EnableFsRedirectionEx((PVOID
)TRUE
, OldValue
);
779 if (NT_SUCCESS(Status
))
785 BaseSetLastNTError(Status
);
796 Wow64RevertWow64FsRedirection(IN PVOID OldValue
)
801 Status
= RtlWow64EnableFsRedirectionEx(OldValue
, &OldValue
);
802 if (NT_SUCCESS(Status
))
808 BaseSetLastNTError(Status
);
819 SetFileApisToOEM(VOID
)
821 /* Set the correct Base Api */
822 Basep8BitStringToUnicodeString
= (PRTL_CONVERT_STRING
)RtlOemStringToUnicodeString
;
823 BasepUnicodeStringTo8BitString
= RtlUnicodeStringToOemString
;
824 BasepUnicodeStringTo8BitSize
= BasepUnicodeStringToOemSize
;
825 Basep8BitStringToUnicodeSize
= BasepOemStringToUnicodeSize
;
827 /* FIXME: Old, deprecated way */
828 bIsFileApiAnsi
= FALSE
;
837 SetFileApisToANSI(VOID
)
839 /* Set the correct Base Api */
840 Basep8BitStringToUnicodeString
= RtlAnsiStringToUnicodeString
;
841 BasepUnicodeStringTo8BitString
= RtlUnicodeStringToAnsiString
;
842 BasepUnicodeStringTo8BitSize
= BasepUnicodeStringToAnsiSize
;
843 Basep8BitStringToUnicodeSize
= BasepAnsiStringToUnicodeSize
;
845 /* FIXME: Old, deprecated way */
846 bIsFileApiAnsi
= TRUE
;
854 AreFileApisANSI(VOID
)
856 return Basep8BitStringToUnicodeString
== RtlAnsiStringToUnicodeString
;
864 BaseMarkFileForDelete(IN HANDLE FileHandle
,
865 IN ULONG FileAttributes
)
867 IO_STATUS_BLOCK IoStatusBlock
;
868 FILE_BASIC_INFORMATION FileBasicInfo
;
869 FILE_DISPOSITION_INFORMATION FileDispositionInfo
;
871 /* If no attributes were given, get them */
874 FileBasicInfo
.FileAttributes
= 0;
875 NtQueryInformationFile(FileHandle
,
878 sizeof(FileBasicInfo
),
879 FileBasicInformation
);
880 FileAttributes
= FileBasicInfo
.FileAttributes
;
883 /* If file is marked as RO, reset its attributes */
884 if (FileAttributes
& FILE_ATTRIBUTE_READONLY
)
886 RtlZeroMemory(&FileBasicInfo
, sizeof(FileBasicInfo
));
887 FileBasicInfo
.FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
888 NtSetInformationFile(FileHandle
,
891 sizeof(FileBasicInfo
),
892 FileBasicInformation
);
895 /* Finally, mark the file for deletion */
896 FileDispositionInfo
.DeleteFile
= TRUE
;
897 NtSetInformationFile(FileHandle
,
899 &FileDispositionInfo
,
900 sizeof(FileDispositionInfo
),
901 FileDispositionInformation
);
909 BasepCheckWinSaferRestrictions(IN HANDLE UserToken
,
910 IN LPWSTR ApplicationName
,
911 IN HANDLE FileHandle
,
913 OUT PHANDLE NewToken
,
914 OUT PHANDLE JobHandle
)
918 /* Validate that there's a name */
919 if ((ApplicationName
) && *(ApplicationName
))
921 /* Validate that the required output parameters are there */
922 if ((InJob
) && (NewToken
) && (JobHandle
))
924 /* Do the work (one day...) */
925 DPRINT("BasepCheckWinSaferRestrictions is UNIMPLEMENTED\n");
926 Status
= STATUS_SUCCESS
;
930 /* Act as if SEH hit this */
931 Status
= STATUS_ACCESS_VIOLATION
;
936 /* Input is invalid */
937 Status
= STATUS_INVALID_PARAMETER
;
940 /* Return the status */