mirror of
https://github.com/reactos/reactos.git
synced 2025-05-23 19:14:48 +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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
|
SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
@ stub SamGetCompatibilityMode
|
@ stub SamGetCompatibilityMode
|
||||||
@ stub SamGetDisplayEnumerationIndex
|
@ stub SamGetDisplayEnumerationIndex
|
||||||
@ stub SamGetGroupsForUser
|
@ stub SamGetGroupsForUser
|
||||||
@ stub SamGetMembersInAlias
|
@ stdcall SamGetMembersInAlias(ptr ptr ptr)
|
||||||
@ stub SamGetMembersInGroup
|
@ stub SamGetMembersInGroup
|
||||||
@ stdcall SamLookupDomainInSamServer(ptr ptr ptr)
|
@ stdcall SamLookupDomainInSamServer(ptr ptr ptr)
|
||||||
@ stub SamLookupIdsInDomain
|
@ stub SamLookupIdsInDomain
|
||||||
|
|
|
@ -44,210 +44,6 @@ SampOpenSamKey(VOID)
|
||||||
return Status;
|
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
|
NTSTATUS
|
||||||
SampInitDatabase(VOID)
|
SampInitDatabase(VOID)
|
||||||
|
@ -310,7 +106,8 @@ SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject,
|
||||||
UNICODE_STRING KeyName;
|
UNICODE_STRING KeyName;
|
||||||
HANDLE ParentKeyHandle;
|
HANDLE ParentKeyHandle;
|
||||||
HANDLE ContainerKeyHandle = NULL;
|
HANDLE ContainerKeyHandle = NULL;
|
||||||
HANDLE ObjectKeyHandle;
|
HANDLE ObjectKeyHandle = NULL;
|
||||||
|
HANDLE MembersKeyHandle = NULL;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
if (DbObject == NULL)
|
if (DbObject == NULL)
|
||||||
|
@ -359,6 +156,28 @@ SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject,
|
||||||
0,
|
0,
|
||||||
NULL);
|
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);
|
NtClose(ContainerKeyHandle);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -395,15 +214,32 @@ SampCreateDbObject(IN PSAM_DB_OBJECT ParentObject,
|
||||||
sizeof(SAM_DB_OBJECT));
|
sizeof(SAM_DB_OBJECT));
|
||||||
if (NewObject == NULL)
|
if (NewObject == NULL)
|
||||||
{
|
{
|
||||||
|
if (MembersKeyHandle != NULL)
|
||||||
|
NtClose(MembersKeyHandle);
|
||||||
NtClose(ObjectKeyHandle);
|
NtClose(ObjectKeyHandle);
|
||||||
return STATUS_NO_MEMORY;
|
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->Signature = SAMP_DB_SIGNATURE;
|
||||||
NewObject->RefCount = 1;
|
NewObject->RefCount = 1;
|
||||||
NewObject->ObjectType = ObjectType;
|
NewObject->ObjectType = ObjectType;
|
||||||
NewObject->Access = DesiredAccess;
|
NewObject->Access = DesiredAccess;
|
||||||
NewObject->KeyHandle = ObjectKeyHandle;
|
NewObject->KeyHandle = ObjectKeyHandle;
|
||||||
|
NewObject->MembersKeyHandle = MembersKeyHandle;
|
||||||
NewObject->ParentObject = ParentObject;
|
NewObject->ParentObject = ParentObject;
|
||||||
|
|
||||||
if (ParentObject != NULL)
|
if (ParentObject != NULL)
|
||||||
|
@ -428,7 +264,8 @@ SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject,
|
||||||
UNICODE_STRING KeyName;
|
UNICODE_STRING KeyName;
|
||||||
HANDLE ParentKeyHandle;
|
HANDLE ParentKeyHandle;
|
||||||
HANDLE ContainerKeyHandle = NULL;
|
HANDLE ContainerKeyHandle = NULL;
|
||||||
HANDLE ObjectKeyHandle;
|
HANDLE ObjectKeyHandle = NULL;
|
||||||
|
HANDLE MembersKeyHandle = NULL;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
if (DbObject == NULL)
|
if (DbObject == NULL)
|
||||||
|
@ -473,6 +310,28 @@ SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject,
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
&ObjectAttributes);
|
&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);
|
NtClose(ContainerKeyHandle);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -506,15 +365,31 @@ SampOpenDbObject(IN PSAM_DB_OBJECT ParentObject,
|
||||||
sizeof(SAM_DB_OBJECT));
|
sizeof(SAM_DB_OBJECT));
|
||||||
if (NewObject == NULL)
|
if (NewObject == NULL)
|
||||||
{
|
{
|
||||||
|
if (MembersKeyHandle != NULL)
|
||||||
|
NtClose(MembersKeyHandle);
|
||||||
NtClose(ObjectKeyHandle);
|
NtClose(ObjectKeyHandle);
|
||||||
return STATUS_NO_MEMORY;
|
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->Signature = SAMP_DB_SIGNATURE;
|
||||||
NewObject->RefCount = 1;
|
NewObject->RefCount = 1;
|
||||||
NewObject->ObjectType = ObjectType;
|
NewObject->ObjectType = ObjectType;
|
||||||
NewObject->Access = DesiredAccess;
|
NewObject->Access = DesiredAccess;
|
||||||
NewObject->KeyHandle = ObjectKeyHandle;
|
NewObject->KeyHandle = ObjectKeyHandle;
|
||||||
|
NewObject->MembersKeyHandle = MembersKeyHandle;
|
||||||
NewObject->ParentObject = ParentObject;
|
NewObject->ParentObject = ParentObject;
|
||||||
|
|
||||||
if (ParentObject != NULL)
|
if (ParentObject != NULL)
|
||||||
|
@ -585,9 +460,15 @@ SampCloseDbObject(PSAM_DB_OBJECT DbObject)
|
||||||
if (DbObject->KeyHandle != NULL)
|
if (DbObject->KeyHandle != NULL)
|
||||||
NtClose(DbObject->KeyHandle);
|
NtClose(DbObject->KeyHandle);
|
||||||
|
|
||||||
|
if (DbObject->MembersKeyHandle != NULL)
|
||||||
|
NtClose(DbObject->MembersKeyHandle);
|
||||||
|
|
||||||
if (DbObject->ParentObject != NULL)
|
if (DbObject->ParentObject != NULL)
|
||||||
ParentObject = DbObject->ParentObject;
|
ParentObject = DbObject->ParentObject;
|
||||||
|
|
||||||
|
if (DbObject->Name != NULL)
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject->Name);
|
||||||
|
|
||||||
RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
|
||||||
|
|
||||||
if (ParentObject != NULL)
|
if (ParentObject != NULL)
|
||||||
|
|
|
@ -15,6 +15,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(samsrv);
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
|
static
|
||||||
|
BOOLEAN
|
||||||
|
IsStringType(ULONG Type)
|
||||||
|
{
|
||||||
|
return (Type == REG_SZ) || (Type == REG_EXPAND_SZ) || (Type == REG_MULTI_SZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
SampRegCloseKey(IN HANDLE KeyHandle)
|
SampRegCloseKey(IN HANDLE KeyHandle)
|
||||||
{
|
{
|
||||||
|
@ -132,32 +140,148 @@ SampRegOpenKey(IN HANDLE ParentKeyHandle,
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
SampRegSetValue(HANDLE KeyHandle,
|
SampRegQueryKeyInfo(IN HANDLE KeyHandle,
|
||||||
LPWSTR ValueName,
|
OUT PULONG SubKeyCount,
|
||||||
ULONG Type,
|
OUT PULONG ValueCount)
|
||||||
LPVOID Data,
|
|
||||||
ULONG DataLength)
|
|
||||||
{
|
{
|
||||||
UNICODE_STRING Name;
|
KEY_FULL_INFORMATION FullInfoBuffer;
|
||||||
|
ULONG Length;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
RtlInitUnicodeString(&Name,
|
FullInfoBuffer.ClassLength = 0;
|
||||||
ValueName);
|
FullInfoBuffer.ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
|
||||||
|
|
||||||
return ZwSetValueKey(KeyHandle,
|
Status = NtQueryKey(KeyHandle,
|
||||||
&Name,
|
KeyFullInformation,
|
||||||
0,
|
&FullInfoBuffer,
|
||||||
Type,
|
sizeof(KEY_FULL_INFORMATION),
|
||||||
Data,
|
&Length);
|
||||||
DataLength);
|
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
|
NTSTATUS
|
||||||
SampRegQueryValue(HANDLE KeyHandle,
|
SampRegEnumerateValue(IN HANDLE KeyHandle,
|
||||||
LPWSTR ValueName,
|
IN ULONG Index,
|
||||||
PULONG Type OPTIONAL,
|
OUT LPWSTR Name,
|
||||||
LPVOID Data OPTIONAL,
|
IN OUT PULONG NameLength,
|
||||||
PULONG DataLength OPTIONAL)
|
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;
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
||||||
UNICODE_STRING Name;
|
UNICODE_STRING Name;
|
||||||
|
@ -200,6 +324,16 @@ SampRegQueryValue(HANDLE KeyHandle,
|
||||||
RtlMoveMemory(Data,
|
RtlMoveMemory(Data,
|
||||||
ValueInfo->Data,
|
ValueInfo->Data,
|
||||||
ValueInfo->DataLength);
|
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 */
|
/* Free the memory and return status */
|
||||||
|
@ -210,3 +344,24 @@ SampRegQueryValue(HANDLE KeyHandle,
|
||||||
|
|
||||||
return Status;
|
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;
|
PSAM_DB_OBJECT AliasObject;
|
||||||
LPWSTR MemberIdString = NULL;
|
LPWSTR MemberIdString = NULL;
|
||||||
HANDLE MembersKeyHandle = NULL;
|
HANDLE MembersKeyHandle = NULL;
|
||||||
|
HANDLE MemberKeyHandle = NULL;
|
||||||
|
ULONG MemberIdLength;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
TRACE("SamrAddMemberToAlias(%p %p)\n",
|
TRACE("SamrAddMemberToAlias(%p %p)\n",
|
||||||
|
@ -1205,6 +1207,8 @@ SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
|
||||||
ConvertSidToStringSidW(MemberId, &MemberIdString);
|
ConvertSidToStringSidW(MemberId, &MemberIdString);
|
||||||
TRACE("Member SID: %S\n", MemberIdString);
|
TRACE("Member SID: %S\n", MemberIdString);
|
||||||
|
|
||||||
|
MemberIdLength = RtlLengthSid(MemberId);
|
||||||
|
|
||||||
Status = SampRegCreateKey(AliasObject->KeyHandle,
|
Status = SampRegCreateKey(AliasObject->KeyHandle,
|
||||||
L"Members",
|
L"Members",
|
||||||
KEY_WRITE,
|
KEY_WRITE,
|
||||||
|
@ -1218,10 +1222,39 @@ SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
|
||||||
Status = SampRegSetValue(MembersKeyHandle,
|
Status = SampRegSetValue(MembersKeyHandle,
|
||||||
MemberIdString,
|
MemberIdString,
|
||||||
REG_BINARY,
|
REG_BINARY,
|
||||||
NULL,
|
MemberId,
|
||||||
0);
|
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:
|
done:
|
||||||
|
if (MemberKeyHandle != NULL)
|
||||||
|
SampRegCloseKey(MemberKeyHandle);
|
||||||
|
|
||||||
if (MembersKeyHandle != NULL)
|
if (MembersKeyHandle != NULL)
|
||||||
SampRegCloseKey(MembersKeyHandle);
|
SampRegCloseKey(MembersKeyHandle);
|
||||||
|
|
||||||
|
@ -1247,8 +1280,129 @@ NTAPI
|
||||||
SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
|
SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
|
||||||
OUT PSAMPR_PSID_ARRAY_OUT Members)
|
OUT PSAMPR_PSID_ARRAY_OUT Members)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
PSAM_DB_OBJECT AliasObject;
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
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 */
|
/* Function 34 */
|
||||||
|
|
|
@ -42,7 +42,9 @@ typedef struct _SAM_DB_OBJECT
|
||||||
SAM_DB_OBJECT_TYPE ObjectType;
|
SAM_DB_OBJECT_TYPE ObjectType;
|
||||||
ULONG RefCount;
|
ULONG RefCount;
|
||||||
ACCESS_MASK Access;
|
ACCESS_MASK Access;
|
||||||
|
LPWSTR Name;
|
||||||
HANDLE KeyHandle;
|
HANDLE KeyHandle;
|
||||||
|
HANDLE MembersKeyHandle; // only used by Aliases and Groups
|
||||||
struct _SAM_DB_OBJECT *ParentObject;
|
struct _SAM_DB_OBJECT *ParentObject;
|
||||||
} SAM_DB_OBJECT, *PSAM_DB_OBJECT;
|
} SAM_DB_OBJECT, *PSAM_DB_OBJECT;
|
||||||
|
|
||||||
|
@ -126,6 +128,20 @@ SampRegOpenKey(IN HANDLE ParentKeyHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
OUT HANDLE KeyHandle);
|
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
|
NTSTATUS
|
||||||
SampRegQueryValue(IN HANDLE KeyHandle,
|
SampRegQueryValue(IN HANDLE KeyHandle,
|
||||||
IN LPWSTR ValueName,
|
IN LPWSTR ValueName,
|
||||||
|
|
|
@ -164,6 +164,12 @@ NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
SamFreeMemory(IN PVOID Buffer);
|
SamFreeMemory(IN PVOID Buffer);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
|
||||||
|
OUT PSID **MemberIds,
|
||||||
|
OUT PULONG MemberCount);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
|
SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
|
||||||
|
|
Loading…
Reference in a new issue