From f82ab0c4b0f1169b385448e33d83973f871978fd Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 3 Jun 2012 20:54:06 +0000 Subject: [PATCH] [SAMLIB]: Implement SamAddMemberToAlias, SamCreateAliasInDomain, SamEnumerateDomainsInSamServer, SamOpenAlias, SamQueryInformationDomain and SamQueryInformationUser. [SAMSRV]: Implement SamrEnumerateDomainsInSamServer (buggy, probably a bug in WIDL), SamrQueryInformationDomain.DomainNameInformation, SamrCreateAliasInDomain, SamrOpenAlias and SamrAddMemberToAlias. [SAMSRV]: Add more registry helper routines. [SAMSRV]: Create builtin aliases upon setup. svn path=/trunk/; revision=56690 --- reactos/dll/win32/samlib/samlib.c | 185 +++++++++- reactos/dll/win32/samlib/samlib.spec | 10 +- reactos/dll/win32/samsrv/registry.c | 41 ++- reactos/dll/win32/samsrv/samrpc.c | 488 ++++++++++++++++++++++++++- reactos/dll/win32/samsrv/samsrv.h | 12 +- reactos/dll/win32/samsrv/setup.c | 97 +++++- reactos/include/ddk/ntsam.h | 53 +++ reactos/include/reactos/idl/sam.idl | 4 +- 8 files changed, 847 insertions(+), 43 deletions(-) diff --git a/reactos/dll/win32/samlib/samlib.c b/reactos/dll/win32/samlib/samlib.c index bb686508863..31c0f837b3e 100644 --- a/reactos/dll/win32/samlib/samlib.c +++ b/reactos/dll/win32/samlib/samlib.c @@ -103,6 +103,31 @@ PSAMPR_SERVER_NAME_unbind(PSAMPR_SERVER_NAME pszSystemName, } +NTSTATUS +NTAPI +SamAddMemberToAlias(IN SAM_HANDLE AliasHandle, + IN PSID MemberId) +{ + NTSTATUS Status; + + TRACE("SamAddMemberToAlias(%p %p)\n", + AliasHandle, MemberId); + + RpcTryExcept + { + Status = SamrAddMemberToAlias((SAMPR_HANDLE)AliasHandle, + (PRPC_SID)MemberId); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; +} + + NTSTATUS NTAPI SamCloseHandle(IN SAM_HANDLE SamHandle) @@ -153,6 +178,37 @@ SamConnect(IN OUT PUNICODE_STRING ServerName, } +NTSTATUS +NTAPI +SamCreateAliasInDomain(IN SAM_HANDLE DomainHandle, + IN PUNICODE_STRING AccountName, + IN ACCESS_MASK DesiredAccess, + OUT PSAM_HANDLE AliasHandle, + OUT PULONG RelativeId) +{ + NTSTATUS Status; + + TRACE("SamCreateAliasInDomain(%p,%p,0x%08x,%p,%p)\n", + DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId); + + RpcTryExcept + { + Status = SamrCreateAliasInDomain((SAMPR_HANDLE)DomainHandle, + (PRPC_UNICODE_STRING)AccountName, + DesiredAccess, + (SAMPR_HANDLE *)AliasHandle, + RelativeId); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; +} + + NTSTATUS NTAPI SamCreateUserInDomain(IN SAM_HANDLE DomainHandle, @@ -184,11 +240,61 @@ SamCreateUserInDomain(IN SAM_HANDLE DomainHandle, } +NTSTATUS +NTAPI +SamEnumerateDomainsInSamServer(IN SAM_HANDLE ServerHandle, + IN OUT PSAM_ENUMERATE_HANDLE EnumerationContext, + OUT PVOID *Buffer, + IN ULONG PreferedMaximumLength, + OUT PULONG CountReturned) +{ + PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL; + NTSTATUS Status; + + TRACE("SamEnumerateDomainsInSamServer(%p,%p,%p,%lu,%p)\n", + ServerHandle, EnumerationContext, Buffer, PreferedMaximumLength, + CountReturned); + + if ((EnumerationContext == NULL) || + (Buffer == NULL) || + (CountReturned == NULL)) + return STATUS_INVALID_PARAMETER; + + *Buffer = NULL; + + RpcTryExcept + { + Status = SamrEnumerateDomainsInSamServer((SAMPR_HANDLE)ServerHandle, + EnumerationContext, + (PSAMPR_ENUMERATION_BUFFER *)&EnumBuffer, + PreferedMaximumLength, + CountReturned); + + if (EnumBuffer != NULL) + { + if (EnumBuffer->Buffer != NULL) + { + *Buffer = EnumBuffer->Buffer; + } + + midl_user_free(EnumBuffer); + } + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; +} + + NTSTATUS NTAPI SamFreeMemory(IN PVOID Buffer) { - if (Buffer!= NULL) + if (Buffer != NULL) midl_user_free(Buffer); return STATUS_SUCCESS; @@ -222,6 +328,35 @@ SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle, } +NTSTATUS +NTAPI +SamOpenAlias(IN SAM_HANDLE DomainHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG AliasId, + OUT PSAM_HANDLE AliasHandle) +{ + NTSTATUS Status; + + TRACE("SamOpenAlias(%p 0x%08x %lx %p)\n", + DomainHandle, DesiredAccess, AliasId, AliasHandle); + + RpcTryExcept + { + Status = SamrOpenAlias((SAMPR_HANDLE)DomainHandle, + DesiredAccess, + AliasId, + (SAMPR_HANDLE *)AliasHandle); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; +} + + NTSTATUS NTAPI SamOpenDomain(IN SAM_HANDLE ServerHandle, @@ -280,14 +415,57 @@ SamOpenUser(IN SAM_HANDLE DomainHandle, } +NTSTATUS +NTAPI +SamQueryInformationDomain(IN SAM_HANDLE DomainHandle, + IN DOMAIN_INFORMATION_CLASS DomainInformationClass, + OUT PVOID *Buffer) +{ + NTSTATUS Status; + + TRACE("SamQueryInformationDomain(%p %lu %p)\n", + DomainHandle, DomainInformationClass, Buffer); + + RpcTryExcept + { + Status = SamrQueryInformationDomain((SAMPR_HANDLE)DomainHandle, + DomainInformationClass, + (PSAMPR_DOMAIN_INFO_BUFFER *)Buffer); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; +} + + NTSTATUS NTAPI SamQueryInformationUser(IN SAM_HANDLE UserHandle, IN USER_INFORMATION_CLASS UserInformationClass, OUT PVOID *Buffer) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + + TRACE("SamQueryInformationUser(%p %lu %p)\n", + UserHandle, UserInformationClass, Buffer); + + RpcTryExcept + { + Status = SamrQueryInformationUser((SAMPR_HANDLE)UserHandle, + UserInformationClass, + (PSAMPR_USER_INFO_BUFFER *)Buffer); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; } @@ -349,6 +527,7 @@ NTSTATUS NTAPI SamShutdownSamServer(IN SAM_HANDLE ServerHandle) { + UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } diff --git a/reactos/dll/win32/samlib/samlib.spec b/reactos/dll/win32/samlib/samlib.spec index 004e7afd0e8..18b0ebf25eb 100644 --- a/reactos/dll/win32/samlib/samlib.spec +++ b/reactos/dll/win32/samlib/samlib.spec @@ -1,4 +1,4 @@ -@ stub SamAddMemberToAlias +@ stdcall SamAddMemberToAlias(ptr ptr) @ stub SamAddMemberToGroup @ stub SamAddMultipleMembersToAlias @ stub SamChangePasswordUser2 @@ -7,7 +7,7 @@ @ stdcall SamCloseHandle(ptr) @ stdcall SamConnect(ptr ptr long ptr) @ stub SamConnectWithCreds -@ stub SamCreateAliasInDomain +@ stdcall SamCreateAliasInDomain(ptr ptr long ptr ptr) @ stub SamCreateGroupInDomain @ stub SamCreateUser2InDomain @ stdcall SamCreateUserInDomain(ptr ptr long ptr ptr) @@ -15,7 +15,7 @@ @ stub SamDeleteGroup @ stub SamDeleteUser @ stub SamEnumerateAliasesInDomain -@ stub SamEnumerateDomainsInSamServer +@ stdcall SamEnumerateDomainsInSamServer(ptr ptr ptr long ptr) @ stub SamEnumerateGroupsInDomain @ stub SamEnumerateUsersInDomain @ stdcall SamFreeMemory(ptr) @@ -28,13 +28,13 @@ @ stdcall SamLookupDomainInSamServer(ptr ptr ptr) @ stub SamLookupIdsInDomain @ stub SamLookupNamesInDomain -@ stub SamOpenAlias +@ stdcall SamOpenAlias(ptr long long ptr) @ stdcall SamOpenDomain(ptr long ptr ptr) @ stub SamOpenGroup @ stdcall SamOpenUser(ptr long long ptr) @ stub SamQueryDisplayInformation @ stub SamQueryInformationAlias -@ stub SamQueryInformationDomain +@ stdcall SamQueryInformationDomain(ptr long ptr) @ stub SamQueryInformationGroup @ stdcall SamQueryInformationUser(ptr long ptr) @ stub SamQuerySecurityObject diff --git a/reactos/dll/win32/samsrv/registry.c b/reactos/dll/win32/samsrv/registry.c index 28e6bb00792..7fcd021447b 100644 --- a/reactos/dll/win32/samsrv/registry.c +++ b/reactos/dll/win32/samsrv/registry.c @@ -16,7 +16,42 @@ WINE_DEFAULT_DEBUG_CHANNEL(samsrv); /* FUNCTIONS ***************************************************************/ NTSTATUS -NTAPI +SampRegCloseKey(IN HANDLE KeyHandle) +{ + return NtClose(KeyHandle); +} + + +NTSTATUS +SampRegCreateKey(IN HANDLE ParentKeyHandle, + IN LPCWSTR KeyName, + IN ACCESS_MASK DesiredAccess, + OUT HANDLE KeyHandle) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING Name; + ULONG Disposition; + + RtlInitUnicodeString(&Name, KeyName); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + ParentKeyHandle, + NULL); + + /* Create the key */ + return ZwCreateKey(KeyHandle, + DesiredAccess, + &ObjectAttributes, + 0, + NULL, + 0, + &Disposition); +} + + +NTSTATUS SampRegEnumerateSubKey(IN HANDLE KeyHandle, IN ULONG Index, IN ULONG Length, @@ -74,7 +109,6 @@ SampRegEnumerateSubKey(IN HANDLE KeyHandle, NTSTATUS -NTAPI SampRegOpenKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName, IN ACCESS_MASK DesiredAccess, @@ -171,5 +205,8 @@ SampRegQueryValue(HANDLE KeyHandle, /* Free the memory and return status */ RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo); + if ((Data == NULL) && (Status == STATUS_BUFFER_OVERFLOW)) + Status = STATUS_SUCCESS; + return Status; } diff --git a/reactos/dll/win32/samsrv/samrpc.c b/reactos/dll/win32/samsrv/samrpc.c index f01d05de8dc..bdfbbbf2389 100644 --- a/reactos/dll/win32/samsrv/samrpc.c +++ b/reactos/dll/win32/samsrv/samrpc.c @@ -269,11 +269,201 @@ NTAPI SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle, IN OUT unsigned long *EnumerationContext, OUT PSAMPR_ENUMERATION_BUFFER *Buffer, - IN unsigned long PreferedMaximumLength, - OUT unsigned long *CountReturned) + IN ULONG PreferedMaximumLength, + OUT PULONG CountReturned) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT ServerObject; + WCHAR DomainKeyName[64]; + HANDLE DomainsKeyHandle; + HANDLE DomainKeyHandle; + ULONG EnumIndex; + ULONG EnumCount; + ULONG RequiredLength; + ULONG DataLength; + ULONG i; + PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL; + NTSTATUS Status; + + TRACE("SamrEnumerateDomainsInSamServer(%p %p %p %lu %p)\n", + ServerHandle, EnumerationContext, Buffer, PreferedMaximumLength, + CountReturned); + + /* Validate the server handle */ + Status = SampValidateDbObject(ServerHandle, + SamDbServerObject, + SAM_SERVER_ENUMERATE_DOMAINS, + &ServerObject); + if (!NT_SUCCESS(Status)) + return Status; + + Status = SampRegOpenKey(ServerObject->KeyHandle, + L"Domains", + KEY_READ, + &DomainsKeyHandle); + if (!NT_SUCCESS(Status)) + return Status; + + EnumIndex = *EnumerationContext; + EnumCount = 0; + RequiredLength = 0; + + while (TRUE) + { + Status = SampRegEnumerateSubKey(DomainsKeyHandle, + EnumIndex, + 64 * sizeof(WCHAR), + DomainKeyName); + if (!NT_SUCCESS(Status)) + break; + + TRACE("EnumIndex: %lu\n", EnumIndex); + TRACE("Domain key name: %S\n", DomainKeyName); + + Status = SampRegOpenKey(DomainsKeyHandle, + DomainKeyName, + KEY_READ, + &DomainKeyHandle); + TRACE("SampRegOpenKey returned %08lX\n", Status); + if (NT_SUCCESS(Status)) + { + DataLength = 0; + Status = SampRegQueryValue(DomainKeyHandle, + L"Name", + NULL, + NULL, + &DataLength); + TRACE("SampRegQueryValue returned %08lX\n", Status); + if (NT_SUCCESS(Status)) + { + TRACE("Data length: %lu\n", DataLength); + + if ((RequiredLength + DataLength + sizeof(UNICODE_STRING)) > PreferedMaximumLength) + break; + + RequiredLength += (DataLength + sizeof(UNICODE_STRING)); + EnumCount++; + } + + NtClose(DomainKeyHandle); + } + + EnumIndex++; + } + + TRACE("EnumCount: %lu\n", EnumCount); + TRACE("RequiredLength: %lu\n", RequiredLength); + + EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER)); + if (EnumBuffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + EnumBuffer->EntriesRead = EnumCount; + EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION)); + if (EnumBuffer->Buffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + EnumIndex = *EnumerationContext; + for (i = 0; i < EnumCount; i++, EnumIndex++) + { + Status = SampRegEnumerateSubKey(DomainsKeyHandle, + EnumIndex, + 64 * sizeof(WCHAR), + DomainKeyName); + if (!NT_SUCCESS(Status)) + break; + + TRACE("EnumIndex: %lu\n", EnumIndex); + TRACE("Domain key name: %S\n", DomainKeyName); + + Status = SampRegOpenKey(DomainsKeyHandle, + DomainKeyName, + KEY_READ, + &DomainKeyHandle); + TRACE("SampRegOpenKey returned %08lX\n", Status); + if (NT_SUCCESS(Status)) + { + DataLength = 0; + Status = SampRegQueryValue(DomainKeyHandle, + L"Name", + NULL, + NULL, + &DataLength); + TRACE("SampRegQueryValue returned %08lX\n", Status); + if (NT_SUCCESS(Status)) + { + EnumBuffer->Buffer[i].RelativeId = 0; + EnumBuffer->Buffer[i].Name.Length = (USHORT)DataLength - sizeof(WCHAR); + EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)DataLength; + EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(DataLength); + if (EnumBuffer->Buffer[i].Name.Buffer == NULL) + { + NtClose(DomainKeyHandle); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + Status = SampRegQueryValue(DomainKeyHandle, + L"Name", + NULL, + EnumBuffer->Buffer[i].Name.Buffer, + &DataLength); + TRACE("SampRegQueryValue returned %08lX\n", Status); + if (NT_SUCCESS(Status)) + { + TRACE("Domain name: %S\n", EnumBuffer->Buffer[i].Name.Buffer); + } + } + + NtClose(DomainKeyHandle); + + if (!NT_SUCCESS(Status)) + goto done; + } + } + + if (NT_SUCCESS(Status)) + { + *EnumerationContext += EnumCount; + *Buffer = EnumBuffer; + *CountReturned = EnumCount; + } + +done: + if (!NT_SUCCESS(Status)) + { + *EnumerationContext = 0; + *Buffer = NULL; + *CountReturned = 0; + + if (EnumBuffer != NULL) + { + if (EnumBuffer->Buffer != NULL) + { + if (EnumBuffer->EntriesRead != 0) + { + for (i = 0; i < EnumBuffer->EntriesRead; i++) + { + if (EnumBuffer->Buffer[i].Name.Buffer != NULL) + midl_user_free(EnumBuffer->Buffer[i].Name.Buffer); + } + } + + midl_user_free(EnumBuffer->Buffer); + } + + midl_user_free(EnumBuffer); + } + } + + NtClose(DomainsKeyHandle); + + return Status; } /* Function 7 */ @@ -348,6 +538,64 @@ SamrOpenDomain(IN SAMPR_HANDLE ServerHandle, return Status; } + +static NTSTATUS +SampQueryDomainName(PSAM_DB_OBJECT DomainObject, + PSAMPR_DOMAIN_INFO_BUFFER *Buffer) +{ + PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; + ULONG Length = 0; + NTSTATUS Status; + + *Buffer = NULL; + + InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); + if (InfoBuffer == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + Status = SampGetObjectAttribute(DomainObject, + L"Name", + NULL, + NULL, + &Length); + if (!NT_SUCCESS(Status)) + goto done; + + InfoBuffer->Name.DomainName.Length = Length - sizeof(WCHAR); + InfoBuffer->Name.DomainName.MaximumLength = Length; + InfoBuffer->Name.DomainName.Buffer = midl_user_allocate(Length); + if (InfoBuffer->Name.DomainName.Buffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + Status = SampGetObjectAttribute(DomainObject, + L"Name", + NULL, + (PVOID)InfoBuffer->Name.DomainName.Buffer, + &Length); + if (!NT_SUCCESS(Status)) + goto done; + + *Buffer = InfoBuffer; + +done: + if (!NT_SUCCESS(Status)) + { + if (InfoBuffer != NULL) + { + if (InfoBuffer->Name.DomainName.Buffer != NULL) + midl_user_free(InfoBuffer->Name.DomainName.Buffer); + + midl_user_free(InfoBuffer); + } + } + + return Status; +} + + /* Function 8 */ NTSTATUS NTAPI @@ -355,8 +603,32 @@ SamrQueryInformationDomain(IN SAMPR_HANDLE DomainHandle, IN DOMAIN_INFORMATION_CLASS DomainInformationClass, OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT DomainObject; + NTSTATUS Status; + + TRACE("SamrQueryInformationDomain(%p %lu %p)\n", + DomainHandle, DomainInformationClass, Buffer); + + /* Validate the server handle */ + Status = SampValidateDbObject(DomainHandle, + SamDbDomainObject, + DOMAIN_READ_OTHER_PARAMETERS, + &DomainObject); + if (!NT_SUCCESS(Status)) + return Status; + + switch (DomainInformationClass) + { + case DomainNameInformation: + Status = SampQueryDomainName(DomainObject, + Buffer); + break; + + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + return Status; } static NTSTATUS @@ -399,7 +671,7 @@ SamrSetInformationDomain(IN SAMPR_HANDLE DomainHandle, { case DomainNameInformation: Status = SampSetDomainName(DomainObject, - (PSAMPR_DOMAIN_NAME_INFORMATION)DomainInformation); + &DomainInformation->Name); break; default: @@ -579,8 +851,116 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle, OUT SAMPR_HANDLE *AliasHandle, OUT unsigned long *RelativeId) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT DomainObject; + PSAM_DB_OBJECT AliasObject; + ULONG ulSize; + ULONG ulRid; + WCHAR szRid[9]; + BOOL bAliasExists = FALSE; + NTSTATUS Status; + + TRACE("SamrCreateAliasInDomain(%p %p %lx %p %p)\n", + DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId); + + /* Validate the domain handle */ + Status = SampValidateDbObject(DomainHandle, + SamDbDomainObject, + DOMAIN_CREATE_ALIAS, + &DomainObject); + if (!NT_SUCCESS(Status)) + { + TRACE("failed with status 0x%08lx\n", Status); + return Status; + } + + /* Get the NextRID attribute */ + ulSize = sizeof(ULONG); + Status = SampGetObjectAttribute(DomainObject, + L"NextRID", + NULL, + (LPVOID)&ulRid, + &ulSize); + if (!NT_SUCCESS(Status)) + ulRid = DOMAIN_USER_RID_MAX + 1; + + TRACE("RID: %lx\n", ulRid); + + /* Convert the RID into a string (hex) */ + swprintf(szRid, L"%08lX", ulRid); + + /* Check whether the user name is already in use */ + Status = SampCheckDbObjectNameAlias(DomainObject, + L"Aliases", + AccountName->Buffer, + &bAliasExists); + if (!NT_SUCCESS(Status)) + { + TRACE("failed with status 0x%08lx\n", Status); + return Status; + } + + if (bAliasExists) + { + TRACE("The alias account %S already exists!\n", AccountName->Buffer); + return STATUS_ALIAS_EXISTS; + } + + /* Create the user object */ + Status = SampCreateDbObject(DomainObject, + L"Aliases", + szRid, + SamDbAliasObject, + DesiredAccess, + &AliasObject); + 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"Aliases", + AccountName->Buffer, + ulRid); + if (!NT_SUCCESS(Status)) + { + TRACE("failed with status 0x%08lx\n", Status); + return Status; + } + + /* Set the name attribute */ + Status = SampSetObjectAttribute(AliasObject, + L"Name", + REG_SZ, + (LPVOID)AccountName->Buffer, + AccountName->MaximumLength); + if (!NT_SUCCESS(Status)) + { + TRACE("failed with status 0x%08lx\n", Status); + return Status; + } + + /* FIXME: Set default alias attributes */ + + if (NT_SUCCESS(Status)) + { + *AliasHandle = (SAMPR_HANDLE)AliasObject; + *RelativeId = ulRid; + } + + /* Increment the NextRID attribute */ + ulRid++; + ulSize = sizeof(ULONG); + SampSetObjectAttribute(DomainObject, + L"NextRID", + REG_DWORD, + (LPVOID)&ulRid, + ulSize); + + TRACE("returns with status 0x%08lx\n", Status); + + return Status; } /* Function 15 */ @@ -723,11 +1103,47 @@ NTSTATUS NTAPI SamrOpenAlias(IN SAMPR_HANDLE DomainHandle, IN ACCESS_MASK DesiredAccess, - IN unsigned long AliasId, + IN ULONG AliasId, OUT SAMPR_HANDLE *AliasHandle) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT DomainObject; + PSAM_DB_OBJECT AliasObject; + WCHAR szRid[9]; + NTSTATUS Status; + + TRACE("SamrOpenAlias(%p %lx %lx %p)\n", + DomainHandle, DesiredAccess, AliasId, AliasHandle); + + /* 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", AliasId); + + /* Create the alias object */ + Status = SampOpenDbObject(DomainObject, + L"Aliases", + szRid, + SamDbAliasObject, + DesiredAccess, + &AliasObject); + if (!NT_SUCCESS(Status)) + { + TRACE("failed with status 0x%08lx\n", Status); + return Status; + } + + *AliasHandle = (SAMPR_HANDLE)AliasObject; + + return STATUS_SUCCESS; } /* Function 28 */ @@ -767,8 +1183,52 @@ NTAPI SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle, IN PRPC_SID MemberId) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PSAM_DB_OBJECT AliasObject; + LPWSTR MemberIdString = NULL; + HANDLE MembersKeyHandle = NULL; + NTSTATUS Status; + + TRACE("SamrAddMemberToAlias(%p %p)\n", + AliasHandle, MemberId); + + /* Validate the domain handle */ + Status = SampValidateDbObject(AliasHandle, + SamDbAliasObject, + ALIAS_ADD_MEMBER, + &AliasObject); + if (!NT_SUCCESS(Status)) + { + TRACE("failed with status 0x%08lx\n", Status); + return Status; + } + + ConvertSidToStringSidW(MemberId, &MemberIdString); + TRACE("Member SID: %S\n", MemberIdString); + + Status = SampRegCreateKey(AliasObject->KeyHandle, + L"Members", + KEY_WRITE, + &MembersKeyHandle); + if (!NT_SUCCESS(Status)) + { + TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status); + goto done; + } + + Status = SampRegSetValue(MembersKeyHandle, + MemberIdString, + REG_BINARY, + NULL, + 0); + +done: + if (MembersKeyHandle != NULL) + SampRegCloseKey(MembersKeyHandle); + + if (MemberIdString != NULL) + LocalFree(MemberIdString); + + return Status; } /* Function 32 */ diff --git a/reactos/dll/win32/samsrv/samsrv.h b/reactos/dll/win32/samsrv/samsrv.h index 1b0def3e349..e8628c963ed 100644 --- a/reactos/dll/win32/samsrv/samsrv.h +++ b/reactos/dll/win32/samsrv/samsrv.h @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -105,14 +106,21 @@ SampGetObjectAttribute(PSAM_DB_OBJECT DbObject, /* registry.h */ NTSTATUS -NTAPI +SampRegCloseKey(IN HANDLE KeyHandle); + +NTSTATUS +SampRegCreateKey(IN HANDLE ParentKeyHandle, + IN LPCWSTR KeyName, + IN ACCESS_MASK DesiredAccess, + OUT HANDLE KeyHandle); + +NTSTATUS SampRegEnumerateSubKey(IN HANDLE KeyHandle, IN ULONG Index, IN ULONG Length, OUT LPWSTR Buffer); NTSTATUS -NTAPI SampRegOpenKey(IN HANDLE ParentKeyHandle, IN LPCWSTR KeyName, IN ACCESS_MASK DesiredAccess, diff --git a/reactos/dll/win32/samsrv/setup.c b/reactos/dll/win32/samsrv/setup.c index ec46a032daa..cf9ec290683 100644 --- a/reactos/dll/win32/samsrv/setup.c +++ b/reactos/dll/win32/samsrv/setup.c @@ -59,35 +59,87 @@ SampIsSetupRunning(VOID) static BOOL -SampCreateUserAccount(HKEY hDomainKey, - LPCWSTR lpAccountName, - ULONG ulRelativeId) +SampCreateAliasAccount(HKEY hDomainKey, + LPCWSTR lpAccountName, + ULONG ulRelativeId) { DWORD dwDisposition; - WCHAR szUserKeyName[32]; - HKEY hUserKey = NULL; + WCHAR szAccountKeyName[32]; + HKEY hAccountKey = NULL; HKEY hNamesKey = NULL; - swprintf(szUserKeyName, L"Users\\%08lX", ulRelativeId); + swprintf(szAccountKeyName, L"Aliases\\%08lX", ulRelativeId); if (!RegCreateKeyExW(hDomainKey, - szUserKeyName, + szAccountKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, - &hUserKey, + &hAccountKey, &dwDisposition)) { - RegSetValueEx(hUserKey, + RegSetValueEx(hAccountKey, L"Name", 0, REG_SZ, (LPVOID)lpAccountName, (wcslen(lpAccountName) + 1) * sizeof(WCHAR)); - RegCloseKey(hUserKey); + RegCloseKey(hAccountKey); + } + + if (!RegOpenKeyExW(hDomainKey, + L"Aliases\\Names", + 0, + KEY_ALL_ACCESS, + &hNamesKey)) + { + RegSetValueEx(hNamesKey, + lpAccountName, + 0, + REG_DWORD, + (LPVOID)&ulRelativeId, + sizeof(ULONG)); + + RegCloseKey(hNamesKey); + } + + return TRUE; +} + + +static BOOL +SampCreateUserAccount(HKEY hDomainKey, + LPCWSTR lpAccountName, + ULONG ulRelativeId) +{ + DWORD dwDisposition; + WCHAR szAccountKeyName[32]; + HKEY hAccountKey = NULL; + HKEY hNamesKey = NULL; + + swprintf(szAccountKeyName, L"Users\\%08lX", ulRelativeId); + + if (!RegCreateKeyExW(hDomainKey, + szAccountKeyName, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hAccountKey, + &dwDisposition)) + { + RegSetValueEx(hAccountKey, + L"Name", + 0, + REG_SZ, + (LPVOID)lpAccountName, + (wcslen(lpAccountName) + 1) * sizeof(WCHAR)); + + RegCloseKey(hAccountKey); } if (!RegOpenKeyExW(hDomainKey, @@ -119,7 +171,7 @@ SampCreateDomain(IN HKEY hDomainsKey, { DWORD dwDisposition; HKEY hDomainKey = NULL; - HKEY hAliasKey = NULL; + HKEY hAliasesKey = NULL; HKEY hGroupsKey = NULL; HKEY hUsersKey = NULL; HKEY hNamesKey = NULL; @@ -157,16 +209,16 @@ SampCreateDomain(IN HKEY hDomainsKey, /* Create the Alias container */ if (!RegCreateKeyExW(hDomainKey, - L"Alias", + L"Aliases", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, - &hAliasKey, + &hAliasesKey, &dwDisposition)) { - if (!RegCreateKeyExW(hAliasKey, + if (!RegCreateKeyExW(hAliasesKey, L"Names", 0, NULL, @@ -177,7 +229,7 @@ SampCreateDomain(IN HKEY hDomainsKey, &dwDisposition)) RegCloseKey(hNamesKey); - RegCloseKey(hAliasKey); + RegCloseKey(hAliasesKey); } /* Create the Groups container */ @@ -344,6 +396,21 @@ SampInitializeSAM(VOID) pBuiltinSid, &hDomainKey)) { + SampCreateAliasAccount(hDomainKey, + L"Administrators", + DOMAIN_ALIAS_RID_ADMINS); + + SampCreateAliasAccount(hDomainKey, + L"Users", + DOMAIN_ALIAS_RID_USERS); + + SampCreateAliasAccount(hDomainKey, + L"Guests", + DOMAIN_ALIAS_RID_GUESTS); + + SampCreateAliasAccount(hDomainKey, + L"Power Users", + DOMAIN_ALIAS_RID_POWER_USERS); RegCloseKey(hDomainKey); } diff --git a/reactos/include/ddk/ntsam.h b/reactos/include/ddk/ntsam.h index f2b1b4bdfde..90a5d5daa85 100644 --- a/reactos/include/ddk/ntsam.h +++ b/reactos/include/ddk/ntsam.h @@ -6,6 +6,12 @@ extern "C" { #endif +#define ALIAS_ADD_MEMBER 1 +#define ALIAS_REMOVE_MEMBER 2 +#define ALIAS_LIST_MEMBERS 4 +#define ALIAS_READ_INFORMATION 8 +#define ALIAS_WRITE_ACCOUNT 16 + #define DOMAIN_READ_PASSWORD_PARAMETERS 1 #define DOMAIN_WRITE_PASSWORD_PARAMS 2 #define DOMAIN_READ_OTHER_PARAMETERS 4 @@ -38,6 +44,19 @@ extern "C" { #define USER_WRITE_GROUP_INFORMATION 1024 typedef PVOID SAM_HANDLE, *PSAM_HANDLE; +typedef ULONG SAM_ENUMERATE_HANDLE, *PSAM_ENUMERATE_HANDLE; + +typedef struct _SAM_RID_ENUMERATION +{ + ULONG RelativeId; + UNICODE_STRING Name; +} SAM_RID_ENUMERATION, *PSAM_RID_ENUMERATION; + +typedef struct _SAM_SID_ENUMERATION +{ + PSID Sid; + UNICODE_STRING Name; +} SAM_SID_ENUMERATION, *PSAM_SID_ENUMERATION; typedef enum _DOMAIN_INFORMATION_CLASS { @@ -101,6 +120,11 @@ typedef struct _USER_SET_PASSWORD_INFORMATION } USER_SET_PASSWORD_INFORMATION, *PUSER_SET_PASSWORD_INFORMATION; +NTSTATUS +NTAPI +SamAddMemberToAlias(IN SAM_HANDLE AliasHandle, + IN PSID MemberId); + NTSTATUS NTAPI SamCloseHandle(IN SAM_HANDLE SamHandle); @@ -112,6 +136,14 @@ SamConnect(IN OUT PUNICODE_STRING ServerName, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes); +NTSTATUS +NTAPI +SamCreateAliasInDomain(IN SAM_HANDLE DomainHandle, + IN PUNICODE_STRING AccountName, + IN ACCESS_MASK DesiredAccess, + OUT PSAM_HANDLE AliasHandle, + OUT PULONG RelativeId); + NTSTATUS NTAPI SamCreateUserInDomain(IN SAM_HANDLE DomainHandle, @@ -120,6 +152,14 @@ SamCreateUserInDomain(IN SAM_HANDLE DomainHandle, OUT PSAM_HANDLE UserHandle, OUT PULONG RelativeId); +NTSTATUS +NTAPI +SamEnumerateDomainsInSamServer(IN SAM_HANDLE ServerHandle, + IN OUT PSAM_ENUMERATE_HANDLE EnumerationContext, + OUT PVOID *Buffer, + IN ULONG PreferedMaximumLength, + OUT PULONG CountReturned); + NTSTATUS NTAPI SamFreeMemory(IN PVOID Buffer); @@ -130,6 +170,13 @@ SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle, IN PUNICODE_STRING Name, OUT PSID *DomainId); +NTSTATUS +NTAPI +SamOpenAlias(IN SAM_HANDLE DomainHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG AliasId, + OUT PSAM_HANDLE AliasHandle); + NTSTATUS NTAPI SamOpenDomain(IN SAM_HANDLE ServerHandle, @@ -144,6 +191,12 @@ SamOpenUser(IN SAM_HANDLE DomainHandle, IN ULONG UserId, OUT PSAM_HANDLE UserHandle); +NTSTATUS +NTAPI +SamQueryInformationDomain(IN SAM_HANDLE DomainHandle, + IN DOMAIN_INFORMATION_CLASS DomainInformationClass, + OUT PVOID *Buffer); + NTSTATUS NTAPI SamQueryInformationUser(IN SAM_HANDLE UserHandle, diff --git a/reactos/include/reactos/idl/sam.idl b/reactos/include/reactos/idl/sam.idl index 313ec8adccd..b31514d3a0f 100644 --- a/reactos/include/reactos/idl/sam.idl +++ b/reactos/include/reactos/idl/sam.idl @@ -1036,7 +1036,7 @@ interface samr SamrOpenAlias( [in] SAMPR_HANDLE DomainHandle, [in] ACCESS_MASK DesiredAccess, - [in] unsigned long AliasId, + [in] ULONG AliasId, [out] SAMPR_HANDLE *AliasHandle); /* Function 28 */ @@ -1088,7 +1088,7 @@ interface samr SamrOpenUser( [in] SAMPR_HANDLE DomainHandle, [in] ACCESS_MASK DesiredAccess, - [in] unsigned long UserId, + [in] ULONG UserId, [out] SAMPR_HANDLE *UserHandle); /* Function 35 */