Author: ekohl Date: Sun Jan 20 10:22:15 2013 New Revision: 58196
URL: http://svn.reactos.org/svn/reactos?rev=58196&view=rev Log: [SAMSRV] - Add a generic delete function for database objects. - Do not create Members sub keys for group objects. - Get rid of the SamDbContainerObject object type. - Implement SamrDeleteGroup.
Modified: trunk/reactos/dll/win32/samsrv/database.c trunk/reactos/dll/win32/samsrv/samrpc.c trunk/reactos/dll/win32/samsrv/samsrv.h
Modified: trunk/reactos/dll/win32/samsrv/database.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samsrv/database.c... ============================================================================== --- trunk/reactos/dll/win32/samsrv/database.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/samsrv/database.c [iso-8859-1] Sun Jan 20 10:22:15 2013 @@ -157,8 +157,7 @@ 0, NULL);
- if ((ObjectType == SamDbAliasObject) || - (ObjectType == SamDbGroupObject)) + if (ObjectType == SamDbAliasObject) { /* Open the object key */ RtlInitUnicodeString(&KeyName, @@ -244,9 +243,6 @@ NewObject->RelativeId = RelativeId; NewObject->ParentObject = ParentObject;
- if (ParentObject != NULL) - ParentObject->RefCount++; - *DbObject = NewObject;
return STATUS_SUCCESS; @@ -313,8 +309,7 @@ KEY_ALL_ACCESS, &ObjectAttributes);
- if ((ObjectType == SamDbAliasObject) || - (ObjectType == SamDbGroupObject)) + if (ObjectType == SamDbAliasObject) { /* Open the object key */ RtlInitUnicodeString(&KeyName, @@ -396,9 +391,6 @@ NewObject->RelativeId = RelativeId; NewObject->ParentObject = ParentObject;
- if (ParentObject != NULL) - ParentObject->RefCount++; - *DbObject = NewObject;
return STATUS_SUCCESS; @@ -475,13 +467,143 @@
RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
- if (ParentObject != NULL) - { - ParentObject->RefCount--; - - if (ParentObject->RefCount == 0) - Status = SampCloseDbObject(ParentObject); - } + return Status; +} + + +NTSTATUS +SampDeleteAccountDbObject(PSAM_DB_OBJECT DbObject) +{ + LPCWSTR ContainerName; + LPWSTR AccountName = NULL; + HKEY ContainerKey; + HKEY NamesKey; + ULONG Length = 0; + NTSTATUS Status = STATUS_SUCCESS; + + TRACE("(%p)\n", DbObject); + + /* Server and Domain objects cannot be deleted */ + switch (DbObject->ObjectType) + { + case SamDbAliasObject: + ContainerName = L"Aliases"; + break; + + case SamDbGroupObject: + ContainerName = L"Groups"; + break; + + case SamDbUserObject: + ContainerName = L"Users"; + break; + + default: + return STATUS_INVALID_PARAMETER; + } + + /* Get the account name */ + Status = SampGetObjectAttribute(DbObject, + L"Name", + NULL, + NULL, + &Length); + if (Status != STATUS_BUFFER_OVERFLOW) + { + TRACE("Status 0x%08lx\n", Status); + goto done; + } + + AccountName = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + Length); + if (AccountName == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + Status = SampGetObjectAttribute(DbObject, + L"Name", + NULL, + (PVOID)AccountName, + &Length); + if (!NT_SUCCESS(Status)) + { + TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status); + goto done; + } + + if (DbObject->KeyHandle != NULL) + NtClose(DbObject->KeyHandle); + + if (DbObject->ObjectType == SamDbAliasObject) + { + if (DbObject->MembersKeyHandle != NULL) + NtClose(DbObject->MembersKeyHandle); + + SampRegDeleteKey(DbObject->KeyHandle, + L"Members"); + } + + /* Open the domain container key */ + Status = SampRegOpenKey(DbObject->ParentObject->KeyHandle, + ContainerName, + DELETE | KEY_SET_VALUE, + &ContainerKey); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegOpenKey failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Open the Names key */ + Status = SampRegOpenKey(ContainerKey, + L"Names", + KEY_SET_VALUE, + &NamesKey); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegOpenKey failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Remove the account from the Names key */ + Status = SampRegDeleteValue(NamesKey, + AccountName); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegDeleteValue failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Remove the account key from the container */ + Status = SampRegDeleteKey(ContainerKey, + DbObject->Name); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegDeleteKey failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Release the database object name */ + if (DbObject->Name != NULL) + RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject->Name); + + /* Release the database object */ + RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject); + + Status = STATUS_SUCCESS; + +done: + if (NamesKey != NULL) + SampRegCloseKey(NamesKey); + + if (ContainerKey != NULL) + SampRegCloseKey(ContainerKey); + + if (AccountName != NULL) + RtlFreeHeap(RtlGetProcessHeap(), 0, AccountName);
return Status; }
Modified: trunk/reactos/dll/win32/samsrv/samrpc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samsrv/samrpc.c?r... ============================================================================== --- trunk/reactos/dll/win32/samsrv/samrpc.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/samsrv/samrpc.c [iso-8859-1] Sun Jan 20 10:22:15 2013 @@ -3952,7 +3952,7 @@ &UserObject); if (!NT_SUCCESS(Status)) { - ERR("SampOpenUserObject() failed (Status 0x%08lx)\n", Status); + TRACE("SampOpenUserObject() failed (Status 0x%08lx)\n", Status); goto done; }
@@ -3962,7 +3962,7 @@ Attributes); if (!NT_SUCCESS(Status)) { - ERR("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status); + TRACE("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status); goto done; }
@@ -3971,7 +3971,7 @@ MemberId); if (!NT_SUCCESS(Status)) { - ERR("SampAddMemberToGroup() failed (Status 0x%08lx)\n", Status); + TRACE("SampAddMemberToGroup() failed (Status 0x%08lx)\n", Status); }
done: @@ -3987,8 +3987,58 @@ NTAPI SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT GroupObject; + ULONG Length = 0; + NTSTATUS Status; + + TRACE("(%p)\n", GroupHandle); + + /* Validate the group handle */ + Status = SampValidateDbObject(*GroupHandle, + SamDbGroupObject, + DELETE, + &GroupObject); + if (!NT_SUCCESS(Status)) + { + TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status); + return Status; + } + + /* Fail, if the group is built-in */ + if (GroupObject->RelativeId < 1000) + { + TRACE("You can not delete a special account!\n"); + return STATUS_SPECIAL_ACCOUNT; + } + + /* Get the length of the Members attribute */ + SampGetObjectAttribute(GroupObject, + L"Members", + NULL, + NULL, + &Length); + + /* Fail, if the group has members */ + if (Length != 0) + { + TRACE("There are still members in the group!\n"); + return STATUS_MEMBER_IN_GROUP; + } + + /* FIXME: Remove the group from all aliases */ + + /* Delete the group from the database */ + Status = SampDeleteAccountDbObject(GroupObject); + if (!NT_SUCCESS(Status)) + { + TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status); + return Status; + } + + /* Invalidate the handle */ + *GroupHandle = NULL; + + return STATUS_SUCCESS; }
Modified: trunk/reactos/dll/win32/samsrv/samsrv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/samsrv/samsrv.h?r... ============================================================================== --- trunk/reactos/dll/win32/samsrv/samsrv.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/samsrv/samsrv.h [iso-8859-1] Sun Jan 20 10:22:15 2013 @@ -29,7 +29,6 @@ typedef enum _SAM_DB_OBJECT_TYPE { SamDbIgnoreObject, - SamDbContainerObject, SamDbServerObject, SamDbDomainObject, SamDbAliasObject, @@ -45,7 +44,7 @@ ACCESS_MASK Access; LPWSTR Name; HANDLE KeyHandle; - HANDLE MembersKeyHandle; // only used by Aliases and Groups + HANDLE MembersKeyHandle; // only used by Aliases ULONG RelativeId; struct _SAM_DB_OBJECT *ParentObject; } SAM_DB_OBJECT, *PSAM_DB_OBJECT; @@ -143,6 +142,9 @@ SampCloseDbObject(PSAM_DB_OBJECT DbObject);
NTSTATUS +SampDeleteAccountDbObject(PSAM_DB_OBJECT DbObject); + +NTSTATUS SampSetObjectAttribute(PSAM_DB_OBJECT DbObject, LPWSTR AttributeName, ULONG AttributeType,