From 47ef13cf4aa703290adffa970a937022963a5012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Wed, 11 Oct 2006 22:14:05 +0000 Subject: [PATCH] Replace incomplete and broken implementations of ConvertStringSecurityDescriptorToSecurityDescriptorW and ConvertStringSidToSidW by new ones svn path=/trunk/; revision=24490 --- reactos/dll/win32/advapi32/advapi32.rbuild | 2 + reactos/dll/win32/advapi32/sec/ac.c | 10 +- reactos/dll/win32/advapi32/sec/misc.c | 6 +- reactos/dll/win32/advapi32/sec/sid.c | 1289 +++++++++++--------- 4 files changed, 718 insertions(+), 589 deletions(-) diff --git a/reactos/dll/win32/advapi32/advapi32.rbuild b/reactos/dll/win32/advapi32/advapi32.rbuild index 07b0a5420d9..776a8ca930d 100644 --- a/reactos/dll/win32/advapi32/advapi32.rbuild +++ b/reactos/dll/win32/advapi32/advapi32.rbuild @@ -7,6 +7,8 @@ 0x600 0x0500 0x0600 + + scm_client lsa_client ntdll diff --git a/reactos/dll/win32/advapi32/sec/ac.c b/reactos/dll/win32/advapi32/sec/ac.c index 3bf16a393c5..184231db08b 100644 --- a/reactos/dll/win32/advapi32/sec/ac.c +++ b/reactos/dll/win32/advapi32/sec/ac.c @@ -536,7 +536,7 @@ GetInheritanceSourceA ( PACL pAcl, PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL, PGENERIC_MAPPING pGenericMapping, - PINHERITED_FROM pInheritArray + PINHERITED_FROMA pInheritArray ) { /* That's all this function does, at least up to w2k3... Even MS was too @@ -609,14 +609,14 @@ InternalTrusteeAToW(IN PTRUSTEE_A pTrusteeA, //ASSERT(sizeof(TRUSTEE_W) == sizeof(TRUSTEE_A)); - TrusteeForm = GetTrusteeForm(pTrusteeA); + TrusteeForm = GetTrusteeFormA(pTrusteeA); switch (TrusteeForm) { case TRUSTEE_IS_NAME: { /* directly copy the array, this works as the size of the EXPLICIT_ACCESS_A structure matches the size of the EXPLICIT_ACCESS_W version */ - lpStr = GetTrusteeName(pTrusteeA); + lpStr = GetTrusteeNameA(pTrusteeA); if (lpStr != NULL) BufferSize = strlen(lpStr) + 1; @@ -800,7 +800,7 @@ InternalExplicitAccessAToW(IN ULONG cCountOfExplicitEntries, Size = cCountOfExplicitEntries * sizeof(EXPLICIT_ACCESS_W); for (i = 0; i != cCountOfExplicitEntries; i++) { - TrusteeForm = GetTrusteeForm(&pListOfExplicitEntriesA[i].Trustee); + TrusteeForm = GetTrusteeFormA(&pListOfExplicitEntriesA[i].Trustee); switch (TrusteeForm) { @@ -852,7 +852,7 @@ InternalExplicitAccessAToW(IN ULONG cCountOfExplicitEntries, peaw[i].grfInheritance = pListOfExplicitEntriesA[i].grfInheritance; /* convert or copy the TRUSTEE structure */ - TrusteeForm = GetTrusteeForm(&pListOfExplicitEntriesA[i].Trustee); + TrusteeForm = GetTrusteeFormA(&pListOfExplicitEntriesA[i].Trustee); switch (TrusteeForm) { case TRUSTEE_IS_NAME: diff --git a/reactos/dll/win32/advapi32/sec/misc.c b/reactos/dll/win32/advapi32/sec/misc.c index 927a8e35a92..ae5ca3656b1 100644 --- a/reactos/dll/win32/advapi32/sec/misc.c +++ b/reactos/dll/win32/advapi32/sec/misc.c @@ -916,7 +916,7 @@ LookupAccountSidW ( { *pdwAccountName = dwSrcLen; RtlCopyMemory ( pAccountName, TranslatedName->Name.Buffer, TranslatedName->Name.Length ); - pAccountName[TranslatedName->Name.Length / sizeof(WCHAR)] = L'\0'; + pAccountName[TranslatedName->Name.Length / sizeof(WCHAR)] = L'\0'; } if ( peUse ) *peUse = TranslatedName->Use; @@ -936,7 +936,7 @@ LookupAccountSidW ( { *pdwDomainName = dwSrcLen; RtlCopyMemory ( pDomainName, ReferencedDomain->Domains[0].Name.Buffer, ReferencedDomain->Domains[0].Name.Length ); - pDomainName[ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR)] = L'\0'; + pDomainName[ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR)] = L'\0'; } } } @@ -1960,7 +1960,7 @@ InternalfnProgressW(LPWSTR pObjectName, NULL, NULL); - pifnProgressData->fnProgress(pObjectNameA, + pifnProgressData->fnProgress((LPWSTR)pObjectNameA, /* FIXME: wrong cast!! */ Status, pInvokeSetting, pifnProgressData->Args, diff --git a/reactos/dll/win32/advapi32/sec/sid.c b/reactos/dll/win32/advapi32/sec/sid.c index c4658957642..6b38fc573e4 100644 --- a/reactos/dll/win32/advapi32/sec/sid.c +++ b/reactos/dll/win32/advapi32/sec/sid.c @@ -1,9 +1,9 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * WINE COPYRIGHT: * Copyright 1999, 2000 Juergen Schmied * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla) + * Copyright 2006 Hervé Poussineau * * PROJECT: ReactOS system libraries * FILE: lib/advapi32/sec/sid.c @@ -11,25 +11,20 @@ */ #include +#include #include #include WINE_DEFAULT_DEBUG_CHANNEL(advapi); +#define MAX_GUID_STRING_LEN 39 -static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes); -static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, - PACL pAcl, LPDWORD cBytes); -static BYTE ParseAceStringFlags(LPCWSTR* StringAcl); -static BYTE ParseAceStringType(LPCWSTR* StringAcl); -static DWORD ParseAceStringRights(LPCWSTR* StringAcl); -static DWORD ParseAclStringFlags(LPCWSTR* StringAcl); - -typedef struct _ACEFLAG +typedef struct RECORD { - LPCWSTR wstr; - DWORD value; -} ACEFLAG, *LPACEFLAG; + LPCWSTR key; + DWORD value; +} RECORD; + typedef struct _MAX_SID { @@ -90,18 +85,6 @@ static const WELLKNOWNSID WellKnownSids[] = static const SID sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } }; -/* - * ACE access rights - */ -static const WCHAR SDDL_READ_CONTROL[] = {'R','C',0}; -static const WCHAR SDDL_WRITE_DAC[] = {'W','D',0}; -static const WCHAR SDDL_WRITE_OWNER[] = {'W','O',0}; -static const WCHAR SDDL_STANDARD_DELETE[] = {'S','D',0}; -static const WCHAR SDDL_GENERIC_ALL[] = {'G','A',0}; -static const WCHAR SDDL_GENERIC_READ[] = {'G','R',0}; -static const WCHAR SDDL_GENERIC_WRITE[] = {'G','W',0}; -static const WCHAR SDDL_GENERIC_EXECUTE[] = {'G','X',0}; - /* * ACE types */ @@ -114,6 +97,19 @@ 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}; +/* + * 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 */ @@ -184,532 +180,343 @@ static __inline BOOL set_ntstatus( NTSTATUS status ) return !status; } -#define WINE_SIZE_OF_WORLD_ACCESS_ACL (sizeof(ACL) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + sizeof(sidWorld)) - - -/* some helper functions - taken from winehq cvs 20050916 */ -/****************************************************************************** - * ComputeStringSidSize - */ -static DWORD ComputeStringSidSize(LPCWSTR StringSid) +static BOOL +FindKeyInTable( + IN const RECORD* Table, + IN LPCWSTR Key, + OUT SIZE_T* pKeyLength, + OUT DWORD* pItem) { - int ctok = 0; - DWORD size = sizeof(SID); - - while (*StringSid) - { - if (*StringSid == '-') - ctok++; - StringSid++; - } - - if (ctok > 3) - size += (ctok - 3) * sizeof(DWORD); - - return size; -} - -/****************************************************************************** - * ParseAceStringType - */ -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_DENIED, ACCESS_DENIED_ACE_TYPE }, - { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE }, - { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE }, - { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE }, - { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE }, - { NULL, 0 }, -}; - -static BYTE ParseAceStringType(LPCWSTR* StringAcl) -{ - UINT len = 0; - LPCWSTR szAcl = *StringAcl; - const ACEFLAG *lpaf = AceType; - - while (lpaf->wstr && - (len = strlenW(lpaf->wstr)) && - strncmpW(lpaf->wstr, szAcl, len)) - lpaf++; - - if (!lpaf->wstr) - return 0; - - *StringAcl += len; - return lpaf->value; -} - - -/****************************************************************************** - * ParseAceStringFlags - */ -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 != ';') - { - 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 }, - { NULL, 0 }, -}; - -static DWORD ParseAceStringRights(LPCWSTR* StringAcl) -{ - UINT len = 0; - DWORD rights = 0; - LPCWSTR szAcl = *StringAcl; - - if ((*szAcl == '0') && (*(szAcl + 1) == 'x')) - { - LPCWSTR p = szAcl; - - while (*p && *p != ';') - p++; - - if (p - szAcl <= 8) + const RECORD* pRecord = Table; + while (pRecord->key != NULL) { - rights = strtoulW(szAcl, NULL, 16); - *StringAcl = 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); - PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */ - - TRACE("%s\n", debugstr_w(StringAcl)); - - if (!StringAcl) - return FALSE; - - if (pAcl) /* pAce is only useful if we're setting values */ - pAce = (PACCESS_ALLOWED_ACE) ((LPBYTE)pAcl + sizeof(PACL)); - - /* Parse ACL flags */ - *lpdwFlags = ParseAclStringFlags(&StringAcl); - - /* Parse ACE */ - while (*StringAcl == '(') - { - StringAcl++; - - /* Parse ACE type */ - val = ParseAceStringType(&StringAcl); - if (pAce) - pAce->Header.AceType = (BYTE) val; - if (*StringAcl != ';') - goto lerr; - StringAcl++; - - /* Parse ACE flags */ - val = ParseAceStringFlags(&StringAcl); - if (pAce) - pAce->Header.AceFlags = (BYTE) val; - if (*StringAcl != ';') - goto lerr; - StringAcl++; - - /* Parse ACE rights */ - val = ParseAceStringRights(&StringAcl); - if (pAce) - pAce->Mask = val; - if (*StringAcl != ';') - goto lerr; - StringAcl++; - - /* Parse ACE object guid */ - if (*StringAcl != ';') - { - FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n"); - goto lerr; - } - StringAcl++; - - /* Parse ACE inherit object guid */ - if (*StringAcl != ';') - { - FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n"); - goto lerr; - } - StringAcl++; - - /* Parse ACE account sid */ - if (ParseStringSidToSid(StringAcl, pAce ? (PSID)&pAce->SidStart : NULL, &sidlen)) - { - while (*StringAcl && *StringAcl != ')') - StringAcl++; - } - - if (*StringAcl != ')') - goto lerr; - StringAcl++; - - length += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + sidlen; - } - - *cBytes = length; - return TRUE; - -lerr: - WARN("Invalid ACE string format\n"); - return FALSE; -} - -/****************************************************************************** - * ParseStringSecurityDescriptorToSecurityDescriptor - */ -static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( - LPCWSTR StringSecurityDescriptor, - SECURITY_DESCRIPTOR* SecurityDescriptor, - LPDWORD cBytes) -{ - BOOL bret = FALSE; - WCHAR toktype; - WCHAR tok[MAX_PATH]; - LPCWSTR lptoken; - LPBYTE lpNext = NULL; - DWORD len; - - *cBytes = 0; - - if (SecurityDescriptor) - lpNext = ((LPBYTE) SecurityDescriptor) + sizeof(SECURITY_DESCRIPTOR); - - while (*StringSecurityDescriptor) - { - toktype = *StringSecurityDescriptor; - - /* Expect char identifier followed by ':' */ - StringSecurityDescriptor++; - if (*StringSecurityDescriptor != ':') - { - SetLastError(ERROR_INVALID_PARAMETER); - goto lend; - } - StringSecurityDescriptor++; - - /* Extract token */ - lptoken = StringSecurityDescriptor; - while (*lptoken && *lptoken != ':') - lptoken++; - - if (*lptoken) - lptoken--; - - len = lptoken - StringSecurityDescriptor; - memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) ); - tok[len] = 0; - - switch (toktype) - { - case 'O': - { - DWORD bytes; - - if (!ParseStringSidToSid(tok, (PSID)lpNext, &bytes)) - goto lend; - - if (SecurityDescriptor) - { - SecurityDescriptor->Owner = (PSID) ((DWORD) lpNext - - (DWORD) SecurityDescriptor); - lpNext += bytes; /* Advance to next token */ - } - - *cBytes += bytes; - - break; - } - - case 'G': - { - DWORD bytes; - - if (!ParseStringSidToSid(tok, (PSID)lpNext, &bytes)) - goto lend; - - if (SecurityDescriptor) - { - SecurityDescriptor->Group = (PSID) ((DWORD) lpNext - - (DWORD) SecurityDescriptor); - lpNext += bytes; /* Advance to next token */ - } - - *cBytes += bytes; - - break; - } - - case 'D': - { - DWORD flags; - DWORD bytes; - - if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes)) - goto lend; - - if (SecurityDescriptor) - { - SecurityDescriptor->Control |= SE_DACL_PRESENT | flags; - SecurityDescriptor->Dacl = (PACL) ((DWORD) lpNext - - (DWORD) SecurityDescriptor); - lpNext += bytes; /* Advance to next token */ + if (wcsncmp(pRecord->key, Key, wcslen(pRecord->key)) == 0) + { + *pKeyLength = wcslen(pRecord->key); + *pItem = pRecord->value; + return TRUE; } - - *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; + pRecord++; } - - 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"); + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; - } +} - *cBytes = ComputeStringSidSize(StringSid); - if (!pisid) /* Simply compute the size */ - { - TRACE("only size requested, returning TRUE\n"); - return TRUE; - } +static BOOL +ParseSidString( + IN LPCWSTR Buffer, + OUT PSID* pSid, + OUT SIZE_T* pLength) +{ + WCHAR str[SDDL_ALIAS_SIZE + 1]; + LPWSTR strSid; + LPCWSTR end; + BOOL ret; + DWORD i; - if (*StringSid != 'S' || *StringSid != '-') /* S-R-I-S-S */ - { - DWORD i = 0, identAuth; - DWORD csubauth = ((*cBytes - sizeof(SID)) / sizeof(DWORD)) + 1; + wcsncpy(str, Buffer, SDDL_ALIAS_SIZE); + for (i = SDDL_ALIAS_SIZE; i > 0; i--) + { + str[i] = UNICODE_NULL; + if (ConvertStringSidToSidW(str, pSid)) + { + *pLength = i; + return TRUE; + } + } - StringSid += 2; /* Advance to Revision */ - pisid->Revision = atoiW(StringSid); + end = wcschr(Buffer, SDDL_ACE_ENDC); + if (!end) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + strSid = (LPWSTR)LocalAlloc(0, (end - Buffer) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); + if (!strSid) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + wcsncpy(strSid, Buffer, end - Buffer + 1); + strSid[end - Buffer] = UNICODE_NULL; + *pLength = end - Buffer; + ret = ConvertStringSidToSidW(strSid, pSid); + LocalFree(strSid); + return ret; +} - 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 */ - } +static const RECORD DaclFlagTable[] = +{ + { SDDL_PROTECTED, SE_DACL_PROTECTED }, + { SDDL_AUTO_INHERIT_REQ, SE_DACL_AUTO_INHERIT_REQ }, + { SDDL_AUTO_INHERITED, SE_DACL_AUTO_INHERITED }, + { NULL, 0 }, +}; - pisid->SubAuthorityCount = csubauth; +static const RECORD SaclFlagTable[] = +{ + { SDDL_PROTECTED, SE_SACL_PROTECTED }, + { SDDL_AUTO_INHERIT_REQ, SE_SACL_AUTO_INHERIT_REQ }, + { SDDL_AUTO_INHERITED, SE_SACL_AUTO_INHERITED }, + { NULL, 0 }, +}; - /* Advance to identifier authority */ - while (*StringSid && *StringSid != '-') - StringSid++; - if (*StringSid == '-') - StringSid++; +static const RECORD AceFlagTable[] = +{ + { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE }, + { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE }, + { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE }, + { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE }, + { SDDL_INHERITED, INHERITED_ACE }, + { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG }, + { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG }, + { NULL, 0 }, +}; - /* 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; +static BOOL +ParseFlagsString( + IN LPCWSTR Buffer, + IN const RECORD* FlagTable, + IN WCHAR LimitChar, + OUT DWORD* pFlags, + OUT SIZE_T* pLength) +{ + LPCWSTR ptr = Buffer; + SIZE_T PartialLength; + DWORD Flag; - /* Advance to first sub authority */ - while (*StringSid && *StringSid != '-') - StringSid++; - if (*StringSid == '-') - StringSid++; + *pFlags = 0; + while (*ptr != LimitChar) + { + if (!FindKeyInTable(FlagTable, ptr, &PartialLength, &Flag)) + return FALSE; + *pFlags |= Flag; + ptr += PartialLength; + } + *pLength = ptr - Buffer; + return TRUE; +} - while (*StringSid) - { - while (*StringSid && *StringSid != '-') - StringSid++; +static const RECORD AccessMaskTable[] = +{ + { 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 }, +}; - pisid->SubAuthority[i++] = atoiW(StringSid); - } +static BOOL +ParseAccessMaskString( + IN LPCWSTR Buffer, + OUT DWORD* pAccessMask, + OUT SIZE_T* pLength) +{ + /* FIXME: Allow hexadecimal string for access rights! */ - if (i != pisid->SubAuthorityCount) - goto lend; /* ERROR_INVALID_SID */ + return ParseFlagsString(Buffer, AccessMaskTable, SDDL_SEPERATORC, pAccessMask, pLength); +} - bret = TRUE; - } - else /* String constant format - Only available in winxp and above */ - { - pisid->Revision = SDDL_REVISION; - pisid->SubAuthorityCount = 1; +static BOOL +ParseGuidString( + IN LPCWSTR Buffer, + OUT GUID* pGuid, + OUT BOOL* pIsGuidValid, + OUT SIZE_T* pLength) +{ + WCHAR GuidStr[MAX_GUID_STRING_LEN + 1]; + LPCWSTR end; - FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2)); + end = wcschr(Buffer, SDDL_SEPERATORC); + if (!end) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } - /* TODO: Lookup string of well-known SIDs in table */ - pisid->IdentifierAuthority.Value[5] = 0; - pisid->SubAuthority[0] = 0; + *pLength = end - Buffer; + *pIsGuidValid = (end != Buffer); + if (!*pIsGuidValid) + return TRUE; - bret = TRUE; - } + if (end - Buffer > MAX_GUID_STRING_LEN - 1) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + GuidStr[end - Buffer] = UNICODE_NULL; + wcsncpy(GuidStr, Buffer, end - Buffer); + if (RPC_S_OK != UuidFromStringW((unsigned short*)&GuidStr, pGuid)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + return TRUE; +} -lend: - if (!bret) - SetLastError(ERROR_INVALID_SID); +static const RECORD AceTypeTable[] = +{ + { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE }, + { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE }, + { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE }, + { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE }, + { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE }, + { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE }, + { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE }, + { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE }, + { NULL, 0 }, +}; - TRACE("returning %s\n", bret ? "TRUE" : "FALSE"); - return bret; +static BOOL +ParseAceString( + IN LPCWSTR Buffer, + IN PACL pAcl, + OUT SIZE_T* pLength) +{ + LPCWSTR ptr = Buffer; + SIZE_T PartialLength; + DWORD aceType, aceFlags, accessMask; + GUID object, inheritObject; + BOOL objectValid, inheritObjectValid; + PSID sid = NULL; + BOOL ret; + + if (*ptr != SDDL_ACE_BEGINC) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + ptr++; /* Skip SDDL_ACE_BEGINC */ + + if (!FindKeyInTable(AceTypeTable, ptr, &PartialLength, &aceType)) + return FALSE; + ptr += PartialLength; + + if (*ptr != SDDL_SEPERATORC) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + ptr++; /* Skip SDDL_SEPERATORC */ + + if (!ParseFlagsString(ptr, AceFlagTable, SDDL_SEPERATORC, &aceFlags, &PartialLength)) + return FALSE; + ptr += PartialLength + 1; + + if (!ParseAccessMaskString(ptr, &accessMask, &PartialLength)) + return FALSE; + ptr += PartialLength + 1; + + if (!ParseGuidString(ptr, &object, &objectValid, &PartialLength)) + return FALSE; + ptr += PartialLength + 1; + + if (!ParseGuidString(ptr, &inheritObject, &inheritObjectValid, &PartialLength)) + return FALSE; + ptr += PartialLength + 1; + + if (!ParseSidString(ptr, &sid, &PartialLength)) + return FALSE; + ptr += PartialLength; + if (*ptr != SDDL_ACE_ENDC) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + ptr++; /* Skip SDDL_ACE_ENDC */ + *pLength = ptr - Buffer; + + switch (aceType) + { + case ACCESS_ALLOWED_ACE_TYPE: + ret = AddAccessAllowedAceEx( + pAcl, + ACL_REVISION_DS, + aceFlags, + accessMask, + sid); + break; + case ACCESS_ALLOWED_OBJECT_ACE_TYPE: + ret = AddAccessAllowedObjectAce( + pAcl, + ACL_REVISION_DS, + aceFlags, + accessMask, + objectValid ? &object : NULL, + inheritObjectValid ? &inheritObject : NULL, + sid); + break; + case ACCESS_DENIED_ACE_TYPE: + ret = AddAccessDeniedAceEx( + pAcl, + ACL_REVISION_DS, + aceFlags, + accessMask, + sid); + break; + case ACCESS_DENIED_OBJECT_ACE_TYPE: + ret = AddAccessDeniedObjectAce( + pAcl, + ACL_REVISION_DS, + aceFlags, + accessMask, + objectValid ? &object : NULL, + inheritObjectValid ? &inheritObject : NULL, + sid); + break; + case SYSTEM_AUDIT_ACE_TYPE: + ret = AddAuditAccessAceEx( + pAcl, + ACL_REVISION_DS, + aceFlags, + accessMask, + sid, + FALSE, + FALSE); + break; + case SYSTEM_AUDIT_OBJECT_ACE_TYPE: + ret = AddAuditAccessObjectAce( + pAcl, + ACL_REVISION_DS, + aceFlags, + accessMask, + objectValid ? &object : NULL, + inheritObjectValid ? &inheritObject : NULL, + sid, + FALSE, + FALSE); + break; + case SYSTEM_ALARM_ACE_TYPE: + case SYSTEM_ALARM_OBJECT_ACE_TYPE: + default: + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + ret = FALSE; + } + } + LocalFree(sid); + return ret; } /* Exported functions */ @@ -793,60 +600,190 @@ CopySid (DWORD nDestinationSidLength, return TRUE; } -/* Winehq cvs 20050916 */ /****************************************************************************** * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@] * @implemented */ -BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW( - LPCWSTR StringSecurityDescriptor, - DWORD StringSDRevision, - PSECURITY_DESCRIPTOR* SecurityDescriptor, - PULONG SecurityDescriptorSize) +BOOL WINAPI +ConvertStringSecurityDescriptorToSecurityDescriptorW( + IN LPCWSTR StringSecurityDescriptor, + IN DWORD StringSDRevision, + OUT PSECURITY_DESCRIPTOR* SecurityDescriptor, + OUT PULONG SecurityDescriptorSize) { - DWORD cBytes; - SECURITY_DESCRIPTOR* psd; - BOOL bret = FALSE; + PSECURITY_DESCRIPTOR sd = NULL; + BOOL ret = FALSE; - TRACE("%s\n", debugstr_w(StringSecurityDescriptor)); + if (!StringSecurityDescriptor) + SetLastError(ERROR_INVALID_PARAMETER); + else if (StringSDRevision != SDDL_REVISION_1) + SetLastError(ERROR_INVALID_PARAMETER); + else + { + LPCWSTR ptr = StringSecurityDescriptor; + DWORD numberOfAces = 0; + DWORD relativeSdSize; + SIZE_T MaxAclSize; + PSECURITY_DESCRIPTOR relativeSd = NULL; + PSID pSid; + PACL pAcl; + BOOL present, dummy; + /* An easy way to know how much space we need for an ACL is to count + * the number of ACEs and say that we have 1 SID by ACE + */ + ptr = wcschr(StringSecurityDescriptor, SDDL_ACE_BEGINC); + while (ptr != NULL) + { + numberOfAces++; + ptr = wcschr(ptr + 1, SDDL_ACE_BEGINC); + } + MaxAclSize = sizeof(ACL) + numberOfAces * + (sizeof(ACCESS_ALLOWED_OBJECT_ACE) + SECURITY_MAX_SID_SIZE); - if (GetVersion() & 0x80000000) - { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - goto lend; - } - else if (StringSDRevision != SID_REVISION) - { - SetLastError(ERROR_UNKNOWN_REVISION); - goto lend; - } + sd = (SECURITY_DESCRIPTOR*)LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR)); + if (!sd) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); + if (!ret) + goto cleanup; - /* Compute security descriptor length */ - if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor, - NULL, &cBytes)) - goto lend; + /* Now, really parse the string */ + ptr = StringSecurityDescriptor; + while (*ptr) + { + if (ptr[1] != SDDL_DELIMINATORC) + { + SetLastError(ERROR_INVALID_PARAMETER); + ret = FALSE; + goto cleanup; + } + ptr += 2; + switch (ptr[-2]) + { + case 'O': + case 'G': + { + PSID pSid; + SIZE_T Length; - psd = *SecurityDescriptor = (SECURITY_DESCRIPTOR*) LocalAlloc( - GMEM_ZEROINIT, cBytes); + ret = ParseSidString(ptr, &pSid, &Length); + if (!ret) + goto cleanup; + if (ptr[-2] == 'O') + ret = SetSecurityDescriptorOwner(sd, pSid, FALSE); + else + ret = SetSecurityDescriptorGroup(sd, pSid, FALSE); + if (!ret) + { + LocalFree(pSid); + goto cleanup; + } + ptr += Length; + break; + } + case 'D': + case 'S': + { + DWORD aclFlags; + SIZE_T Length; + BOOL isDacl = (ptr[-2] == 'D'); + + if (isDacl) + ret = ParseFlagsString(ptr, DaclFlagTable, SDDL_ACE_BEGINC, &aclFlags, &Length); + else + ret = ParseFlagsString(ptr, SaclFlagTable, SDDL_ACE_BEGINC, &aclFlags, &Length); + if (!ret) + goto cleanup; + pAcl = (PACL)LocalAlloc(0, MaxAclSize); + if (!pAcl) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + ret = FALSE; + goto cleanup; + } + if (!InitializeAcl(pAcl, (DWORD)MaxAclSize, ACL_REVISION_DS)) + { + LocalFree(pAcl); + goto cleanup; + } + if (aclFlags != 0) + { + ret = SetSecurityDescriptorControl( + sd, + (SECURITY_DESCRIPTOR_CONTROL)aclFlags, + (SECURITY_DESCRIPTOR_CONTROL)aclFlags); + if (!ret) + { + LocalFree(pAcl); + goto cleanup; + } + } + ptr += Length; + while (*ptr == SDDL_ACE_BEGINC) + { + ret = ParseAceString(ptr, pAcl, &Length); + if (!ret) + { + LocalFree(pAcl); + goto cleanup; + } + ptr += Length; + } + if (isDacl) + ret = SetSecurityDescriptorDacl(sd, TRUE, pAcl, FALSE); + else + ret = SetSecurityDescriptorSacl(sd, TRUE, pAcl, FALSE); + if (!ret) + { + LocalFree(pAcl); + goto cleanup; + } + break; + } + default: + { + SetLastError(ERROR_INVALID_PARAMETER); + ret = FALSE; + goto cleanup; + } + } + } - psd->Revision = SID_REVISION; - psd->Control |= SE_SELF_RELATIVE; + relativeSdSize = 0; + while (TRUE) + { + if (relativeSd) + LocalFree(relativeSd); + relativeSd = LocalAlloc(0, relativeSdSize); + if (!relativeSd) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto cleanup; + } + ret = MakeSelfRelativeSD(sd, relativeSd, &relativeSdSize); + if (ret || GetLastError() != ERROR_INSUFFICIENT_BUFFER) + break; + } + if (SecurityDescriptorSize) + *SecurityDescriptorSize = relativeSdSize; + *SecurityDescriptor = relativeSd; - if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor, - psd, &cBytes)) - { - LocalFree(psd); - goto lend; - } - - if (SecurityDescriptorSize) - *SecurityDescriptorSize = cBytes; - - bret = TRUE; - -lend: - TRACE(" ret=%d\n", bret); - return bret; +cleanup: + if (GetSecurityDescriptorOwner(sd, &pSid, &dummy)) + LocalFree(pSid); + if (GetSecurityDescriptorGroup(sd, &pSid, &dummy)) + LocalFree(pSid); + if (GetSecurityDescriptorDacl(sd, &present, &pAcl, &dummy) && present) + LocalFree(pAcl); + if (GetSecurityDescriptorSacl(sd, &present, &pAcl, &dummy) && present) + LocalFree(pAcl); + LocalFree(sd); + return ret; + } + return FALSE; } /* Winehq cvs 20050916 */ @@ -1204,16 +1141,206 @@ ConvertStringSidToSidA( return bRetVal; } -/* - * @unimplemented +/****************************************************************************** + * ComputeStringSidSize */ -BOOL STDCALL -ConvertStringSidToSidW( - IN LPCWSTR StringSid, - OUT PSID* sid) +static DWORD ComputeStringSidSize(LPCWSTR StringSid) { - FIXME("unimplemented!\n", __FUNCTION__); - return FALSE; + DWORD size = sizeof(SID); + + if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */ + { + int ctok = 0; + while (*StringSid) + { + if (*StringSid == '-') + ctok++; + StringSid++; + } + + if (ctok > 3) + size += (ctok - 3) * sizeof(DWORD); + } + else /* String constant format - Only available in winxp and above */ + { + int i; + + for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) + if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2)) + size += (WellKnownSids[i].Sid.SubAuthorityCount - 1) * sizeof(DWORD); + } + + return size; +} + +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 }, +}; + +/* + * @implemented + */ +BOOL WINAPI +ConvertStringSidToSidW( + IN LPCWSTR StringSid, + OUT PSID* sid) +{ + DWORD size; + DWORD i, cBytes, identAuth, csubauth; + BOOL ret; + SID* pisid; + + TRACE("%s %p\n", 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 - sizeof(SID)) / sizeof(DWORD)) + 1; + + StringSid += 2; /* Advance to Revision */ + pisid->Revision = atoiW(StringSid); + + if (pisid->Revision != SDDL_REVISION) + { + TRACE("Revision %d is unknown\n", pisid->Revision); + goto lend; /* ERROR_INVALID_SID */ + } + if (csubauth == 0) + { + TRACE("SubAuthorityCount is 0\n"); + goto lend; /* ERROR_INVALID_SID */ + } + + pisid->SubAuthorityCount = csubauth; + + /* Advance to identifier authority */ + while (*StringSid && *StringSid != '-') + StringSid++; + if (*StringSid == '-') + StringSid++; + + /* MS' implementation can't handle values greater than 2^32 - 1, so + * we don't either; assume most significant bytes are always 0 + */ + pisid->IdentifierAuthority.Value[0] = 0; + pisid->IdentifierAuthority.Value[1] = 0; + identAuth = atoiW(StringSid); + pisid->IdentifierAuthority.Value[5] = identAuth & 0xff; + pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8; + pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16; + pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24; + + /* Advance to first sub authority */ + while (*StringSid && *StringSid != '-') + StringSid++; + if (*StringSid == '-') + StringSid++; + + while (*StringSid) + { + while (*StringSid && *StringSid != '-') + StringSid++; + 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; }