xref: /reactos/dll/win32/samlib/samlib.c (revision 5100859e)
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 2004 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 /*
20  * COPYRIGHT:         See COPYING in the top level directory
21  * PROJECT:           ReactOS system libraries
22  * PURPOSE:           SAM interface library
23  * FILE:              lib/samlib/samlib.c
24  * PROGRAMER:         Eric Kohl
25  */
26 
27 #include "precomp.h"
28 
29 #define NTOS_MODE_USER
30 #include <ndk/rtlfuncs.h>
31 #include <ntsam.h>
32 #include <sam_c.h>
33 
34 #include <wine/debug.h>
35 
36 WINE_DEFAULT_DEBUG_CHANNEL(samlib);
37 
38 NTSTATUS
39 WINAPI
40 SystemFunction006(LPCSTR password,
41                   LPSTR hash);
42 
43 NTSTATUS
44 WINAPI
45 SystemFunction007(PUNICODE_STRING string,
46                   LPBYTE hash);
47 
48 NTSTATUS
49 WINAPI
50 SystemFunction012(const BYTE *in,
51                   const BYTE *key,
52                   LPBYTE out);
53 
54 /* GLOBALS *******************************************************************/
55 
56 
57 /* FUNCTIONS *****************************************************************/
58 
59 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
60 {
61     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
62 }
63 
64 
65 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
66 {
67     HeapFree(GetProcessHeap(), 0, ptr);
68 }
69 
70 
71 handle_t __RPC_USER
72 PSAMPR_SERVER_NAME_bind(PSAMPR_SERVER_NAME pszSystemName)
73 {
74     handle_t hBinding = NULL;
75     LPWSTR pszStringBinding;
76     RPC_STATUS status;
77 
78     TRACE("PSAMPR_SERVER_NAME_bind() called\n");
79 
80     status = RpcStringBindingComposeW(NULL,
81                                       L"ncacn_np",
82                                       pszSystemName,
83                                       L"\\pipe\\samr",
84                                       NULL,
85                                       &pszStringBinding);
86     if (status)
87     {
88         TRACE("RpcStringBindingCompose returned 0x%x\n", status);
89         return NULL;
90     }
91 
92     /* Set the binding handle that will be used to bind to the server. */
93     status = RpcBindingFromStringBindingW(pszStringBinding,
94                                           &hBinding);
95     if (status)
96     {
97         TRACE("RpcBindingFromStringBinding returned 0x%x\n", status);
98     }
99 
100     status = RpcStringFreeW(&pszStringBinding);
101     if (status)
102     {
103 //        TRACE("RpcStringFree returned 0x%x\n", status);
104     }
105 
106     return hBinding;
107 }
108 
109 
110 void __RPC_USER
111 PSAMPR_SERVER_NAME_unbind(PSAMPR_SERVER_NAME pszSystemName,
112                           handle_t hBinding)
113 {
114     RPC_STATUS status;
115 
116     TRACE("PSAMPR_SERVER_NAME_unbind() called\n");
117 
118     status = RpcBindingFree(&hBinding);
119     if (status)
120     {
121         TRACE("RpcBindingFree returned 0x%x\n", status);
122     }
123 }
124 
125 
126 NTSTATUS
127 SampCheckPassword(IN SAMPR_HANDLE UserHandle,
128                   IN PUNICODE_STRING Password)
129 {
130     USER_DOMAIN_PASSWORD_INFORMATION DomainPasswordInformation;
131     LPWORD CharTypeBuffer = NULL;
132     ULONG PasswordLength;
133     ULONG i;
134     ULONG Upper = 0, Lower = 0, Digit = 0, Punct = 0, Alpha = 0;
135     NTSTATUS Status = STATUS_SUCCESS;
136 
137     TRACE("(%p %p)\n", UserHandle, Password);
138 
139     /* Get the domain password information */
140     Status = SamrGetUserDomainPasswordInformation(UserHandle,
141                                                   &DomainPasswordInformation);
142     if (!NT_SUCCESS(Status))
143     {
144         TRACE("SamrGetUserDomainPasswordInformation failed (Status 0x%08lx)\n", Status);
145         return Status;
146     }
147 
148     PasswordLength = (ULONG)(Password->Length / sizeof(WCHAR));
149 
150     /* Fail if the password is too short or too long */
151     if ((PasswordLength < DomainPasswordInformation.MinPasswordLength) ||
152         (PasswordLength > 256))
153         return STATUS_PASSWORD_RESTRICTION;
154 
155     /* Check the password complexity */
156     if (DomainPasswordInformation.PasswordProperties & DOMAIN_PASSWORD_COMPLEX)
157     {
158         CharTypeBuffer = midl_user_allocate(PasswordLength * sizeof(WORD));
159         if (CharTypeBuffer == NULL)
160             return STATUS_INSUFFICIENT_RESOURCES;
161 
162         GetStringTypeW(CT_CTYPE1,
163                        Password->Buffer,
164                        PasswordLength,
165                        CharTypeBuffer);
166 
167         for (i = 0; i < PasswordLength; i++)
168         {
169             TRACE("%lu: %C %s %s %s %s\n", i, Password->Buffer[i],
170                   (CharTypeBuffer[i] & C1_UPPER) ? "C1_UPPER" : "        ",
171                   (CharTypeBuffer[i] & C1_LOWER) ? "C1_LOWER" : "        ",
172                   (CharTypeBuffer[i] & C1_DIGIT) ? "C1_DIGIT" : "        ",
173                   (CharTypeBuffer[i] & C1_PUNCT) ? "C1_PUNCT" : "        ",
174                   (CharTypeBuffer[i] & C1_ALPHA) ? "C1_ALPHA" : "        ");
175 
176             if (CharTypeBuffer[i] & C1_UPPER)
177                 Upper = 1;
178 
179             if (CharTypeBuffer[i] & C1_LOWER)
180                 Lower = 1;
181 
182             if (CharTypeBuffer[i] & C1_DIGIT)
183                 Digit = 1;
184 
185             if (CharTypeBuffer[i] & C1_PUNCT)
186                 Punct = 1;
187 
188             if ((CharTypeBuffer[i] & C1_ALPHA) &&
189                 !(CharTypeBuffer[i] & C1_UPPER) &&
190                 !(CharTypeBuffer[i] & C1_LOWER))
191                 Alpha = 1;
192         }
193 
194         TRACE("Upper: %lu\n", Upper);
195         TRACE("Lower: %lu\n", Lower);
196         TRACE("Digit: %lu\n", Digit);
197         TRACE("Punct: %lu\n", Punct);
198         TRACE("Alpha: %lu\n", Alpha);
199 
200         TRACE("Total: %lu\n", Upper + Lower + Digit + Punct + Alpha);
201         if (Upper + Lower + Digit + Punct + Alpha < 3)
202             Status = STATUS_PASSWORD_RESTRICTION;
203     }
204 
205     if (CharTypeBuffer != NULL)
206         midl_user_free(CharTypeBuffer);
207 
208     return Status;
209 }
210 
211 
212 NTSTATUS
213 NTAPI
214 SamAddMemberToAlias(IN SAM_HANDLE AliasHandle,
215                     IN PSID MemberId)
216 {
217     NTSTATUS Status;
218 
219     TRACE("SamAddMemberToAlias(%p %p)\n",
220           AliasHandle, MemberId);
221 
222     RpcTryExcept
223     {
224         Status = SamrAddMemberToAlias((SAMPR_HANDLE)AliasHandle,
225                                       (PRPC_SID)MemberId);
226     }
227     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
228     {
229         Status = I_RpcMapWin32Status(RpcExceptionCode());
230     }
231     RpcEndExcept;
232 
233     return Status;
234 }
235 
236 
237 NTSTATUS
238 NTAPI
239 SamAddMemberToGroup(IN SAM_HANDLE GroupHandle,
240                     IN ULONG MemberId,
241                     IN ULONG Attributes)
242 {
243     NTSTATUS Status;
244 
245     TRACE("SamAddMemberToGroup(%p %lu %lx)\n",
246           GroupHandle, MemberId, Attributes);
247 
248     RpcTryExcept
249     {
250         Status = SamrAddMemberToGroup((SAMPR_HANDLE)GroupHandle,
251                                       MemberId,
252                                       Attributes);
253     }
254     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
255     {
256         Status = I_RpcMapWin32Status(RpcExceptionCode());
257     }
258     RpcEndExcept;
259 
260     return Status;
261 }
262 
263 
264 NTSTATUS
265 NTAPI
266 SamAddMultipleMembersToAlias(IN SAM_HANDLE AliasHandle,
267                              IN PSID *MemberIds,
268                              IN ULONG MemberCount)
269 {
270     SAMPR_PSID_ARRAY Buffer;
271     NTSTATUS Status;
272 
273     TRACE("SamAddMultipleMembersToAlias(%p %p %lu)\n",
274           AliasHandle, MemberIds, MemberCount);
275 
276     if (MemberIds == NULL)
277         return STATUS_INVALID_PARAMETER_2;
278 
279     Buffer.Count = MemberCount;
280     Buffer.Sids = (PSAMPR_SID_INFORMATION)MemberIds;
281 
282     RpcTryExcept
283     {
284         Status = SamrAddMultipleMembersToAlias((SAMPR_HANDLE)AliasHandle,
285                                                &Buffer);
286     }
287     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
288     {
289         Status = I_RpcMapWin32Status(RpcExceptionCode());
290     }
291     RpcEndExcept;
292 
293     return Status;
294 }
295 
296 
297 NTSTATUS
298 NTAPI
299 SamChangePasswordUser(IN SAM_HANDLE UserHandle,
300                       IN PUNICODE_STRING OldPassword,
301                       IN PUNICODE_STRING NewPassword)
302 {
303     NT_OWF_PASSWORD OldNtPassword;
304     NT_OWF_PASSWORD NewNtPassword;
305     LM_OWF_PASSWORD OldLmPassword;
306     LM_OWF_PASSWORD NewLmPassword;
307     OEM_STRING LmPwdString;
308     CHAR LmPwdBuffer[15];
309     BOOLEAN OldLmPasswordPresent = FALSE;
310     BOOLEAN NewLmPasswordPresent = FALSE;
311     NTSTATUS Status;
312 
313     ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm;
314     ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm;
315     ENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt;
316     ENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt;
317     PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm = NULL;
318     PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm = NULL;
319 
320     /* Calculate the NT hash for the old password */
321     Status = SystemFunction007(OldPassword,
322                                (LPBYTE)&OldNtPassword);
323     if (!NT_SUCCESS(Status))
324     {
325         TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
326         return Status;
327     }
328 
329     /* Calculate the NT hash for the new password */
330     Status = SystemFunction007(NewPassword,
331                                (LPBYTE)&NewNtPassword);
332     if (!NT_SUCCESS(Status))
333     {
334         TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
335         return Status;
336     }
337 
338     /* Calculate the LM password and hash for the old password */
339     LmPwdString.Length = 15;
340     LmPwdString.MaximumLength = 15;
341     LmPwdString.Buffer = LmPwdBuffer;
342     ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
343 
344     Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
345                                                OldPassword,
346                                                FALSE);
347     if (NT_SUCCESS(Status))
348     {
349         /* Calculate the LM hash value of the password */
350         Status = SystemFunction006(LmPwdString.Buffer,
351                                    (LPSTR)&OldLmPassword);
352         if (NT_SUCCESS(Status))
353         {
354             OldLmPasswordPresent = TRUE;
355         }
356     }
357 
358     /* Calculate the LM password and hash for the new password */
359     LmPwdString.Length = 15;
360     LmPwdString.MaximumLength = 15;
361     LmPwdString.Buffer = LmPwdBuffer;
362     ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
363 
364     Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
365                                                NewPassword,
366                                                FALSE);
367     if (NT_SUCCESS(Status))
368     {
369         /* Calculate the LM hash value of the password */
370         Status = SystemFunction006(LmPwdString.Buffer,
371                                    (LPSTR)&NewLmPassword);
372         if (NT_SUCCESS(Status))
373         {
374             NewLmPasswordPresent = TRUE;
375         }
376     }
377 
378     if (OldLmPasswordPresent && NewLmPasswordPresent)
379     {
380         /* Encrypt the old LM hash with the new LM hash */
381         Status = SystemFunction012((const BYTE *)&OldLmPassword,
382                                    (const BYTE *)&NewLmPassword,
383                                    (LPBYTE)&OldLmEncryptedWithNewLm);
384         if (!NT_SUCCESS(Status))
385         {
386             TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
387             return Status;
388         }
389 
390         /* Encrypt the new LM hash with the old LM hash */
391         Status = SystemFunction012((const BYTE *)&NewLmPassword,
392                                    (const BYTE *)&OldLmPassword,
393                                    (LPBYTE)&NewLmEncryptedWithOldLm);
394         if (!NT_SUCCESS(Status))
395         {
396             TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
397             return Status;
398         }
399 
400         pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
401         pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
402     }
403 
404     /* Encrypt the old NT hash with the new NT hash */
405     Status = SystemFunction012((const BYTE *)&OldNtPassword,
406                                (const BYTE *)&NewNtPassword,
407                                (LPBYTE)&OldNtEncryptedWithNewNt);
408     if (!NT_SUCCESS(Status))
409     {
410         TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
411         return Status;
412     }
413 
414     /* Encrypt the new NT hash with the old NT hash */
415     Status = SystemFunction012((const BYTE *)&NewNtPassword,
416                                (const BYTE *)&OldNtPassword,
417                                (LPBYTE)&NewNtEncryptedWithOldNt);
418     if (!NT_SUCCESS(Status))
419     {
420         TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
421         return Status;
422     }
423 
424     RpcTryExcept
425     {
426         Status = SamrChangePasswordUser((SAMPR_HANDLE)UserHandle,
427                                         OldLmPasswordPresent && NewLmPasswordPresent,
428                                         pOldLmEncryptedWithNewLm,
429                                         pNewLmEncryptedWithOldLm,
430                                         TRUE,
431                                         &OldNtEncryptedWithNewNt,
432                                         &NewNtEncryptedWithOldNt,
433                                         FALSE,
434                                         NULL,
435                                         FALSE,
436                                         NULL);
437     }
438     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
439     {
440         Status = I_RpcMapWin32Status(RpcExceptionCode());
441     }
442     RpcEndExcept;
443 
444     return Status;
445 }
446 
447 
448 NTSTATUS
449 NTAPI
450 SamChangePasswordUser2(IN PUNICODE_STRING ServerName,
451                        IN PUNICODE_STRING UserName,
452                        IN PUNICODE_STRING OldPassword,
453                        IN PUNICODE_STRING NewPassword)
454 {
455     UNIMPLEMENTED;
456     return STATUS_NOT_IMPLEMENTED;
457 }
458 
459 
460 NTSTATUS
461 NTAPI
462 SamChangePasswordUser3(IN PUNICODE_STRING ServerName,
463                        IN PUNICODE_STRING UserName,
464                        IN PUNICODE_STRING OldPassword,
465                        IN PUNICODE_STRING NewPassword,
466                        OUT PDOMAIN_PASSWORD_INFORMATION *EffectivePasswordPolicy,
467                        OUT PUSER_PWD_CHANGE_FAILURE_INFORMATION *PasswordChangeFailureInfo)
468 {
469     UNIMPLEMENTED;
470     return STATUS_NOT_IMPLEMENTED;
471 }
472 
473 
474 NTSTATUS
475 NTAPI
476 SamCloseHandle(IN SAM_HANDLE SamHandle)
477 {
478     NTSTATUS Status;
479 
480     TRACE("SamCloseHandle(%p)\n", SamHandle);
481 
482     RpcTryExcept
483     {
484         Status = SamrCloseHandle((SAMPR_HANDLE *)&SamHandle);
485     }
486     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
487     {
488         Status = I_RpcMapWin32Status(RpcExceptionCode());
489     }
490     RpcEndExcept;
491 
492     return Status;
493 }
494 
495 
496 NTSTATUS
497 NTAPI
498 SamConnect(IN OUT PUNICODE_STRING ServerName OPTIONAL,
499            OUT PSAM_HANDLE ServerHandle,
500            IN ACCESS_MASK DesiredAccess,
501            IN POBJECT_ATTRIBUTES ObjectAttributes)
502 {
503     NTSTATUS Status;
504 
505     TRACE("SamConnect(%p %p 0x%08x %p)\n",
506           ServerName, ServerHandle, DesiredAccess, ObjectAttributes);
507 
508     RpcTryExcept
509     {
510         Status = SamrConnect((PSAMPR_SERVER_NAME)ServerName,
511                              (SAMPR_HANDLE *)ServerHandle,
512                              DesiredAccess);
513     }
514     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
515     {
516         Status = I_RpcMapWin32Status(RpcExceptionCode());
517     }
518     RpcEndExcept;
519 
520     return Status;
521 }
522 
523 
524 NTSTATUS
525 NTAPI
526 SamCreateAliasInDomain(IN SAM_HANDLE DomainHandle,
527                        IN PUNICODE_STRING AccountName,
528                        IN ACCESS_MASK DesiredAccess,
529                        OUT PSAM_HANDLE AliasHandle,
530                        OUT PULONG RelativeId)
531 {
532     NTSTATUS Status;
533 
534     TRACE("SamCreateAliasInDomain(%p %p 0x%08x %p %p)\n",
535           DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId);
536 
537     *AliasHandle = NULL;
538     *RelativeId = 0;
539 
540     RpcTryExcept
541     {
542         Status = SamrCreateAliasInDomain((SAMPR_HANDLE)DomainHandle,
543                                          (PRPC_UNICODE_STRING)AccountName,
544                                          DesiredAccess,
545                                          (SAMPR_HANDLE *)AliasHandle,
546                                          RelativeId);
547     }
548     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
549     {
550         Status = I_RpcMapWin32Status(RpcExceptionCode());
551     }
552     RpcEndExcept;
553 
554     return Status;
555 }
556 
557 
558 NTSTATUS
559 NTAPI
560 SamCreateGroupInDomain(IN SAM_HANDLE DomainHandle,
561                        IN PUNICODE_STRING AccountName,
562                        IN ACCESS_MASK DesiredAccess,
563                        OUT PSAM_HANDLE GroupHandle,
564                        OUT PULONG RelativeId)
565 {
566     NTSTATUS Status;
567 
568     TRACE("SamCreateGroupInDomain(%p %p 0x%08x %p %p)\n",
569           DomainHandle, AccountName, DesiredAccess, GroupHandle, RelativeId);
570 
571     *GroupHandle = NULL;
572     *RelativeId = 0;
573 
574     RpcTryExcept
575     {
576         Status = SamrCreateGroupInDomain((SAMPR_HANDLE)DomainHandle,
577                                          (PRPC_UNICODE_STRING)AccountName,
578                                          DesiredAccess,
579                                          (SAMPR_HANDLE *)GroupHandle,
580                                          RelativeId);
581     }
582     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
583     {
584         Status = I_RpcMapWin32Status(RpcExceptionCode());
585     }
586     RpcEndExcept;
587 
588     return Status;
589 }
590 
591 
592 NTSTATUS
593 NTAPI
594 SamCreateUser2InDomain(IN SAM_HANDLE DomainHandle,
595                        IN PUNICODE_STRING AccountName,
596                        IN ULONG AccountType,
597                        IN ACCESS_MASK DesiredAccess,
598                        OUT PSAM_HANDLE UserHandle,
599                        OUT PULONG GrantedAccess,
600                        OUT PULONG RelativeId)
601 {
602     NTSTATUS Status;
603 
604     TRACE("SamCreateUser2InDomain(%p %p %lu 0x%08x %p %p %p)\n",
605           DomainHandle, AccountName, AccountType, DesiredAccess,
606           UserHandle, GrantedAccess, RelativeId);
607 
608     *UserHandle = NULL;
609     *RelativeId = 0;
610 
611     RpcTryExcept
612     {
613         Status = SamrCreateUser2InDomain((SAMPR_HANDLE)DomainHandle,
614                                          (PRPC_UNICODE_STRING)AccountName,
615                                          AccountType,
616                                          DesiredAccess,
617                                          (SAMPR_HANDLE *)UserHandle,
618                                          GrantedAccess,
619                                          RelativeId);
620 
621     }
622     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
623     {
624         Status = I_RpcMapWin32Status(RpcExceptionCode());
625     }
626     RpcEndExcept;
627 
628     return Status;
629 }
630 
631 
632 NTSTATUS
633 NTAPI
634 SamCreateUserInDomain(IN SAM_HANDLE DomainHandle,
635                       IN PUNICODE_STRING AccountName,
636                       IN ACCESS_MASK DesiredAccess,
637                       OUT PSAM_HANDLE UserHandle,
638                       OUT PULONG RelativeId)
639 {
640     NTSTATUS Status;
641 
642     TRACE("SamCreateUserInDomain(%p %p 0x%08x %p %p)\n",
643           DomainHandle, AccountName, DesiredAccess, UserHandle, RelativeId);
644 
645     *UserHandle = NULL;
646     *RelativeId = 0;
647 
648     RpcTryExcept
649     {
650         Status = SamrCreateUserInDomain((SAMPR_HANDLE)DomainHandle,
651                                         (PRPC_UNICODE_STRING)AccountName,
652                                         DesiredAccess,
653                                         (SAMPR_HANDLE *)UserHandle,
654                                         RelativeId);
655     }
656     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
657     {
658         Status = I_RpcMapWin32Status(RpcExceptionCode());
659     }
660     RpcEndExcept;
661 
662     return Status;
663 }
664 
665 
666 NTSTATUS
667 NTAPI
668 SamDeleteAlias(IN SAM_HANDLE AliasHandle)
669 {
670     SAMPR_HANDLE LocalAliasHandle;
671     NTSTATUS Status;
672 
673     TRACE("SamDeleteAlias(%p)\n", AliasHandle);
674 
675     LocalAliasHandle = (SAMPR_HANDLE)AliasHandle;
676 
677     if (LocalAliasHandle == NULL)
678         return STATUS_INVALID_HANDLE;
679 
680     RpcTryExcept
681     {
682         Status = SamrDeleteAlias(&LocalAliasHandle);
683     }
684     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
685     {
686         Status = I_RpcMapWin32Status(RpcExceptionCode());
687     }
688     RpcEndExcept;
689 
690     return Status;
691 }
692 
693 
694 NTSTATUS
695 NTAPI
696 SamDeleteGroup(IN SAM_HANDLE GroupHandle)
697 {
698     SAMPR_HANDLE LocalGroupHandle;
699     NTSTATUS Status;
700 
701     TRACE("SamDeleteGroup(%p)\n", GroupHandle);
702 
703     LocalGroupHandle = (SAMPR_HANDLE)GroupHandle;
704 
705     if (LocalGroupHandle == NULL)
706         return STATUS_INVALID_HANDLE;
707 
708     RpcTryExcept
709     {
710         Status = SamrDeleteGroup(&LocalGroupHandle);
711     }
712     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
713     {
714         Status = I_RpcMapWin32Status(RpcExceptionCode());
715     }
716     RpcEndExcept;
717 
718     return Status;
719 }
720 
721 
722 NTSTATUS
723 NTAPI
724 SamDeleteUser(IN SAM_HANDLE UserHandle)
725 {
726     SAMPR_HANDLE LocalUserHandle;
727     NTSTATUS Status;
728 
729     TRACE("SamDeleteUser(%p)\n", UserHandle);
730 
731     LocalUserHandle = (SAMPR_HANDLE)UserHandle;
732 
733     if (LocalUserHandle == NULL)
734         return STATUS_INVALID_HANDLE;
735 
736     RpcTryExcept
737     {
738         Status = SamrDeleteUser(&LocalUserHandle);
739     }
740     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
741     {
742         Status = I_RpcMapWin32Status(RpcExceptionCode());
743     }
744     RpcEndExcept;
745 
746     return Status;
747 }
748 
749 
750 NTSTATUS
751 NTAPI
752 SamEnumerateAliasesInDomain(IN SAM_HANDLE DomainHandle,
753                             IN OUT PSAM_ENUMERATE_HANDLE EnumerationContext,
754                             OUT PVOID *Buffer,
755                             IN ULONG PreferedMaximumLength,
756                             OUT PULONG CountReturned)
757 {
758     PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
759     NTSTATUS Status;
760 
761     TRACE("SamEnumerateAliasesInDomain(%p %p %p %lu %p)\n",
762           DomainHandle, EnumerationContext, Buffer, PreferedMaximumLength,
763           CountReturned);
764 
765     if ((EnumerationContext == NULL) ||
766         (Buffer == NULL) ||
767         (CountReturned == NULL))
768         return STATUS_INVALID_PARAMETER;
769 
770     *Buffer = NULL;
771 
772     RpcTryExcept
773     {
774         Status = SamrEnumerateAliasesInDomain((SAMPR_HANDLE)DomainHandle,
775                                               EnumerationContext,
776                                               &EnumBuffer,
777                                               PreferedMaximumLength,
778                                               CountReturned);
779 
780         if (EnumBuffer != NULL)
781         {
782             if (EnumBuffer->Buffer != NULL)
783             {
784                 *Buffer = EnumBuffer->Buffer;
785             }
786 
787             midl_user_free(EnumBuffer);
788         }
789     }
790     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
791     {
792         Status = I_RpcMapWin32Status(RpcExceptionCode());
793     }
794     RpcEndExcept;
795 
796     return Status;
797 }
798 
799 
800 NTSTATUS
801 NTAPI
802 SamEnumerateDomainsInSamServer(IN SAM_HANDLE ServerHandle,
803                                IN OUT PSAM_ENUMERATE_HANDLE EnumerationContext,
804                                OUT PVOID *Buffer,
805                                IN ULONG PreferedMaximumLength,
806                                OUT PULONG CountReturned)
807 {
808     PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
809     NTSTATUS Status;
810 
811     TRACE("SamEnumerateDomainsInSamServer(%p %p %p %lu %p)\n",
812           ServerHandle, EnumerationContext, Buffer, PreferedMaximumLength,
813           CountReturned);
814 
815     if ((EnumerationContext == NULL) ||
816         (Buffer == NULL) ||
817         (CountReturned == NULL))
818         return STATUS_INVALID_PARAMETER;
819 
820     *Buffer = NULL;
821 
822     RpcTryExcept
823     {
824         Status = SamrEnumerateDomainsInSamServer((SAMPR_HANDLE)ServerHandle,
825                                                  EnumerationContext,
826                                                  &EnumBuffer,
827                                                  PreferedMaximumLength,
828                                                  CountReturned);
829 
830         if (EnumBuffer != NULL)
831         {
832             if (EnumBuffer->Buffer != NULL)
833             {
834                 *Buffer = EnumBuffer->Buffer;
835             }
836 
837             midl_user_free(EnumBuffer);
838         }
839     }
840     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
841     {
842         Status = I_RpcMapWin32Status(RpcExceptionCode());
843     }
844     RpcEndExcept;
845 
846     return Status;
847 }
848 
849 
850 NTSTATUS
851 NTAPI
852 SamEnumerateGroupsInDomain(IN SAM_HANDLE DomainHandle,
853                            IN OUT PSAM_ENUMERATE_HANDLE EnumerationContext,
854                            IN PVOID *Buffer,
855                            IN ULONG PreferedMaximumLength,
856                            OUT PULONG CountReturned)
857 {
858     PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
859     NTSTATUS Status;
860 
861     TRACE("SamEnumerateGroupsInDomain(%p %p %p %lu %p)\n",
862           DomainHandle, EnumerationContext, Buffer,
863           PreferedMaximumLength, CountReturned);
864 
865     if (EnumerationContext == NULL || Buffer == NULL || CountReturned == NULL)
866         return STATUS_INVALID_PARAMETER;
867 
868     *Buffer = NULL;
869 
870     RpcTryExcept
871     {
872         Status = SamrEnumerateGroupsInDomain((SAMPR_HANDLE)DomainHandle,
873                                              EnumerationContext,
874                                              &EnumBuffer,
875                                              PreferedMaximumLength,
876                                              CountReturned);
877         if (EnumBuffer != NULL)
878         {
879             if (EnumBuffer->Buffer != NULL)
880                 *Buffer = EnumBuffer->Buffer;
881 
882             midl_user_free(EnumBuffer);
883         }
884     }
885     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
886     {
887         Status = I_RpcMapWin32Status(RpcExceptionCode());
888     }
889     RpcEndExcept;
890 
891     return Status;
892 }
893 
894 
895 NTSTATUS
896 NTAPI
897 SamEnumerateUsersInDomain(IN SAM_HANDLE DomainHandle,
898                           IN OUT PSAM_ENUMERATE_HANDLE EnumerationContext,
899                           IN ULONG UserAccountControl,
900                           OUT PVOID *Buffer,
901                           IN ULONG PreferedMaximumLength,
902                           OUT PULONG CountReturned)
903 {
904     PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
905     NTSTATUS Status;
906 
907     TRACE("SamEnumerateUsersInDomain(%p %p %lx %p %lu %p)\n",
908           DomainHandle, EnumerationContext, UserAccountControl, Buffer,
909           PreferedMaximumLength, CountReturned);
910 
911     if (EnumerationContext == NULL || Buffer == NULL || CountReturned == NULL)
912         return STATUS_INVALID_PARAMETER;
913 
914     *Buffer = NULL;
915 
916     RpcTryExcept
917     {
918         Status = SamrEnumerateUsersInDomain((SAMPR_HANDLE)DomainHandle,
919                                             EnumerationContext,
920                                             UserAccountControl,
921                                             &EnumBuffer,
922                                             PreferedMaximumLength,
923                                             CountReturned);
924         if (EnumBuffer != NULL)
925         {
926             if (EnumBuffer->Buffer != NULL)
927             {
928                 *Buffer = EnumBuffer->Buffer;
929             }
930 
931             midl_user_free(EnumBuffer);
932         }
933 
934     }
935     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
936     {
937         Status = I_RpcMapWin32Status(RpcExceptionCode());
938     }
939     RpcEndExcept;
940 
941     return Status;
942 }
943 
944 
945 NTSTATUS
946 NTAPI
947 SamFreeMemory(IN PVOID Buffer)
948 {
949     if (Buffer != NULL)
950         midl_user_free(Buffer);
951 
952     return STATUS_SUCCESS;
953 }
954 
955 
956 NTSTATUS
957 NTAPI
958 SamGetAliasMembership(IN SAM_HANDLE DomainHandle,
959                       IN ULONG PassedCount,
960                       IN PSID *Sids,
961                       OUT PULONG MembershipCount,
962                       OUT PULONG *Aliases)
963 {
964     SAMPR_PSID_ARRAY SidArray;
965     SAMPR_ULONG_ARRAY Membership;
966     NTSTATUS Status;
967 
968     TRACE("SamAliasMembership(%p %lu %p %p %p)\n",
969           DomainHandle, PassedCount, Sids, MembershipCount, Aliases);
970 
971     if (Sids == NULL ||
972         MembershipCount == NULL ||
973         Aliases == NULL)
974         return STATUS_INVALID_PARAMETER;
975 
976     Membership.Element = NULL;
977 
978     RpcTryExcept
979     {
980         SidArray.Count = PassedCount;
981         SidArray.Sids = (PSAMPR_SID_INFORMATION)Sids;
982 
983         Status = SamrGetAliasMembership((SAMPR_HANDLE)DomainHandle,
984                                         &SidArray,
985                                         &Membership);
986         if (NT_SUCCESS(Status))
987         {
988             *MembershipCount = Membership.Count;
989             *Aliases = Membership.Element;
990         }
991         else
992         {
993             if (Membership.Element != NULL)
994                 midl_user_free(Membership.Element);
995         }
996     }
997     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
998     {
999         Status = I_RpcMapWin32Status(RpcExceptionCode());
1000     }
1001     RpcEndExcept;
1002 
1003     return Status;
1004 }
1005 
1006 
1007 NTSTATUS
1008 NTAPI
1009 SamGetCompatibilityMode(IN SAM_HANDLE ObjectHandle,
1010                         OUT PULONG Mode)
1011 {
1012     TRACE("(%p %p)\n", ObjectHandle, Mode);
1013 
1014     if (Mode == NULL)
1015         return STATUS_INVALID_PARAMETER;
1016 
1017     *Mode = SAM_SID_COMPATIBILITY_ALL;
1018 
1019     return STATUS_SUCCESS;
1020 }
1021 
1022 
1023 NTSTATUS
1024 NTAPI
1025 SamGetDisplayEnumerationIndex(IN SAM_HANDLE DomainHandle,
1026                               IN DOMAIN_DISPLAY_INFORMATION DisplayInformation,
1027                               IN PUNICODE_STRING Prefix,
1028                               OUT PULONG Index)
1029 {
1030     NTSTATUS Status;
1031 
1032     TRACE("(%p %lu %wZ %p)\n",
1033            DomainHandle, DisplayInformation, Prefix, Index);
1034 
1035     if ((Prefix == NULL) ||
1036         (Index == NULL))
1037         return STATUS_INVALID_PARAMETER;
1038 
1039     RpcTryExcept
1040     {
1041         Status = SamrGetDisplayEnumerationIndex2((SAMPR_HANDLE)DomainHandle,
1042                                                  DisplayInformation,
1043                                                  (PRPC_UNICODE_STRING)Prefix,
1044                                                  Index);
1045     }
1046     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1047     {
1048         Status = I_RpcMapWin32Status(RpcExceptionCode());
1049     }
1050     RpcEndExcept;
1051 
1052     return Status;
1053 }
1054 
1055 
1056 NTSTATUS
1057 NTAPI
1058 SamGetGroupsForUser(IN SAM_HANDLE UserHandle,
1059                     OUT PGROUP_MEMBERSHIP *Groups,
1060                     OUT PULONG MembershipCount)
1061 {
1062     PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL;
1063     NTSTATUS Status;
1064 
1065     TRACE("SamGetGroupsForUser(%p %p %p)\n",
1066           UserHandle, Groups, MembershipCount);
1067 
1068     RpcTryExcept
1069     {
1070         Status = SamrGetGroupsForUser((SAMPR_HANDLE)UserHandle,
1071                                       &GroupsBuffer);
1072         if (NT_SUCCESS(Status))
1073         {
1074             *Groups = GroupsBuffer->Groups;
1075             *MembershipCount = GroupsBuffer->MembershipCount;
1076 
1077             MIDL_user_free(GroupsBuffer);
1078         }
1079         else
1080         {
1081             if (GroupsBuffer != NULL)
1082             {
1083                 if (GroupsBuffer->Groups != NULL)
1084                     MIDL_user_free(GroupsBuffer->Groups);
1085 
1086                 MIDL_user_free(GroupsBuffer);
1087             }
1088         }
1089     }
1090     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1091     {
1092         Status = I_RpcMapWin32Status(RpcExceptionCode());
1093     }
1094     RpcEndExcept;
1095 
1096     return Status;
1097 }
1098 
1099 
1100 NTSTATUS
1101 NTAPI
1102 SamGetMembersInAlias(IN SAM_HANDLE AliasHandle,
1103                      OUT PSID **MemberIds,
1104                      OUT PULONG MemberCount)
1105 {
1106     SAMPR_PSID_ARRAY_OUT SidArray;
1107     NTSTATUS Status;
1108 
1109     TRACE("SamGetMembersInAlias(%p %p %p)\n",
1110           AliasHandle, MemberIds, MemberCount);
1111 
1112     if ((MemberIds == NULL) ||
1113         (MemberCount == NULL))
1114         return STATUS_INVALID_PARAMETER;
1115 
1116     *MemberIds = NULL;
1117     *MemberCount = 0;
1118 
1119     SidArray.Sids = NULL;
1120 
1121     RpcTryExcept
1122     {
1123         Status = SamrGetMembersInAlias((SAMPR_HANDLE)AliasHandle,
1124                                        &SidArray);
1125         if (NT_SUCCESS(Status))
1126         {
1127             *MemberCount = SidArray.Count;
1128             *MemberIds = (PSID *)SidArray.Sids;
1129         }
1130 
1131     }
1132     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1133     {
1134         Status = I_RpcMapWin32Status(RpcExceptionCode());
1135     }
1136     RpcEndExcept;
1137 
1138     return Status;
1139 }
1140 
1141 
1142 NTSTATUS
1143 NTAPI
1144 SamGetMembersInGroup(IN SAM_HANDLE GroupHandle,
1145                      OUT PULONG *MemberIds,
1146                      OUT PULONG *Attributes,
1147                      OUT PULONG MemberCount)
1148 {
1149     PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL;
1150     NTSTATUS Status;
1151 
1152     TRACE("SamGetMembersInGroup(%p %p %p %p)\n",
1153           GroupHandle, MemberIds, Attributes, MemberCount);
1154 
1155     RpcTryExcept
1156     {
1157         Status = SamrGetMembersInGroup((SAMPR_HANDLE)GroupHandle,
1158                                        &MembersBuffer);
1159         if (NT_SUCCESS(Status))
1160         {
1161             *MemberIds = MembersBuffer->Members;
1162             *Attributes = MembersBuffer->Attributes;
1163             *MemberCount = MembersBuffer->MemberCount;
1164 
1165             MIDL_user_free(MembersBuffer);
1166         }
1167         else
1168         {
1169             if (MembersBuffer != NULL)
1170             {
1171                 if (MembersBuffer->Members != NULL)
1172                     MIDL_user_free(MembersBuffer->Members);
1173 
1174                 if (MembersBuffer->Attributes != NULL)
1175                     MIDL_user_free(MembersBuffer->Attributes);
1176 
1177                 MIDL_user_free(MembersBuffer);
1178             }
1179         }
1180     }
1181     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1182     {
1183         Status = I_RpcMapWin32Status(RpcExceptionCode());
1184     }
1185     RpcEndExcept;
1186 
1187     return Status;
1188 }
1189 
1190 
1191 NTSTATUS
1192 NTAPI
1193 SamLookupDomainInSamServer(IN SAM_HANDLE ServerHandle,
1194                            IN PUNICODE_STRING Name,
1195                            OUT PSID *DomainId)
1196 {
1197     NTSTATUS Status;
1198 
1199     TRACE("SamLookupDomainInSamServer(%p %p %p)\n",
1200           ServerHandle, Name, DomainId);
1201 
1202     RpcTryExcept
1203     {
1204         Status = SamrLookupDomainInSamServer((SAMPR_HANDLE)ServerHandle,
1205                                              (PRPC_UNICODE_STRING)Name,
1206                                              (PRPC_SID *)DomainId);
1207     }
1208     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1209     {
1210         Status = I_RpcMapWin32Status(RpcExceptionCode());
1211     }
1212     RpcEndExcept;
1213 
1214     return Status;
1215 }
1216 
1217 
1218 NTSTATUS
1219 NTAPI
1220 SamLookupIdsInDomain(IN SAM_HANDLE DomainHandle,
1221                      IN ULONG Count,
1222                      IN PULONG RelativeIds,
1223                      OUT PUNICODE_STRING *Names,
1224                      OUT PSID_NAME_USE *Use OPTIONAL)
1225 {
1226     SAMPR_RETURNED_USTRING_ARRAY NamesBuffer = {0, NULL};
1227     SAMPR_ULONG_ARRAY UseBuffer = {0, NULL};
1228     ULONG i;
1229     NTSTATUS Status;
1230 
1231     TRACE("SamLookupIdsInDomain(%p %lu %p %p %p)\n",
1232           DomainHandle, Count, RelativeIds, Names, Use);
1233 
1234     *Names = NULL;
1235 
1236     if (Use != NULL)
1237         *Use = NULL;
1238 
1239     RpcTryExcept
1240     {
1241         Status = SamrLookupIdsInDomain((SAMPR_HANDLE)DomainHandle,
1242                                        Count,
1243                                        RelativeIds,
1244                                        &NamesBuffer,
1245                                        &UseBuffer);
1246     }
1247     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1248     {
1249         Status = I_RpcMapWin32Status(RpcExceptionCode());
1250     }
1251     RpcEndExcept;
1252 
1253     if (NT_SUCCESS(Status))
1254     {
1255         *Names = midl_user_allocate(Count * sizeof(RPC_UNICODE_STRING));
1256         if (*Names == NULL)
1257         {
1258             Status = STATUS_INSUFFICIENT_RESOURCES;
1259             goto done;
1260         }
1261 
1262         for (i = 0; i < Count; i++)
1263         {
1264             (*Names)[i].Buffer = midl_user_allocate(NamesBuffer.Element[i].MaximumLength);
1265             if ((*Names)[i].Buffer == NULL)
1266             {
1267                 Status = STATUS_INSUFFICIENT_RESOURCES;
1268                 goto done;
1269             }
1270         }
1271 
1272         for (i = 0; i < Count; i++)
1273         {
1274             (*Names)[i].Length = NamesBuffer.Element[i].Length;
1275             (*Names)[i].MaximumLength = NamesBuffer.Element[i].MaximumLength;
1276 
1277             RtlCopyMemory((*Names)[i].Buffer,
1278                           NamesBuffer.Element[i].Buffer,
1279                           NamesBuffer.Element[i].Length);
1280         }
1281 
1282         if (Use != NULL)
1283         {
1284             *Use = midl_user_allocate(Count * sizeof(SID_NAME_USE));
1285             if (*Use == NULL)
1286             {
1287                 Status = STATUS_INSUFFICIENT_RESOURCES;
1288                 goto done;
1289             }
1290 
1291             RtlCopyMemory(*Use,
1292                           UseBuffer.Element,
1293                           Count * sizeof(SID_NAME_USE));
1294         }
1295     }
1296 
1297 done:
1298     if (!NT_SUCCESS(Status))
1299     {
1300         if (*Names != NULL)
1301         {
1302             for (i = 0; i < Count; i++)
1303             {
1304                 if ((*Names)[i].Buffer != NULL)
1305                     midl_user_free((*Names)[i].Buffer);
1306             }
1307 
1308             midl_user_free(*Names);
1309         }
1310 
1311         if (Use != NULL && *Use != NULL)
1312             midl_user_free(*Use);
1313     }
1314 
1315     if (NamesBuffer.Element != NULL)
1316     {
1317         for (i = 0; i < NamesBuffer.Count; i++)
1318         {
1319             if (NamesBuffer.Element[i].Buffer != NULL)
1320                 midl_user_free(NamesBuffer.Element[i].Buffer);
1321         }
1322 
1323         midl_user_free(NamesBuffer.Element);
1324     }
1325 
1326     if (UseBuffer.Element != NULL)
1327         midl_user_free(UseBuffer.Element);
1328 
1329     return 0;
1330 }
1331 
1332 
1333 NTSTATUS
1334 NTAPI
1335 SamLookupNamesInDomain(IN SAM_HANDLE DomainHandle,
1336                        IN ULONG Count,
1337                        IN PUNICODE_STRING Names,
1338                        OUT PULONG *RelativeIds,
1339                        OUT PSID_NAME_USE *Use)
1340 {
1341     SAMPR_ULONG_ARRAY RidBuffer = {0, NULL};
1342     SAMPR_ULONG_ARRAY UseBuffer = {0, NULL};
1343     NTSTATUS Status;
1344 
1345     TRACE("SamLookupNamesInDomain(%p %lu %p %p %p)\n",
1346           DomainHandle, Count, Names, RelativeIds, Use);
1347 
1348     *RelativeIds = NULL;
1349     *Use = NULL;
1350 
1351     RpcTryExcept
1352     {
1353         Status = SamrLookupNamesInDomain((SAMPR_HANDLE)DomainHandle,
1354                                          Count,
1355                                          (PRPC_UNICODE_STRING)Names,
1356                                          &RidBuffer,
1357                                          &UseBuffer);
1358     }
1359     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1360     {
1361         Status = I_RpcMapWin32Status(RpcExceptionCode());
1362     }
1363     RpcEndExcept;
1364 
1365     if (NT_SUCCESS(Status))
1366     {
1367         *RelativeIds = midl_user_allocate(Count * sizeof(ULONG));
1368         if (*RelativeIds == NULL)
1369         {
1370             Status = STATUS_INSUFFICIENT_RESOURCES;
1371             goto done;
1372         }
1373 
1374         *Use = midl_user_allocate(Count * sizeof(SID_NAME_USE));
1375         if (*Use == NULL)
1376         {
1377             Status = STATUS_INSUFFICIENT_RESOURCES;
1378             goto done;
1379         }
1380 
1381         RtlCopyMemory(*RelativeIds,
1382                       RidBuffer.Element,
1383                       Count * sizeof(ULONG));
1384 
1385         RtlCopyMemory(*Use,
1386                       UseBuffer.Element,
1387                       Count * sizeof(SID_NAME_USE));
1388     }
1389 
1390 done:
1391     if (!NT_SUCCESS(Status))
1392     {
1393         if (*RelativeIds != NULL)
1394             midl_user_free(*RelativeIds);
1395 
1396         if (*Use != NULL)
1397             midl_user_free(*Use);
1398     }
1399 
1400     if (RidBuffer.Element != NULL)
1401         midl_user_free(RidBuffer.Element);
1402 
1403     if (UseBuffer.Element != NULL)
1404         midl_user_free(UseBuffer.Element);
1405 
1406     return Status;
1407 }
1408 
1409 
1410 NTSTATUS
1411 NTAPI
1412 SamOpenAlias(IN SAM_HANDLE DomainHandle,
1413              IN ACCESS_MASK DesiredAccess,
1414              IN ULONG AliasId,
1415              OUT PSAM_HANDLE AliasHandle)
1416 {
1417     NTSTATUS Status;
1418 
1419     TRACE("SamOpenAlias(%p 0x%08x %lx %p)\n",
1420           DomainHandle, DesiredAccess, AliasId, AliasHandle);
1421 
1422     RpcTryExcept
1423     {
1424         Status = SamrOpenAlias((SAMPR_HANDLE)DomainHandle,
1425                                DesiredAccess,
1426                                AliasId,
1427                                (SAMPR_HANDLE *)AliasHandle);
1428     }
1429     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1430     {
1431         Status = I_RpcMapWin32Status(RpcExceptionCode());
1432     }
1433     RpcEndExcept;
1434 
1435     return Status;
1436 }
1437 
1438 
1439 NTSTATUS
1440 NTAPI
1441 SamOpenDomain(IN SAM_HANDLE ServerHandle,
1442               IN ACCESS_MASK DesiredAccess,
1443               IN PSID DomainId,
1444               OUT PSAM_HANDLE DomainHandle)
1445 {
1446     NTSTATUS Status;
1447 
1448     TRACE("SamOpenDomain(%p 0x%08x %p %p)\n",
1449           ServerHandle, DesiredAccess, DomainId, DomainHandle);
1450 
1451     RpcTryExcept
1452     {
1453         Status = SamrOpenDomain((SAMPR_HANDLE)ServerHandle,
1454                                 DesiredAccess,
1455                                 (PRPC_SID)DomainId,
1456                                 (SAMPR_HANDLE *)DomainHandle);
1457     }
1458     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1459     {
1460         Status = I_RpcMapWin32Status(RpcExceptionCode());
1461     }
1462     RpcEndExcept;
1463 
1464     return Status;
1465 }
1466 
1467 
1468 NTSTATUS
1469 NTAPI
1470 SamOpenGroup(IN SAM_HANDLE DomainHandle,
1471              IN ACCESS_MASK DesiredAccess,
1472              IN ULONG GroupId,
1473              OUT PSAM_HANDLE GroupHandle)
1474 {
1475     NTSTATUS Status;
1476 
1477     TRACE("SamOpenGroup(%p 0x%08x %p %p)\n",
1478           DomainHandle, DesiredAccess, GroupId, GroupHandle);
1479 
1480     RpcTryExcept
1481     {
1482         Status = SamrOpenGroup((SAMPR_HANDLE)DomainHandle,
1483                                DesiredAccess,
1484                                GroupId,
1485                                (SAMPR_HANDLE *)GroupHandle);
1486     }
1487     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1488     {
1489         Status = I_RpcMapWin32Status(RpcExceptionCode());
1490     }
1491     RpcEndExcept;
1492 
1493     return Status;
1494 }
1495 
1496 
1497 NTSTATUS
1498 NTAPI
1499 SamOpenUser(IN SAM_HANDLE DomainHandle,
1500             IN ACCESS_MASK DesiredAccess,
1501             IN ULONG UserId,
1502             OUT PSAM_HANDLE UserHandle)
1503 {
1504     NTSTATUS Status;
1505 
1506     TRACE("SamOpenUser(%p 0x%08x %lx %p)\n",
1507           DomainHandle, DesiredAccess, UserId, UserHandle);
1508 
1509     RpcTryExcept
1510     {
1511         Status = SamrOpenUser((SAMPR_HANDLE)DomainHandle,
1512                               DesiredAccess,
1513                               UserId,
1514                               (SAMPR_HANDLE *)UserHandle);
1515     }
1516     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1517     {
1518         Status = I_RpcMapWin32Status(RpcExceptionCode());
1519     }
1520     RpcEndExcept;
1521 
1522     return Status;
1523 }
1524 
1525 
1526 NTSTATUS
1527 NTAPI
1528 SamQueryDisplayInformation(IN SAM_HANDLE DomainHandle,
1529                            IN DOMAIN_DISPLAY_INFORMATION DisplayInformation,
1530                            IN ULONG Index,
1531                            IN ULONG EntryCount,
1532                            IN ULONG PreferredMaximumLength,
1533                            OUT PULONG TotalAvailable,
1534                            OUT PULONG TotalReturned,
1535                            OUT PULONG ReturnedEntryCount,
1536                            OUT PVOID *SortedBuffer)
1537 {
1538     SAMPR_DISPLAY_INFO_BUFFER LocalBuffer;
1539     NTSTATUS Status;
1540 
1541     TRACE("(%p %lu %lu %lu %lu %p %p %p %p)\n",
1542           DomainHandle, DisplayInformation, Index, EntryCount,
1543           PreferredMaximumLength, TotalAvailable, TotalReturned,
1544           ReturnedEntryCount, SortedBuffer);
1545 
1546     if ((TotalAvailable == NULL) ||
1547         (TotalReturned == NULL) ||
1548         (ReturnedEntryCount == NULL) ||
1549         (SortedBuffer == NULL))
1550         return STATUS_INVALID_PARAMETER;
1551 
1552     RpcTryExcept
1553     {
1554         Status = SamrQueryDisplayInformation3((SAMPR_HANDLE)DomainHandle,
1555                                               DisplayInformation,
1556                                               Index,
1557                                               EntryCount,
1558                                               PreferredMaximumLength,
1559                                               TotalAvailable,
1560                                               TotalReturned,
1561                                               &LocalBuffer);
1562         if (NT_SUCCESS(Status))
1563         {
1564             switch (DisplayInformation)
1565             {
1566                 case DomainDisplayUser:
1567                     *ReturnedEntryCount = LocalBuffer.UserInformation.EntriesRead;
1568                     *SortedBuffer = LocalBuffer.UserInformation.Buffer;
1569                     break;
1570 
1571                 case DomainDisplayMachine:
1572                     *ReturnedEntryCount = LocalBuffer.MachineInformation.EntriesRead;
1573                     *SortedBuffer = LocalBuffer.MachineInformation.Buffer;
1574                     break;
1575 
1576                 case DomainDisplayGroup:
1577                     *ReturnedEntryCount = LocalBuffer.GroupInformation.EntriesRead;
1578                     *SortedBuffer = LocalBuffer.GroupInformation.Buffer;
1579                     break;
1580 
1581                 case DomainDisplayOemUser:
1582                     *ReturnedEntryCount = LocalBuffer.OemUserInformation.EntriesRead;
1583                     *SortedBuffer = LocalBuffer.OemUserInformation.Buffer;
1584                     break;
1585 
1586                 case DomainDisplayOemGroup:
1587                     *ReturnedEntryCount = LocalBuffer.OemGroupInformation.EntriesRead;
1588                     *SortedBuffer = LocalBuffer.OemGroupInformation.Buffer;
1589                     break;
1590 
1591                 case DomainDisplayServer:
1592                     /* FIXME */
1593                     break;
1594             }
1595         }
1596         else
1597         {
1598             *ReturnedEntryCount = 0;
1599             *SortedBuffer = NULL;
1600         }
1601     }
1602     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1603     {
1604         Status = I_RpcMapWin32Status(RpcExceptionCode());
1605     }
1606     RpcEndExcept;
1607 
1608     return Status;
1609 }
1610 
1611 
1612 NTSTATUS
1613 NTAPI
1614 SamQueryInformationAlias(IN SAM_HANDLE AliasHandle,
1615                          IN ALIAS_INFORMATION_CLASS AliasInformationClass,
1616                          OUT PVOID *Buffer)
1617 {
1618     NTSTATUS Status;
1619 
1620     TRACE("SamQueryInformationAlias(%p %lu %p)\n",
1621           AliasHandle, AliasInformationClass, Buffer);
1622 
1623     RpcTryExcept
1624     {
1625         Status = SamrQueryInformationAlias((SAMPR_HANDLE)AliasHandle,
1626                                            AliasInformationClass,
1627                                            (PSAMPR_ALIAS_INFO_BUFFER *)Buffer);
1628     }
1629     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1630     {
1631         Status = I_RpcMapWin32Status(RpcExceptionCode());
1632     }
1633     RpcEndExcept;
1634 
1635     return Status;
1636 }
1637 
1638 
1639 NTSTATUS
1640 NTAPI
1641 SamQueryInformationDomain(IN SAM_HANDLE DomainHandle,
1642                           IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1643                           OUT PVOID *Buffer)
1644 {
1645     NTSTATUS Status;
1646 
1647     TRACE("SamQueryInformationDomain(%p %lu %p)\n",
1648           DomainHandle, DomainInformationClass, Buffer);
1649 
1650     RpcTryExcept
1651     {
1652         Status = SamrQueryInformationDomain((SAMPR_HANDLE)DomainHandle,
1653                                             DomainInformationClass,
1654                                             (PSAMPR_DOMAIN_INFO_BUFFER *)Buffer);
1655     }
1656     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1657     {
1658         Status = I_RpcMapWin32Status(RpcExceptionCode());
1659     }
1660     RpcEndExcept;
1661 
1662     return Status;
1663 }
1664 
1665 
1666 NTSTATUS
1667 NTAPI
1668 SamQueryInformationGroup(IN SAM_HANDLE GroupHandle,
1669                          IN GROUP_INFORMATION_CLASS GroupInformationClass,
1670                          OUT PVOID *Buffer)
1671 {
1672     NTSTATUS Status;
1673 
1674     TRACE("SamQueryInformationGroup(%p %lu %p)\n",
1675           GroupHandle, GroupInformationClass, Buffer);
1676 
1677     RpcTryExcept
1678     {
1679         Status = SamrQueryInformationGroup((SAMPR_HANDLE)GroupHandle,
1680                                            GroupInformationClass,
1681                                            (PSAMPR_GROUP_INFO_BUFFER *)Buffer);
1682     }
1683     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1684     {
1685         Status = I_RpcMapWin32Status(RpcExceptionCode());
1686     }
1687     RpcEndExcept;
1688 
1689     return Status;
1690 }
1691 
1692 
1693 NTSTATUS
1694 NTAPI
1695 SamQueryInformationUser(IN SAM_HANDLE UserHandle,
1696                         IN USER_INFORMATION_CLASS UserInformationClass,
1697                         OUT PVOID *Buffer)
1698 {
1699     NTSTATUS Status;
1700 
1701     TRACE("SamQueryInformationUser(%p %lu %p)\n",
1702           UserHandle, UserInformationClass, Buffer);
1703 
1704     RpcTryExcept
1705     {
1706         Status = SamrQueryInformationUser((SAMPR_HANDLE)UserHandle,
1707                                           UserInformationClass,
1708                                           (PSAMPR_USER_INFO_BUFFER *)Buffer);
1709     }
1710     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1711     {
1712         Status = I_RpcMapWin32Status(RpcExceptionCode());
1713     }
1714     RpcEndExcept;
1715 
1716     return Status;
1717 }
1718 
1719 
1720 NTSTATUS
1721 NTAPI
1722 SamQuerySecurityObject(IN SAM_HANDLE ObjectHandle,
1723                        IN SECURITY_INFORMATION SecurityInformation,
1724                        OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
1725 {
1726     PSAMPR_SR_SECURITY_DESCRIPTOR SamSecurityDescriptor = NULL;
1727     NTSTATUS Status;
1728 
1729     TRACE("SamQuerySecurityObject(%p %lu %p)\n",
1730           ObjectHandle, SecurityInformation, SecurityDescriptor);
1731 
1732     *SecurityDescriptor = NULL;
1733 
1734     RpcTryExcept
1735     {
1736         Status = SamrQuerySecurityObject((SAMPR_HANDLE)ObjectHandle,
1737                                          SecurityInformation,
1738                                          &SamSecurityDescriptor);
1739     }
1740     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1741     {
1742         Status = I_RpcMapWin32Status(RpcExceptionCode());
1743     }
1744     RpcEndExcept;
1745 
1746     TRACE("SamSecurityDescriptor: %p\n", SamSecurityDescriptor);
1747 
1748     if (SamSecurityDescriptor != NULL)
1749     {
1750         TRACE("SamSecurityDescriptor->Length: %lu\n", SamSecurityDescriptor->Length);
1751         TRACE("SamSecurityDescriptor->SecurityDescriptor: %p\n", SamSecurityDescriptor->SecurityDescriptor);
1752 
1753         *SecurityDescriptor = SamSecurityDescriptor->SecurityDescriptor;
1754 
1755         midl_user_free(SamSecurityDescriptor);
1756     }
1757 
1758     return Status;
1759 }
1760 
1761 
1762 NTSTATUS
1763 NTAPI
1764 SamRemoveMemberFromAlias(IN SAM_HANDLE AliasHandle,
1765                          IN PSID MemberId)
1766 {
1767     NTSTATUS Status;
1768 
1769     TRACE("SamRemoveMemberFromAlias(%p %ul)\n",
1770           AliasHandle, MemberId);
1771 
1772     RpcTryExcept
1773     {
1774         Status = SamrRemoveMemberFromAlias((SAMPR_HANDLE)AliasHandle,
1775                                            MemberId);
1776     }
1777     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1778     {
1779         Status = I_RpcMapWin32Status(RpcExceptionCode());
1780     }
1781     RpcEndExcept;
1782 
1783     return Status;
1784 }
1785 
1786 
1787 NTSTATUS
1788 NTAPI
1789 SamRemoveMemberFromForeignDomain(IN SAM_HANDLE DomainHandle,
1790                                  IN PSID MemberId)
1791 {
1792     NTSTATUS Status;
1793 
1794     TRACE("SamRemoveMemberFromForeignDomain(%p %ul)\n",
1795           DomainHandle, MemberId);
1796 
1797     RpcTryExcept
1798     {
1799         Status = SamrRemoveMemberFromForeignDomain((SAMPR_HANDLE)DomainHandle,
1800                                                    MemberId);
1801     }
1802     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1803     {
1804         Status = I_RpcMapWin32Status(RpcExceptionCode());
1805     }
1806     RpcEndExcept;
1807 
1808     return Status;
1809 }
1810 
1811 
1812 NTSTATUS
1813 NTAPI
1814 SamRemoveMemberFromGroup(IN SAM_HANDLE GroupHandle,
1815                          IN ULONG MemberId)
1816 {
1817     NTSTATUS Status;
1818 
1819     TRACE("SamRemoveMemberFromGroup(%p %ul)\n",
1820           GroupHandle, MemberId);
1821 
1822     RpcTryExcept
1823     {
1824         Status = SamrRemoveMemberFromGroup((SAMPR_HANDLE)GroupHandle,
1825                                            MemberId);
1826     }
1827     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1828     {
1829         Status = I_RpcMapWin32Status(RpcExceptionCode());
1830     }
1831     RpcEndExcept;
1832 
1833     return Status;
1834 }
1835 
1836 
1837 NTSTATUS
1838 NTAPI
1839 SamRemoveMultipleMembersFromAlias(IN SAM_HANDLE AliasHandle,
1840                                   IN PSID *MemberIds,
1841                                   IN ULONG MemberCount)
1842 {
1843     SAMPR_PSID_ARRAY Buffer;
1844     NTSTATUS Status;
1845 
1846     TRACE("SamRemoveMultipleMembersFromAlias(%p %p %lu)\n",
1847           AliasHandle, MemberIds, MemberCount);
1848 
1849     if (MemberIds == NULL)
1850         return STATUS_INVALID_PARAMETER_2;
1851 
1852     Buffer.Count = MemberCount;
1853     Buffer.Sids = (PSAMPR_SID_INFORMATION)MemberIds;
1854 
1855     RpcTryExcept
1856     {
1857         Status = SamrRemoveMultipleMembersFromAlias((SAMPR_HANDLE)AliasHandle,
1858                                                     &Buffer);
1859     }
1860     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1861     {
1862         Status = I_RpcMapWin32Status(RpcExceptionCode());
1863     }
1864     RpcEndExcept;
1865 
1866     return Status;
1867 }
1868 
1869 
1870 NTSTATUS
1871 NTAPI
1872 SamRidToSid(IN SAM_HANDLE ObjectHandle,
1873             IN ULONG Rid,
1874             OUT PSID *Sid)
1875 {
1876     UNIMPLEMENTED;
1877     return STATUS_NOT_IMPLEMENTED;
1878 }
1879 
1880 
1881 NTSTATUS
1882 NTAPI
1883 SamSetInformationAlias(IN SAM_HANDLE AliasHandle,
1884                        IN ALIAS_INFORMATION_CLASS AliasInformationClass,
1885                        IN PVOID Buffer)
1886 {
1887     NTSTATUS Status;
1888 
1889     TRACE("SamSetInformationAlias(%p %lu %p)\n",
1890           AliasHandle, AliasInformationClass, Buffer);
1891 
1892     RpcTryExcept
1893     {
1894         Status = SamrSetInformationAlias((SAMPR_HANDLE)AliasHandle,
1895                                          AliasInformationClass,
1896                                          Buffer);
1897     }
1898     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1899     {
1900         Status = I_RpcMapWin32Status(RpcExceptionCode());
1901     }
1902     RpcEndExcept;
1903 
1904     return Status;
1905 }
1906 
1907 
1908 NTSTATUS
1909 NTAPI
1910 SamSetInformationDomain(IN SAM_HANDLE DomainHandle,
1911                         IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1912                         IN PVOID Buffer)
1913 {
1914     NTSTATUS Status;
1915 
1916     TRACE("SamSetInformationDomain(%p %lu %p)\n",
1917           DomainHandle, DomainInformationClass, Buffer);
1918 
1919     RpcTryExcept
1920     {
1921         Status = SamrSetInformationDomain((SAMPR_HANDLE)DomainHandle,
1922                                           DomainInformationClass,
1923                                           Buffer);
1924     }
1925     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1926     {
1927         Status = I_RpcMapWin32Status(RpcExceptionCode());
1928     }
1929     RpcEndExcept;
1930 
1931     return Status;
1932 }
1933 
1934 
1935 NTSTATUS
1936 NTAPI
1937 SamSetInformationGroup(IN SAM_HANDLE GroupHandle,
1938                        IN GROUP_INFORMATION_CLASS GroupInformationClass,
1939                        IN PVOID Buffer)
1940 {
1941     NTSTATUS Status;
1942 
1943     TRACE("SamSetInformationGroup(%p %lu %p)\n",
1944           GroupHandle, GroupInformationClass, Buffer);
1945 
1946     RpcTryExcept
1947     {
1948         Status = SamrSetInformationGroup((SAMPR_HANDLE)GroupHandle,
1949                                          GroupInformationClass,
1950                                          Buffer);
1951     }
1952     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1953     {
1954         Status = I_RpcMapWin32Status(RpcExceptionCode());
1955     }
1956     RpcEndExcept;
1957 
1958     return Status;
1959 }
1960 
1961 
1962 NTSTATUS
1963 NTAPI
1964 SamSetInformationUser(IN SAM_HANDLE UserHandle,
1965                       IN USER_INFORMATION_CLASS UserInformationClass,
1966                       IN PVOID Buffer)
1967 {
1968     PSAMPR_USER_SET_PASSWORD_INFORMATION PasswordBuffer;
1969     SAMPR_USER_INTERNAL1_INFORMATION Internal1Buffer;
1970     USER_ALL_INFORMATION InternalAllBuffer;
1971     OEM_STRING LmPwdString;
1972     CHAR LmPwdBuffer[15];
1973     NTSTATUS Status;
1974 
1975     TRACE("SamSetInformationUser(%p %lu %p)\n",
1976           UserHandle, UserInformationClass, Buffer);
1977 
1978     if (UserInformationClass == UserSetPasswordInformation)
1979     {
1980         PasswordBuffer = (PSAMPR_USER_SET_PASSWORD_INFORMATION)Buffer;
1981 
1982         Status = SampCheckPassword(UserHandle,
1983                                    (PUNICODE_STRING)&PasswordBuffer->Password);
1984         if (!NT_SUCCESS(Status))
1985         {
1986             TRACE("SampCheckPassword failed (Status 0x%08lx)\n", Status);
1987             return Status;
1988         }
1989 
1990         /* Calculate the NT hash value of the password */
1991         Status = SystemFunction007((PUNICODE_STRING)&PasswordBuffer->Password,
1992                                    (LPBYTE)&Internal1Buffer.EncryptedNtOwfPassword);
1993         if (!NT_SUCCESS(Status))
1994         {
1995             TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
1996             return Status;
1997         }
1998 
1999         Internal1Buffer.NtPasswordPresent = TRUE;
2000         Internal1Buffer.LmPasswordPresent = FALSE;
2001 
2002         /* Build the LM password */
2003         LmPwdString.Length = 15;
2004         LmPwdString.MaximumLength = 15;
2005         LmPwdString.Buffer = LmPwdBuffer;
2006         ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
2007 
2008         Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
2009                                                    (PUNICODE_STRING)&PasswordBuffer->Password,
2010                                                    FALSE);
2011         if (NT_SUCCESS(Status))
2012         {
2013             /* Calculate the LM hash value of the password */
2014             Status = SystemFunction006(LmPwdString.Buffer,
2015                                        (LPSTR)&Internal1Buffer.EncryptedLmOwfPassword);
2016             if (NT_SUCCESS(Status))
2017                 Internal1Buffer.LmPasswordPresent = TRUE;
2018         }
2019 
2020         Internal1Buffer.PasswordExpired = PasswordBuffer->PasswordExpired;
2021 
2022         RpcTryExcept
2023         {
2024             Status = SamrSetInformationUser((SAMPR_HANDLE)UserHandle,
2025                                             UserInternal1Information,
2026                                             (PVOID)&Internal1Buffer);
2027         }
2028         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2029         {
2030             Status = I_RpcMapWin32Status(RpcExceptionCode());
2031         }
2032         RpcEndExcept;
2033 
2034         if (!NT_SUCCESS(Status))
2035         {
2036             TRACE("SamrSetInformation() failed (Status 0x%08lx)\n", Status);
2037         }
2038 
2039         return Status;
2040     }
2041     else if (UserInformationClass == UserAllInformation)
2042     {
2043         RtlCopyMemory(&InternalAllBuffer,
2044                       Buffer,
2045                       sizeof(USER_ALL_INFORMATION));
2046 
2047         if (InternalAllBuffer.WhichFields & (USER_ALL_LMPASSWORDPRESENT | USER_ALL_NTPASSWORDPRESENT))
2048         {
2049             if (InternalAllBuffer.WhichFields & USER_ALL_OWFPASSWORD)
2050             {
2051                 /* Check NT password hash */
2052                 if (InternalAllBuffer.WhichFields & USER_ALL_NTPASSWORDPRESENT)
2053                 {
2054                     if (InternalAllBuffer.NtPassword.Length != sizeof(ENCRYPTED_NT_OWF_PASSWORD))
2055                         return STATUS_INVALID_PARAMETER;
2056                 }
2057 
2058                 /* Check LM password hash */
2059                 if (InternalAllBuffer.WhichFields & USER_ALL_LMPASSWORDPRESENT)
2060                 {
2061                     if (InternalAllBuffer.LmPassword.Length != sizeof(ENCRYPTED_LM_OWF_PASSWORD))
2062                         return STATUS_INVALID_PARAMETER;
2063                 }
2064             }
2065             else
2066             {
2067                 /*
2068                  * Only allow the NT password to be set.
2069                  * The LM password will be created here.
2070                  */
2071                 if (InternalAllBuffer.WhichFields & USER_ALL_LMPASSWORDPRESENT)
2072                 {
2073                     TRACE("Do not try to set a clear text LM password!\n");
2074                     return STATUS_INVALID_PARAMETER;
2075                 }
2076 
2077                 if (InternalAllBuffer.WhichFields & USER_ALL_NTPASSWORDPRESENT)
2078                 {
2079                     Status = SampCheckPassword(UserHandle,
2080                                                &InternalAllBuffer.NtPassword);
2081                     if (!NT_SUCCESS(Status))
2082                     {
2083                         TRACE("SampCheckPassword failed (Status 0x%08lx)\n", Status);
2084                         return Status;
2085                     }
2086 
2087                     /* Calculate the NT password hash */
2088                     Status = SystemFunction007((PUNICODE_STRING)&InternalAllBuffer.NtPassword,
2089                                                (LPBYTE)&Internal1Buffer.EncryptedNtOwfPassword);
2090                     if (!NT_SUCCESS(Status))
2091                     {
2092                         TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
2093                         return Status;
2094                     }
2095 
2096                     InternalAllBuffer.NtPasswordPresent = TRUE;
2097                     InternalAllBuffer.LmPasswordPresent = FALSE;
2098 
2099                     InternalAllBuffer.NtPassword.Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
2100                     InternalAllBuffer.NtPassword.MaximumLength = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
2101                     InternalAllBuffer.NtPassword.Buffer = (LPWSTR)&Internal1Buffer.EncryptedNtOwfPassword;
2102 
2103                     /* Build the LM password */
2104                     LmPwdString.Length = 15;
2105                     LmPwdString.MaximumLength = 15;
2106                     LmPwdString.Buffer = LmPwdBuffer;
2107                     ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
2108 
2109                     Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
2110                                                                (PUNICODE_STRING)&InternalAllBuffer.NtPassword,
2111                                                                FALSE);
2112                     if (NT_SUCCESS(Status))
2113                     {
2114                         /* Calculate the LM password hash */
2115                         Status = SystemFunction006(LmPwdString.Buffer,
2116                                                    (LPSTR)&Internal1Buffer.EncryptedLmOwfPassword);
2117                         if (NT_SUCCESS(Status))
2118                         {
2119                             InternalAllBuffer.WhichFields |= USER_ALL_LMPASSWORDPRESENT;
2120                             InternalAllBuffer.LmPasswordPresent = TRUE;
2121 
2122                             InternalAllBuffer.LmPassword.Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
2123                             InternalAllBuffer.LmPassword.MaximumLength = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
2124                             InternalAllBuffer.LmPassword.Buffer = (LPWSTR)&Internal1Buffer.EncryptedLmOwfPassword;
2125                         }
2126                     }
2127                 }
2128             }
2129         }
2130 
2131         RpcTryExcept
2132         {
2133             Status = SamrSetInformationUser((SAMPR_HANDLE)UserHandle,
2134                                             UserAllInformation,
2135                                             (PVOID)&InternalAllBuffer);
2136         }
2137         RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2138         {
2139             Status = I_RpcMapWin32Status(RpcExceptionCode());
2140         }
2141         RpcEndExcept;
2142 
2143         if (!NT_SUCCESS(Status))
2144         {
2145             TRACE("SamrSetInformation() failed (Status 0x%08lx)\n", Status);
2146         }
2147 
2148         return Status;
2149     }
2150 
2151     RpcTryExcept
2152     {
2153         Status = SamrSetInformationUser((SAMPR_HANDLE)UserHandle,
2154                                         UserInformationClass,
2155                                         Buffer);
2156     }
2157     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2158     {
2159         Status = I_RpcMapWin32Status(RpcExceptionCode());
2160     }
2161     RpcEndExcept;
2162 
2163     return Status;
2164 }
2165 
2166 
2167 NTSTATUS
2168 NTAPI
2169 SamSetMemberAttributesOfGroup(IN SAM_HANDLE GroupHandle,
2170                               IN ULONG MemberId,
2171                               IN ULONG Attributes)
2172 {
2173     NTSTATUS Status;
2174 
2175     TRACE("SamSetMemberAttributesOfGroup(%p %lu 0x%lx)\n",
2176           GroupHandle, MemberId, Attributes);
2177 
2178     RpcTryExcept
2179     {
2180         Status = SamrSetMemberAttributesOfGroup((SAMPR_HANDLE)GroupHandle,
2181                                                 MemberId,
2182                                                 Attributes);
2183     }
2184     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2185     {
2186         Status = I_RpcMapWin32Status(RpcExceptionCode());
2187     }
2188     RpcEndExcept;
2189 
2190     return Status;
2191 }
2192 
2193 
2194 NTSTATUS
2195 NTAPI
2196 SamSetSecurityObject(IN SAM_HANDLE ObjectHandle,
2197                      IN SECURITY_INFORMATION SecurityInformation,
2198                      IN PSECURITY_DESCRIPTOR SecurityDescriptor)
2199 {
2200     SAMPR_SR_SECURITY_DESCRIPTOR DescriptorToPass;
2201     ULONG Length;
2202     NTSTATUS Status;
2203 
2204     TRACE("SamSetSecurityObject(%p %lu %p)\n",
2205           ObjectHandle, SecurityInformation, SecurityDescriptor);
2206 
2207     /* Retrieve the length of the relative security descriptor */
2208     Length = 0;
2209     Status = RtlMakeSelfRelativeSD(SecurityDescriptor,
2210                                    NULL,
2211                                    &Length);
2212     if (Status != STATUS_BUFFER_TOO_SMALL)
2213         return STATUS_INVALID_PARAMETER;
2214 
2215 
2216     /* Allocate a buffer for the security descriptor */
2217     DescriptorToPass.Length = Length;
2218     DescriptorToPass.SecurityDescriptor = MIDL_user_allocate(Length);
2219     if (DescriptorToPass.SecurityDescriptor == NULL)
2220         return STATUS_INSUFFICIENT_RESOURCES;
2221 
2222     /* Convert the given security descriptor to a relative security descriptor */
2223     Status = RtlMakeSelfRelativeSD(SecurityDescriptor,
2224                                    (PSECURITY_DESCRIPTOR)DescriptorToPass.SecurityDescriptor,
2225                                    &Length);
2226     if (!NT_SUCCESS(Status))
2227         goto done;
2228 
2229     RpcTryExcept
2230     {
2231         Status = SamrSetSecurityObject((SAMPR_HANDLE)ObjectHandle,
2232                                        SecurityInformation,
2233                                        &DescriptorToPass);
2234     }
2235     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2236     {
2237         Status = I_RpcMapWin32Status(RpcExceptionCode());
2238     }
2239     RpcEndExcept;
2240 
2241 done:
2242     if (DescriptorToPass.SecurityDescriptor != NULL)
2243         MIDL_user_free(DescriptorToPass.SecurityDescriptor);
2244 
2245     return Status;
2246 }
2247 
2248 
2249 NTSTATUS
2250 NTAPI
2251 SamShutdownSamServer(IN SAM_HANDLE ServerHandle)
2252 {
2253     NTSTATUS Status;
2254 
2255     TRACE("(%p)\n", ServerHandle);
2256 
2257     RpcTryExcept
2258     {
2259         Status = SamrShutdownSamServer((SAMPR_HANDLE)ServerHandle);
2260     }
2261     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2262     {
2263         Status = I_RpcMapWin32Status(RpcExceptionCode());
2264     }
2265     RpcEndExcept;
2266 
2267     return Status;
2268 }
2269 
2270 /* EOF */
2271