fixed typo in a comment
[reactos.git] / reactos / lib / advapi32 / sec / misc.c
index 270237f..0af5fca 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: misc.c,v 1.31 2004/12/14 06:40:50 royce Exp $
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/advapi32/sec/misc.c
 #define NDEBUG
 #include <debug.h>
 
+/* Interface to ntmarta.dll ***************************************************/
+
+NTMARTA NtMartaStatic = { 0 };
+static PNTMARTA NtMarta = NULL;
+
+#define FindNtMartaProc(Name)                                                  \
+    NtMartaStatic.Name = (PVOID)GetProcAddress(NtMartaStatic.hDllInstance,     \
+                                               "Acc" # Name );                 \
+    if (NtMartaStatic.Name == NULL)                                            \
+    {                                                                          \
+        return GetLastError();                                                 \
+    }
+
+static DWORD
+LoadAndInitializeNtMarta(VOID)
+{
+    /* this code may be executed simultaneously by multiple threads in case they're
+       trying to initialize the interface at the same time, but that's no problem
+       because the pointers returned by GetProcAddress will be the same. However,
+       only one of the threads will change the NtMarta pointer to the NtMartaStatic
+       structure, the others threads will detect that there were other threads
+       initializing the structure faster and will release the reference to the
+       DLL */
+
+    NtMartaStatic.hDllInstance = LoadLibraryW(L"ntmarta.dll");
+    if (NtMartaStatic.hDllInstance == NULL)
+    {
+        return GetLastError();
+    }
+
+#if 0
+    FindNtMartaProc(LookupAccountTrustee);
+    FindNtMartaProc(LookupAccountName);
+    FindNtMartaProc(LookupAccountSid);
+    FindNtMartaProc(SetEntriesInAList);
+    FindNtMartaProc(ConvertAccessToSecurityDescriptor);
+    FindNtMartaProc(ConvertSDToAccess);
+    FindNtMartaProc(ConvertAclToAccess);
+    FindNtMartaProc(GetAccessForTrustee);
+    FindNtMartaProc(GetExplicitEntries);
+#endif
+    FindNtMartaProc(RewriteGetNamedRights);
+    FindNtMartaProc(RewriteSetNamedRights);
+    FindNtMartaProc(RewriteGetHandleRights);
+    FindNtMartaProc(RewriteSetHandleRights);
+    FindNtMartaProc(RewriteSetEntriesInAcl);
+    FindNtMartaProc(RewriteGetExplicitEntriesFromAcl);
+    FindNtMartaProc(TreeResetNamedSecurityInfo);
+    FindNtMartaProc(GetInheritanceSource);
+    FindNtMartaProc(FreeIndexArray);
+    
+    return ERROR_SUCCESS;
+}
+
+DWORD
+CheckNtMartaPresent(VOID)
+{
+    DWORD ErrorCode;
+    
+    if (NtMarta == NULL)
+    {
+        /* we're the first one trying to use ntmarta, initialize it and change
+           the pointer after initialization */
+        ErrorCode = LoadAndInitializeNtMarta();
+        
+        if (ErrorCode == ERROR_SUCCESS)
+        {
+            /* try change the NtMarta pointer */
+            if (InterlockedCompareExchangePointer(&NtMarta,
+                                                  &NtMartaStatic,
+                                                  NULL) != NULL)
+            {
+                /* another thread initialized ntmarta in the meanwhile, release
+                   the reference of the dll loaded. */
+                FreeLibrary(NtMartaStatic.hDllInstance);
+            }
+        }
+#if DBG
+        else
+        {
+            DPRINT1("Failed to initialize ntmarta.dll! Error: 0x%x", ErrorCode);
+        }
+#endif
+    }
+    else
+    {
+        /* ntmarta was already initialized */
+        ErrorCode = ERROR_SUCCESS;
+    }
+    
+    return ErrorCode;
+}
+
+VOID UnloadNtMarta(VOID)
+{
+    if (InterlockedExchangePointer(&NtMarta,
+                                   NULL) != NULL)
+    {
+        FreeLibrary(NtMartaStatic.hDllInstance);
+    }
+}
+
+/******************************************************************************/
 
 /*
  * @implemented
@@ -53,7 +155,7 @@ AreAnyAccessesGranted(DWORD GrantedAccess,
  *
  * RETURNS
  *  Success: TRUE. pSecurityDescriptor contains the requested information.
- *  Failure: FALSE. lpnLengthNeeded contains the required space to return the info. 
+ *  Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
  *
  * NOTES
  *  The information returned is constrained by the callers access rights and
@@ -335,18 +437,6 @@ SetKernelObjectSecurity(HANDLE Handle,
 }
 
 
-/*
- * @implemented
- */
-VOID STDCALL
-MapGenericMask(PDWORD AccessMask,
-              PGENERIC_MAPPING GenericMapping)
-{
-  RtlMapGenericMask(AccessMask,
-                   GenericMapping);
-}
-
-
 /*
  * @implemented
  */
@@ -485,36 +575,38 @@ RevertToSelf(VOID)
 BOOL WINAPI
 GetUserNameA( LPSTR lpszName, LPDWORD lpSize )
 {
-  WCHAR* lpszNameW = NULL;
-  DWORD len = 0;
-
-  if ( !lpSize )
-  {
-    SetLastError(ERROR_INVALID_PARAMETER);
-    return FALSE;
-  }
+  UNICODE_STRING NameW;
+  ANSI_STRING NameA;
+  BOOL Ret;
 
-  len = *lpSize;
-  lpszNameW = LocalAlloc ( LMEM_FIXED, len * sizeof(WCHAR) );
+  /* apparently Win doesn't check whether lpSize is valid at all! */
 
-  if ( !GetUserNameW ( lpszNameW, &len ) )
+  NameW.Length = 0;
+  NameW.MaximumLength = (*lpSize) * sizeof(WCHAR);
+  NameW.Buffer = LocalAlloc(LMEM_FIXED, NameW.MaximumLength);
+  if(NameW.Buffer == NULL)
   {
-    LocalFree ( lpszNameW );
+    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
     return FALSE;
   }
 
-  len = wcstombs ( lpszName, lpszNameW, len );
+  NameA.Length = 0;
+  NameA.MaximumLength = ((*lpSize) < 0xFFFF ? (USHORT)(*lpSize) : 0xFFFF);
+  NameA.Buffer = lpszName;
 
-  LocalFree ( lpszNameW );
-
-  if ( len > *lpSize )
+  Ret = GetUserNameW(NameW.Buffer,
+                     lpSize);
+  if(Ret)
   {
-    SetLastError(ERROR_INSUFFICIENT_BUFFER);
-    return FALSE;
+    RtlUnicodeStringToAnsiString(&NameA, &NameW, FALSE);
+    NameA.Buffer[NameA.Length] = '\0';
+
+    *lpSize = NameA.Length + 1;
   }
 
-  *lpSize = len;
-  return TRUE;
+  LocalFree(NameW.Buffer);
+
+  return Ret;
 }
 
 /******************************************************************************
@@ -630,7 +722,7 @@ GetUserNameW ( LPWSTR lpszName, LPDWORD lpSize )
 /******************************************************************************
  * LookupAccountSidA [ADVAPI32.@]
  *
- * @unimplemented
+ * @implemented
  */
 BOOL STDCALL
 LookupAccountSidA (LPCSTR lpSystemName,
@@ -641,26 +733,129 @@ LookupAccountSidA (LPCSTR lpSystemName,
                   LPDWORD cchReferencedDomainName,
                   PSID_NAME_USE peUse)
 {
-  DWORD NameLength;
-  DWORD DomainLength;
-  
-  DPRINT1("LookupAccountSidA is unimplemented, but returns success\n");
-  
-  /* Calculate length needed */
-  NameLength = strlen("Administrator") + 1;
-  DomainLength = strlen("BUILTIN") + 1;
-  
-  if (*cchName < NameLength || *cchReferencedDomainName < DomainLength)
+  UNICODE_STRING NameW, ReferencedDomainNameW, SystemNameW;
+  DWORD szName, szReferencedDomainName;
+  BOOL Ret;
+
+  /*
+   * save the buffer sizes the caller passed to us, as they may get modified and
+   * we require the original values when converting back to ansi
+   */
+  szName = *cchName;
+  szReferencedDomainName = *cchReferencedDomainName;
+
+  /*
+   * allocate buffers for the unicode strings to receive
+   */
+
+  if(szName > 0)
   {
-    *cchName = NameLength;
-    *cchReferencedDomainName = DomainLength;
-    SetLastError(ERROR_INSUFFICIENT_BUFFER);
-    return FALSE;
+    NameW.Length = 0;
+    NameW.MaximumLength = szName * sizeof(WCHAR);
+    NameW.Buffer = (PWSTR)LocalAlloc(LMEM_FIXED, NameW.MaximumLength);
+    if(NameW.Buffer == NULL)
+    {
+      SetLastError(ERROR_OUTOFMEMORY);
+      return FALSE;
+    }
   }
-  
-  if (lpName) lstrcpynA(lpName, "Administrator", *cchName);
-  if (lpReferencedDomainName) lstrcpynA(lpReferencedDomainName, "BUILTIN", *cchReferencedDomainName);
-  return TRUE;
+  else
+    NameW.Buffer = NULL;
+
+  if(szReferencedDomainName > 0)
+  {
+    ReferencedDomainNameW.Length = 0;
+    ReferencedDomainNameW.MaximumLength = szReferencedDomainName * sizeof(WCHAR);
+    ReferencedDomainNameW.Buffer = (PWSTR)LocalAlloc(LMEM_FIXED, ReferencedDomainNameW.MaximumLength);
+    if(ReferencedDomainNameW.Buffer == NULL)
+    {
+      if(szName > 0)
+      {
+        LocalFree(NameW.Buffer);
+      }
+      SetLastError(ERROR_OUTOFMEMORY);
+      return FALSE;
+    }
+  }
+  else
+    ReferencedDomainNameW.Buffer = NULL;
+
+  /*
+   * convert the system name to unicode - if present
+   */
+
+  if(lpSystemName != NULL)
+  {
+    ANSI_STRING SystemNameA;
+
+    RtlInitAnsiString(&SystemNameA, lpSystemName);
+    RtlAnsiStringToUnicodeString(&SystemNameW, &SystemNameA, TRUE);
+  }
+  else
+    SystemNameW.Buffer = NULL;
+
+  /*
+   * it's time to call the unicode version
+   */
+
+  Ret = LookupAccountSidW(SystemNameW.Buffer,
+                          lpSid,
+                          NameW.Buffer,
+                          cchName,
+                          ReferencedDomainNameW.Buffer,
+                          cchReferencedDomainName,
+                          peUse);
+  if(Ret)
+  {
+    /*
+     * convert unicode strings back to ansi, don't forget that we can't convert
+     * more than 0xFFFF (USHORT) characters! Also don't forget to explicitly
+     * terminate the converted string, the Rtl functions don't do that!
+     */
+    if(lpName != NULL)
+    {
+      ANSI_STRING NameA;
+
+      NameA.Length = 0;
+      NameA.MaximumLength = ((szName <= 0xFFFF) ? (USHORT)szName : 0xFFFF);
+      NameA.Buffer = lpName;
+
+      RtlUnicodeStringToAnsiString(&NameA, &NameW, FALSE);
+      NameA.Buffer[NameA.Length] = '\0';
+    }
+
+    if(lpReferencedDomainName != NULL)
+    {
+      ANSI_STRING ReferencedDomainNameA;
+
+      ReferencedDomainNameA.Length = 0;
+      ReferencedDomainNameA.MaximumLength = ((szReferencedDomainName <= 0xFFFF) ?
+                                             (USHORT)szReferencedDomainName : 0xFFFF);
+      ReferencedDomainNameA.Buffer = lpReferencedDomainName;
+
+      RtlUnicodeStringToAnsiString(&ReferencedDomainNameA, &ReferencedDomainNameW, FALSE);
+      ReferencedDomainNameA.Buffer[ReferencedDomainNameA.Length] = '\0';
+    }
+  }
+
+  /*
+   * free previously allocated buffers
+   */
+
+  if(SystemNameW.Buffer != NULL)
+  {
+    RtlFreeUnicodeString(&SystemNameW);
+  }
+  if(NameW.Buffer != NULL)
+  {
+    LocalFree(NameW.Buffer);
+  }
+  if(ReferencedDomainNameW.Buffer != NULL)
+  {
+    LocalFree(ReferencedDomainNameW.Buffer);
+  }
+
+  return Ret;
 }
 
 
@@ -690,7 +885,7 @@ LookupAccountSidW (
        RtlInitUnicodeString ( &SystemName, pSystemName );
        ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
        Status = LsaOpenPolicy ( &SystemName, &ObjectAttributes, POLICY_LOOKUP_NAMES, &PolicyHandle );
-       if ( !SUCCEEDED(Status) )
+       if ( !NT_SUCCESS(Status) )
        {
                SetLastError ( LsaNtStatusToWinError(Status) );
                return FALSE;
@@ -699,7 +894,7 @@ LookupAccountSidW (
 
        LsaClose ( PolicyHandle );
 
-       if ( Status != 0 /* STATUS_SUCCESS */ )
+       if ( !NT_SUCCESS(Status) || Status == STATUS_SOME_NOT_MAPPED )
        {
                SetLastError ( LsaNtStatusToWinError(Status) );
                ret = FALSE;
@@ -981,10 +1176,186 @@ LookupPrivilegeNameW (LPCWSTR lpSystemName,
 }
 
 
+static DWORD
+pGetSecurityInfoCheck(SECURITY_INFORMATION SecurityInfo,
+                      PSID* ppsidOwner,
+                      PSID* ppsidGroup,
+                      PACL* ppDacl,
+                      PACL* ppSacl,
+                      PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
+{
+    if ((SecurityInfo & (OWNER_SECURITY_INFORMATION |
+                         GROUP_SECURITY_INFORMATION |
+                         DACL_SECURITY_INFORMATION |
+                         SACL_SECURITY_INFORMATION)) &&
+        ppSecurityDescriptor == NULL)
+    {
+        /* if one of the SIDs or ACLs are present, the security descriptor
+           most not be NULL */
+        return ERROR_INVALID_PARAMETER;
+    }
+    else
+    {
+        /* reset the pointers unless they're ignored */
+        if ((SecurityInfo & OWNER_SECURITY_INFORMATION) &&
+            ppsidOwner != NULL)
+        {
+            ppsidOwner = NULL;
+        }
+        if ((SecurityInfo & GROUP_SECURITY_INFORMATION) &&
+            *ppsidGroup != NULL)
+        {
+            *ppsidGroup = NULL;
+        }
+        if ((SecurityInfo & DACL_SECURITY_INFORMATION) &&
+            ppDacl != NULL)
+        {
+            *ppDacl = NULL;
+        }
+        if ((SecurityInfo & SACL_SECURITY_INFORMATION) &&
+            ppSacl != NULL)
+        {
+            *ppSacl = NULL;
+        }
+
+        if (SecurityInfo & (OWNER_SECURITY_INFORMATION |
+                            GROUP_SECURITY_INFORMATION |
+                            DACL_SECURITY_INFORMATION |
+                            SACL_SECURITY_INFORMATION))
+        {
+            *ppSecurityDescriptor = NULL;
+        }
+
+        return ERROR_SUCCESS;
+    }
+}
+
+
+static DWORD
+pSetSecurityInfoCheck(PSECURITY_DESCRIPTOR pSecurityDescriptor,
+                      SECURITY_INFORMATION SecurityInfo,
+                      PSID psidOwner,
+                      PSID psidGroup,
+                      PACL pDacl,
+                      PACL pSacl)
+{
+    /* initialize a security descriptor on the stack */
+    if (!InitializeSecurityDescriptor(pSecurityDescriptor,
+                                      SECURITY_DESCRIPTOR_REVISION))
+    {
+        return GetLastError();
+    }
+
+    if (SecurityInfo & OWNER_SECURITY_INFORMATION)
+    {
+        if (RtlValidSid(psidOwner))
+        {
+            if (!SetSecurityDescriptorOwner(pSecurityDescriptor,
+                                            psidOwner,
+                                            FALSE))
+            {
+                return GetLastError();
+            }
+        }
+        else
+        {
+            return ERROR_INVALID_PARAMETER;
+        }
+    }
+
+    if (SecurityInfo & GROUP_SECURITY_INFORMATION)
+    {
+        if (RtlValidSid(psidGroup))
+        {
+            if (!SetSecurityDescriptorGroup(pSecurityDescriptor,
+                                            psidGroup,
+                                            FALSE))
+            {
+                return GetLastError();
+            }
+        }
+        else
+        {
+            return ERROR_INVALID_PARAMETER;
+        }
+    }
+
+    if (SecurityInfo & DACL_SECURITY_INFORMATION)
+    {
+        if (pDacl != NULL)
+        {
+            if (SetSecurityDescriptorDacl(pSecurityDescriptor,
+                                          TRUE,
+                                          pDacl,
+                                          FALSE))
+            {
+                /* check if the DACL needs to be protected from being
+                   modified by inheritable ACEs */
+                if (SecurityInfo & PROTECTED_DACL_SECURITY_INFORMATION)
+                {
+                    goto ProtectDacl;
+                }
+            }
+            else
+            {
+                return GetLastError();
+            }
+        }
+        else
+        {
+ProtectDacl:
+            /* protect the DACL from being modified by inheritable ACEs */
+            if (!SetSecurityDescriptorControl(pSecurityDescriptor,
+                                              SE_DACL_PROTECTED,
+                                              SE_DACL_PROTECTED))
+            {
+                return GetLastError();
+            }
+        }
+    }
+
+    if (SecurityInfo & SACL_SECURITY_INFORMATION)
+    {
+        if (pSacl != NULL)
+        {
+            if (SetSecurityDescriptorSacl(pSecurityDescriptor,
+                                          TRUE,
+                                          pSacl,
+                                          FALSE))
+            {
+                /* check if the SACL needs to be protected from being
+                   modified by inheritable ACEs */
+                if (SecurityInfo & PROTECTED_SACL_SECURITY_INFORMATION)
+                {
+                    goto ProtectSacl;
+                }
+            }
+            else
+            {
+                return GetLastError();
+            }
+        }
+        else
+        {
+ProtectSacl:
+            /* protect the SACL from being modified by inheritable ACEs */
+            if (!SetSecurityDescriptorControl(pSecurityDescriptor,
+                                              SE_SACL_PROTECTED,
+                                              SE_SACL_PROTECTED))
+            {
+                return GetLastError();
+            }
+        }
+    }
+    
+    return ERROR_SUCCESS;
+}
+
+
 /**********************************************************************
  * GetNamedSecurityInfoW                       EXPORTED
  *
- * @unimplemented
+ * @implemented
  */
 DWORD STDCALL
 GetNamedSecurityInfoW(LPWSTR pObjectName,
@@ -996,15 +1367,45 @@ GetNamedSecurityInfoW(LPWSTR pObjectName,
                       PACL *ppSacl,
                       PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
 {
-  DPRINT1("GetNamedSecurityInfoW: stub\n");
-  return ERROR_CALL_NOT_IMPLEMENTED;
+    DWORD ErrorCode;
+
+    if (pObjectName != NULL)
+    {
+        ErrorCode = CheckNtMartaPresent();
+        if (ErrorCode == ERROR_SUCCESS)
+        {
+            ErrorCode = pGetSecurityInfoCheck(SecurityInfo,
+                                              ppsidOwner,
+                                              ppsidGroup,
+                                              ppDacl,
+                                              ppSacl,
+                                              ppSecurityDescriptor);
+
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                /* call the MARTA provider */
+                ErrorCode = AccRewriteGetNamedRights(pObjectName,
+                                                     ObjectType,
+                                                     SecurityInfo,
+                                                     ppsidOwner,
+                                                     ppsidGroup,
+                                                     ppDacl,
+                                                     ppSacl,
+                                                     ppSecurityDescriptor);
+            }
+        }
+    }
+    else
+        ErrorCode = ERROR_INVALID_PARAMETER;
+
+    return ErrorCode;
 }
 
 
 /**********************************************************************
  * GetNamedSecurityInfoA                       EXPORTED
  *
- * @unimplemented
+ * @implemented
  */
 DWORD STDCALL
 GetNamedSecurityInfoA(LPSTR pObjectName,
@@ -1016,15 +1417,36 @@ GetNamedSecurityInfoA(LPSTR pObjectName,
                       PACL *ppSacl,
                       PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
 {
-  DPRINT1("GetNamedSecurityInfoA: stub\n");
-  return ERROR_CALL_NOT_IMPLEMENTED;
+    UNICODE_STRING ObjectName;
+    NTSTATUS Status;
+    DWORD Ret;
+
+    Status = RtlCreateUnicodeStringFromAsciiz(&ObjectName,
+                                              pObjectName);
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+
+    Ret = GetNamedSecurityInfoW(ObjectName.Buffer,
+                                ObjectType,
+                                SecurityInfo,
+                                ppsidOwner,
+                                ppsidGroup,
+                                ppDacl,
+                                ppSacl,
+                                ppSecurityDescriptor);
+
+    RtlFreeUnicodeString(&ObjectName);
+
+    return Ret;
 }
 
 
 /**********************************************************************
  * SetNamedSecurityInfoW                       EXPORTED
  *
- * @unimplemented
+ * @implemented
  */
 DWORD STDCALL
 SetNamedSecurityInfoW(LPWSTR pObjectName,
@@ -1035,15 +1457,43 @@ SetNamedSecurityInfoW(LPWSTR pObjectName,
                       PACL pDacl,
                       PACL pSacl)
 {
-  DPRINT1("SetNamedSecurityInfoW: stub\n");
-  return ERROR_CALL_NOT_IMPLEMENTED;
+    DWORD ErrorCode;
+    
+    if (pObjectName != NULL)
+    {
+        ErrorCode = CheckNtMartaPresent();
+        if (ErrorCode == ERROR_SUCCESS)
+        {
+            SECURITY_DESCRIPTOR SecurityDescriptor;
+
+            ErrorCode = pSetSecurityInfoCheck(&SecurityDescriptor,
+                                              SecurityInfo,
+                                              psidOwner,
+                                              psidGroup,
+                                              pDacl,
+                                              pSacl);
+
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                /* call the MARTA provider */
+                ErrorCode = AccRewriteSetNamedRights(pObjectName,
+                                                     ObjectType,
+                                                     SecurityInfo,
+                                                     &SecurityDescriptor);
+            }
+        }
+    }
+    else
+        ErrorCode = ERROR_INVALID_PARAMETER;
+
+    return ErrorCode;
 }
 
 
 /**********************************************************************
  * SetNamedSecurityInfoA                       EXPORTED
  *
- * @unimplemented
+ * @implemented
  */
 DWORD STDCALL
 SetNamedSecurityInfoA(LPSTR pObjectName,
@@ -1054,15 +1504,35 @@ SetNamedSecurityInfoA(LPSTR pObjectName,
                       PACL pDacl,
                       PACL pSacl)
 {
-  DPRINT1("SetNamedSecurityInfoA: stub\n");
-  return ERROR_CALL_NOT_IMPLEMENTED;
+    UNICODE_STRING ObjectName;
+    NTSTATUS Status;
+    DWORD Ret;
+    
+    Status = RtlCreateUnicodeStringFromAsciiz(&ObjectName,
+                                              pObjectName);
+    if (!NT_SUCCESS(Status))
+    {
+        return RtlNtStatusToDosError(Status);
+    }
+    
+    Ret = SetNamedSecurityInfoW(ObjectName.Buffer,
+                                ObjectType,
+                                SecurityInfo,
+                                psidOwner,
+                                psidGroup,
+                                pDacl,
+                                pSacl);
+
+    RtlFreeUnicodeString(&ObjectName);
+
+    return Ret;
 }
 
 
 /**********************************************************************
  * GetSecurityInfo                             EXPORTED
  *
- * @unimplemented
+ * @implemented
  */
 DWORD STDCALL
 GetSecurityInfo(HANDLE handle,
@@ -1074,15 +1544,45 @@ GetSecurityInfo(HANDLE handle,
                 PACL* ppSacl,
                 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
 {
-  DPRINT1("GetSecurityInfo: stub\n");
-  return ERROR_CALL_NOT_IMPLEMENTED;
+    DWORD ErrorCode;
+    
+    if (handle != NULL)
+    {
+        ErrorCode = CheckNtMartaPresent();
+        if (ErrorCode == ERROR_SUCCESS)
+        {
+            ErrorCode = pGetSecurityInfoCheck(SecurityInfo,
+                                              ppsidOwner,
+                                              ppsidGroup,
+                                              ppDacl,
+                                              ppSacl,
+                                              ppSecurityDescriptor);
+
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                /* call the MARTA provider */
+                ErrorCode = AccRewriteGetHandleRights(handle,
+                                                      ObjectType,
+                                                      SecurityInfo,
+                                                      ppsidOwner,
+                                                      ppsidGroup,
+                                                      ppDacl,
+                                                      ppSacl,
+                                                      ppSecurityDescriptor);
+            }
+        }
+    }
+    else
+        ErrorCode = ERROR_INVALID_HANDLE;
+
+    return ErrorCode;
 }
 
 
 /**********************************************************************
  * SetSecurityInfo                             EXPORTED
  *
- * @unimplemented
+ * @implemented
  */
 DWORD
 WINAPI
@@ -1094,8 +1594,36 @@ SetSecurityInfo(HANDLE handle,
                 PACL pDacl,
                 PACL pSacl)
 {
-  DPRINT1("SetSecurityInfo: stub\n");
-  return ERROR_CALL_NOT_IMPLEMENTED;
+    DWORD ErrorCode;
+
+    if (handle != NULL)
+    {
+        ErrorCode = CheckNtMartaPresent();
+        if (ErrorCode == ERROR_SUCCESS)
+        {
+            SECURITY_DESCRIPTOR SecurityDescriptor;
+            
+            ErrorCode = pSetSecurityInfoCheck(&SecurityDescriptor,
+                                              SecurityInfo,
+                                              psidOwner,
+                                              psidGroup,
+                                              pDacl,
+                                              pSacl);
+            
+            if (ErrorCode == ERROR_SUCCESS)
+            {
+                /* call the MARTA provider */
+                ErrorCode = AccRewriteSetHandleRights(handle,
+                                                      ObjectType,
+                                                      SecurityInfo,
+                                                      &SecurityDescriptor);
+            }
+        }
+    }
+    else
+        ErrorCode = ERROR_INVALID_HANDLE;
+
+    return ErrorCode;
 }
 
 
@@ -1103,19 +1631,19 @@ SetSecurityInfo(HANDLE handle,
  * GetSecurityInfoExW         EXPORTED
  */
 DWORD WINAPI GetSecurityInfoExA(
-   HANDLE hObject, 
-   SE_OBJECT_TYPE ObjectType, 
-   SECURITY_INFORMATION SecurityInfo, 
+   HANDLE hObject,
+   SE_OBJECT_TYPE ObjectType,
+   SECURITY_INFORMATION SecurityInfo,
    LPCSTR lpProvider,
-   LPCSTR lpProperty, 
-   PACTRL_ACCESSA *ppAccessList, 
-   PACTRL_AUDITA *ppAuditList, 
-   LPSTR *lppOwner, 
+   LPCSTR lpProperty,
+   PACTRL_ACCESSA *ppAccessList,
+   PACTRL_AUDITA *ppAuditList,
+   LPSTR *lppOwner,
    LPSTR *lppGroup
    )
 {
   DPRINT1("GetSecurityInfoExA stub!\n");
-  return ERROR_BAD_PROVIDER; 
+  return ERROR_BAD_PROVIDER;
 }
 
 
@@ -1123,19 +1651,19 @@ DWORD WINAPI GetSecurityInfoExA(
  * GetSecurityInfoExW         EXPORTED
  */
 DWORD WINAPI GetSecurityInfoExW(
-   HANDLE hObject, 
-   SE_OBJECT_TYPE ObjectType, 
-   SECURITY_INFORMATION SecurityInfo, 
+   HANDLE hObject,
+   SE_OBJECT_TYPE ObjectType,
+   SECURITY_INFORMATION SecurityInfo,
    LPCWSTR lpProvider,
-   LPCWSTR lpProperty, 
-   PACTRL_ACCESSW *ppAccessList, 
-   PACTRL_AUDITW *ppAuditList, 
-   LPWSTR *lppOwner, 
+   LPCWSTR lpProperty,
+   PACTRL_ACCESSW *ppAccessList,
+   PACTRL_AUDITW *ppAuditList,
+   LPWSTR *lppOwner,
    LPWSTR *lppGroup
    )
 {
   DPRINT1("GetSecurityInfoExW stub!\n");
-  return ERROR_BAD_PROVIDER; 
+  return ERROR_BAD_PROVIDER;
 }
 
 
@@ -1171,4 +1699,238 @@ ImpersonateNamedPipeClient(HANDLE hNamedPipe)
   return TRUE;
 }
 
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+CreatePrivateObjectSecurity(PSECURITY_DESCRIPTOR ParentDescriptor,
+                            PSECURITY_DESCRIPTOR CreatorDescriptor,
+                            PSECURITY_DESCRIPTOR *NewDescriptor,
+                            BOOL IsDirectoryObject,
+                            HANDLE Token,
+                            PGENERIC_MAPPING GenericMapping)
+{
+    NTSTATUS Status;
+
+    Status = RtlNewSecurityObject(ParentDescriptor,
+                                  CreatorDescriptor,
+                                  NewDescriptor,
+                                  IsDirectoryObject,
+                                  Token,
+                                  GenericMapping);
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
+CreatePrivateObjectSecurityEx(PSECURITY_DESCRIPTOR ParentDescriptor,
+                              PSECURITY_DESCRIPTOR CreatorDescriptor,
+                              PSECURITY_DESCRIPTOR* NewDescriptor,
+                              GUID* ObjectType,
+                              BOOL IsContainerObject,
+                              ULONG AutoInheritFlags,
+                              HANDLE Token,
+                              PGENERIC_MAPPING GenericMapping)
+{
+    DPRINT1("%s() not implemented!\n", __FUNCTION__);
+    return FALSE;
+}
+
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
+CreatePrivateObjectSecurityWithMultipleInheritance(PSECURITY_DESCRIPTOR ParentDescriptor,
+                                                   PSECURITY_DESCRIPTOR CreatorDescriptor,
+                                                   PSECURITY_DESCRIPTOR* NewDescriptor,
+                                                   GUID** ObjectTypes,
+                                                   ULONG GuidCount,
+                                                   BOOL IsContainerObject,
+                                                   ULONG AutoInheritFlags,
+                                                   HANDLE Token,
+                                                   PGENERIC_MAPPING GenericMapping)
+{
+    DPRINT1("%s() not implemented!\n", __FUNCTION__);
+    return FALSE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+DestroyPrivateObjectSecurity(PSECURITY_DESCRIPTOR *ObjectDescriptor)
+{
+    NTSTATUS Status;
+
+    Status = RtlDeleteSecurityObject(ObjectDescriptor);
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+GetPrivateObjectSecurity(PSECURITY_DESCRIPTOR ObjectDescriptor,
+                         SECURITY_INFORMATION SecurityInformation,
+                         PSECURITY_DESCRIPTOR ResultantDescriptor,
+                         DWORD DescriptorLength,
+                         PDWORD ReturnLength)
+{
+    NTSTATUS Status;
+
+    Status = RtlQuerySecurityObject(ObjectDescriptor,
+                                    SecurityInformation,
+                                    ResultantDescriptor,
+                                    DescriptorLength,
+                                    ReturnLength);
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+SetPrivateObjectSecurity(SECURITY_INFORMATION SecurityInformation,
+                         PSECURITY_DESCRIPTOR ModificationDescriptor,
+                         PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
+                         PGENERIC_MAPPING GenericMapping,
+                         HANDLE Token)
+{
+    NTSTATUS Status;
+
+    Status = RtlSetSecurityObject(SecurityInformation,
+                                  ModificationDescriptor,
+                                  ObjectsSecurityDescriptor,
+                                  GenericMapping,
+                                  Token);
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+TreeResetNamedSecurityInfoW(LPWSTR pObjectName,
+                            SE_OBJECT_TYPE ObjectType,
+                            SECURITY_INFORMATION SecurityInfo,
+                            PSID pOwner,
+                            PSID pGroup,
+                            PACL pDacl,
+                            PACL pSacl,
+                            BOOL KeepExplicit,
+                            FN_PROGRESSW fnProgress,
+                            PROG_INVOKE_SETTING ProgressInvokeSetting,
+                            PVOID Args)
+{
+    DWORD ErrorCode;
+
+    if (pObjectName != NULL)
+    {
+        ErrorCode = CheckNtMartaPresent();
+        if (ErrorCode == ERROR_SUCCESS)
+        {
+            switch (ObjectType)
+            {
+                case SE_FILE_OBJECT:
+                case SE_REGISTRY_KEY:
+                {
+                    /* check the SecurityInfo flags for sanity (both, the protected
+                       and unprotected dacl/sacl flag must not be passed together) */
+                    if (((SecurityInfo & DACL_SECURITY_INFORMATION) &&
+                         (SecurityInfo & (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION)) ==
+                             (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION))
+
+                        ||
+
+                        ((SecurityInfo & SACL_SECURITY_INFORMATION) &&
+                         (SecurityInfo & (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION)) ==
+                             (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION)))
+                    {
+                        ErrorCode = ERROR_INVALID_PARAMETER;
+                        break;
+                    }
+
+                    /* call the MARTA provider */
+                    ErrorCode = AccTreeResetNamedSecurityInfo(pObjectName,
+                                                              ObjectType,
+                                                              SecurityInfo,
+                                                              pOwner,
+                                                              pGroup,
+                                                              pDacl,
+                                                              pSacl,
+                                                              KeepExplicit,
+                                                              fnProgress,
+                                                              ProgressInvokeSetting,
+                                                              Args);
+                    break;
+                }
+
+                default:
+                    /* object type not supported */
+                    ErrorCode = ERROR_INVALID_PARAMETER;
+                    break;
+            }
+        }
+    }
+    else
+        ErrorCode = ERROR_INVALID_PARAMETER;
+
+    return ErrorCode;
+}
+
+
+/*
+ * @unimplemented
+ */
+DWORD STDCALL
+TreeResetNamedSecurityInfoA(LPSTR pObjectName,
+                            SE_OBJECT_TYPE ObjectType,
+                            SECURITY_INFORMATION SecurityInfo,
+                            PSID pOwner,
+                            PSID pGroup,
+                            PACL pDacl,
+                            PACL pSacl,
+                            BOOL KeepExplicit,
+                            FN_PROGRESSA fnProgress,
+                            PROG_INVOKE_SETTING ProgressInvokeSetting,
+                            PVOID Args)
+{
+    /* That's all this function does, at least up to w2k3... Even MS was too
+       lazy to implement it... */
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
 /* EOF */