From e6f01b4dee295de0fccd8b9cc7f6ab677f52d8d9 Mon Sep 17 00:00:00 2001 From: Mikolaj Zalewski Date: Tue, 25 Sep 2007 13:12:50 -0700 Subject: [PATCH] advapi32: implement and test ConvertSecurityDescriptorToStringSecurityDescriptor --- dlls/advapi32/advapi32.spec | 4 dlls/advapi32/security.c | 402 ++++++++++++++++++++++++++++++++++++++++ dlls/advapi32/tests/security.c | 101 ++++++++++ 3 files changed, 505 insertions(+), 2 deletions(-) diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index 3078574..6cb8846 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -75,8 +75,8 @@ # @ stub ConvertSecurityDescriptorToAcce # @ stub ConvertSecurityDescriptorToAccessNamedA # @ stub ConvertSecurityDescriptorToAccessNamedW # @ stub ConvertSecurityDescriptorToAccessW -# @ stub ConvertSecurityDescriptorToStringSecurityDescriptorA -# @ stub ConvertSecurityDescriptorToStringSecurityDescriptorW +@ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorA(ptr long long ptr ptr) +@ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorW(ptr long long ptr ptr) @ stdcall ConvertSidToStringSidA(ptr ptr) @ stdcall ConvertSidToStringSidW(ptr ptr) # @ stub ConvertStringSDToSDDomainA diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index bfe7edf..f2a10fe 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -275,6 +275,13 @@ static const WCHAR SDDL_GENERIC_WRITE[] static const WCHAR SDDL_GENERIC_EXECUTE[] = {'G','X',0}; /* + * ACL flags + */ +static const WCHAR SDDL_PROTECTED[] = {'P',0}; +static const WCHAR SDDL_AUTO_INHERIT_REQ[] = {'A','R',0}; +static const WCHAR SDDL_AUTO_INHERITED[] = {'A','I',0}; + +/* * ACE types */ static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0}; @@ -3535,6 +3542,401 @@ lend: return bret; } +static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen) +{ + if (cch == -1) + cch = strlenW(string); + + if (plen) + *plen += cch; + + if (pwptr) + { + memcpy(*pwptr, string, sizeof(WCHAR)*cch); + *pwptr += cch; + } +} + +static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen) +{ + 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; iSubAuthorityCount; i++ ) + { + sprintfW( buf, subauthfmt, pisid->SubAuthority[i] ); + DumpString(buf, -1, pwptr, plen); + } + return TRUE; +} + +static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen) +{ + int 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); +} + +const static LPCWSTR AceRightBitNames[32] = { + SDDL_CREATE_CHILD, /* 0 */ + SDDL_DELETE_CHILD, + SDDL_LIST_CHILDREN, + SDDL_SELF_WRITE, + SDDL_READ_PROPERTY, /* 4 */ + SDDL_WRITE_PROPERTY, + SDDL_DELETE_TREE, + SDDL_LIST_OBJECT, + SDDL_CONTROL_ACCESS, /* 8 */ + NULL, + NULL, + NULL, + NULL, /* 12 */ + NULL, + NULL, + NULL, + SDDL_STANDARD_DELETE, /* 16 */ + SDDL_READ_CONTROL, + SDDL_WRITE_DAC, + SDDL_WRITE_OWNER, + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, /* 24 */ + NULL, + NULL, + NULL, + SDDL_GENERIC_ALL, /* 28 */ + SDDL_GENERIC_EXECUTE, + SDDL_GENERIC_WRITE, + SDDL_GENERIC_READ +}; + +static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen) +{ + const static WCHAR fmtW[] = {'0','x','%','x',0}; + WCHAR buf[15]; + int 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 */ + const static WCHAR openbr = '('; + const static WCHAR closebr = ')'; + const static 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 = (ACCESS_ALLOWED_ACE *)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) +{ + const static 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) +{ + const static WCHAR prefix[] = {'G',':',0}; + BOOL bDefaulted; + PSID psid; + + if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted)) + return FALSE; + + if (psid == NULL) + return TRUE; + + DumpString(prefix, -1, pwptr, plen); + if (!DumpSid(psid, pwptr, plen)) + return FALSE; + return TRUE; +} + +static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen) +{ + static const WCHAR dacl[] = {'D',':',0}; + SECURITY_DESCRIPTOR_CONTROL control; + BOOL present, defaulted; + DWORD revision; + PACL pacl; + + if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted)) + return FALSE; + + if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision)) + return FALSE; + + if (!present) + return TRUE; + + DumpString(dacl, 2, pwptr, plen); + if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED)) + return FALSE; + return TRUE; +} + +static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen) +{ + static const WCHAR sacl[] = {'S',':',0}; + SECURITY_DESCRIPTOR_CONTROL control; + BOOL present, defaulted; + DWORD revision; + PACL pacl; + + if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted)) + return FALSE; + + if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision)) + return FALSE; + + if (!present) + return TRUE; + + DumpString(sacl, 2, pwptr, plen); + if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED)) + return FALSE; + return TRUE; +} + +/****************************************************************************** + * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@] + */ +BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, ULONG *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 (RequestedInformation & OWNER_SECURITY_INFORMATION) + if (!DumpOwner(SecurityDescriptor, NULL, &len)) + return FALSE; + if (RequestedInformation & GROUP_SECURITY_INFORMATION) + if (!DumpGroup(SecurityDescriptor, NULL, &len)) + return FALSE; + if (RequestedInformation & DACL_SECURITY_INFORMATION) + if (!DumpDacl(SecurityDescriptor, NULL, &len)) + return FALSE; + if (RequestedInformation & SACL_SECURITY_INFORMATION) + if (!DumpSacl(SecurityDescriptor, NULL, &len)) + return FALSE; + + wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR)); + if (RequestedInformation & OWNER_SECURITY_INFORMATION) + if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) + return FALSE; + if (RequestedInformation & GROUP_SECURITY_INFORMATION) + if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) + return FALSE; + if (RequestedInformation & DACL_SECURITY_INFORMATION) + if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) + return FALSE; + if (RequestedInformation & 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.@] + */ +BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, ULONG *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; + } +} + /****************************************************************************** * ConvertStringSidToSidW [ADVAPI32.@] */ diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index 9e356ac..c4b9ed4 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -53,6 +53,8 @@ typedef BOOL (WINAPI *fnConvertSidToStri typedef BOOL (WINAPI *fnConvertStringSidToSidA)( LPCSTR str, PSID pSid ); static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD, PSECURITY_DESCRIPTOR*, PULONG ); +static BOOL (WINAPI *pConvertSecurityDescriptorToStringSecurityDescriptorA)(PSECURITY_DESCRIPTOR, DWORD, + SECURITY_INFORMATION, LPSTR *, PULONG ); typedef BOOL (WINAPI *fnGetFileSecurityA)(LPCSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD); static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, @@ -106,6 +108,8 @@ static void init(void) hmod = GetModuleHandle("advapi32.dll"); pConvertStringSecurityDescriptorToSecurityDescriptorA = (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorA" ); + pConvertSecurityDescriptorToStringSecurityDescriptorA = + (void *)GetProcAddress(hmod, "ConvertSecurityDescriptorToStringSecurityDescriptorA" ); pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA"); pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW"); @@ -1899,6 +1903,102 @@ static void test_ConvertStringSecurityDe GetLastError()); } +static void test_ConvertSecurityDescriptorToString() +{ + SECURITY_DESCRIPTOR desc; + SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION; + LPSTR string; + DWORD size; + PSID psid, psid2; + PACL pacl; + char sid_buf[256]; + char acl_buf[8192]; + ULONG len; + + if (!pConvertSecurityDescriptorToStringSecurityDescriptorA) + { + skip("ConvertSecurityDescriptorToStringSecurityDescriptor is not available\n"); + return; + } + +/* It seems Windows XP add an extra character to the length of the string for each ACE in an ACL. We + * don't replicate this feature so we only test len >= strlen+1. */ +#define CHECK_RESULT_AND_FREE(exp_str) \ + ok(strcmp(string, (exp_str)) == 0, "String mismatch (expected \"%s\", got \"%s\")\n", (exp_str), string); \ + ok(len >= (strlen(exp_str) + 1), "Length mismatch (expected %d, got %d)\n", strlen(exp_str) + 1, len); \ + LocalFree(string); + + InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE(""); + + size = 4096; + CreateWellKnownSid(WinLocalSid, NULL, sid_buf, &size); + SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, FALSE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:S-1-2-0"); + + SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, TRUE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:S-1-2-0"); + + size = sizeof(sid_buf); + CreateWellKnownSid(WinLocalSystemSid, NULL, sid_buf, &size); + SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, TRUE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SY"); + + ConvertStringSidToSid("S-1-5-21-93476-23408-4576", &psid); + SetSecurityDescriptorGroup(&desc, psid, TRUE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576"); + + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, GROUP_SECURITY_INFORMATION, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576"); + + pacl = (PACL)acl_buf; + InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION); + SetSecurityDescriptorDacl(&desc, TRUE, pacl, TRUE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:"); + + SetSecurityDescriptorDacl(&desc, TRUE, pacl, FALSE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:"); + + ConvertStringSidToSid("S-1-5-6", &psid2); + AddAccessAllowedAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, 0xf0000000, psid2); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)"); + + AddAccessAllowedAceEx(pacl, ACL_REVISION, INHERIT_ONLY_ACE|INHERITED_ACE, 0x00000003, psid2); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)"); + + AddAccessDeniedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, 0xffffffff, psid); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"); + + + pacl = (PACL)acl_buf; + InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION); + SetSecurityDescriptorSacl(&desc, TRUE, pacl, FALSE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:"); + + SetSecurityDescriptorDacl(&desc, TRUE, NULL, FALSE); + AddAuditAccessAceEx(pacl, ACL_REVISION, VALID_INHERIT_FLAGS, KEY_READ|KEY_WRITE, psid2, TRUE, TRUE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)"); + + AddAuditAccessAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, FILE_GENERIC_READ|FILE_GENERIC_WRITE, psid2, TRUE, FALSE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)"); + + +#undef CHECK_RESULT_AND_FREE +} + START_TEST(security) { init(); @@ -1922,4 +2022,5 @@ START_TEST(security) test_SetEntriesInAcl(); test_GetNamedSecurityInfoA(); test_ConvertStringSecurityDescriptor(); + test_ConvertSecurityDescriptorToString(); } -- 1.4.1