mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
[SAMLIB][SAMSRV]
- Implement SamGetMembersInAlias and SamrGetMembersInAlias. - Add registry helper routines SampRegQueryKeyInfo, SampRegEnumerateValue and SampRegSetValue. - Remove unused SAM database code. - Store the name and members key (only for aliases and groups) in the database object. svn path=/trunk/; revision=56704
This commit is contained in:
parent
d36d231899
commit
c1fd93e9a2
7 changed files with 484 additions and 230 deletions
|
@ -301,6 +301,48 @@ SamFreeMemory(IN PVOID Buffer)
|
|||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
|
||||
OUT PSID **MemberIds,
|
||||
OUT PULONG MemberCount)
|
||||
{
|
||||
SAMPR_PSID_ARRAY_OUT SidArray;
|
||||
NTSTATUS Status;
|
||||
|
||||
TRACE("SamGetMembersInAlias(%p %p %p)\n",
|
||||
AliasHandle, MemberIds, MemberCount);
|
||||
|
||||
if ((MemberIds == NULL) ||
|
||||
(MemberCount == NULL))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
*MemberIds = NULL;
|
||||
*MemberCount = 0;
|
||||
|
||||
SidArray.Sids = NULL;
|
||||
|
||||
RpcTryExcept
|
||||
{
|
||||
Status = SamrGetMembersInAlias((SAMPR_HANDLE)AliasHandle,
|
||||
&SidArray);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
*MemberCount = SidArray.Count;
|
||||
*MemberIds = (PSID *)(SidArray.Sids);
|
||||
}
|
||||
|
||||
}
|
||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = I_RpcMapWin32Status(RpcExceptionCode());
|
||||
}
|
||||
RpcEndExcept;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
@ stub SamGetCompatibilityMode
|
||||
@ stub SamGetDisplayEnumerationIndex
|
||||
@ stub SamGetGroupsForUser
|
||||
@ stub SamGetMembersInAlias
|
||||
@ stdcall SamGetMembersInAlias(ptr ptr ptr)
|
||||
@ stub SamGetMembersInGroup
|
||||
@ stdcall SamLookupDomainInSamServer(ptr ptr ptr)
|
||||
@ stub SamLookupIdsInDomain
|
||||
|
|
|
@ -44,210 +44,6 @@ SampOpenSamKey(VOID)
|
|||
return Status;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static BOOLEAN
|
||||
LsapIsDatabaseInstalled(VOID)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyName;
|
||||
HANDLE KeyHandle;
|
||||
NTSTATUS Status;
|
||||
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
L"Policy");
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
SecurityKeyHandle,
|
||||
NULL);
|
||||
|
||||
Status = RtlpNtOpenKey(&KeyHandle,
|
||||
KEY_READ,
|
||||
&ObjectAttributes,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return FALSE;
|
||||
|
||||
NtClose(KeyHandle);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
LsapCreateDatabaseKeys(VOID)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyName;
|
||||
HANDLE PolicyKeyHandle = NULL;
|
||||
HANDLE AccountsKeyHandle = NULL;
|
||||
HANDLE DomainsKeyHandle = NULL;
|
||||
HANDLE SecretsKeyHandle = NULL;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
TRACE("LsapInstallDatabase()\n");
|
||||
|
||||
/* Create the 'Policy' key */
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
L"Policy");
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
SecurityKeyHandle,
|
||||
NULL);
|
||||
|
||||
Status = NtCreateKey(&PolicyKeyHandle,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("Failed to create the 'Policy' key (Status: 0x%08lx)\n", Status);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
/* Create the 'Accounts' key */
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
L"Accounts");
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
PolicyKeyHandle,
|
||||
NULL);
|
||||
|
||||
Status = NtCreateKey(&AccountsKeyHandle,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("Failed to create the 'Accounts' key (Status: 0x%08lx)\n", Status);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
/* Create the 'Domains' key */
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
L"Domains");
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
PolicyKeyHandle,
|
||||
NULL);
|
||||
|
||||
Status = NtCreateKey(&DomainsKeyHandle,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("Failed to create the 'Domains' key (Status: 0x%08lx)\n", Status);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
/* Create the 'Secrets' key */
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
L"Secrets");
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
PolicyKeyHandle,
|
||||
NULL);
|
||||
|
||||
Status = NtCreateKey(&SecretsKeyHandle,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("Failed to create the 'Secrets' key (Status: 0x%08lx)\n", Status);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Done:
|
||||
if (SecretsKeyHandle != NULL)
|
||||
NtClose(SecretsKeyHandle);
|
||||
|
||||
if (DomainsKeyHandle != NULL)
|
||||
NtClose(DomainsKeyHandle);
|
||||
|
||||
if (AccountsKeyHandle != NULL)
|
||||
NtClose(AccountsKeyHandle);
|
||||
|
||||
if (PolicyKeyHandle != NULL)
|
||||
NtClose(PolicyKeyHandle);
|
||||
|
||||
TRACE("LsapInstallDatabase() done (Status: 0x%08lx)\n", Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
LsapCreateDatabaseObjects(VOID)
|
||||
{
|
||||
PLSA_DB_OBJECT PolicyObject;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Open the 'Policy' object */
|
||||
Status = LsapOpenDbObject(NULL,
|
||||
L"Policy",
|
||||
LsaDbPolicyObject,
|
||||
0,
|
||||
&PolicyObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
LsapSetObjectAttribute(PolicyObject,
|
||||
L"PolPrDmN",
|
||||
NULL,
|
||||
0);
|
||||
|
||||
LsapSetObjectAttribute(PolicyObject,
|
||||
L"PolPrDmS",
|
||||
NULL,
|
||||
0);
|
||||
|
||||
LsapSetObjectAttribute(PolicyObject,
|
||||
L"PolAcDmN",
|
||||
NULL,
|
||||
0);
|
||||
|
||||
LsapSetObjectAttribute(PolicyObject,
|
||||
L"PolAcDmS",
|
||||
NULL,
|
||||
0);
|
||||
|
||||
/* Close the 'Policy' object */
|
||||
LsapCloseDbObject(PolicyObject);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
LsapUpdateDatabase(VOID)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
NTSTATUS
|
||||
SampInitDatabase(VOID)
|
||||
|
@ -310,7 +106,8 @@ SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject,
|
|||
UNICODE_STRING KeyName;
|
||||
HANDLE ParentKeyHandle;
|
||||
HANDLE ContainerKeyHandle = NULL;
|
||||
HANDLE ObjectKeyHandle;
|
||||
HANDLE ObjectKeyHandle = NULL;
|
||||
HANDLE MembersKeyHandle = NULL;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (DbObject == NULL)
|
||||
|
@ -359,6 +156,28 @@ SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject,
|
|||
0,
|
||||
NULL);
|
||||
|
||||
if ((ObjectType == SamDbAliasObject) ||
|
||||
(ObjectType == SamDbGroupObject))
|
||||
{
|
||||
/* Open the object key */
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
L"Members");
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
|
||||
ContainerKeyHandle,
|
||||
NULL);
|
||||
|
||||
Status = NtCreateKey(&MembersKeyHandle,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
NtClose(ContainerKeyHandle);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -395,15 +214,32 @@ SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject,
|
|||
sizeof(SAM_DB_OBJECT));
|
||||
if (NewObject == NULL)
|
||||
{
|
||||
if (MembersKeyHandle != NULL)
|
||||
NtClose(MembersKeyHandle);
|
||||
NtClose(ObjectKeyHandle);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
NewObject->Name = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
(wcslen(ObjectName) + 1) * sizeof(WCHAR));
|
||||
if (NewObject == NULL)
|
||||
{
|
||||
if (MembersKeyHandle != NULL)
|
||||
NtClose(MembersKeyHandle);
|
||||
NtClose(ObjectKeyHandle);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
wcscpy(NewObject->Name, ObjectName);
|
||||
|
||||
NewObject->Signature = SAMP_DB_SIGNATURE;
|
||||
NewObject->RefCount = 1;
|
||||
NewObject->ObjectType = ObjectType;
|
||||
NewObject->Access = DesiredAccess;
|
||||
NewObject->KeyHandle = ObjectKeyHandle;
|
||||
NewObject->MembersKeyHandle = MembersKeyHandle;
|
||||
NewObject->ParentObject = ParentObject;
|
||||
|
||||
if (ParentObject != NULL)
|
||||
|
@ -428,7 +264,8 @@ SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject,
|
|||
UNICODE_STRING KeyName;
|
||||
HANDLE ParentKeyHandle;
|
||||
HANDLE ContainerKeyHandle = NULL;
|
||||
HANDLE ObjectKeyHandle;
|
||||
HANDLE ObjectKeyHandle = NULL;
|
||||
HANDLE MembersKeyHandle = NULL;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (DbObject == NULL)
|
||||
|
@ -473,6 +310,28 @@ SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject,
|
|||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
|
||||
if ((ObjectType == SamDbAliasObject) ||
|
||||
(ObjectType == SamDbGroupObject))
|
||||
{
|
||||
/* Open the object key */
|
||||
RtlInitUnicodeString(&KeyName,
|
||||
L"Members");
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
|
||||
ContainerKeyHandle,
|
||||
NULL);
|
||||
|
||||
Status = NtCreateKey(&MembersKeyHandle,
|
||||
KEY_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
NtClose(ContainerKeyHandle);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -506,15 +365,31 @@ SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject,
|
|||
sizeof(SAM_DB_OBJECT));
|
||||
if (NewObject == NULL)
|
||||
{
|
||||
if (MembersKeyHandle != NULL)
|
||||
NtClose(MembersKeyHandle);
|
||||
NtClose(ObjectKeyHandle);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
NewObject->Name = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
(wcslen(ObjectName) + 1) * sizeof(WCHAR));
|
||||
if (NewObject == NULL)
|
||||
{
|
||||
if (MembersKeyHandle != NULL)
|
||||
NtClose(MembersKeyHandle);
|
||||
NtClose(ObjectKeyHandle);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, NewObject);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
wcscpy(NewObject->Name, ObjectName);
|
||||
NewObject->Signature = SAMP_DB_SIGNATURE;
|
||||
NewObject->RefCount = 1;
|
||||
NewObject->ObjectType = ObjectType;
|
||||
NewObject->Access = DesiredAccess;
|
||||
NewObject->KeyHandle = ObjectKeyHandle;
|
||||
NewObject->MembersKeyHandle = MembersKeyHandle;
|
||||
NewObject->ParentObject = ParentObject;
|
||||
|
||||
if (ParentObject != NULL)
|
||||
|
@ -585,9 +460,15 @@ SampCloseDbObject(PSAM_DB_OBJECT DbObject)
|
|||
if (DbObject->KeyHandle != NULL)
|
||||
NtClose(DbObject->KeyHandle);
|
||||
|
||||
if (DbObject->MembersKeyHandle != NULL)
|
||||
NtClose(DbObject->MembersKeyHandle);
|
||||
|
||||
if (DbObject->ParentObject != NULL)
|
||||
ParentObject = DbObject->ParentObject;
|
||||
|
||||
if (DbObject->Name != NULL)
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject->Name);
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
|
||||
|
||||
if (ParentObject != NULL)
|
||||
|
|
|
@ -15,6 +15,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(samsrv);
|
|||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
IsStringType(ULONG Type)
|
||||
{
|
||||
return (Type == REG_SZ) || (Type == REG_EXPAND_SZ) || (Type == REG_MULTI_SZ);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
SampRegCloseKey(IN HANDLE KeyHandle)
|
||||
{
|
||||
|
@ -132,32 +140,148 @@ SampRegOpenKey(IN HANDLE ParentKeyHandle,
|
|||
|
||||
|
||||
NTSTATUS
|
||||
SampRegSetValue(HANDLE KeyHandle,
|
||||
LPWSTR ValueName,
|
||||
ULONG Type,
|
||||
LPVOID Data,
|
||||
ULONG DataLength)
|
||||
SampRegQueryKeyInfo(IN HANDLE KeyHandle,
|
||||
OUT PULONG SubKeyCount,
|
||||
OUT PULONG ValueCount)
|
||||
{
|
||||
UNICODE_STRING Name;
|
||||
KEY_FULL_INFORMATION FullInfoBuffer;
|
||||
ULONG Length;
|
||||
NTSTATUS Status;
|
||||
|
||||
RtlInitUnicodeString(&Name,
|
||||
ValueName);
|
||||
FullInfoBuffer.ClassLength = 0;
|
||||
FullInfoBuffer.ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
|
||||
|
||||
return ZwSetValueKey(KeyHandle,
|
||||
&Name,
|
||||
0,
|
||||
Type,
|
||||
Data,
|
||||
DataLength);
|
||||
Status = NtQueryKey(KeyHandle,
|
||||
KeyFullInformation,
|
||||
&FullInfoBuffer,
|
||||
sizeof(KEY_FULL_INFORMATION),
|
||||
&Length);
|
||||
TRACE("NtQueryKey() returned status 0x%08lX\n", Status);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
if (SubKeyCount != NULL)
|
||||
*SubKeyCount = FullInfoBuffer.SubKeys;
|
||||
|
||||
if (ValueCount != NULL)
|
||||
*ValueCount = FullInfoBuffer.Values;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
SampRegQueryValue(HANDLE KeyHandle,
|
||||
LPWSTR ValueName,
|
||||
PULONG Type OPTIONAL,
|
||||
LPVOID Data OPTIONAL,
|
||||
PULONG DataLength OPTIONAL)
|
||||
SampRegEnumerateValue(IN HANDLE KeyHandle,
|
||||
IN ULONG Index,
|
||||
OUT LPWSTR Name,
|
||||
IN OUT PULONG NameLength,
|
||||
OUT PULONG Type OPTIONAL,
|
||||
OUT PVOID Data OPTIONAL,
|
||||
IN OUT PULONG DataLength OPTIONAL)
|
||||
{
|
||||
PKEY_VALUE_FULL_INFORMATION ValueInfo = NULL;
|
||||
ULONG BufferLength = 0;
|
||||
ULONG ReturnedLength;
|
||||
NTSTATUS Status;
|
||||
|
||||
TRACE("Index: %lu\n", Index);
|
||||
|
||||
/* Calculate the required buffer length */
|
||||
BufferLength = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name);
|
||||
BufferLength += (MAX_PATH + 1) * sizeof(WCHAR);
|
||||
if (Data != NULL)
|
||||
BufferLength += *DataLength;
|
||||
|
||||
/* Allocate the value buffer */
|
||||
ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||
if (ValueInfo == NULL)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
/* Enumerate the value*/
|
||||
Status = ZwEnumerateValueKey(KeyHandle,
|
||||
Index,
|
||||
KeyValueFullInformation,
|
||||
ValueInfo,
|
||||
BufferLength,
|
||||
&ReturnedLength);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (Name != NULL)
|
||||
{
|
||||
/* Check if the name fits */
|
||||
if (ValueInfo->NameLength < (*NameLength * sizeof(WCHAR)))
|
||||
{
|
||||
/* Copy it */
|
||||
RtlMoveMemory(Name,
|
||||
ValueInfo->Name,
|
||||
ValueInfo->NameLength);
|
||||
|
||||
/* Terminate the string */
|
||||
Name[ValueInfo->NameLength / sizeof(WCHAR)] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we ran out of buffer space */
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (Data != NULL)
|
||||
{
|
||||
/* Check if the data fits */
|
||||
if (ValueInfo->DataLength <= *DataLength)
|
||||
{
|
||||
/* Copy it */
|
||||
RtlMoveMemory(Data,
|
||||
(PVOID)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset),
|
||||
ValueInfo->DataLength);
|
||||
|
||||
/* if the type is REG_SZ and data is not 0-terminated
|
||||
* and there is enough space in the buffer NT appends a \0 */
|
||||
if (IsStringType(ValueInfo->Type) &&
|
||||
ValueInfo->DataLength <= *DataLength - sizeof(WCHAR))
|
||||
{
|
||||
WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + ValueInfo->DataLength);
|
||||
if ((ptr > (WCHAR *)Data) && ptr[-1])
|
||||
*ptr = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
|
||||
{
|
||||
if (Type != NULL)
|
||||
*Type = ValueInfo->Type;
|
||||
|
||||
if (NameLength != NULL)
|
||||
*NameLength = ValueInfo->NameLength;
|
||||
|
||||
if (DataLength != NULL)
|
||||
*DataLength = ValueInfo->DataLength;
|
||||
}
|
||||
|
||||
/* Free the buffer and return status */
|
||||
if (ValueInfo)
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
SampRegQueryValue(IN HANDLE KeyHandle,
|
||||
IN LPWSTR ValueName,
|
||||
OUT PULONG Type OPTIONAL,
|
||||
OUT PVOID Data OPTIONAL,
|
||||
IN OUT PULONG DataLength OPTIONAL)
|
||||
{
|
||||
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
||||
UNICODE_STRING Name;
|
||||
|
@ -200,6 +324,16 @@ SampRegQueryValue(HANDLE KeyHandle,
|
|||
RtlMoveMemory(Data,
|
||||
ValueInfo->Data,
|
||||
ValueInfo->DataLength);
|
||||
|
||||
/* if the type is REG_SZ and data is not 0-terminated
|
||||
* and there is enough space in the buffer NT appends a \0 */
|
||||
if (IsStringType(ValueInfo->Type) &&
|
||||
ValueInfo->DataLength <= *DataLength - sizeof(WCHAR))
|
||||
{
|
||||
WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + ValueInfo->DataLength);
|
||||
if ((ptr > (WCHAR *)Data) && ptr[-1])
|
||||
*ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the memory and return status */
|
||||
|
@ -210,3 +344,24 @@ SampRegQueryValue(HANDLE KeyHandle,
|
|||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
SampRegSetValue(HANDLE KeyHandle,
|
||||
LPWSTR ValueName,
|
||||
ULONG Type,
|
||||
LPVOID Data,
|
||||
ULONG DataLength)
|
||||
{
|
||||
UNICODE_STRING Name;
|
||||
|
||||
RtlInitUnicodeString(&Name,
|
||||
ValueName);
|
||||
|
||||
return ZwSetValueKey(KeyHandle,
|
||||
&Name,
|
||||
0,
|
||||
Type,
|
||||
Data,
|
||||
DataLength);
|
||||
}
|
||||
|
|
|
@ -1186,6 +1186,8 @@ SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
|
|||
PSAM_DB_OBJECT AliasObject;
|
||||
LPWSTR MemberIdString = NULL;
|
||||
HANDLE MembersKeyHandle = NULL;
|
||||
HANDLE MemberKeyHandle = NULL;
|
||||
ULONG MemberIdLength;
|
||||
NTSTATUS Status;
|
||||
|
||||
TRACE("SamrAddMemberToAlias(%p %p)\n",
|
||||
|
@ -1205,6 +1207,8 @@ SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
|
|||
ConvertSidToStringSidW(MemberId, &MemberIdString);
|
||||
TRACE("Member SID: %S\n", MemberIdString);
|
||||
|
||||
MemberIdLength = RtlLengthSid(MemberId);
|
||||
|
||||
Status = SampRegCreateKey(AliasObject->KeyHandle,
|
||||
L"Members",
|
||||
KEY_WRITE,
|
||||
|
@ -1218,10 +1222,39 @@ SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
|
|||
Status = SampRegSetValue(MembersKeyHandle,
|
||||
MemberIdString,
|
||||
REG_BINARY,
|
||||
NULL,
|
||||
0);
|
||||
MemberId,
|
||||
MemberIdLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
Status = SampRegCreateKey(AliasObject->MembersKeyHandle,
|
||||
MemberIdString,
|
||||
KEY_WRITE,
|
||||
&MemberKeyHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
Status = SampRegSetValue(MemberKeyHandle,
|
||||
AliasObject->Name,
|
||||
REG_BINARY,
|
||||
MemberId,
|
||||
MemberIdLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
if (MemberKeyHandle != NULL)
|
||||
SampRegCloseKey(MemberKeyHandle);
|
||||
|
||||
if (MembersKeyHandle != NULL)
|
||||
SampRegCloseKey(MembersKeyHandle);
|
||||
|
||||
|
@ -1247,8 +1280,129 @@ NTAPI
|
|||
SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
|
||||
OUT PSAMPR_PSID_ARRAY_OUT Members)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
PSAM_DB_OBJECT AliasObject;
|
||||
HANDLE MembersKeyHandle = NULL;
|
||||
PSAMPR_SID_INFORMATION MemberArray = NULL;
|
||||
ULONG ValueCount = 0;
|
||||
ULONG DataLength;
|
||||
ULONG Index;
|
||||
NTSTATUS Status;
|
||||
|
||||
TRACE("SamrGetMembersInAlias(%p %p %p)\n",
|
||||
AliasHandle, Members);
|
||||
|
||||
/* Validate the alias handle */
|
||||
Status = SampValidateDbObject(AliasHandle,
|
||||
SamDbAliasObject,
|
||||
ALIAS_LIST_MEMBERS,
|
||||
&AliasObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("failed with status 0x%08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Open the members key of the alias objct */
|
||||
Status = SampRegOpenKey(AliasObject->KeyHandle,
|
||||
L"Members",
|
||||
KEY_READ,
|
||||
&MembersKeyHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("SampRegOpenKey failed with status 0x%08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get the number of members */
|
||||
Status = SampRegQueryKeyInfo(MembersKeyHandle,
|
||||
NULL,
|
||||
&ValueCount);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Allocate the member array */
|
||||
MemberArray = midl_user_allocate(ValueCount * sizeof(SAMPR_SID_INFORMATION));
|
||||
if (MemberArray == NULL)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Enumerate the members */
|
||||
Index = 0;
|
||||
while (TRUE)
|
||||
{
|
||||
/* Get the size of the next SID */
|
||||
DataLength = 0;
|
||||
Status = SampRegEnumerateValue(MembersKeyHandle,
|
||||
Index,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&DataLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (Status == STATUS_NO_MORE_ENTRIES)
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Allocate a buffer for the SID */
|
||||
MemberArray[Index].SidPointer = midl_user_allocate(DataLength);
|
||||
if (MemberArray[Index].SidPointer == NULL)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read the SID into the buffer */
|
||||
Status = SampRegEnumerateValue(MembersKeyHandle,
|
||||
Index,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(PVOID)MemberArray[Index].SidPointer,
|
||||
&DataLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
|
||||
Index++;
|
||||
}
|
||||
|
||||
/* Return the number of members and the member array */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Members->Count = ValueCount;
|
||||
Members->Sids = MemberArray;
|
||||
}
|
||||
|
||||
done:
|
||||
/* Clean up the members array and the SID buffers if something failed */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (MemberArray != NULL)
|
||||
{
|
||||
for (Index = 0; Index < ValueCount; Index++)
|
||||
{
|
||||
if (MemberArray[Index].SidPointer != NULL)
|
||||
midl_user_free(MemberArray[Index].SidPointer);
|
||||
}
|
||||
|
||||
midl_user_free(MemberArray);
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the members key */
|
||||
if (MembersKeyHandle != NULL)
|
||||
SampRegCloseKey(MembersKeyHandle);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Function 34 */
|
||||
|
|
|
@ -42,7 +42,9 @@ typedef struct _SAM_DB_OBJECT
|
|||
SAM_DB_OBJECT_TYPE ObjectType;
|
||||
ULONG RefCount;
|
||||
ACCESS_MASK Access;
|
||||
LPWSTR Name;
|
||||
HANDLE KeyHandle;
|
||||
HANDLE MembersKeyHandle; // only used by Aliases and Groups
|
||||
struct _SAM_DB_OBJECT *ParentObject;
|
||||
} SAM_DB_OBJECT, *PSAM_DB_OBJECT;
|
||||
|
||||
|
@ -126,6 +128,20 @@ SampRegOpenKey(IN HANDLE ParentKeyHandle,
|
|||
IN ACCESS_MASK DesiredAccess,
|
||||
OUT HANDLE KeyHandle);
|
||||
|
||||
NTSTATUS
|
||||
SampRegQueryKeyInfo(IN HANDLE KeyHandle,
|
||||
OUT PULONG SubKeyCount,
|
||||
OUT PULONG ValueCount);
|
||||
|
||||
NTSTATUS
|
||||
SampRegEnumerateValue(IN HANDLE KeyHandle,
|
||||
IN ULONG Index,
|
||||
OUT LPWSTR Name,
|
||||
IN OUT PULONG NameLength,
|
||||
OUT PULONG Type OPTIONAL,
|
||||
OUT PVOID Data OPTIONAL,
|
||||
IN OUT PULONG DataLength OPTIONAL);
|
||||
|
||||
NTSTATUS
|
||||
SampRegQueryValue(IN HANDLE KeyHandle,
|
||||
IN LPWSTR ValueName,
|
||||
|
|
|
@ -164,6 +164,12 @@ NTSTATUS
|
|||
NTAPI
|
||||
SamFreeMemory(IN PVOID Buffer);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
|
||||
OUT PSID **MemberIds,
|
||||
OUT PULONG MemberCount);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
|
||||
|
|
Loading…
Reference in a new issue