Author: tkreuzer
Date: Wed Jan 22 16:29:26 2014
New Revision: 61753
URL:
http://svn.reactos.org/svn/reactos?rev=61753&view=rev
Log:
[NTOSKRNL]
- Implement NtPrivilegedServiceAuditAlarm, the internal function
SepAdtPrivilegedServiceAuditAlarm is not implemented yet.
- Stubplement SepAccessCheckAndAuditAlarm and make NtAccessCheckAndAuditAlarm,
NtAccessCheckByTypeAndAuditAlarm, NtAccessCheckByTypeResultListAndAuditAlarm and
NtAccessCheckByTypeResultListAndAuditAlarmByHandle (love that name) wrappers around it.
Modified:
trunk/reactos/ntoskrnl/se/audit.c
trunk/reactos/ntoskrnl/se/semgr.c
Modified: trunk/reactos/ntoskrnl/se/audit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/audit.c?rev=61…
==============================================================================
--- trunk/reactos/ntoskrnl/se/audit.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/se/audit.c [iso-8859-1] Wed Jan 22 16:29:26 2014
@@ -5,6 +5,7 @@
* PURPOSE: Audit functions
*
* PROGRAMMERS: Eric Kohl
+ * Timo Kreuzer (timo.kreuzer(a)reactos.org)
*/
/* INCLUDES *******************************************************************/
@@ -12,6 +13,8 @@
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
+
+#define SEP_PRIVILEGE_SET_MAX_COUNT 60
/* PRIVATE FUNCTIONS***********************************************************/
@@ -180,6 +183,145 @@
return Status;
}
+VOID
+NTAPI
+SepAdtCloseObjectAuditAlarm(
+ PUNICODE_STRING SubsystemName,
+ PVOID HandleId,
+ PSID Sid)
+{
+ UNIMPLEMENTED;
+}
+
+VOID
+NTAPI
+SepAdtPrivilegedServiceAuditAlarm(
+ PSECURITY_SUBJECT_CONTEXT SubjectContext,
+ _In_opt_ PUNICODE_STRING SubsystemName,
+ _In_opt_ PUNICODE_STRING ServiceName,
+ _In_ PTOKEN Token,
+ _In_ PTOKEN PrimaryToken,
+ _In_ PPRIVILEGE_SET Privileges,
+ _In_ BOOLEAN AccessGranted )
+{
+ UNIMPLEMENTED;
+}
+
+_Must_inspect_result_
+NTSTATUS
+NTAPI
+SepAccessCheckAndAuditAlarm(
+ _In_ PUNICODE_STRING SubsystemName,
+ _In_opt_ PVOID HandleId,
+ _In_ PHANDLE ClientToken,
+ _In_ PUNICODE_STRING ObjectTypeName,
+ _In_ PUNICODE_STRING ObjectName,
+ _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ _In_opt_ PSID PrincipalSelfSid,
+ _In_ ACCESS_MASK DesiredAccess,
+ _In_ AUDIT_EVENT_TYPE AuditType,
+ _In_ ULONG Flags,
+ _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
+ _In_ ULONG ObjectTypeListLength,
+ _In_ PGENERIC_MAPPING GenericMapping,
+ _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
+ _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
+ _Out_ PBOOLEAN GenerateOnClose,
+ _In_ BOOLEAN UseResultList)
+{
+ SECURITY_SUBJECT_CONTEXT SubjectContext;
+ ULONG ResultListLength;
+ GENERIC_MAPPING LocalGenericMapping;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ DBG_UNREFERENCED_LOCAL_VARIABLE(LocalGenericMapping);
+
+ /* Only user mode is supported! */
+ ASSERT(ExGetPreviousMode() != KernelMode);
+
+ /* Validate AuditType */
+ if ((AuditType != AuditEventObjectAccess) &&
+ (AuditType != AuditEventDirectoryServiceAccess))
+ {
+ DPRINT1("Invalid audit type: %u\n", AuditType);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Capture the security subject context */
+ SeCaptureSubjectContext(&SubjectContext);
+
+ /* Did the caller pass a token handle? */
+ if (ClientToken == NULL)
+ {
+ /* Check if we have a token in the subject context */
+ if (SubjectContext.ClientToken == NULL)
+ {
+ Status = STATUS_NO_IMPERSONATION_TOKEN;
+ goto Cleanup;
+ }
+
+ /* Check if we have a valid impersonation level */
+ if (SubjectContext.ImpersonationLevel < SecurityIdentification)
+ {
+ Status = STATUS_BAD_IMPERSONATION_LEVEL;
+ goto Cleanup;
+ }
+ }
+
+ /* Are we using a result list? */
+ if (UseResultList)
+ {
+ /* The list length equals the object type list length */
+ ResultListLength = ObjectTypeListLength;
+ if ((ResultListLength == 0) || (ResultListLength > 0x1000))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+ }
+ else
+ {
+ /* List length is 1 */
+ ResultListLength = 1;
+ }
+
+ _SEH2_TRY
+ {
+ /* Probe output buffers */
+ ProbeForWrite(AccessStatusList,
+ ResultListLength * sizeof(*AccessStatusList),
+ sizeof(*AccessStatusList));
+ ProbeForWrite(GrantedAccessList,
+ ResultListLength * sizeof(*GrantedAccessList),
+ sizeof(*GrantedAccessList));
+
+ /* Probe generic mapping and make a local copy */
+ ProbeForRead(GenericMapping, sizeof(*GenericMapping), sizeof(ULONG));
+ LocalGenericMapping = * GenericMapping;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ goto Cleanup;
+ }
+ _SEH2_END;
+
+
+ UNIMPLEMENTED;
+
+ /* For now pretend everything else is ok */
+ Status = STATUS_SUCCESS;
+
+Cleanup:
+
+ /* Release the security subject context */
+ SeReleaseSubjectContext(&SubjectContext);
+
+ return Status;
+}
+
+
/* PUBLIC FUNCTIONS ***********************************************************/
/*
@@ -336,36 +478,7 @@
UNIMPLEMENTED;
}
-VOID
-NTAPI
-SepAdtCloseObjectAuditAlarm(
- PUNICODE_STRING SubsystemName,
- PVOID HandleId,
- PSID Sid)
-{
- UNIMPLEMENTED;
-}
-
/* SYSTEM CALLS ***************************************************************/
-
-NTSTATUS
-NTAPI
-NtAccessCheckAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN HANDLE HandleId,
- IN PUNICODE_STRING ObjectTypeName,
- IN PUNICODE_STRING ObjectName,
- IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN ACCESS_MASK DesiredAccess,
- IN PGENERIC_MAPPING GenericMapping,
- IN BOOLEAN ObjectCreation,
- OUT PACCESS_MASK GrantedAccess,
- OUT PNTSTATUS AccessStatus,
- OUT PBOOLEAN GenerateOnClose)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
NTSTATUS
NTAPI
@@ -483,15 +596,157 @@
}
-NTSTATUS NTAPI
-NtPrivilegedServiceAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN PUNICODE_STRING ServiceName,
- IN HANDLE ClientToken,
- IN PPRIVILEGE_SET Privileges,
- IN BOOLEAN AccessGranted)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+__kernel_entry
+NTSTATUS
+NTAPI
+NtPrivilegedServiceAuditAlarm(
+ _In_opt_ PUNICODE_STRING SubsystemName,
+ _In_opt_ PUNICODE_STRING ServiceName,
+ _In_ HANDLE ClientToken,
+ _In_ PPRIVILEGE_SET Privileges,
+ _In_ BOOLEAN AccessGranted )
+{
+ KPROCESSOR_MODE PreviousMode;
+ PTOKEN Token;
+ volatile PPRIVILEGE_SET CapturedPrivileges = NULL;
+ UNICODE_STRING CapturedSubsystemName;
+ UNICODE_STRING CapturedServiceName;
+ ULONG PrivilegeCount, PrivilegesSize;
+ SECURITY_SUBJECT_CONTEXT SubjectContext;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ /* Get the previous mode (only user mode is supported!) */
+ PreviousMode = ExGetPreviousMode();
+ ASSERT(PreviousMode != KernelMode);
+
+ /* Reference the client token */
+ Status = ObReferenceObjectByHandle(ClientToken,
+ TOKEN_QUERY,
+ SeTokenObjectType,
+ PreviousMode,
+ (PVOID*)&Token,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to reference client token: 0x%lx\n", Status);
+ return Status;
+ }
+
+ /* Validate the token's impersonation level */
+ if ((Token->TokenType == TokenImpersonation) &&
+ (Token->ImpersonationLevel < SecurityIdentification))
+ {
+ DPRINT1("Invalid impersonation level (%u)\n",
Token->ImpersonationLevel);
+ ObfDereferenceObject(Token);
+ return STATUS_BAD_IMPERSONATION_LEVEL;
+ }
+
+ /* Validate privilege */
+ if (!SeSinglePrivilegeCheck(SeAuditPrivilege, PreviousMode))
+ {
+ DPRINT1("Caller does not have SeAuditPrivilege\n");
+ ObfDereferenceObject(Token);
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+
+ /* Do we have a subsystem name? */
+ if (SubsystemName != NULL)
+ {
+ /* Probe and capture the subsystem name */
+ Status = ProbeAndCaptureUnicodeString(&CapturedSubsystemName,
+ PreviousMode,
+ SubsystemName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to capture subsystem name!\n");
+ goto Cleanup;
+ }
+ }
+
+ /* Do we have a service name? */
+ if (ServiceName != NULL)
+ {
+ /* Probe and capture the service name */
+ Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
+ PreviousMode,
+ ServiceName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to capture service name!\n");
+ goto Cleanup;
+ }
+ }
+
+ _SEH2_TRY
+ {
+ /* Probe the basic privilege set structure */
+ ProbeForRead(Privileges, sizeof(PRIVILEGE_SET), sizeof(ULONG));
+
+ /* Validate privilege count */
+ PrivilegeCount = Privileges->PrivilegeCount;
+ if (PrivilegeCount > SEP_PRIVILEGE_SET_MAX_COUNT)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ /* Calculate the size of the Privileges structure */
+ PrivilegesSize = FIELD_OFFSET(PRIVILEGE_SET, Privilege[PrivilegeCount]);
+
+ /* Probe the whole structure */
+ ProbeForRead(Privileges, PrivilegesSize, sizeof(ULONG));
+
+ /* Allocate a temp buffer */
+ CapturedPrivileges = ExAllocatePoolWithTag(PagedPool,
+ PrivilegesSize,
+ 'rPeS');
+ if (CapturedPrivileges == NULL)
+ {
+ DPRINT1("Failed to allocate %u bytes\n", PrivilegesSize);
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Cleanup;
+ }
+
+ /* Copy the privileges */
+ RtlCopyMemory(CapturedPrivileges, Privileges, PrivilegesSize);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ DPRINT1("Got exception 0x%lx\n", Status);
+ goto Cleanup;
+ }
+ _SEH2_END;
+
+ /* Capture the security subject context */
+ SeCaptureSubjectContext(&SubjectContext);
+
+ /* Call the internal function */
+ SepAdtPrivilegedServiceAuditAlarm(&SubjectContext,
+ &CapturedSubsystemName,
+ &CapturedServiceName,
+ Token,
+ SubjectContext.PrimaryToken,
+ CapturedPrivileges,
+ AccessGranted);
+
+ /* Release the security subject context */
+ SeReleaseSubjectContext(&SubjectContext);
+
+ Status = STATUS_SUCCESS;
+
+Cleanup:
+ /* Cleanup resources */
+ if (SubsystemName != NULL)
+ ReleaseCapturedUnicodeString(&CapturedSubsystemName, PreviousMode);
+ if (ServiceName != NULL)
+ ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
+ if (CapturedPrivileges != NULL)
+ ExFreePoolWithTag(CapturedPrivileges, 0);
+ ObDereferenceObject(Token);
+
+ return Status;
}
@@ -507,4 +762,171 @@
return STATUS_NOT_IMPLEMENTED;
}
+
+_Must_inspect_result_
+__kernel_entry
+NTSTATUS
+NTAPI
+NtAccessCheckAndAuditAlarm(
+ _In_ PUNICODE_STRING SubsystemName,
+ _In_opt_ PVOID HandleId,
+ _In_ PUNICODE_STRING ObjectTypeName,
+ _In_ PUNICODE_STRING ObjectName,
+ _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ _In_ ACCESS_MASK DesiredAccess,
+ _In_ PGENERIC_MAPPING GenericMapping,
+ _In_ BOOLEAN ObjectCreation,
+ _Out_ PACCESS_MASK GrantedAccess,
+ _Out_ PNTSTATUS AccessStatus,
+ _Out_ PBOOLEAN GenerateOnClose)
+{
+ /* Call the internal function */
+ return SepAccessCheckAndAuditAlarm(SubsystemName,
+ HandleId,
+ NULL,
+ ObjectTypeName,
+ ObjectName,
+ SecurityDescriptor,
+ NULL,
+ DesiredAccess,
+ AuditEventObjectAccess,
+ 0,
+ NULL,
+ 0,
+ GenericMapping,
+ GrantedAccess,
+ AccessStatus,
+ GenerateOnClose,
+ FALSE);
+}
+
+_Must_inspect_result_
+__kernel_entry
+NTSTATUS
+NTAPI
+NtAccessCheckByTypeAndAuditAlarm(
+ _In_ PUNICODE_STRING SubsystemName,
+ _In_opt_ PVOID HandleId,
+ _In_ PUNICODE_STRING ObjectTypeName,
+ _In_ PUNICODE_STRING ObjectName,
+ _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ _In_opt_ PSID PrincipalSelfSid,
+ _In_ ACCESS_MASK DesiredAccess,
+ _In_ AUDIT_EVENT_TYPE AuditType,
+ _In_ ULONG Flags,
+ _In_reads_opt_(ObjectTypeLength) POBJECT_TYPE_LIST ObjectTypeList,
+ _In_ ULONG ObjectTypeLength,
+ _In_ PGENERIC_MAPPING GenericMapping,
+ _In_ BOOLEAN ObjectCreation,
+ _Out_ PACCESS_MASK GrantedAccess,
+ _Out_ PNTSTATUS AccessStatus,
+ _Out_ PBOOLEAN GenerateOnClose)
+{
+ /* Call the internal function */
+ return SepAccessCheckAndAuditAlarm(SubsystemName,
+ HandleId,
+ NULL,
+ ObjectTypeName,
+ ObjectName,
+ SecurityDescriptor,
+ PrincipalSelfSid,
+ DesiredAccess,
+ AuditType,
+ Flags,
+ ObjectTypeList,
+ ObjectTypeLength,
+ GenericMapping,
+ GrantedAccess,
+ AccessStatus,
+ GenerateOnClose,
+ FALSE);
+}
+
+_Must_inspect_result_
+__kernel_entry
+NTSTATUS
+NTAPI
+NtAccessCheckByTypeResultListAndAuditAlarm(
+ _In_ PUNICODE_STRING SubsystemName,
+ _In_opt_ PVOID HandleId,
+ _In_ PUNICODE_STRING ObjectTypeName,
+ _In_ PUNICODE_STRING ObjectName,
+ _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ _In_opt_ PSID PrincipalSelfSid,
+ _In_ ACCESS_MASK DesiredAccess,
+ _In_ AUDIT_EVENT_TYPE AuditType,
+ _In_ ULONG Flags,
+ _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
+ _In_ ULONG ObjectTypeListLength,
+ _In_ PGENERIC_MAPPING GenericMapping,
+ _In_ BOOLEAN ObjectCreation,
+ _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
+ _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
+ _Out_ PBOOLEAN GenerateOnClose)
+{
+ /* Call the internal function */
+ return SepAccessCheckAndAuditAlarm(SubsystemName,
+ HandleId,
+ NULL,
+ ObjectTypeName,
+ ObjectName,
+ SecurityDescriptor,
+ PrincipalSelfSid,
+ DesiredAccess,
+ AuditType,
+ Flags,
+ ObjectTypeList,
+ ObjectTypeListLength,
+ GenericMapping,
+ GrantedAccessList,
+ AccessStatusList,
+ GenerateOnClose,
+ TRUE);
+}
+
+_Must_inspect_result_
+__kernel_entry
+NTSTATUS
+NTAPI
+NtAccessCheckByTypeResultListAndAuditAlarmByHandle(
+ _In_ PUNICODE_STRING SubsystemName,
+ _In_opt_ PVOID HandleId,
+ _In_ HANDLE ClientToken,
+ _In_ PUNICODE_STRING ObjectTypeName,
+ _In_ PUNICODE_STRING ObjectName,
+ _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ _In_opt_ PSID PrincipalSelfSid,
+ _In_ ACCESS_MASK DesiredAccess,
+ _In_ AUDIT_EVENT_TYPE AuditType,
+ _In_ ULONG Flags,
+ _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
+ _In_ ULONG ObjectTypeListLength,
+ _In_ PGENERIC_MAPPING GenericMapping,
+ _In_ BOOLEAN ObjectCreation,
+ _Out_writes_(ObjectTypeListLength) PACCESS_MASK GrantedAccessList,
+ _Out_writes_(ObjectTypeListLength) PNTSTATUS AccessStatusList,
+ _Out_ PBOOLEAN GenerateOnClose)
+{
+ UNREFERENCED_PARAMETER(ObjectCreation);
+
+ /* Call the internal function */
+ return SepAccessCheckAndAuditAlarm(SubsystemName,
+ HandleId,
+ &ClientToken,
+ ObjectTypeName,
+ ObjectName,
+ SecurityDescriptor,
+ PrincipalSelfSid,
+ DesiredAccess,
+ AuditType,
+ Flags,
+ ObjectTypeList,
+ ObjectTypeListLength,
+ GenericMapping,
+ GrantedAccessList,
+ AccessStatusList,
+ GenerateOnClose,
+ TRUE);
+}
+
/* EOF */
Modified: trunk/reactos/ntoskrnl/se/semgr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/semgr.c?rev=61…
==============================================================================
--- trunk/reactos/ntoskrnl/se/semgr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/se/semgr.c [iso-8859-1] Wed Jan 22 16:29:26 2014
@@ -617,7 +617,7 @@
*GrantedAccess = CurrentAccess & DesiredAccess;
- if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) ==
+ if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) ==
(DesiredAccess & ~VALID_INHERIT_FLAGS))
{
*AccessStatus = STATUS_SUCCESS;
@@ -1074,29 +1074,6 @@
NTSTATUS
NTAPI
-NtAccessCheckByTypeAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN HANDLE HandleId,
- IN PUNICODE_STRING ObjectTypeName,
- IN PUNICODE_STRING ObjectName,
- IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN PSID PrincipalSelfSid,
- IN ACCESS_MASK DesiredAccess,
- IN AUDIT_EVENT_TYPE AuditType,
- IN ULONG Flags,
- IN POBJECT_TYPE_LIST ObjectTypeList,
- IN ULONG ObjectTypeLength,
- IN PGENERIC_MAPPING GenericMapping,
- IN BOOLEAN ObjectCreation,
- OUT PACCESS_MASK GrantedAccess,
- OUT PNTSTATUS AccessStatus,
- OUT PBOOLEAN GenerateOnClose)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-NTAPI
NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN PSID PrincipalSelfSid,
IN HANDLE ClientToken,
@@ -1113,51 +1090,4 @@
return STATUS_NOT_IMPLEMENTED;
}
-NTSTATUS
-NTAPI
-NtAccessCheckByTypeResultListAndAuditAlarm(IN PUNICODE_STRING SubsystemName,
- IN HANDLE HandleId,
- IN PUNICODE_STRING ObjectTypeName,
- IN PUNICODE_STRING ObjectName,
- IN PSECURITY_DESCRIPTOR SecurityDescriptor,
- IN PSID PrincipalSelfSid,
- IN ACCESS_MASK DesiredAccess,
- IN AUDIT_EVENT_TYPE AuditType,
- IN ULONG Flags,
- IN POBJECT_TYPE_LIST ObjectTypeList,
- IN ULONG ObjectTypeLength,
- IN PGENERIC_MAPPING GenericMapping,
- IN BOOLEAN ObjectCreation,
- OUT PACCESS_MASK GrantedAccess,
- OUT PNTSTATUS AccessStatus,
- OUT PBOOLEAN GenerateOnClose)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-NTAPI
-NtAccessCheckByTypeResultListAndAuditAlarmByHandle(IN PUNICODE_STRING SubsystemName,
- IN HANDLE HandleId,
- IN HANDLE ClientToken,
- IN PUNICODE_STRING ObjectTypeName,
- IN PUNICODE_STRING ObjectName,
- IN PSECURITY_DESCRIPTOR
SecurityDescriptor,
- IN PSID PrincipalSelfSid,
- IN ACCESS_MASK DesiredAccess,
- IN AUDIT_EVENT_TYPE AuditType,
- IN ULONG Flags,
- IN POBJECT_TYPE_LIST ObjectTypeList,
- IN ULONG ObjectTypeLength,
- IN PGENERIC_MAPPING GenericMapping,
- IN BOOLEAN ObjectCreation,
- OUT PACCESS_MASK GrantedAccess,
- OUT PNTSTATUS AccessStatus,
- OUT PBOOLEAN GenerateOnClose)
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
/* EOF */