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