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