[SAMSRV]
[reactos.git] / reactos / dll / win32 / samsrv / samrpc.c
index e0df244..0538f60 100644 (file)
@@ -145,6 +145,9 @@ SamrConnect(IN PSAMPR_SERVER_NAME ServerName,
     TRACE("SamrConnect(%p %p %lx)\n",
           ServerName, ServerHandle, DesiredAccess);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Map generic access rights */
     RtlMapGenericMask(&DesiredAccess,
                       &ServerMapping);
@@ -160,6 +163,8 @@ SamrConnect(IN PSAMPR_SERVER_NAME ServerName,
     if (NT_SUCCESS(Status))
         *ServerHandle = (SAMPR_HANDLE)ServerObject;
 
+    RtlReleaseResource(&SampResource);
+
     TRACE("SamrConnect done (Status 0x%08lx)\n", Status);
 
     return Status;
@@ -176,6 +181,9 @@ SamrCloseHandle(IN OUT SAMPR_HANDLE *SamHandle)
 
     TRACE("SamrCloseHandle(%p)\n", SamHandle);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     Status = SampValidateDbObject(*SamHandle,
                                   SamDbIgnoreObject,
                                   0,
@@ -186,6 +194,8 @@ SamrCloseHandle(IN OUT SAMPR_HANDLE *SamHandle)
         *SamHandle = NULL;
     }
 
+    RtlReleaseResource(&SampResource);
+
     TRACE("SamrCloseHandle done (Status 0x%08lx)\n", Status);
 
     return Status;
@@ -226,11 +236,17 @@ SamrShutdownSamServer(IN SAMPR_HANDLE ServerHandle)
 
     TRACE("(%p)\n", ServerHandle);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the server handle */
     Status = SampValidateDbObject(ServerHandle,
                                   SamDbServerObject,
                                   SAM_SERVER_SHUTDOWN,
                                   &ServerObject);
+
+    RtlReleaseResource(&SampResource);
+
     if (!NT_SUCCESS(Status))
         return Status;
 
@@ -262,13 +278,16 @@ SamrLookupDomainInSamServer(IN SAMPR_HANDLE ServerHandle,
     TRACE("SamrLookupDomainInSamServer(%p %p %p)\n",
           ServerHandle, Name, DomainId);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the server handle */
     Status = SampValidateDbObject(ServerHandle,
                                   SamDbServerObject,
                                   SAM_SERVER_LOOKUP_DOMAIN,
                                   &ServerObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     *DomainId = NULL;
 
@@ -277,7 +296,7 @@ SamrLookupDomainInSamServer(IN SAMPR_HANDLE ServerHandle,
                             KEY_READ,
                             &DomainsKeyHandle);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     Index = 0;
     while (Found == FALSE)
@@ -339,13 +358,17 @@ SamrLookupDomainInSamServer(IN SAMPR_HANDLE ServerHandle,
                 }
             }
 
-            NtClose(DomainKeyHandle);
+            SampRegCloseKey(&DomainKeyHandle);
         }
 
         Index++;
     }
 
-    NtClose(DomainsKeyHandle);
+done:
+    SampRegCloseKey(&DomainKeyHandle);
+    SampRegCloseKey(&DomainsKeyHandle);
+
+    RtlReleaseResource(&SampResource);
 
     return Status;
 }
@@ -362,8 +385,8 @@ SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle,
 {
     PSAM_DB_OBJECT ServerObject;
     WCHAR DomainKeyName[64];
-    HANDLE DomainsKeyHandle;
-    HANDLE DomainKeyHandle;
+    HANDLE DomainsKeyHandle = NULL;
+    HANDLE DomainKeyHandle = NULL;
     ULONG EnumIndex;
     ULONG EnumCount;
     ULONG RequiredLength;
@@ -376,20 +399,23 @@ SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle,
           ServerHandle, EnumerationContext, Buffer, PreferedMaximumLength,
           CountReturned);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the server handle */
     Status = SampValidateDbObject(ServerHandle,
                                   SamDbServerObject,
                                   SAM_SERVER_ENUMERATE_DOMAINS,
                                   &ServerObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     Status = SampRegOpenKey(ServerObject->KeyHandle,
                             L"Domains",
                             KEY_READ,
                             &DomainsKeyHandle);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     EnumIndex = *EnumerationContext;
     EnumCount = 0;
@@ -432,7 +458,7 @@ SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle,
                 EnumCount++;
             }
 
-            NtClose(DomainKeyHandle);
+            SampRegCloseKey(&DomainKeyHandle);
         }
 
         EnumIndex++;
@@ -491,7 +517,7 @@ SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle,
                 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(DataLength);
                 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
                 {
-                    NtClose(DomainKeyHandle);
+                    SampRegCloseKey(&DomainKeyHandle);
                     Status = STATUS_INSUFFICIENT_RESOURCES;
                     goto done;
                 }
@@ -508,7 +534,7 @@ SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle,
                 }
             }
 
-            NtClose(DomainKeyHandle);
+            SampRegCloseKey(&DomainKeyHandle);
 
             if (!NT_SUCCESS(Status))
                 goto done;
@@ -523,6 +549,9 @@ SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle,
     }
 
 done:
+    SampRegCloseKey(&DomainKeyHandle);
+    SampRegCloseKey(&DomainsKeyHandle);
+
     if (!NT_SUCCESS(Status))
     {
         *EnumerationContext = 0;
@@ -549,7 +578,7 @@ done:
         }
     }
 
-    NtClose(DomainsKeyHandle);
+    RtlReleaseResource(&SampResource);
 
     return Status;
 }
@@ -574,6 +603,9 @@ SamrOpenDomain(IN SAMPR_HANDLE ServerHandle,
     RtlMapGenericMask(&DesiredAccess,
                       &DomainMapping);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the server handle */
     Status = SampValidateDbObject(ServerHandle,
                                   SamDbServerObject,
@@ -628,6 +660,8 @@ SamrOpenDomain(IN SAMPR_HANDLE ServerHandle,
     if (NT_SUCCESS(Status))
         *DomainHandle = (SAMPR_HANDLE)DomainObject;
 
+    RtlReleaseResource(&SampResource);
+
     TRACE("SamrOpenDomain done (Status 0x%08lx)\n", Status);
 
     return Status;
@@ -709,12 +743,10 @@ SampGetNumberOfAccounts(PSAM_DB_OBJECT DomainObject,
     Status = SampRegQueryKeyInfo(NamesKeyHandle,
                                  NULL,
                                  Count);
-done:
-    if (NamesKeyHandle != NULL)
-        SampRegCloseKey(NamesKeyHandle);
 
-    if (AccountKeyHandle != NULL)
-        SampRegCloseKey(AccountKeyHandle);
+done:
+    SampRegCloseKey(&NamesKeyHandle);
+    SampRegCloseKey(&AccountKeyHandle);
 
     return Status;
 }
@@ -1378,13 +1410,16 @@ SamrQueryInformationDomain(IN SAMPR_HANDLE DomainHandle,
             return STATUS_INVALID_INFO_CLASS;
     }
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the server handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
                                   DesiredAccess,
                                   &DomainObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     switch (DomainInformationClass)
     {
@@ -1452,6 +1487,9 @@ SamrQueryInformationDomain(IN SAMPR_HANDLE DomainHandle,
             Status = STATUS_NOT_IMPLEMENTED;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -1652,13 +1690,16 @@ SamrSetInformationDomain(IN SAMPR_HANDLE DomainHandle,
             return STATUS_INVALID_INFO_CLASS;
     }
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the server handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
                                   DesiredAccess,
                                   &DomainObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     switch (DomainInformationClass)
     {
@@ -1673,27 +1714,21 @@ SamrSetInformationDomain(IN SAMPR_HANDLE DomainHandle,
             break;
 
         case DomainOemInformation:
-            Status = SampSetObjectAttribute(DomainObject,
-                                            L"OemInformation",
-                                            REG_SZ,
-                                            DomainInformation->Oem.OemInformation.Buffer,
-                                            DomainInformation->Oem.OemInformation.Length + sizeof(WCHAR));
+            Status = SampSetObjectAttributeString(DomainObject,
+                                                  L"OemInformation",
+                                                  &DomainInformation->Oem.OemInformation);
             break;
 
         case DomainNameInformation:
-            Status = SampSetObjectAttribute(DomainObject,
-                                            L"Name",
-                                            REG_SZ,
-                                            DomainInformation->Name.DomainName.Buffer,
-                                            DomainInformation->Name.DomainName.Length + sizeof(WCHAR));
+            Status = SampSetObjectAttributeString(DomainObject,
+                                                  L"Name",
+                                                  &DomainInformation->Name.DomainName);
             break;
 
         case DomainReplicationInformation:
-            Status = SampSetObjectAttribute(DomainObject,
-                                            L"ReplicaSourceNodeName",
-                                            REG_SZ,
-                                            DomainInformation->Replication.ReplicaSourceNodeName.Buffer,
-                                            DomainInformation->Replication.ReplicaSourceNodeName.Length + sizeof(WCHAR));
+            Status = SampSetObjectAttributeString(DomainObject,
+                                                  L"ReplicaSourceNodeName",
+                                                  &DomainInformation->Replication.ReplicaSourceNodeName);
             break;
 
         case DomainServerRoleInformation:
@@ -1715,6 +1750,9 @@ SamrSetInformationDomain(IN SAMPR_HANDLE DomainHandle,
             Status = STATUS_NOT_IMPLEMENTED;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -1728,7 +1766,6 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
                         OUT SAMPR_HANDLE *GroupHandle,
                         OUT unsigned long *RelativeId)
 {
-    UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
     SAM_DOMAIN_FIXED_DATA FixedDomainData;
     SAM_GROUP_FIXED_DATA FixedGroupData;
     PSAM_DB_OBJECT DomainObject;
@@ -1745,6 +1782,9 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
     RtlMapGenericMask(&DesiredAccess,
                       &GroupMapping);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
@@ -1753,7 +1793,7 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Check the group account name */
@@ -1761,7 +1801,7 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Check if the group name already exists in the domain */
@@ -1771,7 +1811,7 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
     {
         TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n",
               Name->Buffer, Status);
-        return Status;
+        goto done;
     }
 
     /* Get the fixed domain attributes */
@@ -1784,7 +1824,7 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Increment the NextRid attribute */
@@ -1793,14 +1833,14 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
 
     /* Store the fixed domain attributes */
     Status = SampSetObjectAttribute(DomainObject,
-                           L"F",
-                           REG_BINARY,
-                           &FixedDomainData,
-                           ulSize);
+                                    L"F",
+                                    REG_BINARY,
+                                    &FixedDomainData,
+                                    ulSize);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     TRACE("RID: %lx\n", ulRid);
@@ -1819,7 +1859,7 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Add the account name of the user object */
@@ -1830,13 +1870,12 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Initialize fixed user data */
     memset(&FixedGroupData, 0, sizeof(SAM_GROUP_FIXED_DATA));
     FixedGroupData.Version = 1;
-
     FixedGroupData.GroupId = ulRid;
 
     /* Set fixed user data attribute */
@@ -1848,31 +1887,27 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the Name attribute */
-    Status = SampSetObjectAttribute(GroupObject,
-                                    L"Name",
-                                    REG_SZ,
-                                    (LPVOID)Name->Buffer,
-                                    Name->MaximumLength);
+    Status = SampSetObjectAttributeString(GroupObject,
+                                          L"Name",
+                                          Name);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the AdminComment attribute */
-    Status = SampSetObjectAttribute(GroupObject,
-                                    L"AdminComment",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(GroupObject,
+                                          L"AdminComment",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     if (NT_SUCCESS(Status))
@@ -1881,6 +1916,9 @@ SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
         *RelativeId = ulRid;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     TRACE("returns with status 0x%08lx\n", Status);
 
     return Status;
@@ -1915,20 +1953,23 @@ SamrEnumerateGroupsInDomain(IN SAMPR_HANDLE DomainHandle,
           DomainHandle, EnumerationContext, Buffer,
           PreferedMaximumLength, CountReturned);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
                                   DOMAIN_LIST_ACCOUNTS,
                                   &DomainObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     Status = SampRegOpenKey(DomainObject->KeyHandle,
                             L"Groups",
                             KEY_READ,
                             &GroupsKeyHandle);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     Status = SampRegOpenKey(GroupsKeyHandle,
                             L"Names",
@@ -2077,15 +2118,14 @@ done:
         }
     }
 
-    if (NamesKeyHandle != NULL)
-        SampRegCloseKey(NamesKeyHandle);
-
-    if (GroupsKeyHandle != NULL)
-        SampRegCloseKey(GroupsKeyHandle);
+    SampRegCloseKey(&NamesKeyHandle);
+    SampRegCloseKey(&GroupsKeyHandle);
 
     if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
         Status = STATUS_MORE_ENTRIES;
 
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -2099,7 +2139,6 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
                        OUT SAMPR_HANDLE *UserHandle,
                        OUT unsigned long *RelativeId)
 {
-    UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
     SAM_DOMAIN_FIXED_DATA FixedDomainData;
     SAM_USER_FIXED_DATA FixedUserData;
     PSAM_DB_OBJECT DomainObject;
@@ -2125,6 +2164,9 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     RtlMapGenericMask(&DesiredAccess,
                       &UserMapping);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
@@ -2133,7 +2175,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Check the user account name */
@@ -2141,7 +2183,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Check if the user name already exists in the domain */
@@ -2151,7 +2193,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     {
         TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
               Name->Buffer, Status);
-        return Status;
+        goto done;
     }
 
     /* Get the fixed domain attributes */
@@ -2164,7 +2206,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Increment the NextRid attribute */
@@ -2180,7 +2222,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     TRACE("RID: %lx\n", ulRid);
@@ -2199,7 +2241,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Add the account name for the user object */
@@ -2210,7 +2252,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Initialize fixed user data */
@@ -2244,127 +2286,107 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the Name attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"Name",
-                                    REG_SZ,
-                                    (LPVOID)Name->Buffer,
-                                    Name->MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"Name",
+                                          Name);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the FullName attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"FullName",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"FullName",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the HomeDirectory attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"HomeDirectory",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"HomeDirectory",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the HomeDirectoryDrive attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"HomeDirectoryDrive",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"HomeDirectoryDrive",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the ScriptPath attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"ScriptPath",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"ScriptPath",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the ProfilePath attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"ProfilePath",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"ProfilePath",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the AdminComment attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"AdminComment",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"AdminComment",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the UserComment attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"UserComment",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"UserComment",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the WorkStations attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"WorkStations",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"WorkStations",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the Parameters attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"Parameters",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"Parameters",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set LogonHours attribute*/
@@ -2379,7 +2401,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set Groups attribute*/
@@ -2396,7 +2418,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set LMPwd attribute*/
@@ -2408,7 +2430,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set NTPwd attribute*/
@@ -2420,7 +2442,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set LMPwdHistory attribute*/
@@ -2432,7 +2454,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set NTPwdHistory attribute*/
@@ -2444,7 +2466,7 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* FIXME: Set SecDesc attribute*/
@@ -2455,6 +2477,9 @@ SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
         *RelativeId = ulRid;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     TRACE("returns with status 0x%08lx\n", Status);
 
     return Status;
@@ -2490,20 +2515,23 @@ SamrEnumerateUsersInDomain(IN SAMPR_HANDLE DomainHandle,
           DomainHandle, EnumerationContext, UserAccountControl, Buffer,
           PreferedMaximumLength, CountReturned);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
                                   DOMAIN_LIST_ACCOUNTS,
                                   &DomainObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     Status = SampRegOpenKey(DomainObject->KeyHandle,
                             L"Users",
                             KEY_READ,
                             &UsersKeyHandle);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     Status = SampRegOpenKey(UsersKeyHandle,
                             L"Names",
@@ -2652,15 +2680,14 @@ done:
         }
     }
 
-    if (NamesKeyHandle != NULL)
-        SampRegCloseKey(NamesKeyHandle);
-
-    if (UsersKeyHandle != NULL)
-        SampRegCloseKey(UsersKeyHandle);
+    SampRegCloseKey(&NamesKeyHandle);
+    SampRegCloseKey(&UsersKeyHandle);
 
     if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
         Status = STATUS_MORE_ENTRIES;
 
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -2677,7 +2704,6 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
     SAM_DOMAIN_FIXED_DATA FixedDomainData;
     PSAM_DB_OBJECT DomainObject;
     PSAM_DB_OBJECT AliasObject;
-    UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
     ULONG ulSize;
     ULONG ulRid;
     WCHAR szRid[9];
@@ -2690,6 +2716,9 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
     RtlMapGenericMask(&DesiredAccess,
                       &AliasMapping);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
@@ -2698,7 +2727,7 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Check the alias acoount name */
@@ -2706,7 +2735,7 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Check if the alias name already exists in the domain */
@@ -2716,7 +2745,7 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
     {
         TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n",
               AccountName->Buffer, Status);
-        return Status;
+        goto done;
     }
 
     /* Get the fixed domain attributes */
@@ -2729,7 +2758,7 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Increment the NextRid attribute */
@@ -2745,7 +2774,7 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     TRACE("RID: %lx\n", ulRid);
@@ -2764,7 +2793,7 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Add the account name for the alias object */
@@ -2775,31 +2804,27 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the Name attribute */
-    Status = SampSetObjectAttribute(AliasObject,
-                                    L"Name",
-                                    REG_SZ,
-                                    (LPVOID)AccountName->Buffer,
-                                    AccountName->MaximumLength);
+    Status = SampSetObjectAttributeString(AliasObject,
+                                          L"Name",
+                                          AccountName);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the Description attribute */
-    Status = SampSetObjectAttribute(AliasObject,
-                                    L"Description",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(AliasObject,
+                                          L"Description",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     if (NT_SUCCESS(Status))
@@ -2808,6 +2833,9 @@ SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
         *RelativeId = ulRid;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     TRACE("returns with status 0x%08lx\n", Status);
 
     return Status;
@@ -2842,20 +2870,23 @@ SamrEnumerateAliasesInDomain(IN SAMPR_HANDLE DomainHandle,
           DomainHandle, EnumerationContext, Buffer,
           PreferedMaximumLength, CountReturned);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
                                   DOMAIN_LIST_ACCOUNTS,
                                   &DomainObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     Status = SampRegOpenKey(DomainObject->KeyHandle,
                             L"Aliases",
                             KEY_READ,
                             &AliasesKeyHandle);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     Status = SampRegOpenKey(AliasesKeyHandle,
                             L"Names",
@@ -3004,15 +3035,14 @@ done:
         }
     }
 
-    if (NamesKeyHandle != NULL)
-        SampRegCloseKey(NamesKeyHandle);
-
-    if (AliasesKeyHandle != NULL)
-        SampRegCloseKey(AliasesKeyHandle);
+    SampRegCloseKey(&NamesKeyHandle);
+    SampRegCloseKey(&AliasesKeyHandle);
 
     if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
         Status = STATUS_MORE_ENTRIES;
 
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -3040,13 +3070,16 @@ SamrGetAliasMembership(IN SAMPR_HANDLE DomainHandle,
     TRACE("SamrGetAliasMembership(%p %p %p)\n",
           DomainHandle, SidArray, Membership);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
                                   DOMAIN_GET_ALIAS_MEMBERSHIP,
                                   &DomainObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     Status = SampRegOpenKey(DomainObject->KeyHandle,
                             L"Aliases",
@@ -3092,7 +3125,7 @@ TRACE("Open %S\n", MemberSidString);
                 MaxSidCount += ValueCount;
             }
 
-            NtClose(MemberKeyHandle);
+            SampRegCloseKey(&MemberKeyHandle);
         }
 
         if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
@@ -3151,13 +3184,17 @@ TRACE("Open %S\n", MemberSidString);
                 }
             }
 
-            NtClose(MemberKeyHandle);
+            SampRegCloseKey(&MemberKeyHandle);
         }
 
         LocalFree(MemberSidString);
     }
 
 done:
+    SampRegCloseKey(&MembersKeyHandle);
+    SampRegCloseKey(&MembersKeyHandle);
+    SampRegCloseKey(&AliasesKeyHandle);
+
     if (NT_SUCCESS(Status))
     {
         Membership->Count = MaxSidCount;
@@ -3169,14 +3206,7 @@ done:
             midl_user_free(RidArray);
     }
 
-    if (MembersKeyHandle != NULL)
-        NtClose(MembersKeyHandle);
-
-    if (MembersKeyHandle != NULL)
-        NtClose(MembersKeyHandle);
-
-    if (AliasesKeyHandle != NULL)
-        NtClose(AliasesKeyHandle);
+    RtlReleaseResource(&SampResource);
 
     return Status;
 }
@@ -3192,8 +3222,8 @@ SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
                         OUT PSAMPR_ULONG_ARRAY Use)
 {
     PSAM_DB_OBJECT DomainObject;
-    HANDLE AccountsKeyHandle;
-    HANDLE NamesKeyHandle;
+    HANDLE AccountsKeyHandle = NULL;
+    HANDLE NamesKeyHandle = NULL;
     ULONG MappedCount = 0;
     ULONG DataLength;
     ULONG i;
@@ -3203,6 +3233,9 @@ SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
     TRACE("SamrLookupNamesInDomain(%p %lu %p %p %p)\n",
           DomainHandle, Count, Names, RelativeIds, Use);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
@@ -3211,14 +3244,17 @@ SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     RelativeIds->Count = 0;
     Use->Count = 0;
 
     if (Count == 0)
-        return STATUS_SUCCESS;
+    {
+        Status = STATUS_SUCCESS;
+        goto done;
+    }
 
     /* Allocate the relative IDs array */
     RelativeIds->Element = midl_user_allocate(Count * sizeof(ULONG));
@@ -3265,10 +3301,10 @@ SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
                                            &RelativeId,
                                            &DataLength);
 
-                SampRegCloseKey(NamesKeyHandle);
+                SampRegCloseKey(&NamesKeyHandle);
             }
 
-            SampRegCloseKey(AccountsKeyHandle);
+            SampRegCloseKey(&AccountsKeyHandle);
         }
 
         if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
@@ -3304,10 +3340,10 @@ SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
                                            &RelativeId,
                                            &DataLength);
 
-                SampRegCloseKey(NamesKeyHandle);
+                SampRegCloseKey(&NamesKeyHandle);
             }
 
-            SampRegCloseKey(AccountsKeyHandle);
+            SampRegCloseKey(&AccountsKeyHandle);
         }
 
         if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
@@ -3343,10 +3379,10 @@ SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
                                            &RelativeId,
                                            &DataLength);
 
-                SampRegCloseKey(NamesKeyHandle);
+                SampRegCloseKey(&NamesKeyHandle);
             }
 
-            SampRegCloseKey(AccountsKeyHandle);
+            SampRegCloseKey(&AccountsKeyHandle);
         }
 
         if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
@@ -3397,6 +3433,8 @@ done:
         Use->Count = 0;
     }
 
+    RtlReleaseResource(&SampResource);
+
     TRACE("Returned Status %lx\n", Status);
 
     return Status;
@@ -3414,8 +3452,8 @@ SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
 {
     PSAM_DB_OBJECT DomainObject;
     WCHAR RidString[9];
-    HANDLE AccountsKeyHandle;
-    HANDLE AccountKeyHandle;
+    HANDLE AccountsKeyHandle = NULL;
+    HANDLE AccountKeyHandle = NULL;
     ULONG MappedCount = 0;
     ULONG DataLength;
     ULONG i;
@@ -3424,6 +3462,9 @@ SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
     TRACE("SamrLookupIdsInDomain(%p %lu %p %p %p)\n",
           DomainHandle, Count, RelativeIds, Names, Use);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
@@ -3432,14 +3473,17 @@ SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     Names->Count = 0;
     Use->Count = 0;
 
     if (Count == 0)
-        return STATUS_SUCCESS;
+    {
+        Status = STATUS_SUCCESS;
+        goto done;
+    }
 
     /* Allocate the names array */
     Names->Element = midl_user_allocate(Count * sizeof(ULONG));
@@ -3504,10 +3548,10 @@ SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
                     }
                 }
 
-                SampRegCloseKey(AccountKeyHandle);
+                SampRegCloseKey(&AccountKeyHandle);
             }
 
-            SampRegCloseKey(AccountsKeyHandle);
+            SampRegCloseKey(&AccountsKeyHandle);
         }
 
         if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
@@ -3560,10 +3604,10 @@ SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
                     }
                 }
 
-                SampRegCloseKey(AccountKeyHandle);
+                SampRegCloseKey(&AccountKeyHandle);
             }
 
-            SampRegCloseKey(AccountsKeyHandle);
+            SampRegCloseKey(&AccountsKeyHandle);
         }
 
         if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
@@ -3618,10 +3662,10 @@ SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
                     }
                 }
 
-                SampRegCloseKey(AccountKeyHandle);
+                SampRegCloseKey(&AccountKeyHandle);
             }
 
-            SampRegCloseKey(AccountsKeyHandle);
+            SampRegCloseKey(&AccountsKeyHandle);
         }
 
         if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
@@ -3676,6 +3720,8 @@ done:
         Use->Count = 0;
     }
 
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -3700,6 +3746,9 @@ SamrOpenGroup(IN SAMPR_HANDLE DomainHandle,
     RtlMapGenericMask(&DesiredAccess,
                       &GroupMapping);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
@@ -3708,7 +3757,7 @@ SamrOpenGroup(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Convert the RID into a string (hex) */
@@ -3725,12 +3774,15 @@ SamrOpenGroup(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     *GroupHandle = (SAMPR_HANDLE)GroupObject;
 
-    return STATUS_SUCCESS;
+done:
+    RtlReleaseResource(&SampResource);
+
+    return Status;
 }
 
 
@@ -3947,13 +3999,16 @@ SamrQueryInformationGroup(IN SAMPR_HANDLE GroupHandle,
     TRACE("SamrQueryInformationGroup(%p %lu %p)\n",
           GroupHandle, GroupInformationClass, Buffer);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the group handle */
     Status = SampValidateDbObject(GroupHandle,
                                   SamDbGroupObject,
                                   GROUP_READ_INFORMATION,
                                   &GroupObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     switch (GroupInformationClass)
     {
@@ -3982,6 +4037,9 @@ SamrQueryInformationGroup(IN SAMPR_HANDLE GroupHandle,
             break;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -4046,11 +4104,9 @@ SampSetGroupName(PSAM_DB_OBJECT GroupObject,
         goto done;
     }
 
-    Status = SampSetObjectAttribute(GroupObject,
-                                    L"Name",
-                                    REG_SZ,
-                                    NewGroupName.Buffer,
-                                    NewGroupName.Length + sizeof(WCHAR));
+    Status = SampSetObjectAttributeString(GroupObject,
+                                          L"Name",
+                                          (PRPC_UNICODE_STRING)&NewGroupName);
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
@@ -4107,13 +4163,16 @@ SamrSetInformationGroup(IN SAMPR_HANDLE GroupHandle,
     TRACE("SamrSetInformationGroup(%p %lu %p)\n",
           GroupHandle, GroupInformationClass, Buffer);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the group handle */
     Status = SampValidateDbObject(GroupHandle,
                                   SamDbGroupObject,
                                   GROUP_WRITE_ACCOUNT,
                                   &GroupObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     switch (GroupInformationClass)
     {
@@ -4128,11 +4187,9 @@ SamrSetInformationGroup(IN SAMPR_HANDLE GroupHandle,
             break;
 
         case GroupAdminCommentInformation:
-            Status = SampSetObjectAttribute(GroupObject,
-                                            L"Description",
-                                            REG_SZ,
-                                            Buffer->AdminComment.AdminComment.Buffer,
-                                            Buffer->AdminComment.AdminComment.Length + sizeof(WCHAR));
+            Status = SampSetObjectAttributeString(GroupObject,
+                                                  L"Description",
+                                                  &Buffer->AdminComment.AdminComment);
             break;
 
         default:
@@ -4140,6 +4197,9 @@ SamrSetInformationGroup(IN SAMPR_HANDLE GroupHandle,
             break;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -4158,13 +4218,16 @@ SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle,
     TRACE("(%p %lu %lx)\n",
           GroupHandle, MemberId, Attributes);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the group handle */
     Status = SampValidateDbObject(GroupHandle,
                                   SamDbGroupObject,
                                   GROUP_ADD_MEMBER,
                                   &GroupObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     /* Open the user object in the same domain */
     Status = SampOpenUserObject(GroupObject->ParentObject,
@@ -4199,11 +4262,13 @@ done:
     if (UserObject)
         SampCloseDbObject(UserObject);
 
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
 
-/* Function 21 */
+/* Function 23 */
 NTSTATUS
 NTAPI
 SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
@@ -4214,6 +4279,9 @@ SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
 
     TRACE("(%p)\n", GroupHandle);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the group handle */
     Status = SampValidateDbObject(*GroupHandle,
                                   SamDbGroupObject,
@@ -4222,14 +4290,15 @@ SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Fail, if the group is built-in */
     if (GroupObject->RelativeId < 1000)
     {
         TRACE("You can not delete a special account!\n");
-        return STATUS_SPECIAL_ACCOUNT;
+        Status = STATUS_SPECIAL_ACCOUNT;
+        goto done;
     }
 
     /* Get the length of the Members attribute */
@@ -4243,7 +4312,8 @@ SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
     if (Length != 0)
     {
         TRACE("There are still members in the group!\n");
-        return STATUS_MEMBER_IN_GROUP;
+        Status = STATUS_MEMBER_IN_GROUP;
+        goto done;
     }
 
     /* FIXME: Remove the group from all aliases */
@@ -4253,13 +4323,16 @@ SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Invalidate the handle */
     *GroupHandle = NULL;
 
-    return STATUS_SUCCESS;
+done:
+    RtlReleaseResource(&SampResource);
+
+    return Status;
 }
 
 
@@ -4276,13 +4349,16 @@ SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle,
     TRACE("(%p %lu)\n",
           GroupHandle, MemberId);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the group handle */
     Status = SampValidateDbObject(GroupHandle,
                                   SamDbGroupObject,
                                   GROUP_REMOVE_MEMBER,
                                   &GroupObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     /* Open the user object in the same domain */
     Status = SampOpenUserObject(GroupObject->ParentObject,
@@ -4316,6 +4392,8 @@ done:
     if (UserObject)
         SampCloseDbObject(UserObject);
 
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -4332,17 +4410,23 @@ SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle,
     ULONG i;
     NTSTATUS Status;
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the group handle */
     Status = SampValidateDbObject(GroupHandle,
                                   SamDbGroupObject,
                                   GROUP_LIST_MEMBERS,
                                   &GroupObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     MembersBuffer = midl_user_allocate(sizeof(SAMPR_GET_MEMBERS_BUFFER));
     if (MembersBuffer == NULL)
-        return STATUS_INSUFFICIENT_RESOURCES;
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto done;
+    }
 
     SampGetObjectAttribute(GroupObject,
                            L"Members",
@@ -4358,7 +4442,8 @@ SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle,
 
         *Members = MembersBuffer;
 
-        return STATUS_SUCCESS;
+        Status = STATUS_SUCCESS;
+        goto done;
     }
 
     MembersBuffer->Members = midl_user_allocate(Length);
@@ -4418,6 +4503,8 @@ done:
         }
     }
 
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -4432,6 +4519,9 @@ SamrSetMemberAttributesOfGroup(IN SAMPR_HANDLE GroupHandle,
     PSAM_DB_OBJECT GroupObject;
     NTSTATUS Status;
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the group handle */
     Status = SampValidateDbObject(GroupHandle,
                                   SamDbGroupObject,
@@ -4440,7 +4530,7 @@ SamrSetMemberAttributesOfGroup(IN SAMPR_HANDLE GroupHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     Status = SampSetUserGroupAttributes(GroupObject->ParentObject,
@@ -4452,6 +4542,9 @@ SamrSetMemberAttributesOfGroup(IN SAMPR_HANDLE GroupHandle,
         TRACE("SampSetUserGroupAttributes failed with status 0x%08lx\n", Status);
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -4476,6 +4569,9 @@ SamrOpenAlias(IN SAMPR_HANDLE DomainHandle,
     RtlMapGenericMask(&DesiredAccess,
                       &AliasMapping);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
@@ -4484,7 +4580,7 @@ SamrOpenAlias(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Convert the RID into a string (hex) */
@@ -4501,12 +4597,15 @@ SamrOpenAlias(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     *AliasHandle = (SAMPR_HANDLE)AliasObject;
 
-    return STATUS_SUCCESS;
+done:
+    RtlReleaseResource(&SampResource);
+
+    return Status;
 }
 
 
@@ -4573,8 +4672,7 @@ SampQueryAliasGeneral(PSAM_DB_OBJECT AliasObject,
     *Buffer = InfoBuffer;
 
 done:
-    if (MembersKeyHandle != NULL)
-        SampRegCloseKey(MembersKeyHandle);
+    SampRegCloseKey(&MembersKeyHandle);
 
     if (!NT_SUCCESS(Status))
     {
@@ -4687,13 +4785,16 @@ SamrQueryInformationAlias(IN SAMPR_HANDLE AliasHandle,
     TRACE("SamrQueryInformationAlias(%p %lu %p)\n",
           AliasHandle, AliasInformationClass, Buffer);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the alias handle */
     Status = SampValidateDbObject(AliasHandle,
                                   SamDbAliasObject,
                                   ALIAS_READ_INFORMATION,
                                   &AliasObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     switch (AliasInformationClass)
     {
@@ -4717,6 +4818,9 @@ SamrQueryInformationAlias(IN SAMPR_HANDLE AliasHandle,
             break;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -4781,11 +4885,9 @@ SampSetAliasName(PSAM_DB_OBJECT AliasObject,
         goto done;
     }
 
-    Status = SampSetObjectAttribute(AliasObject,
-                                    L"Name",
-                                    REG_SZ,
-                                    NewAliasName.Buffer,
-                                    NewAliasName.Length + sizeof(WCHAR));
+    Status = SampSetObjectAttributeString(AliasObject,
+                                          L"Name",
+                                          (PRPC_UNICODE_STRING)&NewAliasName);
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
@@ -4812,13 +4914,16 @@ SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle,
     TRACE("SamrSetInformationAlias(%p %lu %p)\n",
           AliasHandle, AliasInformationClass, Buffer);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the alias handle */
     Status = SampValidateDbObject(AliasHandle,
                                   SamDbAliasObject,
                                   ALIAS_WRITE_ACCOUNT,
                                   &AliasObject);
     if (!NT_SUCCESS(Status))
-        return Status;
+        goto done;
 
     switch (AliasInformationClass)
     {
@@ -4828,11 +4933,9 @@ SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle,
             break;
 
         case AliasAdminCommentInformation:
-            Status = SampSetObjectAttribute(AliasObject,
-                                            L"Description",
-                                            REG_SZ,
-                                            Buffer->AdminComment.AdminComment.Buffer,
-                                            Buffer->AdminComment.AdminComment.Length + sizeof(WCHAR));
+            Status = SampSetObjectAttributeString(AliasObject,
+                                                  L"Description",
+                                                  &Buffer->AdminComment.AdminComment);
             break;
 
         default:
@@ -4840,6 +4943,9 @@ SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle,
             break;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -4852,6 +4958,9 @@ SamrDeleteAlias(IN OUT SAMPR_HANDLE *AliasHandle)
     PSAM_DB_OBJECT AliasObject;
     NTSTATUS Status;
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the alias handle */
     Status = SampValidateDbObject(*AliasHandle,
                                   SamDbAliasObject,
@@ -4860,29 +4969,39 @@ SamrDeleteAlias(IN OUT SAMPR_HANDLE *AliasHandle)
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampValidateDbObject failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Fail, if the alias is built-in */
     if (AliasObject->RelativeId < 1000)
     {
         TRACE("You can not delete a special account!\n");
-        return STATUS_SPECIAL_ACCOUNT;
+        Status = STATUS_SPECIAL_ACCOUNT;
+        goto done;
     }
 
-    /* FIXME: Remove all members from the alias */
+    /* Remove all members from the alias */
+    Status = SampRemoveAllMembersFromAlias(AliasObject);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("SampRemoveAllMembersFromAlias() failed (Status 0x%08lx)\n", Status);
+        goto done;
+    }
 
     /* Delete the alias from the database */
     Status = SampDeleteAccountDbObject(AliasObject);
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Invalidate the handle */
     *AliasHandle = NULL;
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -4898,6 +5017,9 @@ SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
 
     TRACE("(%p %p)\n", AliasHandle, MemberId);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the alias handle */
     Status = SampValidateDbObject(AliasHandle,
                                   SamDbAliasObject,
@@ -4906,7 +5028,7 @@ SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     Status = SampAddMemberToAlias(AliasObject,
@@ -4916,6 +5038,9 @@ SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
         TRACE("failed with status 0x%08lx\n", Status);
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -4931,6 +5056,9 @@ SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle,
 
     TRACE("(%p %p)\n", AliasHandle, MemberId);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the alias handle */
     Status = SampValidateDbObject(AliasHandle,
                                   SamDbAliasObject,
@@ -4939,7 +5067,7 @@ SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     Status = SampRemoveMemberFromAlias(AliasObject,
@@ -4949,6 +5077,9 @@ SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle,
         TRACE("failed with status 0x%08lx\n", Status);
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -4960,16 +5091,17 @@ SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
                       OUT PSAMPR_PSID_ARRAY_OUT Members)
 {
     PSAM_DB_OBJECT AliasObject;
-    HANDLE MembersKeyHandle = NULL;
     PSAMPR_SID_INFORMATION MemberArray = NULL;
-    ULONG ValueCount = 0;
-    ULONG DataLength;
+    ULONG MemberCount = 0;
     ULONG Index;
     NTSTATUS Status;
 
     TRACE("SamrGetMembersInAlias(%p %p %p)\n",
           AliasHandle, Members);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the alias handle */
     Status = SampValidateDbObject(AliasHandle,
                                   SamDbAliasObject,
@@ -4978,86 +5110,17 @@ SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
     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++;
-    }
+    Status = SampGetMembersInAlias(AliasObject,
+                                   &MemberCount,
+                                   &MemberArray);
 
     /* Return the number of members and the member array */
     if (NT_SUCCESS(Status))
     {
-        Members->Count = ValueCount;
+        Members->Count = MemberCount;
         Members->Sids = MemberArray;
     }
 
@@ -5067,7 +5130,7 @@ done:
     {
         if (MemberArray != NULL)
         {
-            for (Index = 0; Index < ValueCount; Index++)
+            for (Index = 0; Index < MemberCount; Index++)
             {
                 if (MemberArray[Index].SidPointer != NULL)
                     midl_user_free(MemberArray[Index].SidPointer);
@@ -5077,9 +5140,7 @@ done:
         }
     }
 
-    /* Close the members key */
-    if (MembersKeyHandle != NULL)
-        SampRegCloseKey(MembersKeyHandle);
+    RtlReleaseResource(&SampResource);
 
     return Status;
 }
@@ -5105,6 +5166,9 @@ SamrOpenUser(IN SAMPR_HANDLE DomainHandle,
     RtlMapGenericMask(&DesiredAccess,
                       &UserMapping);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
@@ -5113,7 +5177,7 @@ SamrOpenUser(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Convert the RID into a string (hex) */
@@ -5130,12 +5194,15 @@ SamrOpenUser(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     *UserHandle = (SAMPR_HANDLE)UserObject;
 
-    return STATUS_SUCCESS;
+done:
+    RtlReleaseResource(&SampResource);
+
+    return Status;
 }
 
 
@@ -5149,6 +5216,9 @@ SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle)
 
     TRACE("(%p)\n", UserHandle);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the user handle */
     Status = SampValidateDbObject(*UserHandle,
                                   SamDbUserObject,
@@ -5157,14 +5227,15 @@ SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle)
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Fail, if the user is built-in */
     if (UserObject->RelativeId < 1000)
     {
         TRACE("You can not delete a special account!\n");
-        return STATUS_SPECIAL_ACCOUNT;
+        Status = STATUS_SPECIAL_ACCOUNT;
+        goto done;
     }
 
     /* FIXME: Remove the user from all groups */
@@ -5176,13 +5247,16 @@ SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle)
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Invalidate the handle */
     *UserHandle = NULL;
 
-    return STATUS_SUCCESS;
+done:
+    RtlReleaseResource(&SampResource);
+
+    return Status;
 }
 
 
@@ -6231,6 +6305,9 @@ SampQueryUserInternal1(PSAM_DB_OBJECT UserObject,
     if (InfoBuffer == NULL)
         return STATUS_INSUFFICIENT_RESOURCES;
 
+    InfoBuffer->Internal1.LmPasswordPresent = FALSE;
+    InfoBuffer->Internal1.NtPasswordPresent = FALSE;
+
     /* Get the NT password */
     Length = 0;
     SampGetObjectAttribute(UserObject,
@@ -6248,9 +6325,13 @@ SampQueryUserInternal1(PSAM_DB_OBJECT UserObject,
                                         &Length);
         if (!NT_SUCCESS(Status))
             goto done;
+
+        if (memcmp(&InfoBuffer->Internal1.EncryptedNtOwfPassword,
+                   &EmptyNtHash,
+                   sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
+            InfoBuffer->Internal1.NtPasswordPresent = TRUE;
     }
 
-    InfoBuffer->Internal1.NtPasswordPresent = (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD));
 
     /* Get the LM password */
     Length = 0;
@@ -6269,9 +6350,12 @@ SampQueryUserInternal1(PSAM_DB_OBJECT UserObject,
                                         &Length);
         if (!NT_SUCCESS(Status))
             goto done;
-    }
 
-    InfoBuffer->Internal1.LmPasswordPresent = (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD));
+        if (memcmp(&InfoBuffer->Internal1.EncryptedLmOwfPassword,
+                   &EmptyLmHash,
+                   sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+            InfoBuffer->Internal1.LmPasswordPresent = TRUE;
+    }
 
     InfoBuffer->Internal1.PasswordExpired = FALSE;
 
@@ -6369,9 +6453,42 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
     if (!NT_SUCCESS(Status))
         goto done;
 
-    if (UserObject->Access & USER_READ_GENERAL)
+    /* Set the fields to be returned */
+    if (UserObject->Trusted)
+    {
+        InfoBuffer->All.WhichFields = USER_ALL_READ_GENERAL_MASK |
+                                      USER_ALL_READ_LOGON_MASK |
+                                      USER_ALL_READ_ACCOUNT_MASK |
+                                      USER_ALL_READ_PREFERENCES_MASK |
+                                      USER_ALL_READ_TRUSTED_MASK;
+    }
+    else
+    {
+        InfoBuffer->All.WhichFields = 0;
+
+        if (UserObject->Access & USER_READ_GENERAL)
+            InfoBuffer->All.WhichFields |= USER_ALL_READ_GENERAL_MASK;
+
+        if (UserObject->Access & USER_READ_LOGON)
+            InfoBuffer->All.WhichFields |= USER_ALL_READ_LOGON_MASK;
+
+        if (UserObject->Access & USER_READ_ACCOUNT)
+            InfoBuffer->All.WhichFields |= USER_ALL_READ_ACCOUNT_MASK;
+
+        if (UserObject->Access & USER_READ_PREFERENCES)
+            InfoBuffer->All.WhichFields |= USER_ALL_READ_PREFERENCES_MASK;
+    }
+
+    /* Fail, if no fields are to be returned */
+    if (InfoBuffer->All.WhichFields == 0)
+    {
+        Status = STATUS_ACCESS_DENIED;
+        goto done;
+    }
+
+    /* Get the UserName attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_USERNAME)
     {
-        /* Get the Name string */
         Status = SampGetObjectAttributeString(UserObject,
                                               L"Name",
                                               &InfoBuffer->All.UserName);
@@ -6380,8 +6497,11 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
+    }
 
-        /* Get the FullName string */
+    /* Get the FullName attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_FULLNAME)
+    {
         Status = SampGetObjectAttributeString(UserObject,
                                               L"FullName",
                                               &InfoBuffer->All.FullName);
@@ -6390,14 +6510,23 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
+    }
 
-        /* Get the user ID*/
+    /* Get the UserId attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_USERID)
+    {
         InfoBuffer->All.UserId = FixedData.UserId;
+    }
 
-        /* Get the primary group ID */
+    /* Get the PrimaryGroupId attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_PRIMARYGROUPID)
+    {
         InfoBuffer->All.PrimaryGroupId = FixedData.PrimaryGroupId;
+    }
 
-        /* Get the AdminComment string */
+    /* Get the AdminComment attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_ADMINCOMMENT)
+    {
         Status = SampGetObjectAttributeString(UserObject,
                                               L"AdminComment",
                                               &InfoBuffer->All.AdminComment);
@@ -6406,8 +6535,11 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
+    }
 
-        /* Get the UserComment string */
+    /* Get the UserComment attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_USERCOMMENT)
+    {
         Status = SampGetObjectAttributeString(UserObject,
                                               L"UserComment",
                                               &InfoBuffer->All.UserComment);
@@ -6416,19 +6548,11 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
-
-        InfoBuffer->All.WhichFields |= USER_ALL_READ_GENERAL_MASK;
-//            USER_ALL_USERNAME |
-//            USER_ALL_FULLNAME |
-//            USER_ALL_USERID |
-//            USER_ALL_PRIMARYGROUPID |
-//            USER_ALL_ADMINCOMMENT |
-//            USER_ALL_USERCOMMENT;
     }
 
-    if (UserObject->Access & USER_READ_LOGON)
+    /* Get the HomeDirectory attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_HOMEDIRECTORY)
     {
-        /* Get the HomeDirectory string */
         Status = SampGetObjectAttributeString(UserObject,
                                               L"HomeDirectory",
                                               &InfoBuffer->All.HomeDirectory);
@@ -6437,8 +6561,11 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
+    }
 
-        /* Get the HomeDirectoryDrive string */
+    /* Get the HomeDirectoryDrive attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_HOMEDIRECTORYDRIVE)
+    {
         Status = SampGetObjectAttributeString(UserObject,
                                               L"HomeDirectoryDrive",
                                               &InfoBuffer->Home.HomeDirectoryDrive);
@@ -6447,8 +6574,11 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
+    }
 
-        /* Get the ScriptPath string */
+    /* Get the ScriptPath attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_SCRIPTPATH)
+    {
         Status = SampGetObjectAttributeString(UserObject,
                                               L"ScriptPath",
                                               &InfoBuffer->All.ScriptPath);
@@ -6457,8 +6587,11 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
+    }
 
-        /* Get the ProfilePath string */
+    /* Get the ProfilePath attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_PROFILEPATH)
+    {
         Status = SampGetObjectAttributeString(UserObject,
                                               L"ProfilePath",
                                               &InfoBuffer->All.ProfilePath);
@@ -6467,8 +6600,11 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
+    }
 
-        /* Get the WorkStations string */
+    /* Get the WorkStations attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_WORKSTATIONS)
+    {
         Status = SampGetObjectAttributeString(UserObject,
                                               L"WorkStations",
                                               &InfoBuffer->All.WorkStations);
@@ -6477,8 +6613,25 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
+    }
+
+    /* Get the LastLogon attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_LASTLOGON)
+    {
+        InfoBuffer->All.LastLogon.LowPart = FixedData.LastLogon.LowPart;
+        InfoBuffer->All.LastLogon.HighPart = FixedData.LastLogon.HighPart;
+    }
+
+    /* Get the LastLogoff attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_LASTLOGOFF)
+    {
+        InfoBuffer->All.LastLogoff.LowPart = FixedData.LastLogoff.LowPart;
+        InfoBuffer->All.LastLogoff.HighPart = FixedData.LastLogoff.HighPart;
+    }
 
-        /* Get the LogonHours attribute */
+    /* Get the LogonHours attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_LOGONHOURS)
+    {
         Status = SampGetLogonHoursAttrbute(UserObject,
                                            &InfoBuffer->All.LogonHours);
         if (!NT_SUCCESS(Status))
@@ -6486,55 +6639,61 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
+    }
 
-        InfoBuffer->All.LastLogon.LowPart = FixedData.LastLogon.LowPart;
-        InfoBuffer->All.LastLogon.HighPart = FixedData.LastLogon.HighPart;
-
-        InfoBuffer->All.LastLogoff.LowPart = FixedData.LastLogoff.LowPart;
-        InfoBuffer->All.LastLogoff.HighPart = FixedData.LastLogoff.HighPart;
-
+    /* Get the BadPasswordCount attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_BADPASSWORDCOUNT)
+    {
         InfoBuffer->All.BadPasswordCount = FixedData.BadPasswordCount;
+    }
 
+    /* Get the LogonCount attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_LOGONCOUNT)
+    {
         InfoBuffer->All.LogonCount = FixedData.LogonCount;
+    }
 
+    /* Get the PasswordCanChange attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDCANCHANGE)
+    {
         PasswordCanChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet,
                                                       DomainFixedData.MinPasswordAge);
         InfoBuffer->All.PasswordCanChange.LowPart = PasswordCanChange.LowPart;
         InfoBuffer->All.PasswordCanChange.HighPart = PasswordCanChange.HighPart;
+    }
 
+    /* Get the PasswordMustChange attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDMUSTCHANGE)
+    {
         PasswordMustChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet,
                                                        DomainFixedData.MaxPasswordAge);
         InfoBuffer->All.PasswordMustChange.LowPart = PasswordMustChange.LowPart;
         InfoBuffer->All.PasswordMustChange.HighPart = PasswordMustChange.HighPart;
+    }
 
-        InfoBuffer->All. WhichFields |= USER_ALL_READ_LOGON_MASK;
-/*
-            USER_ALL_HOMEDIRECTORY |
-            USER_ALL_HOMEDIRECTORYDRIVE |
-            USER_ALL_SCRIPTPATH |
-            USER_ALL_PROFILEPATH |
-            USER_ALL_WORKSTATIONS |
-            USER_ALL_LASTLOGON |
-            USER_ALL_LASTLOGOFF |
-            USER_ALL_LOGONHOURS |
-            USER_ALL_BADPASSWORDCOUNT |
-            USER_ALL_LOGONCOUNT;
-            USER_ALL_PASSWORDCANCHANGE |
-            USER_ALL_PASSWORDMUSTCHANGE;
-*/
-    }
-
-    if (UserObject->Access & USER_READ_ACCOUNT)
+    /* Get the PasswordLastSet attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDLASTSET)
     {
         InfoBuffer->All.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart;
         InfoBuffer->All.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart;
+    }
 
+    /* Get the AccountExpires attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_ACCOUNTEXPIRES)
+    {
         InfoBuffer->All.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
         InfoBuffer->All.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
+    }
 
+    /* Get the UserAccountControl attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_USERACCOUNTCONTROL)
+    {
         InfoBuffer->All.UserAccountControl = FixedData.UserAccountControl;
+    }
 
-        /* Get the Parameters string */
+    /* Get the Parameters attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_PARAMETERS)
+    {
         Status = SampGetObjectAttributeString(UserObject,
                                               L"Parameters",
                                               &InfoBuffer->All.Parameters);
@@ -6543,23 +6702,108 @@ SampQueryUserAll(PSAM_DB_OBJECT UserObject,
             TRACE("Status 0x%08lx\n", Status);
             goto done;
         }
-
-        InfoBuffer->All. WhichFields |= USER_ALL_READ_ACCOUNT_MASK;
-//            USER_ALL_PASSWORDLASTSET |
-//            USER_ALL_ACCOUNTEXPIRES |
-//            USER_ALL_USERACCOUNTCONTROL |
-//            USER_ALL_PARAMETERS;
     }
 
-    if (UserObject->Access & USER_READ_PREFERENCES)
+    /* Get the CountryCode attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_COUNTRYCODE)
     {
         InfoBuffer->All.CountryCode = FixedData.CountryCode;
+    }
 
+    /* Get the CodePage attribute */
+    if (InfoBuffer->All.WhichFields & USER_ALL_CODEPAGE)
+    {
         InfoBuffer->All.CodePage = FixedData.CodePage;
+    }
+
+    /* Get the LmPassword and NtPassword attributes */
+    if (InfoBuffer->All.WhichFields & (USER_ALL_NTPASSWORDPRESENT | USER_ALL_LMPASSWORDPRESENT))
+    {
+        InfoBuffer->All.LmPasswordPresent = FALSE;
+        InfoBuffer->All.NtPasswordPresent = FALSE;
+
+        /* Get the NT password */
+        Length = 0;
+        SampGetObjectAttribute(UserObject,
+                               L"NTPwd",
+                               NULL,
+                               NULL,
+                               &Length);
+
+        if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD))
+        {
+            InfoBuffer->All.NtOwfPassword.Buffer = midl_user_allocate(sizeof(ENCRYPTED_NT_OWF_PASSWORD));
+            if (InfoBuffer->All.NtOwfPassword.Buffer == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto done;
+            }
+
+            InfoBuffer->All.NtOwfPassword.Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
+            InfoBuffer->All.NtOwfPassword.MaximumLength = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
+
+            Status = SampGetObjectAttribute(UserObject,
+                                            L"NTPwd",
+                                            NULL,
+                                            (PVOID)InfoBuffer->All.NtOwfPassword.Buffer,
+                                            &Length);
+            if (!NT_SUCCESS(Status))
+                goto done;
+
+            if (memcmp(InfoBuffer->All.NtOwfPassword.Buffer,
+                       &EmptyNtHash,
+                       sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
+                InfoBuffer->All.NtPasswordPresent = TRUE;
+        }
+
+        /* Get the LM password */
+        Length = 0;
+        SampGetObjectAttribute(UserObject,
+                               L"LMPwd",
+                               NULL,
+                               NULL,
+                               &Length);
+
+        if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD))
+        {
+            InfoBuffer->All.LmOwfPassword.Buffer = midl_user_allocate(sizeof(ENCRYPTED_LM_OWF_PASSWORD));
+            if (InfoBuffer->All.LmOwfPassword.Buffer == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto done;
+            }
+
+            InfoBuffer->All.LmOwfPassword.Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
+            InfoBuffer->All.LmOwfPassword.MaximumLength = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
 
-        InfoBuffer->All. WhichFields |= USER_ALL_READ_PREFERENCES_MASK;
-//            USER_ALL_COUNTRYCODE |
-//            USER_ALL_CODEPAGE;
+            Status = SampGetObjectAttribute(UserObject,
+                                            L"LMPwd",
+                                            NULL,
+                                            (PVOID)InfoBuffer->All.LmOwfPassword.Buffer,
+                                            &Length);
+            if (!NT_SUCCESS(Status))
+                goto done;
+
+            if (memcmp(InfoBuffer->All.LmOwfPassword.Buffer,
+                       &EmptyLmHash,
+                       sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+                InfoBuffer->All.LmPasswordPresent = TRUE;
+        }
+    }
+
+    if (InfoBuffer->All.WhichFields & USER_ALL_PRIVATEDATA)
+    {
+        /* FIXME */
+    }
+
+    if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDEXPIRED)
+    {
+        /* FIXME */
+    }
+
+    if (InfoBuffer->All.WhichFields & USER_ALL_SECURITYDESCRIPTOR)
+    {
+        /* FIXME */
     }
 
     *Buffer = InfoBuffer;
@@ -6602,6 +6846,12 @@ done:
             if (InfoBuffer->All.Parameters.Buffer != NULL)
                 midl_user_free(InfoBuffer->All.Parameters.Buffer);
 
+            if (InfoBuffer->All.LmOwfPassword.Buffer != NULL)
+                midl_user_free(InfoBuffer->All.LmOwfPassword.Buffer);
+
+            if (InfoBuffer->All.NtOwfPassword.Buffer != NULL)
+                midl_user_free(InfoBuffer->All.NtOwfPassword.Buffer);
+
             midl_user_free(InfoBuffer);
         }
     }
@@ -6671,6 +6921,9 @@ SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
             return STATUS_INVALID_INFO_CLASS;
     }
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(UserHandle,
                                   SamDbUserObject,
@@ -6679,7 +6932,7 @@ SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     switch (UserInformationClass)
@@ -6787,6 +7040,9 @@ SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
             Status = STATUS_INVALID_INFO_CLASS;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -6846,11 +7102,9 @@ SampSetUserName(PSAM_DB_OBJECT UserObject,
         goto done;
     }
 
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"Name",
-                                    REG_SZ,
-                                    NewUserName->Buffer,
-                                    NewUserName->Length + sizeof(WCHAR));
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"Name",
+                                          NewUserName);
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
@@ -6896,27 +7150,21 @@ SampSetUserGeneral(PSAM_DB_OBJECT UserObject,
     if (!NT_SUCCESS(Status))
         goto done;
 
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"FullName",
-                                    REG_SZ,
-                                    Buffer->General.FullName.Buffer,
-                                    Buffer->General.FullName.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"FullName",
+                                          &Buffer->General.FullName);
     if (!NT_SUCCESS(Status))
         goto done;
 
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"AdminComment",
-                                    REG_SZ,
-                                    Buffer->General.AdminComment.Buffer,
-                                    Buffer->General.AdminComment.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"AdminComment",
+                                          &Buffer->General.AdminComment);
     if (!NT_SUCCESS(Status))
         goto done;
 
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"UserComment",
-                                    REG_SZ,
-                                    Buffer->General.UserComment.Buffer,
-                                    Buffer->General.UserComment.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"UserComment",
+                                          &Buffer->General.UserComment);
 
 done:
     return Status;
@@ -6951,11 +7199,9 @@ SampSetUserPreferences(PSAM_DB_OBJECT UserObject,
     if (!NT_SUCCESS(Status))
         goto done;
 
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"UserComment",
-                                    REG_SZ,
-                                    Buffer->Preferences.UserComment.Buffer,
-                                    Buffer->Preferences.UserComment.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"UserComment",
+                                          &Buffer->Preferences.UserComment);
 
 done:
     return Status;
@@ -7144,99 +7390,81 @@ SampSetUserAll(PSAM_DB_OBJECT UserObject,
 
     if (WhichFields & USER_ALL_FULLNAME)
     {
-        Status = SampSetObjectAttribute(UserObject,
-                                        L"FullName",
-                                        REG_SZ,
-                                        Buffer->All.FullName.Buffer,
-                                        Buffer->All.FullName.MaximumLength);
+        Status = SampSetObjectAttributeString(UserObject,
+                                              L"FullName",
+                                              &Buffer->All.FullName);
         if (!NT_SUCCESS(Status))
             goto done;
     }
 
     if (WhichFields & USER_ALL_ADMINCOMMENT)
     {
-        Status = SampSetObjectAttribute(UserObject,
-                                        L"AdminComment",
-                                        REG_SZ,
-                                        Buffer->All.AdminComment.Buffer,
-                                        Buffer->All.AdminComment.MaximumLength);
+        Status = SampSetObjectAttributeString(UserObject,
+                                              L"AdminComment",
+                                              &Buffer->All.AdminComment);
         if (!NT_SUCCESS(Status))
             goto done;
     }
 
     if (WhichFields & USER_ALL_USERCOMMENT)
     {
-        Status = SampSetObjectAttribute(UserObject,
-                                        L"UserComment",
-                                        REG_SZ,
-                                        Buffer->All.UserComment.Buffer,
-                                        Buffer->All.UserComment.MaximumLength);
+        Status = SampSetObjectAttributeString(UserObject,
+                                              L"UserComment",
+                                              &Buffer->All.UserComment);
         if (!NT_SUCCESS(Status))
             goto done;
     }
 
     if (WhichFields & USER_ALL_HOMEDIRECTORY)
     {
-        Status = SampSetObjectAttribute(UserObject,
-                                        L"HomeDirectory",
-                                        REG_SZ,
-                                        Buffer->All.HomeDirectory.Buffer,
-                                        Buffer->All.HomeDirectory.MaximumLength);
+        Status = SampSetObjectAttributeString(UserObject,
+                                              L"HomeDirectory",
+                                              &Buffer->All.HomeDirectory);
         if (!NT_SUCCESS(Status))
             goto done;
     }
 
     if (WhichFields & USER_ALL_HOMEDIRECTORYDRIVE)
     {
-        Status = SampSetObjectAttribute(UserObject,
-                                        L"HomeDirectoryDrive",
-                                        REG_SZ,
-                                        Buffer->All.HomeDirectoryDrive.Buffer,
-                                        Buffer->All.HomeDirectoryDrive.MaximumLength);
+        Status = SampSetObjectAttributeString(UserObject,
+                                              L"HomeDirectoryDrive",
+                                              &Buffer->All.HomeDirectoryDrive);
         if (!NT_SUCCESS(Status))
             goto done;
     }
 
     if (WhichFields & USER_ALL_SCRIPTPATH)
     {
-        Status = SampSetObjectAttribute(UserObject,
-                                        L"ScriptPath",
-                                        REG_SZ,
-                                        Buffer->All.ScriptPath.Buffer,
-                                        Buffer->All.ScriptPath.MaximumLength);
+        Status = SampSetObjectAttributeString(UserObject,
+                                              L"ScriptPath",
+                                              &Buffer->All.ScriptPath);
         if (!NT_SUCCESS(Status))
             goto done;
     }
 
     if (WhichFields & USER_ALL_PROFILEPATH)
     {
-        Status = SampSetObjectAttribute(UserObject,
-                                        L"ProfilePath",
-                                        REG_SZ,
-                                        Buffer->All.ProfilePath.Buffer,
-                                        Buffer->All.ProfilePath.MaximumLength);
+        Status = SampSetObjectAttributeString(UserObject,
+                                              L"ProfilePath",
+                                              &Buffer->All.ProfilePath);
         if (!NT_SUCCESS(Status))
             goto done;
     }
 
     if (WhichFields & USER_ALL_WORKSTATIONS)
     {
-        Status = SampSetObjectAttribute(UserObject,
-                                        L"WorkStations",
-                                        REG_SZ,
-                                        Buffer->All.WorkStations.Buffer,
-                                        Buffer->All.WorkStations.MaximumLength);
+        Status = SampSetObjectAttributeString(UserObject,
+                                              L"WorkStations",
+                                              &Buffer->All.WorkStations);
         if (!NT_SUCCESS(Status))
             goto done;
     }
 
     if (WhichFields & USER_ALL_PARAMETERS)
     {
-        Status = SampSetObjectAttribute(UserObject,
-                                        L"Parameters",
-                                        REG_SZ,
-                                        Buffer->All.Parameters.Buffer,
-                                        Buffer->All.Parameters.MaximumLength);
+        Status = SampSetObjectAttributeString(UserObject,
+                                              L"Parameters",
+                                              &Buffer->All.Parameters);
         if (!NT_SUCCESS(Status))
             goto done;
     }
@@ -7400,6 +7628,9 @@ SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
             return STATUS_INVALID_INFO_CLASS;
     }
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(UserHandle,
                                   SamDbUserObject,
@@ -7408,7 +7639,7 @@ SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     switch (UserInformationClass)
@@ -7434,11 +7665,9 @@ SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
             if (!NT_SUCCESS(Status))
                 break;
 
-            Status = SampSetObjectAttribute(UserObject,
-                                            L"FullName",
-                                            REG_SZ,
-                                            Buffer->Name.FullName.Buffer,
-                                            Buffer->Name.FullName.MaximumLength);
+            Status = SampSetObjectAttributeString(UserObject,
+                                                  L"FullName",
+                                                  &Buffer->Name.FullName);
             break;
 
         case UserAccountNameInformation:
@@ -7447,11 +7676,9 @@ SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
             break;
 
         case UserFullNameInformation:
-            Status = SampSetObjectAttribute(UserObject,
-                                            L"FullName",
-                                            REG_SZ,
-                                            Buffer->FullName.FullName.Buffer,
-                                            Buffer->FullName.FullName.MaximumLength);
+            Status = SampSetObjectAttributeString(UserObject,
+                                                  L"FullName",
+                                                  &Buffer->FullName.FullName);
             break;
 
         case UserPrimaryGroupInformation:
@@ -7460,62 +7687,48 @@ SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
             break;
 
         case UserHomeInformation:
-            Status = SampSetObjectAttribute(UserObject,
-                                            L"HomeDirectory",
-                                            REG_SZ,
-                                            Buffer->Home.HomeDirectory.Buffer,
-                                            Buffer->Home.HomeDirectory.MaximumLength);
+            Status = SampSetObjectAttributeString(UserObject,
+                                                  L"HomeDirectory",
+                                                  &Buffer->Home.HomeDirectory);
             if (!NT_SUCCESS(Status))
                 break;
 
-            Status = SampSetObjectAttribute(UserObject,
-                                            L"HomeDirectoryDrive",
-                                            REG_SZ,
-                                            Buffer->Home.HomeDirectoryDrive.Buffer,
-                                            Buffer->Home.HomeDirectoryDrive.MaximumLength);
+            Status = SampSetObjectAttributeString(UserObject,
+                                                  L"HomeDirectoryDrive",
+                                                  &Buffer->Home.HomeDirectoryDrive);
             break;
 
         case UserScriptInformation:
-            Status = SampSetObjectAttribute(UserObject,
-                                            L"ScriptPath",
-                                            REG_SZ,
-                                            Buffer->Script.ScriptPath.Buffer,
-                                            Buffer->Script.ScriptPath.MaximumLength);
+            Status = SampSetObjectAttributeString(UserObject,
+                                                  L"ScriptPath",
+                                                  &Buffer->Script.ScriptPath);
             break;
 
         case UserProfileInformation:
-            Status = SampSetObjectAttribute(UserObject,
-                                            L"ProfilePath",
-                                            REG_SZ,
-                                            Buffer->Profile.ProfilePath.Buffer,
-                                            Buffer->Profile.ProfilePath.MaximumLength);
+            Status = SampSetObjectAttributeString(UserObject,
+                                                  L"ProfilePath",
+                                                  &Buffer->Profile.ProfilePath);
             break;
 
         case UserAdminCommentInformation:
-            Status = SampSetObjectAttribute(UserObject,
-                                            L"AdminComment",
-                                            REG_SZ,
-                                            Buffer->AdminComment.AdminComment.Buffer,
-                                            Buffer->AdminComment.AdminComment.MaximumLength);
+            Status = SampSetObjectAttributeString(UserObject,
+                                                  L"AdminComment",
+                                                  &Buffer->AdminComment.AdminComment);
             break;
 
         case UserWorkStationsInformation:
-            Status = SampSetObjectAttribute(UserObject,
-                                            L"WorkStations",
-                                            REG_SZ,
-                                            Buffer->WorkStations.WorkStations.Buffer,
-                                            Buffer->WorkStations.WorkStations.MaximumLength);
+            Status = SampSetObjectAttributeString(UserObject,
+                                                  L"WorkStations",
+                                                  &Buffer->WorkStations.WorkStations);
             break;
 
         case UserSetPasswordInformation:
             TRACE("Password: %S\n", Buffer->SetPassword.Password.Buffer);
             TRACE("PasswordExpired: %d\n", Buffer->SetPassword.PasswordExpired);
 
-            Status = SampSetObjectAttribute(UserObject,
-                                            L"Password",
-                                            REG_SZ,
-                                            Buffer->SetPassword.Password.Buffer,
-                                            Buffer->SetPassword.Password.MaximumLength);
+            Status = SampSetObjectAttributeString(UserObject,
+                                                  L"Password",
+                                                  &Buffer->SetPassword.Password);
             break;
 
         case UserControlInformation:
@@ -7534,11 +7747,9 @@ SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
             break;
 
         case UserParametersInformation:
-            Status = SampSetObjectAttribute(UserObject,
-                                            L"Parameters",
-                                            REG_SZ,
-                                            Buffer->Parameters.Parameters.Buffer,
-                                            Buffer->Parameters.Parameters.MaximumLength);
+            Status = SampSetObjectAttributeString(UserObject,
+                                                  L"Parameters",
+                                                  &Buffer->Parameters.Parameters);
             break;
 
         case UserAllInformation:
@@ -7555,6 +7766,9 @@ SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
             Status = STATUS_INVALID_INFO_CLASS;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -7596,6 +7810,9 @@ SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
           NtPresent, OldNtEncryptedWithNewNt, NewNtEncryptedWithOldNt, NtCrossEncryptionPresent,
           NewNtEncryptedWithNewLm, LmCrossEncryptionPresent, NewLmEncryptedWithNewNt);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the user handle */
     Status = SampValidateDbObject(UserHandle,
                                   SamDbUserObject,
@@ -7604,7 +7821,7 @@ SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Get the current time */
@@ -7612,7 +7829,7 @@ SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("NtQuerySystemTime failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Retrieve the LM password */
@@ -7663,7 +7880,7 @@ SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampGetObjectAttribute failed to retrieve the fixed user data (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Check if we can change the password at this time */
@@ -7785,6 +8002,9 @@ SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
                                         Length);
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -7803,6 +8023,9 @@ SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle,
     TRACE("SamrGetGroupsForUser(%p %p)\n",
           UserHandle, Groups);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the user handle */
     Status = SampValidateDbObject(UserHandle,
                                   SamDbUserObject,
@@ -7811,13 +8034,16 @@ SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Allocate the groups buffer */
     GroupsBuffer = midl_user_allocate(sizeof(SAMPR_GET_GROUPS_BUFFER));
     if (GroupsBuffer == NULL)
-        return STATUS_INSUFFICIENT_RESOURCES;
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto done;
+    }
 
     /*
      * Get the size of the Groups attribute.
@@ -7838,7 +8064,8 @@ SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle,
 
         *Groups = GroupsBuffer;
 
-        return STATUS_SUCCESS;
+        Status = STATUS_SUCCESS;
+        goto done;
     }
 
     /* Allocate a buffer for the Groups attribute */
@@ -7879,6 +8106,8 @@ done:
         }
     }
 
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -7946,6 +8175,9 @@ SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
     TRACE("(%p %p)\n",
           UserHandle, PasswordInformation);
 
+    RtlAcquireResourceShared(&SampResource,
+                             TRUE);
+
     /* Validate the user handle */
     Status = SampValidateDbObject(UserHandle,
                                   SamDbUserObject,
@@ -7954,7 +8186,7 @@ SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Validate the domain object */
@@ -7965,7 +8197,7 @@ SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Get fixed user data */
@@ -7978,7 +8210,7 @@ SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     if ((UserObject->RelativeId == DOMAIN_USER_RID_KRBTGT) ||
@@ -8001,13 +8233,16 @@ SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
         if (!NT_SUCCESS(Status))
         {
             TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
-            return Status;
+            goto done;
         }
 
         PasswordInformation->MinPasswordLength = DomainFixedData.MinPasswordLength;
         PasswordInformation->PasswordProperties = DomainFixedData.PasswordProperties;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return STATUS_SUCCESS;
 }
 
@@ -8025,6 +8260,9 @@ SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
     TRACE("(%p %p)\n",
           DomainHandle, MemberSid);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the domain object */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
@@ -8033,7 +8271,7 @@ SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Retrieve the RID from the MemberSID */
@@ -8042,14 +8280,15 @@ SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampGetRidFromSid failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Fail, if the RID represents a special account */
     if (Rid < 1000)
     {
         TRACE("Cannot remove a special account (RID: %lu)\n", Rid);
-        return STATUS_SPECIAL_ACCOUNT;
+        Status = STATUS_SPECIAL_ACCOUNT;
+        goto done;
     }
 
     /* Remove the member from all aliases in the domain */
@@ -8060,6 +8299,9 @@ SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
         TRACE("SampRemoveMemberFromAllAliases failed with status 0x%08lx\n", Status);
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     return Status;
 }
 
@@ -8151,7 +8393,6 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
                         OUT unsigned long *GrantedAccess,
                         OUT unsigned long *RelativeId)
 {
-    UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
     SAM_DOMAIN_FIXED_DATA FixedDomainData;
     SAM_USER_FIXED_DATA FixedUserData;
     PSAM_DB_OBJECT DomainObject;
@@ -8185,6 +8426,9 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     RtlMapGenericMask(&DesiredAccess,
                       &UserMapping);
 
+    RtlAcquireResourceExclusive(&SampResource,
+                                TRUE);
+
     /* Validate the domain handle */
     Status = SampValidateDbObject(DomainHandle,
                                   SamDbDomainObject,
@@ -8193,7 +8437,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Check the user account name */
@@ -8201,7 +8445,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Check if the user name already exists in the domain */
@@ -8211,7 +8455,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     {
         TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
               Name->Buffer, Status);
-        return Status;
+        goto done;
     }
 
     /* Get the fixed domain attributes */
@@ -8224,7 +8468,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Increment the NextRid attribute */
@@ -8240,7 +8484,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     TRACE("RID: %lx\n", ulRid);
@@ -8259,7 +8503,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Add the account name for the user object */
@@ -8270,7 +8514,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Initialize fixed user data */
@@ -8303,127 +8547,107 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the Name attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"Name",
-                                    REG_SZ,
-                                    (LPVOID)Name->Buffer,
-                                    Name->MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"Name",
+                                          Name);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the FullName attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"FullName",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"FullName",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the HomeDirectory attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"HomeDirectory",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"HomeDirectory",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the HomeDirectoryDrive attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"HomeDirectoryDrive",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"HomeDirectoryDrive",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the ScriptPath attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"ScriptPath",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"ScriptPath",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the ProfilePath attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"ProfilePath",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"ProfilePath",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the AdminComment attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"AdminComment",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"AdminComment",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the UserComment attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"UserComment",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"UserComment",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the WorkStations attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"WorkStations",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"WorkStations",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set the Parameters attribute */
-    Status = SampSetObjectAttribute(UserObject,
-                                    L"Parameters",
-                                    REG_SZ,
-                                    EmptyString.Buffer,
-                                    EmptyString.MaximumLength);
+    Status = SampSetObjectAttributeString(UserObject,
+                                          L"Parameters",
+                                          NULL);
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set LogonHours attribute*/
@@ -8438,7 +8662,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set Groups attribute*/
@@ -8455,7 +8679,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set LMPwd attribute*/
@@ -8467,7 +8691,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set NTPwd attribute*/
@@ -8479,7 +8703,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set LMPwdHistory attribute*/
@@ -8491,7 +8715,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* Set NTPwdHistory attribute*/
@@ -8503,7 +8727,7 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
     if (!NT_SUCCESS(Status))
     {
         TRACE("failed with status 0x%08lx\n", Status);
-        return Status;
+        goto done;
     }
 
     /* FIXME: Set SecDesc attribute*/
@@ -8515,6 +8739,9 @@ SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
         *GrantedAccess = UserObject->Access;
     }
 
+done:
+    RtlReleaseResource(&SampResource);
+
     TRACE("returns with status 0x%08lx\n", Status);
 
     return Status;