static HANDLE SecurityKeyHandle = NULL;
+SID_IDENTIFIER_AUTHORITY NullSidAuthority = {SECURITY_NULL_SID_AUTHORITY};
+SID_IDENTIFIER_AUTHORITY WorldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY};
+SID_IDENTIFIER_AUTHORITY LocalSidAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
+SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = {SECURITY_CREATOR_SID_AUTHORITY};
+SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+
+PSID BuiltinDomainSid = NULL;
+PSID AccountDomainSid = NULL;
+UNICODE_STRING BuiltinDomainName = {0, 0, NULL};
+UNICODE_STRING AccountDomainName = {0, 0, NULL};
+
/* FUNCTIONS ***************************************************************/
}
+static NTSTATUS
+LsapCreateRandomDomainSid(OUT PSID *Sid)
+{
+ LARGE_INTEGER SystemTime;
+ PULONG Seed;
+
+ NtQuerySystemTime(&SystemTime);
+ Seed = &SystemTime.u.LowPart;
+
+ return RtlAllocateAndInitializeSid(&NtAuthority,
+ 4,
+ SECURITY_NT_NON_UNIQUE,
+ RtlUniform(Seed),
+ RtlUniform(Seed),
+ RtlUniform(Seed),
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ SECURITY_NULL_RID,
+ Sid);
+}
+
+
static NTSTATUS
LsapCreateDatabaseObjects(VOID)
{
- PLSA_DB_OBJECT DbObject = NULL;
+ PLSAP_POLICY_AUDIT_EVENTS_DATA AuditEventsInfo = NULL;
+ POLICY_DEFAULT_QUOTA_INFO QuotaInfo;
+ POLICY_MODIFICATION_INFO ModificationInfo;
+ POLICY_AUDIT_FULL_QUERY_INFO AuditFullInfo = {FALSE, FALSE};
+ POLICY_AUDIT_LOG_INFO AuditLogInfo;
+ GUID DnsDomainGuid;
+ PLSA_DB_OBJECT PolicyObject = NULL;
+ PSID AccountDomainSid = NULL;
+ PSECURITY_DESCRIPTOR PolicySd = NULL;
+ ULONG PolicySdSize = 0;
+ ULONG AuditEventsCount;
+ ULONG AuditEventsSize;
+ ULONG i;
+ NTSTATUS Status;
+
+ /* Initialize the default quota limits */
+ QuotaInfo.QuotaLimits.PagedPoolLimit = 0x2000000;
+ QuotaInfo.QuotaLimits.NonPagedPoolLimit = 0x100000;
+ QuotaInfo.QuotaLimits.MinimumWorkingSetSize = 0x10000;
+ QuotaInfo.QuotaLimits.MaximumWorkingSetSize = 0xF000000;
+ QuotaInfo.QuotaLimits.PagefileLimit = 0;
+ QuotaInfo.QuotaLimits.TimeLimit.QuadPart = 0;
+
+ /* Initialize the audit log attribute */
+ AuditLogInfo.AuditLogPercentFull = 0;
+ AuditLogInfo.MaximumLogSize = 0; // DWORD
+ AuditLogInfo.AuditRetentionPeriod.QuadPart = 0; // LARGE_INTEGER
+ AuditLogInfo.AuditLogFullShutdownInProgress = 0; // BYTE
+ AuditLogInfo.TimeToShutdown.QuadPart = 0; // LARGE_INTEGER
+ AuditLogInfo.NextAuditRecordId = 0; // DWORD
+
+ /* Initialize the Audit Events attribute */
+ AuditEventsCount = AuditCategoryAccountLogon - AuditCategorySystem + 1;
+ AuditEventsSize = sizeof(LSAP_POLICY_AUDIT_EVENTS_DATA) + AuditEventsCount * sizeof(DWORD);
+ AuditEventsInfo = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ AuditEventsSize);
+ if (AuditEventsInfo == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ AuditEventsInfo->AuditingMode = FALSE;
+ AuditEventsInfo->MaximumAuditEventCount = AuditEventsCount;
+ for (i = 0; i < AuditEventsCount; i++)
+ AuditEventsInfo->AuditEvents[i] = 0;
+
+ /* Initialize the DNS Domain GUID attribute */
+ memset(&DnsDomainGuid, 0, sizeof(GUID));
+
+ /* Initialize the modification attribute */
+ ModificationInfo.ModifiedId.QuadPart = 0;
+ NtQuerySystemTime(&ModificationInfo.DatabaseCreationTime);
+
+ /* Create a random domain SID */
+ Status = LsapCreateRandomDomainSid(&AccountDomainSid);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ Status = LsapCreatePolicySd(&PolicySd,
+ &PolicySdSize);
+ if (!NT_SUCCESS(Status))
+ goto done;
/* Open the 'Policy' object */
- DbObject = (PLSA_DB_OBJECT)LsapCreateDbObject(NULL,
- L"Policy",
- TRUE,
- LsaDbPolicyObject,
- 0);
- if (DbObject != NULL)
- {
- LsapSetObjectAttribute(DbObject,
- L"PolPrDmN",
- NULL,
- 0);
+ Status = LsapOpenDbObject(NULL,
+ NULL,
+ L"Policy",
+ LsaDbPolicyObject,
+ 0,
+ &PolicyObject);
+ if (!NT_SUCCESS(Status))
+ goto done;
- LsapSetObjectAttribute(DbObject,
- L"PolPrDmS",
- NULL,
- 0);
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolPrDmN",
+ NULL,
+ 0);
- LsapSetObjectAttribute(DbObject,
- L"PolAcDmN",
- NULL,
- 0);
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolPrDmS",
+ NULL,
+ 0);
- LsapSetObjectAttribute(DbObject,
- L"PolAcDmS",
- NULL,
- 0);
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolAcDmN",
+ NULL,
+ 0);
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolAcDmS",
+ AccountDomainSid,
+ RtlLengthSid(AccountDomainSid));
+
+ /* Set the default quota limits attribute */
+ LsapSetObjectAttribute(PolicyObject,
+ L"DefQuota",
+ &QuotaInfo,
+ sizeof(POLICY_DEFAULT_QUOTA_INFO));
+
+ /* Set the modification attribute */
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolMod",
+ &ModificationInfo,
+ sizeof(POLICY_MODIFICATION_INFO));
+
+ /* Set the audit full attribute */
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolAdtFl",
+ &AuditFullInfo,
+ sizeof(POLICY_AUDIT_FULL_QUERY_INFO));
+
+ /* Set the audit log attribute */
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolAdtLg",
+ &AuditLogInfo,
+ sizeof(POLICY_AUDIT_LOG_INFO));
+
+ /* Set the audit events attribute */
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolAdtEv",
+ &AuditEventsInfo,
+ AuditEventsSize);
+
+ /* Set the DNS Domain Name attribute */
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolDnDDN",
+ NULL,
+ 0);
- /* Close the 'Policy' object */
- LsapCloseDbObject((LSAPR_HANDLE)DbObject);
- }
+ /* Set the DNS Forest Name attribute */
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolDnTrN",
+ NULL,
+ 0);
- return STATUS_SUCCESS;
+ /* Set the DNS Domain GUID attribute */
+ LsapSetObjectAttribute(PolicyObject,
+ L"PolDnDmG",
+ &DnsDomainGuid,
+ sizeof(GUID));
+
+ /* Set the Sceurity Descriptor */
+ LsapSetObjectAttribute(PolicyObject,
+ L"SecDesc",
+ PolicySd,
+ PolicySdSize);
+
+done:
+ if (AuditEventsInfo != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, AuditEventsInfo);
+
+ if (PolicyObject != NULL)
+ LsapCloseDbObject(PolicyObject);
+
+ if (AccountDomainSid != NULL)
+ RtlFreeSid(AccountDomainSid);
+
+ if (PolicySd != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, PolicySd);
+
+ return Status;
}
}
+static NTSTATUS
+LsapGetDomainInfo(VOID)
+{
+ PLSA_DB_OBJECT PolicyObject = NULL;
+ PUNICODE_STRING DomainName = NULL;
+ ULONG AttributeSize;
+ LPWSTR SidString = NULL;
+ NTSTATUS Status;
+
+ /* Get the built-in domain SID and name */
+ Status = RtlAllocateAndInitializeSid(&NtAuthority,
+ 1,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &BuiltinDomainSid);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /**/
+ RtlInitUnicodeString(&BuiltinDomainName,
+ L"BUILTIN");
+
+ /* Open the 'Policy' object */
+ Status = LsapOpenDbObject(NULL,
+ NULL,
+ L"Policy",
+ LsaDbPolicyObject,
+ 0,
+ &PolicyObject);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ /* Get the account domain SID */
+ AttributeSize = 0;
+ Status = LsapGetObjectAttribute(PolicyObject,
+ L"PolAcDmS",
+ NULL,
+ &AttributeSize);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ if (AttributeSize > 0)
+ {
+ AccountDomainSid = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ AttributeSize);
+ if (AccountDomainSid == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ Status = LsapGetObjectAttribute(PolicyObject,
+ L"PolAcDmS",
+ AccountDomainSid,
+ &AttributeSize);
+ if (!NT_SUCCESS(Status))
+ goto done;
+ }
+
+ /* Get the account domain name */
+ AttributeSize = 0;
+ Status = LsapGetObjectAttribute(PolicyObject,
+ L"PolAcDmN",
+ NULL,
+ &AttributeSize);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ if (AttributeSize > 0)
+ {
+ DomainName = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ AttributeSize);
+ if (DomainName == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ Status = LsapGetObjectAttribute(PolicyObject,
+ L"PolAcDmN",
+ DomainName,
+ &AttributeSize);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ DomainName->Buffer = (LPWSTR)((ULONG_PTR)DomainName + (ULONG_PTR)DomainName->Buffer);
+
+ AccountDomainName.Length = DomainName->Length;
+ AccountDomainName.MaximumLength = DomainName->Length + sizeof(WCHAR);
+ AccountDomainName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ AccountDomainName.MaximumLength);
+ if (AccountDomainName.Buffer == NULL)
+ {
+ ERR("Failed to allocate the account domain name buffer\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ RtlCopyMemory(AccountDomainName.Buffer,
+ DomainName->Buffer,
+ DomainName->Length);
+ }
+
+ ConvertSidToStringSidW(BuiltinDomainSid, &SidString);
+ TRACE("Builtin Domain SID: %S\n", SidString);
+ LocalFree(SidString);
+ SidString = NULL;
+
+ TRACE("Builtin Domain Name: %wZ\n", &BuiltinDomainName);
+
+ ConvertSidToStringSidW(AccountDomainSid, &SidString);
+ TRACE("Account Domain SID: %S\n", SidString);
+ LocalFree(SidString);
+ SidString = NULL;
+
+ TRACE("Account Domain Name: %wZ\n", &AccountDomainName);
+
+done:
+ if (DomainName != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DomainName);
+
+ if (PolicyObject != NULL)
+ LsapCloseDbObject(PolicyObject);
+
+ return Status;
+}
+
+
NTSTATUS
LsapInitDatabase(VOID)
{
}
}
+ Status = LsapGetDomainInfo();
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Failed to get the domain information (Status: 0x%08lx)\n", Status);
+ return Status;
+ }
+
TRACE("LsapInitDatabase() done\n");
return STATUS_SUCCESS;
}
-LSAPR_HANDLE
-LsapCreateDbObject(LSAPR_HANDLE ParentHandle,
- LPWSTR ObjectName,
- BOOLEAN Open,
- LSA_DB_OBJECT_TYPE ObjectType,
- ACCESS_MASK DesiredAccess)
+NTSTATUS
+LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject,
+ IN LPWSTR ContainerName,
+ IN LPWSTR ObjectName,
+ IN LSA_DB_OBJECT_TYPE ObjectType,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PLSA_DB_OBJECT *DbObject)
{
- PLSA_DB_OBJECT ParentObject = (PLSA_DB_OBJECT)ParentHandle;
- PLSA_DB_OBJECT DbObject;
+ PLSA_DB_OBJECT NewObject;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
HANDLE ParentKeyHandle;
- HANDLE ObjectKeyHandle;
+ HANDLE ContainerKeyHandle = NULL;
+ HANDLE ObjectKeyHandle = NULL;
NTSTATUS Status;
- if (ParentHandle != NULL)
- ParentKeyHandle = ParentObject->KeyHandle;
- else
+ if (DbObject == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ if (ParentObject == NULL)
ParentKeyHandle = SecurityKeyHandle;
+ else
+ ParentKeyHandle = ParentObject->KeyHandle;
- RtlInitUnicodeString(&KeyName,
- ObjectName);
+ if (ContainerName != NULL)
+ {
+ /* Open the container key */
+ RtlInitUnicodeString(&KeyName,
+ ContainerName);
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- ParentKeyHandle,
- NULL);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ ParentKeyHandle,
+ NULL);
- if (Open == TRUE)
- {
- Status = NtOpenKey(&ObjectKeyHandle,
+ Status = NtOpenKey(&ContainerKeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Open the object key */
+ RtlInitUnicodeString(&KeyName,
+ ObjectName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ ContainerKeyHandle,
+ NULL);
+
+ Status = NtCreateKey(&ObjectKeyHandle,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ 0,
+ NULL);
+
+ NtClose(ContainerKeyHandle);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
}
else
{
+ RtlInitUnicodeString(&KeyName,
+ ObjectName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ ParentKeyHandle,
+ NULL);
+
Status = NtCreateKey(&ObjectKeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes,
NULL,
0,
NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
}
- if (!NT_SUCCESS(Status))
+ NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ sizeof(LSA_DB_OBJECT));
+ if (NewObject == NULL)
{
- return NULL;
+ NtClose(ObjectKeyHandle);
+ return STATUS_NO_MEMORY;
}
- DbObject = (PLSA_DB_OBJECT)RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- sizeof(LSA_DB_OBJECT));
+ NewObject->Signature = LSAP_DB_SIGNATURE;
+ NewObject->RefCount = 1;
+ NewObject->ObjectType = ObjectType;
+ NewObject->Access = DesiredAccess;
+ NewObject->KeyHandle = ObjectKeyHandle;
+ NewObject->ParentObject = ParentObject;
+
+ if (ParentObject != NULL)
+ ParentObject->RefCount++;
+
+ *DbObject = NewObject;
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject,
+ IN LPWSTR ContainerName,
+ IN LPWSTR ObjectName,
+ IN LSA_DB_OBJECT_TYPE ObjectType,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PLSA_DB_OBJECT *DbObject)
+{
+ PLSA_DB_OBJECT NewObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ HANDLE ParentKeyHandle;
+ HANDLE ContainerKeyHandle = NULL;
+ HANDLE ObjectKeyHandle = NULL;
+ NTSTATUS Status;
+
if (DbObject == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ if (ParentObject == NULL)
+ ParentKeyHandle = SecurityKeyHandle;
+ else
+ ParentKeyHandle = ParentObject->KeyHandle;
+
+ if (ContainerName != NULL)
+ {
+ /* Open the container key */
+ RtlInitUnicodeString(&KeyName,
+ ContainerName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ ParentKeyHandle,
+ NULL);
+
+ Status = NtOpenKey(&ContainerKeyHandle,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Open the object key */
+ RtlInitUnicodeString(&KeyName,
+ ObjectName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ ContainerKeyHandle,
+ NULL);
+
+ Status = NtOpenKey(&ObjectKeyHandle,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes);
+
+ NtClose(ContainerKeyHandle);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ else
+ {
+ /* Open the object key */
+ RtlInitUnicodeString(&KeyName,
+ ObjectName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ ParentKeyHandle,
+ NULL);
+
+ Status = NtOpenKey(&ObjectKeyHandle,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ sizeof(LSA_DB_OBJECT));
+ if (NewObject == NULL)
{
NtClose(ObjectKeyHandle);
- return NULL;
+ return STATUS_NO_MEMORY;
}
- DbObject->Signature = LSAP_DB_SIGNATURE;
- DbObject->RefCount = 0;
- DbObject->ObjectType = ObjectType;
- DbObject->Access = DesiredAccess;
- DbObject->KeyHandle = ObjectKeyHandle;
- DbObject->ParentObject = ParentObject;
+ NewObject->Signature = LSAP_DB_SIGNATURE;
+ NewObject->RefCount = 1;
+ NewObject->ObjectType = ObjectType;
+ NewObject->Access = DesiredAccess;
+ NewObject->KeyHandle = ObjectKeyHandle;
+ NewObject->ParentObject = ParentObject;
if (ParentObject != NULL)
ParentObject->RefCount++;
- return (LSAPR_HANDLE)DbObject;
+ *DbObject = NewObject;
+
+ return STATUS_SUCCESS;
}
NTSTATUS
LsapValidateDbObject(LSAPR_HANDLE Handle,
LSA_DB_OBJECT_TYPE ObjectType,
- ACCESS_MASK GrantedAccess)
+ ACCESS_MASK DesiredAccess,
+ PLSA_DB_OBJECT *DbObject)
{
- PLSA_DB_OBJECT DbObject = (PLSA_DB_OBJECT)Handle;
+ PLSA_DB_OBJECT LocalObject = (PLSA_DB_OBJECT)Handle;
BOOLEAN bValid = FALSE;
_SEH2_TRY
{
- if (DbObject->Signature == LSAP_DB_SIGNATURE)
+ if (LocalObject->Signature == LSAP_DB_SIGNATURE)
{
if ((ObjectType == LsaDbIgnoreObject) ||
- (DbObject->ObjectType == ObjectType))
+ (LocalObject->ObjectType == ObjectType))
bValid = TRUE;
}
}
if (bValid == FALSE)
return STATUS_INVALID_HANDLE;
- if (GrantedAccess != 0)
+ if (DesiredAccess != 0)
{
- /* FIXME: Check for granted access rights */
+ /* Check for granted access rights */
+ if ((LocalObject->Access & DesiredAccess) != DesiredAccess)
+ {
+ ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
+ LocalObject->Access, DesiredAccess);
+ return STATUS_ACCESS_DENIED;
+ }
}
+ if (DbObject != NULL)
+ *DbObject = LocalObject;
+
return STATUS_SUCCESS;
}
NTSTATUS
-LsapCloseDbObject(LSAPR_HANDLE Handle)
+LsapCloseDbObject(PLSA_DB_OBJECT DbObject)
{
- PLSA_DB_OBJECT DbObject = (PLSA_DB_OBJECT)Handle;
+ PLSA_DB_OBJECT ParentObject = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
- if (DbObject->RefCount != 0)
- return STATUS_UNSUCCESSFUL;
+ DbObject->RefCount--;
+
+ if (DbObject->RefCount > 0)
+ return STATUS_SUCCESS;
+
+ if (DbObject->KeyHandle != NULL)
+ NtClose(DbObject->KeyHandle);
if (DbObject->ParentObject != NULL)
- DbObject->ParentObject->RefCount--;
+ ParentObject = DbObject->ParentObject;
+
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
+
+ if (ParentObject != NULL)
+ {
+ ParentObject->RefCount--;
+
+ if (ParentObject->RefCount == 0)
+ Status = LsapCloseDbObject(ParentObject);
+ }
+
+ return Status;
+}
+
+
+NTSTATUS
+LsapDeleteDbObject(IN PLSA_DB_OBJECT DbObject)
+{
+ PLSA_DB_OBJECT ParentObject = NULL;
+ WCHAR KeyName[64];
+ ULONG Index;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ DbObject->RefCount--;
+
+ if (DbObject->RefCount > 0)
+ return STATUS_SUCCESS;
if (DbObject->KeyHandle != NULL)
+ {
+ Index = 0;
+
+ while (TRUE)
+ {
+ Status = LsapRegEnumerateSubKey(DbObject->KeyHandle,
+ Index,
+ 64 * sizeof(WCHAR),
+ KeyName);
+ if (!NT_SUCCESS(Status))
+ break;
+
+ TRACE("Index: %lu\n", Index);
+ TRACE("Key name: %S\n", KeyName);
+
+ Status = LsapRegDeleteSubKey(DbObject->KeyHandle,
+ KeyName);
+ if (!NT_SUCCESS(Status))
+ break;
+ }
+
+ if (Status == STATUS_NO_MORE_ENTRIES)
+ Status = STATUS_SUCCESS;
+
+ LsapRegDeleteKey(DbObject->KeyHandle);
+
NtClose(DbObject->KeyHandle);
+ }
+
+ if (DbObject->ParentObject != NULL)
+ ParentObject = DbObject->ParentObject;
RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
- return STATUS_SUCCESS;
+ if (ParentObject != NULL)
+ {
+ ParentObject->RefCount--;
+
+ if (ParentObject->RefCount == 0)
+ Status = LsapCloseDbObject(ParentObject);
+ }
+
+ return Status;
}