- 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.

svn path=/trunk/; revision=58196
This commit is contained in:
Eric Kohl 2013-01-20 10:22:15 +00:00
parent 56704cdb76
commit 7a779210ab
3 changed files with 196 additions and 22 deletions

View file

@ -157,8 +157,7 @@ SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject,
0,
NULL);
if ((ObjectType == SamDbAliasObject) ||
(ObjectType == SamDbGroupObject))
if (ObjectType == SamDbAliasObject)
{
/* Open the object key */
RtlInitUnicodeString(&KeyName,
@ -244,9 +243,6 @@ SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject,
NewObject->RelativeId = RelativeId;
NewObject->ParentObject = ParentObject;
if (ParentObject != NULL)
ParentObject->RefCount++;
*DbObject = NewObject;
return STATUS_SUCCESS;
@ -313,8 +309,7 @@ SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject,
KEY_ALL_ACCESS,
&ObjectAttributes);
if ((ObjectType == SamDbAliasObject) ||
(ObjectType == SamDbGroupObject))
if (ObjectType == SamDbAliasObject)
{
/* Open the object key */
RtlInitUnicodeString(&KeyName,
@ -396,9 +391,6 @@ SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject,
NewObject->RelativeId = RelativeId;
NewObject->ParentObject = ParentObject;
if (ParentObject != NULL)
ParentObject->RefCount++;
*DbObject = NewObject;
return STATUS_SUCCESS;
@ -475,14 +467,144 @@ SampCloseDbObject(PSAM_DB_OBJECT DbObject)
RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
if (ParentObject != NULL)
{
ParentObject->RefCount--;
return Status;
}
if (ParentObject->RefCount == 0)
Status = SampCloseDbObject(ParentObject);
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;
}

View file

@ -3952,7 +3952,7 @@ SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle,
&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 @@ SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle,
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 @@ SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle,
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 @@ NTSTATUS
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;
}

View file

@ -29,7 +29,6 @@
typedef enum _SAM_DB_OBJECT_TYPE
{
SamDbIgnoreObject,
SamDbContainerObject,
SamDbServerObject,
SamDbDomainObject,
SamDbAliasObject,
@ -45,7 +44,7 @@ typedef struct _SAM_DB_OBJECT
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;
@ -142,6 +141,9 @@ SampValidateDbObject(SAMPR_HANDLE Handle,
NTSTATUS
SampCloseDbObject(PSAM_DB_OBJECT DbObject);
NTSTATUS
SampDeleteAccountDbObject(PSAM_DB_OBJECT DbObject);
NTSTATUS
SampSetObjectAttribute(PSAM_DB_OBJECT DbObject,
LPWSTR AttributeName,