86c6c1dbd718b53b6e1516ecb655bfdb33158719
[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)(DataLength + 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)(DataLength + 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)(DataLength + 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 PENCRYPTED_LM_OWF_PASSWORD OldLmPassword;
8051 PENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
8052 PENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
8053 PENCRYPTED_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 TRACE("(%p %u %p %p %u %p %p %u %p %u %p)\n",
8066 UserHandle, LmPresent, OldLmEncryptedWithNewLm, NewLmEncryptedWithOldLm,
8067 NtPresent, OldNtEncryptedWithNewNt, NewNtEncryptedWithOldNt, NtCrossEncryptionPresent,
8068 NewNtEncryptedWithNewLm, LmCrossEncryptionPresent, NewLmEncryptedWithNewNt);
8069
8070 RtlAcquireResourceExclusive(&SampResource,
8071 TRUE);
8072
8073 /* Validate the user handle */
8074 Status = SampValidateDbObject(UserHandle,
8075 SamDbUserObject,
8076 USER_CHANGE_PASSWORD,
8077 &UserObject);
8078 if (!NT_SUCCESS(Status))
8079 {
8080 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
8081 goto done;
8082 }
8083
8084 /* Get the current time */
8085 Status = NtQuerySystemTime(&SystemTime);
8086 if (!NT_SUCCESS(Status))
8087 {
8088 TRACE("NtQuerySystemTime failed (Status 0x%08lx)\n", Status);
8089 goto done;
8090 }
8091
8092 /* Retrieve the LM password */
8093 Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
8094 Status = SampGetObjectAttribute(UserObject,
8095 L"LMPwd",
8096 NULL,
8097 &StoredLmPassword,
8098 &Length);
8099 if (NT_SUCCESS(Status))
8100 {
8101 if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD))
8102 {
8103 StoredLmPresent = TRUE;
8104 if (!RtlEqualMemory(&StoredLmPassword,
8105 &EmptyLmHash,
8106 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
8107 StoredLmEmpty = FALSE;
8108 }
8109 }
8110
8111 /* Retrieve the NT password */
8112 Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
8113 Status = SampGetObjectAttribute(UserObject,
8114 L"NTPwd",
8115 NULL,
8116 &StoredNtPassword,
8117 &Length);
8118 if (NT_SUCCESS(Status))
8119 {
8120 if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD))
8121 {
8122 StoredNtPresent = TRUE;
8123 if (!RtlEqualMemory(&StoredNtPassword,
8124 &EmptyNtHash,
8125 sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
8126 StoredNtEmpty = FALSE;
8127 }
8128 }
8129
8130 /* Retrieve the fixed size user data */
8131 Length = sizeof(SAM_USER_FIXED_DATA);
8132 Status = SampGetObjectAttribute(UserObject,
8133 L"F",
8134 NULL,
8135 &UserFixedData,
8136 &Length);
8137 if (!NT_SUCCESS(Status))
8138 {
8139 TRACE("SampGetObjectAttribute failed to retrieve the fixed user data (Status 0x%08lx)\n", Status);
8140 goto done;
8141 }
8142
8143 /* Check if we can change the password at this time */
8144 if ((StoredNtEmpty == FALSE) || (StoredNtEmpty == FALSE))
8145 {
8146 /* Get fixed domain data */
8147 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
8148 Status = SampGetObjectAttribute(UserObject->ParentObject,
8149 L"F",
8150 NULL,
8151 &DomainFixedData,
8152 &Length);
8153 if (!NT_SUCCESS(Status))
8154 {
8155 TRACE("SampGetObjectAttribute failed to retrieve the fixed domain data (Status 0x%08lx)\n", Status);
8156 return Status;
8157 }
8158
8159 if (DomainFixedData.MinPasswordAge.QuadPart > 0)
8160 {
8161 if (SystemTime.QuadPart < (UserFixedData.PasswordLastSet.QuadPart + DomainFixedData.MinPasswordAge.QuadPart))
8162 return STATUS_ACCOUNT_RESTRICTION;
8163 }
8164 }
8165
8166 /* FIXME: Decrypt passwords */
8167 OldLmPassword = OldLmEncryptedWithNewLm;
8168 NewLmPassword = NewLmEncryptedWithOldLm;
8169 OldNtPassword = OldNtEncryptedWithNewNt;
8170 NewNtPassword = NewNtEncryptedWithOldNt;
8171
8172 /* Check if the old passwords match the stored ones */
8173 if (NtPresent)
8174 {
8175 if (LmPresent)
8176 {
8177 if (!RtlEqualMemory(&StoredLmPassword,
8178 OldLmPassword,
8179 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
8180 {
8181 TRACE("Old LM Password does not match!\n");
8182 Status = STATUS_WRONG_PASSWORD;
8183 }
8184 else
8185 {
8186 if (!RtlEqualMemory(&StoredNtPassword,
8187 OldNtPassword,
8188 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
8189 {
8190 TRACE("Old NT Password does not match!\n");
8191 Status = STATUS_WRONG_PASSWORD;
8192 }
8193 }
8194 }
8195 else
8196 {
8197 if (!RtlEqualMemory(&StoredNtPassword,
8198 OldNtPassword,
8199 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
8200 {
8201 TRACE("Old NT Password does not match!\n");
8202 Status = STATUS_WRONG_PASSWORD;
8203 }
8204 }
8205 }
8206 else
8207 {
8208 if (LmPresent)
8209 {
8210 if (!RtlEqualMemory(&StoredLmPassword,
8211 OldLmPassword,
8212 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
8213 {
8214 TRACE("Old LM Password does not match!\n");
8215 Status = STATUS_WRONG_PASSWORD;
8216 }
8217 }
8218 else
8219 {
8220 Status = STATUS_INVALID_PARAMETER;
8221 }
8222 }
8223
8224 /* Store the new password hashes */
8225 if (NT_SUCCESS(Status))
8226 {
8227 Status = SampSetUserPassword(UserObject,
8228 NewNtPassword,
8229 NtPresent,
8230 NewLmPassword,
8231 LmPresent);
8232 if (NT_SUCCESS(Status))
8233 {
8234 /* Update PasswordLastSet */
8235 UserFixedData.PasswordLastSet.QuadPart = SystemTime.QuadPart;
8236
8237 /* Set the fixed size user data */
8238 Length = sizeof(SAM_USER_FIXED_DATA);
8239 Status = SampSetObjectAttribute(UserObject,
8240 L"F",
8241 REG_BINARY,
8242 &UserFixedData,
8243 Length);
8244 }
8245 }
8246
8247 if (Status == STATUS_WRONG_PASSWORD)
8248 {
8249 /* Update BadPasswordCount and LastBadPasswordTime */
8250 UserFixedData.BadPasswordCount++;
8251 UserFixedData.LastBadPasswordTime.QuadPart = SystemTime.QuadPart;
8252
8253 /* Set the fixed size user data */
8254 Length = sizeof(SAM_USER_FIXED_DATA);
8255 Status = SampSetObjectAttribute(UserObject,
8256 L"F",
8257 REG_BINARY,
8258 &UserFixedData,
8259 Length);
8260 }
8261
8262 done:
8263 RtlReleaseResource(&SampResource);
8264
8265 return Status;
8266 }
8267
8268
8269 /* Function 39 */
8270 NTSTATUS
8271 NTAPI
8272 SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle,
8273 OUT PSAMPR_GET_GROUPS_BUFFER *Groups)
8274 {
8275 PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL;
8276 PSAM_DB_OBJECT UserObject;
8277 ULONG Length = 0;
8278 NTSTATUS Status;
8279
8280 TRACE("SamrGetGroupsForUser(%p %p)\n",
8281 UserHandle, Groups);
8282
8283 RtlAcquireResourceShared(&SampResource,
8284 TRUE);
8285
8286 /* Validate the user handle */
8287 Status = SampValidateDbObject(UserHandle,
8288 SamDbUserObject,
8289 USER_LIST_GROUPS,
8290 &UserObject);
8291 if (!NT_SUCCESS(Status))
8292 {
8293 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
8294 goto done;
8295 }
8296
8297 /* Allocate the groups buffer */
8298 GroupsBuffer = midl_user_allocate(sizeof(SAMPR_GET_GROUPS_BUFFER));
8299 if (GroupsBuffer == NULL)
8300 {
8301 Status = STATUS_INSUFFICIENT_RESOURCES;
8302 goto done;
8303 }
8304
8305 /*
8306 * Get the size of the Groups attribute.
8307 * Do not check the status code because in case of an error
8308 * Length will be 0. And that is all we need.
8309 */
8310 SampGetObjectAttribute(UserObject,
8311 L"Groups",
8312 NULL,
8313 NULL,
8314 &Length);
8315
8316 /* If there is no Groups attribute, return a groups buffer without an array */
8317 if (Length == 0)
8318 {
8319 GroupsBuffer->MembershipCount = 0;
8320 GroupsBuffer->Groups = NULL;
8321
8322 *Groups = GroupsBuffer;
8323
8324 Status = STATUS_SUCCESS;
8325 goto done;
8326 }
8327
8328 /* Allocate a buffer for the Groups attribute */
8329 GroupsBuffer->Groups = midl_user_allocate(Length);
8330 if (GroupsBuffer->Groups == NULL)
8331 {
8332 Status = STATUS_INSUFFICIENT_RESOURCES;
8333 goto done;
8334 }
8335
8336 /* Retrieve the Grous attribute */
8337 Status = SampGetObjectAttribute(UserObject,
8338 L"Groups",
8339 NULL,
8340 GroupsBuffer->Groups,
8341 &Length);
8342 if (!NT_SUCCESS(Status))
8343 {
8344 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
8345 goto done;
8346 }
8347
8348 /* Calculate the membership count */
8349 GroupsBuffer->MembershipCount = Length / sizeof(GROUP_MEMBERSHIP);
8350
8351 /* Return the groups buffer to the caller */
8352 *Groups = GroupsBuffer;
8353
8354 done:
8355 if (!NT_SUCCESS(Status))
8356 {
8357 if (GroupsBuffer != NULL)
8358 {
8359 if (GroupsBuffer->Groups != NULL)
8360 midl_user_free(GroupsBuffer->Groups);
8361
8362 midl_user_free(GroupsBuffer);
8363 }
8364 }
8365
8366 RtlReleaseResource(&SampResource);
8367
8368 return Status;
8369 }
8370
8371
8372 /* Function 40 */
8373 NTSTATUS
8374 NTAPI
8375 SamrQueryDisplayInformation(IN SAMPR_HANDLE DomainHandle,
8376 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
8377 IN unsigned long Index,
8378 IN unsigned long EntryCount,
8379 IN unsigned long PreferredMaximumLength,
8380 OUT unsigned long *TotalAvailable,
8381 OUT unsigned long *TotalReturned,
8382 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
8383 {
8384 UNIMPLEMENTED;
8385 return STATUS_NOT_IMPLEMENTED;
8386 }
8387
8388 /* Function 41 */
8389 NTSTATUS
8390 NTAPI
8391 SamrGetDisplayEnumerationIndex(IN SAMPR_HANDLE DomainHandle,
8392 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
8393 IN PRPC_UNICODE_STRING Prefix,
8394 OUT unsigned long *Index)
8395 {
8396 UNIMPLEMENTED;
8397 return STATUS_NOT_IMPLEMENTED;
8398 }
8399
8400 /* Function 42 */
8401 NTSTATUS
8402 NTAPI
8403 SamrTestPrivateFunctionsDomain(IN SAMPR_HANDLE DomainHandle)
8404 {
8405 UNIMPLEMENTED;
8406 return STATUS_NOT_IMPLEMENTED;
8407 }
8408
8409 /* Function 43 */
8410 NTSTATUS
8411 NTAPI
8412 SamrTestPrivateFunctionsUser(IN SAMPR_HANDLE UserHandle)
8413 {
8414 UNIMPLEMENTED;
8415 return STATUS_NOT_IMPLEMENTED;
8416 }
8417
8418
8419 /* Function 44 */
8420 NTSTATUS
8421 NTAPI
8422 SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
8423 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
8424 {
8425 SAM_DOMAIN_FIXED_DATA DomainFixedData;
8426 SAM_USER_FIXED_DATA UserFixedData;
8427 PSAM_DB_OBJECT DomainObject;
8428 PSAM_DB_OBJECT UserObject;
8429 ULONG Length = 0;
8430 NTSTATUS Status;
8431
8432 TRACE("(%p %p)\n",
8433 UserHandle, PasswordInformation);
8434
8435 RtlAcquireResourceShared(&SampResource,
8436 TRUE);
8437
8438 /* Validate the user handle */
8439 Status = SampValidateDbObject(UserHandle,
8440 SamDbUserObject,
8441 0,
8442 &UserObject);
8443 if (!NT_SUCCESS(Status))
8444 {
8445 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
8446 goto done;
8447 }
8448
8449 /* Validate the domain object */
8450 Status = SampValidateDbObject((SAMPR_HANDLE)UserObject->ParentObject,
8451 SamDbDomainObject,
8452 DOMAIN_READ_PASSWORD_PARAMETERS,
8453 &DomainObject);
8454 if (!NT_SUCCESS(Status))
8455 {
8456 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
8457 goto done;
8458 }
8459
8460 /* Get fixed user data */
8461 Length = sizeof(SAM_USER_FIXED_DATA);
8462 Status = SampGetObjectAttribute(UserObject,
8463 L"F",
8464 NULL,
8465 (PVOID)&UserFixedData,
8466 &Length);
8467 if (!NT_SUCCESS(Status))
8468 {
8469 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
8470 goto done;
8471 }
8472
8473 if ((UserObject->RelativeId == DOMAIN_USER_RID_KRBTGT) ||
8474 (UserFixedData.UserAccountControl & (USER_INTERDOMAIN_TRUST_ACCOUNT |
8475 USER_WORKSTATION_TRUST_ACCOUNT |
8476 USER_SERVER_TRUST_ACCOUNT)))
8477 {
8478 PasswordInformation->MinPasswordLength = 0;
8479 PasswordInformation->PasswordProperties = 0;
8480 }
8481 else
8482 {
8483 /* Get fixed domain data */
8484 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
8485 Status = SampGetObjectAttribute(DomainObject,
8486 L"F",
8487 NULL,
8488 (PVOID)&DomainFixedData,
8489 &Length);
8490 if (!NT_SUCCESS(Status))
8491 {
8492 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status);
8493 goto done;
8494 }
8495
8496 PasswordInformation->MinPasswordLength = DomainFixedData.MinPasswordLength;
8497 PasswordInformation->PasswordProperties = DomainFixedData.PasswordProperties;
8498 }
8499
8500 done:
8501 RtlReleaseResource(&SampResource);
8502
8503 return STATUS_SUCCESS;
8504 }
8505
8506
8507 /* Function 45 */
8508 NTSTATUS
8509 NTAPI
8510 SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
8511 IN PRPC_SID MemberSid)
8512 {
8513 PSAM_DB_OBJECT DomainObject;
8514 ULONG Rid = 0;
8515 NTSTATUS Status;
8516
8517 TRACE("(%p %p)\n",
8518 DomainHandle, MemberSid);
8519
8520 RtlAcquireResourceExclusive(&SampResource,
8521 TRUE);
8522
8523 /* Validate the domain object */
8524 Status = SampValidateDbObject(DomainHandle,
8525 SamDbDomainObject,
8526 DOMAIN_LOOKUP,
8527 &DomainObject);
8528 if (!NT_SUCCESS(Status))
8529 {
8530 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status);
8531 goto done;
8532 }
8533
8534 /* Retrieve the RID from the MemberSID */
8535 Status = SampGetRidFromSid((PSID)MemberSid,
8536 &Rid);
8537 if (!NT_SUCCESS(Status))
8538 {
8539 TRACE("SampGetRidFromSid failed with status 0x%08lx\n", Status);
8540 goto done;
8541 }
8542
8543 /* Fail, if the RID represents a special account */
8544 if (Rid < 1000)
8545 {
8546 TRACE("Cannot remove a special account (RID: %lu)\n", Rid);
8547 Status = STATUS_SPECIAL_ACCOUNT;
8548 goto done;
8549 }
8550
8551 /* Remove the member from all aliases in the domain */
8552 Status = SampRemoveMemberFromAllAliases(DomainObject,
8553 MemberSid);
8554 if (!NT_SUCCESS(Status))
8555 {
8556 TRACE("SampRemoveMemberFromAllAliases failed with status 0x%08lx\n", Status);
8557 }
8558
8559 done:
8560 RtlReleaseResource(&SampResource);
8561
8562 return Status;
8563 }
8564
8565
8566 /* Function 46 */
8567 NTSTATUS
8568 NTAPI
8569 SamrQueryInformationDomain2(IN SAMPR_HANDLE DomainHandle,
8570 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
8571 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
8572 {
8573 TRACE("(%p %lu %p)\n", DomainHandle, DomainInformationClass, Buffer);
8574
8575 return SamrQueryInformationDomain(DomainHandle,
8576 DomainInformationClass,
8577 Buffer);
8578 }
8579
8580
8581 /* Function 47 */
8582 NTSTATUS
8583 NTAPI
8584 SamrQueryInformationUser2(IN SAMPR_HANDLE UserHandle,
8585 IN USER_INFORMATION_CLASS UserInformationClass,
8586 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
8587 {
8588 TRACE("(%p %lu %p)\n", UserHandle, UserInformationClass, Buffer);
8589
8590 return SamrQueryInformationUser(UserHandle,
8591 UserInformationClass,
8592 Buffer);
8593 }
8594
8595
8596 /* Function 48 */
8597 NTSTATUS
8598 NTAPI
8599 SamrQueryDisplayInformation2(IN SAMPR_HANDLE DomainHandle,
8600 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
8601 IN unsigned long Index,
8602 IN unsigned long EntryCount,
8603 IN unsigned long PreferredMaximumLength,
8604 OUT unsigned long *TotalAvailable,
8605 OUT unsigned long *TotalReturned,
8606 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
8607 {
8608 TRACE("%p %lu %lu %lu %lu %p %p %p\n",
8609 DomainHandle, DisplayInformationClass, Index,
8610 EntryCount, PreferredMaximumLength, TotalAvailable,
8611 TotalReturned, Buffer);
8612
8613 return SamrQueryDisplayInformation(DomainHandle,
8614 DisplayInformationClass,
8615 Index,
8616 EntryCount,
8617 PreferredMaximumLength,
8618 TotalAvailable,
8619 TotalReturned,
8620 Buffer);
8621 }
8622
8623
8624 /* Function 49 */
8625 NTSTATUS
8626 NTAPI
8627 SamrGetDisplayEnumerationIndex2(IN SAMPR_HANDLE DomainHandle,
8628 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
8629 IN PRPC_UNICODE_STRING Prefix,
8630 OUT unsigned long *Index)
8631 {
8632 TRACE("(%p %lu %p %p)\n",
8633 DomainHandle, DisplayInformationClass, Prefix, Index);
8634
8635 return SamrGetDisplayEnumerationIndex(DomainHandle,
8636 DisplayInformationClass,
8637 Prefix,
8638 Index);
8639 }
8640
8641
8642 /* Function 50 */
8643 NTSTATUS
8644 NTAPI
8645 SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
8646 IN PRPC_UNICODE_STRING Name,
8647 IN unsigned long AccountType,
8648 IN ACCESS_MASK DesiredAccess,
8649 OUT SAMPR_HANDLE *UserHandle,
8650 OUT unsigned long *GrantedAccess,
8651 OUT unsigned long *RelativeId)
8652 {
8653 SAM_DOMAIN_FIXED_DATA FixedDomainData;
8654 SAM_USER_FIXED_DATA FixedUserData;
8655 PSAM_DB_OBJECT DomainObject;
8656 PSAM_DB_OBJECT UserObject;
8657 GROUP_MEMBERSHIP GroupMembership;
8658 UCHAR LogonHours[23];
8659 ULONG ulSize;
8660 ULONG ulRid;
8661 WCHAR szRid[9];
8662 PSECURITY_DESCRIPTOR Sd = NULL;
8663 ULONG SdSize = 0;
8664 PSID UserSid = NULL;
8665 NTSTATUS Status;
8666
8667 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
8668 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
8669
8670 if (Name == NULL ||
8671 Name->Length == 0 ||
8672 Name->Buffer == NULL ||
8673 UserHandle == NULL ||
8674 RelativeId == NULL)
8675 return STATUS_INVALID_PARAMETER;
8676
8677 /* Check for valid account type */
8678 if (AccountType != USER_NORMAL_ACCOUNT &&
8679 AccountType != USER_WORKSTATION_TRUST_ACCOUNT &&
8680 AccountType != USER_INTERDOMAIN_TRUST_ACCOUNT &&
8681 AccountType != USER_SERVER_TRUST_ACCOUNT &&
8682 AccountType != USER_TEMP_DUPLICATE_ACCOUNT)
8683 return STATUS_INVALID_PARAMETER;
8684
8685 /* Map generic access rights */
8686 RtlMapGenericMask(&DesiredAccess,
8687 &UserMapping);
8688
8689 RtlAcquireResourceExclusive(&SampResource,
8690 TRUE);
8691
8692 /* Validate the domain handle */
8693 Status = SampValidateDbObject(DomainHandle,
8694 SamDbDomainObject,
8695 DOMAIN_CREATE_USER,
8696 &DomainObject);
8697 if (!NT_SUCCESS(Status))
8698 {
8699 TRACE("failed with status 0x%08lx\n", Status);
8700 goto done;
8701 }
8702
8703 /* Check the user account name */
8704 Status = SampCheckAccountName(Name, 20);
8705 if (!NT_SUCCESS(Status))
8706 {
8707 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status);
8708 goto done;
8709 }
8710
8711 /* Check if the user name already exists in the domain */
8712 Status = SampCheckAccountNameInDomain(DomainObject,
8713 Name->Buffer);
8714 if (!NT_SUCCESS(Status))
8715 {
8716 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
8717 Name->Buffer, Status);
8718 goto done;
8719 }
8720
8721 /* Get the fixed domain attributes */
8722 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
8723 Status = SampGetObjectAttribute(DomainObject,
8724 L"F",
8725 NULL,
8726 (PVOID)&FixedDomainData,
8727 &ulSize);
8728 if (!NT_SUCCESS(Status))
8729 {
8730 TRACE("failed with status 0x%08lx\n", Status);
8731 goto done;
8732 }
8733
8734 /* Increment the NextRid attribute */
8735 ulRid = FixedDomainData.NextRid;
8736 FixedDomainData.NextRid++;
8737
8738 TRACE("RID: %lx\n", ulRid);
8739
8740 /* Create the user SID */
8741 Status = SampCreateAccountSid(DomainObject,
8742 ulRid,
8743 &UserSid);
8744 if (!NT_SUCCESS(Status))
8745 {
8746 TRACE("SampCreateAccountSid failed (Status 0x%08lx)\n", Status);
8747 goto done;
8748 }
8749
8750 /* Create the security descriptor */
8751 Status = SampCreateUserSD(UserSid,
8752 &Sd,
8753 &SdSize);
8754 if (!NT_SUCCESS(Status))
8755 {
8756 TRACE("SampCreateUserSD failed (Status 0x%08lx)\n", Status);
8757 goto done;
8758 }
8759
8760 /* Store the fixed domain attributes */
8761 Status = SampSetObjectAttribute(DomainObject,
8762 L"F",
8763 REG_BINARY,
8764 &FixedDomainData,
8765 ulSize);
8766 if (!NT_SUCCESS(Status))
8767 {
8768 TRACE("failed with status 0x%08lx\n", Status);
8769 goto done;
8770 }
8771
8772 /* Convert the RID into a string (hex) */
8773 swprintf(szRid, L"%08lX", ulRid);
8774
8775 /* Create the user object */
8776 Status = SampCreateDbObject(DomainObject,
8777 L"Users",
8778 szRid,
8779 ulRid,
8780 SamDbUserObject,
8781 DesiredAccess,
8782 &UserObject);
8783 if (!NT_SUCCESS(Status))
8784 {
8785 TRACE("failed with status 0x%08lx\n", Status);
8786 goto done;
8787 }
8788
8789 /* Add the account name for the user object */
8790 Status = SampSetAccountNameInDomain(DomainObject,
8791 L"Users",
8792 Name->Buffer,
8793 ulRid);
8794 if (!NT_SUCCESS(Status))
8795 {
8796 TRACE("failed with status 0x%08lx\n", Status);
8797 goto done;
8798 }
8799
8800 /* Initialize fixed user data */
8801 FixedUserData.Version = 1;
8802 FixedUserData.Reserved = 0;
8803 FixedUserData.LastLogon.QuadPart = 0;
8804 FixedUserData.LastLogoff.QuadPart = 0;
8805 FixedUserData.PasswordLastSet.QuadPart = 0;
8806 FixedUserData.AccountExpires.LowPart = MAXULONG;
8807 FixedUserData.AccountExpires.HighPart = MAXLONG;
8808 FixedUserData.LastBadPasswordTime.QuadPart = 0;
8809 FixedUserData.UserId = ulRid;
8810 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
8811 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
8812 USER_PASSWORD_NOT_REQUIRED |
8813 AccountType;
8814 FixedUserData.CountryCode = 0;
8815 FixedUserData.CodePage = 0;
8816 FixedUserData.BadPasswordCount = 0;
8817 FixedUserData.LogonCount = 0;
8818 FixedUserData.AdminCount = 0;
8819 FixedUserData.OperatorCount = 0;
8820
8821 /* Set fixed user data attribute */
8822 Status = SampSetObjectAttribute(UserObject,
8823 L"F",
8824 REG_BINARY,
8825 (LPVOID)&FixedUserData,
8826 sizeof(SAM_USER_FIXED_DATA));
8827 if (!NT_SUCCESS(Status))
8828 {
8829 TRACE("failed with status 0x%08lx\n", Status);
8830 goto done;
8831 }
8832
8833 /* Set the Name attribute */
8834 Status = SampSetObjectAttributeString(UserObject,
8835 L"Name",
8836 Name);
8837 if (!NT_SUCCESS(Status))
8838 {
8839 TRACE("failed with status 0x%08lx\n", Status);
8840 goto done;
8841 }
8842
8843 /* Set the FullName attribute */
8844 Status = SampSetObjectAttributeString(UserObject,
8845 L"FullName",
8846 NULL);
8847 if (!NT_SUCCESS(Status))
8848 {
8849 TRACE("failed with status 0x%08lx\n", Status);
8850 goto done;
8851 }
8852
8853 /* Set the HomeDirectory attribute */
8854 Status = SampSetObjectAttributeString(UserObject,
8855 L"HomeDirectory",
8856 NULL);
8857 if (!NT_SUCCESS(Status))
8858 {
8859 TRACE("failed with status 0x%08lx\n", Status);
8860 goto done;
8861 }
8862
8863 /* Set the HomeDirectoryDrive attribute */
8864 Status = SampSetObjectAttributeString(UserObject,
8865 L"HomeDirectoryDrive",
8866 NULL);
8867 if (!NT_SUCCESS(Status))
8868 {
8869 TRACE("failed with status 0x%08lx\n", Status);
8870 goto done;
8871 }
8872
8873 /* Set the ScriptPath attribute */
8874 Status = SampSetObjectAttributeString(UserObject,
8875 L"ScriptPath",
8876 NULL);
8877 if (!NT_SUCCESS(Status))
8878 {
8879 TRACE("failed with status 0x%08lx\n", Status);
8880 goto done;
8881 }
8882
8883 /* Set the ProfilePath attribute */
8884 Status = SampSetObjectAttributeString(UserObject,
8885 L"ProfilePath",
8886 NULL);
8887 if (!NT_SUCCESS(Status))
8888 {
8889 TRACE("failed with status 0x%08lx\n", Status);
8890 goto done;
8891 }
8892
8893 /* Set the AdminComment attribute */
8894 Status = SampSetObjectAttributeString(UserObject,
8895 L"AdminComment",
8896 NULL);
8897 if (!NT_SUCCESS(Status))
8898 {
8899 TRACE("failed with status 0x%08lx\n", Status);
8900 goto done;
8901 }
8902
8903 /* Set the UserComment attribute */
8904 Status = SampSetObjectAttributeString(UserObject,
8905 L"UserComment",
8906 NULL);
8907 if (!NT_SUCCESS(Status))
8908 {
8909 TRACE("failed with status 0x%08lx\n", Status);
8910 goto done;
8911 }
8912
8913 /* Set the WorkStations attribute */
8914 Status = SampSetObjectAttributeString(UserObject,
8915 L"WorkStations",
8916 NULL);
8917 if (!NT_SUCCESS(Status))
8918 {
8919 TRACE("failed with status 0x%08lx\n", Status);
8920 goto done;
8921 }
8922
8923 /* Set the Parameters attribute */
8924 Status = SampSetObjectAttributeString(UserObject,
8925 L"Parameters",
8926 NULL);
8927 if (!NT_SUCCESS(Status))
8928 {
8929 TRACE("failed with status 0x%08lx\n", Status);
8930 goto done;
8931 }
8932
8933 /* Set LogonHours attribute*/
8934 *((PUSHORT)LogonHours) = 168;
8935 memset(&(LogonHours[2]), 0xff, 21);
8936
8937 Status = SampSetObjectAttribute(UserObject,
8938 L"LogonHours",
8939 REG_BINARY,
8940 &LogonHours,
8941 sizeof(LogonHours));
8942 if (!NT_SUCCESS(Status))
8943 {
8944 TRACE("failed with status 0x%08lx\n", Status);
8945 goto done;
8946 }
8947
8948 /* Set Groups attribute*/
8949 GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS;
8950 GroupMembership.Attributes = SE_GROUP_MANDATORY |
8951 SE_GROUP_ENABLED |
8952 SE_GROUP_ENABLED_BY_DEFAULT;
8953
8954 Status = SampSetObjectAttribute(UserObject,
8955 L"Groups",
8956 REG_BINARY,
8957 &GroupMembership,
8958 sizeof(GROUP_MEMBERSHIP));
8959 if (!NT_SUCCESS(Status))
8960 {
8961 TRACE("failed with status 0x%08lx\n", Status);
8962 goto done;
8963 }
8964
8965 /* Set LMPwd attribute*/
8966 Status = SampSetObjectAttribute(UserObject,
8967 L"LMPwd",
8968 REG_BINARY,
8969 NULL,
8970 0);
8971 if (!NT_SUCCESS(Status))
8972 {
8973 TRACE("failed with status 0x%08lx\n", Status);
8974 goto done;
8975 }
8976
8977 /* Set NTPwd attribute*/
8978 Status = SampSetObjectAttribute(UserObject,
8979 L"NTPwd",
8980 REG_BINARY,
8981 NULL,
8982 0);
8983 if (!NT_SUCCESS(Status))
8984 {
8985 TRACE("failed with status 0x%08lx\n", Status);
8986 goto done;
8987 }
8988
8989 /* Set LMPwdHistory attribute*/
8990 Status = SampSetObjectAttribute(UserObject,
8991 L"LMPwdHistory",
8992 REG_BINARY,
8993 NULL,
8994 0);
8995 if (!NT_SUCCESS(Status))
8996 {
8997 TRACE("failed with status 0x%08lx\n", Status);
8998 goto done;
8999 }
9000
9001 /* Set NTPwdHistory attribute*/
9002 Status = SampSetObjectAttribute(UserObject,
9003 L"NTPwdHistory",
9004 REG_BINARY,
9005 NULL,
9006 0);
9007 if (!NT_SUCCESS(Status))
9008 {
9009 TRACE("failed with status 0x%08lx\n", Status);
9010 goto done;
9011 }
9012
9013 /* Set the PrivateData attribute */
9014 Status = SampSetObjectAttributeString(UserObject,
9015 L"PrivateData",
9016 NULL);
9017 if (!NT_SUCCESS(Status))
9018 {
9019 TRACE("failed with status 0x%08lx\n", Status);
9020 goto done;
9021 }
9022
9023 /* Set the SecDesc attribute*/
9024 Status = SampSetObjectAttribute(UserObject,
9025 L"SecDesc",
9026 REG_BINARY,
9027 Sd,
9028 SdSize);
9029 if (!NT_SUCCESS(Status))
9030 {
9031 TRACE("failed with status 0x%08lx\n", Status);
9032 goto done;
9033 }
9034
9035 if (NT_SUCCESS(Status))
9036 {
9037 *UserHandle = (SAMPR_HANDLE)UserObject;
9038 *RelativeId = ulRid;
9039 *GrantedAccess = UserObject->Access;
9040 }
9041
9042 done:
9043 if (Sd != NULL)
9044 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
9045
9046 if (UserSid != NULL)
9047 RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid);
9048
9049 RtlReleaseResource(&SampResource);
9050
9051 TRACE("returns with status 0x%08lx\n", Status);
9052
9053 return Status;
9054 }
9055
9056
9057 /* Function 51 */
9058 NTSTATUS
9059 NTAPI
9060 SamrQueryDisplayInformation3(IN SAMPR_HANDLE DomainHandle,
9061 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
9062 IN unsigned long Index,
9063 IN unsigned long EntryCount,
9064 IN unsigned long PreferredMaximumLength,
9065 OUT unsigned long *TotalAvailable,
9066 OUT unsigned long *TotalReturned,
9067 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
9068 {
9069 TRACE("%p %lu %lu %lu %lu %p %p %p\n",
9070 DomainHandle, DisplayInformationClass, Index,
9071 EntryCount, PreferredMaximumLength, TotalAvailable,
9072 TotalReturned, Buffer);
9073
9074 return SamrQueryDisplayInformation(DomainHandle,
9075 DisplayInformationClass,
9076 Index,
9077 EntryCount,
9078 PreferredMaximumLength,
9079 TotalAvailable,
9080 TotalReturned,
9081 Buffer);
9082 }
9083
9084
9085 /* Function 52 */
9086 NTSTATUS
9087 NTAPI
9088 SamrAddMultipleMembersToAlias(IN SAMPR_HANDLE AliasHandle,
9089 IN PSAMPR_PSID_ARRAY MembersBuffer)
9090 {
9091 ULONG i;
9092 NTSTATUS Status = STATUS_SUCCESS;
9093
9094 TRACE("SamrAddMultipleMembersToAlias(%p %p)\n",
9095 AliasHandle, MembersBuffer);
9096
9097 for (i = 0; i < MembersBuffer->Count; i++)
9098 {
9099 Status = SamrAddMemberToAlias(AliasHandle,
9100 ((PSID *)MembersBuffer->Sids)[i]);
9101
9102 if (Status == STATUS_MEMBER_IN_ALIAS)
9103 Status = STATUS_SUCCESS;
9104
9105 if (!NT_SUCCESS(Status))
9106 break;
9107 }
9108
9109 return Status;
9110 }
9111
9112
9113 /* Function 53 */
9114 NTSTATUS
9115 NTAPI
9116 SamrRemoveMultipleMembersFromAlias(IN SAMPR_HANDLE AliasHandle,
9117 IN PSAMPR_PSID_ARRAY MembersBuffer)
9118 {
9119 ULONG i;
9120 NTSTATUS Status = STATUS_SUCCESS;
9121
9122 TRACE("SamrRemoveMultipleMembersFromAlias(%p %p)\n",
9123 AliasHandle, MembersBuffer);
9124
9125 for (i = 0; i < MembersBuffer->Count; i++)
9126 {
9127 Status = SamrRemoveMemberFromAlias(AliasHandle,
9128 ((PSID *)MembersBuffer->Sids)[i]);
9129
9130 if (Status == STATUS_MEMBER_IN_ALIAS)
9131 Status = STATUS_SUCCESS;
9132
9133 if (!NT_SUCCESS(Status))
9134 break;
9135 }
9136
9137 return Status;
9138 }
9139
9140
9141 /* Function 54 */
9142 NTSTATUS
9143 NTAPI
9144 SamrOemChangePasswordUser2(IN handle_t BindingHandle,
9145 IN PRPC_STRING ServerName,
9146 IN PRPC_STRING UserName,
9147 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
9148 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewLm)
9149 {
9150 UNIMPLEMENTED;
9151 return STATUS_NOT_IMPLEMENTED;
9152 }
9153
9154 /* Function 55 */
9155 NTSTATUS
9156 NTAPI
9157 SamrUnicodeChangePasswordUser2(IN handle_t BindingHandle,
9158 IN PRPC_UNICODE_STRING ServerName,
9159 IN PRPC_UNICODE_STRING UserName,
9160 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldNt,
9161 IN PENCRYPTED_NT_OWF_PASSWORD OldNtOwfPasswordEncryptedWithNewNt,
9162 IN unsigned char LmPresent,
9163 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
9164 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewNt)
9165 {
9166 UNIMPLEMENTED;
9167 return STATUS_NOT_IMPLEMENTED;
9168 }
9169
9170 /* Function 56 */
9171 NTSTATUS
9172 NTAPI
9173 SamrGetDomainPasswordInformation(IN handle_t BindingHandle,
9174 IN PRPC_UNICODE_STRING Unused,
9175 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
9176 {
9177 UNIMPLEMENTED;
9178 return STATUS_NOT_IMPLEMENTED;
9179 }
9180
9181
9182 /* Function 57 */
9183 NTSTATUS
9184 NTAPI
9185 SamrConnect2(IN PSAMPR_SERVER_NAME ServerName,
9186 OUT SAMPR_HANDLE *ServerHandle,
9187 IN ACCESS_MASK DesiredAccess)
9188 {
9189 TRACE("(%p %p %lx)\n", ServerName, ServerHandle, DesiredAccess);
9190
9191 return SamrConnect(ServerName,
9192 ServerHandle,
9193 DesiredAccess);
9194 }
9195
9196
9197 /* Function 58 */
9198 NTSTATUS
9199 NTAPI
9200 SamrSetInformationUser2(IN SAMPR_HANDLE UserHandle,
9201 IN USER_INFORMATION_CLASS UserInformationClass,
9202 IN PSAMPR_USER_INFO_BUFFER Buffer)
9203 {
9204 TRACE("(%p %lu %p)\n", UserHandle, UserInformationClass, Buffer);
9205
9206 return SamrSetInformationUser(UserHandle,
9207 UserInformationClass,
9208 Buffer);
9209 }
9210
9211
9212 /* Function 59 */
9213 NTSTATUS
9214 NTAPI
9215 SamrSetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
9216 {
9217 UNIMPLEMENTED;
9218 return STATUS_NOT_IMPLEMENTED;
9219 }
9220
9221 /* Function 60 */
9222 NTSTATUS
9223 NTAPI
9224 SamrGetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
9225 {
9226 UNIMPLEMENTED;
9227 return STATUS_NOT_IMPLEMENTED;
9228 }
9229
9230 /* Function 61 */
9231 NTSTATUS
9232 NTAPI
9233 SamrConnect3(IN handle_t BindingHandle) /* FIXME */
9234 {
9235 UNIMPLEMENTED;
9236 return STATUS_NOT_IMPLEMENTED;
9237 }
9238
9239 /* Function 62 */
9240 NTSTATUS
9241 NTAPI
9242 SamrConnect4(IN PSAMPR_SERVER_NAME ServerName,
9243 OUT SAMPR_HANDLE *ServerHandle,
9244 IN unsigned long ClientRevision,
9245 IN ACCESS_MASK DesiredAccess)
9246 {
9247 UNIMPLEMENTED;
9248 return STATUS_NOT_IMPLEMENTED;
9249 }
9250
9251 /* Function 63 */
9252 NTSTATUS
9253 NTAPI
9254 SamrUnicodeChangePasswordUser3(IN handle_t BindingHandle) /* FIXME */
9255 {
9256 UNIMPLEMENTED;
9257 return STATUS_NOT_IMPLEMENTED;
9258 }
9259
9260 /* Function 64 */
9261 NTSTATUS
9262 NTAPI
9263 SamrConnect5(IN PSAMPR_SERVER_NAME ServerName,
9264 IN ACCESS_MASK DesiredAccess,
9265 IN unsigned long InVersion,
9266 IN SAMPR_REVISION_INFO *InRevisionInfo,
9267 OUT unsigned long *OutVersion,
9268 OUT SAMPR_REVISION_INFO *OutRevisionInfo,
9269 OUT SAMPR_HANDLE *ServerHandle)
9270 {
9271 UNIMPLEMENTED;
9272 return STATUS_NOT_IMPLEMENTED;
9273 }
9274
9275 /* Function 65 */
9276 NTSTATUS
9277 NTAPI
9278 SamrRidToSid(IN SAMPR_HANDLE ObjectHandle,
9279 IN unsigned long Rid,
9280 OUT PRPC_SID *Sid)
9281 {
9282 UNIMPLEMENTED;
9283 return STATUS_NOT_IMPLEMENTED;
9284 }
9285
9286 /* Function 66 */
9287 NTSTATUS
9288 NTAPI
9289 SamrSetDSRMPassword(IN handle_t BindingHandle,
9290 IN PRPC_UNICODE_STRING Unused,
9291 IN unsigned long UserId,
9292 IN PENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword)
9293 {
9294 UNIMPLEMENTED;
9295 return STATUS_NOT_IMPLEMENTED;
9296 }
9297
9298 /* Function 67 */
9299 NTSTATUS
9300 NTAPI
9301 SamrValidatePassword(IN handle_t Handle,
9302 IN PASSWORD_POLICY_VALIDATION_TYPE ValidationType,
9303 IN PSAM_VALIDATE_INPUT_ARG InputArg,
9304 OUT PSAM_VALIDATE_OUTPUT_ARG *OutputArg)
9305 {
9306 UNIMPLEMENTED;
9307 return STATUS_NOT_IMPLEMENTED;
9308 }
9309
9310 /* EOF */