ReactOS 0.4.15-dev-7693-gd0e2924
samrpc.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Security Account Manager (SAM) Server
4 * FILE: reactos/dll/win32/samsrv/samrpc.c
5 * PURPOSE: RPC interface functions
6 *
7 * PROGRAMMERS: Eric Kohl
8 */
9
10#include "samsrv.h"
11
12/* GLOBALS *******************************************************************/
13
15
17{
22};
23
25{
30};
31
33{
38};
39
41{
46};
47
49{
54};
55
57
58
59/* FUNCTIONS *****************************************************************/
60
61static
64 IN LARGE_INTEGER RelativeTime)
65{
66 LARGE_INTEGER NewTime;
67
68 NewTime.QuadPart = AbsoluteTime.QuadPart - RelativeTime.QuadPart;
69
70 if (NewTime.QuadPart < 0)
71 NewTime.QuadPart = 0;
72
73 return NewTime;
74}
75
76
77VOID
79{
81
82 TRACE("SampStartRpcServer() called\n");
83
86 L"\\pipe\\samr",
87 NULL);
88 if (Status != RPC_S_OK)
89 {
90 WARN("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
91 return;
92 }
93
94 Status = RpcServerRegisterIf(samr_v1_0_s_ifspec,
95 NULL,
96 NULL);
97 if (Status != RPC_S_OK)
98 {
99 WARN("RpcServerRegisterIf() failed (Status %lx)\n", Status);
100 return;
101 }
102
103 Status = RpcServerListen(1, 20, TRUE);
104 if (Status != RPC_S_OK)
105 {
106 WARN("RpcServerListen() failed (Status %lx)\n", Status);
107 return;
108 }
109
110 TRACE("SampStartRpcServer() done\n");
111}
112
113
115{
117}
118
119
121{
123}
124
125
127{
128 FIXME("SAMPR_HANDLE_rundown(%p)\n", hHandle);
129}
130
131
132/* Function 0 */
134NTAPI
136 OUT SAMPR_HANDLE *ServerHandle,
138{
139 SAMPR_REVISION_INFO InRevisionInfo, OutRevisionInfo;
140 ULONG OutVersion;
141
142 TRACE("SamrConnect(%p %p %lx)\n",
143 ServerName, ServerHandle, DesiredAccess);
144
145 InRevisionInfo.V1.Revision = 0;
146 InRevisionInfo.V1.SupportedFeatures = 0;
147
148 return SamrConnect5(ServerName,
150 1,
151 &InRevisionInfo,
152 &OutVersion,
153 &OutRevisionInfo,
154 ServerHandle);
155}
156
157
158/* Function 1 */
160NTAPI
162{
163 PSAM_DB_OBJECT DbObject;
165
166 TRACE("SamrCloseHandle(%p)\n", SamHandle);
167
169 TRUE);
170
171 Status = SampValidateDbObject(*SamHandle,
173 0,
174 &DbObject);
175 if (Status == STATUS_SUCCESS)
176 {
177 Status = SampCloseDbObject(DbObject);
178 *SamHandle = NULL;
179 }
180
182
183 TRACE("SamrCloseHandle done (Status 0x%08lx)\n", Status);
184
185 return Status;
186}
187
188
189/* Function 2 */
191NTAPI
195{
196 PSAM_DB_OBJECT DbObject = NULL;
198 PSECURITY_DESCRIPTOR RelativeSd = NULL;
199 ULONG RelativeSdSize = 0;
203
204 TRACE("SamrSetSecurityObject(%p %lx %p)\n",
206
207 if ((SecurityDescriptor == NULL) ||
208 (SecurityDescriptor->SecurityDescriptor == NULL) ||
211
212 if (SecurityInformation == 0 ||
216
219
222
225
229
233
234 /* Validate the server handle */
235 Status = SampValidateDbObject(ObjectHandle,
238 &DbObject);
239 if (!NT_SUCCESS(Status))
240 goto done;
241
242 /* Get the mapping for the object type */
243 switch (DbObject->ObjectType)
244 {
247 break;
248
251 break;
252
253 case SamDbAliasObject:
255 break;
256
257 case SamDbGroupObject:
259 break;
260
261 case SamDbUserObject:
263 break;
264
265 default:
267 }
268
269 /* Get the size of the SD */
271 L"SecDesc",
272 NULL,
273 NULL,
274 &RelativeSdSize);
275 if (!NT_SUCCESS(Status))
276 return Status;
277
278 /* Allocate a buffer for the SD */
279 RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(), 0, RelativeSdSize);
280 if (RelativeSd == NULL)
282
283 /* Get the SD */
285 L"SecDesc",
286 NULL,
287 RelativeSd,
288 &RelativeSdSize);
289 if (!NT_SUCCESS(Status))
290 goto done;
291
292 /* Build the new security descriptor */
294 (PSECURITY_DESCRIPTOR)SecurityDescriptor->SecurityDescriptor,
295 &RelativeSd,
296 Mapping,
298 if (!NT_SUCCESS(Status))
299 {
300 ERR("RtlSetSecurityObject failed (Status 0x%08lx)\n", Status);
301 goto done;
302 }
303
304 /* Set the modified SD */
306 L"SecDesc",
308 RelativeSd,
309 RtlLengthSecurityDescriptor(RelativeSd));
310 if (!NT_SUCCESS(Status))
311 {
312 ERR("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
313 }
314
315done:
316 if (TokenHandle != NULL)
318
319 if (RelativeSd != NULL)
320 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
321
322 return Status;
323}
324
325
326/* Function 3 */
328NTAPI
332{
333 PSAM_DB_OBJECT SamObject;
336 PSECURITY_DESCRIPTOR ResultSd = NULL;
338 ULONG RelativeSdSize = 0;
339 ULONG ResultSdSize = 0;
341
342 TRACE("SamrQuerySecurityObject(%p %lx %p)\n",
344
346
348 TRUE);
349
354
357
358 /* Validate the server handle */
359 Status = SampValidateDbObject(ObjectHandle,
362 &SamObject);
363 if (!NT_SUCCESS(Status))
364 goto done;
365
366 /* Get the size of the SD */
367 Status = SampGetObjectAttribute(SamObject,
368 L"SecDesc",
369 NULL,
370 NULL,
371 &RelativeSdSize);
373 {
374 TRACE("Status 0x%08lx\n", Status);
375 goto done;
376 }
377
378 /* Allocate a buffer for the SD */
379 RelativeSd = midl_user_allocate(RelativeSdSize);
380 if (RelativeSd == NULL)
381 {
383 goto done;
384 }
385
386 /* Get the SD */
387 Status = SampGetObjectAttribute(SamObject,
388 L"SecDesc",
389 NULL,
390 RelativeSd,
391 &RelativeSdSize);
392 if (!NT_SUCCESS(Status))
393 {
394 TRACE("Status 0x%08lx\n", Status);
395 goto done;
396 }
397
398 /* Invalidate the SD information that was not requested */
400 RelativeSd->Owner = 0;
401
403 RelativeSd->Group = 0;
404
406 RelativeSd->Control &= ~SE_DACL_PRESENT;
407
409 RelativeSd->Control &= ~SE_SACL_PRESENT;
410
411 /* Calculate the required SD size */
412 Status = RtlMakeSelfRelativeSD(RelativeSd,
413 NULL,
414 &ResultSdSize);
416 goto done;
417
418 /* Allocate a buffer for the new SD */
419 ResultSd = MIDL_user_allocate(ResultSdSize);
420 if (ResultSd == NULL)
421 {
423 goto done;
424 }
425
426 /* Build the new SD */
427 Status = RtlMakeSelfRelativeSD(RelativeSd,
428 ResultSd,
429 &ResultSdSize);
430 if (!NT_SUCCESS(Status))
431 goto done;
432
433 /* Allocate the SD data buffer */
435 if (SdData == NULL)
436 {
438 goto done;
439 }
440
441 /* Fill the SD data buffer and return it to the caller */
442 SdData->Length = ResultSdSize;
443 SdData->SecurityDescriptor = (PBYTE)ResultSd;
444
445 *SecurityDescriptor = SdData;
446
447done:
449
450 if (!NT_SUCCESS(Status))
451 {
452 if (ResultSd != NULL)
453 MIDL_user_free(ResultSd);
454 }
455
456 if (RelativeSd != NULL)
457 MIDL_user_free(RelativeSd);
458
459 return Status;
460}
461
462
463/* Function 4 */
465NTAPI
467{
468 PSAM_DB_OBJECT ServerObject;
470
471 TRACE("SamrShutdownSamServer(%p)\n",
472 ServerHandle);
473
475 TRUE);
476
477 /* Validate the server handle */
478 Status = SampValidateDbObject(ServerHandle,
481 &ServerObject);
482
484
485 if (!NT_SUCCESS(Status))
486 return Status;
487
488 /* Shut the server down */
490
492 if (!NT_SUCCESS(Status))
493 {
494 ERR("SampShutdownDisplayCache() failed (Status 0x%08lx)\n", Status);
495 }
496
497 return STATUS_SUCCESS;
498}
499
500
501/* Function 5 */
503NTAPI
506 OUT PRPC_SID *DomainId)
507{
508 PSAM_DB_OBJECT ServerObject;
509 HANDLE DomainsKeyHandle = NULL;
510 HANDLE DomainKeyHandle = NULL;
511 WCHAR DomainKeyName[64];
512 ULONG Index;
513 WCHAR DomainNameString[MAX_COMPUTERNAME_LENGTH + 1];
514 UNICODE_STRING DomainName;
516 BOOL Found = FALSE;
518
519 TRACE("SamrLookupDomainInSamServer(%p %p %p)\n",
520 ServerHandle, Name, DomainId);
521
523 TRUE);
524
525 /* Validate the server handle */
526 Status = SampValidateDbObject(ServerHandle,
529 &ServerObject);
530 if (!NT_SUCCESS(Status))
531 goto done;
532
533 *DomainId = NULL;
534
535 Status = SampRegOpenKey(ServerObject->KeyHandle,
536 L"Domains",
537 KEY_READ,
538 &DomainsKeyHandle);
539 if (!NT_SUCCESS(Status))
540 goto done;
541
542 Index = 0;
543 while (Found == FALSE)
544 {
545 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
546 Index,
547 64,
548 DomainKeyName);
549 if (!NT_SUCCESS(Status))
550 {
553 break;
554 }
555
556 TRACE("Domain key name: %S\n", DomainKeyName);
557
558 Status = SampRegOpenKey(DomainsKeyHandle,
559 DomainKeyName,
560 KEY_READ,
561 &DomainKeyHandle);
562 if (NT_SUCCESS(Status))
563 {
564 Length = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR);
565 Status = SampRegQueryValue(DomainKeyHandle,
566 L"Name",
567 NULL,
568 (PVOID)&DomainNameString,
569 &Length);
570 if (NT_SUCCESS(Status))
571 {
572 TRACE("Domain name: %S\n", DomainNameString);
573
574 RtlInitUnicodeString(&DomainName,
575 DomainNameString);
577 {
578 TRACE("Found it!\n");
579 Found = TRUE;
580
581 Status = SampRegQueryValue(DomainKeyHandle,
582 L"SID",
583 NULL,
584 NULL,
585 &Length);
586 if (NT_SUCCESS(Status))
587 {
588 *DomainId = midl_user_allocate(Length);
589
590 SampRegQueryValue(DomainKeyHandle,
591 L"SID",
592 NULL,
593 (PVOID)*DomainId,
594 &Length);
595
597 break;
598 }
599 }
600 }
601
602 SampRegCloseKey(&DomainKeyHandle);
603 }
604
605 Index++;
606 }
607
608done:
609 SampRegCloseKey(&DomainKeyHandle);
610 SampRegCloseKey(&DomainsKeyHandle);
611
613
614 return Status;
615}
616
617
618/* Function 6 */
620NTAPI
622 IN OUT unsigned long *EnumerationContext,
624 IN ULONG PreferedMaximumLength,
625 OUT PULONG CountReturned)
626{
627 PSAM_DB_OBJECT ServerObject;
628 WCHAR DomainKeyName[64];
629 HANDLE DomainsKeyHandle = NULL;
630 HANDLE DomainKeyHandle = NULL;
631 ULONG EnumIndex;
632 ULONG EnumCount;
635 ULONG i;
636 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
638
639 TRACE("SamrEnumerateDomainsInSamServer(%p %p %p %lu %p)\n",
640 ServerHandle, EnumerationContext, Buffer, PreferedMaximumLength,
641 CountReturned);
642
644 TRUE);
645
646 /* Validate the server handle */
647 Status = SampValidateDbObject(ServerHandle,
650 &ServerObject);
651 if (!NT_SUCCESS(Status))
652 goto done;
653
654 Status = SampRegOpenKey(ServerObject->KeyHandle,
655 L"Domains",
656 KEY_READ,
657 &DomainsKeyHandle);
658 if (!NT_SUCCESS(Status))
659 goto done;
660
661 EnumIndex = *EnumerationContext;
662 EnumCount = 0;
663 RequiredLength = 0;
664
665 while (TRUE)
666 {
667 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
668 EnumIndex,
669 64 * sizeof(WCHAR),
670 DomainKeyName);
671 if (!NT_SUCCESS(Status))
672 break;
673
674 TRACE("EnumIndex: %lu\n", EnumIndex);
675 TRACE("Domain key name: %S\n", DomainKeyName);
676
677 Status = SampRegOpenKey(DomainsKeyHandle,
678 DomainKeyName,
679 KEY_READ,
680 &DomainKeyHandle);
681 TRACE("SampRegOpenKey returned %08lX\n", Status);
682 if (NT_SUCCESS(Status))
683 {
684 DataLength = 0;
685 Status = SampRegQueryValue(DomainKeyHandle,
686 L"Name",
687 NULL,
688 NULL,
689 &DataLength);
690 TRACE("SampRegQueryValue returned %08lX\n", Status);
691 if (NT_SUCCESS(Status))
692 {
693 TRACE("Data length: %lu\n", DataLength);
694
695 if ((RequiredLength + DataLength + sizeof(UNICODE_STRING)) > PreferedMaximumLength)
696 break;
697
699 EnumCount++;
700 }
701
702 SampRegCloseKey(&DomainKeyHandle);
703 }
704
705 EnumIndex++;
706 }
707
708 TRACE("EnumCount: %lu\n", EnumCount);
709 TRACE("RequiredLength: %lu\n", RequiredLength);
710
711 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
712 if (EnumBuffer == NULL)
713 {
715 goto done;
716 }
717
718 EnumBuffer->EntriesRead = EnumCount;
719 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
720 if (EnumBuffer->Buffer == NULL)
721 {
723 goto done;
724 }
725
726 EnumIndex = *EnumerationContext;
727 for (i = 0; i < EnumCount; i++, EnumIndex++)
728 {
729 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
730 EnumIndex,
731 64 * sizeof(WCHAR),
732 DomainKeyName);
733 if (!NT_SUCCESS(Status))
734 break;
735
736 TRACE("EnumIndex: %lu\n", EnumIndex);
737 TRACE("Domain key name: %S\n", DomainKeyName);
738
739 Status = SampRegOpenKey(DomainsKeyHandle,
740 DomainKeyName,
741 KEY_READ,
742 &DomainKeyHandle);
743 TRACE("SampRegOpenKey returned %08lX\n", Status);
744 if (NT_SUCCESS(Status))
745 {
746 DataLength = 0;
747 Status = SampRegQueryValue(DomainKeyHandle,
748 L"Name",
749 NULL,
750 NULL,
751 &DataLength);
752 TRACE("SampRegQueryValue returned %08lX\n", Status);
753 if (NT_SUCCESS(Status))
754 {
755 EnumBuffer->Buffer[i].RelativeId = 0;
756 EnumBuffer->Buffer[i].Name.Length = (USHORT)DataLength - sizeof(WCHAR);
757 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)DataLength;
759 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
760 {
761 SampRegCloseKey(&DomainKeyHandle);
763 goto done;
764 }
765
766 Status = SampRegQueryValue(DomainKeyHandle,
767 L"Name",
768 NULL,
769 EnumBuffer->Buffer[i].Name.Buffer,
770 &DataLength);
771 TRACE("SampRegQueryValue returned %08lX\n", Status);
772 if (NT_SUCCESS(Status))
773 {
774 TRACE("Domain name: %S\n", EnumBuffer->Buffer[i].Name.Buffer);
775 }
776 }
777
778 SampRegCloseKey(&DomainKeyHandle);
779
780 if (!NT_SUCCESS(Status))
781 goto done;
782 }
783 }
784
785 if (NT_SUCCESS(Status))
786 {
787 *EnumerationContext += EnumCount;
788 *Buffer = EnumBuffer;
789 *CountReturned = EnumCount;
790 }
791
792done:
793 SampRegCloseKey(&DomainKeyHandle);
794 SampRegCloseKey(&DomainsKeyHandle);
795
796 if (!NT_SUCCESS(Status))
797 {
798 *EnumerationContext = 0;
799 *Buffer = NULL;
800 *CountReturned = 0;
801
802 if (EnumBuffer != NULL)
803 {
804 if (EnumBuffer->Buffer != NULL)
805 {
806 if (EnumBuffer->EntriesRead != 0)
807 {
808 for (i = 0; i < EnumBuffer->EntriesRead; i++)
809 {
810 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
811 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
812 }
813 }
814
815 midl_user_free(EnumBuffer->Buffer);
816 }
817
818 midl_user_free(EnumBuffer);
819 }
820 }
821
823
824 return Status;
825}
826
827
828/* Function 7 */
830NTAPI
833 IN PRPC_SID DomainId,
834 OUT SAMPR_HANDLE *DomainHandle)
835{
836 PSAM_DB_OBJECT ServerObject;
837 PSAM_DB_OBJECT DomainObject;
839
840 TRACE("SamrOpenDomain(%p %lx %p %p)\n",
841 ServerHandle, DesiredAccess, DomainId, DomainHandle);
842
843 /* Map generic access rights */
846
848 TRUE);
849
850 /* Validate the server handle */
851 Status = SampValidateDbObject(ServerHandle,
854 &ServerObject);
855 if (!NT_SUCCESS(Status))
856 return Status;
857
858 /* Validate the Domain SID */
859 if ((DomainId->Revision != SID_REVISION) ||
860 (DomainId->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) ||
861 (memcmp(&DomainId->IdentifierAuthority, &NtSidAuthority, sizeof(SID_IDENTIFIER_AUTHORITY)) != 0))
863
864 /* Open the domain object */
865 if ((DomainId->SubAuthorityCount == 1) &&
866 (DomainId->SubAuthority[0] == SECURITY_BUILTIN_DOMAIN_RID))
867 {
868 /* Builtin domain object */
869 TRACE("Opening the builtin domain object.\n");
870
871 Status = SampOpenDbObject(ServerObject,
872 L"Domains",
873 L"Builtin",
874 0,
877 &DomainObject);
878 }
879 else if ((DomainId->SubAuthorityCount == 4) &&
880 (DomainId->SubAuthority[0] == SECURITY_NT_NON_UNIQUE))
881 {
882 /* Account domain object */
883 TRACE("Opening the account domain object.\n");
884
885 /* FIXME: Check the account domain sub authorities!!! */
886
887 Status = SampOpenDbObject(ServerObject,
888 L"Domains",
889 L"Account",
890 0,
893 &DomainObject);
894 }
895 else
896 {
897 /* No valid domain SID */
899 }
900
901 if (NT_SUCCESS(Status))
902 *DomainHandle = (SAMPR_HANDLE)DomainObject;
903
905
906 TRACE("SamrOpenDomain done (Status 0x%08lx)\n", Status);
907
908 return Status;
909}
910
911
912static NTSTATUS
915{
916 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
917 SAM_DOMAIN_FIXED_DATA FixedData;
918 ULONG Length = 0;
920
921 *Buffer = NULL;
922
923 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
924 if (InfoBuffer == NULL)
926
928 Status = SampGetObjectAttribute(DomainObject,
929 L"F",
930 NULL,
931 (PVOID)&FixedData,
932 &Length);
933 if (!NT_SUCCESS(Status))
934 goto done;
935
936 InfoBuffer->Password.MinPasswordLength = FixedData.MinPasswordLength;
938 InfoBuffer->Password.PasswordProperties = FixedData.PasswordProperties;
939 InfoBuffer->Password.MaxPasswordAge.LowPart = FixedData.MaxPasswordAge.LowPart;
941 InfoBuffer->Password.MinPasswordAge.LowPart = FixedData.MinPasswordAge.LowPart;
943
944 *Buffer = InfoBuffer;
945
946done:
947 if (!NT_SUCCESS(Status))
948 {
949 if (InfoBuffer != NULL)
950 {
951 midl_user_free(InfoBuffer);
952 }
953 }
954
955 return Status;
956}
957
958
959static NTSTATUS
961 LPCWSTR AccountType,
963{
964 HANDLE AccountKeyHandle = NULL;
965 HANDLE NamesKeyHandle = NULL;
967
968 *Count = 0;
969
970 Status = SampRegOpenKey(DomainObject->KeyHandle,
971 AccountType,
972 KEY_READ,
973 &AccountKeyHandle);
974 if (!NT_SUCCESS(Status))
975 return Status;
976
977 Status = SampRegOpenKey(AccountKeyHandle,
978 L"Names",
979 KEY_READ,
980 &NamesKeyHandle);
981 if (!NT_SUCCESS(Status))
982 goto done;
983
984 Status = SampRegQueryKeyInfo(NamesKeyHandle,
985 NULL,
986 Count);
987
988done:
989 SampRegCloseKey(&NamesKeyHandle);
990 SampRegCloseKey(&AccountKeyHandle);
991
992 return Status;
993}
994
995
996static NTSTATUS
999{
1000 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1001 SAM_DOMAIN_FIXED_DATA FixedData;
1002 ULONG Length = 0;
1004
1005 *Buffer = NULL;
1006
1007 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1008 if (InfoBuffer == NULL)
1010
1011 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1012 Status = SampGetObjectAttribute(DomainObject,
1013 L"F",
1014 NULL,
1015 (PVOID)&FixedData,
1016 &Length);
1017 if (!NT_SUCCESS(Status))
1018 goto done;
1019
1020 InfoBuffer->General.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
1021 InfoBuffer->General.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
1024 InfoBuffer->General.DomainServerState = FixedData.DomainServerState;
1025 InfoBuffer->General.DomainServerRole = FixedData.DomainServerRole;
1027
1028 /* Get the OemInformation string */
1029 Status = SampGetObjectAttributeString(DomainObject,
1030 L"OemInformation",
1031 &InfoBuffer->General.OemInformation);
1032 if (!NT_SUCCESS(Status))
1033 {
1034 TRACE("Status 0x%08lx\n", Status);
1035 goto done;
1036 }
1037
1038 /* Get the Name string */
1039 Status = SampGetObjectAttributeString(DomainObject,
1040 L"Name",
1041 &InfoBuffer->General.DomainName);
1042 if (!NT_SUCCESS(Status))
1043 {
1044 TRACE("Status 0x%08lx\n", Status);
1045 goto done;
1046 }
1047
1048 /* Get the ReplicaSourceNodeName string */
1049 Status = SampGetObjectAttributeString(DomainObject,
1050 L"ReplicaSourceNodeName",
1051 &InfoBuffer->General.ReplicaSourceNodeName);
1052 if (!NT_SUCCESS(Status))
1053 {
1054 TRACE("Status 0x%08lx\n", Status);
1055 goto done;
1056 }
1057
1058 /* Get the number of Users in the Domain */
1059 Status = SampGetNumberOfAccounts(DomainObject,
1060 L"Users",
1061 &InfoBuffer->General.UserCount);
1062 if (!NT_SUCCESS(Status))
1063 {
1064 TRACE("Status 0x%08lx\n", Status);
1065 goto done;
1066 }
1067
1068 /* Get the number of Groups in the Domain */
1069 Status = SampGetNumberOfAccounts(DomainObject,
1070 L"Groups",
1071 &InfoBuffer->General.GroupCount);
1072 if (!NT_SUCCESS(Status))
1073 {
1074 TRACE("Status 0x%08lx\n", Status);
1075 goto done;
1076 }
1077
1078 /* Get the number of Aliases in the Domain */
1079 Status = SampGetNumberOfAccounts(DomainObject,
1080 L"Aliases",
1081 &InfoBuffer->General.AliasCount);
1082 if (!NT_SUCCESS(Status))
1083 {
1084 TRACE("Status 0x%08lx\n", Status);
1085 goto done;
1086 }
1087
1088 *Buffer = InfoBuffer;
1089
1090done:
1091 if (!NT_SUCCESS(Status))
1092 {
1093 if (InfoBuffer != NULL)
1094 {
1095 if (InfoBuffer->General.OemInformation.Buffer != NULL)
1097
1098 if (InfoBuffer->General.DomainName.Buffer != NULL)
1100
1101 if (InfoBuffer->General.ReplicaSourceNodeName.Buffer != NULL)
1103
1104 midl_user_free(InfoBuffer);
1105 }
1106 }
1107
1108 return Status;
1109}
1110
1111
1112static NTSTATUS
1115{
1116 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1117 SAM_DOMAIN_FIXED_DATA FixedData;
1118 ULONG Length = 0;
1120
1121 *Buffer = NULL;
1122
1123 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1124 if (InfoBuffer == NULL)
1126
1127 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1128 Status = SampGetObjectAttribute(DomainObject,
1129 L"F",
1130 NULL,
1131 (PVOID)&FixedData,
1132 &Length);
1133 if (!NT_SUCCESS(Status))
1134 goto done;
1135
1136 InfoBuffer->Logoff.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
1137 InfoBuffer->Logoff.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
1138
1139 *Buffer = InfoBuffer;
1140
1141done:
1142 if (!NT_SUCCESS(Status))
1143 {
1144 if (InfoBuffer != NULL)
1145 {
1146 midl_user_free(InfoBuffer);
1147 }
1148 }
1149
1150 return Status;
1151}
1152
1153
1154static NTSTATUS
1157{
1158 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1160
1161 *Buffer = NULL;
1162
1163 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1164 if (InfoBuffer == NULL)
1166
1167 /* Get the OemInformation string */
1168 Status = SampGetObjectAttributeString(DomainObject,
1169 L"OemInformation",
1170 &InfoBuffer->Oem.OemInformation);
1171 if (!NT_SUCCESS(Status))
1172 {
1173 TRACE("Status 0x%08lx\n", Status);
1174 goto done;
1175 }
1176
1177 *Buffer = InfoBuffer;
1178
1179done:
1180 if (!NT_SUCCESS(Status))
1181 {
1182 if (InfoBuffer != NULL)
1183 {
1184 if (InfoBuffer->Oem.OemInformation.Buffer != NULL)
1186
1187 midl_user_free(InfoBuffer);
1188 }
1189 }
1190
1191 return Status;
1192}
1193
1194
1195static NTSTATUS
1198{
1199 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1201
1202 *Buffer = NULL;
1203
1204 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1205 if (InfoBuffer == NULL)
1207
1208 /* Get the Name string */
1209 Status = SampGetObjectAttributeString(DomainObject,
1210 L"Name",
1211 &InfoBuffer->Name.DomainName);
1212 if (!NT_SUCCESS(Status))
1213 {
1214 TRACE("Status 0x%08lx\n", Status);
1215 goto done;
1216 }
1217
1218 *Buffer = InfoBuffer;
1219
1220done:
1221 if (!NT_SUCCESS(Status))
1222 {
1223 if (InfoBuffer != NULL)
1224 {
1225 if (InfoBuffer->Name.DomainName.Buffer != NULL)
1226 midl_user_free(InfoBuffer->Name.DomainName.Buffer);
1227
1228 midl_user_free(InfoBuffer);
1229 }
1230 }
1231
1232 return Status;
1233}
1234
1235
1236static NTSTATUS
1239{
1240 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1242
1243 *Buffer = NULL;
1244
1245 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1246 if (InfoBuffer == NULL)
1248
1249 /* Get the ReplicaSourceNodeName string */
1250 Status = SampGetObjectAttributeString(DomainObject,
1251 L"ReplicaSourceNodeName",
1252 &InfoBuffer->Replication.ReplicaSourceNodeName);
1253 if (!NT_SUCCESS(Status))
1254 {
1255 TRACE("Status 0x%08lx\n", Status);
1256 goto done;
1257 }
1258
1259 *Buffer = InfoBuffer;
1260
1261done:
1262 if (!NT_SUCCESS(Status))
1263 {
1264 if (InfoBuffer != NULL)
1265 {
1266 if (InfoBuffer->Replication.ReplicaSourceNodeName.Buffer != NULL)
1268
1269 midl_user_free(InfoBuffer);
1270 }
1271 }
1272
1273 return Status;
1274}
1275
1276
1277static NTSTATUS
1280{
1281 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1282 SAM_DOMAIN_FIXED_DATA FixedData;
1283 ULONG Length = 0;
1285
1286 *Buffer = NULL;
1287
1288 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1289 if (InfoBuffer == NULL)
1291
1292 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1293 Status = SampGetObjectAttribute(DomainObject,
1294 L"F",
1295 NULL,
1296 (PVOID)&FixedData,
1297 &Length);
1298 if (!NT_SUCCESS(Status))
1299 goto done;
1300
1301 InfoBuffer->Role.DomainServerRole = FixedData.DomainServerRole;
1302
1303 *Buffer = InfoBuffer;
1304
1305done:
1306 if (!NT_SUCCESS(Status))
1307 {
1308 if (InfoBuffer != NULL)
1309 {
1310 midl_user_free(InfoBuffer);
1311 }
1312 }
1313
1314 return Status;
1315}
1316
1317
1318static NTSTATUS
1321{
1322 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1323 SAM_DOMAIN_FIXED_DATA FixedData;
1324 ULONG Length = 0;
1326
1327 *Buffer = NULL;
1328
1329 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1330 if (InfoBuffer == NULL)
1332
1333 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1334 Status = SampGetObjectAttribute(DomainObject,
1335 L"F",
1336 NULL,
1337 (PVOID)&FixedData,
1338 &Length);
1339 if (!NT_SUCCESS(Status))
1340 goto done;
1341
1344 InfoBuffer->Modified.CreationTime.LowPart = FixedData.CreationTime.LowPart;
1345 InfoBuffer->Modified.CreationTime.HighPart = FixedData.CreationTime.HighPart;
1346
1347 *Buffer = InfoBuffer;
1348
1349done:
1350 if (!NT_SUCCESS(Status))
1351 {
1352 if (InfoBuffer != NULL)
1353 {
1354 midl_user_free(InfoBuffer);
1355 }
1356 }
1357
1358 return Status;
1359}
1360
1361
1362static NTSTATUS
1365{
1366 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1367 SAM_DOMAIN_FIXED_DATA FixedData;
1368 ULONG Length = 0;
1370
1371 *Buffer = NULL;
1372
1373 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1374 if (InfoBuffer == NULL)
1376
1377 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1378 Status = SampGetObjectAttribute(DomainObject,
1379 L"F",
1380 NULL,
1381 (PVOID)&FixedData,
1382 &Length);
1383 if (!NT_SUCCESS(Status))
1384 goto done;
1385
1386 InfoBuffer->State.DomainServerState = FixedData.DomainServerState;
1387
1388 *Buffer = InfoBuffer;
1389
1390done:
1391 if (!NT_SUCCESS(Status))
1392 {
1393 if (InfoBuffer != NULL)
1394 {
1395 midl_user_free(InfoBuffer);
1396 }
1397 }
1398
1399 return Status;
1400}
1401
1402
1403static NTSTATUS
1406{
1407 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1408 SAM_DOMAIN_FIXED_DATA FixedData;
1409 ULONG Length = 0;
1411
1412 *Buffer = NULL;
1413
1414 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1415 if (InfoBuffer == NULL)
1417
1418 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1419 Status = SampGetObjectAttribute(DomainObject,
1420 L"F",
1421 NULL,
1422 (PVOID)&FixedData,
1423 &Length);
1424 if (!NT_SUCCESS(Status))
1425 goto done;
1426
1427 InfoBuffer->General2.I1.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
1428 InfoBuffer->General2.I1.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
1431 InfoBuffer->General2.I1.DomainServerState = FixedData.DomainServerState;
1432 InfoBuffer->General2.I1.DomainServerRole = FixedData.DomainServerRole;
1434
1435 InfoBuffer->General2.LockoutDuration = FixedData.LockoutDuration;
1437 InfoBuffer->General2.LockoutThreshold = FixedData.LockoutThreshold;
1438
1439 /* Get the OemInformation string */
1440 Status = SampGetObjectAttributeString(DomainObject,
1441 L"OemInformation",
1442 &InfoBuffer->General2.I1.OemInformation);
1443 if (!NT_SUCCESS(Status))
1444 {
1445 TRACE("Status 0x%08lx\n", Status);
1446 goto done;
1447 }
1448
1449 /* Get the Name string */
1450 Status = SampGetObjectAttributeString(DomainObject,
1451 L"Name",
1452 &InfoBuffer->General2.I1.DomainName);
1453 if (!NT_SUCCESS(Status))
1454 {
1455 TRACE("Status 0x%08lx\n", Status);
1456 goto done;
1457 }
1458
1459 /* Get the ReplicaSourceNodeName string */
1460 Status = SampGetObjectAttributeString(DomainObject,
1461 L"ReplicaSourceNodeName",
1462 &InfoBuffer->General2.I1.ReplicaSourceNodeName);
1463 if (!NT_SUCCESS(Status))
1464 {
1465 TRACE("Status 0x%08lx\n", Status);
1466 goto done;
1467 }
1468
1469 /* Get the number of Users in the Domain */
1470 Status = SampGetNumberOfAccounts(DomainObject,
1471 L"Users",
1472 &InfoBuffer->General2.I1.UserCount);
1473 if (!NT_SUCCESS(Status))
1474 {
1475 TRACE("Status 0x%08lx\n", Status);
1476 goto done;
1477 }
1478
1479 /* Get the number of Groups in the Domain */
1480 Status = SampGetNumberOfAccounts(DomainObject,
1481 L"Groups",
1482 &InfoBuffer->General2.I1.GroupCount);
1483 if (!NT_SUCCESS(Status))
1484 {
1485 TRACE("Status 0x%08lx\n", Status);
1486 goto done;
1487 }
1488
1489 /* Get the number of Aliases in the Domain */
1490 Status = SampGetNumberOfAccounts(DomainObject,
1491 L"Aliases",
1492 &InfoBuffer->General2.I1.AliasCount);
1493 if (!NT_SUCCESS(Status))
1494 {
1495 TRACE("Status 0x%08lx\n", Status);
1496 goto done;
1497 }
1498
1499 *Buffer = InfoBuffer;
1500
1501done:
1502 if (!NT_SUCCESS(Status))
1503 {
1504 if (InfoBuffer != NULL)
1505 {
1506 if (InfoBuffer->General2.I1.OemInformation.Buffer != NULL)
1508
1509 if (InfoBuffer->General2.I1.DomainName.Buffer != NULL)
1511
1512 if (InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer != NULL)
1514
1515 midl_user_free(InfoBuffer);
1516 }
1517 }
1518
1519 return Status;
1520}
1521
1522
1523static NTSTATUS
1526{
1527 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1528 SAM_DOMAIN_FIXED_DATA FixedData;
1529 ULONG Length = 0;
1531
1532 *Buffer = NULL;
1533
1534 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1535 if (InfoBuffer == NULL)
1537
1538 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1539 Status = SampGetObjectAttribute(DomainObject,
1540 L"F",
1541 NULL,
1542 (PVOID)&FixedData,
1543 &Length);
1544 if (!NT_SUCCESS(Status))
1545 goto done;
1546
1547 InfoBuffer->Lockout.LockoutDuration = FixedData.LockoutDuration;
1549 InfoBuffer->Lockout.LockoutThreshold = FixedData.LockoutThreshold;
1550
1551 *Buffer = InfoBuffer;
1552
1553done:
1554 if (!NT_SUCCESS(Status))
1555 {
1556 if (InfoBuffer != NULL)
1557 {
1558 midl_user_free(InfoBuffer);
1559 }
1560 }
1561
1562 return Status;
1563}
1564
1565
1566static NTSTATUS
1569{
1570 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1571 SAM_DOMAIN_FIXED_DATA FixedData;
1572 ULONG Length = 0;
1574
1575 *Buffer = NULL;
1576
1577 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1578 if (InfoBuffer == NULL)
1580
1581 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1582 Status = SampGetObjectAttribute(DomainObject,
1583 L"F",
1584 NULL,
1585 (PVOID)&FixedData,
1586 &Length);
1587 if (!NT_SUCCESS(Status))
1588 goto done;
1589
1592 InfoBuffer->Modified2.CreationTime.LowPart = FixedData.CreationTime.LowPart;
1593 InfoBuffer->Modified2.CreationTime.HighPart = FixedData.CreationTime.HighPart;
1596
1597 *Buffer = InfoBuffer;
1598
1599done:
1600 if (!NT_SUCCESS(Status))
1601 {
1602 if (InfoBuffer != NULL)
1603 {
1604 midl_user_free(InfoBuffer);
1605 }
1606 }
1607
1608 return Status;
1609}
1610
1611
1612/* Function 8 */
1614NTAPI
1616 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1618{
1619 TRACE("SamrQueryInformationDomain(%p %lu %p)\n",
1620 DomainHandle, DomainInformationClass, Buffer);
1621
1622 return SamrQueryInformationDomain2(DomainHandle,
1623 DomainInformationClass,
1624 Buffer);
1625}
1626
1627
1628static NTSTATUS
1631{
1632 SAM_DOMAIN_FIXED_DATA FixedData;
1633 ULONG Length = 0;
1635
1636 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1637 Status = SampGetObjectAttribute(DomainObject,
1638 L"F",
1639 NULL,
1640 (PVOID)&FixedData,
1641 &Length);
1642 if (!NT_SUCCESS(Status))
1643 goto done;
1644
1645 FixedData.MinPasswordLength = Buffer->Password.MinPasswordLength;
1646 FixedData.PasswordHistoryLength = Buffer->Password.PasswordHistoryLength;
1647 FixedData.PasswordProperties = Buffer->Password.PasswordProperties;
1648 FixedData.MaxPasswordAge.LowPart = Buffer->Password.MaxPasswordAge.LowPart;
1649 FixedData.MaxPasswordAge.HighPart = Buffer->Password.MaxPasswordAge.HighPart;
1650 FixedData.MinPasswordAge.LowPart = Buffer->Password.MinPasswordAge.LowPart;
1651 FixedData.MinPasswordAge.HighPart = Buffer->Password.MinPasswordAge.HighPart;
1652
1653 Status = SampSetObjectAttribute(DomainObject,
1654 L"F",
1655 REG_BINARY,
1656 &FixedData,
1657 Length);
1658
1659done:
1660 return Status;
1661}
1662
1663
1664static NTSTATUS
1667{
1668 SAM_DOMAIN_FIXED_DATA FixedData;
1669 ULONG Length = 0;
1671
1672 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1673 Status = SampGetObjectAttribute(DomainObject,
1674 L"F",
1675 NULL,
1676 (PVOID)&FixedData,
1677 &Length);
1678 if (!NT_SUCCESS(Status))
1679 goto done;
1680
1681 FixedData.ForceLogoff.LowPart = Buffer->Logoff.ForceLogoff.LowPart;
1682 FixedData.ForceLogoff.HighPart = Buffer->Logoff.ForceLogoff.HighPart;
1683
1684 Status = SampSetObjectAttribute(DomainObject,
1685 L"F",
1686 REG_BINARY,
1687 &FixedData,
1688 Length);
1689
1690done:
1691 return Status;
1692}
1693
1694
1695static NTSTATUS
1698{
1699 SAM_DOMAIN_FIXED_DATA FixedData;
1700 ULONG Length = 0;
1702
1703 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1704 Status = SampGetObjectAttribute(DomainObject,
1705 L"F",
1706 NULL,
1707 (PVOID)&FixedData,
1708 &Length);
1709 if (!NT_SUCCESS(Status))
1710 goto done;
1711
1712 FixedData.DomainServerRole = Buffer->Role.DomainServerRole;
1713
1714 Status = SampSetObjectAttribute(DomainObject,
1715 L"F",
1716 REG_BINARY,
1717 &FixedData,
1718 Length);
1719
1720done:
1721 return Status;
1722}
1723
1724
1725static NTSTATUS
1728{
1729 SAM_DOMAIN_FIXED_DATA FixedData;
1730 ULONG Length = 0;
1732
1733 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1734 Status = SampGetObjectAttribute(DomainObject,
1735 L"F",
1736 NULL,
1737 (PVOID)&FixedData,
1738 &Length);
1739 if (!NT_SUCCESS(Status))
1740 goto done;
1741
1742 FixedData.DomainServerState = Buffer->State.DomainServerState;
1743
1744 Status = SampSetObjectAttribute(DomainObject,
1745 L"F",
1746 REG_BINARY,
1747 &FixedData,
1748 Length);
1749
1750done:
1751 return Status;
1752}
1753
1754
1755static NTSTATUS
1758{
1759 SAM_DOMAIN_FIXED_DATA FixedData;
1760 ULONG Length = 0;
1762
1763 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1764 Status = SampGetObjectAttribute(DomainObject,
1765 L"F",
1766 NULL,
1767 (PVOID)&FixedData,
1768 &Length);
1769 if (!NT_SUCCESS(Status))
1770 goto done;
1771
1772 FixedData.LockoutDuration = Buffer->Lockout.LockoutDuration;
1773 FixedData.LockoutObservationWindow = Buffer->Lockout.LockoutObservationWindow;
1774 FixedData.LockoutThreshold = Buffer->Lockout.LockoutThreshold;
1775
1776 Status = SampSetObjectAttribute(DomainObject,
1777 L"F",
1778 REG_BINARY,
1779 &FixedData,
1780 Length);
1781
1782done:
1783 return Status;
1784}
1785
1786
1787/* Function 9 */
1789NTAPI
1791 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1792 IN PSAMPR_DOMAIN_INFO_BUFFER DomainInformation)
1793{
1794 PSAM_DB_OBJECT DomainObject;
1797
1798 TRACE("SamrSetInformationDomain(%p %lu %p)\n",
1799 DomainHandle, DomainInformationClass, DomainInformation);
1800
1801 switch (DomainInformationClass)
1802 {
1806 break;
1807
1812 break;
1813
1818 break;
1819
1820 default:
1822 }
1823
1825 TRUE);
1826
1827 /* Validate the server handle */
1828 Status = SampValidateDbObject(DomainHandle,
1831 &DomainObject);
1832 if (!NT_SUCCESS(Status))
1833 goto done;
1834
1835 switch (DomainInformationClass)
1836 {
1838 Status = SampSetDomainPassword(DomainObject,
1839 DomainInformation);
1840 break;
1841
1843 Status = SampSetDomainLogoff(DomainObject,
1844 DomainInformation);
1845 break;
1846
1848 Status = SampSetObjectAttributeString(DomainObject,
1849 L"OemInformation",
1850 &DomainInformation->Oem.OemInformation);
1851 break;
1852
1854 Status = SampSetObjectAttributeString(DomainObject,
1855 L"Name",
1856 &DomainInformation->Name.DomainName);
1857 break;
1858
1860 Status = SampSetObjectAttributeString(DomainObject,
1861 L"ReplicaSourceNodeName",
1862 &DomainInformation->Replication.ReplicaSourceNodeName);
1863 break;
1864
1866 Status = SampSetDomainServerRole(DomainObject,
1867 DomainInformation);
1868 break;
1869
1871 Status = SampSetDomainState(DomainObject,
1872 DomainInformation);
1873 break;
1874
1876 Status = SampSetDomainLockout(DomainObject,
1877 DomainInformation);
1878 break;
1879
1880 default:
1882 }
1883
1884done:
1886
1887 return Status;
1888}
1889
1890
1891/* Function 10 */
1893NTAPI
1897 OUT SAMPR_HANDLE *GroupHandle,
1898 OUT unsigned long *RelativeId)
1899{
1900 SAM_DOMAIN_FIXED_DATA FixedDomainData;
1901 SAM_GROUP_FIXED_DATA FixedGroupData;
1902 PSAM_DB_OBJECT DomainObject;
1903 PSAM_DB_OBJECT GroupObject;
1905 ULONG SdSize = 0;
1906 ULONG ulSize;
1907 ULONG ulRid;
1908 WCHAR szRid[9];
1910
1911 TRACE("SamrCreateGroupInDomain(%p %p %lx %p %p)\n",
1912 DomainHandle, Name, DesiredAccess, GroupHandle, RelativeId);
1913
1914 /* Map generic access rights */
1916 &GroupMapping);
1917
1919 TRUE);
1920
1921 /* Validate the domain handle */
1922 Status = SampValidateDbObject(DomainHandle,
1925 &DomainObject);
1926 if (!NT_SUCCESS(Status))
1927 {
1928 TRACE("failed with status 0x%08lx\n", Status);
1929 goto done;
1930 }
1931
1932 /* Check the group account name */
1934 if (!NT_SUCCESS(Status))
1935 {
1936 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
1937 goto done;
1938 }
1939
1940 /* Check if the group name already exists in the domain */
1941 Status = SampCheckAccountNameInDomain(DomainObject,
1942 Name->Buffer);
1943 if (!NT_SUCCESS(Status))
1944 {
1945 TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n",
1946 Name->Buffer, Status);
1947 goto done;
1948 }
1949
1950 /* Create the security descriptor */
1952 &SdSize);
1953 if (!NT_SUCCESS(Status))
1954 {
1955 TRACE("SampCreateGroupSD failed (Status 0x%08lx)\n", Status);
1956 goto done;
1957 }
1958
1959 /* Get the fixed domain attributes */
1960 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
1961 Status = SampGetObjectAttribute(DomainObject,
1962 L"F",
1963 NULL,
1964 (PVOID)&FixedDomainData,
1965 &ulSize);
1966 if (!NT_SUCCESS(Status))
1967 {
1968 TRACE("failed with status 0x%08lx\n", Status);
1969 goto done;
1970 }
1971
1972 /* Increment the NextRid attribute */
1973 ulRid = FixedDomainData.NextRid;
1974 FixedDomainData.NextRid++;
1975
1976 /* Store the fixed domain attributes */
1977 Status = SampSetObjectAttribute(DomainObject,
1978 L"F",
1979 REG_BINARY,
1980 &FixedDomainData,
1981 ulSize);
1982 if (!NT_SUCCESS(Status))
1983 {
1984 TRACE("failed with status 0x%08lx\n", Status);
1985 goto done;
1986 }
1987
1988 TRACE("RID: %lx\n", ulRid);
1989
1990 /* Convert the RID into a string (hex) */
1991 swprintf(szRid, L"%08lX", ulRid);
1992
1993 /* Create the group object */
1994 Status = SampCreateDbObject(DomainObject,
1995 L"Groups",
1996 szRid,
1997 ulRid,
2000 &GroupObject);
2001 if (!NT_SUCCESS(Status))
2002 {
2003 TRACE("failed with status 0x%08lx\n", Status);
2004 goto done;
2005 }
2006
2007 /* Add the account name of the user object */
2008 Status = SampSetAccountNameInDomain(DomainObject,
2009 L"Groups",
2010 Name->Buffer,
2011 ulRid);
2012 if (!NT_SUCCESS(Status))
2013 {
2014 TRACE("failed with status 0x%08lx\n", Status);
2015 goto done;
2016 }
2017
2018 /* Initialize fixed user data */
2019 memset(&FixedGroupData, 0, sizeof(SAM_GROUP_FIXED_DATA));
2020 FixedGroupData.Version = 1;
2021 FixedGroupData.GroupId = ulRid;
2022
2023 /* Set fixed user data attribute */
2024 Status = SampSetObjectAttribute(GroupObject,
2025 L"F",
2026 REG_BINARY,
2027 (LPVOID)&FixedGroupData,
2028 sizeof(SAM_GROUP_FIXED_DATA));
2029 if (!NT_SUCCESS(Status))
2030 {
2031 TRACE("failed with status 0x%08lx\n", Status);
2032 goto done;
2033 }
2034
2035 /* Set the Name attribute */
2037 L"Name",
2038 Name);
2039 if (!NT_SUCCESS(Status))
2040 {
2041 TRACE("failed with status 0x%08lx\n", Status);
2042 goto done;
2043 }
2044
2045 /* Set the AdminComment attribute */
2047 L"AdminComment",
2048 NULL);
2049 if (!NT_SUCCESS(Status))
2050 {
2051 TRACE("failed with status 0x%08lx\n", Status);
2052 goto done;
2053 }
2054
2055 /* Set the SecDesc attribute*/
2056 Status = SampSetObjectAttribute(GroupObject,
2057 L"SecDesc",
2058 REG_BINARY,
2059 Sd,
2060 SdSize);
2061 if (!NT_SUCCESS(Status))
2062 {
2063 TRACE("failed with status 0x%08lx\n", Status);
2064 goto done;
2065 }
2066
2067 if (NT_SUCCESS(Status))
2068 {
2069 *GroupHandle = (SAMPR_HANDLE)GroupObject;
2070 *RelativeId = ulRid;
2071 }
2072
2073done:
2074 if (Sd != NULL)
2075 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
2076
2078
2079 TRACE("returns with status 0x%08lx\n", Status);
2080
2081 return Status;
2082}
2083
2084
2085/* Function 11 */
2087NTAPI
2089 IN OUT unsigned long *EnumerationContext,
2091 IN unsigned long PreferedMaximumLength,
2092 OUT unsigned long *CountReturned)
2093{
2094 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
2095 PSAM_DB_OBJECT DomainObject;
2096 HANDLE GroupsKeyHandle = NULL;
2097 HANDLE NamesKeyHandle = NULL;
2098 WCHAR GroupName[64];
2099 ULONG EnumIndex;
2100 ULONG EnumCount = 0;
2102 ULONG NameLength;
2104 ULONG Rid;
2105 ULONG i;
2106 BOOLEAN MoreEntries = FALSE;
2108
2109 TRACE("SamrEnumerateUsersInDomain(%p %p %p %lu %p)\n",
2110 DomainHandle, EnumerationContext, Buffer,
2111 PreferedMaximumLength, CountReturned);
2112
2114 TRUE);
2115
2116 /* Validate the domain handle */
2117 Status = SampValidateDbObject(DomainHandle,
2120 &DomainObject);
2121 if (!NT_SUCCESS(Status))
2122 goto done;
2123
2124 Status = SampRegOpenKey(DomainObject->KeyHandle,
2125 L"Groups",
2126 KEY_READ,
2127 &GroupsKeyHandle);
2128 if (!NT_SUCCESS(Status))
2129 goto done;
2130
2131 Status = SampRegOpenKey(GroupsKeyHandle,
2132 L"Names",
2133 KEY_READ,
2134 &NamesKeyHandle);
2135 if (!NT_SUCCESS(Status))
2136 goto done;
2137
2138 TRACE("Part 1\n");
2139
2140 EnumIndex = *EnumerationContext;
2141
2142 while (TRUE)
2143 {
2144 NameLength = 64 * sizeof(WCHAR);
2145 Status = SampRegEnumerateValue(NamesKeyHandle,
2146 EnumIndex,
2147 GroupName,
2148 &NameLength,
2149 NULL,
2150 NULL,
2151 NULL);
2152 if (!NT_SUCCESS(Status))
2153 {
2156 break;
2157 }
2158
2159 TRACE("EnumIndex: %lu\n", EnumIndex);
2160 TRACE("Group name: %S\n", GroupName);
2161 TRACE("Name length: %lu\n", NameLength);
2162
2163 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
2164 {
2165 MoreEntries = TRUE;
2166 break;
2167 }
2168
2169 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
2170 EnumCount++;
2171
2172 EnumIndex++;
2173 }
2174
2175 TRACE("EnumCount: %lu\n", EnumCount);
2176 TRACE("RequiredLength: %lu\n", RequiredLength);
2177
2178 if (!NT_SUCCESS(Status))
2179 goto done;
2180
2181 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
2182 if (EnumBuffer == NULL)
2183 {
2185 goto done;
2186 }
2187
2188 EnumBuffer->EntriesRead = EnumCount;
2189 if (EnumCount == 0)
2190 {
2192 goto done;
2193 }
2194
2195 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
2196 if (EnumBuffer->Buffer == NULL)
2197 {
2199 goto done;
2200 }
2201
2202 TRACE("Part 2\n");
2203
2204 EnumIndex = *EnumerationContext;
2205 for (i = 0; i < EnumCount; i++, EnumIndex++)
2206 {
2207 NameLength = 64 * sizeof(WCHAR);
2208 DataLength = sizeof(ULONG);
2209 Status = SampRegEnumerateValue(NamesKeyHandle,
2210 EnumIndex,
2211 GroupName,
2212 &NameLength,
2213 NULL,
2214 &Rid,
2215 &DataLength);
2216 if (!NT_SUCCESS(Status))
2217 {
2220 break;
2221 }
2222
2223 TRACE("EnumIndex: %lu\n", EnumIndex);
2224 TRACE("Group name: %S\n", GroupName);
2225 TRACE("Name length: %lu\n", NameLength);
2226 TRACE("RID: %lu\n", Rid);
2227
2228 EnumBuffer->Buffer[i].RelativeId = Rid;
2229
2230 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
2231 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(NameLength + sizeof(UNICODE_NULL));
2232
2233/* FIXME: Disabled because of bugs in widl and rpcrt4 */
2234#if 0
2235 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
2236 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
2237 {
2239 goto done;
2240 }
2241
2242 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
2243 GroupName,
2244 EnumBuffer->Buffer[i].Name.Length);
2245#endif
2246 }
2247
2248done:
2249 if (NT_SUCCESS(Status))
2250 {
2251 *EnumerationContext += EnumCount;
2252 *Buffer = EnumBuffer;
2253 *CountReturned = EnumCount;
2254 }
2255 else
2256 {
2257 *EnumerationContext = 0;
2258 *Buffer = NULL;
2259 *CountReturned = 0;
2260
2261 if (EnumBuffer != NULL)
2262 {
2263 if (EnumBuffer->Buffer != NULL)
2264 {
2265 if (EnumBuffer->EntriesRead != 0)
2266 {
2267 for (i = 0; i < EnumBuffer->EntriesRead; i++)
2268 {
2269 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
2270 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
2271 }
2272 }
2273
2274 midl_user_free(EnumBuffer->Buffer);
2275 }
2276
2277 midl_user_free(EnumBuffer);
2278 }
2279 }
2280
2281 SampRegCloseKey(&NamesKeyHandle);
2282 SampRegCloseKey(&GroupsKeyHandle);
2283
2284 if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE))
2286
2288
2289 return Status;
2290}
2291
2292
2293/* Function 12 */
2295NTAPI
2299 OUT SAMPR_HANDLE *UserHandle,
2300 OUT unsigned long *RelativeId)
2301{
2302 SAM_DOMAIN_FIXED_DATA FixedDomainData;
2303 SAM_USER_FIXED_DATA FixedUserData;
2304 PSAM_DB_OBJECT DomainObject;
2305 PSAM_DB_OBJECT UserObject;
2306 GROUP_MEMBERSHIP GroupMembership;
2307 UCHAR LogonHours[23];
2308 ULONG ulSize;
2309 ULONG ulRid;
2310 WCHAR szRid[9];
2312 ULONG SdSize = 0;
2313 PSID UserSid = NULL;
2315
2316 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
2317 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
2318
2319 if (Name == NULL ||
2320 Name->Length == 0 ||
2321 Name->Buffer == NULL ||
2322 UserHandle == NULL ||
2323 RelativeId == NULL)
2325
2326 /* Map generic access rights */
2328 &UserMapping);
2329
2331 TRUE);
2332
2333 /* Validate the domain handle */
2334 Status = SampValidateDbObject(DomainHandle,
2337 &DomainObject);
2338 if (!NT_SUCCESS(Status))
2339 {
2340 TRACE("failed with status 0x%08lx\n", Status);
2341 goto done;
2342 }
2343
2344 /* Check the user account name */
2346 if (!NT_SUCCESS(Status))
2347 {
2348 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
2349 goto done;
2350 }
2351
2352 /* Check if the user name already exists in the domain */
2353 Status = SampCheckAccountNameInDomain(DomainObject,
2354 Name->Buffer);
2355 if (!NT_SUCCESS(Status))
2356 {
2357 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
2358 Name->Buffer, Status);
2359 goto done;
2360 }
2361
2362 /* Get the fixed domain attributes */
2363 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
2364 Status = SampGetObjectAttribute(DomainObject,
2365 L"F",
2366 NULL,
2367 (PVOID)&FixedDomainData,
2368 &ulSize);
2369 if (!NT_SUCCESS(Status))
2370 {
2371 TRACE("failed with status 0x%08lx\n", Status);
2372 goto done;
2373 }
2374
2375 /* Increment the NextRid attribute */
2376 ulRid = FixedDomainData.NextRid;
2377 FixedDomainData.NextRid++;
2378
2379 TRACE("RID: %lx\n", ulRid);
2380
2381 /* Create the user SID */
2382 Status = SampCreateAccountSid(DomainObject,
2383 ulRid,
2384 &UserSid);
2385 if (!NT_SUCCESS(Status))
2386 {
2387 TRACE("SampCreateAccountSid failed (Status 0x%08lx)\n", Status);
2388 goto done;
2389 }
2390
2391 /* Create the security descriptor */
2392 Status = SampCreateUserSD(UserSid,
2393 &Sd,
2394 &SdSize);
2395 if (!NT_SUCCESS(Status))
2396 {
2397 TRACE("SampCreateUserSD failed (Status 0x%08lx)\n", Status);
2398 goto done;
2399 }
2400
2401 /* Store the fixed domain attributes */
2402 Status = SampSetObjectAttribute(DomainObject,
2403 L"F",
2404 REG_BINARY,
2405 &FixedDomainData,
2406 ulSize);
2407 if (!NT_SUCCESS(Status))
2408 {
2409 TRACE("failed with status 0x%08lx\n", Status);
2410 goto done;
2411 }
2412
2413 /* Convert the RID into a string (hex) */
2414 swprintf(szRid, L"%08lX", ulRid);
2415
2416 /* Create the user object */
2417 Status = SampCreateDbObject(DomainObject,
2418 L"Users",
2419 szRid,
2420 ulRid,
2423 &UserObject);
2424 if (!NT_SUCCESS(Status))
2425 {
2426 TRACE("failed with status 0x%08lx\n", Status);
2427 goto done;
2428 }
2429
2430 /* Add the account name for the user object */
2431 Status = SampSetAccountNameInDomain(DomainObject,
2432 L"Users",
2433 Name->Buffer,
2434 ulRid);
2435 if (!NT_SUCCESS(Status))
2436 {
2437 TRACE("failed with status 0x%08lx\n", Status);
2438 goto done;
2439 }
2440
2441 /* Initialize fixed user data */
2442 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
2443 FixedUserData.Version = 1;
2444 FixedUserData.Reserved = 0;
2445 FixedUserData.LastLogon.QuadPart = 0;
2446 FixedUserData.LastLogoff.QuadPart = 0;
2447 FixedUserData.PasswordLastSet.QuadPart = 0;
2448 FixedUserData.AccountExpires.QuadPart = MAXLONGLONG;
2449 FixedUserData.LastBadPasswordTime.QuadPart = 0;
2450 FixedUserData.UserId = ulRid;
2451 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
2455 FixedUserData.CountryCode = 0;
2456 FixedUserData.CodePage = 0;
2457 FixedUserData.BadPasswordCount = 0;
2458 FixedUserData.LogonCount = 0;
2459 FixedUserData.AdminCount = 0;
2460 FixedUserData.OperatorCount = 0;
2461
2462 /* Set fixed user data attribute */
2463 Status = SampSetObjectAttribute(UserObject,
2464 L"F",
2465 REG_BINARY,
2466 (LPVOID)&FixedUserData,
2467 sizeof(SAM_USER_FIXED_DATA));
2468 if (!NT_SUCCESS(Status))
2469 {
2470 TRACE("failed with status 0x%08lx\n", Status);
2471 goto done;
2472 }
2473
2474 /* Set the Name attribute */
2476 L"Name",
2477 Name);
2478 if (!NT_SUCCESS(Status))
2479 {
2480 TRACE("failed with status 0x%08lx\n", Status);
2481 goto done;
2482 }
2483
2484 /* Set the FullName attribute */
2486 L"FullName",
2487 NULL);
2488 if (!NT_SUCCESS(Status))
2489 {
2490 TRACE("failed with status 0x%08lx\n", Status);
2491 goto done;
2492 }
2493
2494 /* Set the HomeDirectory attribute */
2496 L"HomeDirectory",
2497 NULL);
2498 if (!NT_SUCCESS(Status))
2499 {
2500 TRACE("failed with status 0x%08lx\n", Status);
2501 goto done;
2502 }
2503
2504 /* Set the HomeDirectoryDrive attribute */
2506 L"HomeDirectoryDrive",
2507 NULL);
2508 if (!NT_SUCCESS(Status))
2509 {
2510 TRACE("failed with status 0x%08lx\n", Status);
2511 goto done;
2512 }
2513
2514 /* Set the ScriptPath attribute */
2516 L"ScriptPath",
2517 NULL);
2518 if (!NT_SUCCESS(Status))
2519 {
2520 TRACE("failed with status 0x%08lx\n", Status);
2521 goto done;
2522 }
2523
2524 /* Set the ProfilePath attribute */
2526 L"ProfilePath",
2527 NULL);
2528 if (!NT_SUCCESS(Status))
2529 {
2530 TRACE("failed with status 0x%08lx\n", Status);
2531 goto done;
2532 }
2533
2534 /* Set the AdminComment attribute */
2536 L"AdminComment",
2537 NULL);
2538 if (!NT_SUCCESS(Status))
2539 {
2540 TRACE("failed with status 0x%08lx\n", Status);
2541 goto done;
2542 }
2543
2544 /* Set the UserComment attribute */
2546 L"UserComment",
2547 NULL);
2548 if (!NT_SUCCESS(Status))
2549 {
2550 TRACE("failed with status 0x%08lx\n", Status);
2551 goto done;
2552 }
2553
2554 /* Set the WorkStations attribute */
2556 L"WorkStations",
2557 NULL);
2558 if (!NT_SUCCESS(Status))
2559 {
2560 TRACE("failed with status 0x%08lx\n", Status);
2561 goto done;
2562 }
2563
2564 /* Set the Parameters attribute */
2566 L"Parameters",
2567 NULL);
2568 if (!NT_SUCCESS(Status))
2569 {
2570 TRACE("failed with status 0x%08lx\n", Status);
2571 goto done;
2572 }
2573
2574 /* Set LogonHours attribute*/
2575 *((PUSHORT)LogonHours) = 168;
2576 memset(&(LogonHours[2]), 0xff, 21);
2577
2578 Status = SampSetObjectAttribute(UserObject,
2579 L"LogonHours",
2580 REG_BINARY,
2581 &LogonHours,
2582 sizeof(LogonHours));
2583 if (!NT_SUCCESS(Status))
2584 {
2585 TRACE("failed with status 0x%08lx\n", Status);
2586 goto done;
2587 }
2588
2589 /* Set Groups attribute*/
2590 GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS;
2591 GroupMembership.Attributes = SE_GROUP_MANDATORY |
2594
2595 Status = SampSetObjectAttribute(UserObject,
2596 L"Groups",
2597 REG_BINARY,
2598 &GroupMembership,
2599 sizeof(GROUP_MEMBERSHIP));
2600 if (!NT_SUCCESS(Status))
2601 {
2602 TRACE("failed with status 0x%08lx\n", Status);
2603 goto done;
2604 }
2605
2606 /* Set LMPwd attribute*/
2607 Status = SampSetObjectAttribute(UserObject,
2608 L"LMPwd",
2609 REG_BINARY,
2610 &EmptyLmHash,
2612 if (!NT_SUCCESS(Status))
2613 {
2614 TRACE("failed with status 0x%08lx\n", Status);
2615 goto done;
2616 }
2617
2618 /* Set NTPwd attribute*/
2619 Status = SampSetObjectAttribute(UserObject,
2620 L"NTPwd",
2621 REG_BINARY,
2622 &EmptyNtHash,
2624 if (!NT_SUCCESS(Status))
2625 {
2626 TRACE("failed with status 0x%08lx\n", Status);
2627 goto done;
2628 }
2629
2630 /* Set LMPwdHistory attribute*/
2631 Status = SampSetObjectAttribute(UserObject,
2632 L"LMPwdHistory",
2633 REG_BINARY,
2634 NULL,
2635 0);
2636 if (!NT_SUCCESS(Status))
2637 {
2638 TRACE("failed with status 0x%08lx\n", Status);
2639 goto done;
2640 }
2641
2642 /* Set NTPwdHistory attribute*/
2643 Status = SampSetObjectAttribute(UserObject,
2644 L"NTPwdHistory",
2645 REG_BINARY,
2646 NULL,
2647 0);
2648 if (!NT_SUCCESS(Status))
2649 {
2650 TRACE("failed with status 0x%08lx\n", Status);
2651 goto done;
2652 }
2653
2654 /* Set the PrivateData attribute */
2656 L"PrivateData",
2657 NULL);
2658 if (!NT_SUCCESS(Status))
2659 {
2660 TRACE("failed with status 0x%08lx\n", Status);
2661 goto done;
2662 }
2663
2664 /* Set the SecDesc attribute*/
2665 Status = SampSetObjectAttribute(UserObject,
2666 L"SecDesc",
2667 REG_BINARY,
2668 Sd,
2669 SdSize);
2670 if (!NT_SUCCESS(Status))
2671 {
2672 TRACE("failed with status 0x%08lx\n", Status);
2673 goto done;
2674 }
2675
2676 if (NT_SUCCESS(Status))
2677 {
2678 *UserHandle = (SAMPR_HANDLE)UserObject;
2679 *RelativeId = ulRid;
2680 }
2681
2682done:
2683 if (Sd != NULL)
2684 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
2685
2686 if (UserSid != NULL)
2687 RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid);
2688
2690
2691 TRACE("returns with status 0x%08lx\n", Status);
2692
2693 return Status;
2694}
2695
2696
2697/* Function 13 */
2699NTAPI
2701 IN OUT unsigned long *EnumerationContext,
2702 IN unsigned long UserAccountControl,
2704 IN unsigned long PreferedMaximumLength,
2705 OUT unsigned long *CountReturned)
2706{
2707 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
2708 PSAM_DB_OBJECT DomainObject;
2709 HANDLE UsersKeyHandle = NULL;
2710 HANDLE NamesKeyHandle = NULL;
2711 WCHAR UserName[64];
2712 ULONG EnumIndex;
2713 ULONG EnumCount = 0;
2715 ULONG NameLength;
2717 ULONG Rid;
2718 ULONG i;
2719 BOOLEAN MoreEntries = FALSE;
2721
2722 TRACE("SamrEnumerateUsersInDomain(%p %p %lx %p %lu %p)\n",
2723 DomainHandle, EnumerationContext, UserAccountControl, Buffer,
2724 PreferedMaximumLength, CountReturned);
2725
2727 TRUE);
2728
2729 /* Validate the domain handle */
2730 Status = SampValidateDbObject(DomainHandle,
2733 &DomainObject);
2734 if (!NT_SUCCESS(Status))
2735 goto done;
2736
2737 Status = SampRegOpenKey(DomainObject->KeyHandle,
2738 L"Users",
2739 KEY_READ,
2740 &UsersKeyHandle);
2741 if (!NT_SUCCESS(Status))
2742 goto done;
2743
2744 Status = SampRegOpenKey(UsersKeyHandle,
2745 L"Names",
2746 KEY_READ,
2747 &NamesKeyHandle);
2748 if (!NT_SUCCESS(Status))
2749 goto done;
2750
2751 TRACE("Part 1\n");
2752
2753 EnumIndex = *EnumerationContext;
2754
2755 while (TRUE)
2756 {
2757 NameLength = 64 * sizeof(WCHAR);
2758 Status = SampRegEnumerateValue(NamesKeyHandle,
2759 EnumIndex,
2760 UserName,
2761 &NameLength,
2762 NULL,
2763 NULL,
2764 NULL);
2765 if (!NT_SUCCESS(Status))
2766 {
2769 break;
2770 }
2771
2772 TRACE("EnumIndex: %lu\n", EnumIndex);
2773 TRACE("User name: %S\n", UserName);
2774 TRACE("Name length: %lu\n", NameLength);
2775
2776 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
2777 {
2778 MoreEntries = TRUE;
2779 break;
2780 }
2781
2782 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
2783 EnumCount++;
2784
2785 EnumIndex++;
2786 }
2787
2788 TRACE("EnumCount: %lu\n", EnumCount);
2789 TRACE("RequiredLength: %lu\n", RequiredLength);
2790
2791 if (!NT_SUCCESS(Status))
2792 goto done;
2793
2794 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
2795 if (EnumBuffer == NULL)
2796 {
2798 goto done;
2799 }
2800
2801 EnumBuffer->EntriesRead = EnumCount;
2802 if (EnumCount == 0)
2803 {
2805 goto done;
2806 }
2807
2808 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
2809 if (EnumBuffer->Buffer == NULL)
2810 {
2812 goto done;
2813 }
2814
2815 TRACE("Part 2\n");
2816
2817 EnumIndex = *EnumerationContext;
2818 for (i = 0; i < EnumCount; i++, EnumIndex++)
2819 {
2820 NameLength = 64 * sizeof(WCHAR);
2821 DataLength = sizeof(ULONG);
2822 Status = SampRegEnumerateValue(NamesKeyHandle,
2823 EnumIndex,
2824 UserName,
2825 &NameLength,
2826 NULL,
2827 &Rid,
2828 &DataLength);
2829 if (!NT_SUCCESS(Status))
2830 {
2833 break;
2834 }
2835
2836 TRACE("EnumIndex: %lu\n", EnumIndex);
2837 TRACE("User name: %S\n", UserName);
2838 TRACE("Name length: %lu\n", NameLength);
2839 TRACE("RID: %lu\n", Rid);
2840
2841 EnumBuffer->Buffer[i].RelativeId = Rid;
2842
2843 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
2844 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(NameLength + sizeof(UNICODE_NULL));
2845
2846/* FIXME: Disabled because of bugs in widl and rpcrt4 */
2847#if 0
2848 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
2849 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
2850 {
2852 goto done;
2853 }
2854
2855 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
2856 UserName,
2857 EnumBuffer->Buffer[i].Name.Length);
2858#endif
2859 }
2860
2861done:
2862 if (NT_SUCCESS(Status))
2863 {
2864 *EnumerationContext += EnumCount;
2865 *Buffer = EnumBuffer;
2866 *CountReturned = EnumCount;
2867 }
2868 else
2869 {
2870 *EnumerationContext = 0;
2871 *Buffer = NULL;
2872 *CountReturned = 0;
2873
2874 if (EnumBuffer != NULL)
2875 {
2876 if (EnumBuffer->Buffer != NULL)
2877 {
2878 if (EnumBuffer->EntriesRead != 0)
2879 {
2880 for (i = 0; i < EnumBuffer->EntriesRead; i++)
2881 {
2882 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
2883 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
2884 }
2885 }
2886
2887 midl_user_free(EnumBuffer->Buffer);
2888 }
2889
2890 midl_user_free(EnumBuffer);
2891 }
2892 }
2893
2894 SampRegCloseKey(&NamesKeyHandle);
2895 SampRegCloseKey(&UsersKeyHandle);
2896
2897 if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE))
2899
2901
2902 return Status;
2903}
2904
2905
2906/* Function 14 */
2908NTAPI
2910 IN PRPC_UNICODE_STRING AccountName,
2912 OUT SAMPR_HANDLE *AliasHandle,
2913 OUT unsigned long *RelativeId)
2914{
2915 SAM_DOMAIN_FIXED_DATA FixedDomainData;
2916 PSAM_DB_OBJECT DomainObject;
2917 PSAM_DB_OBJECT AliasObject;
2919 ULONG SdSize = 0;
2920 ULONG ulSize;
2921 ULONG ulRid;
2922 WCHAR szRid[9];
2924
2925 TRACE("SamrCreateAliasInDomain(%p %p %lx %p %p)\n",
2926 DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId);
2927
2928 /* Map generic access rights */
2930 &AliasMapping);
2931
2933 TRUE);
2934
2935 /* Validate the domain handle */
2936 Status = SampValidateDbObject(DomainHandle,
2939 &DomainObject);
2940 if (!NT_SUCCESS(Status))
2941 {
2942 TRACE("failed with status 0x%08lx\n", Status);
2943 goto done;
2944 }
2945
2946 /* Check the alias account name */
2947 Status = SampCheckAccountName(AccountName, 256);
2948 if (!NT_SUCCESS(Status))
2949 {
2950 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
2951 goto done;
2952 }
2953
2954 /* Check if the alias name already exists in the domain */
2955 Status = SampCheckAccountNameInDomain(DomainObject,
2956 AccountName->Buffer);
2957 if (!NT_SUCCESS(Status))
2958 {
2959 TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n",
2960 AccountName->Buffer, Status);
2961 goto done;
2962 }
2963
2964 /* Create the security descriptor */
2966 &SdSize);
2967 if (!NT_SUCCESS(Status))
2968 {
2969 TRACE("SampCreateAliasSD failed (Status 0x%08lx)\n", Status);
2970 goto done;
2971 }
2972
2973 /* Get the fixed domain attributes */
2974 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
2975 Status = SampGetObjectAttribute(DomainObject,
2976 L"F",
2977 NULL,
2978 (PVOID)&FixedDomainData,
2979 &ulSize);
2980 if (!NT_SUCCESS(Status))
2981 {
2982 TRACE("failed with status 0x%08lx\n", Status);
2983 goto done;
2984 }
2985
2986 /* Increment the NextRid attribute */
2987 ulRid = FixedDomainData.NextRid;
2988 FixedDomainData.NextRid++;
2989
2990 /* Store the fixed domain attributes */
2991 Status = SampSetObjectAttribute(DomainObject,
2992 L"F",
2993 REG_BINARY,
2994 &FixedDomainData,
2995 ulSize);
2996 if (!NT_SUCCESS(Status))
2997 {
2998 TRACE("failed with status 0x%08lx\n", Status);
2999 goto done;
3000 }
3001
3002 TRACE("RID: %lx\n", ulRid);
3003
3004 /* Convert the RID into a string (hex) */
3005 swprintf(szRid, L"%08lX", ulRid);
3006
3007 /* Create the alias object */
3008 Status = SampCreateDbObject(DomainObject,
3009 L"Aliases",
3010 szRid,
3011 ulRid,
3014 &AliasObject);
3015 if (!NT_SUCCESS(Status))
3016 {
3017 TRACE("failed with status 0x%08lx\n", Status);
3018 goto done;
3019 }
3020
3021 /* Add the account name for the alias object */
3022 Status = SampSetAccountNameInDomain(DomainObject,
3023 L"Aliases",
3024 AccountName->Buffer,
3025 ulRid);
3026 if (!NT_SUCCESS(Status))
3027 {
3028 TRACE("failed with status 0x%08lx\n", Status);
3029 goto done;
3030 }
3031
3032 /* Set the Name attribute */
3034 L"Name",
3035 AccountName);
3036 if (!NT_SUCCESS(Status))
3037 {
3038 TRACE("failed with status 0x%08lx\n", Status);
3039 goto done;
3040 }
3041
3042 /* Set the Description attribute */
3044 L"Description",
3045 NULL);
3046 if (!NT_SUCCESS(Status))
3047 {
3048 TRACE("failed with status 0x%08lx\n", Status);
3049 goto done;
3050 }
3051
3052 /* Set the SecDesc attribute*/
3053 Status = SampSetObjectAttribute(AliasObject,
3054 L"SecDesc",
3055 REG_BINARY,
3056 Sd,
3057 SdSize);
3058 if (!NT_SUCCESS(Status))
3059 {
3060 TRACE("failed with status 0x%08lx\n", Status);
3061 goto done;
3062 }
3063
3064 if (NT_SUCCESS(Status))
3065 {
3066 *AliasHandle = (SAMPR_HANDLE)AliasObject;
3067 *RelativeId = ulRid;
3068 }
3069
3070done:
3071 if (Sd != NULL)
3072 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
3073
3075
3076 TRACE("returns with status 0x%08lx\n", Status);
3077
3078 return Status;
3079}
3080
3081
3082/* Function 15 */
3084NTAPI
3086 IN OUT unsigned long *EnumerationContext,
3088 IN unsigned long PreferedMaximumLength,
3089 OUT unsigned long *CountReturned)
3090{
3091 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
3092 PSAM_DB_OBJECT DomainObject;
3093 HANDLE AliasesKeyHandle = NULL;
3094 HANDLE NamesKeyHandle = NULL;
3095 WCHAR AliasName[64];
3096 ULONG EnumIndex;
3097 ULONG EnumCount = 0;
3099 ULONG NameLength;
3101 ULONG Rid;
3102 ULONG i;
3103 BOOLEAN MoreEntries = FALSE;
3105
3106 TRACE("SamrEnumerateAliasesInDomain(%p %p %p %lu %p)\n",
3107 DomainHandle, EnumerationContext, Buffer,
3108 PreferedMaximumLength, CountReturned);
3109
3111 TRUE);
3112
3113 /* Validate the domain handle */
3114 Status = SampValidateDbObject(DomainHandle,
3117 &DomainObject);
3118 if (!NT_SUCCESS(Status))
3119 goto done;
3120
3121 Status = SampRegOpenKey(DomainObject->KeyHandle,
3122 L"Aliases",
3123 KEY_READ,
3124 &AliasesKeyHandle);
3125 if (!NT_SUCCESS(Status))
3126 goto done;
3127
3128 Status = SampRegOpenKey(AliasesKeyHandle,
3129 L"Names",
3130 KEY_READ,
3131 &NamesKeyHandle);
3132 if (!NT_SUCCESS(Status))
3133 goto done;
3134
3135 TRACE("Part 1\n");
3136
3137 EnumIndex = *EnumerationContext;
3138
3139 while (TRUE)
3140 {
3141 NameLength = 64 * sizeof(WCHAR);
3142 Status = SampRegEnumerateValue(NamesKeyHandle,
3143 EnumIndex,
3144 AliasName,
3145 &NameLength,
3146 NULL,
3147 NULL,
3148 NULL);
3149 if (!NT_SUCCESS(Status))
3150 {
3153 break;
3154 }
3155
3156 TRACE("EnumIndex: %lu\n", EnumIndex);
3157 TRACE("Alias name: %S\n", AliasName);
3158 TRACE("Name length: %lu\n", NameLength);
3159
3160 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
3161 {
3162 MoreEntries = TRUE;
3163 break;
3164 }
3165
3166 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
3167 EnumCount++;
3168
3169 EnumIndex++;
3170 }
3171
3172 TRACE("EnumCount: %lu\n", EnumCount);
3173 TRACE("RequiredLength: %lu\n", RequiredLength);
3174
3175 if (!NT_SUCCESS(Status))
3176 goto done;
3177
3178 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
3179 if (EnumBuffer == NULL)
3180 {
3182 goto done;
3183 }
3184
3185 EnumBuffer->EntriesRead = EnumCount;
3186 if (EnumCount == 0)
3187 {
3189 goto done;
3190 }
3191
3192 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
3193 if (EnumBuffer->Buffer == NULL)
3194 {
3196 goto done;
3197 }
3198
3199 TRACE("Part 2\n");
3200
3201 EnumIndex = *EnumerationContext;
3202 for (i = 0; i < EnumCount; i++, EnumIndex++)
3203 {
3204 NameLength = 64 * sizeof(WCHAR);
3205 DataLength = sizeof(ULONG);
3206 Status = SampRegEnumerateValue(NamesKeyHandle,
3207 EnumIndex,
3208 AliasName,
3209 &NameLength,
3210 NULL,
3211 &Rid,
3212 &DataLength);
3213 if (!NT_SUCCESS(Status))
3214 {
3217 break;
3218 }
3219
3220 TRACE("EnumIndex: %lu\n", EnumIndex);
3221 TRACE("Alias name: %S\n", AliasName);
3222 TRACE("Name length: %lu\n", NameLength);
3223 TRACE("RID: %lu\n", Rid);
3224
3225 EnumBuffer->Buffer[i].RelativeId = Rid;
3226
3227 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
3228 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(NameLength + sizeof(UNICODE_NULL));
3229
3230/* FIXME: Disabled because of bugs in widl and rpcrt4 */
3231#if 0
3232 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
3233 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
3234 {
3236 goto done;
3237 }
3238
3239 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
3240 AliasName,
3241 EnumBuffer->Buffer[i].Name.Length);
3242#endif
3243 }
3244
3245done:
3246 if (NT_SUCCESS(Status))
3247 {
3248 *EnumerationContext += EnumCount;
3249 *Buffer = EnumBuffer;
3250 *CountReturned = EnumCount;
3251 }
3252 else
3253 {
3254 *EnumerationContext = 0;
3255 *Buffer = NULL;
3256 *CountReturned = 0;
3257
3258 if (EnumBuffer != NULL)
3259 {
3260 if (EnumBuffer->Buffer != NULL)
3261 {
3262 if (EnumBuffer->EntriesRead != 0)
3263 {
3264 for (i = 0; i < EnumBuffer->EntriesRead; i++)
3265 {
3266 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
3267 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
3268 }
3269 }
3270
3271 midl_user_free(EnumBuffer->Buffer);
3272 }
3273
3274 midl_user_free(EnumBuffer);
3275 }
3276 }
3277
3278 SampRegCloseKey(&NamesKeyHandle);
3279 SampRegCloseKey(&AliasesKeyHandle);
3280
3281 if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE))
3283
3285
3286 return Status;
3287}
3288
3289
3290/* Function 16 */
3292NTAPI
3294 IN PSAMPR_PSID_ARRAY SidArray,
3295 OUT PSAMPR_ULONG_ARRAY Membership)
3296{
3297 PSAM_DB_OBJECT DomainObject;
3298 HANDLE AliasesKeyHandle = NULL;
3299 HANDLE MembersKeyHandle = NULL;
3300 HANDLE MemberKeyHandle = NULL;
3301 LPWSTR MemberSidString = NULL;
3302 PULONG RidArray = NULL;
3303 ULONG MaxSidCount = 0;
3304 ULONG ValueCount;
3306 ULONG i, j;
3307 ULONG RidIndex;
3309 WCHAR NameBuffer[9];
3310
3311 TRACE("SamrGetAliasMembership(%p %p %p)\n",
3312 DomainHandle, SidArray, Membership);
3313
3315 TRUE);
3316
3317 /* Validate the domain handle */
3318 Status = SampValidateDbObject(DomainHandle,
3321 &DomainObject);
3322 if (!NT_SUCCESS(Status))
3323 goto done;
3324
3325 Status = SampRegOpenKey(DomainObject->KeyHandle,
3326 L"Aliases",
3327 KEY_READ,
3328 &AliasesKeyHandle);
3329 TRACE("SampRegOpenKey returned %08lX\n", Status);
3330 if (!NT_SUCCESS(Status))
3331 goto done;
3332
3333 Status = SampRegOpenKey(AliasesKeyHandle,
3334 L"Members",
3335 KEY_READ,
3336 &MembersKeyHandle);
3337 TRACE("SampRegOpenKey returned %08lX\n", Status);
3338
3340 {
3342 goto done;
3343 }
3344
3345 if (!NT_SUCCESS(Status))
3346 goto done;
3347
3348 for (i = 0; i < SidArray->Count; i++)
3349 {
3350 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
3351TRACE("Open %S\n", MemberSidString);
3352
3353 Status = SampRegOpenKey(MembersKeyHandle,
3354 MemberSidString,
3355 KEY_READ,
3356 &MemberKeyHandle);
3357 TRACE("SampRegOpenKey returned %08lX\n", Status);
3358 if (NT_SUCCESS(Status))
3359 {
3360 Status = SampRegQueryKeyInfo(MemberKeyHandle,
3361 NULL,
3362 &ValueCount);
3363 if (NT_SUCCESS(Status))
3364 {
3365 TRACE("Found %lu values\n", ValueCount);
3366 MaxSidCount += ValueCount;
3367 }
3368
3369 SampRegCloseKey(&MemberKeyHandle);
3370 }
3371
3374
3375 LocalFree(MemberSidString);
3376 }
3377
3378 if (MaxSidCount == 0)
3379 {
3381 goto done;
3382 }
3383
3384 TRACE("Maximum sid count: %lu\n", MaxSidCount);
3385 RidArray = midl_user_allocate(MaxSidCount * sizeof(ULONG));
3386 if (RidArray == NULL)
3387 {
3389 goto done;
3390 }
3391
3392 RidIndex = 0;
3393 for (i = 0; i < SidArray->Count; i++)
3394 {
3395 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
3396TRACE("Open %S\n", MemberSidString);
3397
3398 Status = SampRegOpenKey(MembersKeyHandle,
3399 MemberSidString,
3400 KEY_READ,
3401 &MemberKeyHandle);
3402 TRACE("SampRegOpenKey returned %08lX\n", Status);
3403 if (NT_SUCCESS(Status))
3404 {
3405 Status = SampRegQueryKeyInfo(MemberKeyHandle,
3406 NULL,
3407 &ValueCount);
3408 if (NT_SUCCESS(Status))
3409 {
3410 TRACE("Found %lu values\n", ValueCount);
3411
3412 for (j = 0; j < ValueCount; j++)
3413 {
3414 DataLength = 9 * sizeof(WCHAR);
3415 Status = SampRegEnumerateValue(MemberKeyHandle,
3416 j,
3417 NameBuffer,
3418 &DataLength,
3419 NULL,
3420 NULL,
3421 NULL);
3422 if (NT_SUCCESS(Status))
3423 {
3424 /* FIXME: Do not return each RID more than once. */
3425 RidArray[RidIndex] = wcstoul(NameBuffer, NULL, 16);
3426 RidIndex++;
3427 }
3428 }
3429 }
3430
3431 SampRegCloseKey(&MemberKeyHandle);
3432 }
3433
3436
3437 LocalFree(MemberSidString);
3438 }
3439
3440done:
3441 SampRegCloseKey(&MembersKeyHandle);
3442 SampRegCloseKey(&AliasesKeyHandle);
3443
3444 if (NT_SUCCESS(Status))
3445 {
3446 Membership->Count = MaxSidCount;
3447 Membership->Element = RidArray;
3448 }
3449 else
3450 {
3451 if (RidArray != NULL)
3452 midl_user_free(RidArray);
3453 }
3454
3456
3457 return Status;
3458}
3459
3460
3461/* Function 17 */
3463NTAPI
3465 IN ULONG Count,
3467 OUT PSAMPR_ULONG_ARRAY RelativeIds,
3469{
3470 PSAM_DB_OBJECT DomainObject;
3471 HANDLE AccountsKeyHandle = NULL;
3472 HANDLE NamesKeyHandle = NULL;
3473 ULONG MappedCount = 0;
3475 ULONG i;
3476 ULONG RelativeId;
3478
3479 TRACE("SamrLookupNamesInDomain(%p %lu %p %p %p)\n",
3480 DomainHandle, Count, Names, RelativeIds, Use);
3481
3483 TRUE);
3484
3485 /* Validate the domain handle */
3486 Status = SampValidateDbObject(DomainHandle,
3489 &DomainObject);
3490 if (!NT_SUCCESS(Status))
3491 {
3492 TRACE("failed with status 0x%08lx\n", Status);
3493 goto done;
3494 }
3495
3496 RelativeIds->Count = 0;
3497 Use->Count = 0;
3498
3499 if (Count == 0)
3500 {
3502 goto done;
3503 }
3504
3505 /* Allocate the relative IDs array */
3506 RelativeIds->Element = midl_user_allocate(Count * sizeof(ULONG));
3507 if (RelativeIds->Element == NULL)
3508 {
3510 goto done;
3511 }
3512
3513 /* Allocate the use array */
3514 Use->Element = midl_user_allocate(Count * sizeof(ULONG));
3515 if (Use->Element == NULL)
3516 {
3518 goto done;
3519 }
3520
3521 RelativeIds->Count = Count;
3522 Use->Count = Count;
3523
3524 for (i = 0; i < Count; i++)
3525 {
3526 TRACE("Name: %S\n", Names[i].Buffer);
3527
3528 RelativeId = 0;
3529
3530 /* Lookup aliases */
3531 Status = SampRegOpenKey(DomainObject->KeyHandle,
3532 L"Aliases",
3533 KEY_READ,
3534 &AccountsKeyHandle);
3535 if (NT_SUCCESS(Status))
3536 {
3537 Status = SampRegOpenKey(AccountsKeyHandle,
3538 L"Names",
3539 KEY_READ,
3540 &NamesKeyHandle);
3541 if (NT_SUCCESS(Status))
3542 {
3543 DataLength = sizeof(ULONG);
3544 Status = SampRegQueryValue(NamesKeyHandle,
3545 Names[i].Buffer,
3546 NULL,
3547 &RelativeId,
3548 &DataLength);
3549
3550 SampRegCloseKey(&NamesKeyHandle);
3551 }
3552
3553 SampRegCloseKey(&AccountsKeyHandle);
3554 }
3555
3557 break;
3558
3559 /* Return alias account */
3560 if (NT_SUCCESS(Status) && RelativeId != 0)
3561 {
3562 TRACE("Rid: %lu\n", RelativeId);
3563 RelativeIds->Element[i] = RelativeId;
3564 Use->Element[i] = SidTypeAlias;
3565 MappedCount++;
3566 continue;
3567 }
3568
3569 /* Lookup groups */
3570 Status = SampRegOpenKey(DomainObject->KeyHandle,
3571 L"Groups",
3572 KEY_READ,
3573 &AccountsKeyHandle);
3574 if (NT_SUCCESS(Status))
3575 {
3576 Status = SampRegOpenKey(AccountsKeyHandle,
3577 L"Names",
3578 KEY_READ,
3579 &NamesKeyHandle);
3580 if (NT_SUCCESS(Status))
3581 {
3582 DataLength = sizeof(ULONG);
3583 Status = SampRegQueryValue(NamesKeyHandle,
3584 Names[i].Buffer,
3585 NULL,
3586 &RelativeId,
3587 &DataLength);
3588
3589 SampRegCloseKey(&NamesKeyHandle);
3590 }
3591
3592 SampRegCloseKey(&AccountsKeyHandle);
3593 }
3594
3596 break;
3597
3598 /* Return group account */
3599 if (NT_SUCCESS(Status) && RelativeId != 0)
3600 {
3601 TRACE("Rid: %lu\n", RelativeId);
3602 RelativeIds->Element[i] = RelativeId;
3603 Use->Element[i] = SidTypeGroup;
3604 MappedCount++;
3605 continue;
3606 }
3607
3608 /* Lookup users */
3609 Status = SampRegOpenKey(DomainObject->KeyHandle,
3610 L"Users",
3611 KEY_READ,
3612 &AccountsKeyHandle);
3613 if (NT_SUCCESS(Status))
3614 {
3615 Status = SampRegOpenKey(AccountsKeyHandle,
3616 L"Names",
3617 KEY_READ,
3618 &NamesKeyHandle);
3619 if (NT_SUCCESS(Status))
3620 {
3621 DataLength = sizeof(ULONG);
3622 Status = SampRegQueryValue(NamesKeyHandle,
3623 Names[i].Buffer,
3624 NULL,
3625 &RelativeId,
3626 &DataLength);
3627
3628 SampRegCloseKey(&NamesKeyHandle);
3629 }
3630
3631 SampRegCloseKey(&AccountsKeyHandle);
3632 }
3633
3635 break;
3636
3637 /* Return user account */
3638 if (NT_SUCCESS(Status) && RelativeId != 0)
3639 {
3640 TRACE("Rid: %lu\n", RelativeId);
3641 RelativeIds->Element[i] = RelativeId;
3642 Use->Element[i] = SidTypeUser;
3643 MappedCount++;
3644 continue;
3645 }
3646
3647 /* Return unknown account */
3648 RelativeIds->Element[i] = 0;
3649 Use->Element[i] = SidTypeUnknown;
3650 }
3651
3652done:
3655
3656 if (NT_SUCCESS(Status))
3657 {
3658 if (MappedCount == 0)
3660 else if (MappedCount < Count)
3662 }
3663 else
3664 {
3665 if (RelativeIds->Element != NULL)
3666 {
3667 midl_user_free(RelativeIds->Element);
3668 RelativeIds->Element = NULL;
3669 }
3670
3671 RelativeIds->Count = 0;
3672
3673 if (Use->Element != NULL)
3674 {
3675 midl_user_free(Use->Element);
3676 Use->Element = NULL;
3677 }
3678
3679 Use->Count = 0;
3680 }
3681
3683
3684 TRACE("Returned Status %lx\n", Status);
3685
3686 return Status;
3687}
3688
3689
3690/* Function 18 */
3692NTAPI
3694 IN ULONG Count,
3695 IN ULONG *RelativeIds,
3698{
3699 PSAM_DB_OBJECT DomainObject;
3700 WCHAR RidString[9];
3701 HANDLE AccountsKeyHandle = NULL;
3702 HANDLE AccountKeyHandle = NULL;
3703 ULONG MappedCount = 0;
3705 ULONG i;
3707
3708 TRACE("SamrLookupIdsInDomain(%p %lu %p %p %p)\n",
3709 DomainHandle, Count, RelativeIds, Names, Use);
3710
3712 TRUE);
3713
3714 /* Validate the domain handle */
3715 Status = SampValidateDbObject(DomainHandle,
3718 &DomainObject);
3719 if (!NT_SUCCESS(Status))
3720 {
3721 TRACE("failed with status 0x%08lx\n", Status);
3722 goto done;
3723 }
3724
3725 Names->Count = 0;
3726 Use->Count = 0;
3727
3728 if (Count == 0)
3729 {
3731 goto done;
3732 }
3733
3734 /* Allocate the names array */
3735 Names->Element = midl_user_allocate(Count * sizeof(*Names->Element));
3736 if (Names->Element == NULL)
3737 {
3739 goto done;
3740 }
3741
3742 /* Allocate the use array */
3743 Use->Element = midl_user_allocate(Count * sizeof(*Use->Element));
3744 if (Use->Element == NULL)
3745 {
3747 goto done;
3748 }
3749
3750 Names->Count = Count;
3751 Use->Count = Count;
3752
3753 for (i = 0; i < Count; i++)
3754 {
3755 TRACE("RID: %lu\n", RelativeIds[i]);
3756
3757 swprintf(RidString, L"%08lx", RelativeIds[i]);
3758
3759 /* Lookup aliases */
3760 Status = SampRegOpenKey(DomainObject->KeyHandle,
3761 L"Aliases",
3762 KEY_READ,
3763 &AccountsKeyHandle);
3764 if (NT_SUCCESS(Status))
3765 {
3766 Status = SampRegOpenKey(AccountsKeyHandle,
3767 RidString,
3768 KEY_READ,
3769 &AccountKeyHandle);
3770 if (NT_SUCCESS(Status))
3771 {
3772 DataLength = 0;
3773 Status = SampRegQueryValue(AccountKeyHandle,
3774 L"Name",
3775 NULL,
3776 NULL,
3777 &DataLength);
3778 if (NT_SUCCESS(Status))
3779 {
3780 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3781 if (Names->Element[i].Buffer == NULL)
3783
3784 if (NT_SUCCESS(Status))
3785 {
3786 Names->Element[i].MaximumLength = (USHORT)DataLength;
3787 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3788
3789 Status = SampRegQueryValue(AccountKeyHandle,
3790 L"Name",
3791 NULL,
3792 Names->Element[i].Buffer,
3793 &DataLength);
3794 }
3795 }
3796
3797 SampRegCloseKey(&AccountKeyHandle);
3798 }
3799
3800 SampRegCloseKey(&AccountsKeyHandle);
3801 }
3802
3804 break;
3805
3806 /* Return alias account */
3807 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3808 {
3809 TRACE("Name: %S\n", Names->Element[i].Buffer);
3810 Use->Element[i] = SidTypeAlias;
3811 MappedCount++;
3812 continue;
3813 }
3814
3815 /* Lookup groups */
3816 Status = SampRegOpenKey(DomainObject->KeyHandle,
3817 L"Groups",
3818 KEY_READ,
3819 &AccountsKeyHandle);
3820 if (NT_SUCCESS(Status))
3821 {
3822 Status = SampRegOpenKey(AccountsKeyHandle,
3823 RidString,
3824 KEY_READ,
3825 &AccountKeyHandle);
3826 if (NT_SUCCESS(Status))
3827 {
3828 DataLength = 0;
3829 Status = SampRegQueryValue(AccountKeyHandle,
3830 L"Name",
3831 NULL,
3832 NULL,
3833 &DataLength);
3834 if (NT_SUCCESS(Status))
3835 {
3836 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3837 if (Names->Element[i].Buffer == NULL)
3839
3840 if (NT_SUCCESS(Status))
3841 {
3842 Names->Element[i].MaximumLength = (USHORT)DataLength;
3843 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3844
3845 Status = SampRegQueryValue(AccountKeyHandle,
3846 L"Name",
3847 NULL,
3848 Names->Element[i].Buffer,
3849 &DataLength);
3850 }
3851 }
3852
3853 SampRegCloseKey(&AccountKeyHandle);
3854 }
3855
3856 SampRegCloseKey(&AccountsKeyHandle);
3857 }
3858
3860 break;
3861
3862 /* Return group account */
3863 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3864 {
3865 TRACE("Name: %S\n", Names->Element[i].Buffer);
3866 Use->Element[i] = SidTypeGroup;
3867 MappedCount++;
3868 continue;
3869 }
3870
3871 /* Lookup users */
3872 Status = SampRegOpenKey(DomainObject->KeyHandle,
3873 L"Users",
3874 KEY_READ,
3875 &AccountsKeyHandle);
3876 if (NT_SUCCESS(Status))
3877 {
3878 Status = SampRegOpenKey(AccountsKeyHandle,
3879 RidString,
3880 KEY_READ,
3881 &AccountKeyHandle);
3882 if (NT_SUCCESS(Status))
3883 {
3884 DataLength = 0;
3885 Status = SampRegQueryValue(AccountKeyHandle,
3886 L"Name",
3887 NULL,
3888 NULL,
3889 &DataLength);
3890 if (NT_SUCCESS(Status))
3891 {
3892 TRACE("DataLength: %lu\n", DataLength);
3893
3894 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3895 if (Names->Element[i].Buffer == NULL)
3897
3898 if (NT_SUCCESS(Status))
3899 {
3900 Names->Element[i].MaximumLength = (USHORT)DataLength;
3901 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3902
3903 Status = SampRegQueryValue(AccountKeyHandle,
3904 L"Name",
3905 NULL,
3906 Names->Element[i].Buffer,
3907 &DataLength);
3908 }
3909 }
3910
3911 SampRegCloseKey(&AccountKeyHandle);
3912 }
3913
3914 SampRegCloseKey(&AccountsKeyHandle);
3915 }
3916
3918 break;
3919
3920 /* Return user account */
3921 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3922 {
3923 TRACE("Name: %S\n", Names->Element[i].Buffer);
3924 Use->Element[i] = SidTypeUser;
3925 MappedCount++;
3926 continue;
3927 }
3928
3929 /* Return unknown account */
3930 Use->Element[i] = SidTypeUnknown;
3931 }
3932
3933done:
3936
3937 if (NT_SUCCESS(Status))
3938 {
3939 if (MappedCount == 0)
3941 else if (MappedCount < Count)
3943 }
3944 else
3945 {
3946 if (Names->Element != NULL)
3947 {
3948 for (i = 0; i < Count; i++)
3949 {
3950 if (Names->Element[i].Buffer != NULL)
3951 midl_user_free(Names->Element[i].Buffer);
3952 }
3953
3954 midl_user_free(Names->Element);
3955 Names->Element = NULL;
3956 }
3957
3958 Names->Count = 0;
3959
3960 if (Use->Element != NULL)
3961 {
3962 midl_user_free(Use->Element);
3963 Use->Element = NULL;
3964 }
3965
3966 Use->Count = 0;
3967 }
3968
3970
3971 return Status;
3972}
3973
3974
3975/* Function 19 */
3977NTAPI
3980 IN unsigned long GroupId,
3981 OUT SAMPR_HANDLE *GroupHandle)
3982{
3983 PSAM_DB_OBJECT DomainObject;
3984 PSAM_DB_OBJECT GroupObject;
3985 WCHAR szRid[9];
3987
3988 TRACE("SamrOpenGroup(%p %lx %lx %p)\n",
3989 DomainHandle, DesiredAccess, GroupId, GroupHandle);
3990
3991 /* Map generic access rights */
3993 &GroupMapping);
3994
3996 TRUE);
3997
3998 /* Validate the domain handle */
3999 Status = SampValidateDbObject(DomainHandle,
4002 &DomainObject);
4003 if (!NT_SUCCESS(Status))
4004 {
4005 TRACE("failed with status 0x%08lx\n", Status);
4006 goto done;
4007 }
4008
4009 /* Convert the RID into a string (hex) */
4010 swprintf(szRid, L"%08lX", GroupId);
4011
4012 /* Create the group object */
4013 Status = SampOpenDbObject(DomainObject,
4014 L"Groups",
4015 szRid,
4016 GroupId,
4019 &GroupObject);
4020 if (!NT_SUCCESS(Status))
4021 {
4022 TRACE("failed with status 0x%08lx\n", Status);
4023 goto done;
4024 }
4025
4026 *GroupHandle = (SAMPR_HANDLE)GroupObject;
4027
4028done:
4030
4031 return Status;
4032}
4033
4034
4035static NTSTATUS
4038{
4039 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
4040 SAM_GROUP_FIXED_DATA FixedData;
4041 ULONG MembersLength = 0;
4042 ULONG Length = 0;
4044
4045 *Buffer = NULL;
4046
4047 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
4048 if (InfoBuffer == NULL)
4050
4052 L"Name",
4053 &InfoBuffer->General.Name);
4054 if (!NT_SUCCESS(Status))
4055 {
4056 TRACE("Status 0x%08lx\n", Status);
4057 goto done;
4058 }
4059
4061 L"AdminComment",
4062 &InfoBuffer->General.AdminComment);
4063 if (!NT_SUCCESS(Status))
4064 {
4065 TRACE("Status 0x%08lx\n", Status);
4066 goto done;
4067 }
4068
4069 Length = sizeof(SAM_GROUP_FIXED_DATA);
4070 Status = SampGetObjectAttribute(GroupObject,
4071 L"F",
4072 NULL,
4073 (PVOID)&FixedData,
4074 &Length);
4075 if (!NT_SUCCESS(Status))
4076 {
4077 TRACE("Status 0x%08lx\n", Status);
4078 goto done;
4079 }
4080
4081 InfoBuffer->General.Attributes = FixedData.Attributes;
4082
4083 Status = SampGetObjectAttribute(GroupObject,
4084 L"Members",
4085 NULL,
4086 NULL,
4087 &MembersLength);
4089 {
4090 TRACE("Status 0x%08lx\n", Status);
4091 goto done;
4092 }
4093
4095 {
4096 InfoBuffer->General.MemberCount = 0;
4098 }
4099 else
4100 {
4101 InfoBuffer->General.MemberCount = MembersLength / sizeof(ULONG);
4102 }
4103
4104 *Buffer = InfoBuffer;
4105
4106done:
4107 if (!NT_SUCCESS(Status))
4108 {
4109 if (InfoBuffer != NULL)
4110 {
4111 if (InfoBuffer->General.Name.Buffer != NULL)
4112 midl_user_free(InfoBuffer->General.Name.Buffer);
4113
4114 if (InfoBuffer->General.AdminComment.Buffer != NULL)
4116
4117 midl_user_free(InfoBuffer);
4118 }
4119 }
4120
4121 return Status;
4122}
4123
4124
4125static NTSTATUS
4128{
4129 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
4131
4132 *Buffer = NULL;
4133
4134 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
4135 if (InfoBuffer == NULL)
4137
4139 L"Name",
4140 &InfoBuffer->Name.Name);
4141 if (!NT_SUCCESS(Status))
4142 {
4143 TRACE("Status 0x%08lx\n", Status);
4144 goto done;
4145 }
4146
4147 *Buffer = InfoBuffer;
4148
4149done:
4150 if (!NT_SUCCESS(Status))
4151 {
4152 if (InfoBuffer != NULL)
4153 {
4154 if (InfoBuffer->Name.Name.Buffer != NULL)
4155 midl_user_free(InfoBuffer->Name.Name.Buffer);
4156
4157 midl_user_free(InfoBuffer);
4158 }
4159 }
4160
4161 return Status;
4162}
4163
4164
4165static NTSTATUS
4168{
4169 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
4170 SAM_GROUP_FIXED_DATA FixedData;
4171 ULONG Length = 0;
4173
4174 *Buffer = NULL;
4175
4176 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
4177 if (InfoBuffer == NULL)
4179
4180 Length = sizeof(SAM_GROUP_FIXED_DATA);
4181 Status = SampGetObjectAttribute(GroupObject,
4182 L"F",
4183 NULL,
4184 (PVOID)&FixedData,
4185 &Length);
4186 if (!NT_SUCCESS(Status))
4187 {
4188 TRACE("Status 0x%08lx\n", Status);
4189 goto done;
4190 }
4191
4192 InfoBuffer->Attribute.Attributes = FixedData.Attributes;
4193
4194 *Buffer = InfoBuffer;
4195
4196done:
4197 if (!NT_SUCCESS(Status))
4198 {
4199 if (InfoBuffer != NULL)
4200 {
4201 midl_user_free(InfoBuffer);
4202 }
4203 }
4204
4205 return Status;
4206}
4207
4208
4209static NTSTATUS
4212{
4213 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
4215
4216 *Buffer = NULL;
4217
4218 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
4219 if (InfoBuffer == NULL)
4221
4223 L"AdminComment",
4224 &InfoBuffer->AdminComment.AdminComment);
4225 if (!NT_SUCCESS(Status))
4226 {
4227 TRACE("Status 0x%08lx\n", Status);
4228 goto done;
4229 }
4230
4231 *Buffer = InfoBuffer;
4232
4233done:
4234 if (!NT_SUCCESS(Status))
4235 {
4236 if (InfoBuffer != NULL)
4237 {
4238 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
4240
4241 midl_user_free(InfoBuffer);
4242 }
4243 }
4244
4245 return Status;
4246}
4247
4248
4249/* Function 20 */
4251NTAPI
4253 IN GROUP_INFORMATION_CLASS GroupInformationClass,
4255{
4256 PSAM_DB_OBJECT GroupObject;
4258
4259 TRACE("SamrQueryInformationGroup(%p %lu %p)\n",
4260 GroupHandle, GroupInformationClass, Buffer);
4261
4263 TRUE);
4264
4265 /* Validate the group handle */
4266 Status = SampValidateDbObject(GroupHandle,
4269 &GroupObject);
4270 if (!NT_SUCCESS(Status))
4271 goto done;
4272
4273 switch (GroupInformationClass)
4274 {
4276 Status = SampQueryGroupGeneral(GroupObject,
4277 Buffer);
4278 break;
4279
4281 Status = SampQueryGroupName(GroupObject,
4282 Buffer);
4283 break;
4284
4286 Status = SampQueryGroupAttribute(GroupObject,
4287 Buffer);
4288 break;
4289
4291 Status = SampQueryGroupAdminComment(GroupObject,
4292 Buffer);
4293 break;
4294
4295 default:
4297 break;
4298 }
4299
4300done:
4302
4303 return Status;
4304}
4305
4306
4307static NTSTATUS
4310{
4311 UNICODE_STRING OldGroupName = {0, 0, NULL};
4312 UNICODE_STRING NewGroupName;
4314
4316 L"Name",
4317 (PRPC_UNICODE_STRING)&OldGroupName);
4318 if (!NT_SUCCESS(Status))
4319 {
4320 TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status);
4321 goto done;
4322 }
4323
4324 /* Check the new account name */
4325 Status = SampCheckAccountName(&Buffer->Name.Name, 256);
4326 if (!NT_SUCCESS(Status))
4327 {
4328 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
4329 return Status;
4330 }
4331
4332 NewGroupName.Length = Buffer->Name.Name.Length;
4333 NewGroupName.MaximumLength = Buffer->Name.Name.MaximumLength;
4334 NewGroupName.Buffer = Buffer->Name.Name.Buffer;
4335
4336 if (!RtlEqualUnicodeString(&OldGroupName, &NewGroupName, TRUE))
4337 {
4339 NewGroupName.Buffer);
4340 if (!NT_SUCCESS(Status))
4341 {
4342 TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n",
4343 NewGroupName.Buffer, Status);
4344 goto done;
4345 }
4346 }
4347
4349 L"Groups",
4350 NewGroupName.Buffer,
4351 GroupObject->RelativeId);
4352 if (!NT_SUCCESS(Status))
4353 {
4354 TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status);
4355 goto done;
4356 }
4357
4359 L"Groups",
4360 OldGroupName.Buffer);
4361 if (!NT_SUCCESS(Status))
4362 {
4363 TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status);
4364 goto done;
4365 }
4366
4368 L"Name",
4369 (PRPC_UNICODE_STRING)&NewGroupName);
4370 if (!NT_SUCCESS(Status))
4371 {
4372 TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
4373 }
4374
4375done:
4376 if (OldGroupName.Buffer != NULL)
4377 midl_user_free(OldGroupName.Buffer);
4378
4379 return Status;
4380}
4381
4382
4383static NTSTATUS
4386{
4387 SAM_GROUP_FIXED_DATA FixedData;
4388 ULONG Length = 0;
4390
4391 Length = sizeof(SAM_GROUP_FIXED_DATA);
4392 Status = SampGetObjectAttribute(GroupObject,
4393 L"F",
4394 NULL,
4395 (PVOID)&FixedData,
4396 &Length);
4397 if (!NT_SUCCESS(Status))
4398 goto done;
4399
4400 FixedData.Attributes = Buffer->Attribute.Attributes;
4401
4402 Status = SampSetObjectAttribute(GroupObject,
4403 L"F",
4404 REG_BINARY,
4405 &FixedData,
4406 Length);
4407
4408done:
4409 return Status;
4410}
4411
4412
4413/* Function 21 */
4415NTAPI
4417 IN GROUP_INFORMATION_CLASS GroupInformationClass,
4419{
4420 PSAM_DB_OBJECT GroupObject;
4422
4423 TRACE("SamrSetInformationGroup(%p %lu %p)\n",
4424 GroupHandle, GroupInformationClass, Buffer);
4425
4427 TRUE);
4428
4429 /* Validate the group handle */
4430 Status = SampValidateDbObject(GroupHandle,
4432