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