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