Author: ekohl
Date: Thu Jun  7 10:31:17 2012
New Revision: 56704

URL: http://svn.reactos.org/svn/reactos?rev=56704&view=rev
Log:
[SAMLIB][SAMSRV]
- Implement SamGetMembersInAlias and SamrGetMembersInAlias.
- Add registry helper routines SampRegQueryKeyInfo, SampRegEnumerateValue and 
SampRegSetValue.
- Remove unused SAM database code.
- Store the name and members key (only for aliases and groups) in the database 
object.

Modified:
    trunk/reactos/dll/win32/samlib/samlib.c
    trunk/reactos/dll/win32/samlib/samlib.spec
    trunk/reactos/dll/win32/samsrv/database.c
    trunk/reactos/dll/win32/samsrv/registry.c
    trunk/reactos/dll/win32/samsrv/samrpc.c
    trunk/reactos/dll/win32/samsrv/samsrv.h
    trunk/reactos/include/ddk/ntsam.h

Modified: trunk/reactos/dll/win32/samlib/samlib.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samlib/samlib.c?rev=56704&r1=56703&r2=56704&view=diff
==============================================================================
--- trunk/reactos/dll/win32/samlib/samlib.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/samlib/samlib.c [iso-8859-1] Thu Jun  7 10:31:17 
2012
@@ -303,6 +303,48 @@
 
 NTSTATUS
 NTAPI
+SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
+                     OUT PSID **MemberIds,
+                     OUT PULONG MemberCount)
+{
+    SAMPR_PSID_ARRAY_OUT SidArray;
+    NTSTATUS Status;
+
+    TRACE("SamGetMembersInAlias(%p %p %p)\n",
+          AliasHandle, MemberIds, MemberCount);
+
+    if ((MemberIds == NULL) ||
+        (MemberCount == NULL))
+        return STATUS_INVALID_PARAMETER;
+
+    *MemberIds = NULL;
+    *MemberCount = 0;
+
+    SidArray.Sids = NULL;
+
+    RpcTryExcept
+    {
+        Status = SamrGetMembersInAlias((SAMPR_HANDLE)AliasHandle,
+                                       &SidArray);
+        if (NT_SUCCESS(Status))
+        {
+            *MemberCount = SidArray.Count;
+            *MemberIds = (PSID *)(SidArray.Sids);
+        }
+
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
 SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
                            IN PUNICODE_STRING Name,
                            OUT PSID *DomainId)

Modified: trunk/reactos/dll/win32/samlib/samlib.spec
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samlib/samlib.spec?rev=56704&r1=56703&r2=56704&view=diff
==============================================================================
--- trunk/reactos/dll/win32/samlib/samlib.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/samlib/samlib.spec [iso-8859-1] Thu Jun  7 10:31:17 
2012
@@ -23,7 +23,7 @@
 @ stub SamGetCompatibilityMode
 @ stub SamGetDisplayEnumerationIndex
 @ stub SamGetGroupsForUser
-@ stub SamGetMembersInAlias
+@ stdcall SamGetMembersInAlias(ptr ptr ptr)
 @ stub SamGetMembersInGroup
 @ stdcall SamLookupDomainInSamServer(ptr ptr ptr)
 @ stub SamLookupIdsInDomain

Modified: trunk/reactos/dll/win32/samsrv/database.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samsrv/database.c?rev=56704&r1=56703&r2=56704&view=diff
==============================================================================
--- trunk/reactos/dll/win32/samsrv/database.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/samsrv/database.c [iso-8859-1] Thu Jun  7 10:31:17 
2012
@@ -44,210 +44,6 @@
     return Status;
 }
 
-#if 0
-static BOOLEAN
-LsapIsDatabaseInstalled(VOID)
-{
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    UNICODE_STRING KeyName;
-    HANDLE KeyHandle;
-    NTSTATUS Status;
-
-    RtlInitUnicodeString(&KeyName,
-                         L"Policy");
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &KeyName,
-                               OBJ_CASE_INSENSITIVE,
-                               SecurityKeyHandle,
-                               NULL);
-
-    Status = RtlpNtOpenKey(&KeyHandle,
-                           KEY_READ,
-                           &ObjectAttributes,
-                           0);
-    if (!NT_SUCCESS(Status))
-        return FALSE;
-
-    NtClose(KeyHandle);
-
-    return TRUE;
-}
-
-
-static NTSTATUS
-LsapCreateDatabaseKeys(VOID)
-{
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    UNICODE_STRING KeyName;
-    HANDLE PolicyKeyHandle = NULL;
-    HANDLE AccountsKeyHandle = NULL;
-    HANDLE DomainsKeyHandle = NULL;
-    HANDLE SecretsKeyHandle = NULL;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    TRACE("LsapInstallDatabase()\n");
-
-    /* Create the 'Policy' key */
-    RtlInitUnicodeString(&KeyName,
-                         L"Policy");
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &KeyName,
-                               OBJ_CASE_INSENSITIVE,
-                               SecurityKeyHandle,
-                               NULL);
-
-    Status = NtCreateKey(&PolicyKeyHandle,
-                         KEY_ALL_ACCESS,
-                         &ObjectAttributes,
-                         0,
-                         NULL,
-                         0,
-                         NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        ERR("Failed to create the 'Policy' key (Status: 0x%08lx)\n", Status);
-        goto Done;
-    }
-
-    /* Create the 'Accounts' key */
-    RtlInitUnicodeString(&KeyName,
-                         L"Accounts");
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &KeyName,
-                               OBJ_CASE_INSENSITIVE,
-                               PolicyKeyHandle,
-                               NULL);
-
-    Status = NtCreateKey(&AccountsKeyHandle,
-                         KEY_ALL_ACCESS,
-                         &ObjectAttributes,
-                         0,
-                         NULL,
-                         0,
-                         NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        ERR("Failed to create the 'Accounts' key (Status: 0x%08lx)\n", Status);
-        goto Done;
-    }
-
-    /* Create the 'Domains' key */
-    RtlInitUnicodeString(&KeyName,
-                         L"Domains");
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &KeyName,
-                               OBJ_CASE_INSENSITIVE,
-                               PolicyKeyHandle,
-                               NULL);
-
-    Status = NtCreateKey(&DomainsKeyHandle,
-                         KEY_ALL_ACCESS,
-                         &ObjectAttributes,
-                         0,
-                         NULL,
-                         0,
-                         NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        ERR("Failed to create the 'Domains' key (Status: 0x%08lx)\n", Status);
-        goto Done;
-    }
-
-    /* Create the 'Secrets' key */
-    RtlInitUnicodeString(&KeyName,
-                         L"Secrets");
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &KeyName,
-                               OBJ_CASE_INSENSITIVE,
-                               PolicyKeyHandle,
-                               NULL);
-
-    Status = NtCreateKey(&SecretsKeyHandle,
-                         KEY_ALL_ACCESS,
-                         &ObjectAttributes,
-                         0,
-                         NULL,
-                         0,
-                         NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        ERR("Failed to create the 'Secrets' key (Status: 0x%08lx)\n", Status);
-        goto Done;
-    }
-
-Done:
-    if (SecretsKeyHandle != NULL)
-        NtClose(SecretsKeyHandle);
-
-    if (DomainsKeyHandle != NULL)
-        NtClose(DomainsKeyHandle);
-
-    if (AccountsKeyHandle != NULL)
-        NtClose(AccountsKeyHandle);
-
-    if (PolicyKeyHandle != NULL)
-        NtClose(PolicyKeyHandle);
-
-    TRACE("LsapInstallDatabase() done (Status: 0x%08lx)\n", Status);
-
-    return Status;
-}
-
-
-static NTSTATUS
-LsapCreateDatabaseObjects(VOID)
-{
-    PLSA_DB_OBJECT PolicyObject;
-    NTSTATUS Status;
-
-    /* Open the 'Policy' object */
-    Status = LsapOpenDbObject(NULL,
-                              L"Policy",
-                              LsaDbPolicyObject,
-                              0,
-                              &PolicyObject);
-    if (!NT_SUCCESS(Status))
-        return Status;
-
-    LsapSetObjectAttribute(PolicyObject,
-                           L"PolPrDmN",
-                           NULL,
-                           0);
-
-    LsapSetObjectAttribute(PolicyObject,
-                           L"PolPrDmS",
-                           NULL,
-                           0);
-
-    LsapSetObjectAttribute(PolicyObject,
-                           L"PolAcDmN",
-                           NULL,
-                           0);
-
-    LsapSetObjectAttribute(PolicyObject,
-                           L"PolAcDmS",
-                           NULL,
-                           0);
-
-    /* Close the 'Policy' object */
-    LsapCloseDbObject(PolicyObject);
-
-    return STATUS_SUCCESS;
-}
-
-
-static NTSTATUS
-LsapUpdateDatabase(VOID)
-{
-    return STATUS_SUCCESS;
-}
-#endif
-
 
 NTSTATUS
 SampInitDatabase(VOID)
@@ -310,7 +106,8 @@
     UNICODE_STRING KeyName;
     HANDLE ParentKeyHandle;
     HANDLE ContainerKeyHandle = NULL;
-    HANDLE ObjectKeyHandle;
+    HANDLE ObjectKeyHandle = NULL;
+    HANDLE MembersKeyHandle = NULL;
     NTSTATUS Status;
 
     if (DbObject == NULL)
@@ -359,6 +156,28 @@
                              0,
                              NULL);
 
+        if ((ObjectType == SamDbAliasObject) ||
+            (ObjectType == SamDbGroupObject))
+        {
+            /* Open the object key */
+            RtlInitUnicodeString(&KeyName,
+                                 L"Members");
+
+            InitializeObjectAttributes(&ObjectAttributes,
+                                       &KeyName,
+                                       OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                                       ContainerKeyHandle,
+                                       NULL);
+
+            Status = NtCreateKey(&MembersKeyHandle,
+                                 KEY_ALL_ACCESS,
+                                 &ObjectAttributes,
+                                 0,
+                                 NULL,
+                                 0,
+                                 NULL);
+        }
+
         NtClose(ContainerKeyHandle);
 
         if (!NT_SUCCESS(Status))
@@ -395,15 +214,32 @@
                                 sizeof(SAM_DB_OBJECT));
     if (NewObject == NULL)
     {
+        if (MembersKeyHandle != NULL)
+            NtClose(MembersKeyHandle);
         NtClose(ObjectKeyHandle);
         return STATUS_NO_MEMORY;
     }
+
+    NewObject->Name = RtlAllocateHeap(RtlGetProcessHeap(),
+                                      0,
+                                      (wcslen(ObjectName) + 1) * 
sizeof(WCHAR));
+    if (NewObject == NULL)
+    {
+        if (MembersKeyHandle != NULL)
+            NtClose(MembersKeyHandle);
+        NtClose(ObjectKeyHandle);
+        RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject);
+        return STATUS_NO_MEMORY;
+    }
+
+    wcscpy(NewObject->Name, ObjectName);
 
     NewObject->Signature = SAMP_DB_SIGNATURE;
     NewObject->RefCount = 1;
     NewObject->ObjectType = ObjectType;
     NewObject->Access = DesiredAccess;
     NewObject->KeyHandle = ObjectKeyHandle;
+    NewObject->MembersKeyHandle = MembersKeyHandle;
     NewObject->ParentObject = ParentObject;
 
     if (ParentObject != NULL)
@@ -428,7 +264,8 @@
     UNICODE_STRING KeyName;
     HANDLE ParentKeyHandle;
     HANDLE ContainerKeyHandle = NULL;
-    HANDLE ObjectKeyHandle;
+    HANDLE ObjectKeyHandle = NULL;
+    HANDLE MembersKeyHandle = NULL;
     NTSTATUS Status;
 
     if (DbObject == NULL)
@@ -473,6 +310,28 @@
                            KEY_ALL_ACCESS,
                            &ObjectAttributes);
 
+        if ((ObjectType == SamDbAliasObject) ||
+            (ObjectType == SamDbGroupObject))
+        {
+            /* Open the object key */
+            RtlInitUnicodeString(&KeyName,
+                                 L"Members");
+
+            InitializeObjectAttributes(&ObjectAttributes,
+                                       &KeyName,
+                                       OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                                       ContainerKeyHandle,
+                                       NULL);
+
+            Status = NtCreateKey(&MembersKeyHandle,
+                                 KEY_ALL_ACCESS,
+                                 &ObjectAttributes,
+                                 0,
+                                 NULL,
+                                 0,
+                                 NULL);
+        }
+
         NtClose(ContainerKeyHandle);
 
         if (!NT_SUCCESS(Status))
@@ -506,15 +365,31 @@
                                 sizeof(SAM_DB_OBJECT));
     if (NewObject == NULL)
     {
+        if (MembersKeyHandle != NULL)
+            NtClose(MembersKeyHandle);
         NtClose(ObjectKeyHandle);
         return STATUS_NO_MEMORY;
     }
 
+    NewObject->Name = RtlAllocateHeap(RtlGetProcessHeap(),
+                                      0,
+                                      (wcslen(ObjectName) + 1) * 
sizeof(WCHAR));
+    if (NewObject == NULL)
+    {
+        if (MembersKeyHandle != NULL)
+            NtClose(MembersKeyHandle);
+        NtClose(ObjectKeyHandle);
+        RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject);
+        return STATUS_NO_MEMORY;
+    }
+
+    wcscpy(NewObject->Name, ObjectName);
     NewObject->Signature = SAMP_DB_SIGNATURE;
     NewObject->RefCount = 1;
     NewObject->ObjectType = ObjectType;
     NewObject->Access = DesiredAccess;
     NewObject->KeyHandle = ObjectKeyHandle;
+    NewObject->MembersKeyHandle = MembersKeyHandle;
     NewObject->ParentObject = ParentObject;
 
     if (ParentObject != NULL)
@@ -585,8 +460,14 @@
     if (DbObject->KeyHandle != NULL)
         NtClose(DbObject->KeyHandle);
 
+    if (DbObject->MembersKeyHandle != NULL)
+        NtClose(DbObject->MembersKeyHandle);
+
     if (DbObject->ParentObject != NULL)
         ParentObject = DbObject->ParentObject;
+
+    if (DbObject->Name != NULL)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject->Name);
 
     RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
 

Modified: trunk/reactos/dll/win32/samsrv/registry.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samsrv/registry.c?rev=56704&r1=56703&r2=56704&view=diff
==============================================================================
--- trunk/reactos/dll/win32/samsrv/registry.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/samsrv/registry.c [iso-8859-1] Thu Jun  7 10:31:17 
2012
@@ -15,6 +15,14 @@
 
 /* FUNCTIONS ***************************************************************/
 
+static
+BOOLEAN
+IsStringType(ULONG Type)
+{
+    return (Type == REG_SZ) || (Type == REG_EXPAND_SZ) || (Type == 
REG_MULTI_SZ);
+}
+
+
 NTSTATUS
 SampRegCloseKey(IN HANDLE KeyHandle)
 {
@@ -132,32 +140,148 @@
 
 
 NTSTATUS
-SampRegSetValue(HANDLE KeyHandle,
-                LPWSTR ValueName,
-                ULONG Type,
-                LPVOID Data,
-                ULONG DataLength)
-{
-    UNICODE_STRING Name;
-
-    RtlInitUnicodeString(&Name,
-                         ValueName);
-
-    return ZwSetValueKey(KeyHandle,
-                         &Name,
-                         0,
-                         Type,
-                         Data,
-                         DataLength);
-}
-
-
-NTSTATUS
-SampRegQueryValue(HANDLE KeyHandle,
-                  LPWSTR ValueName,
-                  PULONG Type OPTIONAL,
-                  LPVOID Data OPTIONAL,
-                  PULONG DataLength OPTIONAL)
+SampRegQueryKeyInfo(IN HANDLE KeyHandle,
+                    OUT PULONG SubKeyCount,
+                    OUT PULONG ValueCount)
+{
+    KEY_FULL_INFORMATION FullInfoBuffer;
+    ULONG Length;
+    NTSTATUS Status;
+
+    FullInfoBuffer.ClassLength = 0;
+    FullInfoBuffer.ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
+
+    Status = NtQueryKey(KeyHandle,
+                        KeyFullInformation,
+                        &FullInfoBuffer,
+                        sizeof(KEY_FULL_INFORMATION),
+                        &Length);
+    TRACE("NtQueryKey() returned status 0x%08lX\n", Status);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    if (SubKeyCount != NULL)
+        *SubKeyCount = FullInfoBuffer.SubKeys;
+
+    if (ValueCount != NULL)
+        *ValueCount = FullInfoBuffer.Values;
+
+    return Status;
+}
+
+
+NTSTATUS
+SampRegEnumerateValue(IN HANDLE KeyHandle,
+                      IN ULONG Index,
+                      OUT LPWSTR Name,
+                      IN OUT PULONG NameLength,
+                      OUT PULONG Type OPTIONAL,
+                      OUT PVOID Data OPTIONAL,
+                      IN OUT PULONG DataLength OPTIONAL)
+{
+    PKEY_VALUE_FULL_INFORMATION ValueInfo = NULL;
+    ULONG BufferLength = 0;
+    ULONG ReturnedLength;
+    NTSTATUS Status;
+
+    TRACE("Index: %lu\n", Index);
+
+    /* Calculate the required buffer length */
+    BufferLength = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name);
+    BufferLength += (MAX_PATH + 1) * sizeof(WCHAR);
+    if (Data != NULL)
+        BufferLength += *DataLength;
+
+    /* Allocate the value buffer */
+    ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
+    if (ValueInfo == NULL)
+        return STATUS_NO_MEMORY;
+
+    /* Enumerate the value*/
+    Status = ZwEnumerateValueKey(KeyHandle,
+                                 Index,
+                                 KeyValueFullInformation,
+                                 ValueInfo,
+                                 BufferLength,
+                                 &ReturnedLength);
+    if (NT_SUCCESS(Status))
+    {
+        if (Name != NULL)
+        {
+            /* Check if the name fits */
+            if (ValueInfo->NameLength < (*NameLength * sizeof(WCHAR)))
+            {
+                /* Copy it */
+                RtlMoveMemory(Name,
+                              ValueInfo->Name,
+                              ValueInfo->NameLength);
+
+                /* Terminate the string */
+                Name[ValueInfo->NameLength / sizeof(WCHAR)] = 0;
+            }
+            else
+            {
+                /* Otherwise, we ran out of buffer space */
+                Status = STATUS_BUFFER_OVERFLOW;
+                goto done;
+            }
+        }
+
+        if (Data != NULL)
+        {
+            /* Check if the data fits */
+            if (ValueInfo->DataLength <= *DataLength)
+            {
+                /* Copy it */
+                RtlMoveMemory(Data,
+                              (PVOID)((ULONG_PTR)ValueInfo + 
ValueInfo->DataOffset),
+                              ValueInfo->DataLength);
+
+                /* if the type is REG_SZ and data is not 0-terminated
+                 * and there is enough space in the buffer NT appends a \0 */
+                if (IsStringType(ValueInfo->Type) &&
+                    ValueInfo->DataLength <= *DataLength - sizeof(WCHAR))
+                {
+                    WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + 
ValueInfo->DataLength);
+                    if ((ptr > (WCHAR *)Data) && ptr[-1])
+                        *ptr = 0;
+                }
+            }
+            else
+            {
+                Status = STATUS_BUFFER_OVERFLOW;
+                goto done;
+            }
+        }
+    }
+
+done:
+    if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
+    {
+        if (Type != NULL)
+            *Type = ValueInfo->Type;
+
+        if (NameLength != NULL)
+            *NameLength = ValueInfo->NameLength;
+
+        if (DataLength != NULL)
+            *DataLength = ValueInfo->DataLength;
+    }
+
+    /* Free the buffer and return status */
+    if (ValueInfo)
+        RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
+
+    return Status;
+}
+
+
+NTSTATUS
+SampRegQueryValue(IN HANDLE KeyHandle,
+                  IN LPWSTR ValueName,
+                  OUT PULONG Type OPTIONAL,
+                  OUT PVOID Data OPTIONAL,
+                  IN OUT PULONG DataLength OPTIONAL)
 {
     PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
     UNICODE_STRING Name;
@@ -200,6 +324,16 @@
         RtlMoveMemory(Data,
                       ValueInfo->Data,
                       ValueInfo->DataLength);
+
+        /* if the type is REG_SZ and data is not 0-terminated
+         * and there is enough space in the buffer NT appends a \0 */
+        if (IsStringType(ValueInfo->Type) &&
+            ValueInfo->DataLength <= *DataLength - sizeof(WCHAR))
+        {
+            WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + ValueInfo->DataLength);
+            if ((ptr > (WCHAR *)Data) && ptr[-1])
+                *ptr = 0;
+        }
     }
 
     /* Free the memory and return status */
@@ -210,3 +344,24 @@
 
     return Status;
 }
+
+
+NTSTATUS
+SampRegSetValue(HANDLE KeyHandle,
+                LPWSTR ValueName,
+                ULONG Type,
+                LPVOID Data,
+                ULONG DataLength)
+{
+    UNICODE_STRING Name;
+
+    RtlInitUnicodeString(&Name,
+                         ValueName);
+
+    return ZwSetValueKey(KeyHandle,
+                         &Name,
+                         0,
+                         Type,
+                         Data,
+                         DataLength);
+}

Modified: trunk/reactos/dll/win32/samsrv/samrpc.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samsrv/samrpc.c?rev=56704&r1=56703&r2=56704&view=diff
==============================================================================
--- trunk/reactos/dll/win32/samsrv/samrpc.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/samsrv/samrpc.c [iso-8859-1] Thu Jun  7 10:31:17 
2012
@@ -1186,6 +1186,8 @@
     PSAM_DB_OBJECT AliasObject;
     LPWSTR MemberIdString = NULL;
     HANDLE MembersKeyHandle = NULL;
+    HANDLE MemberKeyHandle = NULL;
+    ULONG MemberIdLength;
     NTSTATUS Status;
 
     TRACE("SamrAddMemberToAlias(%p %p)\n",
@@ -1205,6 +1207,8 @@
     ConvertSidToStringSidW(MemberId, &MemberIdString);
     TRACE("Member SID: %S\n", MemberIdString);
 
+    MemberIdLength = RtlLengthSid(MemberId);
+
     Status = SampRegCreateKey(AliasObject->KeyHandle,
                               L"Members",
                               KEY_WRITE,
@@ -1218,10 +1222,39 @@
     Status = SampRegSetValue(MembersKeyHandle,
                              MemberIdString,
                              REG_BINARY,
-                             NULL,
-                             0);
+                             MemberId,
+                             MemberIdLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
+        goto done;
+    }
+
+    Status = SampRegCreateKey(AliasObject->MembersKeyHandle,
+                              MemberIdString,
+                              KEY_WRITE,
+                              &MemberKeyHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
+        goto done;
+    }
+
+    Status = SampRegSetValue(MemberKeyHandle,
+                             AliasObject->Name,
+                             REG_BINARY,
+                             MemberId,
+                             MemberIdLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
+        goto done;
+    }
 
 done:
+    if (MemberKeyHandle != NULL)
+        SampRegCloseKey(MemberKeyHandle);
+
     if (MembersKeyHandle != NULL)
         SampRegCloseKey(MembersKeyHandle);
 
@@ -1247,8 +1280,129 @@
 SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
                       OUT PSAMPR_PSID_ARRAY_OUT Members)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PSAM_DB_OBJECT AliasObject;
+    HANDLE MembersKeyHandle = NULL;
+    PSAMPR_SID_INFORMATION MemberArray = NULL;
+    ULONG ValueCount = 0;
+    ULONG DataLength;
+    ULONG Index;
+    NTSTATUS Status;
+
+    TRACE("SamrGetMembersInAlias(%p %p %p)\n",
+          AliasHandle, Members);
+
+    /* Validate the alias handle */
+    Status = SampValidateDbObject(AliasHandle,
+                                  SamDbAliasObject,
+                                  ALIAS_LIST_MEMBERS,
+                                  &AliasObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Open the members key of the alias objct */
+    Status = SampRegOpenKey(AliasObject->KeyHandle,
+                            L"Members",
+                            KEY_READ,
+                            &MembersKeyHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("SampRegOpenKey failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Get the number of members */
+    Status = SampRegQueryKeyInfo(MembersKeyHandle,
+                                 NULL,
+                                 &ValueCount);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
+        goto done;
+    }
+
+    /* Allocate the member array */
+    MemberArray = midl_user_allocate(ValueCount * 
sizeof(SAMPR_SID_INFORMATION));
+    if (MemberArray == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto done;
+    }
+
+    /* Enumerate the members */
+    Index = 0;
+    while (TRUE)
+    {
+        /* Get the size of the next SID */
+        DataLength = 0;
+        Status = SampRegEnumerateValue(MembersKeyHandle,
+                                       Index,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       &DataLength);
+        if (!NT_SUCCESS(Status))
+        {
+            if (Status == STATUS_NO_MORE_ENTRIES)
+                Status = STATUS_SUCCESS;
+            break;
+        }
+
+        /* Allocate a buffer for the SID */
+        MemberArray[Index].SidPointer = midl_user_allocate(DataLength);
+        if (MemberArray[Index].SidPointer == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto done;
+        }
+
+        /* Read the SID into the buffer */
+        Status = SampRegEnumerateValue(MembersKeyHandle,
+                                       Index,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       (PVOID)MemberArray[Index].SidPointer,
+                                       &DataLength);
+        if (!NT_SUCCESS(Status))
+        {
+            goto done;
+        }
+
+        Index++;
+    }
+
+    /* Return the number of members and the member array */
+    if (NT_SUCCESS(Status))
+    {
+        Members->Count = ValueCount;
+        Members->Sids = MemberArray;
+    }
+
+done:
+    /* Clean up the members array and the SID buffers if something failed */
+    if (!NT_SUCCESS(Status))
+    {
+        if (MemberArray != NULL)
+        {
+            for (Index = 0; Index < ValueCount; Index++)
+            {
+                if (MemberArray[Index].SidPointer != NULL)
+                    midl_user_free(MemberArray[Index].SidPointer);
+            }
+
+            midl_user_free(MemberArray);
+        }
+    }
+
+    /* Close the members key */
+    if (MembersKeyHandle != NULL)
+        SampRegCloseKey(MembersKeyHandle);
+
+    return Status;
 }
 
 /* Function 34 */

Modified: trunk/reactos/dll/win32/samsrv/samsrv.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samsrv/samsrv.h?rev=56704&r1=56703&r2=56704&view=diff
==============================================================================
--- trunk/reactos/dll/win32/samsrv/samsrv.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/samsrv/samsrv.h [iso-8859-1] Thu Jun  7 10:31:17 
2012
@@ -42,7 +42,9 @@
     SAM_DB_OBJECT_TYPE ObjectType;
     ULONG RefCount;
     ACCESS_MASK Access;
+    LPWSTR Name;
     HANDLE KeyHandle;
+    HANDLE MembersKeyHandle;  // only used by Aliases and Groups
     struct _SAM_DB_OBJECT *ParentObject;
 } SAM_DB_OBJECT, *PSAM_DB_OBJECT;
 
@@ -127,6 +129,20 @@
                OUT HANDLE KeyHandle);
 
 NTSTATUS
+SampRegQueryKeyInfo(IN HANDLE KeyHandle,
+                    OUT PULONG SubKeyCount,
+                    OUT PULONG ValueCount);
+
+NTSTATUS
+SampRegEnumerateValue(IN HANDLE KeyHandle,
+                      IN ULONG Index,
+                      OUT LPWSTR Name,
+                      IN OUT PULONG NameLength,
+                      OUT PULONG Type OPTIONAL,
+                      OUT PVOID Data OPTIONAL,
+                      IN OUT PULONG DataLength OPTIONAL);
+
+NTSTATUS
 SampRegQueryValue(IN HANDLE KeyHandle,
                   IN LPWSTR ValueName,
                   OUT PULONG Type OPTIONAL,

Modified: trunk/reactos/include/ddk/ntsam.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/ntsam.h?rev=56704&r1=56703&r2=56704&view=diff
==============================================================================
--- trunk/reactos/include/ddk/ntsam.h [iso-8859-1] (original)
+++ trunk/reactos/include/ddk/ntsam.h [iso-8859-1] Thu Jun  7 10:31:17 2012
@@ -166,6 +166,12 @@
 
 NTSTATUS
 NTAPI
+SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
+                     OUT PSID **MemberIds,
+                     OUT PULONG MemberCount);
+
+NTSTATUS
+NTAPI
 SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
                            IN PUNICODE_STRING Name,
                            OUT PSID *DomainId);


Reply via email to