diff --git a/reactos/dll/win32/samsrv/CMakeLists.txt b/reactos/dll/win32/samsrv/CMakeLists.txt index bdc88e0a55f..d52210a2621 100644 --- a/reactos/dll/win32/samsrv/CMakeLists.txt +++ b/reactos/dll/win32/samsrv/CMakeLists.txt @@ -9,6 +9,7 @@ spec2def(samsrv.dll samsrv.spec ADD_IMPORTLIB) list(APPEND SOURCE database.c + group.c registry.c samrpc.c samsrv.c diff --git a/reactos/dll/win32/samsrv/database.c b/reactos/dll/win32/samsrv/database.c index 59b99697dad..94e725230f5 100644 --- a/reactos/dll/win32/samsrv/database.c +++ b/reactos/dll/win32/samsrv/database.c @@ -555,7 +555,7 @@ done: NTSTATUS SampCheckAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject, - IN LPWSTR lpAccountName) + IN LPCWSTR lpAccountName) { HANDLE AccountKey; HANDLE NamesKey; diff --git a/reactos/dll/win32/samsrv/group.c b/reactos/dll/win32/samsrv/group.c new file mode 100644 index 00000000000..696beb4e5a8 --- /dev/null +++ b/reactos/dll/win32/samsrv/group.c @@ -0,0 +1,154 @@ +/* + * PROJECT: Local Security Authority Server DLL + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/win32/samsrv/group.c + * PURPOSE: Group specific helper functions + * COPYRIGHT: Copyright 2013 Eric Kohl + */ + +/* INCLUDES ****************************************************************/ + +#include "samsrv.h" + +WINE_DEFAULT_DEBUG_CHANNEL(samsrv); + + +/* FUNCTIONS ***************************************************************/ + + +NTSTATUS +SampAddMemberToGroup(IN PSAM_DB_OBJECT GroupObject, + IN ULONG MemberId) +{ + PULONG MembersBuffer = NULL; + ULONG MembersCount = 0; + ULONG Length = 0; + ULONG i; + NTSTATUS Status; + + Status = SampGetObjectAttribute(GroupObject, + L"Members", + NULL, + NULL, + &Length); + if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) + goto done; + + MembersBuffer = midl_user_allocate(Length + sizeof(ULONG)); + if (MembersBuffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + if (Status != STATUS_OBJECT_NAME_NOT_FOUND) + { + Status = SampGetObjectAttribute(GroupObject, + L"Members", + NULL, + MembersBuffer, + &Length); + if (!NT_SUCCESS(Status)) + goto done; + + MembersCount = Length / sizeof(ULONG); + } + + for (i = 0; i < MembersCount; i++) + { + if (MembersBuffer[i] == MemberId) + { + Status = STATUS_MEMBER_IN_GROUP; + goto done; + } + } + + MembersBuffer[MembersCount] = MemberId; + Length += sizeof(ULONG); + + Status = SampSetObjectAttribute(GroupObject, + L"Members", + REG_BINARY, + MembersBuffer, + Length); + +done: + if (MembersBuffer != NULL) + midl_user_free(MembersBuffer); + + return Status; +} + + +NTSTATUS +SampRemoveMemberFromGroup(IN PSAM_DB_OBJECT GroupObject, + IN ULONG MemberId) +{ + PULONG MembersBuffer = NULL; + ULONG MembersCount = 0; + ULONG Length = 0; + ULONG i; + NTSTATUS Status; + + Status = SampGetObjectAttribute(GroupObject, + L"Members", + NULL, + NULL, + &Length); + + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + return STATUS_MEMBER_NOT_IN_GROUP; + + if (!NT_SUCCESS(Status)) + return Status; + + MembersBuffer = midl_user_allocate(Length); + if (MembersBuffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + Status = SampGetObjectAttribute(GroupObject, + L"Members", + NULL, + MembersBuffer, + &Length); + if (!NT_SUCCESS(Status)) + goto done; + + Status = STATUS_MEMBER_NOT_IN_GROUP; + + MembersCount = Length / sizeof(ULONG); + for (i = 0; i < MembersCount; i++) + { + if (MembersBuffer[i] == MemberId) + { + Length -= sizeof(ULONG); + Status = STATUS_SUCCESS; + break; + } + + if (Status == STATUS_SUCCESS && i < MembersCount - 1) + { + MembersBuffer[i] = MembersBuffer[i + 1]; + } + } + + if (!NT_SUCCESS(Status)) + goto done; + + Status = SampSetObjectAttribute(GroupObject, + L"Members", + REG_BINARY, + MembersBuffer, + Length); + +done: + if (MembersBuffer != NULL) + midl_user_free(MembersBuffer); + + return Status; +} + +/* EOF */ diff --git a/reactos/dll/win32/samsrv/registry.c b/reactos/dll/win32/samsrv/registry.c index ed172edaec4..e00963213f7 100644 --- a/reactos/dll/win32/samsrv/registry.c +++ b/reactos/dll/win32/samsrv/registry.c @@ -202,7 +202,7 @@ SampRegQueryKeyInfo(IN HANDLE KeyHandle, NTSTATUS SampRegDeleteValue(IN HANDLE KeyHandle, - IN LPWSTR ValueName) + IN LPCWSTR ValueName) { UNICODE_STRING Name; @@ -322,7 +322,7 @@ done: NTSTATUS SampRegQueryValue(IN HANDLE KeyHandle, - IN LPWSTR ValueName, + IN LPCWSTR ValueName, OUT PULONG Type OPTIONAL, OUT PVOID Data OPTIONAL, IN OUT PULONG DataLength OPTIONAL) @@ -392,7 +392,7 @@ SampRegQueryValue(IN HANDLE KeyHandle, NTSTATUS SampRegSetValue(HANDLE KeyHandle, - LPWSTR ValueName, + LPCWSTR ValueName, ULONG Type, LPVOID Data, ULONG DataLength) diff --git a/reactos/dll/win32/samsrv/samrpc.c b/reactos/dll/win32/samsrv/samrpc.c index d996c8c68d6..6c522d6d4c2 100644 --- a/reactos/dll/win32/samsrv/samrpc.c +++ b/reactos/dll/win32/samsrv/samrpc.c @@ -191,7 +191,7 @@ NTSTATUS NTAPI SamrQuerySecurityObject(IN SAMPR_HANDLE ObjectHandle, IN SECURITY_INFORMATION SecurityInformation, - OUT PSAMPR_SR_SECURITY_DESCRIPTOR * SecurityDescriptor) + OUT PSAMPR_SR_SECURITY_DESCRIPTOR *SecurityDescriptor) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; @@ -3593,8 +3593,8 @@ SampQueryGroupGeneral(PSAM_DB_OBJECT GroupObject, PSAMPR_GROUP_INFO_BUFFER *Buffer) { PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL; - HANDLE MembersKeyHandle = NULL; SAM_GROUP_FIXED_DATA FixedData; + ULONG MembersLength = 0; ULONG Length = 0; NTSTATUS Status; @@ -3633,33 +3633,22 @@ SampQueryGroupGeneral(PSAM_DB_OBJECT GroupObject, InfoBuffer->General.Attributes = FixedData.Attributes; - /* Open the Members subkey */ - Status = SampRegOpenKey(GroupObject->KeyHandle, - L"Members", - KEY_READ, - &MembersKeyHandle); - if (!NT_SUCCESS(Status)) - { - TRACE("Status 0x%08lx\n", Status); + Status = SampGetObjectAttribute(GroupObject, + L"Members", + NULL, + NULL, + &MembersLength); + if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) goto done; - } - /* Retrieve the number of members of the alias */ - Status = SampRegQueryKeyInfo(MembersKeyHandle, - NULL, - &InfoBuffer->General.MemberCount); - if (!NT_SUCCESS(Status)) - { - TRACE("Status 0x%08lx\n", Status); - goto done; - } + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + InfoBuffer->General.MemberCount = 0; + else + InfoBuffer->General.MemberCount = MembersLength / sizeof(ULONG); *Buffer = InfoBuffer; done: - if (MembersKeyHandle != NULL) - SampRegCloseKey(MembersKeyHandle); - if (!NT_SUCCESS(Status)) { if (InfoBuffer != NULL) @@ -3941,10 +3930,29 @@ SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle, IN unsigned long MemberId, IN unsigned long Attributes) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT GroupObject; + NTSTATUS Status; + + TRACE("(%p %lu %lx)\n", + GroupHandle, MemberId, Attributes); + + /* Validate the group handle */ + Status = SampValidateDbObject(GroupHandle, + SamDbGroupObject, + GROUP_ADD_MEMBER, + &GroupObject); + if (!NT_SUCCESS(Status)) + return Status; + + /* FIXME: Add group membership to the user object */ + + Status = SampAddMemberToGroup(GroupObject, + MemberId); + + return Status; } + /* Function 21 */ NTSTATUS NTAPI @@ -3954,16 +3962,36 @@ SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle) return STATUS_NOT_IMPLEMENTED; } + /* Function 24 */ NTSTATUS NTAPI SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle, IN unsigned long MemberId) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT GroupObject; + NTSTATUS Status; + + TRACE("(%p %lu)\n", + GroupHandle, MemberId); + + /* Validate the group handle */ + Status = SampValidateDbObject(GroupHandle, + SamDbGroupObject, + GROUP_REMOVE_MEMBER, + &GroupObject); + if (!NT_SUCCESS(Status)) + return Status; + + /* FIXME: Remove group membership from the user object */ + + Status = SampRemoveMemberFromGroup(GroupObject, + MemberId); + + return Status; } + /* Function 25 */ NTSTATUS NTAPI diff --git a/reactos/dll/win32/samsrv/samsrv.h b/reactos/dll/win32/samsrv/samsrv.h index 609a4029bd7..55db546537a 100644 --- a/reactos/dll/win32/samsrv/samsrv.h +++ b/reactos/dll/win32/samsrv/samsrv.h @@ -1,6 +1,6 @@ /* * COPYRIGHT: See COPYING in the top level directory - * PROJECT: Security Account Manager (LSA) Server + * PROJECT: Security Account Manager (SAM) Server * FILE: reactos/dll/win32/samsrv/samsrv.h * PURPOSE: Common header file * @@ -109,6 +109,7 @@ typedef struct _SAM_USER_FIXED_DATA USHORT OperatorCount; } SAM_USER_FIXED_DATA, *PSAM_USER_FIXED_DATA; + /* database.c */ NTSTATUS @@ -143,7 +144,7 @@ SampCloseDbObject(PSAM_DB_OBJECT DbObject); NTSTATUS SampCheckAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject, - IN LPWSTR lpAccountName); + IN LPCWSTR lpAccountName); NTSTATUS SampSetAccountNameInDomain(IN PSAM_DB_OBJECT DomainObject, @@ -170,7 +171,20 @@ SampGetObjectAttributeString(PSAM_DB_OBJECT DbObject, LPWSTR AttributeName, RPC_UNICODE_STRING *String); + +/* group.h */ + +NTSTATUS +SampAddMemberToGroup(IN PSAM_DB_OBJECT GroupObject, + IN ULONG MemberId); + +NTSTATUS +SampRemoveMemberFromGroup(IN PSAM_DB_OBJECT GroupObject, + IN ULONG MemberId); + + /* registry.h */ + NTSTATUS SampRegCloseKey(IN HANDLE KeyHandle); @@ -203,7 +217,7 @@ SampRegQueryKeyInfo(IN HANDLE KeyHandle, NTSTATUS SampRegDeleteValue(IN HANDLE KeyHandle, - IN LPWSTR ValueName); + IN LPCWSTR ValueName); NTSTATUS SampRegEnumerateValue(IN HANDLE KeyHandle, @@ -216,21 +230,27 @@ SampRegEnumerateValue(IN HANDLE KeyHandle, NTSTATUS SampRegQueryValue(IN HANDLE KeyHandle, - IN LPWSTR ValueName, + IN LPCWSTR ValueName, OUT PULONG Type OPTIONAL, OUT LPVOID Data OPTIONAL, IN OUT PULONG DataLength OPTIONAL); NTSTATUS SampRegSetValue(IN HANDLE KeyHandle, - IN LPWSTR ValueName, + IN LPCWSTR ValueName, IN ULONG Type, IN LPVOID Data, IN ULONG DataLength); + /* samspc.c */ + VOID SampStartRpcServer(VOID); + /* setup.c */ + BOOL SampIsSetupRunning(VOID); -BOOL SampInitializeSAM(VOID); \ No newline at end of file +BOOL SampInitializeSAM(VOID); + +/* EOF */