[ADVAPI32]
[reactos.git] / reactos / dll / win32 / advapi32 / sec / sid.c
index f82ef5b..ed466a5 100644 (file)
@@ -1,29 +1,56 @@
-/* $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)
+ * Copyright 2006 Robert Reif
+ * Copyright 2006 HervĂ© Poussineau
  *
  * PROJECT:         ReactOS system libraries
- * FILE:            lib/advapi32/sec/sid.c
+ * FILE:            dll/win32/advapi32/sec/sid.c
  * PURPOSE:         Security ID functions
  */
 
 #include <advapi32.h>
+#include <sddl.h>
 #include <wine/debug.h>
 #include <wine/unicode.h>
 
 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
 
+#define MAX_GUID_STRING_LEN 39
+
+BOOL WINAPI
+AddAuditAccessAceEx(PACL pAcl,
+                   DWORD dwAceRevision,
+                   DWORD AceFlags,
+                   DWORD dwAccessMask,
+                   PSID pSid,
+                   BOOL bAuditSuccess,
+                   BOOL bAuditFailure);
+
+typedef struct RECORD
+{
+       LPCWSTR key;
+       DWORD value;
+} RECORD;
 
-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 _MAX_SID
+{
+    /* same fields as struct _SID */
+    BYTE Revision;
+    BYTE SubAuthorityCount;
+    SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
+    DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
+} MAX_SID;
+
+typedef struct WELLKNOWNSID
+{
+    WCHAR wstr[2];
+    WELL_KNOWN_SID_TYPE Type;
+    MAX_SID Sid;
+} WELLKNOWNSID;
 
 typedef struct _ACEFLAG
 {
@@ -31,19 +58,85 @@ typedef struct _ACEFLAG
    DWORD value;
 } ACEFLAG, *LPACEFLAG;
 
-static const SID sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
+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 } } },
+    { {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 } } },
+    { {'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 } } },
+};
 
-/*
- * 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};
+typedef struct WELLKNOWNRID
+{
+    WELL_KNOWN_SID_TYPE Type;
+    DWORD Rid;
+} WELLKNOWNRID;
+
+static const WELLKNOWNRID WellKnownRids[] = {
+    { WinAccountAdministratorSid,    DOMAIN_USER_RID_ADMIN },
+    { WinAccountGuestSid,            DOMAIN_USER_RID_GUEST },
+    { WinAccountKrbtgtSid,           DOMAIN_USER_RID_KRBTGT },
+    { WinAccountDomainAdminsSid,     DOMAIN_GROUP_RID_ADMINS },
+    { WinAccountDomainUsersSid,      DOMAIN_GROUP_RID_USERS },
+    { WinAccountDomainGuestsSid,     DOMAIN_GROUP_RID_GUESTS },
+    { WinAccountComputersSid,        DOMAIN_GROUP_RID_COMPUTERS },
+    { WinAccountControllersSid,      DOMAIN_GROUP_RID_CONTROLLERS },
+    { WinAccountCertAdminsSid,       DOMAIN_GROUP_RID_CERT_ADMINS },
+    { WinAccountSchemaAdminsSid,     DOMAIN_GROUP_RID_SCHEMA_ADMINS },
+    { WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
+    { WinAccountPolicyAdminsSid,     DOMAIN_GROUP_RID_POLICY_ADMINS },
+    { WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
+};
+
+static const SID sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
 
 /*
  * ACE types
@@ -57,48 +150,785 @@ static const WCHAR SDDL_ALARM[]                 = {'A','L',0};
 static const WCHAR SDDL_OBJECT_AUDIT[]          = {'O','U',0};
 static const WCHAR SDDL_OBJECT_ALARM[]          = {'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};
+/*
+ * SDDL ADS Rights
+ */
+#define ADS_RIGHT_DS_CREATE_CHILD   0x0001
+#define ADS_RIGHT_DS_DELETE_CHILD   0x0002
+#define ADS_RIGHT_ACTRL_DS_LIST     0x0004
+#define ADS_RIGHT_DS_SELF           0x0008
+#define ADS_RIGHT_DS_READ_PROP      0x0010
+#define ADS_RIGHT_DS_WRITE_PROP     0x0020
+#define ADS_RIGHT_DS_DELETE_TREE    0x0040
+#define ADS_RIGHT_DS_LIST_OBJECT    0x0080
+#define ADS_RIGHT_DS_CONTROL_ACCESS 0x0100
+
+/*
+ * 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};
+
+static const char * debugstr_sid(PSID sid)
+{
+    int auth = 0;
+    SID * psid = (SID *)sid;
+
+    if (psid == NULL)
+        return "(null)";
+
+    auth = psid->IdentifierAuthority.Value[5] +
+           (psid->IdentifierAuthority.Value[4] << 8) +
+           (psid->IdentifierAuthority.Value[3] << 16) +
+           (psid->IdentifierAuthority.Value[2] << 24);
+
+    switch (psid->SubAuthorityCount) {
+    case 0:
+        return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
+    case 1:
+        return wine_dbg_sprintf("S-%d-%d-%lu", psid->Revision, auth,
+            psid->SubAuthority[0]);
+    case 2:
+        return wine_dbg_sprintf("S-%d-%d-%lu-%lu", psid->Revision, auth,
+            psid->SubAuthority[0], psid->SubAuthority[1]);
+    case 3:
+        return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu", psid->Revision, auth,
+            psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
+    case 4:
+        return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu", psid->Revision, auth,
+            psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
+            psid->SubAuthority[3]);
+    case 5:
+        return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
+            psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
+            psid->SubAuthority[3], psid->SubAuthority[4]);
+    case 6:
+        return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
+            psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
+            psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
+    case 7:
+        return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
+            psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
+            psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
+            psid->SubAuthority[6]);
+    case 8:
+        return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
+            psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
+            psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
+            psid->SubAuthority[6], psid->SubAuthority[7]);
+    }
+    return "(too-big)";
+}
+
+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 },
+    { NULL, 0 },
+};
+
+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
+};
+
+
+/* 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;
+}
+
+/* Exported functions */
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+AllocateLocallyUniqueId(PLUID Luid)
+{
+    NTSTATUS Status;
+
+    Status = NtAllocateLocallyUniqueId (Luid);
+    if (!NT_SUCCESS (Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+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,
+                                         dwSubAuthority5,
+                                         dwSubAuthority6,
+                                         dwSubAuthority7,
+                                         pSid);
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+CopySid(DWORD nDestinationSidLength,
+        PSID pDestinationSid,
+        PSID pSourceSid)
+{
+    NTSTATUS Status;
+
+    Status = RtlCopySid(nDestinationSidLength,
+                        pDestinationSid,
+                        pSourceSid);
+    if (!NT_SUCCESS (Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+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)
+{
+    DWORD i;
+    WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
+    WCHAR subauthfmt[] = { '-','%','u',0 };
+    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 < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); 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 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 < sizeof(AceRights)/sizeof(AceRights[0]); 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 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 = ';';
+
+    if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
+    {
+        SetLastError(ERROR_INVALID_ACL);
+        return FALSE;
+    }
+
+    piace = pace;
+    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);
+    /* objects not supported */
+    DumpString(&semicolon, 1, pwptr, plen);
+    /* objects not supported */
+    DumpString(&semicolon, 1, pwptr, plen);
+    if (!DumpSid((PSID)&piace->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;
+    int 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;
+}
+
+/******************************************************************************
+ * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
+ * @implemented
+ */
+BOOL WINAPI
+ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
+                                                     DWORD SDRevision,
+                                                     SECURITY_INFORMATION SecurityInformation,
+                                                     LPWSTR *OutputString,
+                                                     PULONG OutputLen)
+{
+    ULONG len;
+    WCHAR *wptr, *wstr;
+
+    if (SDRevision != SDDL_REVISION_1)
+    {
+        ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
+        SetLastError(ERROR_UNKNOWN_REVISION);
+        return FALSE;
+    }
+
+    len = 0;
+    if (SecurityInformation & OWNER_SECURITY_INFORMATION)
+        if (!DumpOwner(SecurityDescriptor, NULL, &len))
+            return FALSE;
+    if (SecurityInformation & GROUP_SECURITY_INFORMATION)
+        if (!DumpGroup(SecurityDescriptor, NULL, &len))
+            return FALSE;
+    if (SecurityInformation & DACL_SECURITY_INFORMATION)
+        if (!DumpDacl(SecurityDescriptor, NULL, &len))
+            return FALSE;
+    if (SecurityInformation & SACL_SECURITY_INFORMATION)
+        if (!DumpSacl(SecurityDescriptor, NULL, &len))
+            return FALSE;
+
+    wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
+    if (SecurityInformation & OWNER_SECURITY_INFORMATION)
+        if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
+            return FALSE;
+    if (SecurityInformation & GROUP_SECURITY_INFORMATION)
+        if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
+            return FALSE;
+    if (SecurityInformation & DACL_SECURITY_INFORMATION)
+        if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
+            return FALSE;
+    if (SecurityInformation & SACL_SECURITY_INFORMATION)
+        if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
+            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.@]
+ * @implemented
+ */
+BOOL WINAPI
+ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
+                                                     DWORD SDRevision,
+                                                     SECURITY_INFORMATION Information,
+                                                     LPSTR *OutputString,
+                                                     PULONG OutputLen)
+{
+    LPWSTR wstr;
+    ULONG len;
+    if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
+    {
+        int lenA;
+
+        lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
+        *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
+        WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
+        LocalFree(wstr);
+
+        if (OutputLen != NULL)
+            *OutputLen = lenA;
+        return TRUE;
+    }
+    else
+    {
+        *OutputString = NULL;
+        if (OutputLen)
+            *OutputLen = 0;
+        return FALSE;
+    }
+}
+
+
+/******************************************************************************
+ * 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 < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
+            if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
+                return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
+    }
+
+    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\n");
+        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 < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); 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;
+            }
 
-/* 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;
-}
+        if (!bret)
+            FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
+    }
 
-#define        WINE_SIZE_OF_WORLD_ACCESS_ACL   (sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(sidWorld) - sizeof(DWORD))
+lend:
+    if (!bret)
+        SetLastError(ERROR_INVALID_SID);
 
+    TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
+    return bret;
+}
 
-/* some helper functions - taken from winehq cvs 20050916 */
 /******************************************************************************
- * ComputeStringSidSize
+ * ParseAclStringFlags
  */
-static DWORD ComputeStringSidSize(LPCWSTR StringSid)
+static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
 {
-    int ctok = 0;
-    DWORD size = sizeof(SID);
+    DWORD flags = 0;
+    LPCWSTR szAcl = *StringAcl;
 
-    while (*StringSid)
+    while (*szAcl != '(')
     {
-        if (*StringSid == '-')
-            ctok++;
-        StringSid++;
+        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++;
     }
 
-    if (ctok > 3)
-        size += (ctok - 3) * sizeof(DWORD);
-
-    return size;
+    *StringAcl = szAcl;
+    return flags;
 }
 
 /******************************************************************************
@@ -106,14 +936,16 @@ static DWORD ComputeStringSidSize(LPCWSTR StringSid)
  */
 static const ACEFLAG AceType[] =
 {
-    { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
     { 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_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 },
 };
 
@@ -181,19 +1013,6 @@ static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
 /******************************************************************************
  * 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 },
-    { NULL, 0 },
-};
-
 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
 {
     UINT len = 0;
@@ -207,10 +1026,10 @@ static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
        while (*p && *p != ';')
             p++;
 
-       if (p - szAcl <= 8)
+       if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
        {
            rights = strtoulW(szAcl, NULL, 16);
-           *StringAcl = p;
+           szAcl = p;
        }
        else
             WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
@@ -240,6 +1059,7 @@ static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
     return rights;
 }
 
+
 /******************************************************************************
  * ParseStringAclToAcl
  * 
@@ -251,6 +1071,8 @@ static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
     DWORD val;
     DWORD sidlen;
     DWORD length = sizeof(ACL);
+    DWORD acesize = 0;
+    DWORD acecount = 0;
     PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
 
     TRACE("%s\n", debugstr_w(StringAcl));
@@ -259,7 +1081,7 @@ static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
        return FALSE;
 
     if (pAcl) /* pAce is only useful if we're setting values */
-        pAce = (PACCESS_ALLOWED_ACE) ((LPBYTE)pAcl + sizeof(PACL));
+        pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
 
     /* Parse ACL flags */
     *lpdwFlags = ParseAclStringFlags(&StringAcl);
@@ -310,7 +1132,7 @@ static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
         StringAcl++;
 
         /* Parse ACE account sid */
-        if (ParseStringSidToSid(StringAcl, pAce ? (PSID)&pAce->SidStart : NULL, &sidlen))
+        if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
        {
             while (*StringAcl && *StringAcl != ')')
                 StringAcl++;
@@ -320,23 +1142,47 @@ static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
             goto lerr;
         StringAcl++;
 
-       length += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
+        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_INVALID_ACL);
     WARN("Invalid ACE string format\n");
     return FALSE;
 }
 
+
 /******************************************************************************
  * ParseStringSecurityDescriptorToSecurityDescriptor
  */
 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
     LPCWSTR StringSecurityDescriptor,
-    SECURITY_DESCRIPTOR* SecurityDescriptor,
+    SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
     LPDWORD cBytes)
 {
     BOOL bret = FALSE;
@@ -346,346 +1192,130 @@ static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
     LPBYTE lpNext = NULL;
     DWORD len;
 
-    *cBytes = 0;
+    *cBytes = sizeof(SECURITY_DESCRIPTOR);
 
     if (SecurityDescriptor)
-        lpNext = ((LPBYTE) SecurityDescriptor) + sizeof(SECURITY_DESCRIPTOR);
+        lpNext = (LPBYTE)(SecurityDescriptor + 1);
 
     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)
+        toktype = *StringSecurityDescriptor;
+
+       /* Expect char identifier followed by ':' */
+       StringSecurityDescriptor++;
+        if (*StringSecurityDescriptor != ':')
         {
-            TRACE("SubAuthorityCount is 0\n");
-            goto lend; /* ERROR_INVALID_SID */
+            SetLastError(ERROR_INVALID_PARAMETER);
+            goto lend;
         }
+       StringSecurityDescriptor++;
 
-       pisid->SubAuthorityCount = csubauth;
+       /* Extract token */
+       lptoken = StringSecurityDescriptor;
+       while (*lptoken && *lptoken != ':')
+            lptoken++;
 
-        /* Advance to identifier authority */
-       while (*StringSid && *StringSid != '-')
-            StringSid++;
-        if (*StringSid == '-')
-            StringSid++;
+       if (*lptoken)
+            lptoken--;
 
-        /* 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;
+        len = lptoken - StringSecurityDescriptor;
+        memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
+        tok[len] = 0;
 
-        /* Advance to first sub authority */
-        while (*StringSid && *StringSid != '-')
-            StringSid++;
-        if (*StringSid == '-')
-            StringSid++;
+        switch (toktype)
+       {
+            case 'O':
+            {
+                DWORD bytes;
 
-        while (*StringSid)
-       {       
-           while (*StringSid && *StringSid != '-')
-                StringSid++;
+                if (!ParseStringSidToSid(tok, lpNext, &bytes))
+                    goto lend;
 
-            pisid->SubAuthority[i++] = atoiW(StringSid);
-        }
+                if (SecurityDescriptor)
+                {
+                    SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
+                    lpNext += bytes; /* Advance to next token */
+                }
 
-       if (i != pisid->SubAuthorityCount)
-            goto lend; /* ERROR_INVALID_SID */
+               *cBytes += bytes;
 
-        bret = TRUE;
-    }
-    else /* String constant format  - Only available in winxp and above */
-    {
-        pisid->Revision = SDDL_REVISION;
-       pisid->SubAuthorityCount = 1;
+                break;
+            }
 
-       FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
+            case 'G':
+            {
+                DWORD bytes;
 
-       /* TODO: Lookup string of well-known SIDs in table */
-       pisid->IdentifierAuthority.Value[5] = 0;
-       pisid->SubAuthority[0] = 0;
+                if (!ParseStringSidToSid(tok, lpNext, &bytes))
+                    goto lend;
 
-        bret = TRUE;
-    }
+                if (SecurityDescriptor)
+                {
+                    SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
+                    lpNext += bytes; /* Advance to next token */
+                }
 
-lend:
-    if (!bret)
-        SetLastError(ERROR_INVALID_SID);
+               *cBytes += bytes;
 
-    TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
-    return bret;
-}
+                break;
+            }
 
-/* Exported functions */
+            case 'D':
+           {
+                DWORD flags;
+                DWORD bytes;
 
-/*
- * @implemented
- */
-BOOL STDCALL
-AllocateLocallyUniqueId(PLUID Luid)
-{
-  NTSTATUS Status;
+                if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
+                    goto lend;
 
-  Status = NtAllocateLocallyUniqueId (Luid);
-  if (!NT_SUCCESS (Status))
-    {
-      SetLastError (RtlNtStatusToDosError (Status));
-      return FALSE;
-    }
+                if (SecurityDescriptor)
+                {
+                    SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
+                    SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
+                    lpNext += bytes; /* Advance to next token */
+               }
 
-  return TRUE;
-}
+               *cBytes += bytes;
 
+               break;
+            }
 
-/*
- * @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,
-                                             dwSubAuthority2,
-                                             dwSubAuthority3,
-                                             dwSubAuthority4,
-                                             dwSubAuthority5,
-                                             dwSubAuthority6,
-                                             dwSubAuthority7,
-                                             pSid);
-  if (!NT_SUCCESS (Status))
-    {
-      SetLastError (RtlNtStatusToDosError (Status));
-      return FALSE;
-    }
+            case 'S':
+            {
+                DWORD flags;
+                DWORD bytes;
 
-  return TRUE;
-}
+                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 */
+               }
 
-/*
- * @implemented
- */
-BOOL STDCALL
-CopySid (DWORD nDestinationSidLength,
-        PSID pDestinationSid,
-        PSID pSourceSid)
-{
-  NTSTATUS Status;
+               *cBytes += bytes;
 
-  Status = RtlCopySid (nDestinationSidLength,
-                      pDestinationSid,
-                      pSourceSid);
-  if (!NT_SUCCESS (Status))
-    {
-      SetLastError (RtlNtStatusToDosError (Status));
-      return FALSE;
+               break;
+            }
+
+            default:
+                FIXME("Unknown token\n");
+                SetLastError(ERROR_INVALID_PARAMETER);
+               goto lend;
+       }
+
+        StringSecurityDescriptor = lptoken;
     }
 
-  return TRUE;
+    bret = TRUE;
+
+lend:
+    return bret;
 }
-/* Winehq cvs 20050916 */
+
+
 /******************************************************************************
  * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
  * @implemented
@@ -707,6 +1337,11 @@ BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
         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);
@@ -718,14 +1353,14 @@ BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
         NULL, &cBytes))
        goto lend;
 
-    psd = *SecurityDescriptor = (SECURITY_DESCRIPTOR*) LocalAlloc(
-        GMEM_ZEROINIT, cBytes);
+    psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
+    if (!psd) goto lend;
 
     psd->Revision = SID_REVISION;
     psd->Control |= SE_SELF_RELATIVE;
 
     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
-        psd, &cBytes))
+             (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
     {
         LocalFree(psd);
        goto lend;
@@ -741,6 +1376,7 @@ lend:
     return bret;
 }
 
+
 /* Winehq cvs 20050916 */
 /******************************************************************************
  * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
@@ -775,22 +1411,22 @@ BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
 /*
  * @implemented
  */
-BOOL STDCALL
-EqualPrefixSid (PSID pSid1,
-               PSID pSid2)
+BOOL WINAPI
+EqualPrefixSid(PSID pSid1,
+               PSID pSid2)
 {
-  return RtlEqualPrefixSid (pSid1, pSid2);
+    return RtlEqualPrefixSid (pSid1, pSid2);
 }
 
 
 /*
  * @implemented
  */
-BOOL STDCALL
-EqualSid (PSID pSid1,
-         PSID pSid2)
+BOOL WINAPI
+EqualSid(PSID pSid1,
+         PSID pSid2)
 {
-  return RtlEqualSid (pSid1, pSid2);
+    return RtlEqualSid (pSid1, pSid2);
 }
 
 
@@ -801,199 +1437,204 @@ EqualSid (PSID pSid1,
  *  Docs says this function does NOT return a value
  *  even thou it's defined to return a PVOID...
  */
-PVOID STDCALL
-FreeSid (PSID pSid)
+PVOID WINAPI
+FreeSid(PSID pSid)
 {
-   return RtlFreeSid (pSid);
+    return RtlFreeSid(pSid);
 }
 
 
 /*
  * @implemented
  */
-DWORD STDCALL
-GetLengthSid (PSID pSid)
+DWORD WINAPI
+GetLengthSid(PSID pSid)
 {
-  return (DWORD)RtlLengthSid (pSid);
+    return (DWORD)RtlLengthSid(pSid);
 }
 
 
 /*
  * @implemented
  */
-PSID_IDENTIFIER_AUTHORITY STDCALL
-GetSidIdentifierAuthority (PSID pSid)
+PSID_IDENTIFIER_AUTHORITY WINAPI
+GetSidIdentifierAuthority(PSID pSid)
 {
-  return RtlIdentifierAuthoritySid (pSid);
+    return RtlIdentifierAuthoritySid(pSid);
 }
 
 
 /*
  * @implemented
  */
-DWORD STDCALL
-GetSidLengthRequired (UCHAR nSubAuthorityCount)
+DWORD WINAPI
+GetSidLengthRequired(UCHAR nSubAuthorityCount)
 {
-  return (DWORD)RtlLengthRequiredSid (nSubAuthorityCount);
+    return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
 }
 
 
 /*
  * @implemented
  */
-PDWORD STDCALL
-GetSidSubAuthority (PSID pSid,
-                   DWORD nSubAuthority)
+PDWORD WINAPI
+GetSidSubAuthority(PSID pSid,
+                   DWORD nSubAuthority)
 {
-  return (PDWORD)RtlSubAuthoritySid (pSid, nSubAuthority);
+    return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority);
 }
 
 
 /*
  * @implemented
  */
-PUCHAR STDCALL
-GetSidSubAuthorityCount (PSID pSid)
+PUCHAR WINAPI
+GetSidSubAuthorityCount(PSID pSid)
 {
-  return RtlSubAuthorityCountSid (pSid);
+    return RtlSubAuthorityCountSid(pSid);
 }
 
 
 /*
  * @implemented
  */
-BOOL STDCALL
-InitializeSid (PSID Sid,
-              PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
-              BYTE nSubAuthorityCount)
+BOOL WINAPI
+InitializeSid(PSID Sid,
+              PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
+              BYTE nSubAuthorityCount)
 {
-  NTSTATUS Status;
+    NTSTATUS Status;
 
-  Status = RtlInitializeSid (Sid,
-                            pIdentifierAuthority,
-                            nSubAuthorityCount);
-  if (!NT_SUCCESS (Status))
+    Status = RtlInitializeSid(Sid,
+                              pIdentifierAuthority,
+                              nSubAuthorityCount);
+    if (!NT_SUCCESS(Status))
     {
-      SetLastError (RtlNtStatusToDosError (Status));
-      return FALSE;
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
     }
 
-  return TRUE;
+    return TRUE;
 }
 
 
 /*
  * @implemented
  */
-BOOL STDCALL
-IsValidSid (PSID pSid)
+BOOL WINAPI
+IsValidSid(PSID pSid)
 {
-  return (BOOL)RtlValidSid (pSid);
+    return (BOOL)RtlValidSid(pSid);
 }
 
+
 /*
  * @implemented
  */
-BOOL STDCALL
-ConvertSidToStringSidW(PSID Sid, LPWSTR *StringSid)
+BOOL WINAPI
+ConvertSidToStringSidW(PSID Sid,
+                       LPWSTR *StringSid)
 {
-  NTSTATUS Status;
-  UNICODE_STRING UnicodeString;
-  WCHAR FixedBuffer[64];
+    NTSTATUS Status;
+    UNICODE_STRING UnicodeString;
+    WCHAR FixedBuffer[64];
 
-  if (! RtlValidSid(Sid))
+    if (!RtlValidSid(Sid))
     {
-      SetLastError(ERROR_INVALID_SID);
-      return FALSE;
+        SetLastError(ERROR_INVALID_SID);
+        return FALSE;
     }
 
-  UnicodeString.Length = 0;
-  UnicodeString.MaximumLength = sizeof(FixedBuffer);
-  UnicodeString.Buffer = FixedBuffer;
-  Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
-  if (STATUS_BUFFER_TOO_SMALL == Status)
+    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);
+        Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
     }
-  if (! NT_SUCCESS(Status))
+
+    if (!NT_SUCCESS(Status))
     {
-      SetLastError(RtlNtStatusToDosError(Status));
-      return FALSE;
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
     }
 
-  *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
-  if (NULL == *StringSid)
+    *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
+    if (NULL == *StringSid)
     {
-      if (UnicodeString.Buffer != FixedBuffer)
+        if (UnicodeString.Buffer != FixedBuffer)
         {
-          RtlFreeUnicodeString(&UnicodeString);
+            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)
+    MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
+    ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
+    if (UnicodeString.Buffer != FixedBuffer)
     {
-      RtlFreeUnicodeString(&UnicodeString);
+        RtlFreeUnicodeString(&UnicodeString);
     }
 
-  return TRUE;
+    return TRUE;
 }
 
 
 /*
  * @implemented
  */
-BOOL STDCALL
-ConvertSidToStringSidA(PSID Sid, LPSTR *StringSid)
+BOOL WINAPI
+ConvertSidToStringSidA(PSID Sid,
+                       LPSTR *StringSid)
 {
-  LPWSTR StringSidW;
-  int Len;
+    LPWSTR StringSidW;
+    int Len;
 
-  if (! ConvertSidToStringSidW(Sid, &StringSidW))
+    if (!ConvertSidToStringSidW(Sid, &StringSidW))
     {
-      return FALSE;
+        return FALSE;
     }
 
-  Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
-  if (Len <= 0)
+    Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
+    if (Len <= 0)
     {
-      LocalFree(StringSidW);
-      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
+        LocalFree(StringSidW);
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
     }
-  *StringSid = LocalAlloc(LMEM_FIXED, Len);
-  if (NULL == *StringSid)
+
+    *StringSid = LocalAlloc(LMEM_FIXED, Len);
+    if (NULL == *StringSid)
     {
-      LocalFree(StringSidW);
-      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
+        LocalFree(StringSidW);
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
     }
 
-  if (! WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
+    if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
     {
-      LocalFree(StringSid);
-      LocalFree(StringSidW);
-      return FALSE;
+        LocalFree(StringSid);
+        LocalFree(StringSidW);
+        return FALSE;
     }
 
-  LocalFree(StringSidW);
+    LocalFree(StringSidW);
 
-  return TRUE;
+    return TRUE;
 }
 
 
 /*
  * @unimplemented
  */
-BOOL STDCALL
+BOOL WINAPI
 EqualDomainSid(IN PSID pSid1,
                IN PSID pSid2,
                OUT BOOL* pfEqual)
 {
-    FIXME("%s() not implemented!\n", __FUNCTION__);
+    UNIMPLEMENTED;
     return FALSE;
 }
 
@@ -1001,12 +1642,12 @@ EqualDomainSid(IN PSID pSid1,
 /*
  * @unimplemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetWindowsAccountDomainSid(IN PSID pSid,
                            OUT PSID ppDomainSid,
                            IN OUT DWORD* cbSid)
 {
-    FIXME("%s() not implemented!\n", __FUNCTION__);
+    UNIMPLEMENTED;
     return FALSE;
 }
 
@@ -1014,13 +1655,73 @@ GetWindowsAccountDomainSid(IN PSID pSid,
 /*
  * @unimplemented
  */
-BOOL STDCALL
+BOOL WINAPI
 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
                    IN PSID DomainSid  OPTIONAL,
                    OUT PSID pSid,
                    IN OUT DWORD* cbSid)
 {
-    FIXME("unimplemented!\n", __FUNCTION__);
+    unsigned int i;
+    TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
+
+    if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
+        if (WellKnownSids[i].Type == WellKnownSidType) {
+            DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
+
+            if (*cbSid < length)
+            {
+                *cbSid = length;
+                SetLastError(ERROR_INSUFFICIENT_BUFFER);
+                return FALSE;
+            }
+            if (!pSid)
+            {
+                SetLastError(ERROR_INVALID_PARAMETER);
+                return FALSE;
+            }
+            CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
+            *cbSid = length;
+            return TRUE;
+        }
+    }
+
+    if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
+        if (WellKnownRids[i].Type == WellKnownSidType) {
+            UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
+            DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
+            DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
+
+            if (*cbSid < output_sid_length)
+            {
+                *cbSid = output_sid_length;
+                SetLastError(ERROR_INSUFFICIENT_BUFFER);
+                return FALSE;
+            }
+            if (!pSid)
+            {
+                SetLastError(ERROR_INVALID_PARAMETER);
+                return FALSE;
+            }
+            CopyMemory(pSid, DomainSid, domain_sid_length);
+            (*GetSidSubAuthorityCount(pSid))++;
+            (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
+            *cbSid = output_sid_length;
+            return TRUE;
+        }
+
+    SetLastError(ERROR_INVALID_PARAMETER);
     return FALSE;
 }
 
@@ -1028,11 +1729,22 @@ CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
 /*
  * @unimplemented
  */
-BOOL STDCALL
+BOOL WINAPI
 IsWellKnownSid(IN PSID pSid,
                IN WELL_KNOWN_SID_TYPE WellKnownSidType)
 {
-    FIXME("unimplemented!\n", __FUNCTION__);
+    unsigned int i;
+    TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
+
+    for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
+    {
+        if (WellKnownSids[i].Type == WellKnownSidType)
+        {
+            if (EqualSid(pSid, (PSID)((ULONG_PTR)&WellKnownSids[i].Sid.Revision)))
+                return TRUE;
+        }
+    }
+
     return FALSE;
 }
 
@@ -1040,10 +1752,9 @@ IsWellKnownSid(IN PSID pSid,
 /*
  * @implemented
  */
-BOOL STDCALL
-ConvertStringSidToSidA(
-                IN LPCSTR StringSid,
-                OUT PSID* sid)
+BOOL WINAPI
+ConvertStringSidToSidA(IN LPCSTR StringSid,
+                       OUT PSID* sid)
 {
     BOOL bRetVal = FALSE;
 
@@ -1060,16 +1771,176 @@ ConvertStringSidToSidA(
     return bRetVal;
 }
 
+
+static const RECORD SidTable[] =
+{
+       { SDDL_ACCOUNT_OPERATORS, WinBuiltinAccountOperatorsSid },
+       { SDDL_ALIAS_PREW2KCOMPACC, WinBuiltinPreWindows2000CompatibleAccessSid },
+       { SDDL_ANONYMOUS, WinAnonymousSid },
+       { SDDL_AUTHENTICATED_USERS, WinAuthenticatedUserSid },
+       { SDDL_BUILTIN_ADMINISTRATORS, WinBuiltinAdministratorsSid },
+       { SDDL_BUILTIN_GUESTS, WinBuiltinGuestsSid },
+       { SDDL_BACKUP_OPERATORS, WinBuiltinBackupOperatorsSid },
+       { SDDL_BUILTIN_USERS, WinBuiltinUsersSid },
+       { SDDL_CERT_SERV_ADMINISTRATORS, WinAccountCertAdminsSid /* FIXME: DOMAIN_GROUP_RID_CERT_ADMINS */ },
+       { SDDL_CREATOR_GROUP, WinCreatorGroupSid },
+       { SDDL_CREATOR_OWNER, WinCreatorOwnerSid },
+       { SDDL_DOMAIN_ADMINISTRATORS, WinAccountDomainAdminsSid /* FIXME: DOMAIN_GROUP_RID_ADMINS */ },
+       { SDDL_DOMAIN_COMPUTERS, WinAccountComputersSid /* FIXME: DOMAIN_GROUP_RID_COMPUTERS */ },
+       { SDDL_DOMAIN_DOMAIN_CONTROLLERS, WinAccountControllersSid /* FIXME: DOMAIN_GROUP_RID_CONTROLLERS */ },
+       { SDDL_DOMAIN_GUESTS, WinAccountDomainGuestsSid /* FIXME: DOMAIN_GROUP_RID_GUESTS */ },
+       { SDDL_DOMAIN_USERS, WinAccountDomainUsersSid /* FIXME: DOMAIN_GROUP_RID_USERS */ },
+       { SDDL_ENTERPRISE_ADMINS, WinAccountEnterpriseAdminsSid /* FIXME: DOMAIN_GROUP_RID_ENTERPRISE_ADMINS */ },
+       { SDDL_ENTERPRISE_DOMAIN_CONTROLLERS, WinLogonIdsSid /* FIXME: SECURITY_SERVER_LOGON_RID */ },
+       { SDDL_EVERYONE, WinWorldSid },
+       { SDDL_GROUP_POLICY_ADMINS, WinAccountPolicyAdminsSid /* FIXME: DOMAIN_GROUP_RID_POLICY_ADMINS */ },
+       { SDDL_INTERACTIVE, WinInteractiveSid },
+       { SDDL_LOCAL_ADMIN, WinAccountAdministratorSid /* FIXME: DOMAIN_USER_RID_ADMIN */ },
+       { SDDL_LOCAL_GUEST, WinAccountGuestSid /* FIXME: DOMAIN_USER_RID_GUEST */ },
+       { SDDL_LOCAL_SERVICE, WinLocalServiceSid },
+       { SDDL_LOCAL_SYSTEM, WinLocalSystemSid },
+       { SDDL_NETWORK, WinNetworkSid },
+       { SDDL_NETWORK_CONFIGURATION_OPS, WinBuiltinNetworkConfigurationOperatorsSid },
+       { SDDL_NETWORK_SERVICE, WinNetworkServiceSid },
+       { SDDL_PRINTER_OPERATORS, WinBuiltinPrintOperatorsSid },
+       { SDDL_PERSONAL_SELF, WinSelfSid },
+       { SDDL_POWER_USERS, WinBuiltinPowerUsersSid },
+       { SDDL_RAS_SERVERS, WinAccountRasAndIasServersSid /* FIXME: DOMAIN_ALIAS_RID_RAS_SERVERS */ },
+       { SDDL_REMOTE_DESKTOP, WinBuiltinRemoteDesktopUsersSid },
+       { SDDL_REPLICATOR, WinBuiltinReplicatorSid },
+       { SDDL_RESTRICTED_CODE, WinRestrictedCodeSid },
+       { SDDL_SCHEMA_ADMINISTRATORS, WinAccountSchemaAdminsSid /* FIXME: DOMAIN_GROUP_RID_SCHEMA_ADMINS */ },
+       { SDDL_SERVER_OPERATORS, WinBuiltinSystemOperatorsSid },
+       { SDDL_SERVICE, WinServiceSid },
+       { NULL, 0 },
+};
+
 /*
- * @unimplemented
+ * @implemented
  */
-BOOL STDCALL
-ConvertStringSidToSidW(
-                IN LPCWSTR StringSid,
-                OUT PSID* sid)
+BOOL WINAPI
+ConvertStringSidToSidW(IN LPCWSTR StringSid,
+                       OUT PSID* sid)
 {
-    FIXME("unimplemented!\n", __FUNCTION__);
-    return FALSE;
+    DWORD size;
+    DWORD i, cBytes, identAuth, csubauth;
+    BOOL ret;
+    SID* pisid;
+
+    TRACE("%s %p\n", debugstr_w(StringSid), sid);
+
+       if (!StringSid)
+       {
+               SetLastError(ERROR_INVALID_SID);
+               return FALSE;
+       }
+       for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
+       {
+               if (wcscmp(StringSid, SidTable[i].key) == 0)
+               {
+                       WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
+                       size = SECURITY_MAX_SID_SIZE;
+                       *sid = LocalAlloc(0, size);
+                       if (!*sid)
+                       {
+                               SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                               return FALSE;
+                       }
+                       ret = CreateWellKnownSid(
+                               knownSid,
+                               NULL,
+                               *sid,
+                               &size);
+                       if (!ret)
+                       {
+                               SetLastError(ERROR_INVALID_SID);
+                               LocalFree(*sid);
+                       }
+                       return ret;
+               }
+       }
+
+       /* That's probably a string S-R-I-S-S... */
+       if (StringSid[0] != 'S' || StringSid[1] != '-')
+       {
+               SetLastError(ERROR_INVALID_SID);
+               return FALSE;
+       }
+
+    cBytes = ComputeStringSidSize(StringSid);
+    pisid = (SID*)LocalAlloc( 0, cBytes );
+    if (!pisid)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+    i = 0;
+    ret = FALSE;
+    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++;
+
+    pisid->SubAuthority[i] = atoiW(StringSid);
+
+    while (*StringSid)
+    {
+        while (*StringSid && *StringSid != '-')
+            StringSid++;
+        if (*StringSid == '-')
+            StringSid++;
+
+        pisid->SubAuthority[++i] = atoiW(StringSid);
+    }
+
+    if (i != pisid->SubAuthorityCount)
+        goto lend; /* ERROR_INVALID_SID */
+
+    *sid = pisid;
+    ret = TRUE;
+
+lend:
+    if (!ret)
+        SetLastError(ERROR_INVALID_SID);
+
+    TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
+    return ret;
 }