implemented some stubs needed by ClamWin
[reactos.git] / reactos / lib / advapi32 / sec / sid.c
index 3b8ae89..048b766 100644 (file)
-/* $Id: sid.c,v 1.5 2002/09/07 15:12:22 chorns Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
+ * WINE COPYRIGHT:
+ * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
+ * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
+ *
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/advapi32/sec/sid.c
  * PURPOSE:         Security ID functions
  */
 
 #include <advapi32.h>
+#include <wine/debug.h>
+#include <wine/unicode.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(advapi);
+
+
+static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
+static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, 
+    PACL pAcl, LPDWORD cBytes);
+static BYTE ParseAceStringFlags(LPCWSTR* StringAcl);
+static BYTE ParseAceStringType(LPCWSTR* StringAcl);
+static DWORD ParseAceStringRights(LPCWSTR* StringAcl);
+static DWORD ParseAclStringFlags(LPCWSTR* StringAcl);
+
+typedef struct _ACEFLAG
+{
+   LPCWSTR wstr;
+   DWORD value;
+} ACEFLAG, *LPACEFLAG;
+
+static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
+
+/*
+ * ACE access rights
+ */
+static const WCHAR SDDL_READ_CONTROL[]     = {'R','C',0};
+static const WCHAR SDDL_WRITE_DAC[]        = {'W','D',0};
+static const WCHAR SDDL_WRITE_OWNER[]      = {'W','O',0};
+static const WCHAR SDDL_STANDARD_DELETE[]  = {'S','D',0};
+static const WCHAR SDDL_GENERIC_ALL[]      = {'G','A',0};
+static const WCHAR SDDL_GENERIC_READ[]     = {'G','R',0};
+static const WCHAR SDDL_GENERIC_WRITE[]    = {'G','W',0};
+static const WCHAR SDDL_GENERIC_EXECUTE[]  = {'G','X',0};
+
+/*
+ * ACE types
+ */
+static const WCHAR SDDL_ACCESS_ALLOWED[]        = {'A',0};
+static const WCHAR SDDL_ACCESS_DENIED[]         = {'D',0};
+static const WCHAR SDDL_OBJECT_ACCESS_ALLOWED[] = {'O','A',0};
+static const WCHAR SDDL_OBJECT_ACCESS_DENIED[]  = {'O','D',0};
+static const WCHAR SDDL_AUDIT[]                 = {'A','U',0};
+static const WCHAR SDDL_ALARM[]                 = {'A','L',0};
+static const WCHAR SDDL_OBJECT_AUDIT[]          = {'O','U',0};
+static const WCHAR SDDL_OBJECT_ALARMp[]         = {'O','L',0};
+
+/*
+ * ACE flags
+ */
+static const WCHAR SDDL_CONTAINER_INHERIT[]  = {'C','I',0};
+static const WCHAR SDDL_OBJECT_INHERIT[]     = {'O','I',0};
+static const WCHAR SDDL_NO_PROPAGATE[]       = {'N','P',0};
+static const WCHAR SDDL_INHERIT_ONLY[]       = {'I','O',0};
+static const WCHAR SDDL_INHERITED[]          = {'I','D',0};
+static const WCHAR SDDL_AUDIT_SUCCESS[]      = {'S','A',0};
+static const WCHAR SDDL_AUDIT_FAILURE[]      = {'F','A',0};
+
+/* set last error code from NT status and get the proper boolean return value */
+/* used for functions that are a simple wrapper around the corresponding ntdll API */
+static inline BOOL set_ntstatus( NTSTATUS status )
+{
+    if (status) SetLastError( RtlNtStatusToDosError( status ));
+    return !status;
+}
+
+#define        WINE_SIZE_OF_WORLD_ACCESS_ACL   (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD))
+
+
+/* some helper functions - taken from winehq cvs 20050916 */
+/******************************************************************************
+ * ComputeStringSidSize
+ */
+static DWORD ComputeStringSidSize(LPCWSTR StringSid)
+{
+    int ctok = 0;
+    DWORD size = sizeof(SID);
+
+    while (*StringSid)
+    {
+        if (*StringSid == '-')
+            ctok++;
+        StringSid++;
+    }
+
+    if (ctok > 3)
+        size += (ctok - 3) * sizeof(DWORD);
+
+    return size;
+}
+
+/******************************************************************************
+ * ParseAceStringType
+ */
+ACEFLAG AceType[] =
+{
+    { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
+    { SDDL_ALARM,          SYSTEM_ALARM_ACE_TYPE },
+    { SDDL_AUDIT,          SYSTEM_AUDIT_ACE_TYPE },
+    { SDDL_ACCESS_DENIED,  ACCESS_DENIED_ACE_TYPE },
+    /*
+    { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
+    { SDDL_OBJECT_ACCESS_DENIED,  ACCESS_DENIED_OBJECT_ACE_TYPE },
+    { SDDL_OBJECT_ALARM,          SYSTEM_ALARM_OBJECT_ACE_TYPE },
+    { SDDL_OBJECT_AUDIT,          SYSTEM_AUDIT_OBJECT_ACE_TYPE },
+    */
+    { NULL, 0 },
+};
+
+static BYTE ParseAceStringType(LPCWSTR* StringAcl)
+{
+    UINT len = 0;
+    LPCWSTR szAcl = *StringAcl;
+    LPACEFLAG lpaf = AceType;
+
+    while (lpaf->wstr &&
+        (len = strlenW(lpaf->wstr)) &&
+        strncmpW(lpaf->wstr, szAcl, len))
+        lpaf++;
+
+    if (!lpaf->wstr)
+        return 0;
 
+    *StringAcl += len;
+    return lpaf->value;
+}
+
+
+/******************************************************************************
+ * ParseAceStringFlags
+ */
+ACEFLAG AceFlags[] =
+{
+    { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
+    { SDDL_AUDIT_FAILURE,     FAILED_ACCESS_ACE_FLAG },
+    { SDDL_INHERITED,         INHERITED_ACE },
+    { SDDL_INHERIT_ONLY,      INHERIT_ONLY_ACE },
+    { SDDL_NO_PROPAGATE,      NO_PROPAGATE_INHERIT_ACE },
+    { SDDL_OBJECT_INHERIT,    OBJECT_INHERIT_ACE },
+    { SDDL_AUDIT_SUCCESS,     SUCCESSFUL_ACCESS_ACE_FLAG },
+    { NULL, 0 },
+};
+
+static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
+{
+    UINT len = 0;
+    BYTE flags = 0;
+    LPCWSTR szAcl = *StringAcl;
+
+    while (*szAcl != ';')
+    {
+        LPACEFLAG lpaf = AceFlags;
+
+        while (lpaf->wstr &&
+               (len = strlenW(lpaf->wstr)) &&
+               strncmpW(lpaf->wstr, szAcl, len))
+            lpaf++;
+
+        if (!lpaf->wstr)
+            return 0;
+
+       flags |= lpaf->value;
+        szAcl += len;
+    }
+
+    *StringAcl = szAcl;
+    return flags;
+}
+
+
+/******************************************************************************
+ * ParseAceStringRights
+ */
+ACEFLAG AceRights[] =
+{
+    { SDDL_GENERIC_ALL,     GENERIC_ALL },
+    { SDDL_GENERIC_READ,    GENERIC_READ },
+    { SDDL_GENERIC_WRITE,   GENERIC_WRITE },
+    { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
+    { SDDL_READ_CONTROL,    READ_CONTROL },
+    { SDDL_STANDARD_DELETE, DELETE },
+    { SDDL_WRITE_DAC,       WRITE_DAC },
+    { SDDL_WRITE_OWNER,     WRITE_OWNER },
+    { NULL, 0 },
+};
+
+static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
+{
+    UINT len = 0;
+    DWORD rights = 0;
+    LPCWSTR szAcl = *StringAcl;
+
+    if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
+    {
+        LPCWSTR p = szAcl;
+
+       while (*p && *p != ';')
+            p++;
+
+       if (p - szAcl <= 8)
+       {
+           rights = strtoulW(szAcl, NULL, 16);
+           *StringAcl = p;
+       }
+       else
+            WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
+    }
+    else
+    {
+        while (*szAcl != ';')
+        {
+            LPACEFLAG lpaf = AceRights;
+
+            while (lpaf->wstr &&
+               (len = strlenW(lpaf->wstr)) &&
+               strncmpW(lpaf->wstr, szAcl, len))
+           {
+               lpaf++;
+           }
+
+            if (!lpaf->wstr)
+                return 0;
+
+           rights |= lpaf->value;
+            szAcl += len;
+        }
+    }
+
+    *StringAcl = szAcl;
+    return rights;
+}
+
+/******************************************************************************
+ * ParseStringAclToAcl
+ * 
+ * dacl_flags(string_ace1)(string_ace2)... (string_acen) 
+ */
+static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, 
+    PACL pAcl, LPDWORD cBytes)
+{
+    DWORD val;
+    DWORD sidlen;
+    DWORD length = sizeof(ACL);
+    PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
+
+    TRACE("%s\n", debugstr_w(StringAcl));
+
+    if (!StringAcl)
+       return FALSE;
+
+    if (pAcl) /* pAce is only useful if we're setting values */
+        pAce = (PACCESS_ALLOWED_ACE) ((LPBYTE)pAcl + sizeof(PACL));
+
+    /* Parse ACL flags */
+    *lpdwFlags = ParseAclStringFlags(&StringAcl);
+
+    /* Parse ACE */
+    while (*StringAcl == '(')
+    {
+        StringAcl++;
+
+        /* Parse ACE type */
+        val = ParseAceStringType(&StringAcl);
+       if (pAce)
+            pAce->Header.AceType = (BYTE) val;
+        if (*StringAcl != ';')
+            goto lerr;
+        StringAcl++;
+
+        /* Parse ACE flags */
+       val = ParseAceStringFlags(&StringAcl);
+       if (pAce)
+            pAce->Header.AceFlags = (BYTE) val;
+        if (*StringAcl != ';')
+            goto lerr;
+        StringAcl++;
+
+        /* Parse ACE rights */
+       val = ParseAceStringRights(&StringAcl);
+       if (pAce)
+            pAce->Mask = val;
+        if (*StringAcl != ';')
+            goto lerr;
+        StringAcl++;
+
+        /* Parse ACE object guid */
+        if (*StringAcl != ';')
+        {
+            FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
+            goto lerr;
+        }
+        StringAcl++;
+
+        /* Parse ACE inherit object guid */
+        if (*StringAcl != ';')
+        {
+            FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
+            goto lerr;
+        }
+        StringAcl++;
+
+        /* Parse ACE account sid */
+        if (ParseStringSidToSid(StringAcl, pAce ? (PSID)&pAce->SidStart : NULL, &sidlen))
+       {
+            while (*StringAcl && *StringAcl != ')')
+                StringAcl++;
+       }
+
+        if (*StringAcl != ')')
+            goto lerr;
+        StringAcl++;
+
+       length += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
+    }
+
+    *cBytes = length;
+    return TRUE;
+
+lerr:
+    WARN("Invalid ACE string format\n");
+    return FALSE;
+}
+
+/******************************************************************************
+ * ParseStringSecurityDescriptorToSecurityDescriptor
+ */
+static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
+    LPCWSTR StringSecurityDescriptor,
+    SECURITY_DESCRIPTOR* SecurityDescriptor,
+    LPDWORD cBytes)
+{
+    BOOL bret = FALSE;
+    WCHAR toktype;
+    WCHAR tok[MAX_PATH];
+    LPCWSTR lptoken;
+    LPBYTE lpNext = NULL;
+    DWORD len;
+
+    *cBytes = 0;
+
+    if (SecurityDescriptor)
+        lpNext = ((LPBYTE) SecurityDescriptor) + sizeof(SECURITY_DESCRIPTOR);
+
+    while (*StringSecurityDescriptor)
+    {
+        toktype = *StringSecurityDescriptor;
+
+       /* Expect char identifier followed by ':' */
+       StringSecurityDescriptor++;
+        if (*StringSecurityDescriptor != ':')
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            goto lend;
+        }
+       StringSecurityDescriptor++;
+
+       /* Extract token */
+       lptoken = StringSecurityDescriptor;
+       while (*lptoken && *lptoken != ':')
+            lptoken++;
+
+       if (*lptoken)
+            lptoken--;
+
+        len = lptoken - StringSecurityDescriptor;
+        memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
+        tok[len] = 0;
+
+        switch (toktype)
+       {
+            case 'O':
+            {
+                DWORD bytes;
+
+                if (!ParseStringSidToSid(tok, (PSID)lpNext, &bytes))
+                    goto lend;
+
+                if (SecurityDescriptor)
+                {
+                    SecurityDescriptor->Owner = (PSID) ((DWORD) lpNext -
+                        (DWORD) SecurityDescriptor);
+                    lpNext += bytes; /* Advance to next token */
+                }
+
+               *cBytes += bytes;
+
+                break;
+            }
+
+            case 'G':
+            {
+                DWORD bytes;
+
+                if (!ParseStringSidToSid(tok, (PSID)lpNext, &bytes))
+                    goto lend;
+
+                if (SecurityDescriptor)
+                {
+                    SecurityDescriptor->Group = (PSID) ((DWORD) lpNext - 
+                        (DWORD) SecurityDescriptor);
+                    lpNext += bytes; /* Advance to next token */
+                }
+
+               *cBytes += bytes;
+
+                break;
+            }
+
+            case 'D':
+           {
+                DWORD flags;
+                DWORD bytes;
+
+                if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
+                    goto lend;
+
+                if (SecurityDescriptor)
+                {
+                    SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
+                    SecurityDescriptor->Dacl = (PACL) ((DWORD) lpNext -
+                        (DWORD) SecurityDescriptor);
+                    lpNext += bytes; /* Advance to next token */
+               }
+
+               *cBytes += bytes;
+
+               break;
+            }
+
+            case 'S':
+            {
+                DWORD flags;
+                DWORD bytes;
+
+                if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
+                    goto lend;
+
+                if (SecurityDescriptor)
+                {
+                    SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
+                    SecurityDescriptor->Sacl = (PACL) ((DWORD) lpNext -
+                        (DWORD) SecurityDescriptor);
+                    lpNext += bytes; /* Advance to next token */
+               }
+
+               *cBytes += bytes;
+
+               break;
+            }
+
+            default:
+                FIXME("Unknown token\n");
+                SetLastError(ERROR_INVALID_PARAMETER);
+               goto lend;
+       }
+
+        StringSecurityDescriptor = lptoken;
+    }
+
+    bret = TRUE;
+
+lend:
+    return bret;
+}
+
+/******************************************************************************
+ * ParseAclStringFlags
+ */
+static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
+{
+    DWORD flags = 0;
+    LPCWSTR szAcl = *StringAcl;
+
+    while (*szAcl != '(')
+    {
+        if (*szAcl == 'P')
+       {
+            flags |= SE_DACL_PROTECTED;
+       }
+        else if (*szAcl == 'A')
+        {
+            szAcl++;
+            if (*szAcl == 'R')
+                flags |= SE_DACL_AUTO_INHERIT_REQ;
+           else if (*szAcl == 'I')
+                flags |= SE_DACL_AUTO_INHERITED;
+        }
+        szAcl++;
+    }
 
+    *StringAcl = szAcl;
+    return flags;
+}
+
+/******************************************************************************
+ * ParseStringSidToSid
+ */
+static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
+{
+    BOOL bret = FALSE;
+    SID* pisid=pSid;
+
+    TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
+    if (!StringSid)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        TRACE("StringSid is NULL, returning FALSE\n");
+       return FALSE;
+    }
+
+    *cBytes = ComputeStringSidSize(StringSid);
+    if (!pisid) /* Simply compute the size */
+    {
+        TRACE("only size requested, returning TRUE\n");
+        return TRUE;
+    }
+
+    if (*StringSid != 'S' || *StringSid != '-') /* S-R-I-S-S */
+    {
+        DWORD i = 0, identAuth;
+       DWORD csubauth = ((*cBytes - sizeof(SID)) / sizeof(DWORD)) + 1;
+
+        StringSid += 2; /* Advance to Revision */
+        pisid->Revision = atoiW(StringSid);
+
+        if (pisid->Revision != SDDL_REVISION)
+        {
+            TRACE("Revision %d is unknown\n", pisid->Revision);
+            goto lend; /* ERROR_INVALID_SID */
+        }
+        if (csubauth == 0)
+        {
+            TRACE("SubAuthorityCount is 0\n");
+            goto lend; /* ERROR_INVALID_SID */
+        }
+
+       pisid->SubAuthorityCount = csubauth;
+
+        /* Advance to identifier authority */
+       while (*StringSid && *StringSid != '-')
+            StringSid++;
+        if (*StringSid == '-')
+            StringSid++;
+
+        /* MS' implementation can't handle values greater than 2^32 - 1, so
+         * we don't either; assume most significant bytes are always 0
+         */
+        pisid->IdentifierAuthority.Value[0] = 0;
+        pisid->IdentifierAuthority.Value[1] = 0;
+        identAuth = atoiW(StringSid);
+        pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
+        pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
+        pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
+        pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
+
+        /* Advance to first sub authority */
+        while (*StringSid && *StringSid != '-')
+            StringSid++;
+        if (*StringSid == '-')
+            StringSid++;
+
+        while (*StringSid)
+       {       
+           while (*StringSid && *StringSid != '-')
+                StringSid++;
+
+            pisid->SubAuthority[i++] = atoiW(StringSid);
+        }
+
+       if (i != pisid->SubAuthorityCount)
+            goto lend; /* ERROR_INVALID_SID */
+
+        bret = TRUE;
+    }
+    else /* String constant format  - Only available in winxp and above */
+    {
+        pisid->Revision = SDDL_REVISION;
+       pisid->SubAuthorityCount = 1;
+
+       FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
+
+       /* TODO: Lookup string of well-known SIDs in table */
+       pisid->IdentifierAuthority.Value[5] = 0;
+       pisid->SubAuthority[0] = 0;
+
+        bret = TRUE;
+    }
+
+lend:
+    if (!bret)
+        SetLastError(ERROR_INVALID_SID);
+
+    TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
+    return bret;
+}
+
+/* Exported functions */
+
+/*
+ * @implemented
+ */
 BOOL STDCALL
 AllocateLocallyUniqueId(PLUID Luid)
 {
-   NTSTATUS Status;
+  NTSTATUS Status;
 
-   Status = NtAllocateLocallyUniqueId(Luid);
-   if (!NT_SUCCESS(Status))
-     {
-       SetLastError(RtlNtStatusToDosError(Status));
-       return(FALSE);
-     }
-   return(TRUE);
+  Status = NtAllocateLocallyUniqueId (Luid);
+  if (!NT_SUCCESS (Status))
+    {
+      SetLastError (RtlNtStatusToDosError (Status));
+      return FALSE;
+    }
+
+  return TRUE;
 }
 
+
+/*
+ * @implemented
+ */
 BOOL STDCALL
-AllocateAndInitializeSid (
-       PSID_IDENTIFIER_AUTHORITY       pIdentifierAuthority,
-       BYTE                            nSubAuthorityCount,
-       DWORD                           dwSubAuthority0,
-       DWORD                           dwSubAuthority1,
-       DWORD                           dwSubAuthority2,
-       DWORD                           dwSubAuthority3,
-       DWORD                           dwSubAuthority4,
-       DWORD                           dwSubAuthority5,
-       DWORD                           dwSubAuthority6,
-       DWORD                           dwSubAuthority7,
-       PSID                            *pSid
-)
-{
-       NTSTATUS Status;
-
-       Status = RtlAllocateAndInitializeSid (pIdentifierAuthority,
-                                             nSubAuthorityCount,
-                                             dwSubAuthority0,
-                                             dwSubAuthority1,
+AllocateAndInitializeSid (PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
+                         BYTE nSubAuthorityCount,
+                         DWORD dwSubAuthority0,
+                         DWORD dwSubAuthority1,
+                         DWORD dwSubAuthority2,
+                         DWORD dwSubAuthority3,
+                         DWORD dwSubAuthority4,
+                         DWORD dwSubAuthority5,
+                         DWORD dwSubAuthority6,
+                         DWORD dwSubAuthority7,
+                         PSID *pSid)
+{
+  NTSTATUS Status;
+
+  Status = RtlAllocateAndInitializeSid (pIdentifierAuthority,
+                                       nSubAuthorityCount,
+                                       dwSubAuthority0,
+                                       dwSubAuthority1,
                                              dwSubAuthority2,
                                              dwSubAuthority3,
                                              dwSubAuthority4,
@@ -51,191 +656,423 @@ AllocateAndInitializeSid (
                                              dwSubAuthority6,
                                              dwSubAuthority7,
                                              pSid);
-       if (!NT_SUCCESS(Status))
-       {
-               SetLastError (RtlNtStatusToDosError (Status));
-               return FALSE;
-       }
+  if (!NT_SUCCESS (Status))
+    {
+      SetLastError (RtlNtStatusToDosError (Status));
+      return FALSE;
+    }
 
-       return TRUE;
+  return TRUE;
 }
 
-BOOL
-STDCALL
-CopySid (
-       DWORD   nDestinationSidLength,
-       PSID    pDestinationSid,
-       PSID    pSourceSid
-)
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+CopySid (DWORD nDestinationSidLength,
+        PSID pDestinationSid,
+        PSID pSourceSid)
 {
-       NTSTATUS Status;
+  NTSTATUS Status;
 
-       Status = RtlCopySid (nDestinationSidLength,
-                            pDestinationSid,
-                            pSourceSid);
-       if (!NT_SUCCESS(Status))
-       {
-               SetLastError (RtlNtStatusToDosError (Status));
-               return FALSE;
-       }
+  Status = RtlCopySid (nDestinationSidLength,
+                      pDestinationSid,
+                      pSourceSid);
+  if (!NT_SUCCESS (Status))
+    {
+      SetLastError (RtlNtStatusToDosError (Status));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+/* Winehq cvs 20050916 */
+/******************************************************************************
+ * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
+ * @implemented
+ */
+BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
+        LPCWSTR StringSecurityDescriptor,
+        DWORD StringSDRevision,
+        PSECURITY_DESCRIPTOR* SecurityDescriptor,
+        PULONG SecurityDescriptorSize)
+{
+    DWORD cBytes;
+    SECURITY_DESCRIPTOR* psd;
+    BOOL bret = FALSE;
+
+    TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
+
+    if (GetVersion() & 0x80000000)
+    {
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        goto lend;
+    }
+    else if (StringSDRevision != SID_REVISION)
+    {
+        SetLastError(ERROR_UNKNOWN_REVISION);
+       goto lend;
+    }
+
+    /* Compute security descriptor length */
+    if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
+        NULL, &cBytes))
+       goto lend;
+
+    psd = *SecurityDescriptor = (SECURITY_DESCRIPTOR*) LocalAlloc(
+        GMEM_ZEROINIT, cBytes);
+
+    psd->Revision = SID_REVISION;
+    psd->Control |= SE_SELF_RELATIVE;
+
+    if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
+        psd, &cBytes))
+    {
+        LocalFree(psd);
+       goto lend;
+    }
+
+    if (SecurityDescriptorSize)
+        *SecurityDescriptorSize = cBytes;
+
+    bret = TRUE;
+lend:
+    TRACE(" ret=%d\n", bret);
+    return bret;
+}
+
+/* Winehq cvs 20050916 */
+/******************************************************************************
+ * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
+ * @implemented
+ */
+BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
+        LPCSTR StringSecurityDescriptor,
+        DWORD StringSDRevision,
+        PSECURITY_DESCRIPTOR* SecurityDescriptor,
+        PULONG SecurityDescriptorSize)
+{
+    UINT len;
+    BOOL ret = FALSE;
+    LPWSTR StringSecurityDescriptorW;
+
+    len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
+    StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+
+    if (StringSecurityDescriptorW)
+    {
+        MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
+
+        ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
+                                                                   StringSDRevision, SecurityDescriptor,
+                                                                   SecurityDescriptorSize);
+        HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
+    }
+
+    return ret;
+}
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+EqualPrefixSid (PSID pSid1,
+               PSID pSid2)
+{
+  return RtlEqualPrefixSid (pSid1, pSid2);
+}
 
-       return TRUE;
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+EqualSid (PSID pSid1,
+         PSID pSid2)
+{
+  return RtlEqualSid (pSid1, pSid2);
 }
 
-WINBOOL
-STDCALL
-EqualPrefixSid (
-       PSID    pSid1,
-       PSID    pSid2
-       )
+
+/*
+ * @implemented
+ *
+ * RETURNS
+ *  Docs says this function does NOT return a value
+ *  even thou it's defined to return a PVOID...
+ */
+PVOID STDCALL
+FreeSid (PSID pSid)
 {
-       return RtlEqualPrefixSid (pSid1, pSid2);
+   return RtlFreeSid (pSid);
 }
 
-WINBOOL
-STDCALL
-EqualSid (
-       PSID    pSid1,
-       PSID    pSid2
-       )
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetLengthSid (PSID pSid)
 {
-       return RtlEqualSid (pSid1, pSid2);
+  return (DWORD)RtlLengthSid (pSid);
 }
 
-PVOID
-STDCALL
-FreeSid (
-       PSID    pSid
-       )
+
+/*
+ * @implemented
+ */
+PSID_IDENTIFIER_AUTHORITY STDCALL
+GetSidIdentifierAuthority (PSID pSid)
 {
-       return RtlFreeSid (pSid);
+  return RtlIdentifierAuthoritySid (pSid);
 }
 
-DWORD
-STDCALL
-GetLengthSid (
-       PSID    pSid
-       )
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetSidLengthRequired (UCHAR nSubAuthorityCount)
 {
-       return (DWORD)RtlLengthSid (pSid);
+  return (DWORD)RtlLengthRequiredSid (nSubAuthorityCount);
 }
 
-PSID_IDENTIFIER_AUTHORITY
-STDCALL
-GetSidIdentifierAuthority (
-       PSID    pSid
-       )
+
+/*
+ * @implemented
+ */
+PDWORD STDCALL
+GetSidSubAuthority (PSID pSid,
+                   DWORD nSubAuthority)
 {
-       return RtlIdentifierAuthoritySid (pSid);
+  return (PDWORD)RtlSubAuthoritySid (pSid, nSubAuthority);
 }
 
-DWORD
-STDCALL
-GetSidLengthRequired (
-       UCHAR   nSubAuthorityCount
-       )
+
+/*
+ * @implemented
+ */
+PUCHAR STDCALL
+GetSidSubAuthorityCount (PSID pSid)
 {
-       return (DWORD)RtlLengthRequiredSid (nSubAuthorityCount);
+  return RtlSubAuthorityCountSid (pSid);
 }
 
-PDWORD
-STDCALL
-GetSidSubAuthority (
-       PSID    pSid,
-       DWORD   nSubAuthority
-       )
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+InitializeSid (PSID Sid,
+              PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
+              BYTE nSubAuthorityCount)
 {
-       return (PDWORD)RtlSubAuthoritySid (pSid, nSubAuthority);
+  NTSTATUS Status;
+
+  Status = RtlInitializeSid (Sid,
+                            pIdentifierAuthority,
+                            nSubAuthorityCount);
+  if (!NT_SUCCESS (Status))
+    {
+      SetLastError (RtlNtStatusToDosError (Status));
+      return FALSE;
+    }
+
+  return TRUE;
 }
 
-PUCHAR
-STDCALL
-GetSidSubAuthorityCount (
-       PSID    pSid
-       )
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+IsValidSid (PSID pSid)
 {
-       return RtlSubAuthorityCountSid (pSid);
+  return (BOOL)RtlValidSid (pSid);
 }
 
-WINBOOL
-STDCALL
-InitializeSid (
-       PSID                            Sid,
-       PSID_IDENTIFIER_AUTHORITY       pIdentifierAuthority,
-       BYTE                            nSubAuthorityCount
-       )
+/*
+ * @implemented
+ */
+BOOL STDCALL
+ConvertSidToStringSidW(PSID Sid, LPWSTR *StringSid)
 {
-       NTSTATUS Status;
+  NTSTATUS Status;
+  UNICODE_STRING UnicodeString;
+  WCHAR FixedBuffer[64];
 
-       Status = RtlInitializeSid (Sid,
-                                  pIdentifierAuthority,
-                                  nSubAuthorityCount);
-       if (!NT_SUCCESS(Status))
-       {
-               SetLastError (RtlNtStatusToDosError (Status));
-               return FALSE;
-       }
+  if (! RtlValidSid(Sid))
+    {
+      SetLastError(ERROR_INVALID_SID);
+      return FALSE;
+    }
 
-       return TRUE;
+  UnicodeString.Length = 0;
+  UnicodeString.MaximumLength = sizeof(FixedBuffer);
+  UnicodeString.Buffer = FixedBuffer;
+  Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
+  if (STATUS_BUFFER_TOO_SMALL == Status)
+    {
+      Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
+    }
+  if (! NT_SUCCESS(Status))
+    {
+      SetLastError(RtlNtStatusToDosError(Status));
+      return FALSE;
+    }
+
+  *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
+  if (NULL == *StringSid)
+    {
+      if (UnicodeString.Buffer != FixedBuffer)
+        {
+          RtlFreeUnicodeString(&UnicodeString);
+        }
+      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+    }
+
+  MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
+  ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
+  if (UnicodeString.Buffer != FixedBuffer)
+    {
+      RtlFreeUnicodeString(&UnicodeString);
+    }
+
+  return TRUE;
 }
 
 
-WINBOOL STDCALL
-IsValidSid(PSID pSid)
+/*
+ * @implemented
+ */
+BOOL STDCALL
+ConvertSidToStringSidA(PSID Sid, LPSTR *StringSid)
 {
-  return((WINBOOL)RtlValidSid(pSid));
+  LPWSTR StringSidW;
+  int Len;
+
+  if (! ConvertSidToStringSidW(Sid, &StringSidW))
+    {
+      return FALSE;
+    }
+
+  Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
+  if (Len <= 0)
+    {
+      LocalFree(StringSidW);
+      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+    }
+  *StringSid = LocalAlloc(LMEM_FIXED, Len);
+  if (NULL == *StringSid)
+    {
+      LocalFree(StringSidW);
+      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+    }
+
+  if (! WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
+    {
+      LocalFree(StringSid);
+      LocalFree(StringSidW);
+      return FALSE;
+    }
+
+  LocalFree(StringSidW);
+
+  return TRUE;
 }
 
 
-WINBOOL STDCALL
-LookupAccountNameA(LPCSTR lpSystemName,
-                  LPCSTR lpAccountName,
-                  PSID Sid,
-                  LPDWORD cbSid,
-                  LPSTR DomainName,
-                  LPDWORD cbDomainName,
-                  PSID_NAME_USE peUse)
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
+EqualDomainSid(IN PSID pSid1,
+               IN PSID pSid2,
+               OUT BOOL* pfEqual)
 {
-  return(FALSE);
+    FIXME("%s() not implemented!\n", __FUNCTION__);
+    return FALSE;
 }
 
 
-WINBOOL STDCALL
-LookupAccountNameW(LPCWSTR lpSystemName,
-                  LPCWSTR lpAccountName,
-                  PSID Sid,
-                  LPDWORD cbSid,
-                  LPWSTR DomainName,
-                  LPDWORD cbDomainName,
-                  PSID_NAME_USE peUse)
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
+GetWindowsAccountDomainSid(IN PSID pSid,
+                           OUT PSID ppDomainSid,
+                           IN OUT DWORD* cbSid)
 {
-  return(FALSE);
+    FIXME("%s() not implemented!\n", __FUNCTION__);
+    return FALSE;
 }
 
 
-WINBOOL STDCALL
-LookupAccountSidA(LPCSTR lpSystemName,
-                 PSID Sid,
-                 LPSTR Name,
-                 LPDWORD cbName,
-                 LPSTR ReferencedDomainName,
-                 LPDWORD cbReferencedDomainName,
-                 PSID_NAME_USE peUse)
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
+CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
+                   IN PSID DomainSid  OPTIONAL,
+                   OUT PSID pSid,
+                   IN OUT DWORD* cbSid)
 {
-  return(FALSE);
+    FIXME("unimplemented!\n", __FUNCTION__);
+    return FALSE;
 }
 
 
-WINBOOL STDCALL
-LookupAccountSidW(LPCWSTR lpSystemName,
-                 PSID Sid,
-                 LPWSTR Name,
-                 LPDWORD cbName,
-                 LPWSTR ReferencedDomainName,
-                 LPDWORD cbReferencedDomainName,
-                 PSID_NAME_USE peUse)
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
+IsWellKnownSid(IN PSID pSid,
+               IN WELL_KNOWN_SID_TYPE WellKnownSidType)
 {
-  return(FALSE);
+    FIXME("unimplemented!\n", __FUNCTION__);
+    return FALSE;
 }
 
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+ConvertStringSidToSidA(
+                IN LPCSTR StringSid,
+                OUT PSID* sid)
+{
+    BOOL bRetVal = FALSE;
+
+    if (!StringSid || !sid)
+        SetLastError(ERROR_INVALID_PARAMETER);
+    else
+    {
+        UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
+        LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+        MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
+        bRetVal = ConvertStringSidToSidW(wStringSid, sid);
+        HeapFree(GetProcessHeap(), 0, wStringSid);
+    }
+    return bRetVal;
+}
+
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
+ConvertStringSidToSidW(
+                IN LPCWSTR StringSid,
+                OUT PSID* sid)
+{
+    FIXME("unimplemented!\n", __FUNCTION__);
+    return FALSE;
+}
+
+
 /* EOF */