[PATCH] advapi32: Move string SID/SD conversion functions to sechost.

Zebediah Figura z.figura12 at gmail.com
Fri May 1 16:51:40 CDT 2020


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/advapi32/advapi32.spec |    8 +-
 dlls/advapi32/security.c    | 1314 -----------------------------------
 dlls/sechost/Makefile.in    |    1 +
 dlls/sechost/sechost.spec   |    8 +-
 dlls/sechost/security.c     | 1247 +++++++++++++++++++++++++++++++++
 5 files changed, 1256 insertions(+), 1322 deletions(-)
 create mode 100644 dlls/sechost/security.c

diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec
index cd4dedac74..ac8ea6268a 100644
--- a/dlls/advapi32/advapi32.spec
+++ b/dlls/advapi32/advapi32.spec
@@ -120,17 +120,17 @@
 # @ stub ConvertSecurityDescriptorToAccessNamedW
 # @ stub ConvertSecurityDescriptorToAccessW
 @ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorA(ptr long long ptr ptr)
-@ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorW(ptr long long ptr ptr)
+@ stdcall -import ConvertSecurityDescriptorToStringSecurityDescriptorW(ptr long long ptr ptr)
 @ stdcall ConvertSidToStringSidA(ptr ptr)
-@ stdcall ConvertSidToStringSidW(ptr ptr)
+@ stdcall -import ConvertSidToStringSidW(ptr ptr)
 # @ stub ConvertStringSDToSDDomainA
 # @ stub ConvertStringSDToSDDomainW
 # @ stub ConvertStringSDToSDRootDomainA
 # @ stub ConvertStringSDToSDRootDomainW
 @ stdcall ConvertStringSecurityDescriptorToSecurityDescriptorA(str long ptr ptr)
-@ stdcall ConvertStringSecurityDescriptorToSecurityDescriptorW(wstr long ptr ptr)
+@ stdcall -import ConvertStringSecurityDescriptorToSecurityDescriptorW(wstr long ptr ptr)
 @ stdcall ConvertStringSidToSidA(ptr ptr)
-@ stdcall ConvertStringSidToSidW(ptr ptr)
+@ stdcall -import ConvertStringSidToSidW(ptr ptr)
 @ stdcall -import ConvertToAutoInheritPrivateObjectSecurity(ptr ptr ptr ptr long ptr)
 @ stdcall -import CopySid(long ptr ptr)
 # @ stub CreateCodeAuthzLevel
diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c
index d3c9a6c1e2..fe2f0d9266 100644
--- a/dlls/advapi32/security.c
+++ b/dlls/advapi32/security.c
@@ -47,15 +47,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
 
-static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
 static DWORD trustee_to_sid(DWORD nDestinationSidLength, PSID pDestinationSid, PTRUSTEEW pTrustee);
 
-typedef struct _ACEFLAG
-{
-   LPCWSTR wstr;
-   DWORD value;
-} ACEFLAG, *LPACEFLAG;
-
 typedef struct _MAX_SID
 {
     /* same fields as struct _SID */
@@ -65,97 +58,6 @@ typedef struct _MAX_SID
     DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
 } MAX_SID;
 
-typedef struct WELLKNOWNSID
-{
-    WCHAR wstr[2];
-    WELL_KNOWN_SID_TYPE Type;
-    MAX_SID Sid;
-} WELLKNOWNSID;
-
-static const WELLKNOWNSID WellKnownSids[] =
-{
-    { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
-    { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
-    { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
-    { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
-    { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
-    { {'O','W'}, WinCreatorOwnerRightsSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RIGHTS_RID } } },
-    { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
-    { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
-    { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
-    { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
-    { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
-    { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
-    { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
-    { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
-    { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
-    { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
-    { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
-    { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
-    { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
-    { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
-    { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
-    { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
-    { {0,0}, WinLogonIdsSid, { SID_REVISION, SECURITY_LOGON_IDS_RID_COUNT, { SECURITY_NT_AUTHORITY }, { SECURITY_LOGON_IDS_RID } } },
-    { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
-    { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
-    { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
-    { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
-    { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
-    { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
-    { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
-    { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
-    { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
-    { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
-    { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
-    { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
-    { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
-    { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
-    { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
-    { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
-    { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
-    { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
-    { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
-    { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
-    { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
-    { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS  } } },
-    { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
-    { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
-    { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
-    { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
-    { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
-    { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
-    { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
-    { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
-    { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
-    { {'A','C'}, WinBuiltinAnyPackageSid, { SID_REVISION, 2, { SECURITY_APP_PACKAGE_AUTHORITY }, { SECURITY_APP_PACKAGE_BASE_RID, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE } } },
-};
-
-/* these SIDs must be constructed as relative to some domain - only the RID is well-known */
-typedef struct WELLKNOWNRID
-{
-    WCHAR wstr[2];
-    WELL_KNOWN_SID_TYPE Type;
-    DWORD Rid;
-} WELLKNOWNRID;
-
-static const WELLKNOWNRID WellKnownRids[] = {
-    { {'L','A'}, WinAccountAdministratorSid,    DOMAIN_USER_RID_ADMIN },
-    { {'L','G'}, WinAccountGuestSid,            DOMAIN_USER_RID_GUEST },
-    { {0,0}, WinAccountKrbtgtSid,           DOMAIN_USER_RID_KRBTGT },
-    { {'D','A'}, WinAccountDomainAdminsSid,     DOMAIN_GROUP_RID_ADMINS },
-    { {'D','U'}, WinAccountDomainUsersSid,      DOMAIN_GROUP_RID_USERS },
-    { {'D','G'}, WinAccountDomainGuestsSid,     DOMAIN_GROUP_RID_GUESTS },
-    { {'D','C'}, WinAccountComputersSid,        DOMAIN_GROUP_RID_COMPUTERS },
-    { {'D','D'}, WinAccountControllersSid,      DOMAIN_GROUP_RID_CONTROLLERS },
-    { {'C','A'}, WinAccountCertAdminsSid,       DOMAIN_GROUP_RID_CERT_ADMINS },
-    { {'S','A'}, WinAccountSchemaAdminsSid,     DOMAIN_GROUP_RID_SCHEMA_ADMINS },
-    { {'E','A'}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
-    { {'P','A'}, WinAccountPolicyAdminsSid,     DOMAIN_GROUP_RID_POLICY_ADMINS },
-    { {'R','S'}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
-};
-
-
 typedef struct _AccountSid {
     WELL_KNOWN_SID_TYPE type;
     LPCWSTR account;
@@ -275,69 +177,6 @@ static const AccountSid ACCOUNT_SIDS[] = {
     { WinBuiltinPerfLoggingUsersSid, Performance_Log_Users, BUILTIN, SidTypeAlias },
     { WinBuiltinAnyPackageSid, ALL_APPLICATION_PACKAGES, APPLICATION_PACKAGE_AUTHORITY, SidTypeWellKnownGroup },
 };
-/*
- * 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_READ_PROPERTY[]    = {'R','P',0};
-static const WCHAR SDDL_WRITE_PROPERTY[]   = {'W','P',0};
-static const WCHAR SDDL_CREATE_CHILD[]     = {'C','C',0};
-static const WCHAR SDDL_DELETE_CHILD[]     = {'D','C',0};
-static const WCHAR SDDL_LIST_CHILDREN[]    = {'L','C',0};
-static const WCHAR SDDL_SELF_WRITE[]       = {'S','W',0};
-static const WCHAR SDDL_LIST_OBJECT[]      = {'L','O',0};
-static const WCHAR SDDL_DELETE_TREE[]      = {'D','T',0};
-static const WCHAR SDDL_CONTROL_ACCESS[]   = {'C','R',0};
-
-static const WCHAR SDDL_FILE_ALL[]         = {'F','A',0};
-static const WCHAR SDDL_FILE_READ[]        = {'F','R',0};
-static const WCHAR SDDL_FILE_WRITE[]       = {'F','W',0};
-static const WCHAR SDDL_FILE_EXECUTE[]     = {'F','X',0};
-
-static const WCHAR SDDL_KEY_ALL[]          = {'K','A',0};
-static const WCHAR SDDL_KEY_READ[]         = {'K','R',0};
-static const WCHAR SDDL_KEY_WRITE[]        = {'K','W',0};
-static const WCHAR SDDL_KEY_EXECUTE[]      = {'K','X',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};
-
-static const WCHAR SDDL_NO_READ_UP[]       = {'N','R',0};
-static const WCHAR SDDL_NO_WRITE_UP[]      = {'N','W',0};
-static const WCHAR SDDL_NO_EXECUTE_UP[]    = {'N','X',0};
-
-/*
- * ACL flags
- */
-static const WCHAR SDDL_PROTECTED[]             = {'P',0};
-static const WCHAR SDDL_AUTO_INHERIT_REQ[]      = {'A','R',0};
-static const WCHAR SDDL_AUTO_INHERITED[]        = {'A','I',0};
-
-/*
- * ACE types
- */
-static const WCHAR SDDL_ACCESS_ALLOWED[]        = {'A',0};
-static const WCHAR SDDL_ACCESS_DENIED[]         = {'D',0};
-static const WCHAR SDDL_AUDIT[]                 = {'A','U',0};
-static const WCHAR SDDL_ALARM[]                 = {'A','L',0};
-static const WCHAR SDDL_MANDATORY_LABEL[]       = {'M','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};
 
 const char * debugstr_sid(PSID sid)
 {
@@ -2807,481 +2646,6 @@ DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCE
 
 }
 
-/******************************************************************************
- * ParseAclStringFlags
- */
-static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
-{
-    DWORD flags = 0;
-    LPCWSTR szAcl = *StringAcl;
-
-    while (*szAcl && *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;
-}
-
-/******************************************************************************
- * ParseAceStringType
- */
-static const ACEFLAG AceType[] =
-{
-    { SDDL_ALARM,          SYSTEM_ALARM_ACE_TYPE },
-    { SDDL_AUDIT,          SYSTEM_AUDIT_ACE_TYPE },
-    { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
-    { SDDL_ACCESS_DENIED,  ACCESS_DENIED_ACE_TYPE },
-    { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_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;
-    const ACEFLAG *lpaf = AceType;
-
-    while (*szAcl == ' ')
-        szAcl++;
-
-    while (lpaf->wstr &&
-        (len = strlenW(lpaf->wstr)) &&
-        strncmpW(lpaf->wstr, szAcl, len))
-        lpaf++;
-
-    if (!lpaf->wstr)
-        return 0;
-
-    *StringAcl = szAcl + len;
-    return lpaf->value;
-}
-
-
-/******************************************************************************
- * ParseAceStringFlags
- */
-static const 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 == ' ')
-        szAcl++;
-
-    while (*szAcl != ';')
-    {
-        const ACEFLAG *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
- */
-static const 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 },
-
-    { SDDL_READ_PROPERTY,   ADS_RIGHT_DS_READ_PROP},
-    { SDDL_WRITE_PROPERTY,  ADS_RIGHT_DS_WRITE_PROP},
-    { SDDL_CREATE_CHILD,    ADS_RIGHT_DS_CREATE_CHILD},
-    { SDDL_DELETE_CHILD,    ADS_RIGHT_DS_DELETE_CHILD},
-    { SDDL_LIST_CHILDREN,   ADS_RIGHT_ACTRL_DS_LIST},
-    { SDDL_SELF_WRITE,      ADS_RIGHT_DS_SELF},
-    { SDDL_LIST_OBJECT,     ADS_RIGHT_DS_LIST_OBJECT},
-    { SDDL_DELETE_TREE,     ADS_RIGHT_DS_DELETE_TREE},
-    { SDDL_CONTROL_ACCESS,  ADS_RIGHT_DS_CONTROL_ACCESS},
-
-    { SDDL_FILE_ALL,        FILE_ALL_ACCESS },
-    { SDDL_FILE_READ,       FILE_GENERIC_READ },
-    { SDDL_FILE_WRITE,      FILE_GENERIC_WRITE },
-    { SDDL_FILE_EXECUTE,    FILE_GENERIC_EXECUTE },
-
-    { SDDL_KEY_ALL,         KEY_ALL_ACCESS },
-    { SDDL_KEY_READ,        KEY_READ },
-    { SDDL_KEY_WRITE,       KEY_WRITE },
-    { SDDL_KEY_EXECUTE,     KEY_EXECUTE },
-
-    { SDDL_NO_READ_UP,      SYSTEM_MANDATORY_LABEL_NO_READ_UP },
-    { SDDL_NO_WRITE_UP,     SYSTEM_MANDATORY_LABEL_NO_WRITE_UP },
-    { SDDL_NO_EXECUTE_UP,   SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP },
-    { NULL, 0 },
-};
-
-static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
-{
-    UINT len = 0;
-    DWORD rights = 0;
-    LPCWSTR szAcl = *StringAcl;
-
-    while (*szAcl == ' ')
-        szAcl++;
-
-    if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
-    {
-        LPCWSTR p = szAcl;
-
-	while (*p && *p != ';')
-            p++;
-
-	if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
-	{
-	    rights = strtoulW(szAcl, NULL, 16);
-	    szAcl = p;
-	}
-	else
-            WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
-    }
-    else
-    {
-        while (*szAcl != ';')
-        {
-            const ACEFLAG *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);
-    DWORD acesize = 0;
-    DWORD acecount = 0;
-    PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
-    DWORD error = ERROR_INVALID_ACL;
-
-    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) (pAcl + 1);
-
-    /* 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 != ';')
-        {
-            error = RPC_S_INVALID_STRING_UUID;
-            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 */
-        while (*StringAcl == ' ')
-            StringAcl++;
-        if (*StringAcl != ';')
-        {
-            FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
-            goto lerr;
-        }
-        StringAcl++;
-
-        /* Parse ACE inherit object guid */
-        while (*StringAcl == ' ')
-            StringAcl++;
-        if (*StringAcl != ';')
-        {
-            FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
-            goto lerr;
-        }
-        StringAcl++;
-
-        /* Parse ACE account sid */
-        if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
-	{
-            while (*StringAcl && *StringAcl != ')')
-                StringAcl++;
-	}
-
-        if (*StringAcl != ')')
-            goto lerr;
-        StringAcl++;
-
-        acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
-        length += acesize;
-        if (pAce)
-        {
-            pAce->Header.AceSize = acesize;
-            pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
-        }
-        acecount++;
-    }
-
-    *cBytes = length;
-
-    if (length > 0xffff)
-    {
-        ERR("ACL too large\n");
-        goto lerr;
-    }
-
-    if (pAcl)
-    {
-        pAcl->AclRevision = ACL_REVISION;
-        pAcl->Sbz1 = 0;
-        pAcl->AclSize = length;
-        pAcl->AceCount = acecount;
-        pAcl->Sbz2 = 0;
-    }
-    return TRUE;
-
-lerr:
-    SetLastError(error);
-    WARN("Invalid ACE string format\n");
-    return FALSE;
-}
-
-
-/******************************************************************************
- * ParseStringSecurityDescriptorToSecurityDescriptor
- */
-static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
-    LPCWSTR StringSecurityDescriptor,
-    SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
-    LPDWORD cBytes)
-{
-    BOOL bret = FALSE;
-    WCHAR toktype;
-    WCHAR *tok;
-    LPCWSTR lptoken;
-    LPBYTE lpNext = NULL;
-    DWORD len;
-
-    *cBytes = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
-
-    tok = heap_alloc( (lstrlenW(StringSecurityDescriptor) + 1) * sizeof(WCHAR));
-
-    if (SecurityDescriptor)
-        lpNext = (LPBYTE)(SecurityDescriptor + 1);
-
-    while (*StringSecurityDescriptor == ' ')
-        StringSecurityDescriptor++;
-
-    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, lpNext, &bytes))
-                    goto lend;
-
-                if (SecurityDescriptor)
-                {
-                    SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
-                    lpNext += bytes; /* Advance to next token */
-                }
-
-		*cBytes += bytes;
-
-                break;
-            }
-
-            case 'G':
-            {
-                DWORD bytes;
-
-                if (!ParseStringSidToSid(tok, lpNext, &bytes))
-                    goto lend;
-
-                if (SecurityDescriptor)
-                {
-                    SecurityDescriptor->Group = lpNext - (LPBYTE)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 = lpNext - (LPBYTE)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 = lpNext - (LPBYTE)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:
-    heap_free(tok);
-    return bret;
-}
-
 /******************************************************************************
  * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
  */
@@ -3309,471 +2673,6 @@ BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
     return ret;
 }
 
-/******************************************************************************
- * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
- */
-BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
-        LPCWSTR StringSecurityDescriptor,
-        DWORD StringSDRevision,
-        PSECURITY_DESCRIPTOR* SecurityDescriptor,
-        PULONG SecurityDescriptorSize)
-{
-    DWORD cBytes;
-    SECURITY_DESCRIPTOR* psd;
-    BOOL bret = FALSE;
-
-    TRACE("%s, %u, %p, %p\n", debugstr_w(StringSecurityDescriptor), StringSDRevision,
-          SecurityDescriptor, SecurityDescriptorSize);
-
-    if (GetVersion() & 0x80000000)
-    {
-        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-        goto lend;
-    }
-    else if (!StringSecurityDescriptor || !SecurityDescriptor)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        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 = LocalAlloc(GMEM_ZEROINIT, cBytes);
-    if (!psd) goto lend;
-
-    psd->Revision = SID_REVISION;
-    psd->Control |= SE_SELF_RELATIVE;
-
-    if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
-             (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
-    {
-        LocalFree(psd);
-	goto lend;
-    }
-
-    if (SecurityDescriptorSize)
-        *SecurityDescriptorSize = cBytes;
-
-    bret = TRUE;
- 
-lend:
-    TRACE(" ret=%d\n", bret);
-    return bret;
-}
-
-static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
-{
-    if (cch == -1)
-        cch = strlenW(string);
-
-    if (plen)
-        *plen += cch;
-
-    if (pwptr)
-    {
-        memcpy(*pwptr, string, sizeof(WCHAR)*cch);
-        *pwptr += cch;
-    }
-}
-
-static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
-{
-    static const WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
-    static const WCHAR subauthfmt[] = { '-','%','u',0 };
-    DWORD i;
-    WCHAR buf[26];
-    SID *pisid = psid;
-
-    if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
-    {
-        SetLastError(ERROR_INVALID_SID);
-        return FALSE;
-    }
-
-    if (pisid->IdentifierAuthority.Value[0] ||
-     pisid->IdentifierAuthority.Value[1])
-    {
-        FIXME("not matching MS' bugs\n");
-        SetLastError(ERROR_INVALID_SID);
-        return FALSE;
-    }
-
-    sprintfW( buf, fmt, pisid->Revision,
-        MAKELONG(
-            MAKEWORD( pisid->IdentifierAuthority.Value[5],
-                    pisid->IdentifierAuthority.Value[4] ),
-            MAKEWORD( pisid->IdentifierAuthority.Value[3],
-                    pisid->IdentifierAuthority.Value[2] )
-        ) );
-    DumpString(buf, -1, pwptr, plen);
-
-    for( i=0; i<pisid->SubAuthorityCount; i++ )
-    {
-        sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
-        DumpString(buf, -1, pwptr, plen);
-    }
-    return TRUE;
-}
-
-static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
-{
-    size_t i;
-    for (i = 0; i < ARRAY_SIZE(WellKnownSids); i++)
-    {
-        if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
-        {
-            DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
-            return TRUE;
-        }
-    }
-
-    return DumpSidNumeric(psid, pwptr, plen);
-}
-
-static const LPCWSTR AceRightBitNames[32] = {
-        SDDL_CREATE_CHILD,        /*  0 */
-        SDDL_DELETE_CHILD,
-        SDDL_LIST_CHILDREN,
-        SDDL_SELF_WRITE,
-        SDDL_READ_PROPERTY,       /*  4 */
-        SDDL_WRITE_PROPERTY,
-        SDDL_DELETE_TREE,
-        SDDL_LIST_OBJECT,
-        SDDL_CONTROL_ACCESS,      /*  8 */
-        NULL,
-        NULL,
-        NULL,
-        NULL,                     /* 12 */
-        NULL,
-        NULL,
-        NULL,
-        SDDL_STANDARD_DELETE,     /* 16 */
-        SDDL_READ_CONTROL,
-        SDDL_WRITE_DAC,
-        SDDL_WRITE_OWNER,
-        NULL,                     /* 20 */
-        NULL,
-        NULL,
-        NULL,
-        NULL,                     /* 24 */
-        NULL,
-        NULL,
-        NULL,
-        SDDL_GENERIC_ALL,         /* 28 */
-        SDDL_GENERIC_EXECUTE,
-        SDDL_GENERIC_WRITE,
-        SDDL_GENERIC_READ
-};
-
-static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
-{
-    static const WCHAR fmtW[] = {'0','x','%','x',0};
-    WCHAR buf[15];
-    size_t i;
-
-    if (mask == 0)
-        return;
-
-    /* first check if the right have name */
-    for (i = 0; i < ARRAY_SIZE(AceRights); i++)
-    {
-        if (AceRights[i].wstr == NULL)
-            break;
-        if (mask == AceRights[i].value)
-        {
-            DumpString(AceRights[i].wstr, -1, pwptr, plen);
-            return;
-        }
-    }
-
-    /* then check if it can be built from bit names */
-    for (i = 0; i < 32; i++)
-    {
-        if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
-        {
-            /* can't be built from bit names */
-            sprintfW(buf, fmtW, mask);
-            DumpString(buf, -1, pwptr, plen);
-            return;
-        }
-    }
-
-    /* build from bit names */
-    for (i = 0; i < 32; i++)
-        if (mask & (1 << i))
-            DumpString(AceRightBitNames[i], -1, pwptr, plen);
-}
-
-static inline BOOL is_object_ace(BYTE AceType)
-{
-    switch (AceType)
-    {
-    case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
-    case ACCESS_DENIED_OBJECT_ACE_TYPE:
-    case ACCESS_AUDIT_OBJECT_ACE_TYPE:
-    case ACCESS_ALARM_OBJECT_ACE_TYPE:
-    case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
-    case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
-    case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
-    case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE:
-        return TRUE;
-
-    default: return FALSE;
-    }
-}
-
-static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
-{
-    ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
-    static const WCHAR openbr = '(';
-    static const WCHAR closebr = ')';
-    static const WCHAR semicolon = ';';
-    DWORD *SidStart;
-
-    piace = pace;
-
-    if (piace->Header.AceType > ACCESS_MAX_MS_V5_ACE_TYPE || piace->Header.AceSize < sizeof(ACCESS_ALLOWED_ACE))
-    {
-        SetLastError(ERROR_INVALID_ACL);
-        return FALSE;
-    }
-
-    DumpString(&openbr, 1, pwptr, plen);
-    switch (piace->Header.AceType)
-    {
-        case ACCESS_ALLOWED_ACE_TYPE:
-            DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
-            break;
-        case ACCESS_DENIED_ACE_TYPE:
-            DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
-            break;
-        case SYSTEM_AUDIT_ACE_TYPE:
-            DumpString(SDDL_AUDIT, -1, pwptr, plen);
-            break;
-        case SYSTEM_ALARM_ACE_TYPE:
-            DumpString(SDDL_ALARM, -1, pwptr, plen);
-            break;
-    }
-    DumpString(&semicolon, 1, pwptr, plen);
-
-    if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
-        DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
-    if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
-        DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
-    if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
-        DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
-    if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
-        DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
-    if (piace->Header.AceFlags & INHERITED_ACE)
-        DumpString(SDDL_INHERITED, -1, pwptr, plen);
-    if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
-        DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
-    if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
-        DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
-    DumpString(&semicolon, 1, pwptr, plen);
-    DumpRights(piace->Mask, pwptr, plen);
-    DumpString(&semicolon, 1, pwptr, plen);
-    SidStart = &piace->SidStart;
-    if (is_object_ace(piace->Header.AceType))
-    {
-        ACCESS_ALLOWED_OBJECT_ACE *objace = pace;
-
-        SidStart++; /* Flags */
-        if (objace->Flags & ACE_OBJECT_TYPE_PRESENT)
-            SidStart += sizeof(GUID) / sizeof(*SidStart); /* ObjectType */
-        if (objace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
-            SidStart += sizeof(GUID) / sizeof(*SidStart); /* InheritedObjectType */
-    }
-    /* objects not supported */
-    DumpString(&semicolon, 1, pwptr, plen);
-    /* objects not supported */
-    DumpString(&semicolon, 1, pwptr, plen);
-    if (!DumpSid(SidStart, pwptr, plen))
-        return FALSE;
-    DumpString(&closebr, 1, pwptr, plen);
-    return TRUE;
-}
-
-static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
-{
-    WORD count;
-    UINT i;
-
-    if (protected)
-        DumpString(SDDL_PROTECTED, -1, pwptr, plen);
-    if (autoInheritReq)
-        DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
-    if (autoInherited)
-        DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
-
-    if (pacl == NULL)
-        return TRUE;
-
-    if (!IsValidAcl(pacl))
-        return FALSE;
-
-    count = pacl->AceCount;
-    for (i = 0; i < count; i++)
-    {
-        LPVOID ace;
-        if (!GetAce(pacl, i, &ace))
-            return FALSE;
-        if (!DumpAce(ace, pwptr, plen))
-            return FALSE;
-    }
-
-    return TRUE;
-}
-
-static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
-{
-    static const WCHAR prefix[] = {'O',':',0};
-    BOOL bDefaulted;
-    PSID psid;
-
-    if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
-        return FALSE;
-
-    if (psid == NULL)
-        return TRUE;
-
-    DumpString(prefix, -1, pwptr, plen);
-    if (!DumpSid(psid, pwptr, plen))
-        return FALSE;
-    return TRUE;
-}
-
-static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
-{
-    static const WCHAR prefix[] = {'G',':',0};
-    BOOL bDefaulted;
-    PSID psid;
-
-    if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
-        return FALSE;
-
-    if (psid == NULL)
-        return TRUE;
-
-    DumpString(prefix, -1, pwptr, plen);
-    if (!DumpSid(psid, pwptr, plen))
-        return FALSE;
-    return TRUE;
-}
-
-static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
-{
-    static const WCHAR dacl[] = {'D',':',0};
-    SECURITY_DESCRIPTOR_CONTROL control;
-    BOOL present, defaulted;
-    DWORD revision;
-    PACL pacl;
-
-    if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
-        return FALSE;
-
-    if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
-        return FALSE;
-
-    if (!present)
-        return TRUE;
-
-    DumpString(dacl, 2, pwptr, plen);
-    if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
-        return FALSE;
-    return TRUE;
-}
-
-static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
-{
-    static const WCHAR sacl[] = {'S',':',0};
-    SECURITY_DESCRIPTOR_CONTROL control;
-    BOOL present, defaulted;
-    DWORD revision;
-    PACL pacl;
-
-    if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
-        return FALSE;
-
-    if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
-        return FALSE;
-
-    if (!present)
-        return TRUE;
-
-    DumpString(sacl, 2, pwptr, plen);
-    if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
-        return FALSE;
-    return TRUE;
-}
-
-/******************************************************************************
- * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
- */
-BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
-{
-    ULONG len;
-    WCHAR *wptr, *wstr;
-
-    if (SDRevision != SDDL_REVISION_1)
-    {
-        ERR("Program requested unknown SDDL revision %d\n", SDRevision);
-        SetLastError(ERROR_UNKNOWN_REVISION);
-        return FALSE;
-    }
-
-    len = 0;
-    if (RequestedInformation & OWNER_SECURITY_INFORMATION)
-        if (!DumpOwner(SecurityDescriptor, NULL, &len))
-            return FALSE;
-    if (RequestedInformation & GROUP_SECURITY_INFORMATION)
-        if (!DumpGroup(SecurityDescriptor, NULL, &len))
-            return FALSE;
-    if (RequestedInformation & DACL_SECURITY_INFORMATION)
-        if (!DumpDacl(SecurityDescriptor, NULL, &len))
-            return FALSE;
-    if (RequestedInformation & SACL_SECURITY_INFORMATION)
-        if (!DumpSacl(SecurityDescriptor, NULL, &len))
-            return FALSE;
-
-    wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
-    if (RequestedInformation & OWNER_SECURITY_INFORMATION)
-        if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) {
-            LocalFree (wstr);
-            return FALSE;
-        }
-    if (RequestedInformation & GROUP_SECURITY_INFORMATION)
-        if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) {
-            LocalFree (wstr);
-            return FALSE;
-        }
-    if (RequestedInformation & DACL_SECURITY_INFORMATION)
-        if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) {
-            LocalFree (wstr);
-            return FALSE;
-        }
-    if (RequestedInformation & SACL_SECURITY_INFORMATION)
-        if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) {
-            LocalFree (wstr);
-            return FALSE;
-        }
-    *wptr = 0;
-
-    TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
-    *OutputString = wstr;
-    if (OutputLen)
-        *OutputLen = strlenW(*OutputString)+1;
-    return TRUE;
-}
-
 /******************************************************************************
  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
  */
@@ -3803,30 +2702,6 @@ BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCR
     }
 }
 
-/******************************************************************************
- * ConvertStringSidToSidW [ADVAPI32.@]
- */
-BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
-{
-    BOOL bret = FALSE;
-    DWORD cBytes;
-
-    TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
-    if (GetVersion() & 0x80000000)
-        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    else if (!StringSid || !Sid)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
-    {
-        PSID pSid = *Sid = LocalAlloc(0, cBytes);
-
-        bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
-        if (!bret)
-            LocalFree(*Sid); 
-    }
-    return bret;
-}
-
 /******************************************************************************
  * ConvertStringSidToSidA [ADVAPI32.@]
  */
@@ -3848,34 +2723,6 @@ BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
     return bret;
 }
 
-/******************************************************************************
- * ConvertSidToStringSidW [ADVAPI32.@]
- *
- *  format of SID string is:
- *    S-<count>-<auth>-<subauth1>-<subauth2>-<subauth3>...
- *  where
- *    <rev> is the revision of the SID encoded as decimal
- *    <auth> is the identifier authority encoded as hex
- *    <subauthN> is the subauthority id encoded as decimal
- */
-BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr )
-{
-    DWORD len = 0;
-    LPWSTR wstr, wptr;
-
-    TRACE("%p %p\n", pSid, pstr );
-
-    len = 0;
-    if (!DumpSidNumeric(pSid, NULL, &len))
-        return FALSE;
-    wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR));
-    DumpSidNumeric(pSid, &wptr, NULL);
-    *wptr = 0;
-
-    *pstr = wstr;
-    return TRUE;
-}
-
 /******************************************************************************
  * ConvertSidToStringSidA [ADVAPI32.@]
  */
@@ -3929,167 +2776,6 @@ BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR app
                            current_directory, startup_info, process_information );
 }
 
-/******************************************************************************
- * ComputeStringSidSize
- */
-static DWORD ComputeStringSidSize(LPCWSTR StringSid)
-{
-    if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
-    {
-        int ctok = 0;
-        while (*StringSid)
-        {
-            if (*StringSid == '-')
-                ctok++;
-            StringSid++;
-        }
-
-        if (ctok >= 3)
-            return GetSidLengthRequired(ctok - 2);
-    }
-    else /* String constant format  - Only available in winxp and above */
-    {
-        unsigned int i;
-
-        for (i = 0; i < ARRAY_SIZE(WellKnownSids); i++)
-            if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
-                return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
-
-        for (i = 0; i < ARRAY_SIZE(WellKnownRids); i++)
-            if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
-            {
-                MAX_SID local;
-                ADVAPI_GetComputerSid(&local);
-                return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
-            }
-
-    }
-
-    return GetSidLengthRequired(0);
-}
-
-/******************************************************************************
- * 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;
-    }
-
-    while (*StringSid == ' ')
-        StringSid++;
-
-    *cBytes = ComputeStringSidSize(StringSid);
-    if (!pisid) /* Simply compute the size */
-    {
-        TRACE("only size requested, returning TRUE with %d\n", *cBytes);
-        return TRUE;
-    }
-
-    if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
-    {
-        DWORD i = 0, identAuth;
-        DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
-
-        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)
-        {
-            pisid->SubAuthority[i++] = atoiW(StringSid);
-
-            while (*StringSid && *StringSid != '-')
-                StringSid++;
-            if (*StringSid == '-')
-                StringSid++;
-        }
-
-        if (i != pisid->SubAuthorityCount)
-            goto lend; /* ERROR_INVALID_SID */
-
-        bret = TRUE;
-    }
-    else /* String constant format  - Only available in winxp and above */
-    {
-        unsigned int i;
-        pisid->Revision = SDDL_REVISION;
-
-        for (i = 0; i < ARRAY_SIZE(WellKnownSids); i++)
-            if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
-            {
-                DWORD j;
-                pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
-                pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
-                for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
-                    pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
-                bret = TRUE;
-            }
-
-        for (i = 0; i < ARRAY_SIZE(WellKnownRids); i++)
-            if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
-            {
-                ADVAPI_GetComputerSid(pisid);
-                pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
-                pisid->SubAuthorityCount++;
-                bret = TRUE;
-            }
-
-        if (!bret)
-            FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
-    }
-
-lend:
-    if (!bret)
-        SetLastError(ERROR_INVALID_SID);
-
-    TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
-    return bret;
-}
-
 /******************************************************************************
  * GetNamedSecurityInfoA [ADVAPI32.@]
  */
diff --git a/dlls/sechost/Makefile.in b/dlls/sechost/Makefile.in
index eb98d04859..91016c6757 100644
--- a/dlls/sechost/Makefile.in
+++ b/dlls/sechost/Makefile.in
@@ -6,6 +6,7 @@ DELAYIMPORTS = rpcrt4
 EXTRADLLFLAGS = -mno-cygwin
 
 C_SRCS = \
+	security.c \
 	service.c \
 	trace.c
 
diff --git a/dlls/sechost/sechost.spec b/dlls/sechost/sechost.spec
index df6af1646d..f21e2f1cda 100644
--- a/dlls/sechost/sechost.spec
+++ b/dlls/sechost/sechost.spec
@@ -31,13 +31,13 @@
 @ stdcall ControlTraceA(int64 str ptr long)
 @ stdcall ControlTraceW(int64 wstr ptr long)
 @ stub ConvertSDToStringSDRootDomainW
-@ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorW(ptr long long ptr ptr) advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
-@ stdcall ConvertSidToStringSidW(ptr ptr) advapi32.ConvertSidToStringSidW
+@ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorW(ptr long long ptr ptr)
+@ stdcall ConvertSidToStringSidW(ptr ptr)
 @ stub ConvertStringSDToSDDomainA
 @ stub ConvertStringSDToSDDomainW
 @ stub ConvertStringSDToSDRootDomainW
-@ stdcall ConvertStringSecurityDescriptorToSecurityDescriptorW(wstr long ptr ptr) advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
-@ stdcall ConvertStringSidToSidW(ptr ptr) advapi32.ConvertStringSidToSidW
+@ stdcall ConvertStringSecurityDescriptorToSecurityDescriptorW(wstr long ptr ptr)
+@ stdcall ConvertStringSidToSidW(ptr ptr)
 @ stdcall CreateServiceA(long str str long long long long str str ptr str str str)
 @ stub CreateServiceEx
 @ stdcall CreateServiceW(long wstr wstr long long long long wstr wstr ptr wstr wstr wstr)
diff --git a/dlls/sechost/security.c b/dlls/sechost/security.c
new file mode 100644
index 0000000000..47ffba9ed5
--- /dev/null
+++ b/dlls/sechost/security.c
@@ -0,0 +1,1247 @@
+/*
+ * Security API
+ *
+ * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "sddl.h"
+#include "iads.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(security);
+
+static const struct
+{
+    WCHAR str[3];
+    DWORD value;
+}
+ace_rights[] =
+{
+    { L"GA", GENERIC_ALL },
+    { L"GR", GENERIC_READ },
+    { L"GW", GENERIC_WRITE },
+    { L"GX", GENERIC_EXECUTE },
+
+    { L"RC", READ_CONTROL },
+    { L"SD", DELETE },
+    { L"WD", WRITE_DAC },
+    { L"WO", WRITE_OWNER },
+
+    { L"RP", ADS_RIGHT_DS_READ_PROP },
+    { L"WP", ADS_RIGHT_DS_WRITE_PROP },
+    { L"CC", ADS_RIGHT_DS_CREATE_CHILD },
+    { L"DC", ADS_RIGHT_DS_DELETE_CHILD },
+    { L"LC", ADS_RIGHT_ACTRL_DS_LIST },
+    { L"SW", ADS_RIGHT_DS_SELF },
+    { L"LO", ADS_RIGHT_DS_LIST_OBJECT },
+    { L"DT", ADS_RIGHT_DS_DELETE_TREE },
+    { L"CR", ADS_RIGHT_DS_CONTROL_ACCESS },
+
+    { L"FA", FILE_ALL_ACCESS },
+    { L"FR", FILE_GENERIC_READ },
+    { L"FW", FILE_GENERIC_WRITE },
+    { L"FX", FILE_GENERIC_EXECUTE },
+
+    { L"KA", KEY_ALL_ACCESS },
+    { L"KR", KEY_READ },
+    { L"KW", KEY_WRITE },
+    { L"KX", KEY_EXECUTE },
+
+    { L"NR", SYSTEM_MANDATORY_LABEL_NO_READ_UP },
+    { L"NW", SYSTEM_MANDATORY_LABEL_NO_WRITE_UP },
+    { L"NX", SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP },
+};
+
+struct max_sid
+{
+    /* same fields as struct _SID */
+    BYTE Revision;
+    BYTE SubAuthorityCount;
+    SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
+    DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
+};
+
+static const struct
+{
+    WCHAR str[2];
+    WELL_KNOWN_SID_TYPE Type;
+    struct max_sid sid;
+}
+well_known_sids[] =
+{
+    { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
+    { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
+    { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
+    { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
+    { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
+    { {'O','W'}, WinCreatorOwnerRightsSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RIGHTS_RID } } },
+    { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
+    { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
+    { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
+    { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
+    { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
+    { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
+    { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
+    { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
+    { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
+    { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
+    { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
+    { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
+    { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
+    { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
+    { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
+    { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
+    { {0,0}, WinLogonIdsSid, { SID_REVISION, SECURITY_LOGON_IDS_RID_COUNT, { SECURITY_NT_AUTHORITY }, { SECURITY_LOGON_IDS_RID } } },
+    { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
+    { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
+    { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
+    { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
+    { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
+    { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
+    { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
+    { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
+    { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
+    { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
+    { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
+    { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
+    { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
+    { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
+    { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
+    { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
+    { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
+    { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
+    { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
+    { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
+    { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
+    { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS  } } },
+    { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
+    { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
+    { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
+    { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
+    { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
+    { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
+    { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
+    { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
+    { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
+    { {'A','C'}, WinBuiltinAnyPackageSid, { SID_REVISION, 2, { SECURITY_APP_PACKAGE_AUTHORITY }, { SECURITY_APP_PACKAGE_BASE_RID, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE } } },
+};
+
+/* these SIDs must be constructed as relative to some domain - only the RID is well-known */
+static const struct
+{
+    WCHAR str[2];
+    WELL_KNOWN_SID_TYPE type;
+    DWORD rid;
+}
+well_known_rids[] =
+{
+    { {'L','A'}, WinAccountAdministratorSid,    DOMAIN_USER_RID_ADMIN },
+    { {'L','G'}, WinAccountGuestSid,            DOMAIN_USER_RID_GUEST },
+    { {0,0},     WinAccountKrbtgtSid,           DOMAIN_USER_RID_KRBTGT },
+    { {'D','A'}, WinAccountDomainAdminsSid,     DOMAIN_GROUP_RID_ADMINS },
+    { {'D','U'}, WinAccountDomainUsersSid,      DOMAIN_GROUP_RID_USERS },
+    { {'D','G'}, WinAccountDomainGuestsSid,     DOMAIN_GROUP_RID_GUESTS },
+    { {'D','C'}, WinAccountComputersSid,        DOMAIN_GROUP_RID_COMPUTERS },
+    { {'D','D'}, WinAccountControllersSid,      DOMAIN_GROUP_RID_CONTROLLERS },
+    { {'C','A'}, WinAccountCertAdminsSid,       DOMAIN_GROUP_RID_CERT_ADMINS },
+    { {'S','A'}, WinAccountSchemaAdminsSid,     DOMAIN_GROUP_RID_SCHEMA_ADMINS },
+    { {'E','A'}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
+    { {'P','A'}, WinAccountPolicyAdminsSid,     DOMAIN_GROUP_RID_POLICY_ADMINS },
+    { {'R','S'}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
+};
+
+
+static void print_string(const WCHAR *string, int cch, WCHAR **pwptr, ULONG *plen)
+{
+    if (cch == -1)
+        cch = wcslen(string);
+
+    if (plen)
+        *plen += cch;
+
+    if (pwptr)
+    {
+        memcpy(*pwptr, string, sizeof(WCHAR)*cch);
+        *pwptr += cch;
+    }
+}
+
+static BOOL print_sid_numeric(PSID psid, WCHAR **pwptr, ULONG *plen)
+{
+    DWORD i;
+    WCHAR buf[26];
+    SID *pisid = psid;
+
+    if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
+    {
+        SetLastError(ERROR_INVALID_SID);
+        return FALSE;
+    }
+
+    if (pisid->IdentifierAuthority.Value[0] ||
+     pisid->IdentifierAuthority.Value[1])
+    {
+        FIXME("not matching MS' bugs\n");
+        SetLastError(ERROR_INVALID_SID);
+        return FALSE;
+    }
+
+    swprintf( buf, ARRAY_SIZE(buf), L"S-%u-%d", pisid->Revision, MAKELONG(
+            MAKEWORD( pisid->IdentifierAuthority.Value[5], pisid->IdentifierAuthority.Value[4] ),
+            MAKEWORD( pisid->IdentifierAuthority.Value[3], pisid->IdentifierAuthority.Value[2] )
+            ) );
+    print_string(buf, -1, pwptr, plen);
+
+    for( i=0; i<pisid->SubAuthorityCount; i++ )
+    {
+        swprintf( buf, ARRAY_SIZE(buf), L"-%u", pisid->SubAuthority[i] );
+        print_string(buf, -1, pwptr, plen);
+    }
+    return TRUE;
+}
+
+/******************************************************************************
+ *     ConvertSidToStringSidW   (sechost.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH ConvertSidToStringSidW( PSID sid, WCHAR **pstr )
+{
+    DWORD len = 0;
+    WCHAR *wstr, *wptr;
+
+    TRACE("%p %p\n", sid, pstr );
+
+    len = 0;
+    if (!print_sid_numeric( sid, NULL, &len ))
+        return FALSE;
+    wstr = wptr = LocalAlloc( 0, (len + 1) * sizeof(WCHAR) );
+    print_sid_numeric( sid, &wptr, NULL );
+    *wptr = 0;
+
+    *pstr = wstr;
+    return TRUE;
+}
+
+static BOOL print_sid(PSID psid, WCHAR **pwptr, ULONG *plen)
+{
+    size_t i;
+    for (i = 0; i < ARRAY_SIZE(well_known_sids); i++)
+    {
+        if (well_known_sids[i].str[0] && EqualSid(psid, (PSID)&well_known_sids[i].sid.Revision))
+        {
+            print_string(well_known_sids[i].str, 2, pwptr, plen);
+            return TRUE;
+        }
+    }
+
+    return print_sid_numeric(psid, pwptr, plen);
+}
+
+static void print_rights(DWORD mask, WCHAR **pwptr, ULONG *plen)
+{
+    static const WCHAR *bit_names[32] =
+    {
+            L"CC",  /*  0 */
+            L"DC",
+            L"LC",
+            L"SW",
+            L"RP",  /*  4 */
+            L"WP",
+            L"DT",
+            L"LO",
+            L"CR",  /*  8 */
+            NULL,
+            NULL,
+            NULL,
+            NULL,   /* 12 */
+            NULL,
+            NULL,
+            NULL,
+            L"SD",  /* 16 */
+            L"RC",
+            L"WD",
+            L"WO",
+            NULL,   /* 20 */
+            NULL,
+            NULL,
+            NULL,
+            NULL,   /* 24 */
+            NULL,
+            NULL,
+            NULL,
+            L"GA",  /* 28 */
+            L"GX",
+            L"GW",
+            L"GR",
+    };
+
+    WCHAR buf[15];
+    size_t i;
+
+    if (mask == 0)
+        return;
+
+    /* first check if the right have name */
+    for (i = 0; i < ARRAY_SIZE(ace_rights); i++)
+    {
+        if (mask == ace_rights[i].value)
+        {
+            print_string(ace_rights[i].str, -1, pwptr, plen);
+            return;
+        }
+    }
+
+    /* then check if it can be built from bit names */
+    for (i = 0; i < 32; i++)
+    {
+        if ((mask & (1 << i)) && !bit_names[i])
+        {
+            /* can't be built from bit names */
+            swprintf(buf, ARRAY_SIZE(buf), L"0x%x", mask);
+            print_string(buf, -1, pwptr, plen);
+            return;
+        }
+    }
+
+    /* build from bit names */
+    for (i = 0; i < 32; i++)
+        if (mask & (1 << i))
+            print_string(bit_names[i], -1, pwptr, plen);
+}
+
+static inline BOOL is_object_ace(BYTE type)
+{
+    switch (type)
+    {
+    case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
+    case ACCESS_DENIED_OBJECT_ACE_TYPE:
+    case ACCESS_AUDIT_OBJECT_ACE_TYPE:
+    case ACCESS_ALARM_OBJECT_ACE_TYPE:
+    case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
+    case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
+    case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
+    case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE:
+        return TRUE;
+
+    default:
+        return FALSE;
+    }
+}
+
+static BOOL print_ace(void *pace, WCHAR **pwptr, ULONG *plen)
+{
+    ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
+    DWORD *sid_start;
+
+    piace = pace;
+
+    if (piace->Header.AceType > ACCESS_MAX_MS_V5_ACE_TYPE || piace->Header.AceSize < sizeof(ACCESS_ALLOWED_ACE))
+    {
+        SetLastError(ERROR_INVALID_ACL);
+        return FALSE;
+    }
+
+    print_string(L"(", -1, pwptr, plen);
+    switch (piace->Header.AceType)
+    {
+        case ACCESS_ALLOWED_ACE_TYPE:
+            print_string(L"A", -1, pwptr, plen);
+            break;
+        case ACCESS_DENIED_ACE_TYPE:
+            print_string(L"D", -1, pwptr, plen);
+            break;
+        case SYSTEM_AUDIT_ACE_TYPE:
+            print_string(L"AU", -1, pwptr, plen);
+            break;
+        case SYSTEM_ALARM_ACE_TYPE:
+            print_string(L"AL", -1, pwptr, plen);
+            break;
+    }
+    print_string(L";", -1, pwptr, plen);
+
+    if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
+        print_string(L"OI", -1, pwptr, plen);
+    if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
+        print_string(L"CI", -1, pwptr, plen);
+    if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
+        print_string(L"NP", -1, pwptr, plen);
+    if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
+        print_string(L"IO", -1, pwptr, plen);
+    if (piace->Header.AceFlags & INHERITED_ACE)
+        print_string(L"ID", -1, pwptr, plen);
+    if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
+        print_string(L"SA", -1, pwptr, plen);
+    if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
+        print_string(L"FA", -1, pwptr, plen);
+    print_string(L";", -1, pwptr, plen);
+    print_rights(piace->Mask, pwptr, plen);
+    print_string(L";", -1, pwptr, plen);
+    sid_start = &piace->SidStart;
+    if (is_object_ace(piace->Header.AceType))
+    {
+        ACCESS_ALLOWED_OBJECT_ACE *objace = pace;
+
+        sid_start++; /* Flags */
+        if (objace->Flags & ACE_OBJECT_TYPE_PRESENT)
+            sid_start += sizeof(GUID) / sizeof(*sid_start); /* ObjectType */
+        if (objace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
+            sid_start += sizeof(GUID) / sizeof(*sid_start); /* InheritedObjectType */
+    }
+    /* objects not supported */
+    print_string(L";", -1, pwptr, plen);
+    /* objects not supported */
+    print_string(L";", -1, pwptr, plen);
+    if (!print_sid(sid_start, pwptr, plen))
+        return FALSE;
+    print_string(L")", -1, pwptr, plen);
+    return TRUE;
+}
+
+static BOOL print_acl(ACL *pacl, WCHAR **pwptr, ULONG *plen, SECURITY_DESCRIPTOR_CONTROL control)
+{
+    WORD count;
+    UINT i;
+
+    if (control & SE_DACL_PROTECTED)
+        print_string(L"P", -1, pwptr, plen);
+    if (control & SE_DACL_AUTO_INHERIT_REQ)
+        print_string(L"AR", -1, pwptr, plen);
+    if (control & SE_DACL_AUTO_INHERITED)
+        print_string(L"AI", -1, pwptr, plen);
+
+    if (pacl == NULL)
+        return TRUE;
+
+    if (!IsValidAcl(pacl))
+        return FALSE;
+
+    count = pacl->AceCount;
+    for (i = 0; i < count; i++)
+    {
+        void *ace;
+        if (!GetAce(pacl, i, &ace))
+            return FALSE;
+        if (!print_ace(ace, pwptr, plen))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+static BOOL print_owner(PSECURITY_DESCRIPTOR sd, WCHAR **pwptr, ULONG *plen)
+{
+    BOOL defaulted;
+    PSID psid;
+
+    if (!GetSecurityDescriptorOwner(sd, &psid, &defaulted))
+        return FALSE;
+
+    if (psid == NULL)
+        return TRUE;
+
+    print_string(L"O:", -1, pwptr, plen);
+    if (!print_sid(psid, pwptr, plen))
+        return FALSE;
+    return TRUE;
+}
+
+static BOOL print_group(PSECURITY_DESCRIPTOR sd, WCHAR **pwptr, ULONG *plen)
+{
+    BOOL defaulted;
+    PSID psid;
+
+    if (!GetSecurityDescriptorGroup(sd, &psid, &defaulted))
+        return FALSE;
+
+    if (psid == NULL)
+        return TRUE;
+
+    print_string(L"G:", -1, pwptr, plen);
+    if (!print_sid(psid, pwptr, plen))
+        return FALSE;
+    return TRUE;
+}
+
+static BOOL print_dacl(PSECURITY_DESCRIPTOR sd, WCHAR **pwptr, ULONG *plen)
+{
+    SECURITY_DESCRIPTOR_CONTROL control;
+    BOOL present, defaulted;
+    DWORD revision;
+    ACL *pacl;
+
+    if (!GetSecurityDescriptorDacl(sd, &present, &pacl, &defaulted))
+        return FALSE;
+
+    if (!GetSecurityDescriptorControl(sd, &control, &revision))
+        return FALSE;
+
+    if (!present)
+        return TRUE;
+
+    print_string(L"D:", -1, pwptr, plen);
+    if (!print_acl(pacl, pwptr, plen, control))
+        return FALSE;
+    return TRUE;
+}
+
+static BOOL print_sacl(PSECURITY_DESCRIPTOR sd, WCHAR **pwptr, ULONG *plen)
+{
+    SECURITY_DESCRIPTOR_CONTROL control;
+    BOOL present, defaulted;
+    DWORD revision;
+    ACL *pacl;
+
+    if (!GetSecurityDescriptorSacl(sd, &present, &pacl, &defaulted))
+        return FALSE;
+
+    if (!GetSecurityDescriptorControl(sd, &control, &revision))
+        return FALSE;
+
+    if (!present)
+        return TRUE;
+
+    print_string(L"S:", -1, pwptr, plen);
+    if (!print_acl(pacl, pwptr, plen, control))
+        return FALSE;
+    return TRUE;
+}
+
+/******************************************************************************
+ *     ConvertSecurityDescriptorToStringSecurityDescriptorW   (sechost.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH ConvertSecurityDescriptorToStringSecurityDescriptorW( PSECURITY_DESCRIPTOR sd,
+        DWORD revision, SECURITY_INFORMATION flags, WCHAR **string, ULONG *ret_len )
+{
+    ULONG len = 0;
+    WCHAR *wptr, *wstr;
+
+    if (revision != SDDL_REVISION_1)
+    {
+        ERR("Unhandled SDDL revision %d\n", revision);
+        SetLastError( ERROR_UNKNOWN_REVISION );
+        return FALSE;
+    }
+
+    if ((flags & OWNER_SECURITY_INFORMATION) && !print_owner(sd, NULL, &len))
+        return FALSE;
+    if ((flags & GROUP_SECURITY_INFORMATION) && !print_group(sd, NULL, &len))
+        return FALSE;
+    if ((flags & DACL_SECURITY_INFORMATION) && !print_dacl(sd, NULL, &len))
+        return FALSE;
+    if ((flags & SACL_SECURITY_INFORMATION) && !print_sacl(sd, NULL, &len))
+        return FALSE;
+
+    wstr = wptr = LocalAlloc( 0, (len + 1) * sizeof(WCHAR) );
+    if ((flags & OWNER_SECURITY_INFORMATION) && !print_owner(sd, &wptr, NULL))
+    {
+        LocalFree(wstr);
+        return FALSE;
+    }
+    if ((flags & GROUP_SECURITY_INFORMATION) && !print_group(sd, &wptr, NULL))
+    {
+        LocalFree(wstr);
+        return FALSE;
+    }
+    if ((flags & DACL_SECURITY_INFORMATION) && !print_dacl(sd, &wptr, NULL))
+    {
+        LocalFree(wstr);
+        return FALSE;
+    }
+    if ((flags & SACL_SECURITY_INFORMATION) && !print_sacl(sd, &wptr, NULL))
+    {
+        LocalFree(wstr);
+        return FALSE;
+    }
+    *wptr = 0;
+
+    TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
+    *string = wstr;
+    if (ret_len) *ret_len = wcslen(*string) + 1;
+    return TRUE;
+}
+
+static BOOL get_computer_sid( PSID sid )
+{
+    static const struct /* same fields as struct SID */
+    {
+        BYTE Revision;
+        BYTE SubAuthorityCount;
+        SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
+        DWORD SubAuthority[4];
+    } computer_sid =
+    { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } };
+
+    memcpy( sid, &computer_sid, sizeof(computer_sid) );
+    return TRUE;
+}
+
+static DWORD get_sid_size( const WCHAR *string )
+{
+    if (string[0] == 'S' && string[1] == '-') /* S-R-I(-S)+ */
+    {
+        int token_count = 0;
+        while (*string)
+        {
+            if (*string == '-')
+                token_count++;
+            string++;
+        }
+
+        if (token_count >= 3)
+            return GetSidLengthRequired( token_count - 2 );
+    }
+    else /* String constant format  - Only available in winxp and above */
+    {
+        unsigned int i;
+
+        for (i = 0; i < ARRAY_SIZE(well_known_sids); i++)
+        {
+            if (!wcsncmp( well_known_sids[i].str, string, 2 ))
+                return GetSidLengthRequired( well_known_sids[i].sid.SubAuthorityCount );
+        }
+
+        for (i = 0; i < ARRAY_SIZE(well_known_rids); i++)
+        {
+            if (!wcsncmp( well_known_rids[i].str, string, 2 ))
+            {
+                struct max_sid local;
+                get_computer_sid(&local);
+                return GetSidLengthRequired( *GetSidSubAuthorityCount(&local) + 1 );
+            }
+        }
+    }
+
+    return GetSidLengthRequired( 0 );
+}
+
+static BOOL parse_sid( const WCHAR *string, SID *pisid, DWORD *size )
+{
+    while (*string == ' ')
+        string++;
+
+    *size = get_sid_size( string );
+    if (!pisid) /* Simply compute the size */
+        return TRUE;
+
+    if (string[0] == 'S' && string[1] == '-') /* S-R-I-S-S */
+    {
+        DWORD i = 0, identAuth;
+        DWORD csubauth = ((*size - GetSidLengthRequired(0)) / sizeof(DWORD));
+
+        string += 2; /* Advance to Revision */
+        pisid->Revision = wcstoul( string, NULL, 10 );
+
+        if (pisid->Revision != SDDL_REVISION)
+        {
+            TRACE("Revision %d is unknown\n", pisid->Revision);
+            SetLastError( ERROR_INVALID_SID );
+            return FALSE;
+        }
+        if (csubauth == 0)
+        {
+            TRACE("SubAuthorityCount is 0\n");
+            SetLastError( ERROR_INVALID_SID );
+            return FALSE;
+        }
+
+        pisid->SubAuthorityCount = csubauth;
+
+        /* Advance to identifier authority */
+        while (*string && *string != '-')
+            string++;
+        if (*string == '-')
+            string++;
+
+        /* 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 = wcstoul( string, NULL, 10 );
+        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 (*string && *string != '-')
+            string++;
+        if (*string == '-')
+            string++;
+
+        while (*string)
+        {
+            pisid->SubAuthority[i++] = wcstoul( string, NULL, 10 );
+
+            while (*string && *string != '-')
+                string++;
+            if (*string == '-')
+                string++;
+        }
+
+        if (i != pisid->SubAuthorityCount)
+        {
+            SetLastError( ERROR_INVALID_SID );
+            return FALSE;
+        }
+
+        return TRUE;
+    }
+    else /* String constant format  - Only available in winxp and above */
+    {
+        unsigned int i;
+        pisid->Revision = SDDL_REVISION;
+
+        for (i = 0; i < ARRAY_SIZE(well_known_sids); i++)
+        {
+            if (!wcsncmp(well_known_sids[i].str, string, 2))
+            {
+                DWORD j;
+                pisid->SubAuthorityCount = well_known_sids[i].sid.SubAuthorityCount;
+                pisid->IdentifierAuthority = well_known_sids[i].sid.IdentifierAuthority;
+                for (j = 0; j < well_known_sids[i].sid.SubAuthorityCount; j++)
+                    pisid->SubAuthority[j] = well_known_sids[i].sid.SubAuthority[j];
+                return TRUE;
+            }
+        }
+
+        for (i = 0; i < ARRAY_SIZE(well_known_rids); i++)
+        {
+            if (!wcsncmp(well_known_rids[i].str, string, 2))
+            {
+                get_computer_sid(pisid);
+                pisid->SubAuthority[pisid->SubAuthorityCount] = well_known_rids[i].rid;
+                pisid->SubAuthorityCount++;
+                return TRUE;
+            }
+        }
+
+        FIXME("String constant not supported: %s\n", debugstr_wn(string, 2));
+        SetLastError( ERROR_INVALID_SID );
+        return FALSE;
+    }
+}
+
+/******************************************************************************
+ *     ConvertStringSidToSidW   (sechost.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH ConvertStringSidToSidW( const WCHAR *string, PSID *sid )
+{
+    DWORD size;
+
+    TRACE("%s, %p\n", debugstr_w(string), sid);
+
+    if (GetVersion() & 0x80000000)
+    {
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return FALSE;
+    }
+
+    if (!string || !sid)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (!parse_sid( string, NULL, &size ))
+        return FALSE;
+
+    *sid = LocalAlloc( 0, size );
+
+    if (!parse_sid( string, *sid, &size ))
+    {
+        LocalFree( *sid );
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static DWORD parse_acl_flags( const WCHAR **string_ptr )
+{
+    DWORD flags = 0;
+    const WCHAR *string = *string_ptr;
+
+    while (*string && *string != '(')
+    {
+        if (*string == 'P')
+        {
+            flags |= SE_DACL_PROTECTED;
+        }
+        else if (*string == 'A')
+        {
+            string++;
+            if (*string == 'R')
+                flags |= SE_DACL_AUTO_INHERIT_REQ;
+            else if (*string == 'I')
+                flags |= SE_DACL_AUTO_INHERITED;
+        }
+        string++;
+    }
+
+    *string_ptr = string;
+    return flags;
+}
+
+static BYTE parse_ace_type( const WCHAR **string_ptr )
+{
+    static const struct
+    {
+        const WCHAR *str;
+        DWORD value;
+    }
+    ace_types[] =
+    {
+        { L"AL", SYSTEM_ALARM_ACE_TYPE },
+        { L"AU", SYSTEM_AUDIT_ACE_TYPE },
+        { L"A",  ACCESS_ALLOWED_ACE_TYPE },
+        { L"D",  ACCESS_DENIED_ACE_TYPE },
+        { L"ML", SYSTEM_MANDATORY_LABEL_ACE_TYPE },
+        /*
+        { ACCESS_ALLOWED_OBJECT_ACE_TYPE },
+        { ACCESS_DENIED_OBJECT_ACE_TYPE },
+        { SYSTEM_ALARM_OBJECT_ACE_TYPE },
+        { SYSTEM_AUDIT_OBJECT_ACE_TYPE },
+        */
+    };
+
+    const WCHAR *string = *string_ptr;
+    unsigned int i;
+
+    while (*string == ' ')
+        string++;
+
+    for (i = 0; i < ARRAY_SIZE(ace_types); ++i)
+    {
+        size_t len = wcslen( ace_types[i].str );
+        if (!wcsncmp( string, ace_types[i].str, len ))
+        {
+            *string_ptr = string + len;
+            return ace_types[i].value;
+        }
+    }
+    return 0;
+}
+
+static DWORD parse_ace_flag( const WCHAR *string )
+{
+    static const struct
+    {
+        WCHAR str[3];
+        DWORD value;
+    }
+    ace_flags[] =
+    {
+        { L"CI", CONTAINER_INHERIT_ACE },
+        { L"FA", FAILED_ACCESS_ACE_FLAG },
+        { L"ID", INHERITED_ACE },
+        { L"IO", INHERIT_ONLY_ACE },
+        { L"NP", NO_PROPAGATE_INHERIT_ACE },
+        { L"OI", OBJECT_INHERIT_ACE },
+        { L"SA", SUCCESSFUL_ACCESS_ACE_FLAG },
+    };
+
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(ace_flags); ++i)
+    {
+        if (!wcsncmp( string, ace_flags[i].str, 2 ))
+            return ace_flags[i].value;
+    }
+    return 0;
+}
+
+static DWORD parse_ace_right( const WCHAR *string )
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(ace_rights); ++i)
+    {
+        if (!wcsncmp( string, ace_rights[i].str, 2 ))
+            return ace_rights[i].value;
+    }
+    return 0;
+}
+
+static BYTE parse_ace_flags( const WCHAR **string_ptr )
+{
+    const WCHAR *string = *string_ptr;
+    BYTE flags = 0;
+
+    while (*string == ' ')
+        string++;
+
+    while (*string != ';')
+    {
+        DWORD flag = parse_ace_flag( string );
+        if (!flag) return 0;
+        flags |= flag;
+        string += 2;
+    }
+
+    *string_ptr = string;
+    return flags;
+}
+
+static DWORD parse_ace_rights( const WCHAR **string_ptr )
+{
+    DWORD rights = 0;
+    const WCHAR *string = *string_ptr;
+
+    while (*string == ' ')
+        string++;
+
+    if (string[0] == '0' && string[1] == 'x')
+    {
+        const WCHAR *p = string;
+
+        while (*p && *p != ';')
+            p++;
+
+        if (p - string <= 10 /* 8 hex digits + "0x" */ )
+        {
+            rights = wcstoul( string, NULL, 16 );
+            string = p;
+        }
+        else
+            WARN("Invalid rights string format: %s\n", debugstr_wn(string, p - string));
+    }
+    else
+    {
+        while (*string != ';')
+        {
+            DWORD right = parse_ace_right( string );
+            if (!right) return 0;
+            rights |= right;
+            string += 2;
+        }
+    }
+
+    *string_ptr = string;
+    return rights;
+}
+
+static BOOL parse_acl( const WCHAR *string, DWORD *flags, ACL *acl, DWORD *ret_size )
+{
+    DWORD val;
+    DWORD sidlen;
+    DWORD length = sizeof(ACL);
+    DWORD acesize = 0;
+    DWORD acecount = 0;
+    ACCESS_ALLOWED_ACE *ace = NULL; /* pointer to current ACE */
+
+    TRACE("%s\n", debugstr_w(string));
+
+    if (acl) /* ace is only useful if we're setting values */
+        ace = (ACCESS_ALLOWED_ACE *)(acl + 1);
+
+    /* Parse ACL flags */
+    *flags = parse_acl_flags( &string );
+
+    /* Parse ACE */
+    while (*string == '(')
+    {
+        string++;
+
+        /* Parse ACE type */
+        val = parse_ace_type( &string );
+        if (ace)
+            ace->Header.AceType = val;
+        if (*string != ';')
+        {
+            SetLastError( RPC_S_INVALID_STRING_UUID );
+            return FALSE;
+        }
+        string++;
+
+        /* Parse ACE flags */
+        val = parse_ace_flags( &string );
+        if (ace)
+            ace->Header.AceFlags = val;
+        if (*string != ';')
+            goto err;
+        string++;
+
+        /* Parse ACE rights */
+        val = parse_ace_rights( &string );
+        if (ace)
+            ace->Mask = val;
+        if (*string != ';')
+            goto err;
+        string++;
+
+        /* Parse ACE object guid */
+        while (*string == ' ')
+            string++;
+        if (*string != ';')
+        {
+            FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
+            goto err;
+        }
+        string++;
+
+        /* Parse ACE inherit object guid */
+        while (*string == ' ')
+            string++;
+        if (*string != ';')
+        {
+            FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
+            goto err;
+        }
+        string++;
+
+        /* Parse ACE account sid */
+        if (parse_sid( string, ace ? (SID *)&ace->SidStart : NULL, &sidlen ))
+        {
+            while (*string && *string != ')')
+                string++;
+        }
+
+        if (*string != ')')
+            goto err;
+        string++;
+
+        acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
+        length += acesize;
+        if (ace)
+        {
+            ace->Header.AceSize = acesize;
+            ace = (ACCESS_ALLOWED_ACE *)((BYTE *)ace + acesize);
+        }
+        acecount++;
+    }
+
+    *ret_size = length;
+
+    if (length > 0xffff)
+    {
+        ERR("ACL too large\n");
+        goto err;
+    }
+
+    if (acl)
+    {
+        acl->AclRevision = ACL_REVISION;
+        acl->Sbz1 = 0;
+        acl->AclSize = length;
+        acl->AceCount = acecount;
+        acl->Sbz2 = 0;
+    }
+    return TRUE;
+
+err:
+    SetLastError( ERROR_INVALID_ACL );
+    WARN("Invalid ACE string format\n");
+    return FALSE;
+}
+
+static BOOL parse_sd( const WCHAR *string, SECURITY_DESCRIPTOR_RELATIVE *sd, DWORD *size)
+{
+    BOOL ret = FALSE;
+    WCHAR toktype;
+    WCHAR *tok;
+    const WCHAR *lptoken;
+    BYTE *next = NULL;
+    DWORD len;
+
+    *size = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
+
+    tok = heap_alloc( (wcslen(string) + 1) * sizeof(WCHAR) );
+    if (!tok)
+    {
+        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+        return FALSE;
+    }
+
+    if (sd)
+        next = (BYTE *)(sd + 1);
+
+    while (*string == ' ')
+        string++;
+
+    while (*string)
+    {
+        toktype = *string;
+
+        /* Expect char identifier followed by ':' */
+        string++;
+        if (*string != ':')
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            goto out;
+        }
+        string++;
+
+        /* Extract token */
+        lptoken = string;
+        while (*lptoken && *lptoken != ':')
+            lptoken++;
+
+        if (*lptoken)
+            lptoken--;
+
+        len = lptoken - string;
+        memcpy( tok, string, len * sizeof(WCHAR) );
+        tok[len] = 0;
+
+        switch (toktype)
+        {
+            case 'O':
+            {
+                DWORD bytes;
+
+                if (!parse_sid( tok, (SID *)next, &bytes ))
+                    goto out;
+
+                if (sd)
+                {
+                    sd->Owner = next - (BYTE *)sd;
+                    next += bytes; /* Advance to next token */
+                }
+
+                *size += bytes;
+
+                break;
+            }
+
+            case 'G':
+            {
+                DWORD bytes;
+
+                if (!parse_sid( tok, (SID *)next, &bytes ))
+                    goto out;
+
+                if (sd)
+                {
+                    sd->Group = next - (BYTE *)sd;
+                    next += bytes; /* Advance to next token */
+                }
+
+                *size += bytes;
+
+                break;
+            }
+
+            case 'D':
+            {
+                DWORD flags;
+                DWORD bytes;
+
+                if (!parse_acl( tok, &flags, (ACL *)next, &bytes ))
+                    goto out;
+
+                if (sd)
+                {
+                    sd->Control |= SE_DACL_PRESENT | flags;
+                    sd->Dacl = next - (BYTE *)sd;
+                    next += bytes; /* Advance to next token */
+                }
+
+                *size += bytes;
+
+                break;
+            }
+
+            case 'S':
+            {
+                DWORD flags;
+                DWORD bytes;
+
+                if (!parse_acl( tok, &flags, (ACL *)next, &bytes ))
+                    goto out;
+
+                if (sd)
+                {
+                    sd->Control |= SE_SACL_PRESENT | flags;
+                    sd->Sacl = next - (BYTE *)sd;
+                    next += bytes; /* Advance to next token */
+                }
+
+                *size += bytes;
+
+                break;
+            }
+
+            default:
+                FIXME("Unknown token\n");
+                SetLastError( ERROR_INVALID_PARAMETER );
+                goto out;
+        }
+
+        string = lptoken;
+    }
+
+    ret = TRUE;
+
+out:
+    heap_free(tok);
+    return ret;
+}
+
+/******************************************************************************
+ *     ConvertStringSecurityDescriptorToSecurityDescriptorW   (sechost.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH ConvertStringSecurityDescriptorToSecurityDescriptorW(
+        const WCHAR *string, DWORD revision, PSECURITY_DESCRIPTOR *sd, ULONG *ret_size )
+{
+    DWORD size;
+    SECURITY_DESCRIPTOR *psd;
+
+    TRACE("%s, %u, %p, %p\n", debugstr_w(string), revision, sd, ret_size);
+
+    if (GetVersion() & 0x80000000)
+    {
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return FALSE;
+    }
+    if (!string || !sd)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (revision != SID_REVISION)
+    {
+        SetLastError(ERROR_UNKNOWN_REVISION);
+        return FALSE;
+    }
+
+    /* Compute security descriptor length */
+    if (!parse_sd( string, NULL, &size ))
+        return FALSE;
+
+    psd = *sd = LocalAlloc( GMEM_ZEROINIT, size );
+    if (!psd)
+    {
+        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+        return FALSE;
+    }
+
+    psd->Revision = SID_REVISION;
+    psd->Control |= SE_SELF_RELATIVE;
+
+    if (!parse_sd( string, (SECURITY_DESCRIPTOR_RELATIVE *)psd, &size ))
+    {
+        LocalFree(psd);
+        return FALSE;
+    }
+
+    if (ret_size) *ret_size = size;
+    return TRUE;
+}
-- 
2.26.2




More information about the wine-devel mailing list