SAMLIB: Implement SamCreateGroupInDoamin and SamOpenGroup.
authorEric Kohl <eric.kohl@reactos.org>
Sun, 15 Jul 2012 13:35:40 +0000 (13:35 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 15 Jul 2012 13:35:40 +0000 (13:35 +0000)
SAMSRV: Implement SamrCreateGroupInDomain and SamrOpenGroup.

svn path=/trunk/; revision=56896

reactos/dll/win32/samlib/samlib.c
reactos/dll/win32/samlib/samlib.spec
reactos/dll/win32/samsrv/registry.c
reactos/dll/win32/samsrv/samrpc.c
reactos/dll/win32/samsrv/samsrv.h
reactos/include/ddk/ntsam.h
reactos/include/reactos/idl/sam.idl

index 7cb6c55..bcc55b3 100644 (file)
@@ -209,6 +209,37 @@ SamCreateAliasInDomain(IN SAM_HANDLE DomainHandle,
 }
 
 
+NTSTATUS
+NTAPI
+SamCreateGroupInDomain(IN SAM_HANDLE DomainHandle,
+                       IN PUNICODE_STRING AccountName,
+                       IN ACCESS_MASK DesiredAccess,
+                       OUT PSAM_HANDLE GroupHandle,
+                       OUT PULONG RelativeId)
+{
+    NTSTATUS Status;
+
+    TRACE("SamCreateGroupInDomain(%p,%p,0x%08x,%p,%p)\n",
+          DomainHandle, AccountName, DesiredAccess, GroupHandle, RelativeId);
+
+    RpcTryExcept
+    {
+        Status = SamrCreateGroupInDomain((SAMPR_HANDLE)DomainHandle,
+                                         (PRPC_UNICODE_STRING)AccountName,
+                                         DesiredAccess,
+                                         (SAMPR_HANDLE *)GroupHandle,
+                                         RelativeId);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
 NTSTATUS
 NTAPI
 SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
@@ -542,6 +573,35 @@ SamOpenDomain(IN SAM_HANDLE ServerHandle,
 }
 
 
+NTSTATUS
+NTAPI
+SamOpenGroup(IN SAM_HANDLE DomainHandle,
+             IN ACCESS_MASK DesiredAccess,
+             IN ULONG GroupId,
+             OUT PSAM_HANDLE GroupHandle)
+{
+    NTSTATUS Status;
+
+    TRACE("SamOpenGroup(%p,0x%08x,%p,%p)\n",
+          DomainHandle, DesiredAccess, GroupId, GroupHandle);
+
+    RpcTryExcept
+    {
+        Status = SamrOpenGroup((SAMPR_HANDLE)DomainHandle,
+                               DesiredAccess,
+                               GroupId,
+                               (SAMPR_HANDLE *)GroupHandle);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = I_RpcMapWin32Status(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return Status;
+}
+
+
 NTSTATUS
 NTAPI
 SamOpenUser(IN SAM_HANDLE DomainHandle,
index 4810b43..a56f817 100644 (file)
@@ -8,7 +8,7 @@
 @ stdcall SamConnect(ptr ptr long ptr)
 @ stub SamConnectWithCreds
 @ stdcall SamCreateAliasInDomain(ptr ptr long ptr ptr)
-@ stub SamCreateGroupInDomain
+@ stdcall SamCreateGroupInDomain(ptr ptr long ptr ptr)
 @ stub SamCreateUser2InDomain
 @ stdcall SamCreateUserInDomain(ptr ptr long ptr ptr)
 @ stub SamDeleteAlias
@@ -30,7 +30,7 @@
 @ stdcall SamLookupNamesInDomain(ptr long ptr ptr ptr)
 @ stdcall SamOpenAlias(ptr long long ptr)
 @ stdcall SamOpenDomain(ptr long ptr ptr)
-@ stub SamOpenGroup
+@ stdcall SamOpenGroup(ptr long long ptr)
 @ stdcall SamOpenUser(ptr long long ptr)
 @ stub SamQueryDisplayInformation
 @ stdcall SamQueryInformationAlias(ptr long ptr)
index cdac96a..ed172ed 100644 (file)
@@ -59,6 +59,36 @@ SampRegCreateKey(IN HANDLE ParentKeyHandle,
 }
 
 
+NTSTATUS
+SampRegDeleteKey(IN HANDLE ParentKeyHandle,
+                 IN LPCWSTR KeyName)
+{
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING SubKeyName;
+    HANDLE TargetKey;
+    NTSTATUS Status;
+
+    RtlInitUnicodeString(&SubKeyName,
+                         (LPWSTR)KeyName);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &SubKeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               ParentKeyHandle,
+                               NULL);
+    Status = NtOpenKey(&TargetKey,
+                       DELETE,
+                       &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    Status = NtDeleteKey(TargetKey);
+
+    NtClose(TargetKey);
+
+    return Status;
+}
+
+
 NTSTATUS
 SampRegEnumerateSubKey(IN HANDLE KeyHandle,
                        IN ULONG Index,
@@ -170,6 +200,20 @@ SampRegQueryKeyInfo(IN HANDLE KeyHandle,
 }
 
 
+NTSTATUS
+SampRegDeleteValue(IN HANDLE KeyHandle,
+                   IN LPWSTR ValueName)
+{
+    UNICODE_STRING Name;
+
+    RtlInitUnicodeString(&Name,
+                         ValueName);
+
+    return NtDeleteValueKey(KeyHandle,
+                            &Name);
+}
+
+
 NTSTATUS
 SampRegEnumerateValue(IN HANDLE KeyHandle,
                       IN ULONG Index,
index e5fda13..7db9e52 100644 (file)
@@ -1541,11 +1541,145 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
                         OUT SAMPR_HANDLE *GroupHandle,
                         OUT unsigned long *RelativeId)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
+    SAM_DOMAIN_FIXED_DATA FixedDomainData;
+    SAM_GROUP_FIXED_DATA FixedGroupData;
+    PSAM_DB_OBJECT DomainObject;
+    PSAM_DB_OBJECT GroupObject;
+    ULONG ulSize;
+    ULONG ulRid;
+    WCHAR szRid[9];
+    NTSTATUS Status;
+
+    TRACE("SamrCreateGroupInDomain(%p %p %lx %p %p)\n",
+          DomainHandle, Name, DesiredAccess, GroupHandle, RelativeId);
+
+    /* Validate the domain handle */
+    Status = SampValidateDbObject(DomainHandle,
+                                  SamDbDomainObject,
+                                  DOMAIN_CREATE_GROUP,
+                                  &DomainObject);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Get the fixed domain attributes */
+    ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
+    Status = SampGetObjectAttribute(DomainObject,
+                                    L"F",
+                                    NULL,
+                                    (PVOID)&FixedDomainData,
+                                    &ulSize);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Increment the NextRid attribute */
+    ulRid = FixedDomainData.NextRid;
+    FixedDomainData.NextRid++;
+
+    /* Store the fixed domain attributes */
+    Status = SampSetObjectAttribute(DomainObject,
+                           L"F",
+                           REG_BINARY,
+                           &FixedDomainData,
+                           ulSize);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    TRACE("RID: %lx\n", ulRid);
+
+    /* Convert the RID into a string (hex) */
+    swprintf(szRid, L"%08lX", ulRid);
+
+    /* FIXME: Check whether the group name is already in use */
+
+    /* Create the group object */
+    Status = SampCreateDbObject(DomainObject,
+                                L"Groups",
+                                szRid,
+                                SamDbGroupObject,
+                                DesiredAccess,
+                                &GroupObject);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Add the name alias for the user object */
+    Status = SampSetDbObjectNameAlias(DomainObject,
+                                      L"Groups",
+                                      Name->Buffer,
+                                      ulRid);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Initialize fixed user data */
+    memset(&FixedGroupData, 0, sizeof(SAM_GROUP_FIXED_DATA));
+    FixedGroupData.Version = 1;
+
+    FixedGroupData.GroupId = ulRid;
+
+    /* Set fixed user data attribute */
+    Status = SampSetObjectAttribute(GroupObject,
+                                    L"F",
+                                    REG_BINARY,
+                                    (LPVOID)&FixedGroupData,
+                                    sizeof(SAM_GROUP_FIXED_DATA));
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Set the Name attribute */
+    Status = SampSetObjectAttribute(GroupObject,
+                                    L"Name",
+                                    REG_SZ,
+                                    (LPVOID)Name->Buffer,
+                                    Name->MaximumLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Set the AdminComment attribute */
+    Status = SampSetObjectAttribute(GroupObject,
+                                    L"AdminComment",
+                                    REG_SZ,
+                                    EmptyString.Buffer,
+                                    EmptyString.MaximumLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    if (NT_SUCCESS(Status))
+    {
+        *GroupHandle = (SAMPR_HANDLE)GroupObject;
+        *RelativeId = ulRid;
+    }
+
+    TRACE("returns with status 0x%08lx\n", Status);
+
+    return Status;
 }
 
-/* Function 10 */
+
+/* Function 11 */
 NTSTATUS
 NTAPI
 SamrEnumerateGroupsInDomain(IN SAMPR_HANDLE DomainHandle,
@@ -1558,6 +1692,7 @@ SamrEnumerateGroupsInDomain(IN SAMPR_HANDLE DomainHandle,
     return STATUS_NOT_IMPLEMENTED;
 }
 
+
 /* Function 12 */
 NTSTATUS
 NTAPI
@@ -1567,6 +1702,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
                        OUT SAMPR_HANDLE *UserHandle,
                        OUT unsigned long *RelativeId)
 {
+    UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
     SAM_DOMAIN_FIXED_DATA FixedDomainData;
     SAM_USER_FIXED_DATA FixedUserData;
     PSAM_DB_OBJECT DomainObject;
@@ -1684,7 +1820,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
         return Status;
     }
 
-    /* Set the name attribute */
+    /* Set the Name attribute */
     Status = SampSetObjectAttribute(UserObject,
                                     L"Name",
                                     REG_SZ,
@@ -1696,6 +1832,102 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
         return Status;
     }
 
+    /* Set the FullName attribute */
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"FullName",
+                                    REG_SZ,
+                                    EmptyString.Buffer,
+                                    EmptyString.MaximumLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Set the HomeDirectory attribute */
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"HomeDirectory",
+                                    REG_SZ,
+                                    EmptyString.Buffer,
+                                    EmptyString.MaximumLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Set the HomeDirectoryDrive attribute */
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"HomeDirectoryDrive",
+                                    REG_SZ,
+                                    EmptyString.Buffer,
+                                    EmptyString.MaximumLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Set the ScriptPath attribute */
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"ScriptPath",
+                                    REG_SZ,
+                                    EmptyString.Buffer,
+                                    EmptyString.MaximumLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Set the ProfilePath attribute */
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"ProfilePath",
+                                    REG_SZ,
+                                    EmptyString.Buffer,
+                                    EmptyString.MaximumLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Set the AdminComment attribute */
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"AdminComment",
+                                    REG_SZ,
+                                    EmptyString.Buffer,
+                                    EmptyString.MaximumLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Set the UserComment attribute */
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"UserComment",
+                                    REG_SZ,
+                                    EmptyString.Buffer,
+                                    EmptyString.MaximumLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Set the WorkStations attribute */
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"WorkStations",
+                                    REG_SZ,
+                                    EmptyString.Buffer,
+                                    EmptyString.MaximumLength);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
     /* FIXME: Set default user attributes */
 
     if (NT_SUCCESS(Status))
@@ -1709,6 +1941,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     return Status;
 }
 
+
 /* Function 13 */
 NTSTATUS
 NTAPI
@@ -1723,6 +1956,7 @@ SamrEnumerateUsersInDomain(IN SAMPR_HANDLE DomainHandle,
     return STATUS_NOT_IMPLEMENTED;
 }
 
+
 /* Function 14 */
 NTSTATUS
 NTAPI
@@ -1807,7 +2041,7 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
         return STATUS_ALIAS_EXISTS;
     }
 
-    /* Create the user object */
+    /* Create the alias object */
     Status = SampCreateDbObject(DomainObject,
                                 L"Aliases",
                                 szRid,
@@ -2239,6 +2473,7 @@ done:
     return Status;
 }
 
+
 /* Function 17 */
 NTSTATUS
 NTAPI
@@ -2265,6 +2500,7 @@ SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
     return STATUS_NOT_IMPLEMENTED;
 }
 
+
 /* Function 19 */
 NTSTATUS
 NTAPI
@@ -2273,10 +2509,47 @@ SamrOpenGroup(IN SAMPR_HANDLE DomainHandle,
               IN unsigned long GroupId,
               OUT SAMPR_HANDLE *GroupHandle)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PSAM_DB_OBJECT DomainObject;
+    PSAM_DB_OBJECT GroupObject;
+    WCHAR szRid[9];
+    NTSTATUS Status;
+
+    TRACE("SamrOpenGroup(%p %lx %lx %p)\n",
+          DomainHandle, DesiredAccess, GroupId, GroupHandle);
+
+    /* Validate the domain handle */
+    Status = SampValidateDbObject(DomainHandle,
+                                  SamDbDomainObject,
+                                  DOMAIN_LOOKUP,
+                                  &DomainObject);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Convert the RID into a string (hex) */
+    swprintf(szRid, L"%08lX", GroupId);
+
+    /* Create the group object */
+    Status = SampOpenDbObject(DomainObject,
+                              L"Groups",
+                              szRid,
+                              SamDbGroupObject,
+                              DesiredAccess,
+                              &GroupObject);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("failed with status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    *GroupHandle = (SAMPR_HANDLE)GroupObject;
+
+    return STATUS_SUCCESS;
 }
 
+
 /* Function 20 */
 NTSTATUS
 NTAPI
@@ -2674,7 +2947,7 @@ SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
     TRACE("SamrAddMemberToAlias(%p %p)\n",
           AliasHandle, MemberId);
 
-    /* Validate the domain handle */
+    /* Validate the alias handle */
     Status = SampValidateDbObject(AliasHandle,
                                   SamDbAliasObject,
                                   ALIAS_ADD_MEMBER,
index 123fdc4..6d83b4e 100644 (file)
@@ -51,6 +51,13 @@ typedef struct _SAM_DB_OBJECT
 
 #define SAMP_DB_SIGNATURE 0x87654321
 
+typedef struct _SAM_ALIAS_FIXED_DATA
+{
+    ULONG Version;
+    ULONG Reserved;
+    ULONG AliasId;
+} SAM_ALIAS_FIXED_DATA, *PSAM_ALIAS_FIXED_DATA;
+
 typedef struct _SAM_DOMAIN_FIXED_DATA
 {
     ULONG Version;
@@ -73,6 +80,14 @@ typedef struct _SAM_DOMAIN_FIXED_DATA
     BOOLEAN UasCompatibilityRequired;
 } SAM_DOMAIN_FIXED_DATA, *PSAM_DOMAIN_FIXED_DATA;
 
+typedef struct _SAM_GROUP_FIXED_DATA
+{
+    ULONG Version;
+    ULONG Reserved;
+    ULONG GroupId;
+    ULONG Attributes;
+} SAM_GROUP_FIXED_DATA, *PSAM_GROUP_FIXED_DATA;
+
 typedef struct _SAM_USER_FIXED_DATA
 {
     ULONG Version;
@@ -164,6 +179,10 @@ SampRegCreateKey(IN HANDLE ParentKeyHandle,
                  IN ACCESS_MASK DesiredAccess,
                  OUT HANDLE KeyHandle);
 
+NTSTATUS
+SampRegDeleteKey(IN HANDLE ParentKeyHandle,
+                 IN LPCWSTR KeyName);
+
 NTSTATUS
 SampRegEnumerateSubKey(IN HANDLE KeyHandle,
                        IN ULONG Index,
@@ -181,6 +200,10 @@ SampRegQueryKeyInfo(IN HANDLE KeyHandle,
                     OUT PULONG SubKeyCount,
                     OUT PULONG ValueCount);
 
+NTSTATUS
+SampRegDeleteValue(IN HANDLE KeyHandle,
+                   IN LPWSTR ValueName);
+
 NTSTATUS
 SampRegEnumerateValue(IN HANDLE KeyHandle,
                       IN ULONG Index,
index 2181aae..1e13410 100644 (file)
@@ -237,6 +237,15 @@ typedef struct _DOMAIN_NAME_INFORMATION
     UNICODE_STRING DomainName;
 } DOMAIN_NAME_INFORMATION, *PDOMAIN_NAME_INFORMATION;
 
+typedef enum _GROUP_INFORMATION_CLASS
+{
+    GroupGeneralInformation = 1,
+    GroupNameInformation,
+    GroupAttributeInformation,
+    GroupAdminCommentInformation,
+    GroupReplicationInformation
+} GROUP_INFORMATION_CLASS;
+
 typedef enum _USER_INFORMATION_CLASS
 {
     UserGeneralInformation = 1,
@@ -301,6 +310,14 @@ SamCreateAliasInDomain(IN SAM_HANDLE DomainHandle,
                        OUT PSAM_HANDLE AliasHandle,
                        OUT PULONG RelativeId);
 
+NTSTATUS
+NTAPI
+SamCreateGroupInDomain(IN SAM_HANDLE DomainHandle,
+                       IN PUNICODE_STRING AccountName,
+                       IN ACCESS_MASK DesiredAccess,
+                       OUT PSAM_HANDLE GroupHandle,
+                       OUT PULONG RelativeId);
+
 NTSTATUS
 NTAPI
 SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
@@ -371,6 +388,13 @@ SamOpenDomain(IN SAM_HANDLE ServerHandle,
               IN PSID DomainId,
               OUT PSAM_HANDLE DomainHandle);
 
+NTSTATUS
+NTAPI
+SamOpenGroup(IN SAM_HANDLE DomainHandle,
+             IN ACCESS_MASK DesiredAccess,
+             IN ULONG GroupId,
+             OUT PSAM_HANDLE GroupHandle);
+
 NTSTATUS
 NTAPI
 SamOpenUser(IN SAM_HANDLE DomainHandle,
index 43f23f8..90d5406 100644 (file)
@@ -382,6 +382,7 @@ typedef struct _SAMPR_GROUP_ADM_COMMENT_INFORMATION
     RPC_UNICODE_STRING AdminComment;
 } SAMPR_GROUP_ADM_COMMENT_INFORMATION, *PSAMPR_GROUP_ADM_COMMENT_INFORMATION;
 
+cpp_quote("#ifndef _NTSAM_")
 typedef enum _GROUP_INFORMATION_CLASS
 {
     GroupGeneralInformation = 1,
@@ -390,6 +391,7 @@ typedef enum _GROUP_INFORMATION_CLASS
     GroupAdminCommentInformation,
     GroupReplicationInformation
 } GROUP_INFORMATION_CLASS;
+cpp_quote("#endif")
 
 typedef [switch_type(GROUP_INFORMATION_CLASS)] union _SAMPR_GROUP_INFO_BUFFER
 {