[SAMSRV]
[reactos.git] / reactos / dll / win32 / samsrv / samrpc.c
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 /* INCLUDES ******************************************************************/
11
12 #include "samsrv.h"
13
14 WINE_DEFAULT_DEBUG_CHANNEL(samsrv);
15
16 /* GLOBALS *******************************************************************/
17
18 static SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
19
20 static GENERIC_MAPPING ServerMapping =
21 {
22 SAM_SERVER_READ,
23 SAM_SERVER_WRITE,
24 SAM_SERVER_EXECUTE,
25 SAM_SERVER_ALL_ACCESS
26 };
27
28 static GENERIC_MAPPING DomainMapping =
29 {
30 DOMAIN_READ,
31 DOMAIN_WRITE,
32 DOMAIN_EXECUTE,
33 DOMAIN_ALL_ACCESS
34 };
35
36 static GENERIC_MAPPING AliasMapping =
37 {
38 ALIAS_READ,
39 ALIAS_WRITE,
40 ALIAS_EXECUTE,
41 ALIAS_ALL_ACCESS
42 };
43
44 static GENERIC_MAPPING GroupMapping =
45 {
46 GROUP_READ,
47 GROUP_WRITE,
48 GROUP_EXECUTE,
49 GROUP_ALL_ACCESS
50 };
51
52 static GENERIC_MAPPING UserMapping =
53 {
54 USER_READ,
55 USER_WRITE,
56 USER_EXECUTE,
57 USER_ALL_ACCESS
58 };
59
60 PGENERIC_MAPPING pServerMapping = &ServerMapping;
61
62
63 /* FUNCTIONS *****************************************************************/
64
65 static
66 LARGE_INTEGER
67 SampAddRelativeTimeToTime(IN LARGE_INTEGER AbsoluteTime,
68 IN LARGE_INTEGER RelativeTime)
69 {
70 LARGE_INTEGER NewTime;
71
72 NewTime.QuadPart = AbsoluteTime.QuadPart - RelativeTime.QuadPart;
73
74 if (NewTime.QuadPart < 0)
75 NewTime.QuadPart = 0;
76
77 return NewTime;
78 }
79
80
81 VOID
82 SampStartRpcServer(VOID)
83 {
84 RPC_STATUS Status;
85
86 TRACE("SampStartRpcServer() called\n");
87
88 Status = RpcServerUseProtseqEpW(L"ncacn_np",
89 10,
90 L"\\pipe\\samr",
91 NULL);
92 if (Status != RPC_S_OK)
93 {
94 WARN("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
95 return;
96 }
97
98 Status = RpcServerRegisterIf(samr_v1_0_s_ifspec,
99 NULL,
100 NULL);
101 if (Status != RPC_S_OK)
102 {
103 WARN("RpcServerRegisterIf() failed (Status %lx)\n", Status);
104 return;
105 }
106
107 Status = RpcServerListen(1, 20, TRUE);
108 if (Status != RPC_S_OK)
109 {
110 WARN("RpcServerListen() failed (Status %lx)\n", Status);
111 return;
112 }
113
114 TRACE("SampStartRpcServer() done\n");
115 }
116
117
118 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
119 {
120 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
121 }
122
123
124 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
125 {
126 HeapFree(GetProcessHeap(), 0, ptr);
127 }
128
129
130 void __RPC_USER SAMPR_HANDLE_rundown(SAMPR_HANDLE hHandle)
131 {
132 }
133
134
135 /* Function 0 */
136 NTSTATUS
137 NTAPI
138 SamrConnect(IN PSAMPR_SERVER_NAME ServerName,
139 OUT SAMPR_HANDLE *ServerHandle,
140 IN ACCESS_MASK DesiredAccess)
141 {
142 PSAM_DB_OBJECT ServerObject;
143 NTSTATUS Status;
144
145 TRACE("SamrConnect(%p %p %lx)\n",
146 ServerName, ServerHandle, DesiredAccess);
147
148 RtlAcquireResourceShared(&SampResource,
149 TRUE);
150
151 /* Map generic access rights */
152 RtlMapGenericMask(&DesiredAccess,
153 &ServerMapping);
154
155 /* Open the Server Object */
156 Status = SampOpenDbObject(NULL,
157 NULL,
158 L"SAM",
159 0,
160 SamDbServerObject,
161 DesiredAccess,
162 &ServerObject);
163 if (NT_SUCCESS(Status))
164 *ServerHandle = (SAMPR_HANDLE)ServerObject;
165
166 RtlReleaseResource(&SampResource);
167
168 TRACE("SamrConnect done (Status 0x%08lx)\n", Status);
169
170 return Status;
171 }
172
173
174 /* Function 1 */
175 NTSTATUS
176 NTAPI
177 SamrCloseHandle(IN OUT SAMPR_HANDLE *SamHandle)
178 {
179 PSAM_DB_OBJECT DbObject;
180 NTSTATUS Status = STATUS_SUCCESS;
181
182 TRACE("SamrCloseHandle(%p)\n", SamHandle);
183
184 RtlAcquireResourceShared(&SampResource,
185 TRUE);
186
187 Status = SampValidateDbObject(*SamHandle,
188 SamDbIgnoreObject,
189 0,
190 &DbObject);
191 if (Status == STATUS_SUCCESS)
192 {
193 Status = SampCloseDbObject(DbObject);
194 *SamHandle = NULL;
195 }
196
197 RtlReleaseResource(&SampResource);
198
199 TRACE("SamrCloseHandle done (Status 0x%08lx)\n", Status);
200
201 return Status;
202 }
203
204
205 /* Function 2 */
206 NTSTATUS
207 NTAPI
208 SamrSetSecurityObject(IN SAMPR_HANDLE ObjectHandle,
209 IN SECURITY_INFORMATION SecurityInformation,
210 IN PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor)
211 {
212 UNIMPLEMENTED;
213 return STATUS_NOT_IMPLEMENTED;
214 }
215
216
217 /* Function 3 */
218 NTSTATUS
219 NTAPI
220 SamrQuerySecurityObject(IN SAMPR_HANDLE ObjectHandle,
221 IN SECURITY_INFORMATION SecurityInformation,
222 OUT PSAMPR_SR_SECURITY_DESCRIPTOR *SecurityDescriptor)
223 {
224 UNIMPLEMENTED;
225 return STATUS_NOT_IMPLEMENTED;
226 }
227
228
229 /* Function 4 */
230 NTSTATUS
231 NTAPI
232 SamrShutdownSamServer(IN SAMPR_HANDLE ServerHandle)
233 {
234 PSAM_DB_OBJECT ServerObject;
235 NTSTATUS Status;
236
237 TRACE("(%p)\n", ServerHandle);
238
239 RtlAcquireResourceShared(&SampResource,
240 TRUE);
241
242 /* Validate the server handle */
243 Status = SampValidateDbObject(ServerHandle,
244 SamDbServerObject,
245 SAM_SERVER_SHUTDOWN,
246 &ServerObject);
247
248 RtlReleaseResource(&SampResource);
249
250 if (!NT_SUCCESS(Status))
251 return Status;
252
253 /* Shut the server down */
254 RpcMgmtStopServerListening(0);
255
256 return STATUS_SUCCESS;
257 }
258
259
260 /* Function 5 */
261 NTSTATUS
262 NTAPI
263 SamrLookupDomainInSamServer(IN SAMPR_HANDLE ServerHandle,
264 IN PRPC_UNICODE_STRING Name,
265 OUT PRPC_SID *DomainId)
266 {
267 PSAM_DB_OBJECT ServerObject;
268 HANDLE DomainsKeyHandle = NULL;
269 HANDLE DomainKeyHandle = NULL;
270 WCHAR DomainKeyName[64];
271 ULONG Index;
272 WCHAR DomainNameString[MAX_COMPUTERNAME_LENGTH + 1];
273 UNICODE_STRING DomainName;
274 ULONG Length;
275 BOOL Found = FALSE;
276 NTSTATUS Status;
277
278 TRACE("SamrLookupDomainInSamServer(%p %p %p)\n",
279 ServerHandle, Name, DomainId);
280
281 RtlAcquireResourceShared(&SampResource,
282 TRUE);
283
284 /* Validate the server handle */
285 Status = SampValidateDbObject(ServerHandle,
286 SamDbServerObject,
287 SAM_SERVER_LOOKUP_DOMAIN,
288 &ServerObject);
289 if (!NT_SUCCESS(Status))
290 goto done;
291
292 *DomainId = NULL;
293
294 Status = SampRegOpenKey(ServerObject->KeyHandle,
295 L"Domains",
296 KEY_READ,
297 &DomainsKeyHandle);
298 if (!NT_SUCCESS(Status))
299 goto done;
300
301 Index = 0;
302 while (Found == FALSE)
303 {
304 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
305 Index,
306 64,
307 DomainKeyName);
308 if (!NT_SUCCESS(Status))
309 {
310 if (Status == STATUS_NO_MORE_ENTRIES)
311 Status = STATUS_NO_SUCH_DOMAIN;
312 break;
313 }
314
315 TRACE("Domain key name: %S\n", DomainKeyName);
316
317 Status = SampRegOpenKey(DomainsKeyHandle,
318 DomainKeyName,
319 KEY_READ,
320 &DomainKeyHandle);
321 if (NT_SUCCESS(Status))
322 {
323 Length = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR);
324 Status = SampRegQueryValue(DomainKeyHandle,
325 L"Name",
326 NULL,
327 (PVOID)&DomainNameString,
328 &Length);
329 if (NT_SUCCESS(Status))
330 {
331 TRACE("Domain name: %S\n", DomainNameString);
332
333 RtlInitUnicodeString(&DomainName,
334 DomainNameString);
335 if (RtlEqualUnicodeString(&DomainName, (PUNICODE_STRING)Name, TRUE))
336 {
337 TRACE("Found it!\n");
338 Found = TRUE;
339
340 Status = SampRegQueryValue(DomainKeyHandle,
341 L"SID",
342 NULL,
343 NULL,
344 &Length);
345 if (NT_SUCCESS(Status))
346 {
347 *DomainId = midl_user_allocate(Length);
348
349 SampRegQueryValue(DomainKeyHandle,
350 L"SID",
351 NULL,
352 (PVOID)*DomainId,
353 &Length);
354
355 Status = STATUS_SUCCESS;
356 break;
357 }
358 }
359 }
360
361 SampRegCloseKey(&DomainKeyHandle);
362 }
363
364 Index++;
365 }
366
367 done:
368 SampRegCloseKey(&DomainKeyHandle);
369 SampRegCloseKey(&DomainsKeyHandle);
370
371 RtlReleaseResource(&SampResource);
372
373 return Status;
374 }
375
376
377 /* Function 6 */
378 NTSTATUS
379 NTAPI
380 SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle,
381 IN OUT unsigned long *EnumerationContext,
382 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
383 IN ULONG PreferedMaximumLength,
384 OUT PULONG CountReturned)
385 {
386 PSAM_DB_OBJECT ServerObject;
387 WCHAR DomainKeyName[64];
388 HANDLE DomainsKeyHandle = NULL;
389 HANDLE DomainKeyHandle = NULL;
390 ULONG EnumIndex;
391 ULONG EnumCount;
392 ULONG RequiredLength;
393 ULONG DataLength;
394 ULONG i;
395 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
396 NTSTATUS Status;
397
398 TRACE("SamrEnumerateDomainsInSamServer(%p %p %p %lu %p)\n",
399 ServerHandle, EnumerationContext, Buffer, PreferedMaximumLength,
400 CountReturned);
401
402 RtlAcquireResourceShared(&SampResource,
403 TRUE);
404
405 /* Validate the server handle */
406 Status = SampValidateDbObject(ServerHandle,
407 SamDbServerObject,
408 SAM_SERVER_ENUMERATE_DOMAINS,
409 &ServerObject);
410 if (!NT_SUCCESS(Status))
411 goto done;
412
413 Status = SampRegOpenKey(ServerObject->KeyHandle,
414 L"Domains",
415 KEY_READ,
416 &DomainsKeyHandle);
417 if (!NT_SUCCESS(Status))
418 goto done;
419
420 EnumIndex = *EnumerationContext;
421 EnumCount = 0;
422 RequiredLength = 0;
423
424 while (TRUE)
425 {
426 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
427 EnumIndex,
428 64 * sizeof(WCHAR),
429 DomainKeyName);
430 if (!NT_SUCCESS(Status))
431 break;
432
433 TRACE("EnumIndex: %lu\n", EnumIndex);
434 TRACE("Domain key name: %S\n", DomainKeyName);
435
436 Status = SampRegOpenKey(DomainsKeyHandle,
437 DomainKeyName,
438 KEY_READ,
439 &DomainKeyHandle);
440 TRACE("SampRegOpenKey returned %08lX\n", Status);
441 if (NT_SUCCESS(Status))
442 {
443 DataLength = 0;
444 Status = SampRegQueryValue(DomainKeyHandle,
445 L"Name",
446 NULL,
447 NULL,
448 &DataLength);
449 TRACE("SampRegQueryValue returned %08lX\n", Status);
450 if (NT_SUCCESS(Status))
451 {
452 TRACE("Data length: %lu\n", DataLength);
453
454 if ((RequiredLength + DataLength + sizeof(UNICODE_STRING)) > PreferedMaximumLength)
455 break;
456
457 RequiredLength += (DataLength + sizeof(UNICODE_STRING));
458 EnumCount++;
459 }
460
461 SampRegCloseKey(&DomainKeyHandle);
462 }
463
464 EnumIndex++;
465 }
466
467 TRACE("EnumCount: %lu\n", EnumCount);
468 TRACE("RequiredLength: %lu\n", RequiredLength);
469
470 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
471 if (EnumBuffer == NULL)
472 {
473 Status = STATUS_INSUFFICIENT_RESOURCES;
474 goto done;
475 }
476
477 EnumBuffer->EntriesRead = EnumCount;
478 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
479 if (EnumBuffer->Buffer == NULL)
480 {
481 Status = STATUS_INSUFFICIENT_RESOURCES;
482 goto done;
483 }
484
485 EnumIndex = *EnumerationContext;
486 for (i = 0; i < EnumCount; i++, EnumIndex++)
487 {
488 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
489 EnumIndex,
490 64 * sizeof(WCHAR),
491 DomainKeyName);
492 if (!NT_SUCCESS(Status))
493 break;
494
495 TRACE("EnumIndex: %lu\n", EnumIndex);
496 TRACE("Domain key name: %S\n", DomainKeyName);
497
498 Status = SampRegOpenKey(DomainsKeyHandle,
499 DomainKeyName,
500 KEY_READ,
501 &DomainKeyHandle);
502 TRACE("SampRegOpenKey returned %08lX\n", Status);
503 if (NT_SUCCESS(Status))
504 {
505 DataLength = 0;
506 Status = SampRegQueryValue(DomainKeyHandle,
507 L"Name",
508 NULL,
509 NULL,
510 &DataLength);
511 TRACE("SampRegQueryValue returned %08lX\n", Status);
512 if (NT_SUCCESS(Status))
513 {
514 EnumBuffer->Buffer[i].RelativeId = 0;
515 EnumBuffer->Buffer[i].Name.Length = (USHORT)DataLength - sizeof(WCHAR);
516 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)DataLength;
517 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(DataLength);
518 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
519 {
520 SampRegCloseKey(&DomainKeyHandle);
521 Status = STATUS_INSUFFICIENT_RESOURCES;
522 goto done;
523 }
524
525 Status = SampRegQueryValue(DomainKeyHandle,
526 L"Name",
527 NULL,
528 EnumBuffer->Buffer[i].Name.Buffer,
529 &DataLength);
530 TRACE("SampRegQueryValue returned %08lX\n", Status);
531 if (NT_SUCCESS(Status))
532 {
533 TRACE("Domain name: %S\n", EnumBuffer->Buffer[i].Name.Buffer);
534 }
535 }
536
537 SampRegCloseKey(&DomainKeyHandle);
538
539 if (!NT_SUCCESS(Status))
540 goto done;
541 }
542 }
543
544 if (NT_SUCCESS(Status))
545 {
546 *EnumerationContext += EnumCount;
547 *Buffer = EnumBuffer;
548 *CountReturned = EnumCount;
549 }
550
551 done:
552 SampRegCloseKey(&DomainKeyHandle);
553 SampRegCloseKey(&DomainsKeyHandle);
554
555 if (!NT_SUCCESS(Status))
556 {
557 *EnumerationContext = 0;
558 *Buffer = NULL;
559 *CountReturned = 0;
560
561 if (EnumBuffer != NULL)
562 {
563 if (EnumBuffer->Buffer != NULL)
564 {
565 if (EnumBuffer->EntriesRead != 0)
566 {
567 for (i = 0; i < EnumBuffer->EntriesRead; i++)
568 {
569 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
570 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
571 }
572 }
573
574 midl_user_free(EnumBuffer->Buffer);
575 }
576
577 midl_user_free(EnumBuffer);
578 }
579 }
580
581 RtlReleaseResource(&SampResource);
582
583 return Status;
584 }
585
586
587 /* Function 7 */
588 NTSTATUS
589 NTAPI
590 SamrOpenDomain(IN SAMPR_HANDLE ServerHandle,
591 IN ACCESS_MASK DesiredAccess,
592 IN PRPC_SID DomainId,
593 OUT SAMPR_HANDLE *DomainHandle)
594 {
595 PSAM_DB_OBJECT ServerObject;
596 PSAM_DB_OBJECT DomainObject;
597 NTSTATUS Status;
598
599 TRACE("SamrOpenDomain(%p %lx %p %p)\n",
600 ServerHandle, DesiredAccess, DomainId, DomainHandle);
601
602 /* Map generic access rights */
603 RtlMapGenericMask(&DesiredAccess,
604 &DomainMapping);
605
606 RtlAcquireResourceShared(&SampResource,
607 TRUE);
608
609 /* Validate the server handle */
610 Status = SampValidateDbObject(ServerHandle,
611 SamDbServerObject,
612 SAM_SERVER_LOOKUP_DOMAIN,
613 &ServerObject);
614 if (!NT_SUCCESS(Status))
615 return Status;
616
617 /* Validate the Domain SID */
618 if ((DomainId->Revision != SID_REVISION) ||
619 (DomainId->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) ||
620 (memcmp(&DomainId->IdentifierAuthority, &NtSidAuthority, sizeof(SID_IDENTIFIER_AUTHORITY)) != 0))
621 return STATUS_INVALID_PARAMETER;
622
623 /* Open the domain object */
624 if ((DomainId->SubAuthorityCount == 1) &&
625 (DomainId->SubAuthority[0] == SECURITY_BUILTIN_DOMAIN_RID))
626 {
627 /* Builtin domain object */
628 TRACE("Opening the builtin domain object.\n");
629
630 Status = SampOpenDbObject(ServerObject,
631 L"Domains",
632 L"Builtin",
633 0,
634 SamDbDomainObject,
635 DesiredAccess,
636 &DomainObject);
637 }
638 else if ((DomainId->SubAuthorityCount == 4) &&
639 (DomainId->SubAuthority[0] == SECURITY_NT_NON_UNIQUE))
640 {
641 /* Account domain object */
642 TRACE("Opening the account domain object.\n");
643
644 /* FIXME: Check the account domain sub authorities!!! */
645
646 Status = SampOpenDbObject(ServerObject,
647 L"Domains",
648 L"Account",
649 0,
650 SamDbDomainObject,
651 DesiredAccess,
652 &DomainObject);
653 }
654 else
655 {
656 /* No vaild domain SID */
657 Status = STATUS_INVALID_PARAMETER;
658 }
659
660 if (NT_SUCCESS(Status))
661 *DomainHandle = (SAMPR_HANDLE)DomainObject;
662
663 RtlReleaseResource(&SampResource);
664
665 TRACE("SamrOpenDomain done (Status 0x%08lx)\n", Status);
666
667 return Status;
668 }
669
670
671 static NTSTATUS
672 SampQueryDomainPassword(PSAM_DB_OBJECT DomainObject,
673 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
674 {
675 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
676 SAM_DOMAIN_FIXED_DATA FixedData;
677 ULONG Length = 0;
678 NTSTATUS Status;
679
680 *Buffer = NULL;
681
682 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
683 if (InfoBuffer == NULL)
684 return STATUS_INSUFFICIENT_RESOURCES;
685
686 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
687 Status = SampGetObjectAttribute(DomainObject,
688 L"F",
689 NULL,
690 (PVOID)&FixedData,
691 &Length);
692 if (!NT_SUCCESS(Status))
693 goto done;
694
695 InfoBuffer->Password.MinPasswordLength = FixedData.MinPasswordLength;
696 InfoBuffer->Password.PasswordHistoryLength = FixedData.PasswordHistoryLength;
697 InfoBuffer->Password.PasswordProperties = FixedData.PasswordProperties;
698 InfoBuffer->Password.MaxPasswordAge.LowPart = FixedData.MaxPasswordAge.LowPart;
699 InfoBuffer->Password.MaxPasswordAge.HighPart = FixedData.MaxPasswordAge.HighPart;
700 InfoBuffer->Password.MinPasswordAge.LowPart = FixedData.MinPasswordAge.LowPart;
701 InfoBuffer->Password.MinPasswordAge.HighPart = FixedData.MinPasswordAge.HighPart;
702
703 *Buffer = InfoBuffer;
704
705 done:
706 if (!NT_SUCCESS(Status))
707 {
708 if (InfoBuffer != NULL)
709 {
710 midl_user_free(InfoBuffer);
711 }
712 }
713
714 return Status;
715 }
716
717
718 static NTSTATUS
719 SampGetNumberOfAccounts(PSAM_DB_OBJECT DomainObject,
720 LPCWSTR AccountType,
721 PULONG Count)
722 {
723 HANDLE AccountKeyHandle = NULL;
724 HANDLE NamesKeyHandle = NULL;
725 NTSTATUS Status;
726
727 *Count = 0;
728
729 Status = SampRegOpenKey(DomainObject->KeyHandle,
730 AccountType,
731 KEY_READ,
732 &AccountKeyHandle);
733 if (!NT_SUCCESS(Status))
734 return Status;
735
736 Status = SampRegOpenKey(AccountKeyHandle,
737 L"Names",
738 KEY_READ,
739 &NamesKeyHandle);
740 if (!NT_SUCCESS(Status))
741 goto done;
742
743 Status = SampRegQueryKeyInfo(NamesKeyHandle,
744 NULL,
745 Count);
746
747 done:
748 SampRegCloseKey(&NamesKeyHandle);
749 SampRegCloseKey(&AccountKeyHandle);
750
751 return Status;
752 }
753
754
755 static NTSTATUS
756 SampQueryDomainGeneral(PSAM_DB_OBJECT DomainObject,
757 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
758 {
759 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
760 SAM_DOMAIN_FIXED_DATA FixedData;
761 ULONG Length = 0;
762 NTSTATUS Status;
763
764 *Buffer = NULL;
765
766 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
767 if (InfoBuffer == NULL)
768 return STATUS_INSUFFICIENT_RESOURCES;
769
770 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
771 Status = SampGetObjectAttribute(DomainObject,
772 L"F",
773 NULL,
774 (PVOID)&FixedData,
775 &Length);
776 if (!NT_SUCCESS(Status))
777 goto done;
778
779 InfoBuffer->General.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
780 InfoBuffer->General.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
781 InfoBuffer->General.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
782 InfoBuffer->General.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
783 InfoBuffer->General.DomainServerState = FixedData.DomainServerState;
784 InfoBuffer->General.DomainServerRole = FixedData.DomainServerRole;
785 InfoBuffer->General.UasCompatibilityRequired = FixedData.UasCompatibilityRequired;
786
787 /* Get the OemInformation string */
788 Status = SampGetObjectAttributeString(DomainObject,
789 L"OemInformation",
790 &InfoBuffer->General.OemInformation);
791 if (!NT_SUCCESS(Status))
792 {
793 TRACE("Status 0x%08lx\n", Status);
794 goto done;
795 }
796
797 /* Get the Name string */
798 Status = SampGetObjectAttributeString(DomainObject,
799 L"Name",
800 &InfoBuffer->General.DomainName);
801 if (!NT_SUCCESS(Status))
802 {
803 TRACE("Status 0x%08lx\n", Status);
804 goto done;
805 }
806
807 /* Get the ReplicaSourceNodeName string */
808 Status = SampGetObjectAttributeString(DomainObject,
809 L"ReplicaSourceNodeName",
810 &InfoBuffer->General.ReplicaSourceNodeName);
811 if (!NT_SUCCESS(Status))
812 {
813 TRACE("Status 0x%08lx\n", Status);
814 goto done;
815 }
816
817 /* Get the number of Users in the Domain */
818 Status = SampGetNumberOfAccounts(DomainObject,
819 L"Users",
820 &InfoBuffer->General.UserCount);
821 if (!NT_SUCCESS(Status))
822 {
823 TRACE("Status 0x%08lx\n", Status);
824 goto done;
825 }
826
827 /* Get the number of Groups in the Domain */
828 Status = SampGetNumberOfAccounts(DomainObject,
829 L"Groups",
830 &InfoBuffer->General.GroupCount);
831 if (!NT_SUCCESS(Status))
832 {
833 TRACE("Status 0x%08lx\n", Status);
834 goto done;
835 }
836
837 /* Get the number of Aliases in the Domain */
838 Status = SampGetNumberOfAccounts(DomainObject,
839 L"Aliases",
840 &InfoBuffer->General.AliasCount);
841 if (!NT_SUCCESS(Status))
842 {
843 TRACE("Status 0x%08lx\n", Status);
844 goto done;
845 }
846
847 *Buffer = InfoBuffer;
848
849 done:
850 if (!NT_SUCCESS(Status))
851 {
852 if (InfoBuffer != NULL)
853 {
854 if (InfoBuffer->General.OemInformation.Buffer != NULL)
855 midl_user_free(InfoBuffer->General.OemInformation.Buffer);
856
857 if (InfoBuffer->General.DomainName.Buffer != NULL)
858 midl_user_free(InfoBuffer->General.DomainName.Buffer);
859
860 if (InfoBuffer->General.ReplicaSourceNodeName.Buffer != NULL)
861 midl_user_free(InfoBuffer->General.ReplicaSourceNodeName.Buffer);
862
863 midl_user_free(InfoBuffer);
864 }
865 }
866
867 return Status;
868 }
869
870
871 static NTSTATUS
872 SampQueryDomainLogoff(PSAM_DB_OBJECT DomainObject,
873 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
874 {
875 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
876 SAM_DOMAIN_FIXED_DATA FixedData;
877 ULONG Length = 0;
878 NTSTATUS Status;
879
880 *Buffer = NULL;
881
882 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
883 if (InfoBuffer == NULL)
884 return STATUS_INSUFFICIENT_RESOURCES;
885
886 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
887 Status = SampGetObjectAttribute(DomainObject,
888 L"F",
889 NULL,
890 (PVOID)&FixedData,
891 &Length);
892 if (!NT_SUCCESS(Status))
893 goto done;
894
895 InfoBuffer->Logoff.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
896 InfoBuffer->Logoff.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
897
898 *Buffer = InfoBuffer;
899
900 done:
901 if (!NT_SUCCESS(Status))
902 {
903 if (InfoBuffer != NULL)
904 {
905 midl_user_free(InfoBuffer);
906 }
907 }
908
909 return Status;
910 }
911
912
913 static NTSTATUS
914 SampQueryDomainOem(PSAM_DB_OBJECT DomainObject,
915 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
916 {
917 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
918 NTSTATUS Status;
919
920 *Buffer = NULL;
921
922 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
923 if (InfoBuffer == NULL)
924 return STATUS_INSUFFICIENT_RESOURCES;
925
926 /* Get the OemInformation string */
927 Status = SampGetObjectAttributeString(DomainObject,
928 L"OemInformation",
929 &InfoBuffer->Oem.OemInformation);
930 if (!NT_SUCCESS(Status))
931 {
932 TRACE("Status 0x%08lx\n", Status);
933 goto done;
934 }
935
936 *Buffer = InfoBuffer;
937
938 done:
939 if (!NT_SUCCESS(Status))
940 {
941 if (InfoBuffer != NULL)
942 {
943 if (InfoBuffer->Oem.OemInformation.Buffer != NULL)
944 midl_user_free(InfoBuffer->Oem.OemInformation.Buffer);
945
946 midl_user_free(InfoBuffer);
947 }
948 }
949
950 return Status;
951 }
952
953
954 static NTSTATUS
955 SampQueryDomainName(PSAM_DB_OBJECT DomainObject,
956 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
957 {
958 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
959 NTSTATUS Status;
960
961 *Buffer = NULL;
962
963 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
964 if (InfoBuffer == NULL)
965 return STATUS_INSUFFICIENT_RESOURCES;
966
967 /* Get the Name string */
968 Status = SampGetObjectAttributeString(DomainObject,
969 L"Name",
970 &InfoBuffer->Name.DomainName);
971 if (!NT_SUCCESS(Status))
972 {
973 TRACE("Status 0x%08lx\n", Status);
974 goto done;
975 }
976
977 *Buffer = InfoBuffer;
978
979 done:
980 if (!NT_SUCCESS(Status))
981 {
982 if (InfoBuffer != NULL)
983 {
984 if (InfoBuffer->Name.DomainName.Buffer != NULL)
985 midl_user_free(InfoBuffer->Name.DomainName.Buffer);
986
987 midl_user_free(InfoBuffer);
988 }
989 }
990
991 return Status;
992 }
993
994
995 static NTSTATUS
996 SampQueryDomainReplication(PSAM_DB_OBJECT DomainObject,
997 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
998 {
999 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1000 NTSTATUS Status;
1001
1002 *Buffer = NULL;
1003
1004 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1005 if (InfoBuffer == NULL)
1006 return STATUS_INSUFFICIENT_RESOURCES;
1007
1008 /* Get the ReplicaSourceNodeName string */
1009 Status = SampGetObjectAttributeString(DomainObject,
1010 L"ReplicaSourceNodeName",
1011 &InfoBuffer->Replication.ReplicaSourceNodeName);
1012 if (!NT_SUCCESS(Status))
1013 {
1014 TRACE("Status 0x%08lx\n", Status);
1015 goto done;
1016 }
1017
1018 *Buffer = InfoBuffer;
1019
1020 done:
1021 if (!NT_SUCCESS(Status))
1022 {
1023 if (InfoBuffer != NULL)
1024 {
1025 if (InfoBuffer->Replication.ReplicaSourceNodeName.Buffer != NULL)
1026 midl_user_free(InfoBuffer->Replication.ReplicaSourceNodeName.Buffer);
1027
1028 midl_user_free(InfoBuffer);
1029 }
1030 }
1031
1032 return Status;
1033 }
1034
1035
1036 static NTSTATUS
1037 SampQueryDomainServerRole(PSAM_DB_OBJECT DomainObject,
1038 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1039 {
1040 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1041 SAM_DOMAIN_FIXED_DATA FixedData;
1042 ULONG Length = 0;
1043 NTSTATUS Status;
1044
1045 *Buffer = NULL;
1046
1047 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1048 if (InfoBuffer == NULL)
1049 return STATUS_INSUFFICIENT_RESOURCES;
1050
1051 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1052 Status = SampGetObjectAttribute(DomainObject,
1053 L"F",
1054 NULL,
1055 (PVOID)&FixedData,
1056 &Length);
1057 if (!NT_SUCCESS(Status))
1058 goto done;
1059
1060 InfoBuffer->Role.DomainServerRole = FixedData.DomainServerRole;
1061
1062 *Buffer = InfoBuffer;
1063
1064 done:
1065 if (!NT_SUCCESS(Status))
1066 {
1067 if (InfoBuffer != NULL)
1068 {
1069 midl_user_free(InfoBuffer);
1070 }
1071 }
1072
1073 return Status;
1074 }
1075
1076
1077 static NTSTATUS
1078 SampQueryDomainModified(PSAM_DB_OBJECT DomainObject,
1079 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1080 {
1081 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1082 SAM_DOMAIN_FIXED_DATA FixedData;
1083 ULONG Length = 0;
1084 NTSTATUS Status;
1085
1086 *Buffer = NULL;
1087
1088 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1089 if (InfoBuffer == NULL)
1090 return STATUS_INSUFFICIENT_RESOURCES;
1091
1092 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1093 Status = SampGetObjectAttribute(DomainObject,
1094 L"F",
1095 NULL,
1096 (PVOID)&FixedData,
1097 &Length);
1098 if (!NT_SUCCESS(Status))
1099 goto done;
1100
1101 InfoBuffer->Modified.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
1102 InfoBuffer->Modified.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
1103 InfoBuffer->Modified.CreationTime.LowPart = FixedData.CreationTime.LowPart;
1104 InfoBuffer->Modified.CreationTime.HighPart = FixedData.CreationTime.HighPart;
1105
1106 *Buffer = InfoBuffer;
1107
1108 done:
1109 if (!NT_SUCCESS(Status))
1110 {
1111 if (InfoBuffer != NULL)
1112 {
1113 midl_user_free(InfoBuffer);
1114 }
1115 }
1116
1117 return Status;
1118 }
1119
1120
1121 static NTSTATUS
1122 SampQueryDomainState(PSAM_DB_OBJECT DomainObject,
1123 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1124 {
1125 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1126 SAM_DOMAIN_FIXED_DATA FixedData;
1127 ULONG Length = 0;
1128 NTSTATUS Status;
1129
1130 *Buffer = NULL;
1131
1132 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1133 if (InfoBuffer == NULL)
1134 return STATUS_INSUFFICIENT_RESOURCES;
1135
1136 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1137 Status = SampGetObjectAttribute(DomainObject,
1138 L"F",
1139 NULL,
1140 (PVOID)&FixedData,
1141 &Length);
1142 if (!NT_SUCCESS(Status))
1143 goto done;
1144
1145 InfoBuffer->State.DomainServerState = FixedData.DomainServerState;
1146
1147 *Buffer = InfoBuffer;
1148
1149 done:
1150 if (!NT_SUCCESS(Status))
1151 {
1152 if (InfoBuffer != NULL)
1153 {
1154 midl_user_free(InfoBuffer);
1155 }
1156 }
1157
1158 return Status;
1159 }
1160
1161
1162 static NTSTATUS
1163 SampQueryDomainGeneral2(PSAM_DB_OBJECT DomainObject,
1164 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1165 {
1166 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1167 SAM_DOMAIN_FIXED_DATA FixedData;
1168 ULONG Length = 0;
1169 NTSTATUS Status;
1170
1171 *Buffer = NULL;
1172
1173 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1174 if (InfoBuffer == NULL)
1175 return STATUS_INSUFFICIENT_RESOURCES;
1176
1177 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1178 Status = SampGetObjectAttribute(DomainObject,
1179 L"F",
1180 NULL,
1181 (PVOID)&FixedData,
1182 &Length);
1183 if (!NT_SUCCESS(Status))
1184 goto done;
1185
1186 InfoBuffer->General2.I1.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
1187 InfoBuffer->General2.I1.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
1188 InfoBuffer->General2.I1.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
1189 InfoBuffer->General2.I1.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
1190 InfoBuffer->General2.I1.DomainServerState = FixedData.DomainServerState;
1191 InfoBuffer->General2.I1.DomainServerRole = FixedData.DomainServerRole;
1192 InfoBuffer->General2.I1.UasCompatibilityRequired = FixedData.UasCompatibilityRequired;
1193
1194 InfoBuffer->General2.LockoutDuration = FixedData.LockoutDuration;
1195 InfoBuffer->General2.LockoutObservationWindow = FixedData.LockoutObservationWindow;
1196 InfoBuffer->General2.LockoutThreshold = FixedData.LockoutThreshold;
1197
1198 /* Get the OemInformation string */
1199 Status = SampGetObjectAttributeString(DomainObject,
1200 L"OemInformation",
1201 &InfoBuffer->General2.I1.OemInformation);
1202 if (!NT_SUCCESS(Status))
1203 {
1204 TRACE("Status 0x%08lx\n", Status);
1205 goto done;
1206 }
1207
1208 /* Get the Name string */
1209 Status = SampGetObjectAttributeString(DomainObject,
1210 L"Name",
1211 &InfoBuffer->General2.I1.DomainName);
1212 if (!NT_SUCCESS(Status))
1213 {
1214 TRACE("Status 0x%08lx\n", Status);
1215 goto done;
1216 }
1217
1218 /* Get the ReplicaSourceNodeName string */
1219 Status = SampGetObjectAttributeString(DomainObject,
1220 L"ReplicaSourceNodeName",
1221 &InfoBuffer->General2.I1.ReplicaSourceNodeName);
1222 if (!NT_SUCCESS(Status))
1223 {
1224 TRACE("Status 0x%08lx\n", Status);
1225 goto done;
1226 }
1227
1228 /* Get the number of Users in the Domain */
1229 Status = SampGetNumberOfAccounts(DomainObject,
1230 L"Users",
1231 &InfoBuffer->General2.I1.UserCount);
1232 if (!NT_SUCCESS(Status))
1233 {
1234 TRACE("Status 0x%08lx\n", Status);
1235 goto done;
1236 }
1237
1238 /* Get the number of Groups in the Domain */
1239 Status = SampGetNumberOfAccounts(DomainObject,
1240 L"Groups",
1241 &InfoBuffer->General2.I1.GroupCount);
1242 if (!NT_SUCCESS(Status))
1243 {
1244 TRACE("Status 0x%08lx\n", Status);
1245 goto done;
1246 }
1247
1248 /* Get the number of Aliases in the Domain */
1249 Status = SampGetNumberOfAccounts(DomainObject,
1250 L"Aliases",
1251 &InfoBuffer->General2.I1.AliasCount);
1252 if (!NT_SUCCESS(Status))
1253 {
1254 TRACE("Status 0x%08lx\n", Status);
1255 goto done;
1256 }
1257
1258 *Buffer = InfoBuffer;
1259
1260 done:
1261 if (!NT_SUCCESS(Status))
1262 {
1263 if (InfoBuffer != NULL)
1264 {
1265 if (InfoBuffer->General2.I1.OemInformation.Buffer != NULL)
1266 midl_user_free(InfoBuffer->General2.I1.OemInformation.Buffer);
1267
1268 if (InfoBuffer->General2.I1.DomainName.Buffer != NULL)
1269 midl_user_free(InfoBuffer->General2.I1.DomainName.Buffer);
1270
1271 if (InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer != NULL)
1272 midl_user_free(InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer);
1273
1274 midl_user_free(InfoBuffer);
1275 }
1276 }
1277
1278 return Status;
1279 }
1280
1281
1282 static NTSTATUS
1283 SampQueryDomainLockout(PSAM_DB_OBJECT DomainObject,
1284 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1285 {
1286 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1287 SAM_DOMAIN_FIXED_DATA FixedData;
1288 ULONG Length = 0;
1289 NTSTATUS Status;
1290
1291 *Buffer = NULL;
1292
1293 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1294 if (InfoBuffer == NULL)
1295 return STATUS_INSUFFICIENT_RESOURCES;
1296
1297 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1298 Status = SampGetObjectAttribute(DomainObject,
1299 L"F",
1300 NULL,
1301 (PVOID)&FixedData,
1302 &Length);
1303 if (!NT_SUCCESS(Status))
1304 goto done;
1305
1306 InfoBuffer->Lockout.LockoutDuration = FixedData.LockoutDuration;
1307 InfoBuffer->Lockout.LockoutObservationWindow = FixedData.LockoutObservationWindow;
1308 InfoBuffer->Lockout.LockoutThreshold = FixedData.LockoutThreshold;
1309
1310 *Buffer = InfoBuffer;
1311
1312 done:
1313 if (!NT_SUCCESS(Status))
1314 {
1315 if (InfoBuffer != NULL)
1316 {
1317 midl_user_free(InfoBuffer);
1318 }
1319 }
1320
1321 return Status;
1322 }
1323
1324
1325 static NTSTATUS
1326 SampQueryDomainModified2(PSAM_DB_OBJECT DomainObject,
1327 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1328 {
1329 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1330 SAM_DOMAIN_FIXED_DATA FixedData;
1331 ULONG Length = 0;
1332 NTSTATUS Status;
1333
1334 *Buffer = NULL;
1335
1336 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1337 if (InfoBuffer == NULL)
1338 return STATUS_INSUFFICIENT_RESOURCES;
1339
1340 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1341 Status = SampGetObjectAttribute(DomainObject,
1342 L"F",
1343 NULL,
1344 (PVOID)&FixedData,
1345 &Length);
1346 if (!NT_SUCCESS(Status))
1347 goto done;
1348
1349 InfoBuffer->Modified2.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
1350 InfoBuffer->Modified2.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
1351 InfoBuffer->Modified2.CreationTime.LowPart = FixedData.CreationTime.LowPart;
1352 InfoBuffer->Modified2.CreationTime.HighPart = FixedData.CreationTime.HighPart;
1353 InfoBuffer->Modified2.ModifiedCountAtLastPromotion.LowPart = FixedData.ModifiedCountAtLastPromotion.LowPart;
1354 InfoBuffer->Modified2.ModifiedCountAtLastPromotion.HighPart = FixedData.ModifiedCountAtLastPromotion.HighPart;
1355
1356 *Buffer = InfoBuffer;
1357
1358 done:
1359 if (!NT_SUCCESS(Status))
1360 {
1361 if (InfoBuffer != NULL)
1362 {
1363 midl_user_free(InfoBuffer);
1364 }
1365 }
1366
1367 return Status;
1368 }
1369
1370
1371 /* Function 8 */
1372 NTSTATUS
1373 NTAPI
1374 SamrQueryInformationDomain(IN SAMPR_HANDLE DomainHandle,
1375 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1376 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1377 {
1378 PSAM_DB_OBJECT DomainObject;
1379 ACCESS_MASK DesiredAccess;
1380 NTSTATUS Status;
1381
1382 TRACE("SamrQueryInformationDomain(%p %lu %p)\n",
1383 DomainHandle, DomainInformationClass, Buffer);
1384
1385 switch (DomainInformationClass)
1386 {
1387 case DomainPasswordInformation:
1388 case DomainLockoutInformation:
1389 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS;
1390 break;
1391
1392 case DomainGeneralInformation:
1393 case DomainLogoffInformation:
1394 case DomainOemInformation:
1395 case DomainNameInformation:
1396 case DomainReplicationInformation:
1397 case DomainServerRoleInformation:
1398 case DomainModifiedInformation:
1399 case DomainStateInformation:
1400 case DomainModifiedInformation2:
1401 DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS;
1402 break;
1403
1404 case DomainGeneralInformation2:
1405 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS |
1406 DOMAIN_READ_OTHER_PARAMETERS;
1407 break;
1408
1409 default:
1410 return STATUS_INVALID_INFO_CLASS;
1411 }
1412
1413 RtlAcquireResourceShared(&SampResource,
1414 TRUE);
1415
1416 /* Validate the server handle */
1417 Status = SampValidateDbObject(DomainHandle,
1418 SamDbDomainObject,
1419 DesiredAccess,
1420 &DomainObject);
1421 if (!NT_SUCCESS(Status))
1422 goto done;
1423
1424 switch (DomainInformationClass)
1425 {
1426 case DomainPasswordInformation:
1427 Status = SampQueryDomainPassword(DomainObject,
1428 Buffer);
1429 break;
1430
1431 case DomainGeneralInformation:
1432 Status = SampQueryDomainGeneral(DomainObject,
1433 Buffer);
1434 break;
1435
1436 case DomainLogoffInformation:
1437 Status = SampQueryDomainLogoff(DomainObject,
1438 Buffer);
1439 break;
1440
1441 case DomainOemInformation:
1442 Status = SampQueryDomainOem(DomainObject,
1443 Buffer);
1444 break;
1445
1446 case DomainNameInformation:
1447 Status = SampQueryDomainName(DomainObject,
1448 Buffer);
1449 break;
1450
1451 case DomainReplicationInformation:
1452 Status = SampQueryDomainReplication(DomainObject,
1453 Buffer);
1454 break;
1455
1456 case DomainServerRoleInformation:
1457 Status = SampQueryDomainServerRole(DomainObject,
1458 Buffer);
1459 break;
1460
1461 case DomainModifiedInformation:
1462 Status = SampQueryDomainModified(DomainObject,
1463 Buffer);
1464 break;
1465
1466 case DomainStateInformation:
1467 Status = SampQueryDomainState(DomainObject,
1468 Buffer);
1469 break;
1470
1471 case DomainGeneralInformation2:
1472 Status = SampQueryDomainGeneral2(DomainObject,
1473 Buffer);
1474 break;
1475
1476 case DomainLockoutInformation:
1477 Status = SampQueryDomainLockout(DomainObject,
1478 Buffer);
1479 break;
1480
1481 case DomainModifiedInformation2:
1482 Status = SampQueryDomainModified2(DomainObject,
1483 Buffer);
1484 break;
1485
1486 default:
1487 Status = STATUS_NOT_IMPLEMENTED;
1488 }
1489
1490 done:
1491 RtlReleaseResource(&SampResource);
1492
1493 return Status;
1494 }
1495
1496
1497 static NTSTATUS
1498 SampSetDomainPassword(PSAM_DB_OBJECT DomainObject,
1499 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1500 {
1501 SAM_DOMAIN_FIXED_DATA FixedData;
1502 ULONG Length = 0;
1503 NTSTATUS Status;
1504
1505 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1506 Status = SampGetObjectAttribute(DomainObject,
1507 L"F",
1508 NULL,
1509 (PVOID)&FixedData,
1510 &Length);
1511 if (!NT_SUCCESS(Status))
1512 goto done;
1513
1514 FixedData.MinPasswordLength = Buffer->Password.MinPasswordLength;
1515 FixedData.PasswordHistoryLength = Buffer->Password.PasswordHistoryLength;
1516 FixedData.PasswordProperties = Buffer->Password.PasswordProperties;
1517 FixedData.MaxPasswordAge.LowPart = Buffer->Password.MaxPasswordAge.LowPart;
1518 FixedData.MaxPasswordAge.HighPart = Buffer->Password.MaxPasswordAge.HighPart;
1519 FixedData.MinPasswordAge.LowPart = Buffer->Password.MinPasswordAge.LowPart;
1520 FixedData.MinPasswordAge.HighPart = Buffer->Password.MinPasswordAge.HighPart;
1521
1522 Status = SampSetObjectAttribute(DomainObject,
1523 L"F",
1524 REG_BINARY,
1525 &FixedData,
1526 Length);
1527
1528 done:
1529 return Status;
1530 }
1531
1532
1533 static NTSTATUS
1534 SampSetDomainLogoff(PSAM_DB_OBJECT DomainObject,
1535 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1536 {
1537 SAM_DOMAIN_FIXED_DATA FixedData;
1538 ULONG Length = 0;
1539 NTSTATUS Status;
1540
1541 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1542 Status = SampGetObjectAttribute(DomainObject,
1543 L"F",
1544 NULL,
1545 (PVOID)&FixedData,
1546 &Length);
1547 if (!NT_SUCCESS(Status))
1548 goto done;
1549
1550 FixedData.ForceLogoff.LowPart = Buffer->Logoff.ForceLogoff.LowPart;
1551 FixedData.ForceLogoff.HighPart = Buffer->Logoff.ForceLogoff.HighPart;
1552
1553 Status = SampSetObjectAttribute(DomainObject,
1554 L"F",
1555 REG_BINARY,
1556 &FixedData,
1557 Length);
1558
1559 done:
1560 return Status;
1561 }
1562
1563
1564 static NTSTATUS
1565 SampSetDomainServerRole(PSAM_DB_OBJECT DomainObject,
1566 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1567 {
1568 SAM_DOMAIN_FIXED_DATA FixedData;
1569 ULONG Length = 0;
1570 NTSTATUS Status;
1571
1572 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1573 Status = SampGetObjectAttribute(DomainObject,
1574 L"F",
1575 NULL,
1576 (PVOID)&FixedData,
1577 &Length);
1578 if (!NT_SUCCESS(Status))
1579 goto done;
1580
1581 FixedData.DomainServerRole = Buffer->Role.DomainServerRole;
1582
1583 Status = SampSetObjectAttribute(DomainObject,
1584 L"F",
1585 REG_BINARY,
1586 &FixedData,
1587 Length);
1588
1589 done:
1590 return Status;
1591 }
1592
1593
1594 static NTSTATUS
1595 SampSetDomainState(PSAM_DB_OBJECT DomainObject,
1596 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1597 {
1598 SAM_DOMAIN_FIXED_DATA FixedData;
1599 ULONG Length = 0;
1600 NTSTATUS Status;
1601
1602 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1603 Status = SampGetObjectAttribute(DomainObject,
1604 L"F",
1605 NULL,
1606 (PVOID)&FixedData,
1607 &Length);
1608 if (!NT_SUCCESS(Status))
1609 goto done;
1610
1611 FixedData.DomainServerState = Buffer->State.DomainServerState;
1612
1613 Status = SampSetObjectAttribute(DomainObject,
1614 L"F",
1615 REG_BINARY,
1616 &FixedData,
1617 Length);
1618
1619 done:
1620 return Status;
1621 }
1622
1623
1624 static NTSTATUS
1625 SampSetDomainLockout(PSAM_DB_OBJECT DomainObject,
1626 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1627 {
1628 SAM_DOMAIN_FIXED_DATA FixedData;
1629 ULONG Length = 0;
1630 NTSTATUS Status;
1631
1632 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1633 Status = SampGetObjectAttribute(DomainObject,
1634 L"F",
1635 NULL,
1636 (PVOID)&FixedData,
1637 &Length);
1638 if (!NT_SUCCESS(Status))
1639 goto done;
1640
1641 FixedData.LockoutDuration = Buffer->Lockout.LockoutDuration;
1642 FixedData.LockoutObservationWindow = Buffer->Lockout.LockoutObservationWindow;
1643 FixedData.LockoutThreshold = Buffer->Lockout.LockoutThreshold;
1644
1645 Status = SampSetObjectAttribute(DomainObject,
1646 L"F",
1647 REG_BINARY,
1648 &FixedData,
1649 Length);
1650
1651 done:
1652 return Status;
1653 }
1654
1655
1656 /* Function 9 */
1657 NTSTATUS
1658 NTAPI
1659 SamrSetInformationDomain(IN SAMPR_HANDLE DomainHandle,
1660 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1661 IN PSAMPR_DOMAIN_INFO_BUFFER DomainInformation)
1662 {
1663 PSAM_DB_OBJECT DomainObject;
1664 ACCESS_MASK DesiredAccess;
1665 NTSTATUS Status;
1666
1667 TRACE("SamrSetInformationDomain(%p %lu %p)\n",
1668 DomainHandle, DomainInformationClass, DomainInformation);
1669
1670 switch (DomainInformationClass)
1671 {
1672 case DomainPasswordInformation:
1673 case DomainLockoutInformation:
1674 DesiredAccess = DOMAIN_WRITE_PASSWORD_PARAMS;
1675 break;
1676
1677 case DomainLogoffInformation:
1678 case DomainOemInformation:
1679 case DomainNameInformation:
1680 DesiredAccess = DOMAIN_WRITE_OTHER_PARAMETERS;
1681 break;
1682
1683 case DomainReplicationInformation:
1684 case DomainServerRoleInformation:
1685 case DomainStateInformation:
1686 DesiredAccess = DOMAIN_ADMINISTER_SERVER;
1687 break;
1688
1689 default:
1690 return STATUS_INVALID_INFO_CLASS;
1691 }
1692
1693 RtlAcquireResourceExclusive(&SampResource,
1694 TRUE);
1695
1696 /* Validate the server handle */
1697 Status = SampValidateDbObject(DomainHandle,
1698 SamDbDomainObject,
1699 DesiredAccess,
1700 &DomainObject);
1701 if (!NT_SUCCESS(Status))
1702 goto done;
1703
1704 switch (DomainInformationClass)
1705 {
1706 case DomainPasswordInformation:
1707 Status = SampSetDomainPassword(DomainObject,
1708 DomainInformation);
1709 break;
1710
1711 case DomainLogoffInformation:
1712 Status = SampSetDomainLogoff(DomainObject,
1713 DomainInformation);
1714 break;
1715
1716 case DomainOemInformation:
1717 Status = SampSetObjectAttributeString(DomainObject,
1718 L"OemInformation",
1719 &DomainInformation->Oem.OemInformation);
1720 break;
1721
1722 case DomainNameInformation:
1723 Status = SampSetObjectAttributeString(DomainObject,
1724 L"Name",
1725 &DomainInformation->Name.DomainName);
1726 break;
1727
1728 case DomainReplicationInformation:
1729 Status = SampSetObjectAttributeString(DomainObject,
1730 L"ReplicaSourceNodeName",
1731 &DomainInformation->Replication.ReplicaSourceNodeName);
1732 break;
1733
1734 case DomainServerRoleInformation:
1735 Status = SampSetDomainServerRole(DomainObject,
1736 DomainInformation);
1737 break;
1738
1739 case DomainStateInformation:
1740 Status = SampSetDomainState(DomainObject,
1741 DomainInformation);
1742 break;
1743
1744 case DomainLockoutInformation:
1745 Status = SampSetDomainLockout(DomainObject,
1746 DomainInformation);
1747 break;
1748
1749 default:
1750 Status = STATUS_NOT_IMPLEMENTED;
1751 }
1752
1753 done:
1754 RtlReleaseResource(&SampResource);
1755
1756 return Status;
1757 }
1758
1759
1760 /* Function 10 */
1761 NTSTATUS
1762 NTAPI
1763 SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
1764 IN PRPC_UNICODE_STRING Name,
1765 IN ACCESS_MASK DesiredAccess,
1766 OUT SAMPR_HANDLE *GroupHandle,
1767 OUT unsigned long *RelativeId)
1768 {
1769 SAM_DOMAIN_FIXED_DATA FixedDomainData;
1770 SAM_GROUP_FIXED_DATA FixedGroupData;
1771 PSAM_DB_OBJECT DomainObject;
1772 PSAM_DB_OBJECT GroupObject;
1773 PSECURITY_DESCRIPTOR Sd = NULL;
1774 ULONG SdSize = 0;
1775 ULONG ulSize;
1776 ULONG ulRid;
1777 WCHAR szRid[9];
1778 NTSTATUS Status;
1779
1780 TRACE("SamrCreateGroupInDomain(%p %p %lx %p %p)\n",
1781 DomainHandle, Name, DesiredAccess, GroupHandle, RelativeId);
1782
1783 /* Map generic access rights */
1784 RtlMapGenericMask(&DesiredAccess,
1785 &GroupMapping);
1786
1787 RtlAcquireResourceExclusive(&SampResource,
1788 TRUE);
1789
1790 /* Validate the domain handle */
1791 Status = SampValidateDbObject(DomainHandle,
1792 SamDbDomainObject,
1793 DOMAIN_CREATE_GROUP,
1794 &DomainObject);
1795 if (!NT_SUCCESS(Status))
1796 {
1797 TRACE("failed with status 0x%08lx\n", Status);
1798 goto done;
1799 }
1800
1801 /* Check the group account name */
1802 Status = SampCheckAccountName(Name, 256);
1803 if (!NT_SUCCESS(Status))
1804 {
1805 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
1806 goto done;
1807 }
1808
1809 /* Check if the group name already exists in the domain */
1810 Status = SampCheckAccountNameInDomain(DomainObject,
1811 Name->Buffer);
1812 if (!NT_SUCCESS(Status))
1813 {
1814 TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n",
1815 Name->Buffer, Status);
1816 goto done;
1817 }
1818
1819 /* Create the security descriptor */
1820 Status = SampCreateGroupSD(&Sd,
1821 &SdSize);
1822 if (!NT_SUCCESS(Status))
1823 {
1824 TRACE("SampCreateGroupSD failed (Status 0x%08lx)\n", Status);
1825 goto done;
1826 }
1827
1828 /* Get the fixed domain attributes */
1829 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
1830 Status = SampGetObjectAttribute(DomainObject,
1831 L"F",
1832 NULL,
1833 (PVOID)&FixedDomainData,
1834 &ulSize);
1835 if (!NT_SUCCESS(Status))
1836 {
1837 TRACE("failed with status 0x%08lx\n", Status);
1838 goto done;
1839 }
1840
1841 /* Increment the NextRid attribute */
1842 ulRid = FixedDomainData.NextRid;
1843 FixedDomainData.NextRid++;
1844
1845 /* Store the fixed domain attributes */
1846 Status = SampSetObjectAttribute(DomainObject,
1847 L"F",
1848 REG_BINARY,
1849 &FixedDomainData,
1850 ulSize);
1851 if (!NT_SUCCESS(Status))
1852 {
1853 TRACE("failed with status 0x%08lx\n", Status);
1854 goto done;
1855 }
1856
1857 TRACE("RID: %lx\n", ulRid);
1858
1859 /* Convert the RID into a string (hex) */
1860 swprintf(szRid, L"%08lX", ulRid);
1861
1862 /* Create the group object */
1863 Status = SampCreateDbObject(DomainObject,
1864 L"Groups",
1865 szRid,
1866 ulRid,
1867 SamDbGroupObject,
1868 DesiredAccess,
1869 &GroupObject);
1870 if (!NT_SUCCESS(Status))
1871 {
1872 TRACE("failed with status 0x%08lx\n", Status);
1873 goto done;
1874 }
1875
1876 /* Add the account name of the user object */
1877 Status = SampSetAccountNameInDomain(DomainObject,
1878 L"Groups",
1879 Name->Buffer,
1880 ulRid);
1881 if (!NT_SUCCESS(Status))
1882 {
1883 TRACE("failed with status 0x%08lx\n", Status);
1884 goto done;
1885 }
1886
1887 /* Initialize fixed user data */
1888 memset(&FixedGroupData, 0, sizeof(SAM_GROUP_FIXED_DATA));
1889 FixedGroupData.Version = 1;
1890 FixedGroupData.GroupId = ulRid;
1891
1892 /* Set fixed user data attribute */
1893 Status = SampSetObjectAttribute(GroupObject,
1894 L"F",
1895 REG_BINARY,
1896 (LPVOID)&FixedGroupData,
1897 sizeof(SAM_GROUP_FIXED_DATA));
1898 if (!NT_SUCCESS(Status))
1899 {
1900 TRACE("failed with status 0x%08lx\n", Status);
1901 goto done;
1902 }
1903
1904 /* Set the Name attribute */
1905 Status = SampSetObjectAttributeString(GroupObject,
1906 L"Name",
1907 Name);
1908 if (!NT_SUCCESS(Status))
1909 {
1910 TRACE("failed with status 0x%08lx\n", Status);
1911 goto done;
1912 }
1913
1914 /* Set the AdminComment attribute */
1915 Status = SampSetObjectAttributeString(GroupObject,
1916 L"AdminComment",
1917 NULL);
1918 if (!NT_SUCCESS(Status))
1919 {
1920 TRACE("failed with status 0x%08lx\n", Status);
1921 goto done;
1922 }
1923
1924 /* Set the SecDesc attribute*/
1925 Status = SampSetObjectAttribute(GroupObject,
1926 L"SecDesc",
1927 REG_BINARY,
1928 Sd,
1929 SdSize);
1930 if (!NT_SUCCESS(Status))
1931 {
1932 TRACE("failed with status 0x%08lx\n", Status);
1933 goto done;
1934 }
1935
1936 if (NT_SUCCESS(Status))
1937 {
1938 *GroupHandle = (SAMPR_HANDLE)GroupObject;
1939 *RelativeId = ulRid;
1940 }
1941
1942 done:
1943 if (Sd != NULL)
1944 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
1945
1946 RtlReleaseResource(&SampResource);
1947
1948 TRACE("returns with status 0x%08lx\n", Status);
1949
1950 return Status;
1951 }
1952
1953
1954 /* Function 11 */
1955 NTSTATUS
1956 NTAPI
1957 SamrEnumerateGroupsInDomain(IN SAMPR_HANDLE DomainHandle,
1958 IN OUT unsigned long *EnumerationContext,
1959 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
1960 IN unsigned long PreferedMaximumLength,
1961 OUT unsigned long *CountReturned)
1962 {
1963 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
1964 PSAM_DB_OBJECT DomainObject;
1965 HANDLE GroupsKeyHandle = NULL;
1966 HANDLE NamesKeyHandle = NULL;
1967 WCHAR GroupName[64];
1968 ULONG EnumIndex;
1969 ULONG EnumCount = 0;
1970 ULONG RequiredLength = 0;
1971 ULONG NameLength;
1972 ULONG DataLength;
1973 ULONG Rid;
1974 ULONG i;
1975 BOOLEAN MoreEntries = FALSE;
1976 NTSTATUS Status;
1977
1978 TRACE("SamrEnumerateUsersInDomain(%p %p %p %lu %p)\n",
1979 DomainHandle, EnumerationContext, Buffer,
1980 PreferedMaximumLength, CountReturned);
1981
1982 RtlAcquireResourceShared(&SampResource,
1983 TRUE);
1984
1985 /* Validate the domain handle */
1986 Status = SampValidateDbObject(DomainHandle,
1987 SamDbDomainObject,
1988 DOMAIN_LIST_ACCOUNTS,
1989 &DomainObject);
1990 if (!NT_SUCCESS(Status))
1991 goto done;
1992
1993 Status = SampRegOpenKey(DomainObject->KeyHandle,
1994 L"Groups",
1995 KEY_READ,
1996 &GroupsKeyHandle);
1997 if (!NT_SUCCESS(Status))
1998 goto done;
1999
2000 Status = SampRegOpenKey(GroupsKeyHandle,
2001 L"Names",
2002 KEY_READ,
2003 &NamesKeyHandle);
2004 if (!NT_SUCCESS(Status))
2005 goto done;
2006
2007 TRACE("Part 1\n");
2008
2009 EnumIndex = *EnumerationContext;
2010
2011 while (TRUE)
2012 {
2013 NameLength = 64 * sizeof(WCHAR);
2014 Status = SampRegEnumerateValue(NamesKeyHandle,
2015 EnumIndex,
2016 GroupName,
2017 &NameLength,
2018 NULL,
2019 NULL,
2020 NULL);
2021 if (!NT_SUCCESS(Status))
2022 {
2023 if (Status == STATUS_NO_MORE_ENTRIES)
2024 Status = STATUS_SUCCESS;
2025 break;
2026 }
2027
2028 TRACE("EnumIndex: %lu\n", EnumIndex);
2029 TRACE("Group name: %S\n", GroupName);
2030 TRACE("Name length: %lu\n", NameLength);
2031
2032 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
2033 {
2034 MoreEntries = TRUE;
2035 break;
2036 }
2037
2038 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
2039 EnumCount++;
2040
2041 EnumIndex++;
2042 }
2043
2044 TRACE("EnumCount: %lu\n", EnumCount);
2045 TRACE("RequiredLength: %lu\n", RequiredLength);
2046
2047 if (!NT_SUCCESS(Status))
2048 goto done;
2049
2050 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
2051 if (EnumBuffer == NULL)
2052 {
2053 Status = STATUS_INSUFFICIENT_RESOURCES;
2054 goto done;
2055 }
2056
2057 EnumBuffer->EntriesRead = EnumCount;
2058 if (EnumCount == 0)
2059 goto done;
2060
2061 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
2062 if (EnumBuffer->Buffer == NULL)
2063 {
2064 Status = STATUS_INSUFFICIENT_RESOURCES;
2065 goto done;
2066 }
2067
2068 TRACE("Part 2\n");
2069
2070 EnumIndex = *EnumerationContext;
2071 for (i = 0; i < EnumCount; i++, EnumIndex++)
2072 {
2073 NameLength = 64 * sizeof(WCHAR);
2074 DataLength = sizeof(ULONG);
2075 Status = SampRegEnumerateValue(NamesKeyHandle,
2076 EnumIndex,
2077 GroupName,
2078 &NameLength,
2079 NULL,
2080 &Rid,
2081 &DataLength);
2082 if (!NT_SUCCESS(Status))
2083 {
2084 if (Status == STATUS_NO_MORE_ENTRIES)
2085 Status = STATUS_SUCCESS;
2086 break;
2087 }
2088
2089 TRACE("EnumIndex: %lu\n", EnumIndex);
2090 TRACE("Group name: %S\n", GroupName);
2091 TRACE("Name length: %lu\n", NameLength);
2092 TRACE("RID: %lu\n", Rid);
2093
2094 EnumBuffer->Buffer[i].RelativeId = Rid;
2095
2096 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
2097 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(DataLength + sizeof(UNICODE_NULL));
2098
2099 /* FIXME: Disabled because of bugs in widl and rpcrt4 */
2100 #if 0
2101 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
2102 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
2103 {
2104 Status = STATUS_INSUFFICIENT_RESOURCES;
2105 goto done;
2106 }
2107
2108 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
2109 GroupName,
2110 EnumBuffer->Buffer[i].Name.Length);
2111 #endif
2112 }
2113
2114 done:
2115 if (NT_SUCCESS(Status))
2116 {
2117 *EnumerationContext += EnumCount;
2118 *Buffer = EnumBuffer;
2119 *CountReturned = EnumCount;
2120 }
2121 else
2122 {
2123 *EnumerationContext = 0;
2124 *Buffer = NULL;
2125 *CountReturned = 0;
2126
2127 if (EnumBuffer != NULL)
2128 {
2129 if (EnumBuffer->Buffer != NULL)
2130 {
2131 if (EnumBuffer->EntriesRead != 0)
2132 {
2133 for (i = 0; i < EnumBuffer->EntriesRead; i++)
2134 {
2135 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
2136 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
2137 }
2138 }
2139
2140 midl_user_free(EnumBuffer->Buffer);
2141 }
2142
2143 midl_user_free(EnumBuffer);
2144 }
2145 }
2146
2147 SampRegCloseKey(&NamesKeyHandle);
2148 SampRegCloseKey(&GroupsKeyHandle);
2149
2150 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
2151 Status = STATUS_MORE_ENTRIES;
2152
2153 RtlReleaseResource(&SampResource);
2154
2155 return Status;
2156 }
2157
2158
2159 /* Function 12 */
2160 NTSTATUS
2161 NTAPI
2162 SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
2163 IN PRPC_UNICODE_STRING Name,
2164 IN ACCESS_MASK DesiredAccess,
2165 OUT SAMPR_HANDLE *UserHandle,
2166 OUT unsigned long *RelativeId)
2167 {
2168 SAM_DOMAIN_FIXED_DATA FixedDomainData;
2169 SAM_USER_FIXED_DATA FixedUserData;
2170 PSAM_DB_OBJECT DomainObject;
2171 PSAM_DB_OBJECT UserObject;
2172 GROUP_MEMBERSHIP GroupMembership;
2173 UCHAR LogonHours[23];
2174 ULONG ulSize;
2175 ULONG ulRid;
2176 WCHAR szRid[9];
2177 PSECURITY_DESCRIPTOR Sd = NULL;
2178 ULONG SdSize = 0;
2179 PSID UserSid = NULL;
2180 NTSTATUS Status;
2181
2182 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
2183 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
2184
2185 if (Name == NULL ||
2186 Name->Length == 0 ||
2187 Name->Buffer == NULL ||
2188 UserHandle == NULL ||
2189 RelativeId == NULL)
2190 return STATUS_INVALID_PARAMETER;
2191
2192 /* Map generic access rights */
2193 RtlMapGenericMask(&DesiredAccess,
2194 &UserMapping);
2195
2196 RtlAcquireResourceExclusive(&SampResource,
2197 TRUE);
2198
2199 /* Validate the domain handle */
2200 Status = SampValidateDbObject(DomainHandle,
2201 SamDbDomainObject,
2202 DOMAIN_CREATE_USER,
2203 &DomainObject);
2204 if (!NT_SUCCESS(Status))
2205 {
2206 TRACE("failed with status 0x%08lx\n", Status);
2207 goto done;
2208 }
2209
2210 /* Check the user account name */
2211 Status = SampCheckAccountName(Name, 20);
2212 if (!NT_SUCCESS(Status))
2213 {
2214 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
2215 goto done;
2216 }
2217
2218 /* Check if the user name already exists in the domain */
2219 Status = SampCheckAccountNameInDomain(DomainObject,
2220 Name->Buffer);
2221 if (!NT_SUCCESS(Status))
2222 {
2223 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
2224 Name->Buffer, Status);
2225 goto done;
2226 }
2227
2228 /* Get the fixed domain attributes */
2229 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
2230 Status = SampGetObjectAttribute(DomainObject,
2231 L"F",
2232 NULL,
2233 (PVOID)&FixedDomainData,
2234 &ulSize);
2235 if (!NT_SUCCESS(Status))
2236 {
2237 TRACE("failed with status 0x%08lx\n", Status);
2238 goto done;
2239 }
2240
2241 /* Increment the NextRid attribute */
2242 ulRid = FixedDomainData.NextRid;
2243 FixedDomainData.NextRid++;
2244
2245 TRACE("RID: %lx\n", ulRid);
2246
2247 /* Create the user SID */
2248 Status = SampCreateAccountSid(DomainObject,
2249 ulRid,
2250 &UserSid);
2251 if (!NT_SUCCESS(Status))
2252 {
2253 TRACE("SampCreateAccountSid failed (Status 0x%08lx)\n", Status);
2254 goto done;
2255 }
2256
2257 /* Create the security descriptor */
2258 Status = SampCreateUserSD(UserSid,
2259 &Sd,
2260 &SdSize);
2261 if (!NT_SUCCESS(Status))
2262 {
2263 TRACE("SampCreateUserSD failed (Status 0x%08lx)\n", Status);
2264 goto done;
2265 }
2266
2267 /* Store the fixed domain attributes */
2268 Status = SampSetObjectAttribute(DomainObject,
2269 L"F",
2270 REG_BINARY,
2271 &FixedDomainData,
2272 ulSize);
2273 if (!NT_SUCCESS(Status))
2274 {
2275 TRACE("failed with status 0x%08lx\n", Status);
2276 goto done;
2277 }
2278
2279 /* Convert the RID into a string (hex) */
2280 swprintf(szRid, L"%08lX", ulRid);
2281
2282 /* Create the user object */
2283 Status = SampCreateDbObject(DomainObject,
2284 L"Users",
2285 szRid,
2286 ulRid,
2287 SamDbUserObject,
2288 DesiredAccess,
2289 &UserObject);
2290 if (!NT_SUCCESS(Status))
2291 {
2292 TRACE("failed with status 0x%08lx\n", Status);
2293 goto done;
2294 }
2295
2296 /* Add the account name for the user object */
2297 Status = SampSetAccountNameInDomain(DomainObject,
2298 L"Users",
2299 Name->Buffer,
2300 ulRid);
2301 if (!NT_SUCCESS(Status))
2302 {
2303 TRACE("failed with status 0x%08lx\n", Status);
2304 goto done;
2305 }
2306
2307 /* Initialize fixed user data */
2308 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
2309 FixedUserData.Version = 1;
2310 FixedUserData.Reserved = 0;
2311 FixedUserData.LastLogon.QuadPart = 0;
2312 FixedUserData.LastLogoff.QuadPart = 0;
2313 FixedUserData.PasswordLastSet.QuadPart = 0;
2314 FixedUserData.AccountExpires.LowPart = MAXULONG;
2315 FixedUserData.AccountExpires.HighPart = MAXLONG;
2316 FixedUserData.LastBadPasswordTime.QuadPart = 0;
2317 FixedUserData.UserId = ulRid;
2318 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
2319 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
2320 USER_PASSWORD_NOT_REQUIRED |
2321 USER_NORMAL_ACCOUNT;
2322 FixedUserData.CountryCode = 0;
2323 FixedUserData.CodePage = 0;
2324 FixedUserData.BadPasswordCount = 0;
2325 FixedUserData.LogonCount = 0;
2326 FixedUserData.AdminCount = 0;
2327 FixedUserData.OperatorCount = 0;
2328
2329 /* Set fixed user data attribute */
2330 Status = SampSetObjectAttribute(UserObject,
2331 L"F",
2332 REG_BINARY,
2333 (LPVOID)&FixedUserData,
2334 sizeof(SAM_USER_FIXED_DATA));
2335 if (!NT_SUCCESS(Status))
2336 {
2337 TRACE("failed with status 0x%08lx\n", Status);
2338 goto done;
2339 }
2340
2341 /* Set the Name attribute */
2342 Status = SampSetObjectAttributeString(UserObject,
2343 L"Name",
2344 Name);
2345 if (!NT_SUCCESS(Status))
2346 {
2347 TRACE("failed with status 0x%08lx\n", Status);
2348 goto done;
2349 }
2350
2351 /* Set the FullName attribute */
2352 Status = SampSetObjectAttributeString(UserObject,
2353 L"FullName",
2354 NULL);
2355 if (!NT_SUCCESS(Status))
2356 {
2357 TRACE("failed with status 0x%08lx\n", Status);
2358 goto done;
2359 }
2360
2361 /* Set the HomeDirectory attribute */
2362 Status = SampSetObjectAttributeString(UserObject,
2363 L"HomeDirectory",
2364 NULL);
2365 if (!NT_SUCCESS(Status))
2366 {
2367 TRACE("failed with status 0x%08lx\n", Status);
2368 goto done;
2369 }
2370
2371 /* Set the HomeDirectoryDrive attribute */
2372 Status = SampSetObjectAttributeString(UserObject,
2373 L"HomeDirectoryDrive",
2374 NULL);
2375 if (!NT_SUCCESS(Status))
2376 {
2377 TRACE("failed with status 0x%08lx\n", Status);
2378 goto done;
2379 }
2380
2381 /* Set the ScriptPath attribute */
2382 Status = SampSetObjectAttributeString(UserObject,
2383 L"ScriptPath",
2384 NULL);
2385 if (!NT_SUCCESS(Status))
2386 {
2387 TRACE("failed with status 0x%08lx\n", Status);
2388 goto done;
2389 }
2390
2391 /* Set the ProfilePath attribute */
2392 Status = SampSetObjectAttributeString(UserObject,
2393 L"ProfilePath",
2394 NULL);
2395 if (!NT_SUCCESS(Status))
2396 {
2397 TRACE("failed with status 0x%08lx\n", Status);
2398 goto done;
2399 }
2400
2401 /* Set the AdminComment attribute */
2402 Status = SampSetObjectAttributeString(UserObject,
2403 L"AdminComment",
2404 NULL);
2405 if (!NT_SUCCESS(Status))
2406 {
2407 TRACE("failed with status 0x%08lx\n", Status);
2408 goto done;
2409 }
2410
2411 /* Set the UserComment attribute */
2412 Status = SampSetObjectAttributeString(UserObject,
2413 L"UserComment",
2414 NULL);
2415 if (!NT_SUCCESS(Status))
2416 {
2417 TRACE("failed with status 0x%08lx\n", Status);
2418 goto done;
2419 }
2420
2421 /* Set the WorkStations attribute */
2422 Status = SampSetObjectAttributeString(UserObject,
2423 L"WorkStations",
2424 NULL);
2425 if (!NT_SUCCESS(Status))
2426 {
2427 TRACE("failed with status 0x%08lx\n", Status);
2428 goto done;
2429 }
2430
2431 /* Set the Parameters attribute */
2432 Status = SampSetObjectAttributeString(UserObject,
2433 L"Parameters",
2434 NULL);
2435 if (!NT_SUCCESS(Status))
2436 {
2437 TRACE("failed with status 0x%08lx\n", Status);
2438 goto done;
2439 }
2440
2441 /* Set LogonHours attribute*/
2442 *((PUSHORT)LogonHours) = 168;
2443 memset(&(LogonHours[2]), 0xff, 21);
2444
2445 Status = SampSetObjectAttribute(UserObject,
2446 L"LogonHours",
2447 REG_BINARY,
2448 &LogonHours,
2449 sizeof(LogonHours));
2450 if (!NT_SUCCESS(Status))
2451 {
2452 TRACE("failed with status 0x%08lx\n", Status);
2453 goto done;
2454 }
2455
2456 /* Set Groups attribute*/
2457 GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS;
2458 GroupMembership.Attributes = SE_GROUP_MANDATORY |
2459 SE_GROUP_ENABLED |
2460 SE_GROUP_ENABLED_BY_DEFAULT;
2461
2462 Status = SampSetObjectAttribute(UserObject,
2463 L"Groups",
2464 REG_BINARY,
2465 &GroupMembership,
2466 sizeof(GROUP_MEMBERSHIP));
2467 if (!NT_SUCCESS(Status))
2468 {
2469 TRACE("failed with status 0x%08lx\n", Status);
2470 goto done;
2471 }
2472
2473 /* Set LMPwd attribute*/
2474 Status = SampSetObjectAttribute(UserObject,
2475 L"LMPwd",
2476 REG_BINARY,
2477 &EmptyLmHash,
2478 sizeof(ENCRYPTED_LM_OWF_PASSWORD));
2479 if (!NT_SUCCESS(Status))
2480 {
2481 TRACE("failed with status 0x%08lx\n", Status);
2482 goto done;
2483 }
2484
2485 /* Set NTPwd attribute*/
2486 Status = SampSetObjectAttribute(UserObject,
2487 L"NTPwd",
2488 REG_BINARY,
2489 &EmptyNtHash,
2490 sizeof(ENCRYPTED_NT_OWF_PASSWORD));
2491 if (!NT_SUCCESS(Status))
2492 {
2493 TRACE("failed with status 0x%08lx\n", Status);
2494 goto done;
2495 }
2496
2497 /* Set LMPwdHistory attribute*/
2498 Status = SampSetObjectAttribute(UserObject,
2499 L"LMPwdHistory",
2500 REG_BINARY,
2501 NULL,
2502 0);
2503 if (!NT_SUCCESS(Status))
2504 {
2505 TRACE("failed with status 0x%08lx\n", Status);
2506 goto done;
2507 }
2508
2509 /* Set NTPwdHistory attribute*/
2510 Status = SampSetObjectAttribute(UserObject,
2511 L"NTPwdHistory",
2512 REG_BINARY,
2513 NULL,
2514 0);
2515 if (!NT_SUCCESS(Status))
2516 {
2517 TRACE("failed with status 0x%08lx\n", Status);
2518 goto done;
2519 }
2520
2521 /* Set the PrivateData attribute */
2522 Status = SampSetObjectAttributeString(UserObject,
2523 L"PrivateData",
2524 NULL);
2525 if (!NT_SUCCESS(Status))
2526 {
2527 TRACE("failed with status 0x%08lx\n", Status);
2528 goto done;
2529 }
2530
2531 /* Set the SecDesc attribute*/
2532 Status = SampSetObjectAttribute(UserObject,
2533 L"SecDesc",
2534 REG_BINARY,
2535 Sd,
2536 SdSize);
2537 if (!NT_SUCCESS(Status))
2538 {
2539 TRACE("failed with status 0x%08lx\n", Status);
2540 goto done;
2541 }
2542
2543 if (NT_SUCCESS(Status))
2544 {
2545 *UserHandle = (SAMPR_HANDLE)UserObject;
2546 *RelativeId = ulRid;
2547 }
2548
2549 done:
2550 if (Sd != NULL)
2551 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
2552
2553 if (UserSid != NULL)
2554 RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid);
2555
2556 RtlReleaseResource(&SampResource);
2557
2558 TRACE("returns with status 0x%08lx\n", Status);
2559
2560 return Status;
2561 }
2562
2563
2564 /* Function 13 */
2565 NTSTATUS
2566 NTAPI
2567 SamrEnumerateUsersInDomain(IN SAMPR_HANDLE DomainHandle,
2568 IN OUT unsigned long *EnumerationContext,
2569 IN unsigned long UserAccountControl,
2570 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
2571 IN unsigned long PreferedMaximumLength,
2572 OUT unsigned long *CountReturned)
2573 {
2574 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
2575 PSAM_DB_OBJECT DomainObject;
2576 HANDLE UsersKeyHandle = NULL;
2577 HANDLE NamesKeyHandle = NULL;
2578 WCHAR UserName[64];
2579 ULONG EnumIndex;
2580 ULONG EnumCount = 0;
2581 ULONG RequiredLength = 0;
2582 ULONG NameLength;
2583 ULONG DataLength;
2584 ULONG Rid;
2585 ULONG i;
2586 BOOLEAN MoreEntries = FALSE;
2587 NTSTATUS Status;
2588
2589 TRACE("SamrEnumerateUsersInDomain(%p %p %lx %p %lu %p)\n",
2590 DomainHandle, EnumerationContext, UserAccountControl, Buffer,
2591 PreferedMaximumLength, CountReturned);
2592
2593 RtlAcquireResourceShared(&SampResource,
2594 TRUE);
2595
2596 /* Validate the domain handle */
2597 Status = SampValidateDbObject(DomainHandle,
2598 SamDbDomainObject,
2599 DOMAIN_LIST_ACCOUNTS,
2600 &DomainObject);
2601 if (!NT_SUCCESS(Status))
2602 goto done;
2603
2604 Status = SampRegOpenKey(DomainObject->KeyHandle,
2605 L"Users",
2606 KEY_READ,
2607 &UsersKeyHandle);
2608 if (!NT_SUCCESS(Status))
2609 goto done;
2610
2611 Status = SampRegOpenKey(UsersKeyHandle,
2612 L"Names",
2613 KEY_READ,
2614 &NamesKeyHandle);
2615 if (!NT_SUCCESS(Status))
2616 goto done;
2617
2618 TRACE("Part 1\n");
2619
2620 EnumIndex = *EnumerationContext;
2621
2622 while (TRUE)
2623 {
2624 NameLength = 64 * sizeof(WCHAR);
2625 Status = SampRegEnumerateValue(NamesKeyHandle,
2626 EnumIndex,
2627 UserName,
2628 &NameLength,
2629 NULL,
2630 NULL,
2631 NULL);
2632 if (!NT_SUCCESS(Status))
2633 {
2634 if (Status == STATUS_NO_MORE_ENTRIES)
2635 Status = STATUS_SUCCESS;
2636 break;
2637 }
2638
2639 TRACE("EnumIndex: %lu\n", EnumIndex);
2640 TRACE("User name: %S\n", UserName);
2641 TRACE("Name length: %lu\n", NameLength);
2642
2643 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
2644 {
2645 MoreEntries = TRUE;
2646 break;
2647 }
2648
2649 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
2650 EnumCount++;
2651
2652 EnumIndex++;
2653 }
2654
2655 TRACE("EnumCount: %lu\n", EnumCount);
2656 TRACE("RequiredLength: %lu\n", RequiredLength);
2657
2658 if (!NT_SUCCESS(Status))
2659 goto done;
2660
2661 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
2662 if (EnumBuffer == NULL)
2663 {
2664 Status = STATUS_INSUFFICIENT_RESOURCES;
2665 goto done;
2666 }
2667
2668 EnumBuffer->EntriesRead = EnumCount;
2669 if (EnumCount == 0)
2670 goto done;
2671
2672 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
2673 if (EnumBuffer->Buffer == NULL)
2674 {
2675 Status = STATUS_INSUFFICIENT_RESOURCES;
2676 goto done;
2677 }
2678
2679 TRACE("Part 2\n");
2680
2681 EnumIndex = *EnumerationContext;
2682 for (i = 0; i < EnumCount; i++, EnumIndex++)
2683 {
2684 NameLength = 64 * sizeof(WCHAR);
2685 DataLength = sizeof(ULONG);
2686 Status = SampRegEnumerateValue(NamesKeyHandle,
2687 EnumIndex,
2688 UserName,
2689 &NameLength,
2690 NULL,
2691 &Rid,
2692 &DataLength);
2693 if (!NT_SUCCESS(Status))
2694 {
2695 if (Status == STATUS_NO_MORE_ENTRIES)
2696 Status = STATUS_SUCCESS;
2697 break;
2698 }
2699
2700 TRACE("EnumIndex: %lu\n", EnumIndex);
2701 TRACE("User name: %S\n", UserName);
2702 TRACE("Name length: %lu\n", NameLength);
2703 TRACE("RID: %lu\n", Rid);
2704
2705 EnumBuffer->Buffer[i].RelativeId = Rid;
2706
2707 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
2708 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(DataLength + sizeof(UNICODE_NULL));
2709
2710 /* FIXME: Disabled because of bugs in widl and rpcrt4 */
2711 #if 0
2712 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
2713 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
2714 {
2715 Status = STATUS_INSUFFICIENT_RESOURCES;
2716 goto done;
2717 }
2718
2719 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
2720 UserName,
2721 EnumBuffer->Buffer[i].Name.Length);
2722 #endif
2723 }
2724
2725 done:
2726 if (NT_SUCCESS(Status))
2727 {
2728 *EnumerationContext += EnumCount;
2729 *Buffer = EnumBuffer;
2730 *CountReturned = EnumCount;
2731 }
2732 else
2733 {
2734 *EnumerationContext = 0;
2735 *Buffer = NULL;
2736 *CountReturned = 0;
2737
2738 if (EnumBuffer != NULL)
2739 {
2740 if (EnumBuffer->Buffer != NULL)
2741 {
2742 if (EnumBuffer->EntriesRead != 0)
2743 {
2744 for (i = 0; i < EnumBuffer->EntriesRead; i++)
2745 {
2746 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
2747 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
2748 }
2749 }
2750
2751 midl_user_free(EnumBuffer->Buffer);
2752 }
2753
2754 midl_user_free(EnumBuffer);
2755 }
2756 }
2757
2758 SampRegCloseKey(&NamesKeyHandle);
2759 SampRegCloseKey(&UsersKeyHandle);
2760
2761 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
2762 Status = STATUS_MORE_ENTRIES;
2763
2764 RtlReleaseResource(&SampResource);
2765
2766 return Status;
2767 }
2768
2769
2770 /* Function 14 */
2771 NTSTATUS
2772 NTAPI
2773 SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
2774 IN PRPC_UNICODE_STRING AccountName,
2775 IN ACCESS_MASK DesiredAccess,
2776 OUT SAMPR_HANDLE *AliasHandle,
2777 OUT unsigned long *RelativeId)
2778 {
2779 SAM_DOMAIN_FIXED_DATA FixedDomainData;
2780 PSAM_DB_OBJECT DomainObject;
2781 PSAM_DB_OBJECT AliasObject;
2782 PSECURITY_DESCRIPTOR Sd = NULL;
2783 ULONG SdSize = 0;
2784 ULONG ulSize;
2785 ULONG ulRid;
2786 WCHAR szRid[9];
2787 NTSTATUS Status;
2788
2789 TRACE("SamrCreateAliasInDomain(%p %p %lx %p %p)\n",
2790 DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId);
2791
2792 /* Map generic access rights */
2793 RtlMapGenericMask(&DesiredAccess,
2794 &AliasMapping);
2795
2796 RtlAcquireResourceExclusive(&SampResource,
2797 TRUE);
2798
2799 /* Validate the domain handle */
2800 Status = SampValidateDbObject(DomainHandle,
2801 SamDbDomainObject,
2802 DOMAIN_CREATE_ALIAS,
2803 &DomainObject);
2804 if (!NT_SUCCESS(Status))
2805 {
2806 TRACE("failed with status 0x%08lx\n", Status);
2807 goto done;
2808 }
2809
2810 /* Check the alias acoount name */
2811 Status = SampCheckAccountName(AccountName, 256);
2812 if (!NT_SUCCESS(Status))
2813 {
2814 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
2815 goto done;
2816 }
2817
2818 /* Check if the alias name already exists in the domain */
2819 Status = SampCheckAccountNameInDomain(DomainObject,
2820 AccountName->Buffer);
2821 if (!NT_SUCCESS(Status))
2822 {
2823 TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n",
2824 AccountName->Buffer, Status);
2825 goto done;
2826 }
2827
2828 /* Create the security descriptor */
2829 Status = SampCreateAliasSD(&Sd,
2830 &SdSize);
2831 if (!NT_SUCCESS(Status))
2832 {
2833 TRACE("SampCreateAliasSD failed (Status 0x%08lx)\n", Status);
2834 goto done;
2835 }
2836
2837 /* Get the fixed domain attributes */
2838 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
2839 Status = SampGetObjectAttribute(DomainObject,
2840 L"F",
2841 NULL,
2842 (PVOID)&FixedDomainData,
2843 &ulSize);
2844 if (!NT_SUCCESS(Status))
2845 {
2846 TRACE("failed with status 0x%08lx\n", Status);
2847 goto done;
2848 }
2849
2850 /* Increment the NextRid attribute */
2851 ulRid = FixedDomainData.NextRid;
2852 FixedDomainData.NextRid++;
2853
2854 /* Store the fixed domain attributes */
2855 Status = SampSetObjectAttribute(DomainObject,
2856 L"F",
2857 REG_BINARY,
2858 &FixedDomainData,
2859 ulSize);
2860 if (!NT_SUCCESS(Status))
2861 {
2862 TRACE("failed with status 0x%08lx\n", Status);
2863 goto done;
2864 }
2865
2866 TRACE("RID: %lx\n", ulRid);
2867
2868 /* Convert the RID into a string (hex) */
2869 swprintf(szRid, L"%08lX", ulRid);
2870
2871 /* Create the alias object */
2872 Status = SampCreateDbObject(DomainObject,
2873 L"Aliases",
2874 szRid,
2875 ulRid,
2876 SamDbAliasObject,
2877 DesiredAccess,
2878 &AliasObject);
2879 if (!NT_SUCCESS(Status))
2880 {
2881 TRACE("failed with status 0x%08lx\n", Status);
2882 goto done;
2883 }
2884
2885 /* Add the account name for the alias object */
2886 Status = SampSetAccountNameInDomain(DomainObject,
2887 L"Aliases",
2888 AccountName->Buffer,
2889 ulRid);
2890 if (!NT_SUCCESS(Status))
2891 {
2892 TRACE("failed with status 0x%08lx\n", Status);
2893 goto done;
2894 }
2895
2896 /* Set the Name attribute */
2897 Status = SampSetObjectAttributeString(AliasObject,
2898 L"Name",
2899 AccountName);
2900 if (!NT_SUCCESS(Status))
2901 {
2902 TRACE("failed with status 0x%08lx\n", Status);
2903 goto done;
2904 }
2905
2906 /* Set the Description attribute */
2907 Status = SampSetObjectAttributeString(AliasObject,
2908 L"Description",
2909 NULL);
2910 if (!NT_SUCCESS(Status))
2911 {
2912 TRACE("failed with status 0x%08lx\n", Status);
2913 goto done;
2914 }
2915
2916 /* Set the SecDesc attribute*/
2917 Status = SampSetObjectAttribute(AliasObject,
2918 L"SecDesc",
2919 REG_BINARY,
2920 Sd,
2921 SdSize);
2922 if (!NT_SUCCESS(Status))
2923 {
2924 TRACE("failed with status 0x%08lx\n", Status);
2925 goto done;
2926 }
2927
2928 if (NT_SUCCESS(Status))
2929 {
2930 *AliasHandle = (SAMPR_HANDLE)AliasObject;
2931 *RelativeId = ulRid;
2932 }
2933
2934 done:
2935 if (Sd != NULL)
2936 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
2937
2938 RtlReleaseResource(&SampResource);
2939
2940 TRACE("returns with status 0x%08lx\n", Status);
2941
2942 return Status;
2943 }
2944
2945
2946 /* Function 15 */
2947 NTSTATUS
2948 NTAPI
2949 SamrEnumerateAliasesInDomain(IN SAMPR_HANDLE DomainHandle,
2950 IN OUT unsigned long *EnumerationContext,
2951 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
2952 IN unsigned long PreferedMaximumLength,
2953 OUT unsigned long *CountReturned)
2954 {
2955 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
2956 PSAM_DB_OBJECT DomainObject;
2957 HANDLE AliasesKeyHandle = NULL;
2958 HANDLE NamesKeyHandle = NULL;
2959 WCHAR AliasName[64];
2960 ULONG EnumIndex;
2961 ULONG EnumCount = 0;
2962 ULONG RequiredLength = 0;
2963 ULONG NameLength;
2964 ULONG DataLength;
2965 ULONG Rid;
2966 ULONG i;
2967 BOOLEAN MoreEntries = FALSE;
2968 NTSTATUS Status;
2969
2970 TRACE("SamrEnumerateAliasesInDomain(%p %p %p %lu %p)\n",
2971 DomainHandle, EnumerationContext, Buffer,
2972 PreferedMaximumLength, CountReturned);
2973
2974 RtlAcquireResourceShared(&SampResource,
2975 TRUE);
2976
2977 /* Validate the domain handle */
2978 Status = SampValidateDbObject(DomainHandle,
2979 SamDbDomainObject,
2980 DOMAIN_LIST_ACCOUNTS,
2981 &DomainObject);
2982 if (!NT_SUCCESS(Status))
2983 goto done;
2984
2985 Status = SampRegOpenKey(DomainObject->KeyHandle,
2986 L"Aliases",
2987 KEY_READ,
2988 &AliasesKeyHandle);
2989 if (!NT_SUCCESS(Status))
2990 goto done;
2991
2992 Status = SampRegOpenKey(AliasesKeyHandle,
2993 L"Names",
2994 KEY_READ,
2995 &NamesKeyHandle);
2996 if (!NT_SUCCESS(Status))
2997 goto done;
2998
2999 TRACE("Part 1\n");
3000
3001 EnumIndex = *EnumerationContext;
3002
3003 while (TRUE)
3004 {
3005 NameLength = 64 * sizeof(WCHAR);
3006 Status = SampRegEnumerateValue(NamesKeyHandle,
3007 EnumIndex,
3008 AliasName,
3009 &NameLength,
3010 NULL,
3011 NULL,
3012 NULL);
3013 if (!NT_SUCCESS(Status))
3014 {
3015 if (Status == STATUS_NO_MORE_ENTRIES)
3016 Status = STATUS_SUCCESS;
3017 break;
3018 }
3019
3020 TRACE("EnumIndex: %lu\n", EnumIndex);
3021 TRACE("Alias name: %S\n", AliasName);
3022 TRACE("Name length: %lu\n", NameLength);
3023
3024 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
3025 {
3026 MoreEntries = TRUE;
3027 break;
3028 }
3029
3030 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
3031 EnumCount++;
3032
3033 EnumIndex++;
3034 }
3035
3036 TRACE("EnumCount: %lu\n", EnumCount);
3037 TRACE("RequiredLength: %lu\n", RequiredLength);
3038
3039 if (!NT_SUCCESS(Status))
3040 goto done;
3041
3042 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
3043 if (EnumBuffer == NULL)
3044 {
3045 Status = STATUS_INSUFFICIENT_RESOURCES;
3046 goto done;
3047 }
3048
3049 EnumBuffer->EntriesRead = EnumCount;
3050 if (EnumCount == 0)
3051 goto done;
3052
3053 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
3054 if (EnumBuffer->Buffer == NULL)
3055 {
3056 Status = STATUS_INSUFFICIENT_RESOURCES;
3057 goto done;
3058 }
3059
3060 TRACE("Part 2\n");
3061
3062 EnumIndex = *EnumerationContext;
3063 for (i = 0; i < EnumCount; i++, EnumIndex++)
3064 {
3065 NameLength = 64 * sizeof(WCHAR);
3066 DataLength = sizeof(ULONG);
3067 Status = SampRegEnumerateValue(NamesKeyHandle,
3068 EnumIndex,
3069 AliasName,
3070 &NameLength,
3071 NULL,
3072 &Rid,
3073 &DataLength);
3074 if (!NT_SUCCESS(Status))
3075 {
3076 if (Status == STATUS_NO_MORE_ENTRIES)
3077 Status = STATUS_SUCCESS;
3078 break;
3079 }
3080
3081 TRACE("EnumIndex: %lu\n", EnumIndex);
3082 TRACE("Alias name: %S\n", AliasName);
3083 TRACE("Name length: %lu\n", NameLength);
3084 TRACE("RID: %lu\n", Rid);
3085
3086 EnumBuffer->Buffer[i].RelativeId = Rid;
3087
3088 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
3089 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(DataLength + sizeof(UNICODE_NULL));
3090
3091 /* FIXME: Disabled because of bugs in widl and rpcrt4 */
3092 #if 0
3093 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
3094 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
3095 {
3096 Status = STATUS_INSUFFICIENT_RESOURCES;
3097 goto done;
3098 }
3099
3100 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
3101 AliasName,
3102 EnumBuffer->Buffer[i].Name.Length);
3103 #endif
3104 }
3105
3106 done:
3107 if (NT_SUCCESS(Status))
3108 {
3109 *EnumerationContext += EnumCount;
3110 *Buffer = EnumBuffer;
3111 *CountReturned = EnumCount;
3112 }
3113 else
3114 {
3115 *EnumerationContext = 0;
3116 *Buffer = NULL;
3117 *CountReturned = 0;
3118
3119 if (EnumBuffer != NULL)
3120 {
3121 if (EnumBuffer->Buffer != NULL)
3122 {
3123 if (EnumBuffer->EntriesRead != 0)
3124 {
3125 for (i = 0; i < EnumBuffer->EntriesRead; i++)
3126 {
3127 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
3128 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
3129 }
3130 }
3131
3132 midl_user_free(EnumBuffer->Buffer);
3133 }
3134
3135 midl_user_free(EnumBuffer);
3136 }
3137 }
3138
3139 SampRegCloseKey(&NamesKeyHandle);
3140 SampRegCloseKey(&AliasesKeyHandle);
3141
3142 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
3143 Status = STATUS_MORE_ENTRIES;
3144
3145 RtlReleaseResource(&SampResource);
3146
3147 return Status;
3148 }
3149
3150
3151 /* Function 16 */
3152 NTSTATUS
3153 NTAPI
3154 SamrGetAliasMembership(IN SAMPR_HANDLE DomainHandle,
3155 IN PSAMPR_PSID_ARRAY SidArray,
3156 OUT PSAMPR_ULONG_ARRAY Membership)
3157 {
3158 PSAM_DB_OBJECT DomainObject;
3159 HANDLE AliasesKeyHandle = NULL;
3160 HANDLE MembersKeyHandle = NULL;
3161 HANDLE MemberKeyHandle = NULL;
3162 LPWSTR MemberSidString = NULL;
3163 PULONG RidArray = NULL;
3164 ULONG MaxSidCount = 0;
3165 ULONG ValueCount;
3166 ULONG DataLength;
3167 ULONG i, j;
3168 NTSTATUS Status;
3169 WCHAR NameBuffer[9];
3170
3171 TRACE("SamrGetAliasMembership(%p %p %p)\n",
3172 DomainHandle, SidArray, Membership);
3173
3174 RtlAcquireResourceShared(&SampResource,
3175 TRUE);
3176
3177 /* Validate the domain handle */
3178 Status = SampValidateDbObject(DomainHandle,
3179 SamDbDomainObject,
3180 DOMAIN_GET_ALIAS_MEMBERSHIP,
3181 &DomainObject);
3182 if (!NT_SUCCESS(Status))
3183 goto done;
3184
3185 Status = SampRegOpenKey(DomainObject->KeyHandle,
3186 L"Aliases",
3187 KEY_READ,
3188 &AliasesKeyHandle);
3189 TRACE("SampRegOpenKey returned %08lX\n", Status);
3190 if (!NT_SUCCESS(Status))
3191 goto done;
3192
3193 Status = SampRegOpenKey(AliasesKeyHandle,
3194 L"Members",
3195 KEY_READ,
3196 &MembersKeyHandle);
3197 TRACE("SampRegOpenKey returned %08lX\n", Status);
3198
3199 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
3200 {
3201 Status = STATUS_SUCCESS;
3202 goto done;
3203 }
3204
3205 if (!NT_SUCCESS(Status))
3206 goto done;
3207
3208 for (i = 0; i < SidArray->Count; i++)
3209 {
3210 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
3211 TRACE("Open %S\n", MemberSidString);
3212
3213 Status = SampRegOpenKey(MembersKeyHandle,
3214 MemberSidString,
3215 KEY_READ,
3216 &MemberKeyHandle);
3217 TRACE("SampRegOpenKey returned %08lX\n", Status);
3218 if (NT_SUCCESS(Status))
3219 {
3220 Status = SampRegQueryKeyInfo(MemberKeyHandle,
3221 NULL,
3222 &ValueCount);
3223 if (NT_SUCCESS(Status))
3224 {
3225 TRACE("Found %lu values\n", ValueCount);
3226 MaxSidCount += ValueCount;
3227 }
3228
3229 SampRegCloseKey(&MemberKeyHandle);
3230 }
3231
3232 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
3233 Status = STATUS_SUCCESS;
3234
3235 LocalFree(MemberSidString);
3236 }
3237
3238 if (MaxSidCount == 0)
3239 {
3240 Status = STATUS_SUCCESS;
3241 goto done;
3242 }
3243
3244 TRACE("Maximum sid count: %lu\n", MaxSidCount);
3245 RidArray = midl_user_allocate(MaxSidCount * sizeof(ULONG));
3246 if (RidArray == NULL)
3247 {
3248 Status = STATUS_INSUFFICIENT_RESOURCES;
3249 goto done;
3250 }
3251
3252 for (i = 0; i < SidArray->Count; i++)
3253 {
3254 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
3255 TRACE("Open %S\n", MemberSidString);
3256
3257 Status = SampRegOpenKey(MembersKeyHandle,
3258 MemberSidString,
3259 KEY_READ,
3260 &MemberKeyHandle);
3261 TRACE("SampRegOpenKey returned %08lX\n", Status);
3262 if (NT_SUCCESS(Status))
3263 {
3264 Status = SampRegQueryKeyInfo(MemberKeyHandle,
3265 NULL,
3266 &ValueCount);
3267 if (NT_SUCCESS(Status))
3268 {
3269 TRACE("Found %lu values\n", ValueCount);
3270
3271 for (j = 0; j < ValueCount; j++)
3272 {
3273 DataLength = 9 * sizeof(WCHAR);
3274 Status = SampRegEnumerateValue(MemberKeyHandle,
3275 j,
3276 NameBuffer,
3277 &DataLength,
3278 NULL,
3279 NULL,
3280 NULL);
3281 if (NT_SUCCESS(Status))
3282 {
3283 RidArray[j] = wcstoul(NameBuffer, NULL, 16);
3284 }
3285 }
3286 }
3287
3288 SampRegCloseKey(&MemberKeyHandle);
3289 }
3290
3291 LocalFree(MemberSidString);
3292 }
3293
3294 done:
3295 SampRegCloseKey(&MembersKeyHandle);
3296 SampRegCloseKey(&AliasesKeyHandle);
3297
3298 if (NT_SUCCESS(Status))
3299 {
3300 Membership->Count = MaxSidCount;
3301 Membership->Element = RidArray;
3302 }
3303 else
3304 {
3305 if (RidArray != NULL)
3306 midl_user_free(RidArray);
3307 }
3308
3309 RtlReleaseResource(&SampResource);
3310
3311 return Status;
3312 }
3313
3314
3315 /* Function 17 */
3316 NTSTATUS
3317 NTAPI
3318 SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
3319 IN ULONG Count,
3320 IN RPC_UNICODE_STRING Names[],
3321 OUT PSAMPR_ULONG_ARRAY RelativeIds,
3322 OUT PSAMPR_ULONG_ARRAY Use)
3323 {
3324 PSAM_DB_OBJECT DomainObject;
3325 HANDLE AccountsKeyHandle = NULL;
3326 HANDLE NamesKeyHandle = NULL;
3327 ULONG MappedCount = 0;
3328 ULONG DataLength;
3329 ULONG i;
3330 ULONG RelativeId;
3331 NTSTATUS Status;
3332
3333 TRACE("SamrLookupNamesInDomain(%p %lu %p %p %p)\n",
3334 DomainHandle, Count, Names, RelativeIds, Use);
3335
3336 RtlAcquireResourceShared(&SampResource,
3337 TRUE);
3338
3339 /* Validate the domain handle */
3340 Status = SampValidateDbObject(DomainHandle,
3341 SamDbDomainObject,
3342 DOMAIN_LOOKUP,
3343 &DomainObject);
3344 if (!NT_SUCCESS(Status))
3345 {
3346 TRACE("failed with status 0x%08lx\n", Status);
3347 goto done;
3348 }
3349
3350 RelativeIds->Count = 0;
3351 Use->Count = 0;
3352
3353 if (Count == 0)
3354 {
3355 Status = STATUS_SUCCESS;
3356 goto done;
3357 }
3358
3359 /* Allocate the relative IDs array */
3360 RelativeIds->Element = midl_user_allocate(Count * sizeof(ULONG));
3361 if (RelativeIds->Element == NULL)
3362 {
3363 Status = STATUS_INSUFFICIENT_RESOURCES;
3364 goto done;
3365 }
3366
3367 /* Allocate the use array */
3368 Use->Element = midl_user_allocate(Count * sizeof(ULONG));
3369 if (Use->Element == NULL)
3370 {
3371 Status = STATUS_INSUFFICIENT_RESOURCES;
3372 goto done;
3373 }
3374
3375 RelativeIds->Count = Count;
3376 Use->Count = Count;
3377
3378 for (i = 0; i < Count; i++)
3379 {
3380 TRACE("Name: %S\n", Names[i].Buffer);
3381
3382 RelativeId = 0;
3383
3384 /* Lookup aliases */
3385 Status = SampRegOpenKey(DomainObject->KeyHandle,
3386 L"Aliases",
3387 KEY_READ,
3388 &AccountsKeyHandle);
3389 if (NT_SUCCESS(Status))
3390 {
3391 Status = SampRegOpenKey(AccountsKeyHandle,
3392 L"Names",
3393 KEY_READ,
3394 &NamesKeyHandle);
3395 if (NT_SUCCESS(Status))
3396 {
3397 DataLength = sizeof(ULONG);
3398 Status = SampRegQueryValue(NamesKeyHandle,
3399 Names[i].Buffer,
3400 NULL,
3401 &RelativeId,
3402 &DataLength);
3403
3404 SampRegCloseKey(&NamesKeyHandle);
3405 }
3406
3407 SampRegCloseKey(&AccountsKeyHandle);
3408 }
3409
3410 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3411 break;
3412
3413 /* Return alias account */
3414 if (NT_SUCCESS(Status) && RelativeId != 0)
3415 {
3416 TRACE("Rid: %lu\n", RelativeId);
3417 RelativeIds->Element[i] = RelativeId;
3418 Use->Element[i] = SidTypeAlias;
3419 MappedCount++;
3420 continue;
3421 }
3422
3423 /* Lookup groups */
3424 Status = SampRegOpenKey(DomainObject->KeyHandle,
3425 L"Groups",
3426 KEY_READ,
3427 &AccountsKeyHandle);
3428 if (NT_SUCCESS(Status))
3429 {
3430 Status = SampRegOpenKey(AccountsKeyHandle,
3431 L"Names",
3432 KEY_READ,
3433 &NamesKeyHandle);
3434 if (NT_SUCCESS(Status))
3435 {
3436 DataLength = sizeof(ULONG);
3437 Status = SampRegQueryValue(NamesKeyHandle,
3438 Names[i].Buffer,
3439 NULL,
3440 &RelativeId,
3441 &DataLength);
3442
3443 SampRegCloseKey(&NamesKeyHandle);
3444 }
3445
3446 SampRegCloseKey(&AccountsKeyHandle);
3447 }
3448
3449 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3450 break;
3451
3452 /* Return group account */
3453 if (NT_SUCCESS(Status) && RelativeId != 0)
3454 {
3455 TRACE("Rid: %lu\n", RelativeId);
3456 RelativeIds->Element[i] = RelativeId;
3457 Use->Element[i] = SidTypeGroup;
3458 MappedCount++;
3459 continue;
3460 }
3461
3462 /* Lookup users */
3463 Status = SampRegOpenKey(DomainObject->KeyHandle,
3464 L"Users",
3465 KEY_READ,
3466 &AccountsKeyHandle);
3467 if (NT_SUCCESS(Status))
3468 {
3469 Status = SampRegOpenKey(AccountsKeyHandle,
3470 L"Names",
3471 KEY_READ,
3472 &NamesKeyHandle);
3473 if (NT_SUCCESS(Status))
3474 {
3475 DataLength = sizeof(ULONG);
3476 Status = SampRegQueryValue(NamesKeyHandle,
3477 Names[i].Buffer,
3478 NULL,
3479 &RelativeId,
3480 &DataLength);
3481
3482 SampRegCloseKey(&NamesKeyHandle);
3483 }
3484
3485 SampRegCloseKey(&AccountsKeyHandle);
3486 }
3487
3488 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3489 break;
3490
3491 /* Return user account */
3492 if (NT_SUCCESS(Status) && RelativeId != 0)
3493 {
3494 TRACE("Rid: %lu\n", RelativeId);
3495 RelativeIds->Element[i] = RelativeId;
3496 Use->Element[i] = SidTypeUser;
3497 MappedCount++;
3498 continue;
3499 }
3500
3501 /* Return unknown account */
3502 RelativeIds->Element[i] = 0;
3503 Use->Element[i] = SidTypeUnknown;
3504 }
3505
3506 done:
3507 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
3508 Status = STATUS_SUCCESS;
3509
3510 if (NT_SUCCESS(Status))
3511 {
3512 if (MappedCount == 0)
3513 Status = STATUS_NONE_MAPPED;
3514 else if (MappedCount < Count)
3515 Status = STATUS_SOME_NOT_MAPPED;
3516 }
3517 else
3518 {
3519 if (RelativeIds->Element != NULL)
3520 {
3521 midl_user_free(RelativeIds->Element);
3522 RelativeIds->Element = NULL;
3523 }
3524
3525 RelativeIds->Count = 0;
3526
3527 if (Use->Element != NULL)
3528 {
3529 midl_user_free(Use->Element);
3530 Use->Element = NULL;
3531 }
3532
3533 Use->Count = 0;
3534 }
3535
3536 RtlReleaseResource(&SampResource);
3537
3538 TRACE("Returned Status %lx\n", Status);
3539
3540 return Status;
3541 }
3542
3543
3544 /* Function 18 */
3545 NTSTATUS
3546 NTAPI
3547 SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
3548 IN ULONG Count,
3549 IN ULONG *RelativeIds,
3550 OUT PSAMPR_RETURNED_USTRING_ARRAY Names,
3551 OUT PSAMPR_ULONG_ARRAY Use)
3552 {
3553 PSAM_DB_OBJECT DomainObject;
3554 WCHAR RidString[9];
3555 HANDLE AccountsKeyHandle = NULL;
3556 HANDLE AccountKeyHandle = NULL;
3557 ULONG MappedCount = 0;
3558 ULONG DataLength;
3559 ULONG i;
3560 NTSTATUS Status;
3561
3562 TRACE("SamrLookupIdsInDomain(%p %lu %p %p %p)\n",
3563 DomainHandle, Count, RelativeIds, Names, Use);
3564
3565 RtlAcquireResourceShared(&SampResource,
3566 TRUE);
3567
3568 /* Validate the domain handle */
3569 Status = SampValidateDbObject(DomainHandle,
3570 SamDbDomainObject,
3571 DOMAIN_LOOKUP,
3572 &DomainObject);
3573 if (!NT_SUCCESS(Status))
3574 {
3575 TRACE("failed with status 0x%08lx\n", Status);
3576 goto done;
3577 }
3578
3579 Names->Count = 0;
3580 Use->Count = 0;
3581
3582 if (Count == 0)
3583 {
3584 Status = STATUS_SUCCESS;
3585 goto done;
3586 }
3587
3588 /* Allocate the names array */
3589 Names->Element = midl_user_allocate(Count * sizeof(ULONG));
3590 if (Names->Element == NULL)
3591 {
3592 Status = STATUS_INSUFFICIENT_RESOURCES;
3593 goto done;
3594 }
3595
3596 /* Allocate the use array */
3597 Use->Element = midl_user_allocate(Count * sizeof(ULONG));
3598 if (Use->Element == NULL)
3599 {
3600 Status = STATUS_INSUFFICIENT_RESOURCES;
3601 goto done;
3602 }
3603
3604 Names->Count = Count;
3605 Use->Count = Count;
3606
3607 for (i = 0; i < Count; i++)
3608 {
3609 TRACE("RID: %lu\n", RelativeIds[i]);
3610
3611 swprintf(RidString, L"%08lx", RelativeIds[i]);
3612
3613 /* Lookup aliases */
3614 Status = SampRegOpenKey(DomainObject->KeyHandle,
3615 L"Aliases",
3616 KEY_READ,
3617 &AccountsKeyHandle);
3618 if (NT_SUCCESS(Status))
3619 {
3620 Status = SampRegOpenKey(AccountsKeyHandle,
3621 RidString,
3622 KEY_READ,
3623 &AccountKeyHandle);
3624 if (NT_SUCCESS(Status))
3625 {
3626 DataLength = 0;
3627 Status = SampRegQueryValue(AccountKeyHandle,
3628 L"Name",
3629 NULL,
3630 NULL,
3631 &DataLength);
3632 if (NT_SUCCESS(Status))
3633 {
3634 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3635 if (Names->Element[i].Buffer == NULL)
3636 Status = STATUS_INSUFFICIENT_RESOURCES;
3637
3638 if (NT_SUCCESS(Status))
3639 {
3640 Names->Element[i].MaximumLength = (USHORT)DataLength;
3641 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3642
3643 Status = SampRegQueryValue(AccountKeyHandle,
3644 L"Name",
3645 NULL,
3646 Names->Element[i].Buffer,
3647 &DataLength);
3648 }
3649 }
3650
3651 SampRegCloseKey(&AccountKeyHandle);
3652 }
3653
3654 SampRegCloseKey(&AccountsKeyHandle);
3655 }
3656
3657 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3658 break;
3659
3660 /* Return alias account */
3661 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3662 {
3663 TRACE("Name: %S\n", Names->Element[i].Buffer);
3664 Use->Element[i] = SidTypeAlias;
3665 MappedCount++;
3666 continue;
3667 }
3668
3669 /* Lookup groups */
3670 Status = SampRegOpenKey(DomainObject->KeyHandle,
3671 L"Groups",
3672 KEY_READ,
3673 &AccountsKeyHandle);
3674 if (NT_SUCCESS(Status))
3675 {
3676 Status = SampRegOpenKey(AccountsKeyHandle,
3677 RidString,
3678 KEY_READ,
3679 &AccountKeyHandle);
3680 if (NT_SUCCESS(Status))
3681 {
3682 DataLength = 0;
3683 Status = SampRegQueryValue(AccountKeyHandle,
3684 L"Name",
3685 NULL,
3686 NULL,
3687 &DataLength);
3688 if (NT_SUCCESS(Status))
3689 {
3690 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3691 if (Names->Element[i].Buffer == NULL)
3692 Status = STATUS_INSUFFICIENT_RESOURCES;
3693
3694 if (NT_SUCCESS(Status))
3695 {
3696 Names->Element[i].MaximumLength = (USHORT)DataLength;
3697 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3698
3699 Status = SampRegQueryValue(AccountKeyHandle,
3700 L"Name",
3701 NULL,
3702 Names->Element[i].Buffer,
3703 &DataLength);
3704 }
3705 }
3706
3707 SampRegCloseKey(&AccountKeyHandle);
3708 }
3709
3710 SampRegCloseKey(&AccountsKeyHandle);
3711 }
3712
3713 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3714 break;
3715
3716 /* Return group account */
3717 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3718 {
3719 TRACE("Name: %S\n", Names->Element[i].Buffer);
3720 Use->Element[i] = SidTypeGroup;
3721 MappedCount++;
3722 continue;
3723 }
3724
3725 /* Lookup users */
3726 Status = SampRegOpenKey(DomainObject->KeyHandle,
3727 L"Users",
3728 KEY_READ,
3729 &AccountsKeyHandle);
3730 if (NT_SUCCESS(Status))
3731 {
3732 Status = SampRegOpenKey(AccountsKeyHandle,
3733 RidString,
3734 KEY_READ,
3735 &AccountKeyHandle);
3736 if (NT_SUCCESS(Status))
3737 {
3738 DataLength = 0;
3739 Status = SampRegQueryValue(AccountKeyHandle,
3740 L"Name",
3741 NULL,
3742 NULL,
3743 &DataLength);
3744 if (NT_SUCCESS(Status))
3745 {
3746 TRACE("DataLength: %lu\n", DataLength);
3747
3748 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3749 if (Names->Element[i].Buffer == NULL)
3750 Status = STATUS_INSUFFICIENT_RESOURCES;
3751
3752 if (NT_SUCCESS(Status))
3753 {
3754 Names->Element[i].MaximumLength = (USHORT)DataLength;
3755 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3756
3757 Status = SampRegQueryValue(AccountKeyHandle,
3758 L"Name",
3759 NULL,
3760 Names->Element[i].Buffer,
3761 &DataLength);
3762 }
3763 }
3764
3765 SampRegCloseKey(&AccountKeyHandle);
3766 }
3767
3768 SampRegCloseKey(&AccountsKeyHandle);
3769 }
3770
3771 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3772 break;
3773
3774 /* Return user account */
3775 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3776 {
3777 TRACE("Name: %S\n", Names->Element[i].Buffer);
3778 Use->Element[i] = SidTypeUser;
3779 MappedCount++;
3780 continue;
3781 }
3782
3783 /* Return unknown account */
3784 Use->Element[i] = SidTypeUnknown;
3785 }
3786
3787 done:
3788 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
3789 Status = STATUS_SUCCESS;
3790
3791 if (NT_SUCCESS(Status))
3792 {
3793 if (MappedCount == 0)
3794 Status = STATUS_NONE_MAPPED;
3795 else if (MappedCount < Count)
3796 Status = STATUS_SOME_NOT_MAPPED;
3797 }
3798 else
3799 {
3800 if (Names->Element != NULL)
3801 {
3802 for (i = 0; i < Count; i++)
3803 {
3804 if (Names->Element[i].Buffer != NULL)
3805 midl_user_free(Names->Element[i].Buffer);
3806 }
3807
3808 midl_user_free(Names->Element);
3809 Names->Element = NULL;
3810 }
3811
3812 Names->Count = 0;
3813
3814 if (Use->Element != NULL)
3815 {
3816 midl_user_free(Use->Element);
3817 Use->Element = NULL;
3818 }
3819
3820 Use->Count = 0;
3821 }
3822
3823 RtlReleaseResource(&SampResource);
3824
3825 return Status;
3826 }
3827
3828
3829 /* Function 19 */
3830 NTSTATUS
3831 NTAPI
3832 SamrOpenGroup(IN SAMPR_HANDLE DomainHandle,
3833 IN ACCESS_MASK DesiredAccess,
3834 IN unsigned long GroupId,
3835 OUT SAMPR_HANDLE *GroupHandle)
3836 {
3837 PSAM_DB_OBJECT DomainObject;
3838 PSAM_DB_OBJECT GroupObject;
3839 WCHAR szRid[9];
3840 NTSTATUS Status;
3841
3842 TRACE("SamrOpenGroup(%p %lx %lx %p)\n",
3843 DomainHandle, DesiredAccess, GroupId, GroupHandle);
3844
3845 /* Map generic access rights */
3846 RtlMapGenericMask(&DesiredAccess,
3847 &GroupMapping);
3848
3849 RtlAcquireResourceShared(&SampResource,
3850 TRUE);
3851
3852 /* Validate the domain handle */
3853 Status = SampValidateDbObject(DomainHandle,
3854 SamDbDomainObject,
3855 DOMAIN_LOOKUP,
3856 &DomainObject);
3857 if (!NT_SUCCESS(Status))
3858 {
3859 TRACE("failed with status 0x%08lx\n", Status);
3860 goto done;
3861 }
3862
3863 /* Convert the RID into a string (hex) */
3864 swprintf(szRid, L"%08lX", GroupId);
3865
3866 /* Create the group object */
3867 Status = SampOpenDbObject(DomainObject,
3868 L"Groups",
3869 szRid,
3870 GroupId,
3871 SamDbGroupObject,
3872 DesiredAccess,
3873 &GroupObject);
3874 if (!NT_SUCCESS(Status))
3875 {
3876 TRACE("failed with status 0x%08lx\n", Status);
3877 goto done;
3878 }
3879
3880 *GroupHandle = (SAMPR_HANDLE)GroupObject;
3881
3882 done:
3883 RtlReleaseResource(&SampResource);
3884
3885 return Status;
3886 }
3887
3888
3889 static NTSTATUS
3890 SampQueryGroupGeneral(PSAM_DB_OBJECT GroupObject,
3891 PSAMPR_GROUP_INFO_BUFFER *Buffer)
3892 {
3893 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
3894 SAM_GROUP_FIXED_DATA FixedData;
3895 ULONG MembersLength = 0;
3896 ULONG Length = 0;
3897 NTSTATUS Status;
3898
3899 *Buffer = NULL;
3900
3901 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
3902 if (InfoBuffer == NULL)
3903 return STATUS_INSUFFICIENT_RESOURCES;
3904
3905 Status = SampGetObjectAttributeString(GroupObject,
3906 L"Name",
3907 &InfoBuffer->General.Name);
3908 if (!NT_SUCCESS(Status))
3909 {
3910 TRACE("Status 0x%08lx\n", Status);
3911 goto done;
3912 }
3913
3914 Status = SampGetObjectAttributeString(GroupObject,
3915 L"Description",
3916 &InfoBuffer->General.AdminComment);
3917 if (!NT_SUCCESS(Status))
3918 {
3919 TRACE("Status 0x%08lx\n", Status);
3920 goto done;
3921 }
3922
3923 Length = sizeof(SAM_GROUP_FIXED_DATA);
3924 Status = SampGetObjectAttribute(GroupObject,
3925 L"F",
3926 NULL,
3927 (PVOID)&FixedData,
3928 &Length);
3929 if (!NT_SUCCESS(Status))
3930 goto done;
3931
3932 InfoBuffer->General.Attributes = FixedData.Attributes;
3933
3934 Status = SampGetObjectAttribute(GroupObject,
3935 L"Members",
3936 NULL,
3937 NULL,
3938 &MembersLength);
3939 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3940 goto done;
3941
3942 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
3943 InfoBuffer->General.MemberCount = 0;
3944 else
3945 InfoBuffer->General.MemberCount = MembersLength / sizeof(ULONG);
3946
3947 *Buffer = InfoBuffer;
3948
3949 done:
3950 if (!NT_SUCCESS(Status))
3951 {
3952 if (InfoBuffer != NULL)
3953 {
3954 if (InfoBuffer->General.Name.Buffer != NULL)
3955 midl_user_free(InfoBuffer->General.Name.Buffer);
3956
3957 if (InfoBuffer->General.AdminComment.Buffer != NULL)
3958 midl_user_free(InfoBuffer->General.AdminComment.Buffer);
3959
3960 midl_user_free(InfoBuffer);
3961 }
3962 }
3963
3964 return Status;
3965 }
3966
3967
3968 static NTSTATUS
3969 SampQueryGroupName(PSAM_DB_OBJECT GroupObject,
3970 PSAMPR_GROUP_INFO_BUFFER *Buffer)
3971 {
3972 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
3973 NTSTATUS Status;
3974
3975 *Buffer = NULL;
3976
3977 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
3978 if (InfoBuffer == NULL)
3979 return STATUS_INSUFFICIENT_RESOURCES;
3980
3981 Status = SampGetObjectAttributeString(GroupObject,
3982 L"Name",
3983 &InfoBuffer->Name.Name);
3984 if (!NT_SUCCESS(Status))
3985 {
3986 TRACE("Status 0x%08lx\n", Status);
3987 goto done;
3988 }
3989
3990 *Buffer = InfoBuffer;
3991
3992 done:
3993 if (!NT_SUCCESS(Status))
3994 {
3995 if (InfoBuffer != NULL)
3996 {
3997 if (InfoBuffer->Name.Name.Buffer != NULL)
3998 midl_user_free(InfoBuffer->Name.Name.Buffer);
3999
4000 midl_user_free(InfoBuffer);
4001 }
4002 }
4003
4004 return Status;
4005 }
4006
4007
4008 static NTSTATUS
4009 SampQueryGroupAttribute(PSAM_DB_OBJECT GroupObject,
4010 PSAMPR_GROUP_INFO_BUFFER *Buffer)
4011 {
4012 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
4013 SAM_GROUP_FIXED_DATA FixedData;
4014 ULONG Length = 0;
4015 NTSTATUS Status;
4016
4017 *Buffer = NULL;
4018
4019 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
4020 if (InfoBuffer == NULL)
4021 return STATUS_INSUFFICIENT_RESOURCES;
4022
4023 Length = sizeof(SAM_GROUP_FIXED_DATA);
4024 Status = SampGetObjectAttribute(GroupObject,
4025 L"F",
4026 NULL,
4027 (PVOID)&FixedData,
4028 &Length);
4029 if (!NT_SUCCESS(Status))
4030 goto done;
4031
4032 InfoBuffer->Attribute.Attributes = FixedData.Attributes;
4033
4034 *Buffer = InfoBuffer;
4035
4036 done:
4037 if (!NT_SUCCESS(Status))
4038 {
4039 if (InfoBuffer != NULL)
4040 {
4041 midl_user_free(InfoBuffer);
4042 }
4043 }
4044
4045 return Status;
4046 }
4047
4048
4049 static NTSTATUS
4050 SampQueryGroupAdminComment(PSAM_DB_OBJECT GroupObject,
4051 PSAMPR_GROUP_INFO_BUFFER *Buffer)
4052 {
4053 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
4054 NTSTATUS Status;
4055
4056 *Buffer = NULL;
4057
4058 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
4059 if (InfoBuffer == NULL)
4060 return STATUS_INSUFFICIENT_RESOURCES;
4061
4062 Status = SampGetObjectAttributeString(GroupObject,
4063 L"Description",
4064 &InfoBuffer->AdminComment.AdminComment);
4065 if (!NT_SUCCESS(Status))
4066 {
4067 TRACE("Status 0x%08lx\n", Status);
4068 goto done;
4069 }
4070
4071 *Buffer = InfoBuffer;
4072
4073 done:
4074 if (!NT_SUCCESS(Status))
4075 {
4076 if (InfoBuffer != NULL)
4077 {
4078 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
4079 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
4080
4081 midl_user_free(InfoBuffer);
4082 }
4083 }
4084
4085 return Status;
4086 }
4087
4088
4089 /* Function 20 */
4090 NTSTATUS
4091 NTAPI
4092 SamrQueryInformationGroup(IN SAMPR_HANDLE GroupHandle,
4093 IN GROUP_INFORMATION_CLASS GroupInformationClass,
4094 OUT PSAMPR_GROUP_INFO_BUFFER *Buffer)
4095 {
4096 PSAM_DB_OBJECT GroupObject;
4097 NTSTATUS Status;
4098
4099 TRACE("SamrQueryInformationGroup(%p %lu %p)\n",
4100 GroupHandle, GroupInformationClass, Buffer);
4101
4102 RtlAcquireResourceShared(&SampResource,
4103 TRUE);
4104
4105 /* Validate the group handle */
4106 Status = SampValidateDbObject(GroupHandle,
4107 SamDbGroupObject,
4108 GROUP_READ_INFORMATION,
4109 &GroupObject);
4110 if (!NT_SUCCESS(Status))
4111 goto done;
4112
4113 switch (GroupInformationClass)
4114 {
4115 case GroupGeneralInformation:
4116 Status = SampQueryGroupGeneral(GroupObject,
4117 Buffer);
4118 break;
4119
4120 case GroupNameInformation:
4121 Status = SampQueryGroupName(GroupObject,
4122 Buffer);
4123 break;
4124
4125 case GroupAttributeInformation:
4126 Status = SampQueryGroupAttribute(GroupObject,
4127 Buffer);
4128 break;
4129
4130 case GroupAdminCommentInformation:
4131 Status = SampQueryGroupAdminComment(GroupObject,
4132 Buffer);
4133 break;
4134
4135 default:
4136 Status = STATUS_INVALID_INFO_CLASS;
4137 break;
4138 }
4139
4140 done:
4141 RtlReleaseResource(&SampResource);
4142
4143 return Status;
4144 }
4145
4146
4147 static NTSTATUS
4148 SampSetGroupName(PSAM_DB_OBJECT GroupObject,
4149 PSAMPR_GROUP_INFO_BUFFER Buffer)
4150 {
4151 UNICODE_STRING OldGroupName = {0, 0, NULL};
4152 UNICODE_STRING NewGroupName;
4153 NTSTATUS Status;
4154
4155 Status = SampGetObjectAttributeString(GroupObject,
4156 L"Name",
4157 (PRPC_UNICODE_STRING)&OldGroupName);
4158 if (!NT_SUCCESS(Status))
4159 {
4160 TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status);
4161 goto done;
4162 }
4163
4164 /* Check the new account name */
4165 Status = SampCheckAccountName(&Buffer->Name.Name, 256);
4166 if (!NT_SUCCESS(Status))
4167 {
4168 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
4169 return Status;
4170 }
4171
4172 NewGroupName.Length = Buffer->Name.Name.Length;
4173 NewGroupName.MaximumLength = Buffer->Name.Name.MaximumLength;
4174 NewGroupName.Buffer = Buffer->Name.Name.Buffer;
4175
4176 if (!RtlEqualUnicodeString(&OldGroupName, &NewGroupName, TRUE))
4177 {
4178 Status = SampCheckAccountNameInDomain(GroupObject->ParentObject,
4179 NewGroupName.Buffer);
4180 if (!NT_SUCCESS(Status))
4181 {
4182 TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n",
4183 NewGroupName.Buffer, Status);
4184 goto done;
4185 }
4186 }
4187
4188 Status = SampSetAccountNameInDomain(GroupObject->ParentObject,
4189 L"Groups",
4190 NewGroupName.Buffer,
4191 GroupObject->RelativeId);
4192 if (!NT_SUCCESS(Status))
4193 {
4194 TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status);
4195 goto done;
4196 }
4197
4198 Status = SampRemoveAccountNameFromDomain(GroupObject->ParentObject,
4199 L"Groups",
4200 OldGroupName.Buffer);
4201 if (!NT_SUCCESS(Status))
4202 {
4203 TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status);
4204 goto done;
4205 }
4206
4207 Status = SampSetObjectAttributeString(GroupObject,
4208 L"Name",
4209 (PRPC_UNICODE_STRING)&NewGroupName);
4210 if (!NT_SUCCESS(Status))
4211 {
4212 TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
4213 }
4214
4215 done:
4216 if (OldGroupName.Buffer != NULL)
4217 midl_user_free(OldGroupName.Buffer);
4218
4219 return Status;
4220 }
4221
4222
4223 static NTSTATUS
4224 SampSetGroupAttribute(PSAM_DB_OBJECT GroupObject,
4225 PSAMPR_GROUP_INFO_BUFFER Buffer)
4226 {
4227 SAM_GROUP_FIXED_DATA FixedData;
4228 ULONG Length = 0;
4229 NTSTATUS Status;
4230
4231 Length = sizeof(SAM_GROUP_FIXED_DATA);
4232 Status = SampGetObjectAttribute(GroupObject,
4233 L"F",
4234 NULL,
4235 (PVOID)&FixedData,
4236 &Length);
4237 if (!NT_SUCCESS(Status))
4238 goto done;
4239
4240 FixedData.Attributes = Buffer->Attribute.Attributes;
4241
4242 Status = SampSetObjectAttribute(GroupObject,
4243 L"F",
4244 REG_BINARY,
4245 &FixedData,
4246 Length);
4247
4248 done:
4249 return Status;
4250 }
4251
4252
4253 /* Function 21 */
4254 NTSTATUS
4255 NTAPI
4256 SamrSetInformationGroup(IN SAMPR_HANDLE GroupHandle,
4257 IN GROUP_INFORMATION_CLASS GroupInformationClass,
4258 IN PSAMPR_GROUP_INFO_BUFFER Buffer)
4259 {
4260 PSAM_DB_OBJECT GroupObject;
4261 NTSTATUS Status;
4262
4263 TRACE("SamrSetInformationGroup(%p %lu %p)\n",
4264 GroupHandle, GroupInformationClass, Buffer);
4265
4266 RtlAcquireResourceExclusive(&SampResource,
4267 TRUE);
4268
4269 /* Validate the group handle */
4270 Status = SampValidateDbObject(GroupHandle,
4271 SamDbGroupObject,
4272 GROUP_WRITE_ACCOUNT,
4273 &GroupObject);
4274 if (!NT_SUCCESS(Status))
4275 goto done;
4276
4277 switch (GroupInformationClass)
4278 {
4279 case GroupNameInformation:
4280 Status = SampSetGroupName(GroupObject,
4281 Buffer);
4282 break;
4283
4284 case GroupAttributeInformation:
4285 Status = SampSetGroupAttribute(GroupObject,
4286 Buffer);
4287 break;
4288
4289 case GroupAdminCommentInformation:
4290 Status = SampSetObjectAttributeString(GroupObject,
4291 L"Description",
4292 &Buffer->AdminComment.AdminComment);
4293 break;
4294
4295 default:
4296 Status = STATUS_INVALID_INFO_CLASS;
4297 break;
4298 }
4299
4300 done:
4301 RtlReleaseResource(&SampResource);
4302
4303 return Status;
4304 }
4305
4306
4307 /* Function 22 */
4308 NTSTATUS
4309 NTAPI
4310 SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle,
4311 IN unsigned long MemberId,
4312 IN unsigned long Attributes)
4313 {
4314 PSAM_DB_OBJECT GroupObject;
4315 PSAM_DB_OBJECT UserObject = NULL;
4316 NTSTATUS Status;
4317
4318 TRACE("(%p %lu %lx)\n",
4319 GroupHandle, MemberId, Attributes);
4320
4321 RtlAcquireResourceExclusive(&SampResource,
4322 TRUE);
4323
4324 /* Validate the group handle */
4325 Status = SampValidateDbObject(GroupHandle,
4326 SamDbGroupObject,
4327 GROUP_ADD_MEMBER,
4328 &GroupObject);
4329 if (!NT_SUCCESS(Status))
4330 goto done;
4331
4332 /* Open the user object in the same domain */
4333 Status = SampOpenUserObject(GroupObject->ParentObject,
4334 MemberId,
4335 0,
4336 &UserObject);
4337 if (!NT_SUCCESS(Status))
4338 {
4339 TRACE("SampOpenUserObject() failed (Status 0x%08lx)\n", Status);
4340 goto done;
4341 }
4342
4343 /* Add group membership to the user object */
4344 Status = SampAddGroupMembershipToUser(UserObject,
4345 GroupObject->RelativeId,
4346 Attributes);
4347 if (!NT_SUCCESS(Status))
4348 {
4349 TRACE("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status);
4350 goto done;
4351 }
4352
4353 /* Add the member to the group object */
4354 Status = SampAddMemberToGroup(GroupObject,
4355 MemberId);
4356 if (!NT_SUCCESS(Status))
4357 {
4358 TRACE("SampAddMemberToGroup() failed (Status 0x%08lx)\n", Status);
4359 }
4360
4361 done:
4362 if (UserObject)
4363 SampCloseDbObject(UserObject);
4364
4365 RtlReleaseResource(&SampResource);
4366
4367 return Status;
4368 }
4369
4370
4371 /* Function 23 */
4372 NTSTATUS
4373 NTAPI
4374 SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
4375 {
4376 PSAM_DB_OBJECT GroupObject;
4377 ULONG Length = 0;
4378 NTSTATUS Status;
4379
4380 TRACE("(%p)\n", GroupHandle);
4381
4382 RtlAcquireResourceExclusive(&SampResource,
4383 TRUE);
4384
4385 /* Validate the group handle */
4386 Status = SampValidateDbObject(*GroupHandle,
4387 SamDbGroupObject,
4388 DELETE,
4389 &GroupObject);
4390 if (!NT_SUCCESS(Status))
4391 {
4392 TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status);
4393 goto done;
4394 }
4395
4396 /* Fail, if the group is built-in */
4397 if (GroupObject->RelativeId < 1000)
4398 {
4399 TRACE("You can not delete a special account!\n");
4400 Status = STATUS_SPECIAL_ACCOUNT;
4401 goto done;
4402 }
4403
4404 /* Get the length of the Members attribute */
4405 SampGetObjectAttribute(GroupObject,
4406 L"Members",
4407 NULL,
4408 NULL,
4409 &Length);
4410
4411 /* Fail, if the group has members */
4412 if (Length != 0)
4413 {
4414 TRACE("There are still members in the group!\n");
4415 Status = STATUS_MEMBER_IN_GROUP;
4416 goto done;
4417 }
4418
4419 /* FIXME: Remove the group from all aliases */
4420
4421 /* Delete the group from the database */
4422 Status = SampDeleteAccountDbObject(GroupObject);
4423 if (!NT_SUCCESS(Status))
4424 {
4425 TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status);
4426 goto done;
4427 }
4428
4429 /* Invalidate the handle */
4430 *GroupHandle = NULL;
4431
4432 done:
4433 RtlReleaseResource(&SampResource);
4434
4435 return Status;
4436 }
4437
4438
4439 /* Function 24 */
4440 NTSTATUS
4441 NTAPI
4442 SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle,
4443 IN unsigned long MemberId)
4444 {
4445 PSAM_DB_OBJECT GroupObject;
4446 PSAM_DB_OBJECT UserObject = NULL;
4447 NTSTATUS Status;
4448
4449 TRACE("(%p %lu)\n",
4450 GroupHandle, MemberId);
4451
4452 RtlAcquireResourceExclusive(&SampResource,
4453 TRUE);
4454
4455 /* Validate the group handle */
4456 Status = SampValidateDbObject(GroupHandle,
4457 SamDbGroupObject,
4458 GROUP_REMOVE_MEMBER,
4459 &GroupObject);
4460 if (!NT_SUCCESS(Status))
4461 goto done;
4462
4463 /* Open the user object in the same domain */
4464 Status = SampOpenUserObject(GroupObject->ParentObject,
4465 MemberId,
4466 0,
4467 &UserObject);
4468 if (!NT_SUCCESS(Status))
4469 {
4470 ERR("SampOpenUserObject() failed (Status 0x%08lx)\n", Status);
4471 goto done;
4472 }
4473
4474 /* Remove group membership from the user object */
4475 Status = SampRemoveGroupMembershipFromUser(UserObject,
4476 GroupObject->RelativeId);
4477 if (!NT_SUCCESS(Status))
4478 {
4479 ERR("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status);
4480 goto done;
4481 }
4482
4483 /* Remove the member from the group object */
4484 Status = SampRemoveMemberFromGroup(GroupObject,
4485 MemberId);
4486 if (!NT_SUCCESS(Status))
4487 {
4488 ERR("SampRemoveMemberFromGroup() failed (Status 0x%08lx)\n", Status);
4489 }
4490
4491 done:
4492 if (UserObject)
4493 SampCloseDbObject(UserObject);
4494
4495 RtlReleaseResource(&SampResource);
4496
4497 return Status;
4498 }
4499
4500
4501 /* Function 25 */
4502 NTSTATUS
4503 NTAPI
4504 SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle,
4505 OUT PSAMPR_GET_MEMBERS_BUFFER *Members)
4506 {
4507 PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL;
4508 PSAM_DB_OBJECT GroupObject;
4509 ULONG Length = 0;
4510 ULONG i;
4511 NTSTATUS Status;
4512
4513 RtlAcquireResourceShared(&SampResource,
4514 TRUE);
4515
4516 /* Validate the group handle */
4517 Status = SampValidateDbObject(GroupHandle,
4518 SamDbGroupObject,
4519 GROUP_LIST_MEMBERS,
4520 &GroupObject);
4521 if (!NT_SUCCESS(Status))
4522 goto done;
4523
4524 MembersBuffer = midl_user_allocate(sizeof(SAMPR_GET_MEMBERS_BUFFER));
4525 if (MembersBuffer == NULL)
4526 {
4527 Status = STATUS_INSUFFICIENT_RESOURCES;
4528 goto done;
4529 }
4530
4531 SampGetObjectAttribute(GroupObject,
4532 L"Members",
4533 NULL,
4534 NULL,
4535 &Length);
4536
4537 if (Length == 0)
4538 {
4539 MembersBuffer->MemberCount = 0;
4540 MembersBuffer->Members = NULL;
4541 MembersBuffer->Attributes = NULL;
4542
4543 *Members = MembersBuffer;
4544
4545 Status = STATUS_SUCCESS;
4546 goto done;
4547 }
4548
4549 MembersBuffer->Members = midl_user_allocate(Length);
4550 if (MembersBuffer->Members == NULL)
4551 {
4552 Status = STATUS_INSUFFICIENT_RESOURCES;
4553 goto done;
4554 }
4555
4556 MembersBuffer->Attributes = midl_user_allocate(Length);
4557 if (MembersBuffer->Attributes == NULL)
4558 {
4559 Status = STATUS_INSUFFICIENT_RESOURCES;
4560 goto done;
4561 }
4562
4563 Status = SampGetObjectAttribute(GroupObject,
4564 L"Members",
4565 NULL,
4566 MembersBuffer->Members,
4567 &Length);
4568 if (!NT_SUCCESS(Status))
4569 {
4570 TRACE("SampGetObjectAttributes() failed (Status 0x%08lx)\n", Status);
4571 goto done;
4572 }
4573
4574 MembersBuffer->MemberCount = Length / sizeof(ULONG);
4575
4576 for (i = 0; i < MembersBuffer->MemberCount; i++)
4577 {
4578 Status = SampGetUserGroupAttributes(GroupObject->ParentObject,
4579 MembersBuffer->Members[i],
4580 GroupObject->RelativeId,
4581 &(MembersBuffer->Attributes[i]));
4582 if (!NT_SUCCESS(Status))
4583 {
4584 TRACE("SampGetUserGroupAttributes() failed (Status 0x%08lx)\n", Status);
4585 goto done;
4586 }
4587 }
4588
4589 *Members = MembersBuffer;
4590
4591 done:
4592 if (!NT_SUCCESS(Status))
4593 {
4594 if (MembersBuffer != NULL)
4595 {
4596 if (MembersBuffer->Members != NULL)
4597 midl_user_free(MembersBuffer->Members);
4598
4599 if (MembersBuffer->Attributes != NULL)
4600 midl_user_free(MembersBuffer->Attributes);
4601
4602 midl_user_free(MembersBuffer);
4603 }
4604 }
4605
4606 RtlReleaseResource(&SampResource);
4607
4608 return Status;
4609 }
4610
4611
4612 /* Function 26 */
4613 NTSTATUS
4614 NTAPI
4615 SamrSetMemberAttributesOfGroup(IN SAMPR_HANDLE GroupHandle,
4616 IN unsigned long MemberId,
4617 IN unsigned long Attributes)
4618 {
4619 PSAM_DB_OBJECT GroupObject;
4620 NTSTATUS Status;
4621
4622 RtlAcquireResourceExclusive(&SampResource,
4623 TRUE);
4624
4625 /* Validate the group handle */
4626 Status = SampValidateDbObject(GroupHandle,
4627 SamDbGroupObject,
4628 GROUP_ADD_MEMBER,
4629 &GroupObject);
4630 if (!NT_SUCCESS(Status))
4631 {
4632 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
4633 goto done;
4634 }
4635
4636 Status = SampSetUserGroupAttributes(GroupObject->ParentObject,
4637 MemberId,
4638 GroupObject->RelativeId,
4639 Attributes);
4640 if (!NT_SUCCESS(Status))
4641 {
4642 TRACE("SampSetUserGroupAttributes failed with status 0x%08lx\n", Status);
4643 }
4644
4645 done:
4646 RtlReleaseResource(&SampResource);
4647
4648 return Status;
4649 }
4650
4651
4652 /* Function 27 */
4653 NTSTATUS
4654 NTAPI
4655 SamrOpenAlias(IN SAMPR_HANDLE DomainHandle,
4656 IN ACCESS_MASK DesiredAccess,
4657 IN ULONG AliasId,
4658 OUT SAMPR_HANDLE *AliasHandle)
4659 {
4660 PSAM_DB_OBJECT DomainObject;
4661 PSAM_DB_OBJECT AliasObject;
4662 WCHAR szRid[9];
4663 NTSTATUS Status;
4664
4665 TRACE("SamrOpenAlias(%p %lx %lx %p)\n",
4666 DomainHandle, DesiredAccess, AliasId, AliasHandle);
4667
4668 /* Map generic access rights */
4669 RtlMapGenericMask(&DesiredAccess,
4670 &AliasMapping);
4671
4672 RtlAcquireResourceShared(&SampResource,
4673 TRUE);
4674
4675 /* Validate the domain handle */
4676 Status = SampValidateDbObject(DomainHandle,
4677 SamDbDomainObject,
4678 DOMAIN_LOOKUP,
4679 &DomainObject);
4680 if (!NT_SUCCESS(Status))
4681 {
4682 TRACE("failed with status 0x%08lx\n", Status);
4683 goto done;
4684 }
4685
4686 /* Convert the RID into a string (hex) */
4687 swprintf(szRid, L"%08lX", AliasId);
4688
4689 /* Create the alias object */
4690 Status = SampOpenDbObject(DomainObject,
4691 L"Aliases",
4692 szRid,
4693 AliasId,
4694 SamDbAliasObject,
4695 DesiredAccess,
4696 &AliasObject);
4697 if (!NT_SUCCESS(Status))
4698 {
4699 TRACE("failed with status 0x%08lx\n", Status);
4700 goto done;
4701 }
4702
4703 *AliasHandle = (SAMPR_HANDLE)AliasObject;
4704
4705 done:
4706 RtlReleaseResource(&SampResource);
4707
4708 return Status;
4709 }
4710
4711
4712 static NTSTATUS
4713 SampQueryAliasGeneral(PSAM_DB_OBJECT AliasObject,
4714 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
4715 {
4716 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
4717 HANDLE MembersKeyHandle = NULL;
4718 NTSTATUS Status;
4719
4720 *Buffer = NULL;
4721
4722 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
4723 if (InfoBuffer == NULL)
4724 return STATUS_INSUFFICIENT_RESOURCES;
4725
4726 Status = SampGetObjectAttributeString(AliasObject,
4727 L"Name",
4728 &InfoBuffer->General.Name);
4729 if (!NT_SUCCESS(Status))
4730 {
4731 TRACE("Status 0x%08lx\n", Status);
4732 goto done;
4733 }
4734
4735 Status = SampGetObjectAttributeString(AliasObject,
4736 L"Description",
4737 &InfoBuffer->General.AdminComment);
4738 if (!NT_SUCCESS(Status))
4739 {
4740 TRACE("Status 0x%08lx\n", Status);
4741 goto done;
4742 }
4743
4744 /* Open the Members subkey */
4745 Status = SampRegOpenKey(AliasObject->KeyHandle,
4746 L"Members",
4747 KEY_READ,
4748 &MembersKeyHandle);
4749 if (NT_SUCCESS(Status))
4750 {
4751 /* Retrieve the number of members of the alias */
4752 Status = SampRegQueryKeyInfo(MembersKeyHandle,
4753 NULL,
4754 &InfoBuffer->General.MemberCount);
4755 if (!NT_SUCCESS(Status))
4756 {
4757 TRACE("Status 0x%08lx\n", Status);
4758 goto done;
4759 }
4760 }
4761 else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
4762 {
4763 InfoBuffer->General.MemberCount = 0;
4764 Status = STATUS_SUCCESS;
4765 }
4766 else
4767 {
4768 TRACE("Status 0x%08lx\n", Status);
4769 goto done;
4770 }
4771
4772 *Buffer = InfoBuffer;
4773
4774 done:
4775 SampRegCloseKey(&MembersKeyHandle);
4776
4777 if (!NT_SUCCESS(Status))
4778 {
4779 if (InfoBuffer != NULL)
4780 {
4781 if (InfoBuffer->General.Name.Buffer != NULL)
4782 midl_user_free(InfoBuffer->General.Name.Buffer);
4783
4784 if (InfoBuffer->General.AdminComment.Buffer != NULL)
4785 midl_user_free(InfoBuffer->General.AdminComment.Buffer);
4786
4787 midl_user_free(InfoBuffer);
4788 }
4789 }
4790
4791 return Status;
4792 }
4793
4794
4795 static NTSTATUS
4796 SampQueryAliasName(PSAM_DB_OBJECT AliasObject,
4797 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
4798 {
4799 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
4800 NTSTATUS Status;
4801
4802 *Buffer = NULL;
4803
4804 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
4805 if (InfoBuffer == NULL)
4806 return STATUS_INSUFFICIENT_RESOURCES;
4807
4808 Status = SampGetObjectAttributeString(AliasObject,
4809 L"Name",
4810 &InfoBuffer->Name.Name);
4811 if (!NT_SUCCESS(Status))
4812 {
4813 TRACE("Status 0x%08lx\n", Status);
4814 goto done;
4815 }
4816
4817 *Buffer = InfoBuffer;
4818
4819 done:
4820 if (!NT_SUCCESS(Status))
4821 {
4822 if (InfoBuffer != NULL)
4823 {
4824 if (InfoBuffer->Name.Name.Buffer != NULL)
4825 midl_user_free(InfoBuffer->Name.Name.Buffer);
4826
4827 midl_user_free(InfoBuffer);
4828 }
4829 }
4830
4831 return Status;
4832 }
4833
4834
4835 static NTSTATUS
4836 SampQueryAliasAdminComment(PSAM_DB_OBJECT AliasObject,
4837 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
4838 {
4839 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
4840 NTSTATUS Status;
4841
4842 *Buffer = NULL;
4843
4844 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
4845 if (InfoBuffer == NULL)
4846 return STATUS_INSUFFICIENT_RESOURCES;
4847
4848 Status = SampGetObjectAttributeString(AliasObject,
4849 L"Description",
4850 &InfoBuffer->AdminComment.AdminComment);
4851 if (!NT_SUCCESS(Status))
4852 {
4853 TRACE("Status 0x%08lx\n", Status);
4854 goto done;
4855 }
4856
4857 *Buffer = InfoBuffer;
4858
4859 done:
4860 if (!NT_SUCCESS(Status))
4861 {
4862 if (InfoBuffer != NULL)
4863 {
4864 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
4865 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
4866
4867 midl_user_free(InfoBuffer);
4868 }
4869 }
4870
4871 return Status;
4872 }
4873
4874
4875 /* Function 28 */
4876 NTSTATUS
4877 NTAPI
4878 SamrQueryInformationAlias(IN SAMPR_HANDLE AliasHandle,
4879 IN ALIAS_INFORMATION_CLASS AliasInformationClass,
4880 OUT PSAMPR_ALIAS_INFO_BUFFER *Buffer)
4881 {
4882 PSAM_DB_OBJECT AliasObject;
4883 NTSTATUS Status;
4884
4885 TRACE("SamrQueryInformationAlias(%p %lu %p)\n",
4886 AliasHandle, AliasInformationClass, Buffer);
4887
4888 RtlAcquireResourceShared(&SampResource,
4889 TRUE);
4890
4891 /* Validate the alias handle */
4892 Status = SampValidateDbObject(AliasHandle,
4893 SamDbAliasObject,
4894 ALIAS_READ_INFORMATION,
4895 &AliasObject);
4896 if (!NT_SUCCESS(Status))
4897 goto done;
4898
4899 switch (AliasInformationClass)
4900 {
4901 case AliasGeneralInformation:
4902 Status = SampQueryAliasGeneral(AliasObject,
4903 Buffer);
4904 break;
4905
4906 case AliasNameInformation:
4907 Status = SampQueryAliasName(AliasObject,
4908 Buffer);
4909 break;
4910
4911 case AliasAdminCommentInformation:
4912 Status = SampQueryAliasAdminComment(AliasObject,
4913 Buffer);
4914 break;
4915
4916 default:
4917 Status = STATUS_INVALID_INFO_CLASS;
4918 break;
4919 }
4920
4921 done:
4922 RtlReleaseResource(&SampResource);
4923
4924 return Status;
4925 }
4926
4927
4928 static NTSTATUS
4929 SampSetAliasName(PSAM_DB_OBJECT AliasObject,
4930 PSAMPR_ALIAS_INFO_BUFFER Buffer)
4931 {
4932 UNICODE_STRING OldAliasName = {0, 0, NULL};
4933 UNICODE_STRING NewAliasName;
4934 NTSTATUS Status;
4935
4936 Status = SampGetObjectAttributeString(AliasObject,
4937 L"Name",
4938 (PRPC_UNICODE_STRING)&OldAliasName);
4939 if (!NT_SUCCESS(Status))
4940 {
4941 TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status);
4942 goto done;
4943 }
4944
4945 /* Check the new account name */
4946 Status = SampCheckAccountName(&Buffer->Name.Name, 256);
4947 if (!NT_SUCCESS(Status))
4948 {
4949 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
4950 return Status;
4951 }
4952
4953 NewAliasName.Length = Buffer->Name.Name.Length;
4954 NewAliasName.MaximumLength = Buffer->Name.Name.MaximumLength;
4955 NewAliasName.Buffer = Buffer->Name.Name.Buffer;
4956
4957 if (!RtlEqualUnicodeString(&OldAliasName, &NewAliasName, TRUE))
4958 {
4959 Status = SampCheckAccountNameInDomain(AliasObject->ParentObject,
4960 NewAliasName.Buffer);
4961 if (!NT_SUCCESS(Status))
4962 {
4963 TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n",
4964 NewAliasName.Buffer, Status);
4965 goto done;
4966 }
4967 }
4968
4969 Status = SampSetAccountNameInDomain(AliasObject->ParentObject,
4970 L"Aliases",
4971 NewAliasName.Buffer,
4972 AliasObject->RelativeId);
4973 if (!NT_SUCCESS(Status))
4974 {
4975 TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status);
4976 goto done;
4977 }
4978
4979 Status = SampRemoveAccountNameFromDomain(AliasObject->ParentObject,
4980 L"Aliases",
4981 OldAliasName.Buffer);
4982 if (!NT_SUCCESS(Status))
4983 {
4984 TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status);
4985 goto done;
4986 }
4987
4988 Status = SampSetObjectAttributeString(AliasObject,
4989 L"Name",
4990 (PRPC_UNICODE_STRING)&NewAliasName);
4991 if (!NT_SUCCESS(Status))
4992 {
4993 TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
4994 }
4995
4996 done:
4997 if (OldAliasName.Buffer != NULL)
4998 midl_user_free(OldAliasName.Buffer);
4999
5000 return Status;
5001 }
5002
5003
5004 /* Function 29 */
5005 NTSTATUS
5006 NTAPI
5007 SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle,
5008 IN ALIAS_INFORMATION_CLASS AliasInformationClass,
5009 IN PSAMPR_ALIAS_INFO_BUFFER Buffer)
5010 {
5011 PSAM_DB_OBJECT AliasObject;
5012 NTSTATUS Status;
5013
5014 TRACE("SamrSetInformationAlias(%p %lu %p)\n",
5015 AliasHandle, AliasInformationClass, Buffer);
5016
5017 RtlAcquireResourceExclusive(&SampResource,
5018 TRUE);
5019
5020 /* Validate the alias handle */
5021 Status = SampValidateDbObject(AliasHandle,
5022 SamDbAliasObject,
5023 ALIAS_WRITE_ACCOUNT,
5024 &AliasObject);
5025 if (!NT_SUCCESS(Status))
5026 goto done;
5027
5028 switch (AliasInformationClass)
5029 {
5030 case AliasNameInformation:
5031 Status = SampSetAliasName(AliasObject,
5032 Buffer);
5033 break;
5034
5035 case AliasAdminCommentInformation:
5036 Status = SampSetObjectAttributeString(AliasObject,
5037 L"Description",
5038 &Buffer->AdminComment.AdminComment);
5039 break;
5040
5041 default:
5042 Status = STATUS_INVALID_INFO_CLASS;
5043 break;
5044 }
5045
5046 done:
5047 RtlReleaseResource(&SampResource);
5048
5049 return Status;
5050 }
5051
5052
5053 /* Function 30 */
5054 NTSTATUS
5055 NTAPI
5056 SamrDeleteAlias(IN OUT SAMPR_HANDLE *AliasHandle)
5057 {
5058 PSAM_DB_OBJECT AliasObject;
5059 NTSTATUS Status;
5060
5061 RtlAcquireResourceExclusive(&SampResource,
5062 TRUE);
5063
5064 /* Validate the alias handle */
5065 Status = SampValidateDbObject(*AliasHandle,
5066 SamDbAliasObject,
5067 DELETE,
5068 &AliasObject);
5069 if (!NT_SUCCESS(Status))
5070 {
5071 TRACE("SampValidateDbObject failed (Status 0x%08lx)\n", Status);
5072 goto done;
5073 }
5074
5075 /* Fail, if the alias is built-in */
5076 if (AliasObject->RelativeId < 1000)
5077 {
5078 TRACE("You can not delete a special account!\n");
5079 Status = STATUS_SPECIAL_ACCOUNT;
5080 goto done;
5081 }
5082
5083 /* Remove all members from the alias */
5084 Status = SampRemoveAllMembersFromAlias(AliasObject);
5085 if (!NT_SUCCESS(Status))
5086 {
5087 TRACE("SampRemoveAllMembersFromAlias() failed (Status 0x%08lx)\n", Status);
5088 goto done;
5089 }
5090
5091 /* Delete the alias from the database */
5092 Status = SampDeleteAccountDbObject(AliasObject);
5093 if (!NT_SUCCESS(Status))
5094 {
5095 TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status);
5096 goto done;
5097 }
5098
5099 /* Invalidate the handle */
5100 *AliasHandle = NULL;
5101
5102 done:
5103 RtlReleaseResource(&SampResource);
5104
5105 return Status;
5106 }
5107
5108
5109 /* Function 31 */
5110 NTSTATUS
5111 NTAPI
5112 SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
5113 IN PRPC_SID MemberId)
5114 {
5115 PSAM_DB_OBJECT AliasObject;
5116 NTSTATUS Status;
5117
5118 TRACE("(%p %p)\n", AliasHandle, MemberId);
5119
5120 RtlAcquireResourceExclusive(&SampResource,
5121 TRUE);
5122
5123 /* Validate the alias handle */
5124 Status = SampValidateDbObject(AliasHandle,
5125 SamDbAliasObject,
5126 ALIAS_ADD_MEMBER,
5127 &AliasObject);
5128 if (!NT_SUCCESS(Status))
5129 {
5130 TRACE("failed with status 0x%08lx\n", Status);
5131 goto done;
5132 }
5133
5134 Status = SampAddMemberToAlias(AliasObject,
5135 MemberId);
5136 if (!NT_SUCCESS(Status))
5137 {
5138 TRACE("failed with status 0x%08lx\n", Status);
5139 }
5140
5141 done:
5142 RtlReleaseResource(&SampResource);
5143
5144 return Status;
5145 }
5146
5147
5148 /* Function 32 */
5149 NTSTATUS
5150 NTAPI
5151 SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle,
5152 IN PRPC_SID MemberId)
5153 {
5154 PSAM_DB_OBJECT AliasObject;
5155 NTSTATUS Status;
5156
5157 TRACE("(%p %p)\n", AliasHandle, MemberId);
5158
5159 RtlAcquireResourceExclusive(&SampResource,
5160 TRUE);
5161
5162 /* Validate the alias handle */
5163 Status = SampValidateDbObject(AliasHandle,
5164 SamDbAliasObject,
5165 ALIAS_REMOVE_MEMBER,
5166 &AliasObject);
5167 if (!NT_SUCCESS(Status))
5168 {
5169 TRACE("failed with status 0x%08lx\n", Status);
5170 goto done;
5171 }
5172
5173 Status = SampRemoveMemberFromAlias(AliasObject,
5174 MemberId);
5175 if (!NT_SUCCESS(Status))
5176 {
5177 TRACE("failed with status 0x%08lx\n", Status);
5178 }
5179
5180 done:
5181 RtlReleaseResource(&SampResource);
5182
5183 return Status;
5184 }
5185
5186
5187 /* Function 33 */
5188 NTSTATUS
5189 NTAPI
5190 SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
5191 OUT PSAMPR_PSID_ARRAY_OUT Members)
5192 {
5193 PSAM_DB_OBJECT AliasObject;
5194 PSAMPR_SID_INFORMATION MemberArray = NULL;
5195 ULONG MemberCount = 0;
5196 ULONG Index;
5197 NTSTATUS Status;
5198
5199 TRACE("SamrGetMembersInAlias(%p %p %p)\n",
5200 AliasHandle, Members);
5201
5202 RtlAcquireResourceShared(&SampResource,
5203 TRUE);
5204
5205 /* Validate the alias handle */
5206 Status = SampValidateDbObject(AliasHandle,
5207 SamDbAliasObject,
5208 ALIAS_LIST_MEMBERS,
5209 &AliasObject);
5210 if (!NT_SUCCESS(Status))
5211 {
5212 ERR("failed with status 0x%08lx\n", Status);
5213 goto done;
5214 }
5215
5216 Status = SampGetMembersInAlias(AliasObject,
5217 &MemberCount,
5218 &MemberArray);
5219
5220 /* Return the number of members and the member array */
5221 if (NT_SUCCESS(Status))
5222 {
5223 Members->Count = MemberCount;
5224 Members->Sids = MemberArray;
5225 }
5226
5227 done:
5228 /* Clean up the members array and the SID buffers if something failed */
5229 if (!NT_SUCCESS(Status))
5230 {
5231 if (MemberArray != NULL)
5232 {
5233 for (Index = 0; Index < MemberCount; Index++)
5234 {
5235 if (MemberArray[Index].SidPointer != NULL)
5236 midl_user_free(MemberArray[Index].SidPointer);
5237 }
5238
5239 midl_user_free(MemberArray);
5240 }
5241 }
5242
5243 RtlReleaseResource(&SampResource);
5244
5245 return Status;
5246 }
5247
5248
5249 /* Function 34 */
5250 NTSTATUS
5251 NTAPI
5252 SamrOpenUser(IN SAMPR_HANDLE DomainHandle,
5253 IN ACCESS_MASK DesiredAccess,
5254 IN unsigned long UserId,
5255 OUT SAMPR_HANDLE *UserHandle)
5256 {
5257 PSAM_DB_OBJECT DomainObject;
5258 PSAM_DB_OBJECT UserObject;
5259 WCHAR szRid[9];
5260 NTSTATUS Status;
5261
5262 TRACE("SamrOpenUser(%p %lx %lx %p)\n",
5263 DomainHandle, DesiredAccess, UserId, UserHandle);
5264
5265 /* Map generic access rights */
5266 RtlMapGenericMask(&DesiredAccess,
5267 &UserMapping);
5268
5269 RtlAcquireResourceShared(&SampResource,
5270 TRUE);
5271
5272 /* Validate the domain handle */
5273 Status = SampValidateDbObject(DomainHandle,
5274 SamDbDomainObject,
5275 DOMAIN_LOOKUP,
5276 &DomainObject);
5277 if (!NT_SUCCESS(Status))
5278 {
5279 TRACE("failed with status 0x%08lx\n", Status);
5280 goto done;
5281 }
5282
5283 /* Convert the RID into a string (hex) */
5284 swprintf(szRid, L"%08lX", UserId);
5285
5286 /* Create the user object */
5287 Status = SampOpenDbObject(DomainObject,
5288 L"Users",
5289 szRid,
5290 UserId,
5291 SamDbUserObject,
5292 DesiredAccess,
5293 &UserObject);
5294 if (!NT_SUCCESS(Status))
5295 {
5296 TRACE("failed with status 0x%08lx\n", Status);
5297 goto done;
5298 }
5299
5300 *UserHandle = (SAMPR_HANDLE)UserObject;
5301
5302 done:
5303 RtlReleaseResource(&SampResource);
5304
5305 return Status;
5306 }
5307
5308
5309 /* Function 35 */
5310 NTSTATUS
5311 NTAPI
5312 SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle)
5313 {
5314 PSAM_DB_OBJECT UserObject;
5315 NTSTATUS Status;
5316
5317 TRACE("(%p)\n", UserHandle);
5318
5319 RtlAcquireResourceExclusive(&SampResource,
5320 TRUE);
5321
5322 /* Validate the user handle */
5323 Status = SampValidateDbObject(*UserHandle,
5324 SamDbUserObject,
5325 DELETE,
5326 &UserObject);
5327 if (!NT_SUCCESS(Status))
5328 {
5329 TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status);
5330 goto done;
5331 }
5332
5333 /* Fail, if the user is built-in */
5334 if (UserObject->RelativeId < 1000)
5335 {
5336 TRACE("You can not delete a special account!\n");
5337 Status = STATUS_SPECIAL_ACCOUNT;
5338 goto done;
5339 }
5340
5341 /* FIXME: Remove the user from all groups */
5342
5343 /* FIXME: Remove the user from all aliases */
5344
5345 /* Delete the user from the database */
5346 Status = SampDeleteAccountDbObject(UserObject);
5347 if (!NT_SUCCESS(Status))
5348 {
5349 TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status);
5350 goto done;
5351 }
5352
5353 /* Invalidate the handle */
5354 *UserHandle = NULL;
5355
5356 done:
5357 RtlReleaseResource(&SampResource);
5358
5359 return Status;
5360 }
5361
5362
5363 static
5364 NTSTATUS
5365 SampQueryUserGeneral(PSAM_DB_OBJECT UserObject,
5366 PSAMPR_USER_INFO_BUFFER *Buffer)
5367 {
5368 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5369 SAM_USER_FIXED_DATA FixedData;
5370 ULONG Length = 0;
5371 NTSTATUS Status;
5372
5373 *Buffer = NULL;
5374
5375 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5376 if (InfoBuffer == NULL)
5377 return STATUS_INSUFFICIENT_RESOURCES;
5378
5379 Length = sizeof(SAM_USER_FIXED_DATA);
5380 Status = SampGetObjectAttribute(UserObject,
5381 L"F",
5382 NULL,
5383 (PVOID)&FixedData,
5384 &Length);
5385 if (!NT_SUCCESS(Status))
5386 goto done;
5387
5388 InfoBuffer->General.PrimaryGroupId = FixedData.PrimaryGroupId;
5389
5390 /* Get the Name string */
5391 Status = SampGetObjectAttributeString(UserObject,
5392 L"Name",
5393 &InfoBuffer->General.UserName);
5394 if (!NT_SUCCESS(Status))
5395 {
5396 TRACE("Status 0x%08lx\n", Status);
5397 goto done;
5398 }
5399
5400 /* Get the FullName string */
5401 Status = SampGetObjectAttributeString(UserObject,
5402 L"FullName",
5403 &InfoBuffer->General.FullName);
5404 if (!NT_SUCCESS(Status))
5405 {
5406 TRACE("Status 0x%08lx\n", Status);
5407 goto done;
5408 }
5409
5410 /* Get the AdminComment string */
5411 Status = SampGetObjectAttributeString(UserObject,
5412 L"AdminComment",
5413 &InfoBuffer->General.AdminComment);
5414 if (!NT_SUCCESS(Status))
5415 {
5416 TRACE("Status 0x%08lx\n", Status);
5417 goto done;
5418 }
5419
5420 /* Get the UserComment string */
5421 Status = SampGetObjectAttributeString(UserObject,
5422 L"UserComment",
5423 &InfoBuffer->General.UserComment);
5424 if (!NT_SUCCESS(Status))
5425 {
5426 TRACE("Status 0x%08lx\n", Status);
5427 goto done;
5428 }
5429
5430 *Buffer = InfoBuffer;
5431
5432 done:
5433 if (!NT_SUCCESS(Status))
5434 {
5435 if (InfoBuffer != NULL)
5436 {
5437 if (InfoBuffer->General.UserName.Buffer != NULL)
5438 midl_user_free(InfoBuffer->General.UserName.Buffer);
5439
5440 if (InfoBuffer->General.FullName.Buffer != NULL)
5441 midl_user_free(InfoBuffer->General.FullName.Buffer);
5442
5443 if (InfoBuffer->General.AdminComment.Buffer != NULL)
5444 midl_user_free(InfoBuffer->General.AdminComment.Buffer);
5445
5446 if (InfoBuffer->General.UserComment.Buffer != NULL)
5447 midl_user_free(InfoBuffer->General.UserComment.Buffer);
5448
5449 midl_user_free(InfoBuffer);
5450 }
5451 }
5452
5453 return Status;
5454 }
5455
5456
5457 static
5458 NTSTATUS
5459 SampQueryUserPreferences(PSAM_DB_OBJECT UserObject,
5460 PSAMPR_USER_INFO_BUFFER *Buffer)
5461 {
5462 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5463 SAM_USER_FIXED_DATA FixedData;
5464 ULONG Length = 0;
5465 NTSTATUS Status;
5466
5467 *Buffer = NULL;
5468
5469 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5470 if (InfoBuffer == NULL)
5471 return STATUS_INSUFFICIENT_RESOURCES;
5472
5473 Length = sizeof(SAM_USER_FIXED_DATA);
5474 Status = SampGetObjectAttribute(UserObject,
5475 L"F",
5476 NULL,
5477 (PVOID)&FixedData,
5478 &Length);
5479 if (!NT_SUCCESS(Status))
5480 goto done;
5481
5482 InfoBuffer->Preferences.CountryCode = FixedData.CountryCode;
5483 InfoBuffer->Preferences.CodePage = FixedData.CodePage;
5484
5485 /* Get the UserComment string */
5486 Status = SampGetObjectAttributeString(UserObject,
5487 L"UserComment",
5488 &InfoBuffer->Preferences.UserComment);
5489 if (!NT_SUCCESS(Status))
5490 {
5491 TRACE("Status 0x%08lx\n", Status);
5492 goto done;
5493 }
5494
5495 *Buffer = InfoBuffer;
5496
5497 done:
5498 if (!NT_SUCCESS(Status))
5499 {
5500 if (InfoBuffer != NULL)
5501 {
5502 if (InfoBuffer->Preferences.UserComment.Buffer != NULL)
5503 midl_user_free(InfoBuffer->Preferences.UserComment.Buffer);
5504
5505 midl_user_free(InfoBuffer);
5506 }
5507 }
5508
5509 return Status;
5510 }
5511
5512
5513 static
5514 NTSTATUS
5515 SampQueryUserLogon(PSAM_DB_OBJECT UserObject,
5516 PSAMPR_USER_INFO_BUFFER *Buffer)
5517 {
5518 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5519 SAM_DOMAIN_FIXED_DATA DomainFixedData;
5520 SAM_USER_FIXED_DATA FixedData;
5521 LARGE_INTEGER PasswordCanChange;
5522 LARGE_INTEGER PasswordMustChange;
5523 ULONG Length = 0;
5524 NTSTATUS Status;
5525
5526 *Buffer = NULL;
5527
5528 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5529 if (InfoBuffer == NULL)
5530 return STATUS_INSUFFICIENT_RESOURCES;
5531
5532 /* Get the fixed size domain data */
5533 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
5534 Status = SampGetObjectAttribute(UserObject->ParentObject,
5535 L"F",
5536 NULL,
5537 (PVOID)&DomainFixedData,
5538 &Length);
5539 if (!NT_SUCCESS(Status))
5540 goto done;
5541
5542 /* Get the fixed size user data */
5543 Length = sizeof(SAM_USER_FIXED_DATA);
5544 Status = SampGetObjectAttribute(UserObject,
5545 L"F",
5546 NULL,
5547 (PVOID)&FixedData,
5548 &Length);
5549 if (!NT_SUCCESS(Status))
5550 goto done;
5551
5552 InfoBuffer->Logon.UserId = FixedData.UserId;
5553 InfoBuffer->Logon.PrimaryGroupId = FixedData.PrimaryGroupId;
5554 InfoBuffer->Logon.LastLogon.LowPart = FixedData.LastLogon.LowPart;
5555 InfoBuffer->Logon.LastLogon.HighPart = FixedData.LastLogon.HighPart;
5556 InfoBuffer->Logon.LastLogoff.LowPart = FixedData.LastLogoff.LowPart;
5557 InfoBuffer->Logon.LastLogoff.HighPart = FixedData.LastLogoff.HighPart;
5558 InfoBuffer->Logon.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart;
5559 InfoBuffer->Logon.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart;
5560 InfoBuffer->Logon.BadPasswordCount = FixedData.BadPasswordCount;
5561 InfoBuffer->Logon.LogonCount = FixedData.LogonCount;
5562 InfoBuffer->Logon.UserAccountControl = FixedData.UserAccountControl;
5563
5564 PasswordCanChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet,
5565 DomainFixedData.MinPasswordAge);
5566 InfoBuffer->Logon.PasswordCanChange.LowPart = PasswordCanChange.LowPart;
5567 InfoBuffer->Logon.PasswordCanChange.HighPart = PasswordCanChange.HighPart;
5568
5569 PasswordMustChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet,
5570 DomainFixedData.MaxPasswordAge);
5571 InfoBuffer->Logon.PasswordMustChange.LowPart = PasswordMustChange.LowPart;
5572 InfoBuffer->Logon.PasswordMustChange.HighPart = PasswordMustChange.HighPart;
5573
5574 /* Get the Name string */
5575 Status = SampGetObjectAttributeString(UserObject,
5576 L"Name",
5577 &InfoBuffer->Logon.UserName);
5578 if (!NT_SUCCESS(Status))
5579 {
5580 TRACE("Status 0x%08lx\n", Status);
5581 goto done;
5582 }
5583
5584 /* Get the FullName string */
5585 Status = SampGetObjectAttributeString(UserObject,
5586 L"FullName",
5587 &InfoBuffer->Logon.FullName);
5588 if (!NT_SUCCESS(Status))
5589 {
5590 TRACE("Status 0x%08lx\n", Status);
5591 goto done;
5592 }
5593
5594 /* Get the HomeDirectory string */
5595 Status = SampGetObjectAttributeString(UserObject,
5596 L"HomeDirectory",
5597 &InfoBuffer->Logon.HomeDirectory);
5598 if (!NT_SUCCESS(Status))
5599 {
5600 TRACE("Status 0x%08lx\n", Status);
5601 goto done;
5602 }
5603
5604 /* Get the HomeDirectoryDrive string */
5605 Status = SampGetObjectAttributeString(UserObject,
5606 L"HomeDirectoryDrive",
5607 &InfoBuffer->Logon.HomeDirectoryDrive);
5608 if (!NT_SUCCESS(Status))
5609 {
5610 TRACE("Status 0x%08lx\n", Status);
5611 goto done;
5612 }
5613
5614 /* Get the ScriptPath string */
5615 Status = SampGetObjectAttributeString(UserObject,
5616 L"ScriptPath",
5617 &InfoBuffer->Logon.ScriptPath);
5618 if (!NT_SUCCESS(Status))
5619 {
5620 TRACE("Status 0x%08lx\n", Status);
5621 goto done;
5622 }
5623
5624 /* Get the ProfilePath string */
5625 Status = SampGetObjectAttributeString(UserObject,
5626 L"ProfilePath",
5627 &InfoBuffer->Logon.ProfilePath);
5628 if (!NT_SUCCESS(Status))
5629 {
5630 TRACE("Status 0x%08lx\n", Status);
5631 goto done;
5632 }
5633
5634 /* Get the WorkStations string */
5635 Status = SampGetObjectAttributeString(UserObject,
5636 L"WorkStations",
5637 &InfoBuffer->Logon.WorkStations);
5638 if (!NT_SUCCESS(Status))
5639 {
5640 TRACE("Status 0x%08lx\n", Status);
5641 goto done;
5642 }
5643
5644 /* Get the LogonHours attribute */
5645 Status = SampGetLogonHoursAttrbute(UserObject,
5646 &InfoBuffer->Logon.LogonHours);
5647 if (!NT_SUCCESS(Status))
5648 {
5649 TRACE("Status 0x%08lx\n", Status);
5650 goto done;
5651 }
5652
5653 *Buffer = InfoBuffer;
5654
5655 done:
5656 if (!NT_SUCCESS(Status))
5657 {
5658 if (InfoBuffer != NULL)
5659 {
5660 if (InfoBuffer->Logon.UserName.Buffer != NULL)
5661 midl_user_free(InfoBuffer->Logon.UserName.Buffer);
5662
5663 if (InfoBuffer->Logon.FullName.Buffer != NULL)
5664 midl_user_free(InfoBuffer->Logon.FullName.Buffer);
5665
5666 if (InfoBuffer->Logon.HomeDirectory.Buffer != NULL)
5667 midl_user_free(InfoBuffer->Logon.HomeDirectory.Buffer);
5668
5669 if (InfoBuffer->Logon.HomeDirectoryDrive.Buffer != NULL)
5670 midl_user_free(InfoBuffer->Logon.HomeDirectoryDrive.Buffer);
5671
5672 if (InfoBuffer->Logon.ScriptPath.Buffer != NULL)
5673 midl_user_free(InfoBuffer->Logon.ScriptPath.Buffer);
5674
5675 if (InfoBuffer->Logon.ProfilePath.Buffer != NULL)
5676 midl_user_free(InfoBuffer->Logon.ProfilePath.Buffer);
5677
5678 if (InfoBuffer->Logon.WorkStations.Buffer != NULL)
5679 midl_user_free(InfoBuffer->Logon.WorkStations.Buffer);
5680
5681 if (InfoBuffer->Logon.LogonHours.LogonHours != NULL)
5682 midl_user_free(InfoBuffer->Logon.LogonHours.LogonHours);
5683
5684 midl_user_free(InfoBuffer);
5685 }
5686 }
5687
5688 return Status;
5689 }
5690
5691
5692 static
5693 NTSTATUS
5694 SampQueryUserAccount(PSAM_DB_OBJECT UserObject,
5695 PSAMPR_USER_INFO_BUFFER *Buffer)
5696 {
5697 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5698 SAM_USER_FIXED_DATA FixedData;
5699 ULONG Length = 0;
5700 NTSTATUS Status;
5701
5702 *Buffer = NULL;
5703
5704 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5705 if (InfoBuffer == NULL)
5706 return STATUS_INSUFFICIENT_RESOURCES;
5707
5708 Length = sizeof(SAM_USER_FIXED_DATA);
5709 Status = SampGetObjectAttribute(UserObject,
5710 L"F",
5711 NULL,
5712 (PVOID)&FixedData,
5713 &Length);
5714 if (!NT_SUCCESS(Status))
5715 goto done;
5716
5717 InfoBuffer->Account.UserId = FixedData.UserId;
5718 InfoBuffer->Account.PrimaryGroupId = FixedData.PrimaryGroupId;
5719 InfoBuffer->Account.LastLogon.LowPart = FixedData.LastLogon.LowPart;
5720 InfoBuffer->Account.LastLogon.HighPart = FixedData.LastLogon.HighPart;
5721 InfoBuffer->Account.LastLogoff.LowPart = FixedData.LastLogoff.LowPart;
5722 InfoBuffer->Account.LastLogoff.HighPart = FixedData.LastLogoff.HighPart;
5723 InfoBuffer->Account.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart;
5724 InfoBuffer->Account.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart;
5725 InfoBuffer->Account.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
5726 InfoBuffer->Account.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
5727 InfoBuffer->Account.BadPasswordCount = FixedData.BadPasswordCount;
5728 InfoBuffer->Account.LogonCount = FixedData.LogonCount;
5729 InfoBuffer->Account.UserAccountControl = FixedData.UserAccountControl;
5730
5731 /* Get the Name string */
5732 Status = SampGetObjectAttributeString(UserObject,
5733 L"Name",
5734 &InfoBuffer->Account.UserName);
5735 if (!NT_SUCCESS(Status))
5736 {
5737 TRACE("Status 0x%08lx\n", Status);
5738 goto done;
5739 }
5740
5741 /* Get the FullName string */
5742 Status = SampGetObjectAttributeString(UserObject,
5743 L"FullName",
5744 &InfoBuffer->Account.FullName);
5745 if (!NT_SUCCESS(Status))
5746 {
5747 TRACE("Status 0x%08lx\n", Status);
5748 goto done;
5749 }
5750
5751 /* Get the HomeDirectory string */
5752 Status = SampGetObjectAttributeString(UserObject,
5753 L"HomeDirectory",
5754 &InfoBuffer->Account.HomeDirectory);
5755 if (!NT_SUCCESS(Status))
5756 {
5757 TRACE("Status 0x%08lx\n", Status);
5758 goto done;
5759 }
5760
5761 /* Get the HomeDirectoryDrive string */
5762 Status = SampGetObjectAttributeString(UserObject,
5763 L"HomeDirectoryDrive",
5764 &InfoBuffer->Account.HomeDirectoryDrive);
5765 if (!NT_SUCCESS(Status))
5766 {
5767 TRACE("Status 0x%08lx\n", Status);
5768 goto done;
5769 }
5770
5771 /* Get the ScriptPath string */
5772 Status = SampGetObjectAttributeString(UserObject,
5773 L"ScriptPath",
5774 &InfoBuffer->Account.ScriptPath);
5775 if (!NT_SUCCESS(Status))
5776 {
5777 TRACE("Status 0x%08lx\n", Status);
5778 goto done;
5779 }
5780
5781 /* Get the ProfilePath string */
5782 Status = SampGetObjectAttributeString(UserObject,
5783 L"ProfilePath",
5784 &InfoBuffer->Account.ProfilePath);
5785 if (!NT_SUCCESS(Status))
5786 {
5787 TRACE("Status 0x%08lx\n", Status);
5788 goto done;
5789 }
5790
5791 /* Get the AdminComment string */
5792 Status = SampGetObjectAttributeString(UserObject,
5793 L"AdminComment",
5794 &InfoBuffer->Account.AdminComment);
5795 if (!NT_SUCCESS(Status))
5796 {
5797 TRACE("Status 0x%08lx\n", Status);
5798 goto done;
5799 }
5800
5801 /* Get the WorkStations string */
5802 Status = SampGetObjectAttributeString(UserObject,
5803 L"WorkStations",
5804 &InfoBuffer->Account.WorkStations);
5805 if (!NT_SUCCESS(Status))
5806 {
5807 TRACE("Status 0x%08lx\n", Status);
5808 goto done;
5809 }
5810
5811 /* Get the LogonHours attribute */
5812 Status = SampGetLogonHoursAttrbute(UserObject,
5813 &InfoBuffer->Account.LogonHours);
5814 if (!NT_SUCCESS(Status))
5815 {
5816 TRACE("Status 0x%08lx\n", Status);
5817 goto done;
5818 }
5819
5820 *Buffer = InfoBuffer;
5821
5822 done:
5823 if (!NT_SUCCESS(Status))
5824 {
5825 if (InfoBuffer != NULL)
5826 {
5827 if (InfoBuffer->Account.UserName.Buffer != NULL)
5828 midl_user_free(InfoBuffer->Account.UserName.Buffer);
5829
5830 if (InfoBuffer->Account.FullName.Buffer != NULL)
5831 midl_user_free(InfoBuffer->Account.FullName.Buffer);
5832
5833 if (InfoBuffer->Account.HomeDirectory.Buffer != NULL)
5834 midl_user_free(InfoBuffer->Account.HomeDirectory.Buffer);
5835
5836 if (InfoBuffer->Account.HomeDirectoryDrive.Buffer != NULL)
5837 midl_user_free(InfoBuffer->Account.HomeDirectoryDrive.Buffer);
5838
5839 if (InfoBuffer->Account.ScriptPath.Buffer != NULL)
5840 midl_user_free(InfoBuffer->Account.ScriptPath.Buffer);
5841
5842 if (InfoBuffer->Account.ProfilePath.Buffer != NULL)
5843 midl_user_free(InfoBuffer->Account.ProfilePath.Buffer);
5844
5845 if (InfoBuffer->Account.AdminComment.Buffer != NULL)
5846 midl_user_free(InfoBuffer->Account.AdminComment.Buffer);
5847
5848 if (InfoBuffer->Account.WorkStations.Buffer != NULL)
5849 midl_user_free(InfoBuffer->Account.WorkStations.Buffer);
5850
5851 if (InfoBuffer->Account.LogonHours.LogonHours != NULL)
5852 midl_user_free(InfoBuffer->Account.LogonHours.LogonHours);
5853
5854 midl_user_free(InfoBuffer);
5855 }
5856 }
5857
5858 return Status;
5859 }
5860
5861
5862 static
5863 NTSTATUS
5864 SampQueryUserLogonHours(PSAM_DB_OBJECT UserObject,
5865 PSAMPR_USER_INFO_BUFFER *Buffer)
5866 {
5867 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5868 NTSTATUS Status;
5869
5870 TRACE("(%p %p)\n", UserObject, Buffer);
5871
5872 *Buffer = NULL;
5873
5874 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5875 if (InfoBuffer == NULL)
5876 {
5877 TRACE("Failed to allocate InfoBuffer!\n");
5878 return STATUS_INSUFFICIENT_RESOURCES;
5879 }
5880
5881 Status = SampGetLogonHoursAttrbute(UserObject,
5882 &InfoBuffer->LogonHours.LogonHours);
5883 if (!NT_SUCCESS(Status))
5884 {
5885 TRACE("SampGetLogonHoursAttrbute failed (Status 0x%08lx)\n", Status);
5886 goto done;
5887 }
5888
5889 *Buffer = InfoBuffer;
5890
5891 done:
5892 if (!NT_SUCCESS(Status))
5893 {
5894 if (InfoBuffer != NULL)
5895 {
5896 if (InfoBuffer->LogonHours.LogonHours.LogonHours != NULL)
5897 midl_user_free(InfoBuffer->LogonHours.LogonHours.LogonHours);
5898
5899 midl_user_free(InfoBuffer);
5900 }
5901 }
5902
5903 return Status;
5904 }
5905
5906
5907 static
5908 NTSTATUS
5909 SampQueryUserName(PSAM_DB_OBJECT UserObject,
5910 PSAMPR_USER_INFO_BUFFER *Buffer)
5911 {
5912 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5913 NTSTATUS Status;
5914
5915 *Buffer = NULL;
5916
5917 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5918 if (InfoBuffer == NULL)
5919 return STATUS_INSUFFICIENT_RESOURCES;
5920
5921 /* Get the Name string */
5922 Status = SampGetObjectAttributeString(UserObject,
5923 L"Name",
5924 &InfoBuffer->Name.UserName);
5925 if (!NT_SUCCESS(Status))
5926 {
5927 TRACE("Status 0x%08lx\n", Status);
5928 goto done;
5929 }
5930
5931 /* Get the FullName string */
5932 Status = SampGetObjectAttributeString(UserObject,
5933 L"FullName",
5934 &InfoBuffer->Name.FullName);
5935 if (!NT_SUCCESS(Status))
5936 {
5937 TRACE("Status 0x%08lx\n", Status);
5938 goto done;
5939 }
5940
5941 *Buffer = InfoBuffer;
5942
5943 done:
5944 if (!NT_SUCCESS(Status))
5945 {
5946 if (InfoBuffer != NULL)
5947 {
5948 if (InfoBuffer->Name.UserName.Buffer != NULL)
5949 midl_user_free(InfoBuffer->Name.UserName.Buffer);
5950
5951 if (InfoBuffer->Name.FullName.Buffer != NULL)
5952 midl_user_free(InfoBuffer->Name.FullName.Buffer);
5953
5954 midl_user_free(InfoBuffer);
5955 }
5956 }
5957
5958 return Status;
5959 }
5960
5961
5962 static NTSTATUS
5963 SampQueryUserAccountName(PSAM_DB_OBJECT UserObject,
5964 PSAMPR_USER_INFO_BUFFER *Buffer)
5965 {
5966 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5967 NTSTATUS Status;
5968
5969 *Buffer = NULL;
5970
5971 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5972 if (InfoBuffer == NULL)
5973 return STATUS_INSUFFICIENT_RESOURCES;
5974
5975 /* Get the Name string */
5976 Status = SampGetObjectAttributeString(UserObject,
5977 L"Name",
5978 &InfoBuffer->AccountName.UserName);
5979 if (!NT_SUCCESS(Status))
5980 {
5981 TRACE("Status 0x%08lx\n", Status);
5982 goto done;
5983 }
5984
5985 *Buffer = InfoBuffer;
5986
5987 done:
5988 if (!NT_SUCCESS(Status))
5989 {
5990 if (InfoBuffer != NULL)
5991 {
5992 if (InfoBuffer->AccountName.UserName.Buffer != NULL)
5993 midl_user_free(InfoBuffer->AccountName.UserName.Buffer);
5994
5995 midl_user_free(InfoBuffer);
5996 }
5997 }
5998
5999 return Status;
6000 }
6001
6002
6003 static NTSTATUS
6004 SampQueryUserFullName(PSAM_DB_OBJECT UserObject,
6005 PSAMPR_USER_INFO_BUFFER *Buffer)
6006 {
6007 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6008 NTSTATUS Status;
6009
6010 *Buffer = NULL;
6011
6012 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6013 if (InfoBuffer == NULL)
6014 return STATUS_INSUFFICIENT_RESOURCES;
6015
6016 /* Get the FullName string */
6017 Status = SampGetObjectAttributeString(UserObject,
6018 L"FullName",
6019 &InfoBuffer->FullName.FullName);
6020 if (!NT_SUCCESS(Status))
6021 {
6022 TRACE("Status 0x%08lx\n", Status);
6023 goto done;
6024 }
6025
6026 *Buffer = InfoBuffer;
6027
6028 done:
6029 if (!NT_SUCCESS(Status))
6030 {
6031 if (InfoBuffer != NULL)
6032 {
6033 if (InfoBuffer->FullName.FullName.Buffer != NULL)
6034 midl_user_free(InfoBuffer->FullName.FullName.Buffer);
6035
6036 midl_user_free(InfoBuffer);
6037 }
6038 }
6039
6040 return Status;
6041 }
6042
6043
6044 static
6045 NTSTATUS
6046 SampQueryUserPrimaryGroup(PSAM_DB_OBJECT UserObject,
6047 PSAMPR_USER_INFO_BUFFER *Buffer)
6048 {
6049 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6050 SAM_USER_FIXED_DATA FixedData;
6051 ULONG Length = 0;
6052 NTSTATUS Status;
6053
6054 *Buffer = NULL;
6055
6056 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6057 if (InfoBuffer == NULL)
6058 return STATUS_INSUFFICIENT_RESOURCES;
6059
6060 Length = sizeof(SAM_USER_FIXED_DATA);
6061 Status = SampGetObjectAttribute(UserObject,
6062 L"F",
6063 NULL,
6064 (PVOID)&FixedData,
6065 &Length);
6066 if (!NT_SUCCESS(Status))
6067 goto done;
6068
6069 InfoBuffer->PrimaryGroup.PrimaryGroupId = FixedData.PrimaryGroupId;
6070
6071 *Buffer = InfoBuffer;
6072
6073 done:
6074 if (!NT_SUCCESS(Status))
6075 {
6076 if (InfoBuffer != NULL)
6077 {
6078 midl_user_free(InfoBuffer);
6079 }
6080 }
6081
6082 return Status;
6083 }
6084
6085
6086 static NTSTATUS
6087 SampQueryUserHome(PSAM_DB_OBJECT UserObject,
6088 PSAMPR_USER_INFO_BUFFER *Buffer)
6089 {
6090 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6091 NTSTATUS Status;
6092
6093 *Buffer = NULL;
6094
6095 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6096 if (InfoBuffer == NULL)
6097 return STATUS_INSUFFICIENT_RESOURCES;
6098
6099 /* Get the HomeDirectory string */
6100 Status = SampGetObjectAttributeString(UserObject,
6101 L"HomeDirectory",
6102 &InfoBuffer->Home.HomeDirectory);
6103 if (!NT_SUCCESS(Status))
6104 {
6105 TRACE("Status 0x%08lx\n", Status);
6106 goto done;
6107 }
6108
6109 /* Get the HomeDirectoryDrive string */
6110 Status = SampGetObjectAttributeString(UserObject,
6111 L"HomeDirectoryDrive",
6112 &InfoBuffer->Home.HomeDirectoryDrive);
6113 if (!NT_SUCCESS(Status))
6114 {
6115 TRACE("Status 0x%08lx\n", Status);
6116 goto done;
6117 }
6118
6119 *Buffer = InfoBuffer;
6120
6121 done:
6122 if (!NT_SUCCESS(Status))
6123 {
6124 if (InfoBuffer != NULL)
6125 {
6126 if (InfoBuffer->Home.HomeDirectory.Buffer != NULL)
6127 midl_user_free(InfoBuffer->Home.HomeDirectory.Buffer);
6128
6129 if (InfoBuffer->Home.HomeDirectoryDrive.Buffer != NULL)
6130 midl_user_free(InfoBuffer->Home.HomeDirectoryDrive.Buffer);
6131
6132 midl_user_free(InfoBuffer);
6133 }
6134 }
6135
6136 return Status;
6137 }
6138
6139
6140 static NTSTATUS
6141 SampQueryUserScript(PSAM_DB_OBJECT UserObject,
6142 PSAMPR_USER_INFO_BUFFER *Buffer)
6143 {
6144 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6145 NTSTATUS Status;
6146
6147 *Buffer = NULL;
6148
6149 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6150 if (InfoBuffer == NULL)
6151 return STATUS_INSUFFICIENT_RESOURCES;
6152
6153 /* Get the ScriptPath string */
6154 Status = SampGetObjectAttributeString(UserObject,
6155 L"ScriptPath",
6156 &InfoBuffer->Script.ScriptPath);
6157 if (!NT_SUCCESS(Status))
6158 {
6159 TRACE("Status 0x%08lx\n", Status);
6160 goto done;
6161 }
6162
6163 *Buffer = InfoBuffer;
6164
6165 done:
6166 if (!NT_SUCCESS(Status))
6167 {
6168 if (InfoBuffer != NULL)
6169 {
6170 if (InfoBuffer->Script.ScriptPath.Buffer != NULL)
6171 midl_user_free(InfoBuffer->Script.ScriptPath.Buffer);
6172
6173 midl_user_free(InfoBuffer);
6174 }
6175 }
6176
6177 return Status;
6178 }
6179
6180
6181 static NTSTATUS
6182 SampQueryUserProfile(PSAM_DB_OBJECT UserObject,
6183 PSAMPR_USER_INFO_BUFFER *Buffer)
6184 {
6185 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6186 NTSTATUS Status;
6187
6188 *Buffer = NULL;
6189
6190 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6191 if (InfoBuffer == NULL)
6192 return STATUS_INSUFFICIENT_RESOURCES;
6193
6194 /* Get the ProfilePath string */
6195 Status = SampGetObjectAttributeString(UserObject,
6196 L"ProfilePath",
6197 &InfoBuffer->Profile.ProfilePath);
6198 if (!NT_SUCCESS(Status))
6199 {
6200 TRACE("Status 0x%08lx\n", Status);
6201 goto done;
6202 }
6203
6204 *Buffer = InfoBuffer;
6205
6206 done:
6207 if (!NT_SUCCESS(Status))
6208 {
6209 if (InfoBuffer != NULL)
6210 {
6211 if (InfoBuffer->Profile.ProfilePath.Buffer != NULL)
6212 midl_user_free(InfoBuffer->Profile.ProfilePath.Buffer);
6213
6214 midl_user_free(InfoBuffer);
6215 }
6216 }
6217
6218 return Status;
6219 }
6220
6221
6222 static NTSTATUS
6223 SampQueryUserAdminComment(PSAM_DB_OBJECT UserObject,
6224 PSAMPR_USER_INFO_BUFFER *Buffer)
6225 {
6226 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6227 NTSTATUS Status;
6228
6229 *Buffer = NULL;
6230
6231 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6232 if (InfoBuffer == NULL)
6233 return STATUS_INSUFFICIENT_RESOURCES;
6234
6235 /* Get the AdminComment string */
6236 Status = SampGetObjectAttributeString(UserObject,
6237 L"AdminComment",
6238 &InfoBuffer->AdminComment.AdminComment);
6239 if (!NT_SUCCESS(Status))
6240 {
6241 TRACE("Status 0x%08lx\n", Status);
6242 goto done;
6243 }
6244
6245 *Buffer = InfoBuffer;
6246
6247 done:
6248 if (!NT_SUCCESS(Status))
6249 {
6250 if (InfoBuffer != NULL)
6251 {
6252 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
6253 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
6254
6255 midl_user_free(InfoBuffer);
6256 }
6257 }
6258
6259 return Status;
6260 }
6261
6262
6263 static NTSTATUS
6264 SampQueryUserWorkStations(PSAM_DB_OBJECT UserObject,
6265 PSAMPR_USER_INFO_BUFFER *Buffer)
6266 {
6267 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6268 NTSTATUS Status;
6269
6270 *Buffer = NULL;
6271
6272 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6273 if (InfoBuffer == NULL)
6274 return STATUS_INSUFFICIENT_RESOURCES;
6275
6276 /* Get the WorkStations string */
6277 Status = SampGetObjectAttributeString(UserObject,
6278 L"WorkStations",
6279 &InfoBuffer->WorkStations.WorkStations);
6280 if (!NT_SUCCESS(Status))
6281 {
6282 TRACE("Status 0x%08lx\n", Status);
6283 goto done;
6284 }
6285
6286 *Buffer = InfoBuffer;
6287
6288 done:
6289 if (!NT_SUCCESS(Status))
6290 {
6291 if (InfoBuffer != NULL)
6292 {
6293 if (InfoBuffer->WorkStations.WorkStations.Buffer != NULL)
6294 midl_user_free(InfoBuffer->WorkStations.WorkStations.Buffer);
6295
6296 midl_user_free(InfoBuffer);
6297 }
6298 }
6299
6300 return Status;
6301 }
6302
6303
6304 static
6305 NTSTATUS
6306 SampQueryUserControl(PSAM_DB_OBJECT UserObject,
6307 PSAMPR_USER_INFO_BUFFER *Buffer)
6308 {
6309 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6310 SAM_USER_FIXED_DATA FixedData;
6311 ULONG Length = 0;
6312 NTSTATUS Status;
6313
6314 *Buffer = NULL;
6315
6316 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6317 if (InfoBuffer == NULL)
6318 return STATUS_INSUFFICIENT_RESOURCES;
6319
6320 Length = sizeof(SAM_USER_FIXED_DATA);
6321 Status = SampGetObjectAttribute(UserObject,
6322 L"F",
6323 NULL,
6324 (PVOID)&FixedData,
6325 &Length);
6326 if (!NT_SUCCESS(Status))
6327 goto done;
6328
6329 InfoBuffer->Control.UserAccountControl = FixedData.UserAccountControl;
6330
6331 *Buffer = InfoBuffer;
6332
6333 done:
6334 if (!NT_SUCCESS(Status))
6335 {
6336 if (InfoBuffer != NULL)
6337 {
6338 midl_user_free(InfoBuffer);
6339 }
6340 }
6341
6342 return Status;
6343 }
6344
6345
6346 static
6347 NTSTATUS
6348 SampQueryUserExpires(PSAM_DB_OBJECT UserObject,
6349 PSAMPR_USER_INFO_BUFFER *Buffer)
6350 {
6351 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6352 SAM_USER_FIXED_DATA FixedData;
6353 ULONG Length = 0;
6354 NTSTATUS Status;
6355
6356 *Buffer = NULL;
6357
6358 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6359 if (InfoBuffer == NULL)
6360 return STATUS_INSUFFICIENT_RESOURCES;
6361
6362 Length = sizeof(SAM_USER_FIXED_DATA);
6363 Status = SampGetObjectAttribute(UserObject,
6364 L"F",
6365 NULL,
6366 (PVOID)&FixedData,
6367 &Length);
6368 if (!NT_SUCCESS(Status))
6369 goto done;
6370
6371 InfoBuffer->Expires.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
6372 InfoBuffer->Expires.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
6373
6374 *Buffer = InfoBuffer;
6375
6376 done:
6377 if (!NT_SUCCESS(Status))
6378 {
6379 if (InfoBuffer != NULL)
6380 {
6381 midl_user_free(InfoBuffer);
6382 }
6383 }
6384
6385 return Status;
6386 }
6387
6388
6389 static
6390 NTSTATUS
6391 SampQueryUserInternal1(PSAM_DB_OBJECT UserObject,
6392 PSAMPR_USER_INFO_BUFFER *Buffer)
6393 {
6394 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6395 ULONG Length = 0;
6396 NTSTATUS Status = STATUS_SUCCESS;
6397
6398 /* Fail, if the caller is not a trusted caller */
6399 if (UserObject->Trusted == FALSE)
6400 return STATUS_INVALID_INFO_CLASS;
6401
6402 *Buffer = NULL;
6403
6404 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6405 if (InfoBuffer == NULL)
6406 return STATUS_INSUFFICIENT_RESOURCES;
6407
6408 InfoBuffer->Internal1.LmPasswordPresent = FALSE;
6409 InfoBuffer->Internal1.NtPasswordPresent = FALSE;
6410
6411 /* Get the NT password */
6412 Length = 0;
6413 SampGetObjectAttribute(UserObject,
6414 L"NTPwd",
6415 NULL,
6416 NULL,
6417 &Length);
6418
6419 if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD))
6420 {
6421 Status = SampGetObjectAttribute(UserObject,
6422 L"NTPwd",
6423 NULL,
6424 (PVOID)&InfoBuffer->Internal1.EncryptedNtOwfPassword,
6425 &Length);
6426 if (!NT_SUCCESS(Status))
6427 goto done;
6428
6429 if (memcmp(&InfoBuffer->Internal1.EncryptedNtOwfPassword,
6430 &EmptyNtHash,
6431 sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
6432 InfoBuffer->Internal1.NtPasswordPresent = TRUE;
6433 }
6434
6435
6436 /* Get the LM password */
6437 Length = 0;
6438 SampGetObjectAttribute(UserObject,
6439 L"LMPwd",
6440 NULL,
6441 NULL,
6442 &Length);
6443
6444 if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD))
6445 {
6446 Status = SampGetObjectAttribute(UserObject,
6447 L"LMPwd",
6448 NULL,
6449 (PVOID)&InfoBuffer->Internal1.EncryptedLmOwfPassword,
6450 &Length);
6451 if (!NT_SUCCESS(Status))
6452 goto done;
6453
6454 if (memcmp(&InfoBuffer->Internal1.EncryptedLmOwfPassword,
6455 &EmptyLmHash,
6456 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
6457 InfoBuffer->Internal1.LmPasswordPresent = TRUE;
6458 }
6459
6460 InfoBuffer->Internal1.PasswordExpired = FALSE;
6461
6462 *Buffer = InfoBuffer;
6463
6464 done:
6465 if (!NT_SUCCESS(Status))
6466 {
6467 if (InfoBuffer != NULL)
6468 {
6469 midl_user_free(InfoBuffer);
6470 }
6471 }
6472
6473 return Status;
6474 }
6475
6476
6477 static NTSTATUS
6478 SampQueryUserParameters(PSAM_DB_OBJECT UserObject,
6479 PSAMPR_USER_INFO_BUFFER *Buffer)
6480 {
6481 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6482 NTSTATUS Status;
6483
6484 *Buffer = NULL;
6485
6486 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6487 if (InfoBuffer == NULL)
6488 return STATUS_INSUFFICIENT_RESOURCES;
6489
6490 /* Get the Parameters string */
6491 Status = SampGetObjectAttributeString(UserObject,
6492 L"Parameters",
6493 &InfoBuffer->Parameters.Parameters);
6494 if (!NT_SUCCESS(Status))
6495 {
6496 TRACE("Status 0x%08lx\n", Status);
6497 goto done;
6498 }
6499
6500 *Buffer = InfoBuffer;
6501
6502 done:
6503 if (!NT_SUCCESS(Status))
6504 {
6505 if (InfoBuffer != NULL)
6506 {
6507 if (InfoBuffer->Parameters.Parameters.Buffer != NULL)
6508 midl_user_free(InfoBuffer->Parameters.Parameters.Buffer);
6509
6510 midl_user_free(InfoBuffer);
6511 }
6512 }
6513
6514 return Status;
6515 }
6516
6517
6518 static NTSTATUS
6519 SampQueryUserAll(PSAM_DB_OBJECT UserObject,
6520 PSAMPR_USER_INFO_BUFFER *Buffer)
6521 {
6522 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
6523 SAM_DOMAIN_FIXED_DATA DomainFixedData;
6524 SAM_USER_FIXED_DATA FixedData;
6525 LARGE_INTEGER PasswordCanChange;
6526 LARGE_INTEGER PasswordMustChange;
6527 ULONG Length = 0;
6528 NTSTATUS Status;
6529
6530 *Buffer = NULL;
6531
6532 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
6533 if (InfoBuffer == NULL)
6534 return STATUS_INSUFFICIENT_RESOURCES;
6535
6536 /* Get the fixed size domain data */
6537 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
6538 Status = SampGetObjectAttribute(UserObject->ParentObject,
6539 L"F",
6540 NULL,
6541 (PVOID)&DomainFixedData,
6542 &Length);
6543 if (!NT_SUCCESS(Status))
6544 goto done;
6545
6546 /* Get the fixed size user data */
6547 Length = sizeof(SAM_USER_FIXED_DATA);
6548 Status = SampGetObjectAttribute(UserObject,
6549 L"F",
6550 NULL,
6551 (PVOID)&FixedData,
6552 &Length);
6553 if (!NT_SUCCESS(Status))
6554 goto done;
6555
6556 /* Set the fields to be returned */
6557 if (UserObject->Trusted)
6558 {
6559 InfoBuffer->All.WhichFields = USER_ALL_READ_GENERAL_MASK |
6560 USER_ALL_READ_LOGON_MASK |
6561 USER_ALL_READ_ACCOUNT_MASK |
6562 USER_ALL_READ_PREFERENCES_MASK |
6563 USER_ALL_READ_TRUSTED_MASK;
6564 }
6565 else
6566 {
6567 InfoBuffer->All.WhichFields = 0;
6568
6569 if (UserObject->Access & USER_READ_GENERAL)
6570 InfoBuffer->All.WhichFields |= USER_ALL_READ_GENERAL_MASK;
6571
6572 if (UserObject->Access & USER_READ_LOGON)
6573 InfoBuffer->All.WhichFields |= USER_ALL_READ_LOGON_MASK;
6574
6575 if (UserObject->Access & USER_READ_ACCOUNT)
6576 InfoBuffer->All.WhichFields |= USER_ALL_READ_ACCOUNT_MASK;
6577
6578 if (UserObject->Access & USER_READ_PREFERENCES)
6579 InfoBuffer->All.WhichFields |= USER_ALL_READ_PREFERENCES_MASK;
6580 }
6581
6582 /* Fail, if no fields are to be returned */
6583 if (InfoBuffer->All.WhichFields == 0)
6584 {
6585 Status = STATUS_ACCESS_DENIED;
6586 goto done;
6587 }
6588
6589 /* Get the UserName attribute */
6590 if (InfoBuffer->All.WhichFields & USER_ALL_USERNAME)
6591 {
6592 Status = SampGetObjectAttributeString(UserObject,
6593 L"Name",
6594 &InfoBuffer->All.UserName);
6595 if (!NT_SUCCESS(Status))
6596 {
6597 TRACE("Status 0x%08lx\n", Status);
6598 goto done;
6599 }
6600 }
6601
6602 /* Get the FullName attribute */
6603 if (InfoBuffer->All.WhichFields & USER_ALL_FULLNAME)
6604 {
6605 Status = SampGetObjectAttributeString(UserObject,
6606 L"FullName",
6607 &InfoBuffer->All.FullName);
6608 if (!NT_SUCCESS(Status))
6609 {
6610 TRACE("Status 0x%08lx\n", Status);
6611 goto done;
6612 }
6613 }
6614
6615 /* Get the UserId attribute */
6616 if (InfoBuffer->All.WhichFields & USER_ALL_USERID)
6617 {
6618 InfoBuffer->All.UserId = FixedData.UserId;
6619 }
6620
6621 /* Get the PrimaryGroupId attribute */
6622 if (InfoBuffer->All.WhichFields & USER_ALL_PRIMARYGROUPID)
6623 {
6624 InfoBuffer->All.PrimaryGroupId = FixedData.PrimaryGroupId;
6625 }
6626
6627 /* Get the AdminComment attribute */
6628 if (InfoBuffer->All.WhichFields & USER_ALL_ADMINCOMMENT)
6629 {
6630 Status = SampGetObjectAttributeString(UserObject,
6631 L"AdminComment",
6632 &InfoBuffer->All.AdminComment);
6633 if (!NT_SUCCESS(Status))
6634 {
6635 TRACE("Status 0x%08lx\n", Status);
6636 goto done;
6637 }
6638 }
6639
6640 /* Get the UserComment attribute */
6641 if (InfoBuffer->All.WhichFields & USER_ALL_USERCOMMENT)
6642 {
6643 Status = SampGetObjectAttributeString(UserObject,
6644 L"UserComment",
6645 &InfoBuffer->All.UserComment);
6646 if (!NT_SUCCESS(Status))
6647 {
6648 TRACE("Status 0x%08lx\n", Status);
6649 goto done;
6650 }
6651 }
6652
6653 /* Get the HomeDirectory attribute */
6654 if (InfoBuffer->All.WhichFields & USER_ALL_HOMEDIRECTORY)
6655 {
6656 Status = SampGetObjectAttributeString(UserObject,
6657 L"HomeDirectory",
6658 &InfoBuffer->All.HomeDirectory);
6659 if (!NT_SUCCESS(Status))
6660 {
6661 TRACE("Status 0x%08lx\n", Status);
6662 goto done;
6663 }
6664 }
6665
6666 /* Get the HomeDirectoryDrive attribute */
6667 if (InfoBuffer->All.WhichFields & USER_ALL_HOMEDIRECTORYDRIVE)
6668 {
6669 Status = SampGetObjectAttributeString(UserObject,
6670 L"HomeDirectoryDrive",
6671 &InfoBuffer->Home.HomeDirectoryDrive);
6672 if (!NT_SUCCESS(Status))
6673 {
6674 TRACE("Status 0x%08lx\n", Status);
6675 goto done;
6676 }
6677 }
6678
6679 /* Get the ScriptPath attribute */
6680 if (InfoBuffer->All.WhichFields & USER_ALL_SCRIPTPATH)
6681 {
6682 Status = SampGetObjectAttributeString(UserObject,
6683 L"ScriptPath",
6684 &InfoBuffer->All.ScriptPath);
6685 if (!NT_SUCCESS(Status))
6686 {
6687 TRACE("Status 0x%08lx\n", Status);
6688 goto done;
6689 }
6690 }
6691
6692 /* Get the ProfilePath attribute */
6693 if (InfoBuffer->All.WhichFields & USER_ALL_PROFILEPATH)
6694 {
6695 Status = SampGetObjectAttributeString(UserObject,
6696 L"ProfilePath",
6697 &InfoBuffer->All.ProfilePath);
6698 if (!NT_SUCCESS(Status))
6699 {
6700 TRACE("Status 0x%08lx\n", Status);
6701 goto done;
6702 }
6703 }
6704
6705 /* Get the WorkStations attribute */
6706 if (InfoBuffer->All.WhichFields & USER_ALL_WORKSTATIONS)
6707 {
6708 Status = SampGetObjectAttributeString(UserObject,
6709 L"WorkStations",
6710 &InfoBuffer->All.WorkStations);
6711 if (!NT_SUCCESS(Status))
6712 {
6713 TRACE("Status 0x%08lx\n", Status);
6714 goto done;
6715 }
6716 }
6717
6718 /* Get the LastLogon attribute */
6719 if (InfoBuffer->All.WhichFields & USER_ALL_LASTLOGON)
6720 {
6721 InfoBuffer->All.LastLogon.LowPart = FixedData.LastLogon.LowPart;
6722 InfoBuffer->All.LastLogon.HighPart = FixedData.LastLogon.HighPart;
6723 }
6724
6725 /* Get the LastLogoff attribute */
6726 if (InfoBuffer->All.WhichFields & USER_ALL_LASTLOGOFF)
6727 {
6728 InfoBuffer->All.LastLogoff.LowPart = FixedData.LastLogoff.LowPart;
6729 InfoBuffer->All.LastLogoff.HighPart = FixedData.LastLogoff.HighPart;
6730 }
6731
6732 /* Get the LogonHours attribute */
6733 if (InfoBuffer->All.WhichFields & USER_ALL_LOGONHOURS)
6734 {
6735 Status = SampGetLogonHoursAttrbute(UserObject,
6736 &InfoBuffer->All.LogonHours);
6737 if (!NT_SUCCESS(Status))
6738 {
6739 TRACE("Status 0x%08lx\n", Status);
6740 goto done;
6741 }
6742 }
6743
6744 /* Get the BadPasswordCount attribute */
6745 if (InfoBuffer->All.WhichFields & USER_ALL_BADPASSWORDCOUNT)
6746 {
6747 InfoBuffer->All.BadPasswordCount = FixedData.BadPasswordCount;
6748 }
6749
6750 /* Get the LogonCount attribute */
6751 if (InfoBuffer->All.WhichFields & USER_ALL_LOGONCOUNT)
6752 {
6753 InfoBuffer->All.LogonCount = FixedData.LogonCount;
6754 }
6755
6756 /* Get the PasswordCanChange attribute */
6757 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDCANCHANGE)
6758 {
6759 PasswordCanChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet,
6760 DomainFixedData.MinPasswordAge);
6761 InfoBuffer->All.PasswordCanChange.LowPart = PasswordCanChange.LowPart;
6762 InfoBuffer->All.PasswordCanChange.HighPart = PasswordCanChange.HighPart;
6763 }
6764
6765 /* Get the PasswordMustChange attribute */
6766 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDMUSTCHANGE)
6767 {
6768 PasswordMustChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet,
6769 DomainFixedData.MaxPasswordAge);
6770 InfoBuffer->All.PasswordMustChange.LowPart = PasswordMustChange.LowPart;
6771 InfoBuffer->All.PasswordMustChange.HighPart = PasswordMustChange.HighPart;
6772 }
6773
6774 /* Get the PasswordLastSet attribute */
6775 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDLASTSET)
6776 {
6777 InfoBuffer->All.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart;
6778 InfoBuffer->All.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart;
6779 }
6780
6781 /* Get the AccountExpires attribute */
6782 if (InfoBuffer->All.WhichFields & USER_ALL_ACCOUNTEXPIRES)
6783 {
6784 InfoBuffer->All.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
6785 InfoBuffer->All.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
6786 }
6787
6788 /* Get the UserAccountControl attribute */
6789 if (InfoBuffer->All.WhichFields & USER_ALL_USERACCOUNTCONTROL)
6790 {
6791 InfoBuffer->All.UserAccountControl = FixedData.UserAccountControl;
6792 }
6793
6794 /* Get the Parameters attribute */
6795 if (InfoBuffer->All.WhichFields & USER_ALL_PARAMETERS)
6796 {
6797 Status = SampGetObjectAttributeString(UserObject,
6798 L"Parameters",
6799 &InfoBuffer->All.Parameters);
6800 if (!NT_SUCCESS(Status))
6801 {
6802 TRACE("Status 0x%08lx\n", Status);
6803 goto done;
6804 }
6805 }
6806
6807 /* Get the CountryCode attribute */
6808 if (InfoBuffer->All.WhichFields & USER_ALL_COUNTRYCODE)
6809 {
6810 InfoBuffer->All.CountryCode = FixedData.CountryCode;
6811 }
6812
6813 /* Get the CodePage attribute */
6814 if (InfoBuffer->All.WhichFields & USER_ALL_CODEPAGE)
6815 {
6816 InfoBuffer->All.CodePage = FixedData.CodePage;
6817 }
6818
6819 /* Get the LmPassword and NtPassword attributes */
6820 if (InfoBuffer->All.WhichFields & (USER_ALL_NTPASSWORDPRESENT | USER_ALL_LMPASSWORDPRESENT))
6821 {
6822 InfoBuffer->All.LmPasswordPresent = FALSE;
6823 InfoBuffer->All.NtPasswordPresent = FALSE;
6824
6825 /* Get the NT password */
6826 Length = 0;
6827 SampGetObjectAttribute(UserObject,
6828 L"NTPwd",
6829 NULL,
6830 NULL,
6831 &Length);
6832
6833 if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD))
6834 {
6835 InfoBuffer->All.NtOwfPassword.Buffer = midl_user_allocate(sizeof(ENCRYPTED_NT_OWF_PASSWORD));
6836 if (InfoBuffer->All.NtOwfPassword.Buffer == NULL)
6837 {
6838 Status = STATUS_INSUFFICIENT_RESOURCES;
6839 goto done;
6840 }
6841
6842 InfoBuffer->All.NtOwfPassword.Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
6843 InfoBuffer->All.NtOwfPassword.MaximumLength = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
6844
6845 Status = SampGetObjectAttribute(UserObject,
6846 L"NTPwd",
6847 NULL,
6848 (PVOID)InfoBuffer->All.NtOwfPassword.Buffer,
6849 &Length);
6850 if (!NT_SUCCESS(Status))
6851 goto done;
6852
6853 if (memcmp(InfoBuffer->All.NtOwfPassword.Buffer,
6854 &EmptyNtHash,
6855 sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
6856 InfoBuffer->All.NtPasswordPresent = TRUE;
6857 }
6858
6859 /* Get the LM password */
6860 Length = 0;
6861 SampGetObjectAttribute(UserObject,
6862 L"LMPwd",
6863 NULL,
6864 NULL,
6865 &Length);
6866
6867 if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD))
6868 {
6869 InfoBuffer->All.LmOwfPassword.Buffer = midl_user_allocate(sizeof(ENCRYPTED_LM_OWF_PASSWORD));
6870 if (InfoBuffer->All.LmOwfPassword.Buffer == NULL)
6871 {
6872 Status = STATUS_INSUFFICIENT_RESOURCES;
6873 goto done;
6874 }
6875
6876 InfoBuffer->All.LmOwfPassword.Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
6877 InfoBuffer->All.LmOwfPassword.MaximumLength = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
6878
6879 Status = SampGetObjectAttribute(UserObject,
6880 L"LMPwd",
6881 NULL,
6882 (PVOID)InfoBuffer->All.LmOwfPassword.Buffer,
6883 &Length);
6884 if (!NT_SUCCESS(Status))
6885 goto done;
6886
6887 if (memcmp(InfoBuffer->All.LmOwfPassword.Buffer,
6888 &EmptyLmHash,
6889 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
6890 InfoBuffer->All.LmPasswordPresent = TRUE;
6891 }
6892 }
6893
6894 if (InfoBuffer->All.WhichFields & USER_ALL_PRIVATEDATA)
6895 {
6896 Status = SampGetObjectAttributeString(UserObject,
6897 L"PrivateData",
6898 &InfoBuffer->All.PrivateData);
6899 if (!NT_SUCCESS(Status))
6900 {
6901 TRACE("Status 0x%08lx\n", Status);
6902 goto done;
6903 }
6904 }
6905
6906 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDEXPIRED)
6907 {
6908 /* FIXME */
6909 }
6910
6911 if (InfoBuffer->All.WhichFields & USER_ALL_SECURITYDESCRIPTOR)
6912 {
6913 Length = 0;
6914 SampGetObjectAttribute(UserObject,
6915 L"SecDesc",
6916 NULL,
6917 NULL,
6918 &Length);
6919
6920 if (Length > 0)
6921 {
6922 InfoBuffer->All.SecurityDescriptor.SecurityDescriptor = midl_user_allocate(Length);
6923 if (InfoBuffer->All.SecurityDescriptor.SecurityDescriptor == NULL)
6924 {
6925 Status = STATUS_INSUFFICIENT_RESOURCES;
6926 goto done;
6927 }
6928
6929 InfoBuffer->All.SecurityDescriptor.Length = Length;
6930
6931 Status = SampGetObjectAttribute(UserObject,
6932 L"SecDesc",
6933 NULL,
6934 (PVOID)InfoBuffer->All.SecurityDescriptor.SecurityDescriptor,
6935 &Length);
6936 if (!NT_SUCCESS(Status))
6937 goto done;
6938 }
6939 }
6940
6941 *Buffer = InfoBuffer;
6942
6943 done:
6944 if (!NT_SUCCESS(Status))
6945 {
6946 if (InfoBuffer != NULL)
6947 {
6948 if (InfoBuffer->All.UserName.Buffer != NULL)
6949 midl_user_free(InfoBuffer->All.UserName.Buffer);
6950
6951 if (InfoBuffer->All.FullName.Buffer != NULL)
6952 midl_user_free(InfoBuffer->All.FullName.Buffer);
6953
6954 if (InfoBuffer->All.AdminComment.Buffer != NULL)
6955 midl_user_free(InfoBuffer->All.AdminComment.Buffer);
6956
6957 if (InfoBuffer->All.UserComment.Buffer != NULL)
6958 midl_user_free(InfoBuffer->All.UserComment.Buffer);
6959
6960 if (InfoBuffer->All.HomeDirectory.Buffer != NULL)
6961 midl_user_free(InfoBuffer->All.HomeDirectory.Buffer);
6962
6963 if (InfoBuffer->All.HomeDirectoryDrive.Buffer != NULL)
6964 midl_user_free(InfoBuffer->All.HomeDirectoryDrive.Buffer);
6965
6966 if (InfoBuffer->All.ScriptPath.Buffer != NULL)
6967 midl_user_free(InfoBuffer->All.ScriptPath.Buffer);
6968
6969 if (InfoBuffer->All.ProfilePath.Buffer != NULL)
6970 midl_user_free(InfoBuffer->All.ProfilePath.Buffer);
6971
6972 if (InfoBuffer->All.WorkStations.Buffer != NULL)
6973 midl_user_free(InfoBuffer->All.WorkStations.Buffer);
6974
6975 if (InfoBuffer->All.LogonHours.LogonHours != NULL)
6976 midl_user_free(InfoBuffer->All.LogonHours.LogonHours);
6977
6978 if (InfoBuffer->All.Parameters.Buffer != NULL)
6979 midl_user_free(InfoBuffer->All.Parameters.Buffer);
6980
6981 if (InfoBuffer->All.LmOwfPassword.Buffer != NULL)
6982 midl_user_free(InfoBuffer->All.LmOwfPassword.Buffer);
6983
6984 if (InfoBuffer->All.NtOwfPassword.Buffer != NULL)
6985 midl_user_free(InfoBuffer->All.NtOwfPassword.Buffer);
6986
6987 if (InfoBuffer->All.PrivateData.Buffer != NULL)
6988 midl_user_free(InfoBuffer->All.PrivateData.Buffer);
6989
6990 if (InfoBuffer->All.SecurityDescriptor.SecurityDescriptor != NULL)
6991 midl_user_free(InfoBuffer->All.SecurityDescriptor.SecurityDescriptor);
6992
6993 midl_user_free(InfoBuffer);
6994 }
6995 }
6996
6997 return Status;
6998 }
6999
7000
7001 /* Function 36 */
7002 NTSTATUS
7003 NTAPI
7004 SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
7005 IN USER_INFORMATION_CLASS UserInformationClass,
7006 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
7007 {
7008 PSAM_DB_OBJECT UserObject;
7009 ACCESS_MASK DesiredAccess;
7010 NTSTATUS Status;
7011
7012 TRACE("SamrQueryInformationUser(%p %lu %p)\n",
7013 UserHandle, UserInformationClass, Buffer);
7014
7015 switch (UserInformationClass)
7016 {
7017 case UserGeneralInformation:
7018 case UserNameInformation:
7019 case UserAccountNameInformation:
7020 case UserFullNameInformation:
7021 case UserPrimaryGroupInformation:
7022 case UserAdminCommentInformation:
7023 DesiredAccess = USER_READ_GENERAL;
7024 break;
7025
7026 case UserLogonHoursInformation:
7027 case UserHomeInformation:
7028 case UserScriptInformation:
7029 case UserProfileInformation:
7030 case UserWorkStationsInformation:
7031 DesiredAccess = USER_READ_LOGON;
7032 break;
7033
7034 case UserControlInformation:
7035 case UserExpiresInformation:
7036 case UserParametersInformation:
7037 DesiredAccess = USER_READ_ACCOUNT;
7038 break;
7039
7040 case UserPreferencesInformation:
7041 DesiredAccess = USER_READ_GENERAL |
7042 USER_READ_PREFERENCES;
7043 break;
7044
7045 case UserLogonInformation:
7046 case UserAccountInformation:
7047 DesiredAccess = USER_READ_GENERAL |
7048 USER_READ_PREFERENCES |
7049 USER_READ_LOGON |
7050 USER_READ_ACCOUNT;
7051 break;
7052
7053 case UserInternal1Information:
7054 case UserAllInformation:
7055 DesiredAccess = 0;
7056 break;
7057
7058 default:
7059 return STATUS_INVALID_INFO_CLASS;
7060 }
7061
7062 RtlAcquireResourceShared(&SampResource,
7063 TRUE);
7064
7065 /* Validate the domain handle */
7066 Status = SampValidateDbObject(UserHandle,
7067 SamDbUserObject,
7068 DesiredAccess,
7069 &UserObject);
7070 if (!NT_SUCCESS(Status))
7071 {
7072 TRACE("failed with status 0x%08lx\n", Status);
7073 goto done;
7074 }
7075
7076 switch (UserInformationClass)
7077 {
7078 case UserGeneralInformation:
7079 Status = SampQueryUserGeneral(UserObject,
7080 Buffer);
7081 break;
7082
7083 case UserPreferencesInformation:
7084 Status = SampQueryUserPreferences(UserObject,
7085 Buffer);
7086 break;
7087
7088 case UserLogonInformation:
7089 Status = SampQueryUserLogon(UserObject,
7090 Buffer);
7091 break;
7092
7093 case UserLogonHoursInformation:
7094 Status = SampQueryUserLogonHours(UserObject,
7095 Buffer);
7096 break;
7097
7098 case UserAccountInformation:
7099 Status = SampQueryUserAccount(UserObject,
7100 Buffer);
7101 break;
7102
7103 case UserNameInformation:
7104 Status = SampQueryUserName(UserObject,
7105 Buffer);
7106 break;
7107
7108 case UserAccountNameInformation:
7109 Status = SampQueryUserAccountName(UserObject,
7110 Buffer);
7111 break;
7112
7113 case UserFullNameInformation:
7114 Status = SampQueryUserFullName(UserObject,
7115 Buffer);
7116 break;
7117
7118 case UserPrimaryGroupInformation:
7119 Status = SampQueryUserPrimaryGroup(UserObject,
7120 Buffer);
7121 break;
7122
7123 case UserHomeInformation:
7124 Status = SampQueryUserHome(UserObject,
7125 Buffer);
7126
7127 case UserScriptInformation:
7128 Status = SampQueryUserScript(UserObject,
7129 Buffer);
7130 break;
7131
7132 case UserProfileInformation:
7133 Status = SampQueryUserProfile(UserObject,
7134 Buffer);
7135 break;
7136
7137 case UserAdminCommentInformation:
7138 Status = SampQueryUserAdminComment(UserObject,
7139 Buffer);
7140 break;
7141
7142 case UserWorkStationsInformation:
7143 Status = SampQueryUserWorkStations(UserObject,
7144 Buffer);
7145 break;
7146
7147 case UserControlInformation:
7148 Status = SampQueryUserControl(UserObject,
7149 Buffer);
7150 break;
7151
7152 case UserExpiresInformation:
7153 Status = SampQueryUserExpires(UserObject,
7154 Buffer);
7155 break;
7156
7157 case UserInternal1Information:
7158 Status = SampQueryUserInternal1(UserObject,
7159 Buffer);
7160 break;
7161
7162 case UserParametersInformation:
7163 Status = SampQueryUserParameters(UserObject,
7164 Buffer);
7165 break;
7166
7167 case UserAllInformation:
7168 Status = SampQueryUserAll(UserObject,
7169 Buffer);
7170 break;
7171
7172 // case UserInternal4Information:
7173 // case UserInternal5Information:
7174 // case UserInternal4InformationNew:
7175 // case UserInternal5InformationNew:
7176
7177 default:
7178 Status = STATUS_INVALID_INFO_CLASS;
7179 }
7180
7181 done:
7182 RtlReleaseResource(&SampResource);
7183
7184 return Status;
7185 }
7186
7187
7188 static NTSTATUS
7189 SampSetUserName(PSAM_DB_OBJECT UserObject,
7190 PRPC_UNICODE_STRING NewUserName)
7191 {
7192 UNICODE_STRING OldUserName = {0, 0, NULL};
7193 NTSTATUS Status;
7194
7195 /* Check the account name */
7196 Status = SampCheckAccountName(NewUserName, 20);
7197 if (!NT_SUCCESS(Status))
7198 {
7199 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
7200 return Status;
7201 }
7202
7203 Status = SampGetObjectAttributeString(UserObject,
7204 L"Name",
7205 (PRPC_UNICODE_STRING)&OldUserName);
7206 if (!NT_SUCCESS(Status))
7207 {
7208 TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status);
7209 goto done;
7210 }
7211
7212 if (!RtlEqualUnicodeString(&OldUserName, (PCUNICODE_STRING)NewUserName, TRUE))
7213 {
7214 Status = SampCheckAccountNameInDomain(UserObject->ParentObject,
7215 NewUserName->Buffer);
7216 if (!NT_SUCCESS(Status))
7217 {
7218 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
7219 NewUserName->Buffer, Status);
7220 goto done;
7221 }
7222 }
7223
7224 Status = SampSetAccountNameInDomain(UserObject->ParentObject,
7225 L"Users",
7226 NewUserName->Buffer,
7227 UserObject->RelativeId);
7228 if (!NT_SUCCESS(Status))
7229 {
7230 TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status);
7231 goto done;
7232 }
7233
7234 Status = SampRemoveAccountNameFromDomain(UserObject->ParentObject,
7235 L"Users",
7236 OldUserName.Buffer);
7237 if (!NT_SUCCESS(Status))
7238 {
7239 TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status);
7240 goto done;
7241 }
7242
7243 Status = SampSetObjectAttributeString(UserObject,
7244 L"Name",
7245 NewUserName);
7246 if (!NT_SUCCESS(Status))
7247 {
7248 TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status);
7249 }
7250
7251 done:
7252 if (OldUserName.Buffer != NULL)
7253 midl_user_free(OldUserName.Buffer);
7254
7255 return Status;
7256 }
7257
7258
7259 static NTSTATUS
7260 SampSetUserGeneral(PSAM_DB_OBJECT UserObject,
7261 PSAMPR_USER_INFO_BUFFER Buffer)
7262 {
7263 SAM_USER_FIXED_DATA FixedData;
7264 ULONG Length = 0;
7265 NTSTATUS Status;
7266
7267 Length = sizeof(SAM_USER_FIXED_DATA);
7268 Status = SampGetObjectAttribute(UserObject,
7269 L"F",
7270 NULL,
7271 (PVOID)&FixedData,
7272 &Length);
7273 if (!NT_SUCCESS(Status))
7274 goto done;
7275
7276 FixedData.PrimaryGroupId = Buffer->General.PrimaryGroupId;
7277
7278 Status = SampSetObjectAttribute(UserObject,
7279 L"F",
7280 REG_BINARY,
7281 &FixedData,
7282 Length);
7283 if (!NT_SUCCESS(Status))
7284 goto done;
7285
7286 Status = SampSetUserName(UserObject,
7287 &Buffer->General.UserName);
7288 if (!NT_SUCCESS(Status))
7289 goto done;
7290
7291 Status = SampSetObjectAttributeString(UserObject,
7292 L"FullName",
7293 &Buffer->General.FullName);
7294 if (!NT_SUCCESS(Status))
7295 goto done;
7296
7297 Status = SampSetObjectAttributeString(UserObject,
7298 L"AdminComment",
7299 &Buffer->General.AdminComment);
7300 if (!NT_SUCCESS(Status))
7301 goto done;
7302
7303 Status = SampSetObjectAttributeString(UserObject,
7304 L"UserComment",
7305 &Buffer->General.UserComment);
7306
7307 done:
7308 return Status;
7309 }
7310
7311
7312 static NTSTATUS
7313 SampSetUserPreferences(PSAM_DB_OBJECT UserObject,
7314 PSAMPR_USER_INFO_BUFFER Buffer)
7315 {
7316 SAM_USER_FIXED_DATA FixedData;
7317 ULONG Length = 0;
7318 NTSTATUS Status;
7319
7320 Length = sizeof(SAM_USER_FIXED_DATA);
7321 Status = SampGetObjectAttribute(UserObject,
7322 L"F",
7323 NULL,
7324 (PVOID)&FixedData,
7325 &Length);
7326 if (!NT_SUCCESS(Status))
7327 goto done;
7328
7329 FixedData.CountryCode = Buffer->Preferences.CountryCode;
7330 FixedData.CodePage = Buffer->Preferences.CodePage;
7331
7332 Status = SampSetObjectAttribute(UserObject,
7333 L"F",
7334 REG_BINARY,
7335 &FixedData,
7336 Length);
7337 if (!NT_SUCCESS(Status))
7338 goto done;
7339
7340 Status = SampSetObjectAttributeString(UserObject,
7341 L"UserComment",
7342 &Buffer->Preferences.UserComment);
7343
7344 done:
7345 return Status;
7346 }
7347
7348
7349 static NTSTATUS
7350 SampSetUserPrimaryGroup(PSAM_DB_OBJECT UserObject,
7351 PSAMPR_USER_INFO_BUFFER Buffer)
7352 {
7353 SAM_USER_FIXED_DATA FixedData;
7354 ULONG Length = 0;
7355 NTSTATUS Status;
7356
7357 Length = sizeof(SAM_USER_FIXED_DATA);
7358 Status = SampGetObjectAttribute(UserObject,
7359 L"F",
7360 NULL,
7361 (PVOID)&FixedData,
7362 &Length);
7363 if (!NT_SUCCESS(Status))
7364 goto done;
7365
7366 FixedData.PrimaryGroupId = Buffer->PrimaryGroup.PrimaryGroupId;
7367
7368 Status = SampSetObjectAttribute(UserObject,
7369 L"F",
7370 REG_BINARY,
7371 &FixedData,
7372 Length);
7373
7374 done:
7375 return Status;
7376 }
7377
7378
7379 static NTSTATUS
7380 SampSetUserControl(PSAM_DB_OBJECT UserObject,
7381 PSAMPR_USER_INFO_BUFFER Buffer)
7382 {
7383 SAM_USER_FIXED_DATA FixedData;
7384 ULONG Length = 0;
7385 NTSTATUS Status;
7386
7387 Length = sizeof(SAM_USER_FIXED_DATA);
7388 Status = SampGetObjectAttribute(UserObject,
7389 L"F",
7390 NULL,
7391 (PVOID)&FixedData,
7392 &Length);
7393 if (!NT_SUCCESS(Status))
7394 goto done;
7395
7396 FixedData.UserAccountControl = Buffer->Control.UserAccountControl;
7397
7398 Status = SampSetObjectAttribute(UserObject,
7399 L"F",
7400 REG_BINARY,
7401 &FixedData,
7402 Length);
7403
7404 done:
7405 return Status;
7406 }
7407
7408
7409 static NTSTATUS
7410 SampSetUserExpires(PSAM_DB_OBJECT UserObject,
7411 PSAMPR_USER_INFO_BUFFER Buffer)
7412 {
7413 SAM_USER_FIXED_DATA FixedData;
7414 ULONG Length = 0;
7415 NTSTATUS Status;
7416
7417 Length = sizeof(SAM_USER_FIXED_DATA);
7418 Status = SampGetObjectAttribute(UserObject,
7419 L"F",
7420 NULL,
7421 (PVOID)&FixedData,
7422 &Length);
7423 if (!NT_SUCCESS(Status))
7424 goto done;
7425
7426 FixedData.AccountExpires.LowPart = Buffer->Expires.AccountExpires.LowPart;
7427 FixedData.AccountExpires.HighPart = Buffer->Expires.AccountExpires.HighPart;
7428
7429 Status = SampSetObjectAttribute(UserObject,
7430 L"F",
7431 REG_BINARY,
7432 &FixedData,
7433 Length);
7434
7435 done:
7436 return Status;
7437 }
7438
7439
7440 static NTSTATUS
7441 SampSetUserInternal1(PSAM_DB_OBJECT UserObject,
7442 PSAMPR_USER_INFO_BUFFER Buffer)
7443 {
7444 SAM_USER_FIXED_DATA FixedData;
7445 ULONG Length = 0;
7446 NTSTATUS Status = STATUS_SUCCESS;
7447
7448 /* FIXME: Decrypt NT password */
7449 /* FIXME: Decrypt LM password */
7450
7451 Status = SampSetUserPassword(UserObject,
7452 &Buffer->Internal1.EncryptedNtOwfPassword,
7453 Buffer->Internal1.NtPasswordPresent,
7454 &Buffer->Internal1.EncryptedLmOwfPassword,
7455 Buffer->Internal1.LmPasswordPresent);
7456 if (!NT_SUCCESS(Status))
7457 goto done;
7458
7459 /* Get the fixed user attributes */
7460 Length = sizeof(SAM_USER_FIXED_DATA);
7461 Status = SampGetObjectAttribute(UserObject,
7462 L"F",
7463 NULL,
7464 (PVOID)&FixedData,
7465 &Length);
7466 if (!NT_SUCCESS(Status))
7467 goto done;
7468
7469 if (Buffer->Internal1.PasswordExpired)
7470 {
7471 /* The password was last set ages ago */
7472 FixedData.PasswordLastSet.LowPart = 0;
7473 FixedData.PasswordLastSet.HighPart = 0;
7474 }
7475 else
7476 {
7477 /* The password was last set right now */
7478 Status = NtQuerySystemTime(&FixedData.PasswordLastSet);
7479 if (!NT_SUCCESS(Status))
7480 goto done;
7481 }
7482
7483 /* Set the fixed user attributes */
7484 Status = SampSetObjectAttribute(UserObject,
7485 L"F",
7486 REG_BINARY,
7487 &FixedData,
7488 Length);
7489
7490 done:
7491 return Status;
7492 }
7493
7494
7495 static NTSTATUS
7496 SampSetUserAll(PSAM_DB_OBJECT UserObject,
7497 PSAMPR_USER_INFO_BUFFER Buffer)
7498 {
7499 SAM_USER_FIXED_DATA FixedData;
7500 ULONG Length = 0;
7501 ULONG WhichFields;
7502 PENCRYPTED_NT_OWF_PASSWORD NtPassword = NULL;
7503 PENCRYPTED_LM_OWF_PASSWORD LmPassword = NULL;
7504 BOOLEAN NtPasswordPresent = FALSE;
7505 BOOLEAN LmPasswordPresent = FALSE;
7506 BOOLEAN WriteFixedData = FALSE;
7507 NTSTATUS Status = STATUS_SUCCESS;
7508
7509 WhichFields = Buffer->All.WhichFields;
7510
7511 /* Get the fixed size attributes */
7512 Length = sizeof(SAM_USER_FIXED_DATA);
7513 Status = SampGetObjectAttribute(UserObject,
7514 L"F",
7515 NULL,
7516 (PVOID)&FixedData,
7517 &Length);
7518 if (!NT_SUCCESS(Status))
7519 goto done;
7520
7521 if (WhichFields & USER_ALL_USERNAME)
7522 {
7523 Status = SampSetUserName(UserObject,
7524 &Buffer->All.UserName);
7525 if (!NT_SUCCESS(Status))
7526 goto done;
7527 }
7528
7529 if (WhichFields & USER_ALL_FULLNAME)
7530 {
7531 Status = SampSetObjectAttributeString(UserObject,
7532 L"FullName",
7533 &Buffer->All.FullName);
7534 if (!NT_SUCCESS(Status))
7535 goto done;
7536 }
7537
7538 if (WhichFields & USER_ALL_ADMINCOMMENT)
7539 {
7540 Status = SampSetObjectAttributeString(UserObject,
7541 L"AdminComment",
7542 &Buffer->All.AdminComment);
7543 if (!NT_SUCCESS(Status))
7544 goto done;
7545 }
7546
7547 if (WhichFields & USER_ALL_USERCOMMENT)
7548 {
7549 Status = SampSetObjectAttributeString(UserObject,
7550 L"UserComment",
7551 &Buffer->All.UserComment);
7552 if (!NT_SUCCESS(Status))
7553 goto done;
7554 }
7555
7556 if (WhichFields & USER_ALL_HOMEDIRECTORY)
7557 {
7558 Status = SampSetObjectAttributeString(UserObject,
7559 L"HomeDirectory",
7560 &Buffer->All.HomeDirectory);
7561 if (!NT_SUCCESS(Status))
7562 goto done;
7563 }
7564
7565 if (WhichFields & USER_ALL_HOMEDIRECTORYDRIVE)
7566 {
7567 Status = SampSetObjectAttributeString(UserObject,
7568 L"HomeDirectoryDrive",
7569 &Buffer->All.HomeDirectoryDrive);
7570 if (!NT_SUCCESS(Status))
7571 goto done;
7572 }
7573
7574 if (WhichFields & USER_ALL_SCRIPTPATH)
7575 {
7576 Status = SampSetObjectAttributeString(UserObject,
7577 L"ScriptPath",
7578 &Buffer->All.ScriptPath);
7579 if (!NT_SUCCESS(Status))
7580 goto done;
7581 }
7582
7583 if (WhichFields & USER_ALL_PROFILEPATH)
7584 {
7585 Status = SampSetObjectAttributeString(UserObject,
7586 L"ProfilePath",
7587 &Buffer->All.ProfilePath);
7588 if (!NT_SUCCESS(Status))
7589 goto done;
7590 }
7591
7592 if (WhichFields & USER_ALL_WORKSTATIONS)
7593 {
7594 Status = SampSetObjectAttributeString(UserObject,
7595 L"WorkStations",
7596 &Buffer->All.WorkStations);
7597 if (!NT_SUCCESS(Status))
7598 goto done;
7599 }
7600
7601 if (WhichFields & USER_ALL_PARAMETERS)
7602 {
7603 Status = SampSetObjectAttributeString(UserObject,
7604 L"Parameters",
7605 &Buffer->All.Parameters);
7606 if (!NT_SUCCESS(Status))
7607 goto done;
7608 }
7609
7610 if (WhichFields & USER_ALL_LOGONHOURS)
7611 {
7612 Status = SampSetLogonHoursAttrbute(UserObject,
7613 &Buffer->All.LogonHours);
7614 if (!NT_SUCCESS(Status))
7615 goto done;
7616 }
7617
7618 if (WhichFields & USER_ALL_PRIMARYGROUPID)
7619 {
7620 FixedData.PrimaryGroupId = Buffer->All.PrimaryGroupId;
7621 WriteFixedData = TRUE;
7622 }
7623
7624 if (WhichFields & USER_ALL_ACCOUNTEXPIRES)
7625 {
7626 FixedData.AccountExpires.LowPart = Buffer->All.AccountExpires.LowPart;
7627 FixedData.AccountExpires.HighPart = Buffer->All.AccountExpires.HighPart;
7628 WriteFixedData = TRUE;
7629 }
7630
7631 if (WhichFields & USER_ALL_USERACCOUNTCONTROL)
7632 {
7633 FixedData.UserAccountControl = Buffer->All.UserAccountControl;
7634 WriteFixedData = TRUE;
7635 }
7636
7637 if (WhichFields & USER_ALL_COUNTRYCODE)
7638 {
7639 FixedData.CountryCode = Buffer->All.CountryCode;
7640 WriteFixedData = TRUE;
7641 }
7642
7643 if (WhichFields & USER_ALL_CODEPAGE)
7644 {
7645 FixedData.CodePage = Buffer->All.CodePage;
7646 WriteFixedData = TRUE;
7647 }
7648
7649 if (WhichFields & (USER_ALL_NTPASSWORDPRESENT |
7650 USER_ALL_LMPASSWORDPRESENT))
7651 {
7652 if (WhichFields & USER_ALL_NTPASSWORDPRESENT)
7653 {
7654 NtPassword = (PENCRYPTED_NT_OWF_PASSWORD)Buffer->All.NtOwfPassword.Buffer;
7655 NtPasswordPresent = Buffer->All.NtPasswordPresent;
7656 }
7657
7658 if (WhichFields & USER_ALL_LMPASSWORDPRESENT)
7659 {
7660 LmPassword = (PENCRYPTED_LM_OWF_PASSWORD)Buffer->All.LmOwfPassword.Buffer;
7661 LmPasswordPresent = Buffer->All.LmPasswordPresent;
7662 }
7663
7664 Status = SampSetUserPassword(UserObject,
7665 NtPassword,
7666 NtPasswordPresent,
7667 LmPassword,
7668 LmPasswordPresent);
7669 if (!NT_SUCCESS(Status))
7670 goto done;
7671
7672 /* The password has just been set */
7673 Status = NtQuerySystemTime(&FixedData.PasswordLastSet);
7674 if (!NT_SUCCESS(Status))
7675 goto done;
7676
7677 WriteFixedData = TRUE;
7678 }
7679
7680 if (WhichFields & USER_ALL_PRIVATEDATA)
7681 {
7682 Status = SampSetObjectAttributeString(UserObject,
7683 L"PrivateData",
7684 &Buffer->All.PrivateData);
7685 if (!NT_SUCCESS(Status))
7686 goto done;
7687 }
7688
7689 if (WhichFields & USER_ALL_PASSWORDEXPIRED)
7690 {
7691 if (Buffer->All.PasswordExpired)
7692 {
7693 /* The pasword was last set ages ago */
7694 FixedData.PasswordLastSet.LowPart = 0;
7695 FixedData.PasswordLastSet.HighPart = 0;
7696 }
7697 else
7698 {
7699 /* The pasword was last set right now */
7700 Status = NtQuerySystemTime(&FixedData.PasswordLastSet);
7701 if (!NT_SUCCESS(Status))
7702 goto done;
7703 }
7704
7705 WriteFixedData = TRUE;
7706 }
7707
7708 if (WhichFields & USER_ALL_SECURITYDESCRIPTOR)
7709 {
7710 Status = SampSetObjectAttribute(UserObject,
7711 L"SecDesc",
7712 REG_BINARY,
7713 Buffer->All.SecurityDescriptor.SecurityDescriptor,
7714 Buffer->All.SecurityDescriptor.Length);
7715 }
7716
7717 if (WriteFixedData == TRUE)
7718 {
7719 Status = SampSetObjectAttribute(UserObject,
7720 L"F",
7721 REG_BINARY,
7722 &FixedData,
7723 Length);
7724 if (!NT_SUCCESS(Status))
7725 goto done;
7726 }
7727
7728 done:
7729 return Status;
7730 }
7731
7732
7733 /* Function 37 */
7734 NTSTATUS
7735 NTAPI
7736 SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
7737 IN USER_INFORMATION_CLASS UserInformationClass,
7738 IN PSAMPR_USER_INFO_BUFFER Buffer)
7739 {
7740 PSAM_DB_OBJECT UserObject;
7741 ACCESS_MASK DesiredAccess;
7742 NTSTATUS Status;
7743
7744 TRACE("SamrSetInformationUser(%p %lu %p)\n",
7745 UserHandle, UserInformationClass, Buffer);
7746
7747 switch (UserInformationClass)
7748 {
7749 case UserLogonHoursInformation:
7750 case UserNameInformation:
7751 case UserAccountNameInformation:
7752 case UserFullNameInformation:
7753 case UserPrimaryGroupInformation:
7754 case UserHomeInformation:
7755 case UserScriptInformation:
7756 case UserProfileInformation:
7757 case UserAdminCommentInformation:
7758 case UserWorkStationsInformation:
7759 case UserControlInformation:
7760 case UserExpiresInformation:
7761 case UserParametersInformation:
7762 DesiredAccess = USER_WRITE_ACCOUNT;
7763 break;
7764
7765 case UserGeneralInformation:
7766 DesiredAccess = USER_WRITE_ACCOUNT |
7767 USER_WRITE_PREFERENCES;
7768 break;
7769
7770 case UserPreferencesInformation:
7771 DesiredAccess = USER_WRITE_PREFERENCES;
7772 break;
7773
7774 case UserSetPasswordInformation:
7775 case UserInternal1Information:
7776 DesiredAccess = USER_FORCE_PASSWORD_CHANGE;
7777 break;
7778
7779 case UserAllInformation:
7780 DesiredAccess = 0; /* FIXME */
7781 break;
7782
7783 default:
7784 return STATUS_INVALID_INFO_CLASS;
7785 }
7786
7787 RtlAcquireResourceExclusive(&SampResource,
7788 TRUE);
7789
7790 /* Validate the domain handle */
7791 Status = SampValidateDbObject(UserHandle,
7792 SamDbUserObject,
7793 DesiredAccess,
7794 &UserObject);
7795 if (!NT_SUCCESS(Status))
7796 {
7797 TRACE("failed with status 0x%08lx\n", Status);
7798 goto done;
7799 }
7800
7801 switch (UserInformationClass)
7802 {
7803 case UserGeneralInformation:
7804 Status = SampSetUserGeneral(UserObject,
7805 Buffer);
7806 break;
7807
7808 case UserPreferencesInformation:
7809 Status = SampSetUserPreferences(UserObject,
7810 Buffer);
7811 break;
7812
7813 case UserLogonHoursInformation:
7814 Status = SampSetLogonHoursAttrbute(UserObject,
7815 &Buffer->LogonHours.LogonHours);
7816 break;
7817
7818 case UserNameInformation:
7819 Status = SampSetUserName(UserObject,
7820 &Buffer->Name.UserName);
7821 if (!NT_SUCCESS(Status))
7822 break;
7823
7824 Status = SampSetObjectAttributeString(UserObject,
7825 L"FullName",
7826 &Buffer->Name.FullName);
7827 break;
7828
7829 case UserAccountNameInformation:
7830 Status = SampSetUserName(UserObject,
7831 &Buffer->AccountName.UserName);
7832 break;
7833
7834 case UserFullNameInformation:
7835 Status = SampSetObjectAttributeString(UserObject,
7836 L"FullName",
7837 &Buffer->FullName.FullName);
7838 break;
7839
7840 case UserPrimaryGroupInformation:
7841 Status = SampSetUserPrimaryGroup(UserObject,
7842 Buffer);
7843 break;
7844
7845 case UserHomeInformation:
7846 Status = SampSetObjectAttributeString(UserObject,
7847 L"HomeDirectory",
7848 &Buffer->Home.HomeDirectory);
7849 if (!NT_SUCCESS(Status))
7850 break;
7851
7852 Status = SampSetObjectAttributeString(UserObject,
7853 L"HomeDirectoryDrive",
7854 &Buffer->Home.HomeDirectoryDrive);
7855 break;
7856
7857 case UserScriptInformation:
7858 Status = SampSetObjectAttributeString(UserObject,
7859 L"ScriptPath",
7860 &Buffer->Script.ScriptPath);
7861 break;
7862
7863 case UserProfileInformation:
7864 Status = SampSetObjectAttributeString(UserObject,
7865 L"ProfilePath",
7866 &Buffer->Profile.ProfilePath);
7867 break;
7868
7869 case UserAdminCommentInformation:
7870 Status = SampSetObjectAttributeString(UserObject,
7871 L"AdminComment",
7872 &Buffer->AdminComment.AdminComment);
7873 break;
7874
7875 case UserWorkStationsInformation:
7876 Status = SampSetObjectAttributeString(UserObject,
7877 L"WorkStations",
7878 &Buffer->WorkStations.WorkStations);
7879 break;
7880
7881 case UserSetPasswordInformation:
7882 TRACE("Password: %S\n", Buffer->SetPassword.Password.Buffer);
7883 TRACE("PasswordExpired: %d\n", Buffer->SetPassword.PasswordExpired);
7884
7885 Status = SampSetObjectAttributeString(UserObject,
7886 L"Password",
7887 &Buffer->SetPassword.Password);
7888 break;
7889
7890 case UserControlInformation:
7891 Status = SampSetUserControl(UserObject,
7892 Buffer);
7893 break;
7894
7895 case UserExpiresInformation:
7896 Status = SampSetUserExpires(UserObject,
7897 Buffer);
7898 break;
7899
7900 case UserInternal1Information:
7901 Status = SampSetUserInternal1(UserObject,
7902 Buffer);
7903 break;
7904
7905 case UserParametersInformation:
7906 Status = SampSetObjectAttributeString(UserObject,
7907 L"Parameters",
7908 &Buffer->Parameters.Parameters);
7909 break;
7910
7911 case UserAllInformation:
7912 Status = SampSetUserAll(UserObject,
7913 Buffer);
7914 break;
7915
7916 // case UserInternal4Information:
7917 // case UserInternal5Information:
7918 // case UserInternal4InformationNew:
7919 // case UserInternal5InformationNew:
7920
7921 default:
7922 Status = STATUS_INVALID_INFO_CLASS;
7923 }
7924
7925 done:
7926 RtlReleaseResource(&SampResource);
7927
7928 return Status;
7929 }
7930
7931
7932 /* Function 38 */
7933 NTSTATUS
7934 NTAPI
7935 SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
7936 IN unsigned char LmPresent,
7937 IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm,
7938 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm,
7939 IN unsigned char NtPresent,
7940 IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt,
7941 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt,
7942 IN unsigned char NtCrossEncryptionPresent,
7943 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm,
7944 IN unsigned char LmCrossEncryptionPresent,
7945 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt)
7946 {
7947 ENCRYPTED_LM_OWF_PASSWORD StoredLmPassword;
7948 ENCRYPTED_NT_OWF_PASSWORD StoredNtPassword;
7949 PENCRYPTED_LM_OWF_PASSWORD OldLmPassword;
7950 PENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
7951 PENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
7952 PENCRYPTED_NT_OWF_PASSWORD NewNtPassword;
7953 BOOLEAN StoredLmPresent = FALSE;
7954 BOOLEAN StoredNtPresent = FALSE;
7955 BOOLEAN StoredLmEmpty = TRUE;
7956 BOOLEAN StoredNtEmpty = TRUE;
7957 PSAM_DB_OBJECT UserObject;
7958 ULONG Length;
7959 SAM_USER_FIXED_DATA UserFixedData;
7960 SAM_DOMAIN_FIXED_DATA DomainFixedData;
7961 LARGE_INTEGER SystemTime;
7962 NTSTATUS Status;
7963
7964 TRACE("(%p %u %p %p %u %p %p %u %p %u %p)\n",
7965 UserHandle, LmPresent, OldLmEncryptedWithNewLm, NewLmEncryptedWithOldLm,
7966 NtPresent, OldNtEncryptedWithNewNt, NewNtEncryptedWithOldNt, NtCrossEncryptionPresent,
7967 NewNtEncryptedWithNewLm, LmCrossEncryptionPresent, NewLmEncryptedWithNewNt);
7968
7969 RtlAcquireResourceExclusive(&SampResource,
7970 TRUE);
7971
7972 /* Validate the user handle */
7973 Status = SampValidateDbObject(UserHandle,
7974 SamDbUserObject,
7975 USER_CHANGE_PASSWORD,
7976 &UserObject);
7977 if (!NT_SUCCESS(Status))
7978 {
7979 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
7980 goto done;
7981 }
7982
7983 /* Get the current time */
7984 Status = NtQuerySystemTime(&SystemTime);
7985 if (!NT_SUCCESS(Status))
7986 {
7987 TRACE("NtQuerySystemTime failed (Status 0x%08lx)\n", Status);
7988 goto done;
7989 }
7990
7991 /* Retrieve the LM password */
7992 Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
7993 Status = SampGetObjectAttribute(UserObject,
7994 L"LMPwd",
7995 NULL,
7996 &StoredLmPassword,
7997 &Length);
7998 if (NT_SUCCESS(Status))
7999 {
8000 if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD))
8001 {
8002 StoredLmPresent = TRUE;
8003 if (!RtlEqualMemory(&StoredLmPassword,
8004 &EmptyLmHash,
8005 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
8006 StoredLmEmpty = FALSE;
8007 }
8008 }
8009
8010 /* Retrieve the NT password */
8011 Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
8012 Status = SampGetObjectAttribute(UserObject,
8013 L"NTPwd",
8014 NULL,
8015 &StoredNtPassword,
8016 &Length);
8017 if (NT_SUCCESS(Status))
8018 {
8019 if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD))
8020 {
8021 StoredNtPresent = TRUE;
8022 if (!RtlEqualMemory(&StoredNtPassword,
8023 &EmptyNtHash,
8024 sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
8025 StoredNtEmpty = FALSE;
8026 }
8027 }
8028
8029 /* Retrieve the fixed size user data */
8030 Length = sizeof(SAM_USER_FIXED_DATA);
8031 Status = SampGetObjectAttribute(UserObject,
8032 L"F",
8033 NULL,
8034 &UserFixedData,
8035 &Length);
8036 if (!NT_SUCCESS(Status))
8037 {
8038 TRACE("SampGetObjectAttribute failed to retrieve the fixed user data (Status 0x%08lx)\n", Status);
8039 goto done;
8040 }
8041
8042 /* Check if we can change the password at this time */
8043 if ((StoredNtEmpty == FALSE) || (StoredNtEmpty == FALSE))
8044 {
8045 /* Get fixed domain data */
8046 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
8047 Status = SampGetObjectAttribute(UserObject->ParentObject,
8048 L"F",
8049 NULL,
8050 &DomainFixedData,
8051 &Length);
8052 if (!NT_SUCCESS(Status))
8053 {
8054 TRACE("SampGetObjectAttribute failed to retrieve the fixed domain data (Status 0x%08lx)\n", Status);
8055 return Status;
8056 }
8057
8058 if (DomainFixedData.MinPasswordAge.QuadPart > 0)
8059 {
8060 if (SystemTime.QuadPart < (UserFixedData.PasswordLastSet.QuadPart + DomainFixedData.MinPasswordAge.QuadPart))
8061 return STATUS_ACCOUNT_RESTRICTION;
8062 }
8063 }
8064
8065 /* FIXME: Decrypt passwords */
8066 OldLmPassword = OldLmEncryptedWithNewLm;
8067 NewLmPassword = NewLmEncryptedWithOldLm;
8068 OldNtPassword = OldNtEncryptedWithNewNt;
8069 NewNtPassword = NewNtEncryptedWithOldNt;
8070
8071 /* Check if the old passwords match the stored ones */
8072 if (NtPresent)
8073 {
8074 if (LmPresent)
8075 {
8076 if (!RtlEqualMemory(&StoredLmPassword,
8077 OldLmPassword,
8078 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
8079 {
8080 TRACE("Old LM Password does not match!\n");
8081 Status = STATUS_WRONG_PASSWORD;
8082 }
8083 else
8084 {
8085 if (!RtlEqualMemory(&StoredNtPassword,
8086 OldNtPassword,
8087 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
8088 {
8089 TRACE("Old NT Password does not match!\n");
8090 Status = STATUS_WRONG_PASSWORD;
8091 }
8092 }
8093 }
8094 else
8095 {
8096 if (!RtlEqualMemory(&StoredNtPassword,
8097 OldNtPassword,
8098 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
8099 {
8100 TRACE("Old NT Password does not match!\n");
8101 Status = STATUS_WRONG_PASSWORD;
8102 }
8103 }
8104 }
8105 else
8106 {
8107 if (LmPresent)
8108 {
8109 if (!RtlEqualMemory(&StoredLmPassword,
8110 OldLmPassword,
8111 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
8112 {
8113 TRACE("Old LM Password does not match!\n");
8114 Status = STATUS_WRONG_PASSWORD;
8115 }
8116 }
8117 else
8118 {
8119 Status = STATUS_INVALID_PARAMETER;
8120 }
8121 }
8122
8123 /* Store the new password hashes */
8124 if (NT_SUCCESS(Status))
8125 {
8126 Status = SampSetUserPassword(UserObject,
8127 NewNtPassword,
8128 NtPresent,
8129 NewLmPassword,
8130 LmPresent);
8131 if (NT_SUCCESS(Status))
8132 {
8133 /* Update PasswordLastSet */
8134 UserFixedData.PasswordLastSet.QuadPart = SystemTime.QuadPart;
8135
8136 /* Set the fixed size user data */
8137 Length = sizeof(SAM_USER_FIXED_DATA);
8138 Status = SampSetObjectAttribute(UserObject,
8139 L"F",
8140 REG_BINARY,
8141 &UserFixedData,
8142 Length);
8143 }
8144 }
8145
8146 if (Status == STATUS_WRONG_PASSWORD)
8147 {
8148 /* Update BadPasswordCount and LastBadPasswordTime */
8149 UserFixedData.BadPasswordCount++;
8150 UserFixedData.LastBadPasswordTime.QuadPart = SystemTime.QuadPart;
8151
8152 /* Set the fixed size user data */
8153 Length = sizeof(SAM_USER_FIXED_DATA);
8154 Status = SampSetObjectAttribute(UserObject,
8155 L"F",
8156 REG_BINARY,
8157 &UserFixedData,
8158 Length);
8159 }
8160
8161 done:
8162 RtlReleaseResource(&SampResource);
8163
8164 return Status;
8165 }
8166
8167
8168 /* Function 39 */
8169 NTSTATUS
8170 NTAPI
8171 SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle,
8172 OUT PSAMPR_GET_GROUPS_BUFFER *Groups)
8173 {
8174 PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL;
8175 PSAM_DB_OBJECT UserObject;
8176 ULONG Length = 0;
8177 NTSTATUS Status;
8178
8179 TRACE("SamrGetGroupsForUser(%p %p)\n",
8180 UserHandle, Groups);
8181
8182 RtlAcquireResourceShared(&SampResource,
8183 TRUE);
8184
8185 /* Validate the user handle */
8186 Status = SampValidateDbObject(UserHandle,
8187 SamDbUserObject,
8188 USER_LIST_GROUPS,
8189 &UserObject);
8190 if (!NT_SUCCESS(Status))
8191 {
8192 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
8193 goto done;
8194 }
8195
8196 /* Allocate the groups buffer */
8197 GroupsBuffer = midl_user_allocate(sizeof(SAMPR_GET_GROUPS_BUFFER));
8198 if (GroupsBuffer == NULL)
8199 {
8200 Status = STATUS_INSUFFICIENT_RESOURCES;
8201 goto done;
8202 }
8203
8204 /*
8205 * Get the size of the Groups attribute.
8206 * Do not check the status code because in case of an error
8207 * Length will be 0. And that is all we need.
8208 */
8209 SampGetObjectAttribute(UserObject,
8210 L"Groups",
8211 NULL,
8212 NULL,
8213 &Length);
8214
8215 /* If there is no Groups attribute, return a groups buffer without an array */
8216 if (Length == 0)
8217 {
8218 GroupsBuffer->MembershipCount = 0;
8219 GroupsBuffer->Groups = NULL;
8220
8221 *Groups = GroupsBuffer;
8222
8223 Status = STATUS_SUCCESS;
8224 goto done;
8225 }
8226
8227 /* Allocate a buffer for the Groups attribute */
8228 GroupsBuffer->Groups = midl_user_allocate(Length);
8229 if (GroupsBuffer->Groups == NULL)
8230 {
8231 Status = STATUS_INSUFFICIENT_RESOURCES;
8232 goto done;
8233 }
8234
8235 /* Retrieve the Grous attribute */
8236 Status = SampGetObjectAttribute(UserObject,
8237 L"Groups",
8238 NULL,
8239 GroupsBuffer->Groups,
8240 &Length);
8241 if (!NT_SUCCESS(Status))
8242 {
8243 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
8244 goto done;
8245 }
8246
8247 /* Calculate the membership count */
8248 GroupsBuffer->MembershipCount = Length / sizeof(GROUP_MEMBERSHIP);
8249
8250 /* Return the groups buffer to the caller */
8251 *Groups = GroupsBuffer;
8252
8253 done:
8254 if (!NT_SUCCESS(Status))
8255 {
8256 if (GroupsBuffer != NULL)
8257 {
8258 if (GroupsBuffer->Groups != NULL)
8259 midl_user_free(GroupsBuffer->Groups);
8260
8261 midl_user_free(GroupsBuffer);
8262 }
8263 }
8264
8265 RtlReleaseResource(&SampResource);
8266
8267 return Status;
8268 }
8269
8270
8271 /* Function 40 */
8272 NTSTATUS
8273 NTAPI
8274 SamrQueryDisplayInformation(IN SAMPR_HANDLE DomainHandle,
8275 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
8276 IN unsigned long Index,
8277 IN unsigned long EntryCount,
8278 IN unsigned long PreferredMaximumLength,
8279 OUT unsigned long *TotalAvailable,
8280 OUT unsigned long *TotalReturned,
8281 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
8282 {
8283 UNIMPLEMENTED;
8284 return STATUS_NOT_IMPLEMENTED;
8285 }
8286
8287 /* Function 41 */
8288 NTSTATUS
8289 NTAPI
8290 SamrGetDisplayEnumerationIndex(IN SAMPR_HANDLE DomainHandle,
8291 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
8292 IN PRPC_UNICODE_STRING Prefix,
8293 OUT unsigned long *Index)
8294 {
8295 UNIMPLEMENTED;
8296 return STATUS_NOT_IMPLEMENTED;
8297 }
8298
8299 /* Function 42 */
8300 NTSTATUS
8301 NTAPI
8302 SamrTestPrivateFunctionsDomain(IN SAMPR_HANDLE DomainHandle)
8303 {
8304 UNIMPLEMENTED;
8305 return STATUS_NOT_IMPLEMENTED;
8306 }
8307
8308 /* Function 43 */
8309 NTSTATUS
8310 NTAPI
8311 SamrTestPrivateFunctionsUser(IN SAMPR_HANDLE UserHandle)
8312 {
8313 UNIMPLEMENTED;
8314 return STATUS_NOT_IMPLEMENTED;
8315 }
8316
8317
8318 /* Function 44 */
8319 NTSTATUS
8320 NTAPI
8321 SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
8322 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
8323 {
8324 SAM_DOMAIN_FIXED_DATA DomainFixedData;
8325 SAM_USER_FIXED_DATA UserFixedData;
8326 PSAM_DB_OBJECT DomainObject;
8327 PSAM_DB_OBJECT UserObject;
8328 ULONG Length = 0;
8329 NTSTATUS Status;
8330
8331 TRACE("(%p %p)\n",
8332 UserHandle, PasswordInformation);
8333
8334 RtlAcquireResourceShared(&SampResource,
8335 TRUE);
8336
8337 /* Validate the user handle */
8338 Status = SampValidateDbObject(UserHandle,
8339 SamDbUserObject,
8340 0,
8341 &UserObject);
8342 if (!NT_SUCCESS(Status))
8343 {
8344 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
8345 goto done;
8346 }
8347
8348 /* Validate the domain object */
8349 Status = SampValidateDbObject((SAMPR_HANDLE)UserObject->ParentObject,
8350 SamDbDomainObject,
8351 DOMAIN_READ_PASSWORD_PARAMETERS,
8352 &DomainObject);
8353 if (!NT_SUCCESS(Status))
8354 {
8355 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
8356 goto done;
8357 }
8358
8359 /* Get fixed user data */
8360 Length = sizeof(SAM_USER_FIXED_DATA);
8361 Status = SampGetObjectAttribute(UserObject,
8362 L"F",
8363 NULL,
8364 (PVOID)&UserFixedData,
8365 &Length);
8366 if (!NT_SUCCESS(Status))
8367 {
8368 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
8369 goto done;
8370 }
8371
8372 if ((UserObject->RelativeId == DOMAIN_USER_RID_KRBTGT) ||
8373 (UserFixedData.UserAccountControl & (USER_INTERDOMAIN_TRUST_ACCOUNT |
8374 USER_WORKSTATION_TRUST_ACCOUNT |
8375 USER_SERVER_TRUST_ACCOUNT)))
8376 {
8377 PasswordInformation->MinPasswordLength = 0;
8378 PasswordInformation->PasswordProperties = 0;
8379 }
8380 else
8381 {
8382 /* Get fixed domain data */
8383 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
8384 Status = SampGetObjectAttribute(DomainObject,
8385 L"F",
8386 NULL,
8387 (PVOID)&DomainFixedData,
8388 &Length);
8389 if (!NT_SUCCESS(Status))
8390 {
8391 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
8392 goto done;
8393 }
8394
8395 PasswordInformation->MinPasswordLength = DomainFixedData.MinPasswordLength;
8396 PasswordInformation->PasswordProperties = DomainFixedData.PasswordProperties;
8397 }
8398
8399 done:
8400 RtlReleaseResource(&SampResource);
8401
8402 return STATUS_SUCCESS;
8403 }
8404
8405
8406 /* Function 45 */
8407 NTSTATUS
8408 NTAPI
8409 SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
8410 IN PRPC_SID MemberSid)
8411 {
8412 PSAM_DB_OBJECT DomainObject;
8413 ULONG Rid = 0;
8414 NTSTATUS Status;
8415
8416 TRACE("(%p %p)\n",
8417 DomainHandle, MemberSid);
8418
8419 RtlAcquireResourceExclusive(&SampResource,
8420 TRUE);
8421
8422 /* Validate the domain object */
8423 Status = SampValidateDbObject(DomainHandle,
8424 SamDbDomainObject,
8425 DOMAIN_LOOKUP,
8426 &DomainObject);
8427 if (!NT_SUCCESS(Status))
8428 {
8429 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
8430 goto done;
8431 }
8432
8433 /* Retrieve the RID from the MemberSID */
8434 Status = SampGetRidFromSid((PSID)MemberSid,
8435 &Rid);
8436 if (!NT_SUCCESS(Status))
8437 {
8438 TRACE("SampGetRidFromSid failed with status 0x%08lx\n", Status);
8439 goto done;
8440 }
8441
8442 /* Fail, if the RID represents a special account */
8443 if (Rid < 1000)
8444 {
8445 TRACE("Cannot remove a special account (RID: %lu)\n", Rid);
8446 Status = STATUS_SPECIAL_ACCOUNT;
8447 goto done;
8448 }
8449
8450 /* Remove the member from all aliases in the domain */
8451 Status = SampRemoveMemberFromAllAliases(DomainObject,
8452 MemberSid);
8453 if (!NT_SUCCESS(Status))
8454 {
8455 TRACE("SampRemoveMemberFromAllAliases failed with status 0x%08lx\n", Status);
8456 }
8457
8458 done:
8459 RtlReleaseResource(&SampResource);
8460
8461 return Status;
8462 }
8463
8464
8465 /* Function 46 */
8466 NTSTATUS
8467 NTAPI
8468 SamrQueryInformationDomain2(IN SAMPR_HANDLE DomainHandle,
8469 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
8470 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
8471 {
8472 TRACE("(%p %lu %p)\n", DomainHandle, DomainInformationClass, Buffer);
8473
8474 return SamrQueryInformationDomain(DomainHandle,
8475 DomainInformationClass,
8476 Buffer);
8477 }
8478
8479
8480 /* Function 47 */
8481 NTSTATUS
8482 NTAPI
8483 SamrQueryInformationUser2(IN SAMPR_HANDLE UserHandle,
8484 IN USER_INFORMATION_CLASS UserInformationClass,
8485 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
8486 {
8487 TRACE("(%p %lu %p)\n", UserHandle, UserInformationClass, Buffer);
8488
8489 return SamrQueryInformationUser(UserHandle,
8490 UserInformationClass,
8491 Buffer);
8492 }
8493
8494
8495 /* Function 48 */
8496 NTSTATUS
8497 NTAPI
8498 SamrQueryDisplayInformation2(IN SAMPR_HANDLE DomainHandle,
8499 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
8500 IN unsigned long Index,
8501 IN unsigned long EntryCount,
8502 IN unsigned long PreferredMaximumLength,
8503 OUT unsigned long *TotalAvailable,
8504 OUT unsigned long *TotalReturned,
8505 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
8506 {
8507 TRACE("%p %lu %lu %lu %lu %p %p %p\n",
8508 DomainHandle, DisplayInformationClass, Index,
8509 EntryCount, PreferredMaximumLength, TotalAvailable,
8510 TotalReturned, Buffer);
8511
8512 return SamrQueryDisplayInformation(DomainHandle,
8513 DisplayInformationClass,
8514 Index,
8515 EntryCount,
8516 PreferredMaximumLength,
8517 TotalAvailable,
8518 TotalReturned,
8519 Buffer);
8520 }
8521
8522
8523 /* Function 49 */
8524 NTSTATUS
8525 NTAPI
8526 SamrGetDisplayEnumerationIndex2(IN SAMPR_HANDLE DomainHandle,
8527 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
8528 IN PRPC_UNICODE_STRING Prefix,
8529 OUT unsigned long *Index)
8530 {
8531 TRACE("(%p %lu %p %p)\n",
8532 DomainHandle, DisplayInformationClass, Prefix, Index);
8533
8534 return SamrGetDisplayEnumerationIndex(DomainHandle,
8535 DisplayInformationClass,
8536 Prefix,
8537 Index);
8538 }
8539
8540
8541 /* Function 50 */
8542 NTSTATUS
8543 NTAPI
8544 SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
8545 IN PRPC_UNICODE_STRING Name,
8546 IN unsigned long AccountType,
8547 IN ACCESS_MASK DesiredAccess,
8548 OUT SAMPR_HANDLE *UserHandle,
8549 OUT unsigned long *GrantedAccess,
8550 OUT unsigned long *RelativeId)
8551 {
8552 SAM_DOMAIN_FIXED_DATA FixedDomainData;
8553 SAM_USER_FIXED_DATA FixedUserData;
8554 PSAM_DB_OBJECT DomainObject;
8555 PSAM_DB_OBJECT UserObject;
8556 GROUP_MEMBERSHIP GroupMembership;
8557 UCHAR LogonHours[23];
8558 ULONG ulSize;
8559 ULONG ulRid;
8560 WCHAR szRid[9];
8561 PSECURITY_DESCRIPTOR Sd = NULL;
8562 ULONG SdSize = 0;
8563 PSID UserSid = NULL;
8564 NTSTATUS Status;
8565
8566 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
8567 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
8568
8569 if (Name == NULL ||
8570 Name->Length == 0 ||
8571 Name->Buffer == NULL ||
8572 UserHandle == NULL ||
8573 RelativeId == NULL)
8574 return STATUS_INVALID_PARAMETER;
8575
8576 /* Check for valid account type */
8577 if (AccountType != USER_NORMAL_ACCOUNT &&
8578 AccountType != USER_WORKSTATION_TRUST_ACCOUNT &&
8579 AccountType != USER_INTERDOMAIN_TRUST_ACCOUNT &&
8580 AccountType != USER_SERVER_TRUST_ACCOUNT &&
8581 AccountType != USER_TEMP_DUPLICATE_ACCOUNT)
8582 return STATUS_INVALID_PARAMETER;
8583
8584 /* Map generic access rights */
8585 RtlMapGenericMask(&DesiredAccess,
8586 &UserMapping);
8587
8588 RtlAcquireResourceExclusive(&SampResource,
8589 TRUE);
8590
8591 /* Validate the domain handle */
8592 Status = SampValidateDbObject(DomainHandle,
8593 SamDbDomainObject,
8594 DOMAIN_CREATE_USER,
8595 &DomainObject);
8596 if (!NT_SUCCESS(Status))
8597 {
8598 TRACE("failed with status 0x%08lx\n", Status);
8599 goto done;
8600 }
8601
8602 /* Check the user account name */
8603 Status = SampCheckAccountName(Name, 20);
8604 if (!NT_SUCCESS(Status))
8605 {
8606 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
8607 goto done;
8608 }
8609
8610 /* Check if the user name already exists in the domain */
8611 Status = SampCheckAccountNameInDomain(DomainObject,
8612 Name->Buffer);
8613 if (!NT_SUCCESS(Status))
8614 {
8615 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
8616 Name->Buffer, Status);
8617 goto done;
8618 }
8619
8620 /* Get the fixed domain attributes */
8621 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
8622 Status = SampGetObjectAttribute(DomainObject,
8623 L"F",
8624 NULL,
8625 (PVOID)&FixedDomainData,
8626 &ulSize);
8627 if (!NT_SUCCESS(Status))
8628 {
8629 TRACE("failed with status 0x%08lx\n", Status);
8630 goto done;
8631 }
8632
8633 /* Increment the NextRid attribute */
8634 ulRid = FixedDomainData.NextRid;
8635 FixedDomainData.NextRid++;
8636
8637 TRACE("RID: %lx\n", ulRid);
8638
8639 /* Create the user SID */
8640 Status = SampCreateAccountSid(DomainObject,
8641 ulRid,
8642 &UserSid);
8643 if (!NT_SUCCESS(Status))
8644 {
8645 TRACE("SampCreateAccountSid failed (Status 0x%08lx)\n", Status);
8646 goto done;
8647 }
8648
8649 /* Create the security descriptor */
8650 Status = SampCreateUserSD(UserSid,
8651 &Sd,
8652 &SdSize);
8653 if (!NT_SUCCESS(Status))
8654 {
8655 TRACE("SampCreateUserSD failed (Status 0x%08lx)\n", Status);
8656 goto done;
8657 }
8658
8659 /* Store the fixed domain attributes */
8660 Status = SampSetObjectAttribute(DomainObject,
8661 L"F",
8662 REG_BINARY,
8663 &FixedDomainData,
8664 ulSize);
8665 if (!NT_SUCCESS(Status))
8666 {
8667 TRACE("failed with status 0x%08lx\n", Status);
8668 goto done;
8669 }
8670
8671 /* Convert the RID into a string (hex) */
8672 swprintf(szRid, L"%08lX", ulRid);
8673
8674 /* Create the user object */
8675 Status = SampCreateDbObject(DomainObject,
8676 L"Users",
8677 szRid,
8678 ulRid,
8679 SamDbUserObject,
8680 DesiredAccess,
8681 &UserObject);
8682 if (!NT_SUCCESS(Status))
8683 {
8684 TRACE("failed with status 0x%08lx\n", Status);
8685 goto done;
8686 }
8687
8688 /* Add the account name for the user object */
8689 Status = SampSetAccountNameInDomain(DomainObject,
8690 L"Users",
8691 Name->Buffer,
8692 ulRid);
8693 if (!NT_SUCCESS(Status))
8694 {
8695 TRACE("failed with status 0x%08lx\n", Status);
8696 goto done;
8697 }
8698
8699 /* Initialize fixed user data */
8700 FixedUserData.Version = 1;
8701 FixedUserData.Reserved = 0;
8702 FixedUserData.LastLogon.QuadPart = 0;
8703 FixedUserData.LastLogoff.QuadPart = 0;
8704 FixedUserData.PasswordLastSet.QuadPart = 0;
8705 FixedUserData.AccountExpires.LowPart = MAXULONG;
8706 FixedUserData.AccountExpires.HighPart = MAXLONG;
8707 FixedUserData.LastBadPasswordTime.QuadPart = 0;
8708 FixedUserData.UserId = ulRid;
8709 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
8710 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
8711 USER_PASSWORD_NOT_REQUIRED |
8712 AccountType;
8713 FixedUserData.CountryCode = 0;
8714 FixedUserData.CodePage = 0;
8715 FixedUserData.BadPasswordCount = 0;
8716 FixedUserData.LogonCount = 0;
8717 FixedUserData.AdminCount = 0;
8718 FixedUserData.OperatorCount = 0;
8719
8720 /* Set fixed user data attribute */
8721 Status = SampSetObjectAttribute(UserObject,
8722 L"F",
8723 REG_BINARY,
8724 (LPVOID)&FixedUserData,
8725 sizeof(SAM_USER_FIXED_DATA));
8726 if (!NT_SUCCESS(Status))
8727 {
8728 TRACE("failed with status 0x%08lx\n", Status);
8729 goto done;
8730 }
8731
8732 /* Set the Name attribute */
8733 Status = SampSetObjectAttributeString(UserObject,
8734 L"Name",
8735 Name);
8736 if (!NT_SUCCESS(Status))
8737 {
8738 TRACE("failed with status 0x%08lx\n", Status);
8739 goto done;
8740 }
8741
8742 /* Set the FullName attribute */
8743 Status = SampSetObjectAttributeString(UserObject,
8744 L"FullName",
8745 NULL);
8746 if (!NT_SUCCESS(Status))
8747 {
8748 TRACE("failed with status 0x%08lx\n", Status);
8749 goto done;
8750 }
8751
8752 /* Set the HomeDirectory attribute */
8753 Status = SampSetObjectAttributeString(UserObject,
8754 L"HomeDirectory",
8755 NULL);
8756 if (!NT_SUCCESS(Status))
8757 {
8758 TRACE("failed with status 0x%08lx\n", Status);
8759 goto done;
8760 }
8761
8762 /* Set the HomeDirectoryDrive attribute */
8763 Status = SampSetObjectAttributeString(UserObject,
8764 L"HomeDirectoryDrive",
8765 NULL);
8766 if (!NT_SUCCESS(Status))
8767 {
8768 TRACE("failed with status 0x%08lx\n", Status);
8769 goto done;
8770 }
8771
8772 /* Set the ScriptPath attribute */
8773 Status = SampSetObjectAttributeString(UserObject,
8774 L"ScriptPath",
8775 NULL);
8776 if (!NT_SUCCESS(Status))
8777 {
8778 TRACE("failed with status 0x%08lx\n", Status);
8779 goto done;
8780 }
8781
8782 /* Set the ProfilePath attribute */
8783 Status = SampSetObjectAttributeString(UserObject,
8784 L"ProfilePath",
8785 NULL);
8786 if (!NT_SUCCESS(Status))
8787 {
8788 TRACE("failed with status 0x%08lx\n", Status);
8789 goto done;
8790 }
8791
8792 /* Set the AdminComment attribute */
8793 Status = SampSetObjectAttributeString(UserObject,
8794 L"AdminComment",
8795 NULL);
8796 if (!NT_SUCCESS(Status))
8797 {
8798 TRACE("failed with status 0x%08lx\n", Status);
8799 goto done;
8800 }
8801
8802 /* Set the UserComment attribute */
8803 Status = SampSetObjectAttributeString(UserObject,
8804 L"UserComment",
8805 NULL);
8806 if (!NT_SUCCESS(Status))
8807 {
8808 TRACE("failed with status 0x%08lx\n", Status);
8809 goto done;
8810 }
8811
8812 /* Set the WorkStations attribute */
8813 Status = SampSetObjectAttributeString(UserObject,
8814 L"WorkStations",
8815 NULL);
8816 if (!NT_SUCCESS(Status))
8817 {
8818 TRACE("failed with status 0x%08lx\n", Status);
8819 goto done;
8820 }
8821
8822 /* Set the Parameters attribute */
8823 Status = SampSetObjectAttributeString(UserObject,
8824 L"Parameters",
8825 NULL);
8826 if (!NT_SUCCESS(Status))
8827 {
8828 TRACE("failed with status 0x%08lx\n", Status);
8829 goto done;
8830 }
8831
8832 /* Set LogonHours attribute*/
8833 *((PUSHORT)LogonHours) = 168;
8834 memset(&(LogonHours[2]), 0xff, 21);
8835
8836 Status = SampSetObjectAttribute(UserObject,
8837 L"LogonHours",
8838 REG_BINARY,
8839 &LogonHours,
8840 sizeof(LogonHours));
8841 if (!NT_SUCCESS(Status))
8842 {
8843 TRACE("failed with status 0x%08lx\n", Status);
8844 goto done;
8845 }
8846
8847 /* Set Groups attribute*/
8848 GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS;
8849 GroupMembership.Attributes = SE_GROUP_MANDATORY |
8850 SE_GROUP_ENABLED |
8851 SE_GROUP_ENABLED_BY_DEFAULT;
8852
8853 Status = SampSetObjectAttribute(UserObject,
8854 L"Groups",
8855 REG_BINARY,
8856 &GroupMembership,
8857 sizeof(GROUP_MEMBERSHIP));
8858 if (!NT_SUCCESS(Status))
8859 {
8860 TRACE("failed with status 0x%08lx\n", Status);
8861 goto done;
8862 }
8863
8864 /* Set LMPwd attribute*/
8865 Status = SampSetObjectAttribute(UserObject,
8866 L"LMPwd",
8867 REG_BINARY,
8868 NULL,
8869 0);
8870 if (!NT_SUCCESS(Status))
8871 {
8872 TRACE("failed with status 0x%08lx\n", Status);
8873 goto done;
8874 }
8875
8876 /* Set NTPwd attribute*/
8877 Status = SampSetObjectAttribute(UserObject,
8878 L"NTPwd",
8879 REG_BINARY,
8880 NULL,
8881 0);
8882 if (!NT_SUCCESS(Status))
8883 {
8884 TRACE("failed with status 0x%08lx\n", Status);
8885 goto done;
8886 }
8887
8888 /* Set LMPwdHistory attribute*/
8889 Status = SampSetObjectAttribute(UserObject,
8890 L"LMPwdHistory",
8891 REG_BINARY,
8892 NULL,
8893 0);
8894 if (!NT_SUCCESS(Status))
8895 {
8896 TRACE("failed with status 0x%08lx\n", Status);
8897 goto done;
8898 }
8899
8900 /* Set NTPwdHistory attribute*/
8901 Status = SampSetObjectAttribute(UserObject,
8902 L"NTPwdHistory",
8903 REG_BINARY,
8904 NULL,
8905 0);
8906 if (!NT_SUCCESS(Status))
8907 {
8908 TRACE("failed with status 0x%08lx\n", Status);
8909 goto done;
8910 }
8911
8912 /* Set the PrivateData attribute */
8913 Status = SampSetObjectAttributeString(UserObject,
8914 L"PrivateData",
8915 NULL);
8916 if (!NT_SUCCESS(Status))
8917 {
8918 TRACE("failed with status 0x%08lx\n", Status);
8919 goto done;
8920 }
8921
8922 /* Set the SecDesc attribute*/
8923 Status = SampSetObjectAttribute(UserObject,
8924 L"SecDesc",
8925 REG_BINARY,
8926 Sd,
8927 SdSize);
8928 if (!NT_SUCCESS(Status))
8929 {
8930 TRACE("failed with status 0x%08lx\n", Status);
8931 goto done;
8932 }
8933
8934 if (NT_SUCCESS(Status))
8935 {
8936 *UserHandle = (SAMPR_HANDLE)UserObject;
8937 *RelativeId = ulRid;
8938 *GrantedAccess = UserObject->Access;
8939 }
8940
8941 done:
8942 if (Sd != NULL)
8943 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
8944
8945 if (UserSid != NULL)
8946 RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid);
8947
8948 RtlReleaseResource(&SampResource);
8949
8950 TRACE("returns with status 0x%08lx\n", Status);
8951
8952 return Status;
8953 }
8954
8955
8956 /* Function 51 */
8957 NTSTATUS
8958 NTAPI
8959 SamrQueryDisplayInformation3(IN SAMPR_HANDLE DomainHandle,
8960 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
8961 IN unsigned long Index,
8962 IN unsigned long EntryCount,
8963 IN unsigned long PreferredMaximumLength,
8964 OUT unsigned long *TotalAvailable,
8965 OUT unsigned long *TotalReturned,
8966 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
8967 {
8968 TRACE("%p %lu %lu %lu %lu %p %p %p\n",
8969 DomainHandle, DisplayInformationClass, Index,
8970 EntryCount, PreferredMaximumLength, TotalAvailable,
8971 TotalReturned, Buffer);
8972
8973 return SamrQueryDisplayInformation(DomainHandle,
8974 DisplayInformationClass,
8975 Index,
8976 EntryCount,
8977 PreferredMaximumLength,
8978 TotalAvailable,
8979 TotalReturned,
8980 Buffer);
8981 }
8982
8983
8984 /* Function 52 */
8985 NTSTATUS
8986 NTAPI
8987 SamrAddMultipleMembersToAlias(IN SAMPR_HANDLE AliasHandle,
8988 IN PSAMPR_PSID_ARRAY MembersBuffer)
8989 {
8990 ULONG i;
8991 NTSTATUS Status = STATUS_SUCCESS;
8992
8993 TRACE("SamrAddMultipleMembersToAlias(%p %p)\n",
8994 AliasHandle, MembersBuffer);
8995
8996 for (i = 0; i < MembersBuffer->Count; i++)
8997 {
8998 Status = SamrAddMemberToAlias(AliasHandle,
8999 ((PSID *)MembersBuffer->Sids)[i]);
9000
9001 if (Status == STATUS_MEMBER_IN_ALIAS)
9002 Status = STATUS_SUCCESS;
9003
9004 if (!NT_SUCCESS(Status))
9005 break;
9006 }
9007
9008 return Status;
9009 }
9010
9011
9012 /* Function 53 */
9013 NTSTATUS
9014 NTAPI
9015 SamrRemoveMultipleMembersFromAlias(IN SAMPR_HANDLE AliasHandle,
9016 IN PSAMPR_PSID_ARRAY MembersBuffer)
9017 {
9018 ULONG i;
9019 NTSTATUS Status = STATUS_SUCCESS;
9020
9021 TRACE("SamrRemoveMultipleMembersFromAlias(%p %p)\n",
9022 AliasHandle, MembersBuffer);
9023
9024 for (i = 0; i < MembersBuffer->Count; i++)
9025 {
9026 Status = SamrRemoveMemberFromAlias(AliasHandle,
9027 ((PSID *)MembersBuffer->Sids)[i]);
9028
9029 if (Status == STATUS_MEMBER_IN_ALIAS)
9030 Status = STATUS_SUCCESS;
9031
9032 if (!NT_SUCCESS(Status))
9033 break;
9034 }
9035
9036 return Status;
9037 }
9038
9039
9040 /* Function 54 */
9041 NTSTATUS
9042 NTAPI
9043 SamrOemChangePasswordUser2(IN handle_t BindingHandle,
9044 IN PRPC_STRING ServerName,
9045 IN PRPC_STRING UserName,
9046 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
9047 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewLm)
9048 {
9049 UNIMPLEMENTED;
9050 return STATUS_NOT_IMPLEMENTED;
9051 }
9052
9053 /* Function 55 */
9054 NTSTATUS
9055 NTAPI
9056 SamrUnicodeChangePasswordUser2(IN handle_t BindingHandle,
9057 IN PRPC_UNICODE_STRING ServerName,
9058 IN PRPC_UNICODE_STRING UserName,
9059 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldNt,
9060 IN PENCRYPTED_NT_OWF_PASSWORD OldNtOwfPasswordEncryptedWithNewNt,
9061 IN unsigned char LmPresent,
9062 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
9063 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewNt)
9064 {
9065 UNIMPLEMENTED;
9066 return STATUS_NOT_IMPLEMENTED;
9067 }
9068
9069 /* Function 56 */
9070 NTSTATUS
9071 NTAPI
9072 SamrGetDomainPasswordInformation(IN handle_t BindingHandle,
9073 IN PRPC_UNICODE_STRING Unused,
9074 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
9075 {
9076 UNIMPLEMENTED;
9077 return STATUS_NOT_IMPLEMENTED;
9078 }
9079
9080
9081 /* Function 57 */
9082 NTSTATUS
9083 NTAPI
9084 SamrConnect2(IN PSAMPR_SERVER_NAME ServerName,
9085 OUT SAMPR_HANDLE *ServerHandle,
9086 IN ACCESS_MASK DesiredAccess)
9087 {
9088 TRACE("(%p %p %lx)\n", ServerName, ServerHandle, DesiredAccess);
9089
9090 return SamrConnect(ServerName,
9091 ServerHandle,
9092 DesiredAccess);
9093 }
9094
9095
9096 /* Function 58 */
9097 NTSTATUS
9098 NTAPI
9099 SamrSetInformationUser2(IN SAMPR_HANDLE UserHandle,
9100 IN USER_INFORMATION_CLASS UserInformationClass,
9101 IN PSAMPR_USER_INFO_BUFFER Buffer)
9102 {
9103 TRACE("(%p %lu %p)\n", UserHandle, UserInformationClass, Buffer);
9104
9105 return SamrSetInformationUser(UserHandle,
9106 UserInformationClass,
9107 Buffer);
9108 }
9109
9110
9111 /* Function 59 */
9112 NTSTATUS
9113 NTAPI
9114 SamrSetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
9115 {
9116 UNIMPLEMENTED;
9117 return STATUS_NOT_IMPLEMENTED;
9118 }
9119
9120 /* Function 60 */
9121 NTSTATUS
9122 NTAPI
9123 SamrGetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
9124 {
9125 UNIMPLEMENTED;
9126 return STATUS_NOT_IMPLEMENTED;
9127 }
9128
9129 /* Function 61 */
9130 NTSTATUS
9131 NTAPI
9132 SamrConnect3(IN handle_t BindingHandle) /* FIXME */
9133 {
9134 UNIMPLEMENTED;
9135 return STATUS_NOT_IMPLEMENTED;
9136 }
9137
9138 /* Function 62 */
9139 NTSTATUS
9140 NTAPI
9141 SamrConnect4(IN PSAMPR_SERVER_NAME ServerName,
9142 OUT SAMPR_HANDLE *ServerHandle,
9143 IN unsigned long ClientRevision,
9144 IN ACCESS_MASK DesiredAccess)
9145 {
9146 UNIMPLEMENTED;
9147 return STATUS_NOT_IMPLEMENTED;
9148 }
9149
9150 /* Function 63 */
9151 NTSTATUS
9152 NTAPI
9153 SamrUnicodeChangePasswordUser3(IN handle_t BindingHandle) /* FIXME */
9154 {
9155 UNIMPLEMENTED;
9156 return STATUS_NOT_IMPLEMENTED;
9157 }
9158
9159 /* Function 64 */
9160 NTSTATUS
9161 NTAPI
9162 SamrConnect5(IN PSAMPR_SERVER_NAME ServerName,
9163 IN ACCESS_MASK DesiredAccess,
9164 IN unsigned long InVersion,
9165 IN SAMPR_REVISION_INFO *InRevisionInfo,
9166 OUT unsigned long *OutVersion,
9167 OUT SAMPR_REVISION_INFO *OutRevisionInfo,
9168 OUT SAMPR_HANDLE *ServerHandle)
9169 {
9170 UNIMPLEMENTED;
9171 return STATUS_NOT_IMPLEMENTED;
9172 }
9173
9174 /* Function 65 */
9175 NTSTATUS
9176 NTAPI
9177 SamrRidToSid(IN SAMPR_HANDLE ObjectHandle,
9178 IN unsigned long Rid,
9179 OUT PRPC_SID *Sid)
9180 {
9181 UNIMPLEMENTED;
9182 return STATUS_NOT_IMPLEMENTED;
9183 }
9184
9185 /* Function 66 */
9186 NTSTATUS
9187 NTAPI
9188 SamrSetDSRMPassword(IN handle_t BindingHandle,
9189 IN PRPC_UNICODE_STRING Unused,
9190 IN unsigned long UserId,
9191 IN PENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword)
9192 {
9193 UNIMPLEMENTED;
9194 return STATUS_NOT_IMPLEMENTED;
9195 }
9196
9197 /* Function 67 */
9198 NTSTATUS
9199 NTAPI
9200 SamrValidatePassword(IN handle_t Handle,
9201 IN PASSWORD_POLICY_VALIDATION_TYPE ValidationType,
9202 IN PSAM_VALIDATE_INPUT_ARG InputArg,
9203 OUT PSAM_VALIDATE_OUTPUT_ARG *OutputArg)
9204 {
9205 UNIMPLEMENTED;
9206 return STATUS_NOT_IMPLEMENTED;
9207 }
9208
9209 /* EOF */