Author: gschneider
Date: Mon Nov 10 08:25:24 2008
New Revision: 37281
URL:
http://svn.reactos.org/svn/reactos?rev=37281&view=rev
Log:
Implement ConvertSecurityDescriptorToStringSecurityDescriptorW based on Wine code.
Modified:
trunk/reactos/dll/win32/advapi32/sec/sid.c
Modified: trunk/reactos/dll/win32/advapi32/sec/sid.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/sec/sid…
==============================================================================
--- trunk/reactos/dll/win32/advapi32/sec/sid.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/advapi32/sec/sid.c [iso-8859-1] Mon Nov 10 08:25:24 2008
@@ -50,6 +50,12 @@
WELL_KNOWN_SID_TYPE Type;
MAX_SID Sid;
} WELLKNOWNSID;
+
+typedef struct _ACEFLAG
+{
+ LPCWSTR wstr;
+ DWORD value;
+} ACEFLAG, *LPACEFLAG;
static const WELLKNOWNSID WellKnownSids[] =
{
@@ -180,6 +186,76 @@
}
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 */
@@ -610,10 +686,289 @@
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 = (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)
+{
+ 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.@]
- * @unimplemented
+ * @implemented
*/
BOOL WINAPI
ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR
SecurityDescriptor,
@@ -622,6 +977,9 @@
LPWSTR *OutputString,
PULONG OutputLen)
{
+ ULONG len;
+ WCHAR *wptr, *wstr;
+
if (SDRevision != SDDL_REVISION_1)
{
ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
@@ -629,9 +987,40 @@
return FALSE;
}
- FIXME("%s() not implemented!\n", __FUNCTION__);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- 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;
}