fixed desired access rights in GetFileSecurityW
[reactos.git] / reactos / lib / advapi32 / sec / misc.c
index d8ca4bc..12b50e4 100644 (file)
-/* $Id: misc.c,v 1.28 2004/12/12 21:25:04 weiden Exp $
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/advapi32/sec/misc.c
  * PURPOSE:         Miscellaneous security functions
  */
 
-#include "advapi32.h"
-#include <accctrl.h>
+#include <advapi32.h>
 
 #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
@@ -51,7 +152,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
@@ -112,7 +213,7 @@ GetFileSecurityW(LPCWSTR lpFileName,
   if (RequestedInformation &
       (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
     {
-      AccessMask |= STANDARD_RIGHTS_READ;
+      AccessMask |= READ_CONTROL;
     }
 
   if (RequestedInformation & SACL_SECURITY_INFORMATION)
@@ -120,7 +221,7 @@ GetFileSecurityW(LPCWSTR lpFileName,
       AccessMask |= ACCESS_SYSTEM_SECURITY;
     }
 
-  if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpFileName,
+  if (!RtlDosPathNameToNtPathName_U(lpFileName,
                                    &FileName,
                                    NULL,
                                    NULL))
@@ -264,7 +365,7 @@ SetFileSecurityW (LPCWSTR lpFileName,
       AccessMask |= ACCESS_SYSTEM_SECURITY;
     }
 
-  if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpFileName,
+  if (!RtlDosPathNameToNtPathName_U(lpFileName,
                                    &FileName,
                                    NULL,
                                    NULL))
@@ -333,18 +434,6 @@ SetKernelObjectSecurity(HANDLE Handle,
 }
 
 
-/*
- * @implemented
- */
-VOID STDCALL
-MapGenericMask(PDWORD AccessMask,
-              PGENERIC_MAPPING GenericMapping)
-{
-  RtlMapGenericMask(AccessMask,
-                   GenericMapping);
-}
-
-
 /*
  * @implemented
  */
@@ -478,32 +567,43 @@ RevertToSelf(VOID)
  *  lpSize   [I/O] Size of lpszName.
  *
  *
- * @unimplemented
+ * @implemented
  */
 BOOL WINAPI
 GetUserNameA( LPSTR lpszName, LPDWORD lpSize )
 {
-  size_t len;
-  const char* name = "Administrator";
-  DPRINT1("GetUserNameA: stub\n");
-  if ( !lpSize )
+  UNICODE_STRING NameW;
+  ANSI_STRING NameA;
+  BOOL Ret;
+
+  /* apparently Win doesn't check whether lpSize is valid at all! */
+
+  NameW.Length = 0;
+  NameW.MaximumLength = (*lpSize) * sizeof(WCHAR);
+  NameW.Buffer = LocalAlloc(LMEM_FIXED, NameW.MaximumLength);
+  if(NameW.Buffer == NULL)
   {
-    SetLastError(ERROR_INVALID_PARAMETER);
+    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
     return FALSE;
   }
-  /* We need to include the null character when determining the size of the buffer. */
-  len = strlen(name) + 1;
-  if (len > *lpSize)
+
+  NameA.Length = 0;
+  NameA.MaximumLength = ((*lpSize) < 0xFFFF ? (USHORT)(*lpSize) : 0xFFFF);
+  NameA.Buffer = lpszName;
+
+  Ret = GetUserNameW(NameW.Buffer,
+                     lpSize);
+  if(Ret)
   {
-    SetLastError(ERROR_MORE_DATA);
-    *lpSize = len;
-    return FALSE;
+    RtlUnicodeStringToAnsiString(&NameA, &NameW, FALSE);
+    NameA.Buffer[NameA.Length] = '\0';
+
+    *lpSize = NameA.Length + 1;
   }
-  *lpSize = len;
-  strcpy(lpszName, name);
-  return TRUE;
+
+  LocalFree(NameW.Buffer);
+
+  return Ret;
 }
 
 /******************************************************************************
@@ -511,33 +611,115 @@ GetUserNameA( LPSTR lpszName, LPDWORD lpSize )
  *
  * See GetUserNameA.
  *
- * @unimplemented
+ * @implemented
  */
 BOOL WINAPI
-GetUserNameW( LPWSTR lpszName, LPDWORD lpSize )
+GetUserNameW ( LPWSTR lpszName, LPDWORD lpSize )
 {
-//    char name[] = { "Administrator" };
+  HANDLE hToken = INVALID_HANDLE_VALUE;
+  DWORD tu_len = 0;
+  char* tu_buf = NULL;
+  TOKEN_USER* token_user = NULL;
+  DWORD an_len = 0;
+  SID_NAME_USE snu = SidTypeUser;
+  WCHAR* domain_name = NULL;
+  DWORD dn_len = 0;
+
+  if ( !OpenThreadToken ( GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken ) )
+  {
+    DWORD dwLastError = GetLastError();
+    if ( dwLastError != ERROR_NO_TOKEN
+      && dwLastError != ERROR_NO_IMPERSONATION_TOKEN )
+    {
+      /* don't call SetLastError(),
+         as OpenThreadToken() ought to have set one */
+      return FALSE;
+    }
+    if ( !OpenProcessToken ( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )
+    {
+      /* don't call SetLastError(),
+         as OpenProcessToken() ought to have set one */
+      return FALSE;
+    }
+  }
+  tu_buf = LocalAlloc ( LMEM_FIXED, 36 );
+  if ( !tu_buf )
+  {
+    SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
+    return FALSE;
+  }
+  if ( !GetTokenInformation ( hToken, TokenUser, tu_buf, 36, &tu_len ) || tu_len > 36 )
+  {
+    LocalFree ( tu_buf );
+    tu_buf = LocalAlloc ( LMEM_FIXED, tu_len );
+    if ( !tu_buf )
+    {
+      SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
+      return FALSE;
+    }
+    if ( !GetTokenInformation ( hToken, TokenUser, tu_buf, tu_len, &tu_len ) )
+    {
+      /* don't call SetLastError(),
+         as GetTokenInformation() ought to have set one */
+      LocalFree ( tu_buf );
+      CloseHandle ( hToken );
+      return FALSE;
+    }
+  }
+  token_user = (TOKEN_USER*)tu_buf;
 
-//    DWORD len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
+  an_len = *lpSize;
+  dn_len = 32;
+  domain_name = LocalAlloc ( LMEM_FIXED, dn_len * sizeof(WCHAR) );
+  if ( !domain_name )
+  {
+    LocalFree ( tu_buf );
+    SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
+    return FALSE;
+  }
+  if ( !LookupAccountSidW ( NULL, token_user->User.Sid, lpszName, &an_len, domain_name, &dn_len, &snu )
+    || dn_len > 32 )
+  {
+    if ( dn_len > 32 )
+    {
+      LocalFree ( domain_name );
+      domain_name = LocalAlloc ( LMEM_FIXED, dn_len * sizeof(WCHAR) );
+      if ( !domain_name )
+      {
+        LocalFree ( tu_buf );
+        SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
+        return FALSE;
+      }
+    }
+    if ( !LookupAccountSidW ( NULL, token_user->User.Sid, lpszName, &an_len, domain_name, &dn_len, &snu ) )
+    {
+      /* don't call SetLastError(),
+         as LookupAccountSid() ought to have set one */
+      LocalFree ( domain_name );
+      CloseHandle ( hToken );
+      return FALSE;
+    }
+  }
 
-//    if (len > *lpSize)
-//    {
-//        SetLastError(ERROR_MORE_DATA);
-//        *lpSize = len;
-//        return FALSE;
-//    }
+  LocalFree ( domain_name );
+  LocalFree ( tu_buf );
+  CloseHandle ( hToken );
 
-//    *lpSize = len;
-//    MultiByteToWideChar( CP_ACP, 0, name, -1, lpszName, len );
-    DPRINT1("GetUserNameW: stub\n");
-    return TRUE;
+  if ( an_len > *lpSize )
+  {
+    *lpSize = an_len;
+    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    return FALSE;
+  }
+
+  return TRUE;
 }
 
 
 /******************************************************************************
  * LookupAccountSidA [ADVAPI32.@]
  *
- * @unimplemented
+ * @implemented
  */
 BOOL STDCALL
 LookupAccountSidA (LPCSTR lpSystemName,
@@ -548,66 +730,224 @@ 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;
 }
 
 
 /******************************************************************************
  * LookupAccountSidW [ADVAPI32.@]
  *
- * @unimplemented
+ * @implemented
  */
-BOOL STDCALL
-LookupAccountSidW (LPCWSTR lpSystemName,
-                  PSID lpSid,
-                  LPWSTR lpName,
-                  LPDWORD cchName,
-                  LPWSTR lpReferencedDomainName,
-                  LPDWORD cchReferencedDomainName,
-                  PSID_NAME_USE peUse)
+BOOL WINAPI
+LookupAccountSidW (
+       LPCWSTR pSystemName,
+       PSID pSid,
+       LPWSTR pAccountName,
+       LPDWORD pdwAccountName,
+       LPWSTR pDomainName,
+       LPDWORD pdwDomainName,
+       PSID_NAME_USE peUse )
 {
-  DWORD NameLength;
-  DWORD DomainLength;
-  
-  DPRINT1("LookupAccountSidW is unimplemented, but returns success\n");
-  
-  /* Calculate length needed */
-  NameLength = wcslen(L"Administrator") + sizeof(WCHAR);
-  DomainLength = wcslen(L"BUILTIN") + sizeof(WCHAR);
-  
-  if (*cchName < NameLength || *cchReferencedDomainName < DomainLength)
-  {
-    *cchName = NameLength;
-    *cchReferencedDomainName = DomainLength;
-    SetLastError(ERROR_INSUFFICIENT_BUFFER);
-    return FALSE;
-  }
-  
-  if (lpName) lstrcpynW(lpName, L"Administrator", *cchName);
-  if (lpReferencedDomainName) lstrcpynW(lpReferencedDomainName, L"BUILTIN", *cchReferencedDomainName);
-  return TRUE;
+       LSA_UNICODE_STRING SystemName;
+       LSA_OBJECT_ATTRIBUTES ObjectAttributes;
+       LSA_HANDLE PolicyHandle = INVALID_HANDLE_VALUE;
+       NTSTATUS Status;
+       PLSA_REFERENCED_DOMAIN_LIST ReferencedDomain = NULL;
+       PLSA_TRANSLATED_NAME TranslatedName = NULL;
+       BOOL ret;
+
+       RtlInitUnicodeString ( &SystemName, pSystemName );
+       ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
+       Status = LsaOpenPolicy ( &SystemName, &ObjectAttributes, POLICY_LOOKUP_NAMES, &PolicyHandle );
+       if ( !NT_SUCCESS(Status) )
+       {
+               SetLastError ( LsaNtStatusToWinError(Status) );
+               return FALSE;
+       }
+       Status = LsaLookupSids ( PolicyHandle, 1, &pSid, &ReferencedDomain, &TranslatedName );
+
+       LsaClose ( PolicyHandle );
+
+       if ( !NT_SUCCESS(Status) || Status == STATUS_SOME_NOT_MAPPED )
+       {
+               SetLastError ( LsaNtStatusToWinError(Status) );
+               ret = FALSE;
+       }
+       else
+       {
+               ret = TRUE;
+               if ( TranslatedName )
+               {
+                       DWORD dwSrcLen = TranslatedName->Name.Length / sizeof(WCHAR);
+                       if ( *pdwAccountName <= dwSrcLen )
+                       {
+                               *pdwAccountName = dwSrcLen + 1;
+                               ret = FALSE;
+                       }
+                       else
+                       {
+                               *pdwAccountName = dwSrcLen;
+                               wcscpy ( pAccountName, TranslatedName->Name.Buffer );
+                       }
+                       if ( peUse )
+                               *peUse = TranslatedName->Use;
+               }
+
+               if ( ReferencedDomain )
+               {
+                       if ( ReferencedDomain->Entries > 0 )
+                       {
+                               DWORD dwSrcLen = ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR);
+                               if ( *pdwDomainName <= dwSrcLen )
+                               {
+                                       *pdwDomainName = dwSrcLen + 1;
+                                       ret = FALSE;
+                               }
+                               else
+                               {
+                                       *pdwDomainName = dwSrcLen;
+                                       wcscpy ( pDomainName, ReferencedDomain->Domains[0].Name.Buffer );
+                               }
+                       }
+               }
+
+               if ( !ret )
+                       SetLastError(ERROR_INSUFFICIENT_BUFFER);
+       }
+
+       if ( ReferencedDomain )
+               LsaFreeMemory ( ReferencedDomain );
+       if ( TranslatedName )
+               LsaFreeMemory ( TranslatedName );
+
+       return ret;
 }
 
 
+
 /******************************************************************************
  * LookupAccountNameA [ADVAPI32.@]
  *
@@ -833,10 +1173,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,
@@ -848,15 +1364,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,
@@ -868,15 +1414,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,
@@ -887,15 +1454,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,
@@ -906,15 +1501,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,
@@ -926,29 +1541,106 @@ 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
+ *
+ * @implemented
+ */
+DWORD
+WINAPI
+SetSecurityInfo(HANDLE handle,
+                SE_OBJECT_TYPE ObjectType,
+                SECURITY_INFORMATION SecurityInfo,
+                PSID psidOwner,
+                PSID psidGroup,
+                PACL pDacl,
+                PACL pSacl)
+{
+    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;
+}
+
 
 /******************************************************************************
  * 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;
 }
 
 
@@ -956,19 +1648,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;
 }
 
 
@@ -1004,4 +1696,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 */