[LSASRV]
[reactos.git] / reactos / dll / win32 / lsasrv / lsarpc.c
index 2fe2d66..5e9742d 100644 (file)
 
 #include "lsasrv.h"
 
+WINE_DEFAULT_DEBUG_CHANNEL(lsasrv);
 
-static RTL_CRITICAL_SECTION PolicyHandleTableLock;
 
-WINE_DEFAULT_DEBUG_CHANNEL(lsasrv);
+/* GLOBALS *****************************************************************/
 
+static RTL_CRITICAL_SECTION PolicyHandleTableLock;
 
-/* FUNCTIONS ***************************************************************/
 
+/* FUNCTIONS ***************************************************************/
 
 VOID
 LsarStartRpcServer(VOID)
@@ -69,6 +70,7 @@ void __RPC_USER LSAPR_HANDLE_rundown(LSAPR_HANDLE hHandle)
 NTSTATUS WINAPI LsarClose(
     LSAPR_HANDLE *ObjectHandle)
 {
+    PLSA_DB_OBJECT DbObject;
     NTSTATUS Status = STATUS_SUCCESS;
 
     TRACE("0x%p\n", ObjectHandle);
@@ -77,10 +79,11 @@ NTSTATUS WINAPI LsarClose(
 
     Status = LsapValidateDbObject(*ObjectHandle,
                                   LsaDbIgnoreObject,
-                                  0);
+                                  0,
+                                  &DbObject);
     if (Status == STATUS_SUCCESS)
     {
-        Status = LsapCloseDbObject(*ObjectHandle);
+        Status = LsapCloseDbObject(DbObject);
         *ObjectHandle = NULL;
     }
 
@@ -154,22 +157,24 @@ NTSTATUS WINAPI LsarOpenPolicy(
     ACCESS_MASK DesiredAccess,
     LSAPR_HANDLE *PolicyHandle)
 {
-    NTSTATUS Status = STATUS_SUCCESS;
+    PLSA_DB_OBJECT PolicyObject;
+    NTSTATUS Status;
 
     TRACE("LsarOpenPolicy called!\n");
 
     RtlEnterCriticalSection(&PolicyHandleTableLock);
 
-    *PolicyHandle = LsapCreateDbObject(NULL,
-                                       L"Policy",
-                                       TRUE,
-                                       LsaDbPolicyObject,
-                                       DesiredAccess);
-    if (*PolicyHandle == NULL)
-        Status = STATUS_INSUFFICIENT_RESOURCES;
+    Status = LsapOpenDbObject(NULL,
+                              L"Policy",
+                              LsaDbPolicyObject,
+                              DesiredAccess,
+                              &PolicyObject);
 
     RtlLeaveCriticalSection(&PolicyHandleTableLock);
 
+    if (NT_SUCCESS(Status))
+        *PolicyHandle = (LSAPR_HANDLE)PolicyObject;
+
     TRACE("LsarOpenPolicy done!\n");
 
     return Status;
@@ -182,6 +187,8 @@ NTSTATUS WINAPI LsarQueryInformationPolicy(
     POLICY_INFORMATION_CLASS InformationClass,
     PLSAPR_POLICY_INFORMATION *PolicyInformation)
 {
+    PLSA_DB_OBJECT DbObject;
+    ACCESS_MASK DesiredAccess = 0;
     NTSTATUS Status;
 
     TRACE("LsarQueryInformationPolicy(%p,0x%08x,%p)\n",
@@ -192,14 +199,48 @@ NTSTATUS WINAPI LsarQueryInformationPolicy(
         TRACE("*PolicyInformation %p\n", *PolicyInformation);
     }
 
+    switch (InformationClass)
+    {
+        case PolicyAuditLogInformation:
+        case PolicyAuditEventsInformation:
+        case PolicyAuditFullQueryInformation:
+            DesiredAccess = POLICY_VIEW_AUDIT_INFORMATION;
+            break;
+
+        case PolicyPrimaryDomainInformation:
+        case PolicyAccountDomainInformation:
+        case PolicyLsaServerRoleInformation:
+        case PolicyReplicaSourceInformation:
+        case PolicyDefaultQuotaInformation:
+        case PolicyModificationInformation:
+        case PolicyDnsDomainInformation:
+        case PolicyDnsDomainInformationInt:
+        case PolicyLocalAccountDomainInformation:
+            DesiredAccess = POLICY_VIEW_LOCAL_INFORMATION;
+            break;
+
+        case PolicyPdAccountInformation:
+            DesiredAccess = POLICY_GET_PRIVATE_INFORMATION;
+            break;
+
+        default:
+            ERR("Invalid InformationClass!\n");
+            return STATUS_INVALID_PARAMETER;
+    }
+
     Status = LsapValidateDbObject(PolicyHandle,
                                   LsaDbPolicyObject,
-                                  0); /* FIXME */
+                                  DesiredAccess,
+                                  &DbObject);
     if (!NT_SUCCESS(Status))
         return Status;
 
     switch (InformationClass)
     {
+        case PolicyAuditLogInformation:      /* 1 */
+            Status = LsarQueryAuditLog(PolicyHandle,
+                                       PolicyInformation);
+
         case PolicyAuditEventsInformation:   /* 2 */
             Status = LsarQueryAuditEvents(PolicyHandle,
                                           PolicyInformation);
@@ -210,28 +251,57 @@ NTSTATUS WINAPI LsarQueryInformationPolicy(
                                             PolicyInformation);
             break;
 
+        case PolicyPdAccountInformation:     /* 4 */
+            Status = LsarQueryPdAccount(PolicyHandle,
+                                        PolicyInformation);
+
         case PolicyAccountDomainInformation: /* 5 */
             Status = LsarQueryAccountDomain(PolicyHandle,
                                             PolicyInformation);
             break;
 
-        case PolicyDnsDomainInformation:     /* 12 (0xc) */
+        case PolicyLsaServerRoleInformation: /* 6 */
+            Status = LsarQueryServerRole(PolicyHandle,
+                                         PolicyInformation);
+            break;
+
+        case PolicyReplicaSourceInformation: /* 7 */
+            Status = LsarQueryReplicaSource(PolicyHandle,
+                                            PolicyInformation);
+
+        case PolicyDefaultQuotaInformation:  /* 8 */
+            Status = LsarQueryDefaultQuota(PolicyHandle,
+                                           PolicyInformation);
+            break;
+
+        case PolicyModificationInformation:  /* 9 */
+            Status = LsarQueryModification(PolicyHandle,
+                                           PolicyInformation);
+            break;
+
+        case PolicyAuditFullQueryInformation: /* 11 (0xB) */
+            Status = LsarQueryAuditFull(PolicyHandle,
+                                        PolicyInformation);
+            break;
+
+        case PolicyDnsDomainInformation:      /* 12 (0xC) */
             Status = LsarQueryDnsDomain(PolicyHandle,
                                         PolicyInformation);
             break;
 
-        case PolicyAuditLogInformation:
-        case PolicyPdAccountInformation:
-        case PolicyLsaServerRoleInformation:
-        case PolicyReplicaSourceInformation:
-        case PolicyDefaultQuotaInformation:
-        case PolicyModificationInformation:
-        case PolicyAuditFullSetInformation:
-        case PolicyAuditFullQueryInformation:
-        case PolicyEfsInformation:
-            FIXME("category not implemented\n");
-            Status = STATUS_UNSUCCESSFUL;
+        case PolicyDnsDomainInformationInt:   /* 13 (0xD) */
+            Status = LsarQueryDnsDomainInt(PolicyHandle,
+                                           PolicyInformation);
+            break;
+
+        case PolicyLocalAccountDomainInformation: /* 14 (0xE) */
+            Status = LsarQueryLocalAccountDomain(PolicyHandle,
+                                                 PolicyInformation);
             break;
+
+        default:
+            ERR("Invalid InformationClass!\n");
+            Status = STATUS_INVALID_PARAMETER;
     }
 
     return Status;
@@ -244,6 +314,8 @@ NTSTATUS WINAPI LsarSetInformationPolicy(
     POLICY_INFORMATION_CLASS InformationClass,
     PLSAPR_POLICY_INFORMATION PolicyInformation)
 {
+    PLSA_DB_OBJECT DbObject;
+    ACCESS_MASK DesiredAccess = 0;
     NTSTATUS Status;
 
     TRACE("LsarSetInformationPolicy(%p,0x%08x,%p)\n",
@@ -254,9 +326,43 @@ NTSTATUS WINAPI LsarSetInformationPolicy(
         TRACE("*PolicyInformation %p\n", *PolicyInformation);
     }
 
+    switch (InformationClass)
+    {
+        case PolicyAuditLogInformation:
+        case PolicyAuditFullSetInformation:
+            DesiredAccess = POLICY_AUDIT_LOG_ADMIN;
+            break;
+
+        case PolicyAuditEventsInformation:
+            DesiredAccess = POLICY_SET_AUDIT_REQUIREMENTS;
+            break;
+
+        case PolicyPrimaryDomainInformation:
+        case PolicyAccountDomainInformation:
+        case PolicyDnsDomainInformation:
+        case PolicyDnsDomainInformationInt:
+        case PolicyLocalAccountDomainInformation:
+            DesiredAccess = POLICY_TRUST_ADMIN;
+            break;
+
+        case PolicyLsaServerRoleInformation:
+        case PolicyReplicaSourceInformation:
+            DesiredAccess = POLICY_SERVER_ADMIN;
+            break;
+
+        case PolicyDefaultQuotaInformation:
+            DesiredAccess = POLICY_SET_DEFAULT_QUOTA_LIMITS;
+            break;
+
+        default:
+            ERR("Invalid InformationClass!\n");
+            return STATUS_INVALID_PARAMETER;
+    }
+
     Status = LsapValidateDbObject(PolicyHandle,
                                   LsaDbPolicyObject,
-                                  0); /* FIXME */
+                                  DesiredAccess,
+                                  &DbObject);
     if (!NT_SUCCESS(Status))
         return Status;
 
@@ -310,15 +416,17 @@ NTSTATUS WINAPI LsarCreateAccount(
     ACCESS_MASK DesiredAccess,
     LSAPR_HANDLE *AccountHandle)
 {
-    LSAPR_HANDLE AccountsHandle;
-    LSAPR_HANDLE Account;
-    LPWSTR SidString;
-    NTSTATUS Status;
+    PLSA_DB_OBJECT PolicyObject;
+    PLSA_DB_OBJECT AccountsObject = NULL;
+    PLSA_DB_OBJECT AccountObject = NULL;
+    LPWSTR SidString = NULL;
+    NTSTATUS Status = STATUS_SUCCESS;
 
     /* Validate the PolicyHandle */
     Status = LsapValidateDbObject(PolicyHandle,
                                   LsaDbPolicyObject,
-                                  POLICY_CREATE_ACCOUNT);
+                                  POLICY_CREATE_ACCOUNT,
+                                  &PolicyObject);
     if (!NT_SUCCESS(Status))
     {
         ERR("LsapValidateDbObject returned 0x%08lx\n", Status);
@@ -326,15 +434,15 @@ NTSTATUS WINAPI LsarCreateAccount(
     }
 
     /* Open the Accounts object */
-    AccountsHandle = LsapCreateDbObject(PolicyHandle,
-                                        L"Accounts",
-                                        TRUE,
-                                        LsaDbContainerObject,
-                                        0);
-    if (AccountsHandle == NULL)
+    Status = LsapOpenDbObject(PolicyObject,
+                              L"Accounts",
+                              LsaDbContainerObject,
+                              0,
+                              &AccountsObject);
+    if (!NT_SUCCESS(Status))
     {
-        ERR("LsapCreateDbObject (Accounts) failed\n");
-        return STATUS_UNSUCCESSFUL;
+        ERR("LsapCreateDbObject (Accounts) failed (Status 0x%08lx)\n", Status);
+        goto done;
     }
 
     /* Create SID string */
@@ -342,31 +450,44 @@ NTSTATUS WINAPI LsarCreateAccount(
                                &SidString))
     {
         ERR("ConvertSidToStringSid failed\n");
-        return STATUS_UNSUCCESSFUL;
+        Status = STATUS_INVALID_PARAMETER;
+        goto done;
     }
 
     /* Create the Account object */
-    Account = LsapCreateDbObject(AccountsHandle,
-                                 SidString,
-                                 FALSE,
-                                 LsaDbAccountObject,
-                                 DesiredAccess);
-    if (Account != NULL)
-    {
-        /* Set the Sid attribute */
-        Status = LsapSetObjectAttribute((PLSA_DB_OBJECT)Account,
-                                        L"Sid",
-                                        (PVOID)AccountSid,
-                                        GetLengthSid(AccountSid));
-        if (NT_SUCCESS(Status))
-        {
-            *AccountHandle = Account;
-        }
+    Status = LsapCreateDbObject(AccountsObject,
+                                SidString,
+                                LsaDbAccountObject,
+                                DesiredAccess,
+                                &AccountObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapCreateDbObject (Account) failed (Status 0x%08lx)\n", Status);
+        goto done;
     }
 
-    LocalFree(SidString);
+    /* Set the Sid attribute */
+    Status = LsapSetObjectAttribute(AccountObject,
+                                    L"Sid",
+                                    (PVOID)AccountSid,
+                                    GetLengthSid(AccountSid));
+
+done:
+    if (SidString != NULL)
+        LocalFree(SidString);
 
-    LsapCloseDbObject(AccountsHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        if (AccountObject != NULL)
+            LsapCloseDbObject(AccountObject);
+    }
+    else
+    {
+        *AccountHandle = (LSAPR_HANDLE)AccountObject;
+    }
+
+    if (AccountsObject != NULL)
+        LsapCloseDbObject(AccountsObject);
 
     return STATUS_SUCCESS;
 }
@@ -606,8 +727,87 @@ NTSTATUS WINAPI LsarCreateSecret(
     ACCESS_MASK DesiredAccess,
     LSAPR_HANDLE *SecretHandle)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PLSA_DB_OBJECT PolicyObject;
+    PLSA_DB_OBJECT SecretsObject = NULL;
+    PLSA_DB_OBJECT SecretObject = NULL;
+    LARGE_INTEGER Time;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    /* Validate the PolicyHandle */
+    Status = LsapValidateDbObject(PolicyHandle,
+                                  LsaDbPolicyObject,
+                                  POLICY_CREATE_SECRET,
+                                  &PolicyObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapValidateDbObject returned 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Open the Secrets object */
+    Status = LsapOpenDbObject(PolicyObject,
+                              L"Secrets",
+                              LsaDbContainerObject,
+                              0,
+                              &SecretsObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapCreateDbObject (Secrets) failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Get the current time */
+    Status = NtQuerySystemTime(&Time);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("NtQuerySystemTime failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Create the Secret object */
+    Status = LsapCreateDbObject(SecretsObject,
+                                SecretName->Buffer,
+                                LsaDbSecretObject,
+                                DesiredAccess,
+                                &SecretObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapCreateDbObject (Secret) failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Set the CurrentTime attribute */
+    Status = LsapSetObjectAttribute(SecretObject,
+                                    L"CurrentTime",
+                                    (PVOID)&Time,
+                                    sizeof(LARGE_INTEGER));
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapSetObjectAttribute (CurrentTime) failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Set the OldTime attribute */
+    Status = LsapSetObjectAttribute(SecretObject,
+                                    L"OldTime",
+                                    (PVOID)&Time,
+                                    sizeof(LARGE_INTEGER));
+
+done:
+    if (!NT_SUCCESS(Status))
+    {
+        if (SecretObject != NULL)
+            LsapCloseDbObject(SecretObject);
+    }
+    else
+    {
+        *SecretHandle = (LSAPR_HANDLE)SecretObject;
+    }
+
+    if (SecretsObject != NULL)
+        LsapCloseDbObject(SecretsObject);
+
+    return STATUS_SUCCESS;
 }
 
 
@@ -618,8 +818,80 @@ NTSTATUS WINAPI LsarOpenAccount(
     ACCESS_MASK DesiredAccess,
     LSAPR_HANDLE *AccountHandle)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PLSA_DB_OBJECT PolicyObject;
+    PLSA_DB_OBJECT AccountsObject = NULL;
+    PLSA_DB_OBJECT AccountObject = NULL;
+    LPWSTR SidString = NULL;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    /* Validate the PolicyHandle */
+    Status = LsapValidateDbObject(PolicyHandle,
+                                  LsaDbPolicyObject,
+                                  POLICY_CREATE_ACCOUNT,
+                                  &PolicyObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapValidateDbObject returned 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Open the Accounts object */
+    Status = LsapOpenDbObject(PolicyObject,
+                              L"Accounts",
+                              LsaDbContainerObject,
+                              0,
+                              &AccountsObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapCreateDbObject (Accounts) failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Create SID string */
+    if (!ConvertSidToStringSid((PSID)AccountSid,
+                               &SidString))
+    {
+        ERR("ConvertSidToStringSid failed\n");
+        Status = STATUS_INVALID_PARAMETER;
+        goto done;
+    }
+
+    /* Create the Account object */
+    Status = LsapOpenDbObject(AccountsObject,
+                              SidString,
+                              LsaDbAccountObject,
+                              DesiredAccess,
+                              &AccountObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapOpenDbObject (Account) failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Set the Sid attribute */
+    Status = LsapSetObjectAttribute(AccountObject,
+                                    L"Sid",
+                                    (PVOID)AccountSid,
+                                    GetLengthSid(AccountSid));
+
+done:
+    if (SidString != NULL)
+        LocalFree(SidString);
+
+    if (!NT_SUCCESS(Status))
+    {
+        if (AccountObject != NULL)
+            LsapCloseDbObject(AccountObject);
+    }
+    else
+    {
+        *AccountHandle = (LSAPR_HANDLE)AccountObject;
+    }
+
+    if (AccountsObject != NULL)
+        LsapCloseDbObject(AccountsObject);
+
+    return STATUS_SUCCESS;
 }
 
 
@@ -628,8 +900,52 @@ NTSTATUS WINAPI LsarEnumeratePrivilegesAccount(
     LSAPR_HANDLE AccountHandle,
     PLSAPR_PRIVILEGE_SET *Privileges)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PLSA_DB_OBJECT AccountObject;
+    ULONG PrivilegeSetSize = 0;
+    PLSAPR_PRIVILEGE_SET PrivilegeSet = NULL;
+    NTSTATUS Status;
+
+    *Privileges = NULL;
+
+    /* Validate the AccountHandle */
+    Status = LsapValidateDbObject(AccountHandle,
+                                  LsaDbAccountObject,
+                                  ACCOUNT_VIEW,
+                                  &AccountObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapValidateDbObject returned 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Get the size of the privilege set */
+    Status = LsapGetObjectAttribute(AccountObject,
+                                    L"Privilgs",
+                                    NULL,
+                                    &PrivilegeSetSize);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    /* Allocate a buffer for the privilege set */
+    PrivilegeSet = MIDL_user_allocate(PrivilegeSetSize);
+    if (PrivilegeSet == NULL)
+        return STATUS_NO_MEMORY;
+
+    /* Get the privilege set */
+    Status = LsapGetObjectAttribute(AccountObject,
+                                    L"Privilgs",
+                                    PrivilegeSet,
+                                    &PrivilegeSetSize);
+    if (!NT_SUCCESS(Status))
+    {
+        MIDL_user_free(PrivilegeSet);
+        return Status;
+    }
+
+    /* Return a pointer to the privilege set */
+    *Privileges = PrivilegeSet;
+
+    return STATUS_SUCCESS;
 }
 
 
@@ -638,8 +954,148 @@ NTSTATUS WINAPI LsarAddPrivilegesToAccount(
     LSAPR_HANDLE AccountHandle,
     PLSAPR_PRIVILEGE_SET Privileges)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PLSA_DB_OBJECT AccountObject;
+    PPRIVILEGE_SET CurrentPrivileges = NULL;
+    PPRIVILEGE_SET NewPrivileges = NULL;
+    ULONG PrivilegeSetSize = 0;
+    ULONG PrivilegeCount;
+    ULONG i, j;
+    BOOL bFound;
+    NTSTATUS Status;
+
+    /* Validate the AccountHandle */
+    Status = LsapValidateDbObject(AccountHandle,
+                                  LsaDbAccountObject,
+                                  ACCOUNT_ADJUST_PRIVILEGES,
+                                  &AccountObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapValidateDbObject returned 0x%08lx\n", Status);
+        return Status;
+    }
+
+    Status = LsapGetObjectAttribute(AccountObject,
+                                    L"Privilgs",
+                                    NULL,
+                                    &PrivilegeSetSize);
+    if (!NT_SUCCESS(Status) || PrivilegeSetSize == 0)
+    {
+        /* The Privilgs attribute does not exist */
+
+        PrivilegeSetSize = sizeof(PRIVILEGE_SET) +
+                           (Privileges->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES);
+        Status = LsapSetObjectAttribute(AccountObject,
+                                        L"Privilgs",
+                                        Privileges,
+                                        PrivilegeSetSize);
+    }
+    else
+    {
+        /* The Privilgs attribute exists */
+
+        /* Allocate memory for the stored privilege set */
+        CurrentPrivileges = MIDL_user_allocate(PrivilegeSetSize);
+        if (CurrentPrivileges == NULL)
+            return STATUS_NO_MEMORY;
+
+        /* Get the current privilege set */
+        Status = LsapGetObjectAttribute(AccountObject,
+                                        L"Privilgs",
+                                        CurrentPrivileges,
+                                        &PrivilegeSetSize);
+        if (!NT_SUCCESS(Status))
+        {
+            TRACE("LsapGetObjectAttribute() failed (Status 0x%08lx)\n", Status);
+            goto done;
+        }
+
+        PrivilegeCount = CurrentPrivileges->PrivilegeCount;
+        TRACE("Current privilege count: %lu\n", PrivilegeCount);
+
+        /* Calculate the number privileges in the combined privilege set */
+        for (i = 0; i < Privileges->PrivilegeCount; i++)
+        {
+            bFound = FALSE;
+            for (j = 0; j < CurrentPrivileges->PrivilegeCount; j++)
+            {
+                if (RtlEqualLuid(&(Privileges->Privilege[i].Luid),
+                                 &(CurrentPrivileges->Privilege[i].Luid)))
+                {
+                    bFound = TRUE;
+                    break;
+                }
+            }
+
+            if (bFound == FALSE)
+            {
+                TRACE("Found new privilege\n");
+                PrivilegeCount++;
+            }
+        }
+        TRACE("New privilege count: %lu\n", PrivilegeCount);
+
+        /* Calculate the size of the new privilege set and allocate it */
+        PrivilegeSetSize = sizeof(PRIVILEGE_SET) +
+                           (PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES);
+        NewPrivileges = MIDL_user_allocate(PrivilegeSetSize);
+        if (NewPrivileges == NULL)
+        {
+            Status = STATUS_NO_MEMORY;
+            goto done;
+        }
+
+        /* Initialize the new privilege set */
+        NewPrivileges->PrivilegeCount = PrivilegeCount;
+        NewPrivileges->Control = 0;
+
+        /* Copy all privileges from the current privilege set */
+        RtlCopyLuidAndAttributesArray(CurrentPrivileges->PrivilegeCount,
+                                      &(CurrentPrivileges->Privilege[0]),
+                                      &(NewPrivileges->Privilege[0]));
+
+        /* Add new privileges to the new privilege set */
+        PrivilegeCount = CurrentPrivileges->PrivilegeCount;
+        for (i = 0; i < Privileges->PrivilegeCount; i++)
+        {
+            bFound = FALSE;
+            for (j = 0; j < CurrentPrivileges->PrivilegeCount; j++)
+            {
+                if (RtlEqualLuid(&(Privileges->Privilege[i].Luid),
+                                 &(CurrentPrivileges->Privilege[i].Luid)))
+                {
+                    /* Overwrite attributes if a matching privilege was found */
+                    NewPrivileges->Privilege[j].Attributes = Privileges->Privilege[i].Attributes;
+
+                    bFound = TRUE;
+                    break;
+                }
+            }
+
+            if (bFound == FALSE)
+            {
+                /* Copy the new privilege */
+                RtlCopyLuidAndAttributesArray(1,
+                                              (PLUID_AND_ATTRIBUTES)&(Privileges->Privilege[i]),
+                                              &(NewPrivileges->Privilege[PrivilegeCount]));
+                PrivilegeCount++;
+            }
+        }
+
+        /* Set the new priivliege set */
+        Status = LsapSetObjectAttribute(AccountObject,
+                                        L"Privilgs",
+                                        NewPrivileges,
+                                        PrivilegeSetSize);
+    }
+
+done:
+    if (CurrentPrivileges != NULL)
+        MIDL_user_free(CurrentPrivileges);
+
+    if (NewPrivileges != NULL)
+        MIDL_user_free(NewPrivileges);
+
+    return Status;
 }
 
 
@@ -679,8 +1135,28 @@ NTSTATUS WINAPI LsarGetSystemAccessAccount(
     LSAPR_HANDLE AccountHandle,
     ACCESS_MASK *SystemAccess)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PLSA_DB_OBJECT AccountObject;
+    ULONG Size;
+    NTSTATUS Status;
+
+    /* Validate the account handle */
+    Status = LsapValidateDbObject(AccountHandle,
+                                  LsaDbAccountObject,
+                                  ACCOUNT_VIEW,
+                                  &AccountObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("Invalid handle (Status %lx)\n", Status);
+        return Status;
+    }
+
+    /* Get the system access flags */
+    Status = LsapGetObjectAttribute(AccountObject,
+                                    L"ActSysAc",
+                                    SystemAccess,
+                                    &Size);
+
+    return Status;
 }
 
 
@@ -689,8 +1165,27 @@ NTSTATUS WINAPI LsarSetSystemAccessAccount(
     LSAPR_HANDLE AccountHandle,
     ACCESS_MASK SystemAccess)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PLSA_DB_OBJECT AccountObject;
+    NTSTATUS Status;
+
+    /* Validate the account handle */
+    Status = LsapValidateDbObject(AccountHandle,
+                                  LsaDbAccountObject,
+                                  ACCOUNT_ADJUST_SYSTEM_ACCESS,
+                                  &AccountObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("Invalid handle (Status %lx)\n", Status);
+        return Status;
+    }
+
+    /* Set the system access flags */
+    Status = LsapSetObjectAttribute(AccountObject,
+                                    L"ActSysAc",
+                                    &SystemAccess,
+                                    sizeof(ACCESS_MASK));
+
+    return Status;
 }
 
 
@@ -735,19 +1230,159 @@ NTSTATUS WINAPI LsarOpenSecret(
     ACCESS_MASK DesiredAccess,
     LSAPR_HANDLE *SecretHandle)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PLSA_DB_OBJECT PolicyObject;
+    PLSA_DB_OBJECT SecretsObject = NULL;
+    PLSA_DB_OBJECT SecretObject = NULL;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    /* Validate the PolicyHandle */
+    Status = LsapValidateDbObject(PolicyHandle,
+                                  LsaDbPolicyObject,
+                                  POLICY_CREATE_SECRET,
+                                  &PolicyObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapValidateDbObject returned 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Open the Secrets object */
+    Status = LsapOpenDbObject(PolicyObject,
+                              L"Secrets",
+                              LsaDbContainerObject,
+                              0,
+                              &SecretsObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapCreateDbObject (Secrets) failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Create the secret object */
+    Status = LsapOpenDbObject(SecretsObject,
+                              SecretName->Buffer,
+                              LsaDbSecretObject,
+                              DesiredAccess,
+                              &SecretObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapOpenDbObject (Secret) failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+done:
+    if (!NT_SUCCESS(Status))
+    {
+        if (SecretObject != NULL)
+            LsapCloseDbObject(SecretObject);
+    }
+    else
+    {
+        *SecretHandle = (LSAPR_HANDLE)SecretObject;
+    }
+
+    if (SecretsObject != NULL)
+        LsapCloseDbObject(SecretsObject);
+
+    return STATUS_SUCCESS;
 }
 
 
 /* Function 29 */
 NTSTATUS WINAPI LsarSetSecret(
-    LSAPR_HANDLE *SecretHandle,
+    LSAPR_HANDLE SecretHandle,
     PLSAPR_CR_CIPHER_VALUE EncryptedCurrentValue,
     PLSAPR_CR_CIPHER_VALUE EncryptedOldValue)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PLSA_DB_OBJECT SecretObject;
+    PBYTE CurrentValue = NULL;
+    PBYTE OldValue = NULL;
+    ULONG CurrentValueLength = 0;
+    ULONG OldValueLength = 0;
+    LARGE_INTEGER Time;
+    NTSTATUS Status;
+
+    TRACE("LsarSetSecret(%p %p %p)\n", SecretHandle,
+          EncryptedCurrentValue, EncryptedOldValue);
+
+    /* Validate the SecretHandle */
+    Status = LsapValidateDbObject(SecretHandle,
+                                  LsaDbSecretObject,
+                                  SECRET_SET_VALUE,
+                                  &SecretObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapValidateDbObject returned 0x%08lx\n", Status);
+        return Status;
+    }
+
+    if (EncryptedCurrentValue != NULL)
+    {
+        /* FIXME: Decrypt the current value */
+        CurrentValue = EncryptedCurrentValue->Buffer;
+        CurrentValueLength = EncryptedCurrentValue->MaximumLength;
+    }
+
+    /* Set the current value */
+    Status = LsapSetObjectAttribute(SecretObject,
+                                    L"CurrentValue",
+                                    CurrentValue,
+                                    CurrentValueLength);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapSetObjectAttribute failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Get the current time */
+    Status = NtQuerySystemTime(&Time);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("NtQuerySystemTime failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Set the current time */
+    Status = LsapSetObjectAttribute(SecretObject,
+                                    L"CurrentTime",
+                                    &Time,
+                                    sizeof(LARGE_INTEGER));
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapSetObjectAttribute failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    if (EncryptedOldValue != NULL)
+    {
+        /* FIXME: Decrypt the old value */
+        OldValue = EncryptedOldValue->Buffer;
+        OldValueLength = EncryptedOldValue->MaximumLength;
+    }
+
+    /* Set the old value */
+    Status = LsapSetObjectAttribute(SecretObject,
+                                    L"OldValue",
+                                    OldValue,
+                                    OldValueLength);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapSetObjectAttribute failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
+
+    /* Set the old time */
+    Status = LsapSetObjectAttribute(SecretObject,
+                                    L"OldTime",
+                                    &Time,
+                                    sizeof(LARGE_INTEGER));
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapSetObjectAttribute failed (Status 0x%08lx)\n", Status);
+    }
+
+done:
+    return Status;
 }
 
 
@@ -759,8 +1394,175 @@ NTSTATUS WINAPI LsarQuerySecret(
     PLSAPR_CR_CIPHER_VALUE *EncryptedOldValue,
     PLARGE_INTEGER OldValueSetTime)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PLSA_DB_OBJECT SecretObject;
+    PLSAPR_CR_CIPHER_VALUE EncCurrentValue = NULL;
+    PLSAPR_CR_CIPHER_VALUE EncOldValue = NULL;
+    PBYTE CurrentValue = NULL;
+    PBYTE OldValue = NULL;
+    ULONG CurrentValueLength = 0;
+    ULONG OldValueLength = 0;
+    ULONG BufferSize;
+    NTSTATUS Status;
+
+    TRACE("LsarQuerySecret(%p %p %p %p %p)\n", SecretHandle,
+          EncryptedCurrentValue, CurrentValueSetTime,
+          EncryptedOldValue, OldValueSetTime);
+
+    /* Validate the SecretHandle */
+    Status = LsapValidateDbObject(SecretHandle,
+                                  LsaDbSecretObject,
+                                  SECRET_QUERY_VALUE,
+                                  &SecretObject);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapValidateDbObject returned 0x%08lx\n", Status);
+        return Status;
+    }
+
+    if (EncryptedCurrentValue != NULL)
+    {
+        CurrentValueLength = 0;
+
+        /* Get the size of the current value */
+        Status = LsapGetObjectAttribute(SecretObject,
+                                        L"CurrentValue",
+                                        NULL,
+                                        &CurrentValueLength);
+        if (!NT_SUCCESS(Status))
+            goto done;
+
+        /* Allocate a buffer for the current value */
+        CurrentValue = midl_user_allocate(CurrentValueLength);
+        if (CurrentValue == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto done;
+        }
+
+        /* Get the current value */
+        Status = LsapGetObjectAttribute(SecretObject,
+                                        L"CurrentValue",
+                                        CurrentValue,
+                                        &CurrentValueLength);
+        if (!NT_SUCCESS(Status))
+            goto done;
+
+        /* Allocate a buffer for the encrypted current value */
+        EncCurrentValue = midl_user_allocate(sizeof(LSAPR_CR_CIPHER_VALUE));
+        if (EncCurrentValue == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto done;
+        }
+
+        /* FIXME: Encrypt the current value */
+        EncCurrentValue->Length = (USHORT)(CurrentValueLength - sizeof(WCHAR));
+        EncCurrentValue->MaximumLength = (USHORT)CurrentValueLength;
+        EncCurrentValue->Buffer = (PBYTE)CurrentValue;
+    }
+
+    if (CurrentValueSetTime != NULL)
+    {
+        BufferSize = sizeof(LARGE_INTEGER);
+
+        /* Get the current value time */
+        Status = LsapGetObjectAttribute(SecretObject,
+                                        L"CurrentTime",
+                                        (PBYTE)CurrentValueSetTime,
+                                        &BufferSize);
+        if (!NT_SUCCESS(Status))
+            goto done;
+    }
+
+    if (EncryptedOldValue != NULL)
+    {
+        OldValueLength = 0;
+
+        /* Get the size of the old value */
+        Status = LsapGetObjectAttribute(SecretObject,
+                                        L"OldValue",
+                                        NULL,
+                                        &OldValueLength);
+        if (!NT_SUCCESS(Status))
+            goto done;
+
+        /* Allocate a buffer for the old value */
+        OldValue = midl_user_allocate(OldValueLength);
+        if (OldValue == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto done;
+        }
+
+        /* Get the old value */
+        Status = LsapGetObjectAttribute(SecretObject,
+                                        L"OldValue",
+                                        OldValue,
+                                        &OldValueLength);
+        if (!NT_SUCCESS(Status))
+            goto done;
+
+        /* Allocate a buffer for the encrypted old value */
+        EncOldValue = midl_user_allocate(sizeof(LSAPR_CR_CIPHER_VALUE) + OldValueLength);
+        if (EncOldValue == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto done;
+        }
+
+        /* FIXME: Encrypt the old value */
+        EncOldValue->Length = (USHORT)(OldValueLength - sizeof(WCHAR));
+        EncOldValue->MaximumLength = (USHORT)OldValueLength;
+        EncOldValue->Buffer = (PBYTE)OldValue;
+    }
+
+    if (OldValueSetTime != NULL)
+    {
+        BufferSize = sizeof(LARGE_INTEGER);
+
+        /* Get the old value time */
+        Status = LsapGetObjectAttribute(SecretObject,
+                                        L"OldTime",
+                                        (PBYTE)OldValueSetTime,
+                                        &BufferSize);
+        if (!NT_SUCCESS(Status))
+            goto done;
+    }
+
+
+done:
+    if (NT_SUCCESS(Status))
+    {
+        if (EncryptedCurrentValue != NULL)
+            *EncryptedCurrentValue = EncCurrentValue;
+
+        if (EncryptedOldValue != NULL)
+            *EncryptedOldValue = EncOldValue;
+    }
+    else
+    {
+        if (EncryptedCurrentValue != NULL)
+            *EncryptedCurrentValue = NULL;
+
+        if (EncryptedOldValue != NULL)
+            *EncryptedOldValue = NULL;
+
+        if (EncCurrentValue != NULL)
+            midl_user_free(EncCurrentValue);
+
+        if (EncOldValue != NULL)
+            midl_user_free(EncOldValue);
+
+        if (CurrentValue != NULL)
+            midl_user_free(CurrentValue);
+
+        if (OldValue != NULL)
+            midl_user_free(OldValue);
+    }
+
+    TRACE("LsarQuerySecret done (Status 0x%08lx)\n", Status);
+
+    return Status;
 }
 
 
@@ -777,7 +1579,8 @@ NTSTATUS WINAPI LsarLookupPrivilegeValue(
 
     Status = LsapValidateDbObject(PolicyHandle,
                                   LsaDbPolicyObject,
-                                  0); /* FIXME */
+                                  POLICY_LOOKUP_NAMES,
+                                  NULL);
     if (!NT_SUCCESS(Status))
     {
         ERR("Invalid handle (Status %lx)\n", Status);
@@ -806,7 +1609,8 @@ NTSTATUS WINAPI LsarLookupPrivilegeName(
 
     Status = LsapValidateDbObject(PolicyHandle,
                                   LsaDbPolicyObject,
-                                  0); /* FIXME */
+                                  POLICY_LOOKUP_NAMES,
+                                  NULL);
     if (!NT_SUCCESS(Status))
     {
         ERR("Invalid handle\n");
@@ -859,13 +1663,15 @@ NTSTATUS WINAPI LsarEnmuerateAccountRights(
     PRPC_SID AccountSid,
     PLSAPR_USER_RIGHT_SET UserRights)
 {
+    PLSA_DB_OBJECT PolicyObject;
     NTSTATUS Status;
 
     FIXME("(%p,%p,%p) stub\n", PolicyHandle, AccountSid, UserRights);
 
     Status = LsapValidateDbObject(PolicyHandle,
                                   LsaDbPolicyObject,
-                                  0); /* FIXME */
+                                  ACCOUNT_VIEW,
+                                  &PolicyObject);
     if (!NT_SUCCESS(Status))
         return Status;
 
@@ -981,10 +1787,11 @@ NTSTATUS WINAPI LsarGetUserName(
 NTSTATUS WINAPI LsarQueryInformationPolicy2(
     LSAPR_HANDLE PolicyHandle,
     POLICY_INFORMATION_CLASS InformationClass,
-    unsigned long *PolicyInformation)
+    PLSAPR_POLICY_INFORMATION *PolicyInformation)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    return LsarQueryInformationPolicy(PolicyHandle,
+                                      InformationClass,
+                                      PolicyInformation);
 }
 
 
@@ -992,10 +1799,11 @@ NTSTATUS WINAPI LsarQueryInformationPolicy2(
 NTSTATUS WINAPI LsarSetInformationPolicy2(
     LSAPR_HANDLE PolicyHandle,
     POLICY_INFORMATION_CLASS InformationClass,
-    unsigned long PolicyInformation)
+    PLSAPR_POLICY_INFORMATION PolicyInformation)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    return LsarSetInformationPolicy(PolicyHandle,
+                                    InformationClass,
+                                    PolicyInformation);
 }