Sync with trunk revision r58045 to bring the corrections on configure.cmd and on...
[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
21 /* FUNCTIONS *****************************************************************/
22
23 VOID
24 SampStartRpcServer(VOID)
25 {
26 RPC_STATUS Status;
27
28 TRACE("SampStartRpcServer() called\n");
29
30 Status = RpcServerUseProtseqEpW(L"ncacn_np",
31 10,
32 L"\\pipe\\samr",
33 NULL);
34 if (Status != RPC_S_OK)
35 {
36 WARN("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
37 return;
38 }
39
40 Status = RpcServerRegisterIf(samr_v1_0_s_ifspec,
41 NULL,
42 NULL);
43 if (Status != RPC_S_OK)
44 {
45 WARN("RpcServerRegisterIf() failed (Status %lx)\n", Status);
46 return;
47 }
48
49 Status = RpcServerListen(1, 20, TRUE);
50 if (Status != RPC_S_OK)
51 {
52 WARN("RpcServerListen() failed (Status %lx)\n", Status);
53 return;
54 }
55
56 TRACE("SampStartRpcServer() done\n");
57 }
58
59
60 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
61 {
62 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
63 }
64
65
66 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
67 {
68 HeapFree(GetProcessHeap(), 0, ptr);
69 }
70
71 void __RPC_USER SAMPR_HANDLE_rundown(SAMPR_HANDLE hHandle)
72 {
73 }
74
75 /* Function 0 */
76 NTSTATUS
77 NTAPI
78 SamrConnect(IN PSAMPR_SERVER_NAME ServerName,
79 OUT SAMPR_HANDLE *ServerHandle,
80 IN ACCESS_MASK DesiredAccess)
81 {
82 PSAM_DB_OBJECT ServerObject;
83 NTSTATUS Status;
84
85 TRACE("SamrConnect(%p %p %lx)\n",
86 ServerName, ServerHandle, DesiredAccess);
87
88 Status = SampOpenDbObject(NULL,
89 NULL,
90 L"SAM",
91 0,
92 SamDbServerObject,
93 DesiredAccess,
94 &ServerObject);
95 if (NT_SUCCESS(Status))
96 *ServerHandle = (SAMPR_HANDLE)ServerObject;
97
98 TRACE("SamrConnect done (Status 0x%08lx)\n", Status);
99
100 return Status;
101 }
102
103 /* Function 1 */
104 NTSTATUS
105 NTAPI
106 SamrCloseHandle(IN OUT SAMPR_HANDLE *SamHandle)
107 {
108 PSAM_DB_OBJECT DbObject;
109 NTSTATUS Status = STATUS_SUCCESS;
110
111 TRACE("SamrCloseHandle(%p)\n", SamHandle);
112
113 Status = SampValidateDbObject(*SamHandle,
114 SamDbIgnoreObject,
115 0,
116 &DbObject);
117 if (Status == STATUS_SUCCESS)
118 {
119 Status = SampCloseDbObject(DbObject);
120 *SamHandle = NULL;
121 }
122
123 TRACE("SamrCloseHandle done (Status 0x%08lx)\n", Status);
124
125 return Status;
126 }
127
128 /* Function 2 */
129 NTSTATUS
130 NTAPI
131 SamrSetSecurityObject(IN SAMPR_HANDLE ObjectHandle,
132 IN SECURITY_INFORMATION SecurityInformation,
133 IN PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor)
134 {
135 UNIMPLEMENTED;
136 return STATUS_NOT_IMPLEMENTED;
137 }
138
139 /* Function 3 */
140 NTSTATUS
141 NTAPI
142 SamrQuerySecurityObject(IN SAMPR_HANDLE ObjectHandle,
143 IN SECURITY_INFORMATION SecurityInformation,
144 OUT PSAMPR_SR_SECURITY_DESCRIPTOR * SecurityDescriptor)
145 {
146 UNIMPLEMENTED;
147 return STATUS_NOT_IMPLEMENTED;
148 }
149
150 /* Function 4 */
151 NTSTATUS
152 NTAPI
153 SamrShutdownSamServer(IN SAMPR_HANDLE ServerHandle)
154 {
155 UNIMPLEMENTED;
156 return STATUS_NOT_IMPLEMENTED;
157 }
158
159
160 /* Function 5 */
161 NTSTATUS
162 NTAPI
163 SamrLookupDomainInSamServer(IN SAMPR_HANDLE ServerHandle,
164 IN PRPC_UNICODE_STRING Name,
165 OUT PRPC_SID *DomainId)
166 {
167 PSAM_DB_OBJECT ServerObject;
168 HANDLE DomainsKeyHandle = NULL;
169 HANDLE DomainKeyHandle = NULL;
170 WCHAR DomainKeyName[64];
171 ULONG Index;
172 WCHAR DomainNameString[MAX_COMPUTERNAME_LENGTH + 1];
173 UNICODE_STRING DomainName;
174 ULONG Length;
175 BOOL Found = FALSE;
176 NTSTATUS Status;
177
178 TRACE("SamrLookupDomainInSamServer(%p %p %p)\n",
179 ServerHandle, Name, DomainId);
180
181 /* Validate the server handle */
182 Status = SampValidateDbObject(ServerHandle,
183 SamDbServerObject,
184 SAM_SERVER_LOOKUP_DOMAIN,
185 &ServerObject);
186 if (!NT_SUCCESS(Status))
187 return Status;
188
189 *DomainId = NULL;
190
191 Status = SampRegOpenKey(ServerObject->KeyHandle,
192 L"Domains",
193 KEY_READ,
194 &DomainsKeyHandle);
195 if (!NT_SUCCESS(Status))
196 return Status;
197
198 Index = 0;
199 while (Found == FALSE)
200 {
201 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
202 Index,
203 64,
204 DomainKeyName);
205 if (!NT_SUCCESS(Status))
206 {
207 if (Status == STATUS_NO_MORE_ENTRIES)
208 Status = STATUS_NO_SUCH_DOMAIN;
209 break;
210 }
211
212 TRACE("Domain key name: %S\n", DomainKeyName);
213
214 Status = SampRegOpenKey(DomainsKeyHandle,
215 DomainKeyName,
216 KEY_READ,
217 &DomainKeyHandle);
218 if (NT_SUCCESS(Status))
219 {
220 Length = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR);
221 Status = SampRegQueryValue(DomainKeyHandle,
222 L"Name",
223 NULL,
224 (PVOID)&DomainNameString,
225 &Length);
226 if (NT_SUCCESS(Status))
227 {
228 TRACE("Domain name: %S\n", DomainNameString);
229
230 RtlInitUnicodeString(&DomainName,
231 DomainNameString);
232 if (RtlEqualUnicodeString(&DomainName, (PUNICODE_STRING)Name, TRUE))
233 {
234 TRACE("Found it!\n");
235 Found = TRUE;
236
237 Status = SampRegQueryValue(DomainKeyHandle,
238 L"SID",
239 NULL,
240 NULL,
241 &Length);
242 if (NT_SUCCESS(Status))
243 {
244 *DomainId = midl_user_allocate(Length);
245
246 SampRegQueryValue(DomainKeyHandle,
247 L"SID",
248 NULL,
249 (PVOID)*DomainId,
250 &Length);
251
252 Status = STATUS_SUCCESS;
253 break;
254 }
255 }
256 }
257
258 NtClose(DomainKeyHandle);
259 }
260
261 Index++;
262 }
263
264 NtClose(DomainsKeyHandle);
265
266 return Status;
267 }
268
269
270 /* Function 6 */
271 NTSTATUS
272 NTAPI
273 SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle,
274 IN OUT unsigned long *EnumerationContext,
275 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
276 IN ULONG PreferedMaximumLength,
277 OUT PULONG CountReturned)
278 {
279 PSAM_DB_OBJECT ServerObject;
280 WCHAR DomainKeyName[64];
281 HANDLE DomainsKeyHandle;
282 HANDLE DomainKeyHandle;
283 ULONG EnumIndex;
284 ULONG EnumCount;
285 ULONG RequiredLength;
286 ULONG DataLength;
287 ULONG i;
288 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
289 NTSTATUS Status;
290
291 TRACE("SamrEnumerateDomainsInSamServer(%p %p %p %lu %p)\n",
292 ServerHandle, EnumerationContext, Buffer, PreferedMaximumLength,
293 CountReturned);
294
295 /* Validate the server handle */
296 Status = SampValidateDbObject(ServerHandle,
297 SamDbServerObject,
298 SAM_SERVER_ENUMERATE_DOMAINS,
299 &ServerObject);
300 if (!NT_SUCCESS(Status))
301 return Status;
302
303 Status = SampRegOpenKey(ServerObject->KeyHandle,
304 L"Domains",
305 KEY_READ,
306 &DomainsKeyHandle);
307 if (!NT_SUCCESS(Status))
308 return Status;
309
310 EnumIndex = *EnumerationContext;
311 EnumCount = 0;
312 RequiredLength = 0;
313
314 while (TRUE)
315 {
316 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
317 EnumIndex,
318 64 * sizeof(WCHAR),
319 DomainKeyName);
320 if (!NT_SUCCESS(Status))
321 break;
322
323 TRACE("EnumIndex: %lu\n", EnumIndex);
324 TRACE("Domain key name: %S\n", DomainKeyName);
325
326 Status = SampRegOpenKey(DomainsKeyHandle,
327 DomainKeyName,
328 KEY_READ,
329 &DomainKeyHandle);
330 TRACE("SampRegOpenKey returned %08lX\n", Status);
331 if (NT_SUCCESS(Status))
332 {
333 DataLength = 0;
334 Status = SampRegQueryValue(DomainKeyHandle,
335 L"Name",
336 NULL,
337 NULL,
338 &DataLength);
339 TRACE("SampRegQueryValue returned %08lX\n", Status);
340 if (NT_SUCCESS(Status))
341 {
342 TRACE("Data length: %lu\n", DataLength);
343
344 if ((RequiredLength + DataLength + sizeof(UNICODE_STRING)) > PreferedMaximumLength)
345 break;
346
347 RequiredLength += (DataLength + sizeof(UNICODE_STRING));
348 EnumCount++;
349 }
350
351 NtClose(DomainKeyHandle);
352 }
353
354 EnumIndex++;
355 }
356
357 TRACE("EnumCount: %lu\n", EnumCount);
358 TRACE("RequiredLength: %lu\n", RequiredLength);
359
360 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
361 if (EnumBuffer == NULL)
362 {
363 Status = STATUS_INSUFFICIENT_RESOURCES;
364 goto done;
365 }
366
367 EnumBuffer->EntriesRead = EnumCount;
368 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
369 if (EnumBuffer->Buffer == NULL)
370 {
371 Status = STATUS_INSUFFICIENT_RESOURCES;
372 goto done;
373 }
374
375 EnumIndex = *EnumerationContext;
376 for (i = 0; i < EnumCount; i++, EnumIndex++)
377 {
378 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
379 EnumIndex,
380 64 * sizeof(WCHAR),
381 DomainKeyName);
382 if (!NT_SUCCESS(Status))
383 break;
384
385 TRACE("EnumIndex: %lu\n", EnumIndex);
386 TRACE("Domain key name: %S\n", DomainKeyName);
387
388 Status = SampRegOpenKey(DomainsKeyHandle,
389 DomainKeyName,
390 KEY_READ,
391 &DomainKeyHandle);
392 TRACE("SampRegOpenKey returned %08lX\n", Status);
393 if (NT_SUCCESS(Status))
394 {
395 DataLength = 0;
396 Status = SampRegQueryValue(DomainKeyHandle,
397 L"Name",
398 NULL,
399 NULL,
400 &DataLength);
401 TRACE("SampRegQueryValue returned %08lX\n", Status);
402 if (NT_SUCCESS(Status))
403 {
404 EnumBuffer->Buffer[i].RelativeId = 0;
405 EnumBuffer->Buffer[i].Name.Length = (USHORT)DataLength - sizeof(WCHAR);
406 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)DataLength;
407 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(DataLength);
408 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
409 {
410 NtClose(DomainKeyHandle);
411 Status = STATUS_INSUFFICIENT_RESOURCES;
412 goto done;
413 }
414
415 Status = SampRegQueryValue(DomainKeyHandle,
416 L"Name",
417 NULL,
418 EnumBuffer->Buffer[i].Name.Buffer,
419 &DataLength);
420 TRACE("SampRegQueryValue returned %08lX\n", Status);
421 if (NT_SUCCESS(Status))
422 {
423 TRACE("Domain name: %S\n", EnumBuffer->Buffer[i].Name.Buffer);
424 }
425 }
426
427 NtClose(DomainKeyHandle);
428
429 if (!NT_SUCCESS(Status))
430 goto done;
431 }
432 }
433
434 if (NT_SUCCESS(Status))
435 {
436 *EnumerationContext += EnumCount;
437 *Buffer = EnumBuffer;
438 *CountReturned = EnumCount;
439 }
440
441 done:
442 if (!NT_SUCCESS(Status))
443 {
444 *EnumerationContext = 0;
445 *Buffer = NULL;
446 *CountReturned = 0;
447
448 if (EnumBuffer != NULL)
449 {
450 if (EnumBuffer->Buffer != NULL)
451 {
452 if (EnumBuffer->EntriesRead != 0)
453 {
454 for (i = 0; i < EnumBuffer->EntriesRead; i++)
455 {
456 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
457 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
458 }
459 }
460
461 midl_user_free(EnumBuffer->Buffer);
462 }
463
464 midl_user_free(EnumBuffer);
465 }
466 }
467
468 NtClose(DomainsKeyHandle);
469
470 return Status;
471 }
472
473
474 /* Function 7 */
475 NTSTATUS
476 NTAPI
477 SamrOpenDomain(IN SAMPR_HANDLE ServerHandle,
478 IN ACCESS_MASK DesiredAccess,
479 IN PRPC_SID DomainId,
480 OUT SAMPR_HANDLE *DomainHandle)
481 {
482 PSAM_DB_OBJECT ServerObject;
483 PSAM_DB_OBJECT DomainObject;
484 NTSTATUS Status;
485
486 TRACE("SamrOpenDomain(%p %lx %p %p)\n",
487 ServerHandle, DesiredAccess, DomainId, DomainHandle);
488
489 /* Validate the server handle */
490 Status = SampValidateDbObject(ServerHandle,
491 SamDbServerObject,
492 SAM_SERVER_LOOKUP_DOMAIN,
493 &ServerObject);
494 if (!NT_SUCCESS(Status))
495 return Status;
496
497 /* Validate the Domain SID */
498 if ((DomainId->Revision != SID_REVISION) ||
499 (DomainId->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) ||
500 (memcmp(&DomainId->IdentifierAuthority, &NtSidAuthority, sizeof(SID_IDENTIFIER_AUTHORITY)) != 0))
501 return STATUS_INVALID_PARAMETER;
502
503 /* Open the domain object */
504 if ((DomainId->SubAuthorityCount == 1) &&
505 (DomainId->SubAuthority[0] == SECURITY_BUILTIN_DOMAIN_RID))
506 {
507 /* Builtin domain object */
508 TRACE("Opening the builtin domain object.\n");
509
510 Status = SampOpenDbObject(ServerObject,
511 L"Domains",
512 L"Builtin",
513 0,
514 SamDbDomainObject,
515 DesiredAccess,
516 &DomainObject);
517 }
518 else if ((DomainId->SubAuthorityCount == 4) &&
519 (DomainId->SubAuthority[0] == SECURITY_NT_NON_UNIQUE))
520 {
521 /* Account domain object */
522 TRACE("Opening the account domain object.\n");
523
524 /* FIXME: Check the account domain sub authorities!!! */
525
526 Status = SampOpenDbObject(ServerObject,
527 L"Domains",
528 L"Account",
529 0,
530 SamDbDomainObject,
531 DesiredAccess,
532 &DomainObject);
533 }
534 else
535 {
536 /* No vaild domain SID */
537 Status = STATUS_INVALID_PARAMETER;
538 }
539
540 if (NT_SUCCESS(Status))
541 *DomainHandle = (SAMPR_HANDLE)DomainObject;
542
543 TRACE("SamrOpenDomain done (Status 0x%08lx)\n", Status);
544
545 return Status;
546 }
547
548
549 static NTSTATUS
550 SampQueryDomainPassword(PSAM_DB_OBJECT DomainObject,
551 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
552 {
553 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
554 SAM_DOMAIN_FIXED_DATA FixedData;
555 ULONG Length = 0;
556 NTSTATUS Status;
557
558 *Buffer = NULL;
559
560 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
561 if (InfoBuffer == NULL)
562 return STATUS_INSUFFICIENT_RESOURCES;
563
564 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
565 Status = SampGetObjectAttribute(DomainObject,
566 L"F",
567 NULL,
568 (PVOID)&FixedData,
569 &Length);
570 if (!NT_SUCCESS(Status))
571 goto done;
572
573 InfoBuffer->Password.MinPasswordLength = FixedData.MinPasswordLength;
574 InfoBuffer->Password.PasswordHistoryLength = FixedData.PasswordHistoryLength;
575 InfoBuffer->Password.PasswordProperties = FixedData.PasswordProperties;
576 InfoBuffer->Password.MaxPasswordAge.LowPart = FixedData.MaxPasswordAge.LowPart;
577 InfoBuffer->Password.MaxPasswordAge.HighPart = FixedData.MaxPasswordAge.HighPart;
578 InfoBuffer->Password.MinPasswordAge.LowPart = FixedData.MinPasswordAge.LowPart;
579 InfoBuffer->Password.MinPasswordAge.HighPart = FixedData.MinPasswordAge.HighPart;
580
581 *Buffer = InfoBuffer;
582
583 done:
584 if (!NT_SUCCESS(Status))
585 {
586 if (InfoBuffer != NULL)
587 {
588 midl_user_free(InfoBuffer);
589 }
590 }
591
592 return Status;
593 }
594
595
596 static NTSTATUS
597 SampGetNumberOfAccounts(PSAM_DB_OBJECT DomainObject,
598 LPCWSTR AccountType,
599 PULONG Count)
600 {
601 HANDLE AccountKeyHandle = NULL;
602 HANDLE NamesKeyHandle = NULL;
603 NTSTATUS Status;
604
605 *Count = 0;
606
607 Status = SampRegOpenKey(DomainObject->KeyHandle,
608 AccountType,
609 KEY_READ,
610 &AccountKeyHandle);
611 if (!NT_SUCCESS(Status))
612 return Status;
613
614 Status = SampRegOpenKey(AccountKeyHandle,
615 L"Names",
616 KEY_READ,
617 &NamesKeyHandle);
618 if (!NT_SUCCESS(Status))
619 goto done;
620
621 Status = SampRegQueryKeyInfo(NamesKeyHandle,
622 NULL,
623 Count);
624 done:
625 if (NamesKeyHandle != NULL)
626 SampRegCloseKey(NamesKeyHandle);
627
628 if (AccountKeyHandle != NULL)
629 SampRegCloseKey(AccountKeyHandle);
630
631 return Status;
632 }
633
634
635 static NTSTATUS
636 SampQueryDomainGeneral(PSAM_DB_OBJECT DomainObject,
637 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
638 {
639 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
640 SAM_DOMAIN_FIXED_DATA FixedData;
641 ULONG Length = 0;
642 NTSTATUS Status;
643
644 *Buffer = NULL;
645
646 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
647 if (InfoBuffer == NULL)
648 return STATUS_INSUFFICIENT_RESOURCES;
649
650 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
651 Status = SampGetObjectAttribute(DomainObject,
652 L"F",
653 NULL,
654 (PVOID)&FixedData,
655 &Length);
656 if (!NT_SUCCESS(Status))
657 goto done;
658
659 InfoBuffer->General.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
660 InfoBuffer->General.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
661 InfoBuffer->General.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
662 InfoBuffer->General.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
663 InfoBuffer->General.DomainServerState = FixedData.DomainServerState;
664 InfoBuffer->General.DomainServerRole = FixedData.DomainServerRole;
665 InfoBuffer->General.UasCompatibilityRequired = FixedData.UasCompatibilityRequired;
666
667 /* Get the OemInformation string */
668 Status = SampGetObjectAttributeString(DomainObject,
669 L"OemInformation",
670 &InfoBuffer->General.OemInformation);
671 if (!NT_SUCCESS(Status))
672 {
673 TRACE("Status 0x%08lx\n", Status);
674 goto done;
675 }
676
677 /* Get the Name string */
678 Status = SampGetObjectAttributeString(DomainObject,
679 L"Name",
680 &InfoBuffer->General.DomainName);
681 if (!NT_SUCCESS(Status))
682 {
683 TRACE("Status 0x%08lx\n", Status);
684 goto done;
685 }
686
687 /* Get the ReplicaSourceNodeName string */
688 Status = SampGetObjectAttributeString(DomainObject,
689 L"ReplicaSourceNodeName",
690 &InfoBuffer->General.ReplicaSourceNodeName);
691 if (!NT_SUCCESS(Status))
692 {
693 TRACE("Status 0x%08lx\n", Status);
694 goto done;
695 }
696
697 /* Get the number of Users in the Domain */
698 Status = SampGetNumberOfAccounts(DomainObject,
699 L"Users",
700 &InfoBuffer->General.UserCount);
701 if (!NT_SUCCESS(Status))
702 {
703 TRACE("Status 0x%08lx\n", Status);
704 goto done;
705 }
706
707 /* Get the number of Groups in the Domain */
708 Status = SampGetNumberOfAccounts(DomainObject,
709 L"Groups",
710 &InfoBuffer->General.GroupCount);
711 if (!NT_SUCCESS(Status))
712 {
713 TRACE("Status 0x%08lx\n", Status);
714 goto done;
715 }
716
717 /* Get the number of Aliases in the Domain */
718 Status = SampGetNumberOfAccounts(DomainObject,
719 L"Aliases",
720 &InfoBuffer->General.AliasCount);
721 if (!NT_SUCCESS(Status))
722 {
723 TRACE("Status 0x%08lx\n", Status);
724 goto done;
725 }
726
727 *Buffer = InfoBuffer;
728
729 done:
730 if (!NT_SUCCESS(Status))
731 {
732 if (InfoBuffer != NULL)
733 {
734 if (InfoBuffer->General.OemInformation.Buffer != NULL)
735 midl_user_free(InfoBuffer->General.OemInformation.Buffer);
736
737 if (InfoBuffer->General.DomainName.Buffer != NULL)
738 midl_user_free(InfoBuffer->General.DomainName.Buffer);
739
740 if (InfoBuffer->General.ReplicaSourceNodeName.Buffer != NULL)
741 midl_user_free(InfoBuffer->General.ReplicaSourceNodeName.Buffer);
742
743 midl_user_free(InfoBuffer);
744 }
745 }
746
747 return Status;
748 }
749
750
751 static NTSTATUS
752 SampQueryDomainLogoff(PSAM_DB_OBJECT DomainObject,
753 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
754 {
755 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
756 SAM_DOMAIN_FIXED_DATA FixedData;
757 ULONG Length = 0;
758 NTSTATUS Status;
759
760 *Buffer = NULL;
761
762 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
763 if (InfoBuffer == NULL)
764 return STATUS_INSUFFICIENT_RESOURCES;
765
766 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
767 Status = SampGetObjectAttribute(DomainObject,
768 L"F",
769 NULL,
770 (PVOID)&FixedData,
771 &Length);
772 if (!NT_SUCCESS(Status))
773 goto done;
774
775 InfoBuffer->Logoff.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
776 InfoBuffer->Logoff.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
777
778 *Buffer = InfoBuffer;
779
780 done:
781 if (!NT_SUCCESS(Status))
782 {
783 if (InfoBuffer != NULL)
784 {
785 midl_user_free(InfoBuffer);
786 }
787 }
788
789 return Status;
790 }
791
792
793 static NTSTATUS
794 SampQueryDomainOem(PSAM_DB_OBJECT DomainObject,
795 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
796 {
797 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
798 NTSTATUS Status;
799
800 *Buffer = NULL;
801
802 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
803 if (InfoBuffer == NULL)
804 return STATUS_INSUFFICIENT_RESOURCES;
805
806 /* Get the OemInformation string */
807 Status = SampGetObjectAttributeString(DomainObject,
808 L"OemInformation",
809 &InfoBuffer->Oem.OemInformation);
810 if (!NT_SUCCESS(Status))
811 {
812 TRACE("Status 0x%08lx\n", Status);
813 goto done;
814 }
815
816 *Buffer = InfoBuffer;
817
818 done:
819 if (!NT_SUCCESS(Status))
820 {
821 if (InfoBuffer != NULL)
822 {
823 if (InfoBuffer->Oem.OemInformation.Buffer != NULL)
824 midl_user_free(InfoBuffer->Oem.OemInformation.Buffer);
825
826 midl_user_free(InfoBuffer);
827 }
828 }
829
830 return Status;
831 }
832
833
834 static NTSTATUS
835 SampQueryDomainName(PSAM_DB_OBJECT DomainObject,
836 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
837 {
838 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
839 NTSTATUS Status;
840
841 *Buffer = NULL;
842
843 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
844 if (InfoBuffer == NULL)
845 return STATUS_INSUFFICIENT_RESOURCES;
846
847 /* Get the Name string */
848 Status = SampGetObjectAttributeString(DomainObject,
849 L"Name",
850 &InfoBuffer->Name.DomainName);
851 if (!NT_SUCCESS(Status))
852 {
853 TRACE("Status 0x%08lx\n", Status);
854 goto done;
855 }
856
857 *Buffer = InfoBuffer;
858
859 done:
860 if (!NT_SUCCESS(Status))
861 {
862 if (InfoBuffer != NULL)
863 {
864 if (InfoBuffer->Name.DomainName.Buffer != NULL)
865 midl_user_free(InfoBuffer->Name.DomainName.Buffer);
866
867 midl_user_free(InfoBuffer);
868 }
869 }
870
871 return Status;
872 }
873
874
875 static NTSTATUS
876 SampQueryDomainReplication(PSAM_DB_OBJECT DomainObject,
877 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
878 {
879 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
880 NTSTATUS Status;
881
882 *Buffer = NULL;
883
884 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
885 if (InfoBuffer == NULL)
886 return STATUS_INSUFFICIENT_RESOURCES;
887
888 /* Get the ReplicaSourceNodeName string */
889 Status = SampGetObjectAttributeString(DomainObject,
890 L"ReplicaSourceNodeName",
891 &InfoBuffer->Replication.ReplicaSourceNodeName);
892 if (!NT_SUCCESS(Status))
893 {
894 TRACE("Status 0x%08lx\n", Status);
895 goto done;
896 }
897
898 *Buffer = InfoBuffer;
899
900 done:
901 if (!NT_SUCCESS(Status))
902 {
903 if (InfoBuffer != NULL)
904 {
905 if (InfoBuffer->Replication.ReplicaSourceNodeName.Buffer != NULL)
906 midl_user_free(InfoBuffer->Replication.ReplicaSourceNodeName.Buffer);
907
908 midl_user_free(InfoBuffer);
909 }
910 }
911
912 return Status;
913 }
914
915
916 static NTSTATUS
917 SampQueryDomainServerRole(PSAM_DB_OBJECT DomainObject,
918 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
919 {
920 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
921 SAM_DOMAIN_FIXED_DATA FixedData;
922 ULONG Length = 0;
923 NTSTATUS Status;
924
925 *Buffer = NULL;
926
927 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
928 if (InfoBuffer == NULL)
929 return STATUS_INSUFFICIENT_RESOURCES;
930
931 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
932 Status = SampGetObjectAttribute(DomainObject,
933 L"F",
934 NULL,
935 (PVOID)&FixedData,
936 &Length);
937 if (!NT_SUCCESS(Status))
938 goto done;
939
940 InfoBuffer->Role.DomainServerRole = FixedData.DomainServerRole;
941
942 *Buffer = InfoBuffer;
943
944 done:
945 if (!NT_SUCCESS(Status))
946 {
947 if (InfoBuffer != NULL)
948 {
949 midl_user_free(InfoBuffer);
950 }
951 }
952
953 return Status;
954 }
955
956
957 static NTSTATUS
958 SampQueryDomainModified(PSAM_DB_OBJECT DomainObject,
959 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
960 {
961 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
962 SAM_DOMAIN_FIXED_DATA FixedData;
963 ULONG Length = 0;
964 NTSTATUS Status;
965
966 *Buffer = NULL;
967
968 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
969 if (InfoBuffer == NULL)
970 return STATUS_INSUFFICIENT_RESOURCES;
971
972 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
973 Status = SampGetObjectAttribute(DomainObject,
974 L"F",
975 NULL,
976 (PVOID)&FixedData,
977 &Length);
978 if (!NT_SUCCESS(Status))
979 goto done;
980
981 InfoBuffer->Modified.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
982 InfoBuffer->Modified.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
983 InfoBuffer->Modified.CreationTime.LowPart = FixedData.CreationTime.LowPart;
984 InfoBuffer->Modified.CreationTime.HighPart = FixedData.CreationTime.HighPart;
985
986 *Buffer = InfoBuffer;
987
988 done:
989 if (!NT_SUCCESS(Status))
990 {
991 if (InfoBuffer != NULL)
992 {
993 midl_user_free(InfoBuffer);
994 }
995 }
996
997 return Status;
998 }
999
1000
1001 static NTSTATUS
1002 SampQueryDomainState(PSAM_DB_OBJECT DomainObject,
1003 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1004 {
1005 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1006 SAM_DOMAIN_FIXED_DATA FixedData;
1007 ULONG Length = 0;
1008 NTSTATUS Status;
1009
1010 *Buffer = NULL;
1011
1012 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1013 if (InfoBuffer == NULL)
1014 return STATUS_INSUFFICIENT_RESOURCES;
1015
1016 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1017 Status = SampGetObjectAttribute(DomainObject,
1018 L"F",
1019 NULL,
1020 (PVOID)&FixedData,
1021 &Length);
1022 if (!NT_SUCCESS(Status))
1023 goto done;
1024
1025 InfoBuffer->State.DomainServerState = FixedData.DomainServerState;
1026
1027 *Buffer = InfoBuffer;
1028
1029 done:
1030 if (!NT_SUCCESS(Status))
1031 {
1032 if (InfoBuffer != NULL)
1033 {
1034 midl_user_free(InfoBuffer);
1035 }
1036 }
1037
1038 return Status;
1039 }
1040
1041
1042 static NTSTATUS
1043 SampQueryDomainGeneral2(PSAM_DB_OBJECT DomainObject,
1044 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1045 {
1046 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1047 SAM_DOMAIN_FIXED_DATA FixedData;
1048 ULONG Length = 0;
1049 NTSTATUS Status;
1050
1051 *Buffer = NULL;
1052
1053 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1054 if (InfoBuffer == NULL)
1055 return STATUS_INSUFFICIENT_RESOURCES;
1056
1057 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1058 Status = SampGetObjectAttribute(DomainObject,
1059 L"F",
1060 NULL,
1061 (PVOID)&FixedData,
1062 &Length);
1063 if (!NT_SUCCESS(Status))
1064 goto done;
1065
1066 InfoBuffer->General2.I1.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
1067 InfoBuffer->General2.I1.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
1068 InfoBuffer->General2.I1.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
1069 InfoBuffer->General2.I1.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
1070 InfoBuffer->General2.I1.DomainServerState = FixedData.DomainServerState;
1071 InfoBuffer->General2.I1.DomainServerRole = FixedData.DomainServerRole;
1072 InfoBuffer->General2.I1.UasCompatibilityRequired = FixedData.UasCompatibilityRequired;
1073
1074 InfoBuffer->General2.LockoutDuration = FixedData.LockoutDuration;
1075 InfoBuffer->General2.LockoutObservationWindow = FixedData.LockoutObservationWindow;
1076 InfoBuffer->General2.LockoutThreshold = FixedData.LockoutThreshold;
1077
1078 /* Get the OemInformation string */
1079 Status = SampGetObjectAttributeString(DomainObject,
1080 L"OemInformation",
1081 &InfoBuffer->General2.I1.OemInformation);
1082 if (!NT_SUCCESS(Status))
1083 {
1084 TRACE("Status 0x%08lx\n", Status);
1085 goto done;
1086 }
1087
1088 /* Get the Name string */
1089 Status = SampGetObjectAttributeString(DomainObject,
1090 L"Name",
1091 &InfoBuffer->General2.I1.DomainName);
1092 if (!NT_SUCCESS(Status))
1093 {
1094 TRACE("Status 0x%08lx\n", Status);
1095 goto done;
1096 }
1097
1098 /* Get the ReplicaSourceNodeName string */
1099 Status = SampGetObjectAttributeString(DomainObject,
1100 L"ReplicaSourceNodeName",
1101 &InfoBuffer->General2.I1.ReplicaSourceNodeName);
1102 if (!NT_SUCCESS(Status))
1103 {
1104 TRACE("Status 0x%08lx\n", Status);
1105 goto done;
1106 }
1107
1108 /* Get the number of Users in the Domain */
1109 Status = SampGetNumberOfAccounts(DomainObject,
1110 L"Users",
1111 &InfoBuffer->General2.I1.UserCount);
1112 if (!NT_SUCCESS(Status))
1113 {
1114 TRACE("Status 0x%08lx\n", Status);
1115 goto done;
1116 }
1117
1118 /* Get the number of Groups in the Domain */
1119 Status = SampGetNumberOfAccounts(DomainObject,
1120 L"Groups",
1121 &InfoBuffer->General2.I1.GroupCount);
1122 if (!NT_SUCCESS(Status))
1123 {
1124 TRACE("Status 0x%08lx\n", Status);
1125 goto done;
1126 }
1127
1128 /* Get the number of Aliases in the Domain */
1129 Status = SampGetNumberOfAccounts(DomainObject,
1130 L"Aliases",
1131 &InfoBuffer->General2.I1.AliasCount);
1132 if (!NT_SUCCESS(Status))
1133 {
1134 TRACE("Status 0x%08lx\n", Status);
1135 goto done;
1136 }
1137
1138 *Buffer = InfoBuffer;
1139
1140 done:
1141 if (!NT_SUCCESS(Status))
1142 {
1143 if (InfoBuffer != NULL)
1144 {
1145 if (InfoBuffer->General2.I1.OemInformation.Buffer != NULL)
1146 midl_user_free(InfoBuffer->General2.I1.OemInformation.Buffer);
1147
1148 if (InfoBuffer->General2.I1.DomainName.Buffer != NULL)
1149 midl_user_free(InfoBuffer->General2.I1.DomainName.Buffer);
1150
1151 if (InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer != NULL)
1152 midl_user_free(InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer);
1153
1154 midl_user_free(InfoBuffer);
1155 }
1156 }
1157
1158 return Status;
1159 }
1160
1161
1162 static NTSTATUS
1163 SampQueryDomainLockout(PSAM_DB_OBJECT DomainObject,
1164 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1165 {
1166 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1167 SAM_DOMAIN_FIXED_DATA FixedData;
1168 ULONG Length = 0;
1169 NTSTATUS Status;
1170
1171 *Buffer = NULL;
1172
1173 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1174 if (InfoBuffer == NULL)
1175 return STATUS_INSUFFICIENT_RESOURCES;
1176
1177 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1178 Status = SampGetObjectAttribute(DomainObject,
1179 L"F",
1180 NULL,
1181 (PVOID)&FixedData,
1182 &Length);
1183 if (!NT_SUCCESS(Status))
1184 goto done;
1185
1186 InfoBuffer->Lockout.LockoutDuration = FixedData.LockoutDuration;
1187 InfoBuffer->Lockout.LockoutObservationWindow = FixedData.LockoutObservationWindow;
1188 InfoBuffer->Lockout.LockoutThreshold = FixedData.LockoutThreshold;
1189
1190 *Buffer = InfoBuffer;
1191
1192 done:
1193 if (!NT_SUCCESS(Status))
1194 {
1195 if (InfoBuffer != NULL)
1196 {
1197 midl_user_free(InfoBuffer);
1198 }
1199 }
1200
1201 return Status;
1202 }
1203
1204
1205 static NTSTATUS
1206 SampQueryDomainModified2(PSAM_DB_OBJECT DomainObject,
1207 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1208 {
1209 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1210 SAM_DOMAIN_FIXED_DATA FixedData;
1211 ULONG Length = 0;
1212 NTSTATUS Status;
1213
1214 *Buffer = NULL;
1215
1216 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1217 if (InfoBuffer == NULL)
1218 return STATUS_INSUFFICIENT_RESOURCES;
1219
1220 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1221 Status = SampGetObjectAttribute(DomainObject,
1222 L"F",
1223 NULL,
1224 (PVOID)&FixedData,
1225 &Length);
1226 if (!NT_SUCCESS(Status))
1227 goto done;
1228
1229 InfoBuffer->Modified2.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
1230 InfoBuffer->Modified2.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
1231 InfoBuffer->Modified2.CreationTime.LowPart = FixedData.CreationTime.LowPart;
1232 InfoBuffer->Modified2.CreationTime.HighPart = FixedData.CreationTime.HighPart;
1233 InfoBuffer->Modified2.ModifiedCountAtLastPromotion.LowPart = FixedData.ModifiedCountAtLastPromotion.LowPart;
1234 InfoBuffer->Modified2.ModifiedCountAtLastPromotion.HighPart = FixedData.ModifiedCountAtLastPromotion.HighPart;
1235
1236 *Buffer = InfoBuffer;
1237
1238 done:
1239 if (!NT_SUCCESS(Status))
1240 {
1241 if (InfoBuffer != NULL)
1242 {
1243 midl_user_free(InfoBuffer);
1244 }
1245 }
1246
1247 return Status;
1248 }
1249
1250
1251 /* Function 8 */
1252 NTSTATUS
1253 NTAPI
1254 SamrQueryInformationDomain(IN SAMPR_HANDLE DomainHandle,
1255 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1256 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1257 {
1258 PSAM_DB_OBJECT DomainObject;
1259 ACCESS_MASK DesiredAccess;
1260 NTSTATUS Status;
1261
1262 TRACE("SamrQueryInformationDomain(%p %lu %p)\n",
1263 DomainHandle, DomainInformationClass, Buffer);
1264
1265 switch (DomainInformationClass)
1266 {
1267 case DomainPasswordInformation:
1268 case DomainLockoutInformation:
1269 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS;
1270 break;
1271
1272 case DomainGeneralInformation:
1273 case DomainLogoffInformation:
1274 case DomainOemInformation:
1275 case DomainNameInformation:
1276 case DomainReplicationInformation:
1277 case DomainServerRoleInformation:
1278 case DomainModifiedInformation:
1279 case DomainStateInformation:
1280 case DomainModifiedInformation2:
1281 DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS;
1282 break;
1283
1284 case DomainGeneralInformation2:
1285 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS |
1286 DOMAIN_READ_OTHER_PARAMETERS;
1287 break;
1288
1289 default:
1290 return STATUS_INVALID_INFO_CLASS;
1291 }
1292
1293 /* Validate the server handle */
1294 Status = SampValidateDbObject(DomainHandle,
1295 SamDbDomainObject,
1296 DesiredAccess,
1297 &DomainObject);
1298 if (!NT_SUCCESS(Status))
1299 return Status;
1300
1301 switch (DomainInformationClass)
1302 {
1303 case DomainPasswordInformation:
1304 Status = SampQueryDomainPassword(DomainObject,
1305 Buffer);
1306 break;
1307
1308 case DomainGeneralInformation:
1309 Status = SampQueryDomainGeneral(DomainObject,
1310 Buffer);
1311 break;
1312
1313 case DomainLogoffInformation:
1314 Status = SampQueryDomainLogoff(DomainObject,
1315 Buffer);
1316 break;
1317
1318 case DomainOemInformation:
1319 Status = SampQueryDomainOem(DomainObject,
1320 Buffer);
1321 break;
1322
1323 case DomainNameInformation:
1324 Status = SampQueryDomainName(DomainObject,
1325 Buffer);
1326 break;
1327
1328 case DomainReplicationInformation:
1329 Status = SampQueryDomainReplication(DomainObject,
1330 Buffer);
1331 break;
1332
1333 case DomainServerRoleInformation:
1334 Status = SampQueryDomainServerRole(DomainObject,
1335 Buffer);
1336 break;
1337
1338 case DomainModifiedInformation:
1339 Status = SampQueryDomainModified(DomainObject,
1340 Buffer);
1341 break;
1342
1343 case DomainStateInformation:
1344 Status = SampQueryDomainState(DomainObject,
1345 Buffer);
1346 break;
1347
1348 case DomainGeneralInformation2:
1349 Status = SampQueryDomainGeneral2(DomainObject,
1350 Buffer);
1351 break;
1352
1353 case DomainLockoutInformation:
1354 Status = SampQueryDomainLockout(DomainObject,
1355 Buffer);
1356 break;
1357
1358 case DomainModifiedInformation2:
1359 Status = SampQueryDomainModified2(DomainObject,
1360 Buffer);
1361 break;
1362
1363 default:
1364 Status = STATUS_NOT_IMPLEMENTED;
1365 }
1366
1367 return Status;
1368 }
1369
1370
1371 static NTSTATUS
1372 SampSetDomainPassword(PSAM_DB_OBJECT DomainObject,
1373 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1374 {
1375 SAM_DOMAIN_FIXED_DATA FixedData;
1376 ULONG Length = 0;
1377 NTSTATUS Status;
1378
1379 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1380 Status = SampGetObjectAttribute(DomainObject,
1381 L"F",
1382 NULL,
1383 (PVOID)&FixedData,
1384 &Length);
1385 if (!NT_SUCCESS(Status))
1386 goto done;
1387
1388 FixedData.MinPasswordLength = Buffer->Password.MinPasswordLength;
1389 FixedData.PasswordHistoryLength = Buffer->Password.PasswordHistoryLength;
1390 FixedData.PasswordProperties = Buffer->Password.PasswordProperties;
1391 FixedData.MaxPasswordAge.LowPart = Buffer->Password.MaxPasswordAge.LowPart;
1392 FixedData.MaxPasswordAge.HighPart = Buffer->Password.MaxPasswordAge.HighPart;
1393 FixedData.MinPasswordAge.LowPart = Buffer->Password.MinPasswordAge.LowPart;
1394 FixedData.MinPasswordAge.HighPart = Buffer->Password.MinPasswordAge.HighPart;
1395
1396 Status = SampSetObjectAttribute(DomainObject,
1397 L"F",
1398 REG_BINARY,
1399 &FixedData,
1400 Length);
1401
1402 done:
1403 return Status;
1404 }
1405
1406
1407 static NTSTATUS
1408 SampSetDomainLogoff(PSAM_DB_OBJECT DomainObject,
1409 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1410 {
1411 SAM_DOMAIN_FIXED_DATA FixedData;
1412 ULONG Length = 0;
1413 NTSTATUS Status;
1414
1415 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1416 Status = SampGetObjectAttribute(DomainObject,
1417 L"F",
1418 NULL,
1419 (PVOID)&FixedData,
1420 &Length);
1421 if (!NT_SUCCESS(Status))
1422 goto done;
1423
1424 FixedData.ForceLogoff.LowPart = Buffer->Logoff.ForceLogoff.LowPart;
1425 FixedData.ForceLogoff.HighPart = Buffer->Logoff.ForceLogoff.HighPart;
1426
1427 Status = SampSetObjectAttribute(DomainObject,
1428 L"F",
1429 REG_BINARY,
1430 &FixedData,
1431 Length);
1432
1433 done:
1434 return Status;
1435 }
1436
1437
1438 static NTSTATUS
1439 SampSetDomainServerRole(PSAM_DB_OBJECT DomainObject,
1440 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1441 {
1442 SAM_DOMAIN_FIXED_DATA FixedData;
1443 ULONG Length = 0;
1444 NTSTATUS Status;
1445
1446 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1447 Status = SampGetObjectAttribute(DomainObject,
1448 L"F",
1449 NULL,
1450 (PVOID)&FixedData,
1451 &Length);
1452 if (!NT_SUCCESS(Status))
1453 goto done;
1454
1455 FixedData.DomainServerRole = Buffer->Role.DomainServerRole;
1456
1457 Status = SampSetObjectAttribute(DomainObject,
1458 L"F",
1459 REG_BINARY,
1460 &FixedData,
1461 Length);
1462
1463 done:
1464 return Status;
1465 }
1466
1467
1468 static NTSTATUS
1469 SampSetDomainState(PSAM_DB_OBJECT DomainObject,
1470 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1471 {
1472 SAM_DOMAIN_FIXED_DATA FixedData;
1473 ULONG Length = 0;
1474 NTSTATUS Status;
1475
1476 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1477 Status = SampGetObjectAttribute(DomainObject,
1478 L"F",
1479 NULL,
1480 (PVOID)&FixedData,
1481 &Length);
1482 if (!NT_SUCCESS(Status))
1483 goto done;
1484
1485 FixedData.DomainServerState = Buffer->State.DomainServerState;
1486
1487 Status = SampSetObjectAttribute(DomainObject,
1488 L"F",
1489 REG_BINARY,
1490 &FixedData,
1491 Length);
1492
1493 done:
1494 return Status;
1495 }
1496
1497
1498 static NTSTATUS
1499 SampSetDomainLockout(PSAM_DB_OBJECT DomainObject,
1500 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1501 {
1502 SAM_DOMAIN_FIXED_DATA FixedData;
1503 ULONG Length = 0;
1504 NTSTATUS Status;
1505
1506 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1507 Status = SampGetObjectAttribute(DomainObject,
1508 L"F",
1509 NULL,
1510 (PVOID)&FixedData,
1511 &Length);
1512 if (!NT_SUCCESS(Status))
1513 goto done;
1514
1515 FixedData.LockoutDuration = Buffer->Lockout.LockoutDuration;
1516 FixedData.LockoutObservationWindow = Buffer->Lockout.LockoutObservationWindow;
1517 FixedData.LockoutThreshold = Buffer->Lockout.LockoutThreshold;
1518
1519 Status = SampSetObjectAttribute(DomainObject,
1520 L"F",
1521 REG_BINARY,
1522 &FixedData,
1523 Length);
1524
1525 done:
1526 return Status;
1527 }
1528
1529
1530 /* Function 9 */
1531 NTSTATUS
1532 NTAPI
1533 SamrSetInformationDomain(IN SAMPR_HANDLE DomainHandle,
1534 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1535 IN PSAMPR_DOMAIN_INFO_BUFFER DomainInformation)
1536 {
1537 PSAM_DB_OBJECT DomainObject;
1538 ACCESS_MASK DesiredAccess;
1539 NTSTATUS Status;
1540
1541 TRACE("SamrSetInformationDomain(%p %lu %p)\n",
1542 DomainHandle, DomainInformationClass, DomainInformation);
1543
1544 switch (DomainInformationClass)
1545 {
1546 case DomainPasswordInformation:
1547 case DomainLockoutInformation:
1548 DesiredAccess = DOMAIN_WRITE_PASSWORD_PARAMS;
1549 break;
1550
1551 case DomainLogoffInformation:
1552 case DomainOemInformation:
1553 case DomainNameInformation:
1554 DesiredAccess = DOMAIN_WRITE_OTHER_PARAMETERS;
1555 break;
1556
1557 case DomainReplicationInformation:
1558 case DomainServerRoleInformation:
1559 case DomainStateInformation:
1560 DesiredAccess = DOMAIN_ADMINISTER_SERVER;
1561 break;
1562
1563 default:
1564 return STATUS_INVALID_INFO_CLASS;
1565 }
1566
1567 /* Validate the server handle */
1568 Status = SampValidateDbObject(DomainHandle,
1569 SamDbDomainObject,
1570 DesiredAccess,
1571 &DomainObject);
1572 if (!NT_SUCCESS(Status))
1573 return Status;
1574
1575 switch (DomainInformationClass)
1576 {
1577 case DomainPasswordInformation:
1578 Status = SampSetDomainPassword(DomainObject,
1579 DomainInformation);
1580 break;
1581
1582 case DomainLogoffInformation:
1583 Status = SampSetDomainLogoff(DomainObject,
1584 DomainInformation);
1585 break;
1586
1587 case DomainOemInformation:
1588 Status = SampSetObjectAttribute(DomainObject,
1589 L"OemInformation",
1590 REG_SZ,
1591 DomainInformation->Oem.OemInformation.Buffer,
1592 DomainInformation->Oem.OemInformation.Length + sizeof(WCHAR));
1593 break;
1594
1595 case DomainNameInformation:
1596 Status = SampSetObjectAttribute(DomainObject,
1597 L"Name",
1598 REG_SZ,
1599 DomainInformation->Name.DomainName.Buffer,
1600 DomainInformation->Name.DomainName.Length + sizeof(WCHAR));
1601 break;
1602
1603 case DomainReplicationInformation:
1604 Status = SampSetObjectAttribute(DomainObject,
1605 L"ReplicaSourceNodeName",
1606 REG_SZ,
1607 DomainInformation->Replication.ReplicaSourceNodeName.Buffer,
1608 DomainInformation->Replication.ReplicaSourceNodeName.Length + sizeof(WCHAR));
1609 break;
1610
1611 case DomainServerRoleInformation:
1612 Status = SampSetDomainServerRole(DomainObject,
1613 DomainInformation);
1614 break;
1615
1616 case DomainStateInformation:
1617 Status = SampSetDomainState(DomainObject,
1618 DomainInformation);
1619 break;
1620
1621 case DomainLockoutInformation:
1622 Status = SampSetDomainLockout(DomainObject,
1623 DomainInformation);
1624 break;
1625
1626 default:
1627 Status = STATUS_NOT_IMPLEMENTED;
1628 }
1629
1630 return Status;
1631 }
1632
1633
1634 /* Function 10 */
1635 NTSTATUS
1636 NTAPI
1637 SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
1638 IN PRPC_UNICODE_STRING Name,
1639 IN ACCESS_MASK DesiredAccess,
1640 OUT SAMPR_HANDLE *GroupHandle,
1641 OUT unsigned long *RelativeId)
1642 {
1643 UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
1644 SAM_DOMAIN_FIXED_DATA FixedDomainData;
1645 SAM_GROUP_FIXED_DATA FixedGroupData;
1646 PSAM_DB_OBJECT DomainObject;
1647 PSAM_DB_OBJECT GroupObject;
1648 ULONG ulSize;
1649 ULONG ulRid;
1650 WCHAR szRid[9];
1651 NTSTATUS Status;
1652
1653 TRACE("SamrCreateGroupInDomain(%p %p %lx %p %p)\n",
1654 DomainHandle, Name, DesiredAccess, GroupHandle, RelativeId);
1655
1656 /* Validate the domain handle */
1657 Status = SampValidateDbObject(DomainHandle,
1658 SamDbDomainObject,
1659 DOMAIN_CREATE_GROUP,
1660 &DomainObject);
1661 if (!NT_SUCCESS(Status))
1662 {
1663 TRACE("failed with status 0x%08lx\n", Status);
1664 return Status;
1665 }
1666
1667 /* Check if the group name already exists in the domain */
1668 Status = SampCheckAccountNameInDomain(DomainObject,
1669 Name->Buffer);
1670 if (!NT_SUCCESS(Status))
1671 {
1672 TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n",
1673 Name->Buffer, Status);
1674 return Status;
1675 }
1676
1677 /* Get the fixed domain attributes */
1678 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
1679 Status = SampGetObjectAttribute(DomainObject,
1680 L"F",
1681 NULL,
1682 (PVOID)&FixedDomainData,
1683 &ulSize);
1684 if (!NT_SUCCESS(Status))
1685 {
1686 TRACE("failed with status 0x%08lx\n", Status);
1687 return Status;
1688 }
1689
1690 /* Increment the NextRid attribute */
1691 ulRid = FixedDomainData.NextRid;
1692 FixedDomainData.NextRid++;
1693
1694 /* Store the fixed domain attributes */
1695 Status = SampSetObjectAttribute(DomainObject,
1696 L"F",
1697 REG_BINARY,
1698 &FixedDomainData,
1699 ulSize);
1700 if (!NT_SUCCESS(Status))
1701 {
1702 TRACE("failed with status 0x%08lx\n", Status);
1703 return Status;
1704 }
1705
1706 TRACE("RID: %lx\n", ulRid);
1707
1708 /* Convert the RID into a string (hex) */
1709 swprintf(szRid, L"%08lX", ulRid);
1710
1711 /* Create the group object */
1712 Status = SampCreateDbObject(DomainObject,
1713 L"Groups",
1714 szRid,
1715 ulRid,
1716 SamDbGroupObject,
1717 DesiredAccess,
1718 &GroupObject);
1719 if (!NT_SUCCESS(Status))
1720 {
1721 TRACE("failed with status 0x%08lx\n", Status);
1722 return Status;
1723 }
1724
1725 /* Add the account name of the user object */
1726 Status = SampSetAccountNameInDomain(DomainObject,
1727 L"Groups",
1728 Name->Buffer,
1729 ulRid);
1730 if (!NT_SUCCESS(Status))
1731 {
1732 TRACE("failed with status 0x%08lx\n", Status);
1733 return Status;
1734 }
1735
1736 /* Initialize fixed user data */
1737 memset(&FixedGroupData, 0, sizeof(SAM_GROUP_FIXED_DATA));
1738 FixedGroupData.Version = 1;
1739
1740 FixedGroupData.GroupId = ulRid;
1741
1742 /* Set fixed user data attribute */
1743 Status = SampSetObjectAttribute(GroupObject,
1744 L"F",
1745 REG_BINARY,
1746 (LPVOID)&FixedGroupData,
1747 sizeof(SAM_GROUP_FIXED_DATA));
1748 if (!NT_SUCCESS(Status))
1749 {
1750 TRACE("failed with status 0x%08lx\n", Status);
1751 return Status;
1752 }
1753
1754 /* Set the Name attribute */
1755 Status = SampSetObjectAttribute(GroupObject,
1756 L"Name",
1757 REG_SZ,
1758 (LPVOID)Name->Buffer,
1759 Name->MaximumLength);
1760 if (!NT_SUCCESS(Status))
1761 {
1762 TRACE("failed with status 0x%08lx\n", Status);
1763 return Status;
1764 }
1765
1766 /* Set the AdminComment attribute */
1767 Status = SampSetObjectAttribute(GroupObject,
1768 L"AdminComment",
1769 REG_SZ,
1770 EmptyString.Buffer,
1771 EmptyString.MaximumLength);
1772 if (!NT_SUCCESS(Status))
1773 {
1774 TRACE("failed with status 0x%08lx\n", Status);
1775 return Status;
1776 }
1777
1778 if (NT_SUCCESS(Status))
1779 {
1780 *GroupHandle = (SAMPR_HANDLE)GroupObject;
1781 *RelativeId = ulRid;
1782 }
1783
1784 TRACE("returns with status 0x%08lx\n", Status);
1785
1786 return Status;
1787 }
1788
1789
1790 /* Function 11 */
1791 NTSTATUS
1792 NTAPI
1793 SamrEnumerateGroupsInDomain(IN SAMPR_HANDLE DomainHandle,
1794 IN OUT unsigned long *EnumerationContext,
1795 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
1796 IN unsigned long PreferedMaximumLength,
1797 OUT unsigned long *CountReturned)
1798 {
1799 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
1800 PSAM_DB_OBJECT DomainObject;
1801 HANDLE GroupsKeyHandle = NULL;
1802 HANDLE NamesKeyHandle = NULL;
1803 WCHAR GroupName[64];
1804 ULONG EnumIndex;
1805 ULONG EnumCount = 0;
1806 ULONG RequiredLength = 0;
1807 ULONG NameLength;
1808 ULONG DataLength;
1809 ULONG Rid;
1810 ULONG i;
1811 BOOLEAN MoreEntries = FALSE;
1812 NTSTATUS Status;
1813
1814 TRACE("SamrEnumerateUsersInDomain(%p %p %p %lu %p)\n",
1815 DomainHandle, EnumerationContext, Buffer,
1816 PreferedMaximumLength, CountReturned);
1817
1818 /* Validate the domain handle */
1819 Status = SampValidateDbObject(DomainHandle,
1820 SamDbDomainObject,
1821 DOMAIN_LIST_ACCOUNTS,
1822 &DomainObject);
1823 if (!NT_SUCCESS(Status))
1824 return Status;
1825
1826 Status = SampRegOpenKey(DomainObject->KeyHandle,
1827 L"Groups",
1828 KEY_READ,
1829 &GroupsKeyHandle);
1830 if (!NT_SUCCESS(Status))
1831 return Status;
1832
1833 Status = SampRegOpenKey(GroupsKeyHandle,
1834 L"Names",
1835 KEY_READ,
1836 &NamesKeyHandle);
1837 if (!NT_SUCCESS(Status))
1838 goto done;
1839
1840 TRACE("Part 1\n");
1841
1842 EnumIndex = *EnumerationContext;
1843
1844 while (TRUE)
1845 {
1846 NameLength = 64 * sizeof(WCHAR);
1847 Status = SampRegEnumerateValue(NamesKeyHandle,
1848 EnumIndex,
1849 GroupName,
1850 &NameLength,
1851 NULL,
1852 NULL,
1853 NULL);
1854 if (!NT_SUCCESS(Status))
1855 {
1856 if (Status == STATUS_NO_MORE_ENTRIES)
1857 Status = STATUS_SUCCESS;
1858 break;
1859 }
1860
1861 TRACE("EnumIndex: %lu\n", EnumIndex);
1862 TRACE("Group name: %S\n", GroupName);
1863 TRACE("Name length: %lu\n", NameLength);
1864
1865 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
1866 {
1867 MoreEntries = TRUE;
1868 break;
1869 }
1870
1871 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
1872 EnumCount++;
1873
1874 EnumIndex++;
1875 }
1876
1877 TRACE("EnumCount: %lu\n", EnumCount);
1878 TRACE("RequiredLength: %lu\n", RequiredLength);
1879
1880 if (!NT_SUCCESS(Status))
1881 goto done;
1882
1883 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
1884 if (EnumBuffer == NULL)
1885 {
1886 Status = STATUS_INSUFFICIENT_RESOURCES;
1887 goto done;
1888 }
1889
1890 EnumBuffer->EntriesRead = EnumCount;
1891 if (EnumCount == 0)
1892 goto done;
1893
1894 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
1895 if (EnumBuffer->Buffer == NULL)
1896 {
1897 Status = STATUS_INSUFFICIENT_RESOURCES;
1898 goto done;
1899 }
1900
1901 TRACE("Part 2\n");
1902
1903 EnumIndex = *EnumerationContext;
1904 for (i = 0; i < EnumCount; i++, EnumIndex++)
1905 {
1906 NameLength = 64 * sizeof(WCHAR);
1907 DataLength = sizeof(ULONG);
1908 Status = SampRegEnumerateValue(NamesKeyHandle,
1909 EnumIndex,
1910 GroupName,
1911 &NameLength,
1912 NULL,
1913 &Rid,
1914 &DataLength);
1915 if (!NT_SUCCESS(Status))
1916 {
1917 if (Status == STATUS_NO_MORE_ENTRIES)
1918 Status = STATUS_SUCCESS;
1919 break;
1920 }
1921
1922 TRACE("EnumIndex: %lu\n", EnumIndex);
1923 TRACE("Group name: %S\n", GroupName);
1924 TRACE("Name length: %lu\n", NameLength);
1925 TRACE("RID: %lu\n", Rid);
1926
1927 EnumBuffer->Buffer[i].RelativeId = Rid;
1928
1929 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
1930 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(DataLength + sizeof(UNICODE_NULL));
1931
1932 /* FIXME: Disabled because of bugs in widl and rpcrt4 */
1933 #if 0
1934 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
1935 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
1936 {
1937 Status = STATUS_INSUFFICIENT_RESOURCES;
1938 goto done;
1939 }
1940
1941 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
1942 GroupName,
1943 EnumBuffer->Buffer[i].Name.Length);
1944 #endif
1945 }
1946
1947 done:
1948 if (NT_SUCCESS(Status))
1949 {
1950 *EnumerationContext += EnumCount;
1951 *Buffer = EnumBuffer;
1952 *CountReturned = EnumCount;
1953 }
1954 else
1955 {
1956 *EnumerationContext = 0;
1957 *Buffer = NULL;
1958 *CountReturned = 0;
1959
1960 if (EnumBuffer != NULL)
1961 {
1962 if (EnumBuffer->Buffer != NULL)
1963 {
1964 if (EnumBuffer->EntriesRead != 0)
1965 {
1966 for (i = 0; i < EnumBuffer->EntriesRead; i++)
1967 {
1968 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
1969 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
1970 }
1971 }
1972
1973 midl_user_free(EnumBuffer->Buffer);
1974 }
1975
1976 midl_user_free(EnumBuffer);
1977 }
1978 }
1979
1980 if (NamesKeyHandle != NULL)
1981 SampRegCloseKey(NamesKeyHandle);
1982
1983 if (GroupsKeyHandle != NULL)
1984 SampRegCloseKey(GroupsKeyHandle);
1985
1986 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
1987 Status = STATUS_MORE_ENTRIES;
1988
1989 return Status;
1990 }
1991
1992
1993 /* Function 12 */
1994 NTSTATUS
1995 NTAPI
1996 SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
1997 IN PRPC_UNICODE_STRING Name,
1998 IN ACCESS_MASK DesiredAccess,
1999 OUT SAMPR_HANDLE *UserHandle,
2000 OUT unsigned long *RelativeId)
2001 {
2002 UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
2003 SAM_DOMAIN_FIXED_DATA FixedDomainData;
2004 SAM_USER_FIXED_DATA FixedUserData;
2005 PSAM_DB_OBJECT DomainObject;
2006 PSAM_DB_OBJECT UserObject;
2007 ULONG ulSize;
2008 ULONG ulRid;
2009 WCHAR szRid[9];
2010 NTSTATUS Status;
2011
2012 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
2013 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
2014
2015 if (Name == NULL ||
2016 Name->Length == 0 ||
2017 Name->Buffer == NULL ||
2018 UserHandle == NULL ||
2019 RelativeId == NULL)
2020 return STATUS_INVALID_PARAMETER;
2021
2022 /* Validate the domain handle */
2023 Status = SampValidateDbObject(DomainHandle,
2024 SamDbDomainObject,
2025 DOMAIN_CREATE_USER,
2026 &DomainObject);
2027 if (!NT_SUCCESS(Status))
2028 {
2029 TRACE("failed with status 0x%08lx\n", Status);
2030 return Status;
2031 }
2032
2033 /* Check if the user name already exists in the domain */
2034 Status = SampCheckAccountNameInDomain(DomainObject,
2035 Name->Buffer);
2036 if (!NT_SUCCESS(Status))
2037 {
2038 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
2039 Name->Buffer, Status);
2040 return Status;
2041 }
2042
2043 /* Get the fixed domain attributes */
2044 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
2045 Status = SampGetObjectAttribute(DomainObject,
2046 L"F",
2047 NULL,
2048 (PVOID)&FixedDomainData,
2049 &ulSize);
2050 if (!NT_SUCCESS(Status))
2051 {
2052 TRACE("failed with status 0x%08lx\n", Status);
2053 return Status;
2054 }
2055
2056 /* Increment the NextRid attribute */
2057 ulRid = FixedDomainData.NextRid;
2058 FixedDomainData.NextRid++;
2059
2060 /* Store the fixed domain attributes */
2061 Status = SampSetObjectAttribute(DomainObject,
2062 L"F",
2063 REG_BINARY,
2064 &FixedDomainData,
2065 ulSize);
2066 if (!NT_SUCCESS(Status))
2067 {
2068 TRACE("failed with status 0x%08lx\n", Status);
2069 return Status;
2070 }
2071
2072 TRACE("RID: %lx\n", ulRid);
2073
2074 /* Convert the RID into a string (hex) */
2075 swprintf(szRid, L"%08lX", ulRid);
2076
2077 /* Create the user object */
2078 Status = SampCreateDbObject(DomainObject,
2079 L"Users",
2080 szRid,
2081 ulRid,
2082 SamDbUserObject,
2083 DesiredAccess,
2084 &UserObject);
2085 if (!NT_SUCCESS(Status))
2086 {
2087 TRACE("failed with status 0x%08lx\n", Status);
2088 return Status;
2089 }
2090
2091 /* Add the account name for the user object */
2092 Status = SampSetAccountNameInDomain(DomainObject,
2093 L"Users",
2094 Name->Buffer,
2095 ulRid);
2096 if (!NT_SUCCESS(Status))
2097 {
2098 TRACE("failed with status 0x%08lx\n", Status);
2099 return Status;
2100 }
2101
2102 /* Initialize fixed user data */
2103 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
2104 FixedUserData.Version = 1;
2105 FixedUserData.LastLogon.QuadPart = 0;
2106 FixedUserData.LastLogoff.QuadPart = 0;
2107 FixedUserData.PasswordLastSet.QuadPart = 0;
2108 FixedUserData.AccountExpires.LowPart = MAXULONG;
2109 FixedUserData.AccountExpires.HighPart = MAXLONG;
2110 FixedUserData.LastBadPasswordTime.QuadPart = 0;
2111 FixedUserData.UserId = ulRid;
2112 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
2113 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
2114 USER_PASSWORD_NOT_REQUIRED |
2115 USER_NORMAL_ACCOUNT;
2116
2117 /* Set fixed user data attribute */
2118 Status = SampSetObjectAttribute(UserObject,
2119 L"F",
2120 REG_BINARY,
2121 (LPVOID)&FixedUserData,
2122 sizeof(SAM_USER_FIXED_DATA));
2123 if (!NT_SUCCESS(Status))
2124 {
2125 TRACE("failed with status 0x%08lx\n", Status);
2126 return Status;
2127 }
2128
2129 /* Set the Name attribute */
2130 Status = SampSetObjectAttribute(UserObject,
2131 L"Name",
2132 REG_SZ,
2133 (LPVOID)Name->Buffer,
2134 Name->MaximumLength);
2135 if (!NT_SUCCESS(Status))
2136 {
2137 TRACE("failed with status 0x%08lx\n", Status);
2138 return Status;
2139 }
2140
2141 /* Set the FullName attribute */
2142 Status = SampSetObjectAttribute(UserObject,
2143 L"FullName",
2144 REG_SZ,
2145 EmptyString.Buffer,
2146 EmptyString.MaximumLength);
2147 if (!NT_SUCCESS(Status))
2148 {
2149 TRACE("failed with status 0x%08lx\n", Status);
2150 return Status;
2151 }
2152
2153 /* Set the HomeDirectory attribute */
2154 Status = SampSetObjectAttribute(UserObject,
2155 L"HomeDirectory",
2156 REG_SZ,
2157 EmptyString.Buffer,
2158 EmptyString.MaximumLength);
2159 if (!NT_SUCCESS(Status))
2160 {
2161 TRACE("failed with status 0x%08lx\n", Status);
2162 return Status;
2163 }
2164
2165 /* Set the HomeDirectoryDrive attribute */
2166 Status = SampSetObjectAttribute(UserObject,
2167 L"HomeDirectoryDrive",
2168 REG_SZ,
2169 EmptyString.Buffer,
2170 EmptyString.MaximumLength);
2171 if (!NT_SUCCESS(Status))
2172 {
2173 TRACE("failed with status 0x%08lx\n", Status);
2174 return Status;
2175 }
2176
2177 /* Set the ScriptPath attribute */
2178 Status = SampSetObjectAttribute(UserObject,
2179 L"ScriptPath",
2180 REG_SZ,
2181 EmptyString.Buffer,
2182 EmptyString.MaximumLength);
2183 if (!NT_SUCCESS(Status))
2184 {
2185 TRACE("failed with status 0x%08lx\n", Status);
2186 return Status;
2187 }
2188
2189 /* Set the ProfilePath attribute */
2190 Status = SampSetObjectAttribute(UserObject,
2191 L"ProfilePath",
2192 REG_SZ,
2193 EmptyString.Buffer,
2194 EmptyString.MaximumLength);
2195 if (!NT_SUCCESS(Status))
2196 {
2197 TRACE("failed with status 0x%08lx\n", Status);
2198 return Status;
2199 }
2200
2201 /* Set the AdminComment attribute */
2202 Status = SampSetObjectAttribute(UserObject,
2203 L"AdminComment",
2204 REG_SZ,
2205 EmptyString.Buffer,
2206 EmptyString.MaximumLength);
2207 if (!NT_SUCCESS(Status))
2208 {
2209 TRACE("failed with status 0x%08lx\n", Status);
2210 return Status;
2211 }
2212
2213 /* Set the UserComment attribute */
2214 Status = SampSetObjectAttribute(UserObject,
2215 L"UserComment",
2216 REG_SZ,
2217 EmptyString.Buffer,
2218 EmptyString.MaximumLength);
2219 if (!NT_SUCCESS(Status))
2220 {
2221 TRACE("failed with status 0x%08lx\n", Status);
2222 return Status;
2223 }
2224
2225 /* Set the WorkStations attribute */
2226 Status = SampSetObjectAttribute(UserObject,
2227 L"WorkStations",
2228 REG_SZ,
2229 EmptyString.Buffer,
2230 EmptyString.MaximumLength);
2231 if (!NT_SUCCESS(Status))
2232 {
2233 TRACE("failed with status 0x%08lx\n", Status);
2234 return Status;
2235 }
2236
2237 /* FIXME: Set default user attributes */
2238
2239 if (NT_SUCCESS(Status))
2240 {
2241 *UserHandle = (SAMPR_HANDLE)UserObject;
2242 *RelativeId = ulRid;
2243 }
2244
2245 TRACE("returns with status 0x%08lx\n", Status);
2246
2247 return Status;
2248 }
2249
2250
2251 /* Function 13 */
2252 NTSTATUS
2253 NTAPI
2254 SamrEnumerateUsersInDomain(IN SAMPR_HANDLE DomainHandle,
2255 IN OUT unsigned long *EnumerationContext,
2256 IN unsigned long UserAccountControl,
2257 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
2258 IN unsigned long PreferedMaximumLength,
2259 OUT unsigned long *CountReturned)
2260 {
2261 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
2262 PSAM_DB_OBJECT DomainObject;
2263 HANDLE UsersKeyHandle = NULL;
2264 HANDLE NamesKeyHandle = NULL;
2265 WCHAR UserName[64];
2266 ULONG EnumIndex;
2267 ULONG EnumCount = 0;
2268 ULONG RequiredLength = 0;
2269 ULONG NameLength;
2270 ULONG DataLength;
2271 ULONG Rid;
2272 ULONG i;
2273 BOOLEAN MoreEntries = FALSE;
2274 NTSTATUS Status;
2275
2276 TRACE("SamrEnumerateUsersInDomain(%p %p %lx %p %lu %p)\n",
2277 DomainHandle, EnumerationContext, UserAccountControl, Buffer,
2278 PreferedMaximumLength, CountReturned);
2279
2280 /* Validate the domain handle */
2281 Status = SampValidateDbObject(DomainHandle,
2282 SamDbDomainObject,
2283 DOMAIN_LIST_ACCOUNTS,
2284 &DomainObject);
2285 if (!NT_SUCCESS(Status))
2286 return Status;
2287
2288 Status = SampRegOpenKey(DomainObject->KeyHandle,
2289 L"Users",
2290 KEY_READ,
2291 &UsersKeyHandle);
2292 if (!NT_SUCCESS(Status))
2293 return Status;
2294
2295 Status = SampRegOpenKey(UsersKeyHandle,
2296 L"Names",
2297 KEY_READ,
2298 &NamesKeyHandle);
2299 if (!NT_SUCCESS(Status))
2300 goto done;
2301
2302 TRACE("Part 1\n");
2303
2304 EnumIndex = *EnumerationContext;
2305
2306 while (TRUE)
2307 {
2308 NameLength = 64 * sizeof(WCHAR);
2309 Status = SampRegEnumerateValue(NamesKeyHandle,
2310 EnumIndex,
2311 UserName,
2312 &NameLength,
2313 NULL,
2314 NULL,
2315 NULL);
2316 if (!NT_SUCCESS(Status))
2317 {
2318 if (Status == STATUS_NO_MORE_ENTRIES)
2319 Status = STATUS_SUCCESS;
2320 break;
2321 }
2322
2323 TRACE("EnumIndex: %lu\n", EnumIndex);
2324 TRACE("User name: %S\n", UserName);
2325 TRACE("Name length: %lu\n", NameLength);
2326
2327 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
2328 {
2329 MoreEntries = TRUE;
2330 break;
2331 }
2332
2333 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
2334 EnumCount++;
2335
2336 EnumIndex++;
2337 }
2338
2339 TRACE("EnumCount: %lu\n", EnumCount);
2340 TRACE("RequiredLength: %lu\n", RequiredLength);
2341
2342 if (!NT_SUCCESS(Status))
2343 goto done;
2344
2345 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
2346 if (EnumBuffer == NULL)
2347 {
2348 Status = STATUS_INSUFFICIENT_RESOURCES;
2349 goto done;
2350 }
2351
2352 EnumBuffer->EntriesRead = EnumCount;
2353 if (EnumCount == 0)
2354 goto done;
2355
2356 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
2357 if (EnumBuffer->Buffer == NULL)
2358 {
2359 Status = STATUS_INSUFFICIENT_RESOURCES;
2360 goto done;
2361 }
2362
2363 TRACE("Part 2\n");
2364
2365 EnumIndex = *EnumerationContext;
2366 for (i = 0; i < EnumCount; i++, EnumIndex++)
2367 {
2368 NameLength = 64 * sizeof(WCHAR);
2369 DataLength = sizeof(ULONG);
2370 Status = SampRegEnumerateValue(NamesKeyHandle,
2371 EnumIndex,
2372 UserName,
2373 &NameLength,
2374 NULL,
2375 &Rid,
2376 &DataLength);
2377 if (!NT_SUCCESS(Status))
2378 {
2379 if (Status == STATUS_NO_MORE_ENTRIES)
2380 Status = STATUS_SUCCESS;
2381 break;
2382 }
2383
2384 TRACE("EnumIndex: %lu\n", EnumIndex);
2385 TRACE("User name: %S\n", UserName);
2386 TRACE("Name length: %lu\n", NameLength);
2387 TRACE("RID: %lu\n", Rid);
2388
2389 EnumBuffer->Buffer[i].RelativeId = Rid;
2390
2391 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
2392 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(DataLength + sizeof(UNICODE_NULL));
2393
2394 /* FIXME: Disabled because of bugs in widl and rpcrt4 */
2395 #if 0
2396 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
2397 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
2398 {
2399 Status = STATUS_INSUFFICIENT_RESOURCES;
2400 goto done;
2401 }
2402
2403 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
2404 UserName,
2405 EnumBuffer->Buffer[i].Name.Length);
2406 #endif
2407 }
2408
2409 done:
2410 if (NT_SUCCESS(Status))
2411 {
2412 *EnumerationContext += EnumCount;
2413 *Buffer = EnumBuffer;
2414 *CountReturned = EnumCount;
2415 }
2416 else
2417 {
2418 *EnumerationContext = 0;
2419 *Buffer = NULL;
2420 *CountReturned = 0;
2421
2422 if (EnumBuffer != NULL)
2423 {
2424 if (EnumBuffer->Buffer != NULL)
2425 {
2426 if (EnumBuffer->EntriesRead != 0)
2427 {
2428 for (i = 0; i < EnumBuffer->EntriesRead; i++)
2429 {
2430 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
2431 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
2432 }
2433 }
2434
2435 midl_user_free(EnumBuffer->Buffer);
2436 }
2437
2438 midl_user_free(EnumBuffer);
2439 }
2440 }
2441
2442 if (NamesKeyHandle != NULL)
2443 SampRegCloseKey(NamesKeyHandle);
2444
2445 if (UsersKeyHandle != NULL)
2446 SampRegCloseKey(UsersKeyHandle);
2447
2448 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
2449 Status = STATUS_MORE_ENTRIES;
2450
2451 return Status;
2452 }
2453
2454
2455 /* Function 14 */
2456 NTSTATUS
2457 NTAPI
2458 SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
2459 IN PRPC_UNICODE_STRING AccountName,
2460 IN ACCESS_MASK DesiredAccess,
2461 OUT SAMPR_HANDLE *AliasHandle,
2462 OUT unsigned long *RelativeId)
2463 {
2464 SAM_DOMAIN_FIXED_DATA FixedDomainData;
2465 PSAM_DB_OBJECT DomainObject;
2466 PSAM_DB_OBJECT AliasObject;
2467 UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
2468 ULONG ulSize;
2469 ULONG ulRid;
2470 WCHAR szRid[9];
2471 NTSTATUS Status;
2472
2473 TRACE("SamrCreateAliasInDomain(%p %p %lx %p %p)\n",
2474 DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId);
2475
2476 /* Validate the domain handle */
2477 Status = SampValidateDbObject(DomainHandle,
2478 SamDbDomainObject,
2479 DOMAIN_CREATE_ALIAS,
2480 &DomainObject);
2481 if (!NT_SUCCESS(Status))
2482 {
2483 TRACE("failed with status 0x%08lx\n", Status);
2484 return Status;
2485 }
2486
2487 /* Check if the alias name already exists in the domain */
2488 Status = SampCheckAccountNameInDomain(DomainObject,
2489 AccountName->Buffer);
2490 if (!NT_SUCCESS(Status))
2491 {
2492 TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n",
2493 AccountName->Buffer, Status);
2494 return Status;
2495 }
2496
2497 /* Get the fixed domain attributes */
2498 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
2499 Status = SampGetObjectAttribute(DomainObject,
2500 L"F",
2501 NULL,
2502 (PVOID)&FixedDomainData,
2503 &ulSize);
2504 if (!NT_SUCCESS(Status))
2505 {
2506 TRACE("failed with status 0x%08lx\n", Status);
2507 return Status;
2508 }
2509
2510 /* Increment the NextRid attribute */
2511 ulRid = FixedDomainData.NextRid;
2512 FixedDomainData.NextRid++;
2513
2514 /* Store the fixed domain attributes */
2515 Status = SampSetObjectAttribute(DomainObject,
2516 L"F",
2517 REG_BINARY,
2518 &FixedDomainData,
2519 ulSize);
2520 if (!NT_SUCCESS(Status))
2521 {
2522 TRACE("failed with status 0x%08lx\n", Status);
2523 return Status;
2524 }
2525
2526 TRACE("RID: %lx\n", ulRid);
2527
2528 /* Convert the RID into a string (hex) */
2529 swprintf(szRid, L"%08lX", ulRid);
2530
2531 /* Create the alias object */
2532 Status = SampCreateDbObject(DomainObject,
2533 L"Aliases",
2534 szRid,
2535 ulRid,
2536 SamDbAliasObject,
2537 DesiredAccess,
2538 &AliasObject);
2539 if (!NT_SUCCESS(Status))
2540 {
2541 TRACE("failed with status 0x%08lx\n", Status);
2542 return Status;
2543 }
2544
2545 /* Add the account name for the alias object */
2546 Status = SampSetAccountNameInDomain(DomainObject,
2547 L"Aliases",
2548 AccountName->Buffer,
2549 ulRid);
2550 if (!NT_SUCCESS(Status))
2551 {
2552 TRACE("failed with status 0x%08lx\n", Status);
2553 return Status;
2554 }
2555
2556 /* Set the Name attribute */
2557 Status = SampSetObjectAttribute(AliasObject,
2558 L"Name",
2559 REG_SZ,
2560 (LPVOID)AccountName->Buffer,
2561 AccountName->MaximumLength);
2562 if (!NT_SUCCESS(Status))
2563 {
2564 TRACE("failed with status 0x%08lx\n", Status);
2565 return Status;
2566 }
2567
2568 /* Set the Description attribute */
2569 Status = SampSetObjectAttribute(AliasObject,
2570 L"Description",
2571 REG_SZ,
2572 EmptyString.Buffer,
2573 EmptyString.MaximumLength);
2574 if (!NT_SUCCESS(Status))
2575 {
2576 TRACE("failed with status 0x%08lx\n", Status);
2577 return Status;
2578 }
2579
2580 if (NT_SUCCESS(Status))
2581 {
2582 *AliasHandle = (SAMPR_HANDLE)AliasObject;
2583 *RelativeId = ulRid;
2584 }
2585
2586 TRACE("returns with status 0x%08lx\n", Status);
2587
2588 return Status;
2589 }
2590
2591
2592 /* Function 15 */
2593 NTSTATUS
2594 NTAPI
2595 SamrEnumerateAliasesInDomain(IN SAMPR_HANDLE DomainHandle,
2596 IN OUT unsigned long *EnumerationContext,
2597 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
2598 IN unsigned long PreferedMaximumLength,
2599 OUT unsigned long *CountReturned)
2600 {
2601 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
2602 PSAM_DB_OBJECT DomainObject;
2603 HANDLE AliasesKeyHandle = NULL;
2604 HANDLE NamesKeyHandle = NULL;
2605 WCHAR AliasName[64];
2606 ULONG EnumIndex;
2607 ULONG EnumCount = 0;
2608 ULONG RequiredLength = 0;
2609 ULONG NameLength;
2610 ULONG DataLength;
2611 ULONG Rid;
2612 ULONG i;
2613 BOOLEAN MoreEntries = FALSE;
2614 NTSTATUS Status;
2615
2616 TRACE("SamrEnumerateAliasesInDomain(%p %p %p %lu %p)\n",
2617 DomainHandle, EnumerationContext, Buffer,
2618 PreferedMaximumLength, CountReturned);
2619
2620 /* Validate the domain handle */
2621 Status = SampValidateDbObject(DomainHandle,
2622 SamDbDomainObject,
2623 DOMAIN_LIST_ACCOUNTS,
2624 &DomainObject);
2625 if (!NT_SUCCESS(Status))
2626 return Status;
2627
2628 Status = SampRegOpenKey(DomainObject->KeyHandle,
2629 L"Aliases",
2630 KEY_READ,
2631 &AliasesKeyHandle);
2632 if (!NT_SUCCESS(Status))
2633 return Status;
2634
2635 Status = SampRegOpenKey(AliasesKeyHandle,
2636 L"Names",
2637 KEY_READ,
2638 &NamesKeyHandle);
2639 if (!NT_SUCCESS(Status))
2640 goto done;
2641
2642 TRACE("Part 1\n");
2643
2644 EnumIndex = *EnumerationContext;
2645
2646 while (TRUE)
2647 {
2648 NameLength = 64 * sizeof(WCHAR);
2649 Status = SampRegEnumerateValue(NamesKeyHandle,
2650 EnumIndex,
2651 AliasName,
2652 &NameLength,
2653 NULL,
2654 NULL,
2655 NULL);
2656 if (!NT_SUCCESS(Status))
2657 {
2658 if (Status == STATUS_NO_MORE_ENTRIES)
2659 Status = STATUS_SUCCESS;
2660 break;
2661 }
2662
2663 TRACE("EnumIndex: %lu\n", EnumIndex);
2664 TRACE("Alias name: %S\n", AliasName);
2665 TRACE("Name length: %lu\n", NameLength);
2666
2667 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
2668 {
2669 MoreEntries = TRUE;
2670 break;
2671 }
2672
2673 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
2674 EnumCount++;
2675
2676 EnumIndex++;
2677 }
2678
2679 TRACE("EnumCount: %lu\n", EnumCount);
2680 TRACE("RequiredLength: %lu\n", RequiredLength);
2681
2682 if (!NT_SUCCESS(Status))
2683 goto done;
2684
2685 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
2686 if (EnumBuffer == NULL)
2687 {
2688 Status = STATUS_INSUFFICIENT_RESOURCES;
2689 goto done;
2690 }
2691
2692 EnumBuffer->EntriesRead = EnumCount;
2693 if (EnumCount == 0)
2694 goto done;
2695
2696 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
2697 if (EnumBuffer->Buffer == NULL)
2698 {
2699 Status = STATUS_INSUFFICIENT_RESOURCES;
2700 goto done;
2701 }
2702
2703 TRACE("Part 2\n");
2704
2705 EnumIndex = *EnumerationContext;
2706 for (i = 0; i < EnumCount; i++, EnumIndex++)
2707 {
2708 NameLength = 64 * sizeof(WCHAR);
2709 DataLength = sizeof(ULONG);
2710 Status = SampRegEnumerateValue(NamesKeyHandle,
2711 EnumIndex,
2712 AliasName,
2713 &NameLength,
2714 NULL,
2715 &Rid,
2716 &DataLength);
2717 if (!NT_SUCCESS(Status))
2718 {
2719 if (Status == STATUS_NO_MORE_ENTRIES)
2720 Status = STATUS_SUCCESS;
2721 break;
2722 }
2723
2724 TRACE("EnumIndex: %lu\n", EnumIndex);
2725 TRACE("Alias name: %S\n", AliasName);
2726 TRACE("Name length: %lu\n", NameLength);
2727 TRACE("RID: %lu\n", Rid);
2728
2729 EnumBuffer->Buffer[i].RelativeId = Rid;
2730
2731 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
2732 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(DataLength + sizeof(UNICODE_NULL));
2733
2734 /* FIXME: Disabled because of bugs in widl and rpcrt4 */
2735 #if 0
2736 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
2737 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
2738 {
2739 Status = STATUS_INSUFFICIENT_RESOURCES;
2740 goto done;
2741 }
2742
2743 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
2744 AliasName,
2745 EnumBuffer->Buffer[i].Name.Length);
2746 #endif
2747 }
2748
2749 done:
2750 if (NT_SUCCESS(Status))
2751 {
2752 *EnumerationContext += EnumCount;
2753 *Buffer = EnumBuffer;
2754 *CountReturned = EnumCount;
2755 }
2756 else
2757 {
2758 *EnumerationContext = 0;
2759 *Buffer = NULL;
2760 *CountReturned = 0;
2761
2762 if (EnumBuffer != NULL)
2763 {
2764 if (EnumBuffer->Buffer != NULL)
2765 {
2766 if (EnumBuffer->EntriesRead != 0)
2767 {
2768 for (i = 0; i < EnumBuffer->EntriesRead; i++)
2769 {
2770 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
2771 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
2772 }
2773 }
2774
2775 midl_user_free(EnumBuffer->Buffer);
2776 }
2777
2778 midl_user_free(EnumBuffer);
2779 }
2780 }
2781
2782 if (NamesKeyHandle != NULL)
2783 SampRegCloseKey(NamesKeyHandle);
2784
2785 if (AliasesKeyHandle != NULL)
2786 SampRegCloseKey(AliasesKeyHandle);
2787
2788 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
2789 Status = STATUS_MORE_ENTRIES;
2790
2791 return Status;
2792 }
2793
2794
2795 /* Function 16 */
2796 NTSTATUS
2797 NTAPI
2798 SamrGetAliasMembership(IN SAMPR_HANDLE DomainHandle,
2799 IN PSAMPR_PSID_ARRAY SidArray,
2800 OUT PSAMPR_ULONG_ARRAY Membership)
2801 {
2802 PSAM_DB_OBJECT DomainObject;
2803 HANDLE AliasesKeyHandle = NULL;
2804 HANDLE MembersKeyHandle = NULL;
2805 HANDLE MemberKeyHandle = NULL;
2806 LPWSTR MemberSidString = NULL;
2807 PULONG RidArray = NULL;
2808 ULONG MaxSidCount = 0;
2809 ULONG ValueCount;
2810 ULONG DataLength;
2811 ULONG i, j;
2812 NTSTATUS Status;
2813
2814 TRACE("SamrGetAliasMembership(%p %p %p)\n",
2815 DomainHandle, SidArray, Membership);
2816
2817 /* Validate the domain handle */
2818 Status = SampValidateDbObject(DomainHandle,
2819 SamDbDomainObject,
2820 DOMAIN_LOOKUP,
2821 &DomainObject);
2822 if (!NT_SUCCESS(Status))
2823 return Status;
2824
2825 Status = SampRegOpenKey(DomainObject->KeyHandle,
2826 L"Aliases",
2827 KEY_READ,
2828 &AliasesKeyHandle);
2829 TRACE("SampRegOpenKey returned %08lX\n", Status);
2830 if (!NT_SUCCESS(Status))
2831 goto done;
2832
2833 Status = SampRegOpenKey(AliasesKeyHandle,
2834 L"Members",
2835 KEY_READ,
2836 &MembersKeyHandle);
2837 TRACE("SampRegOpenKey returned %08lX\n", Status);
2838 if (!NT_SUCCESS(Status))
2839 goto done;
2840
2841 for (i = 0; i < SidArray->Count; i++)
2842 {
2843 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
2844 TRACE("Open %S\n", MemberSidString);
2845
2846 Status = SampRegOpenKey(MembersKeyHandle,
2847 MemberSidString,
2848 KEY_READ,
2849 &MemberKeyHandle);
2850 TRACE("SampRegOpenKey returned %08lX\n", Status);
2851 if (NT_SUCCESS(Status))
2852 {
2853 Status = SampRegQueryKeyInfo(MemberKeyHandle,
2854 NULL,
2855 &ValueCount);
2856 if (NT_SUCCESS(Status))
2857 {
2858 TRACE("Found %lu values\n", ValueCount);
2859 MaxSidCount += ValueCount;
2860 }
2861
2862
2863 NtClose(MemberKeyHandle);
2864 }
2865
2866 LocalFree(MemberSidString);
2867 }
2868
2869 TRACE("Maximum sid count: %lu\n", MaxSidCount);
2870 RidArray = midl_user_allocate(MaxSidCount * sizeof(ULONG));
2871 if (RidArray == NULL)
2872 {
2873 Status = STATUS_INSUFFICIENT_RESOURCES;
2874 goto done;
2875 }
2876
2877 for (i = 0; i < SidArray->Count; i++)
2878 {
2879 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
2880 TRACE("Open %S\n", MemberSidString);
2881
2882 Status = SampRegOpenKey(MembersKeyHandle,
2883 MemberSidString,
2884 KEY_READ,
2885 &MemberKeyHandle);
2886 TRACE("SampRegOpenKey returned %08lX\n", Status);
2887 if (NT_SUCCESS(Status))
2888 {
2889 Status = SampRegQueryKeyInfo(MemberKeyHandle,
2890 NULL,
2891 &ValueCount);
2892 if (NT_SUCCESS(Status))
2893 {
2894 TRACE("Found %lu values\n", ValueCount);
2895
2896 for (j = 0; j < ValueCount; j++)
2897 {
2898 DataLength = sizeof(ULONG);
2899 Status = SampRegEnumerateValue(MemberKeyHandle,
2900 j,
2901 NULL,
2902 NULL,
2903 NULL,
2904 (PVOID)&RidArray[j],
2905 &DataLength);
2906 }
2907 }
2908
2909 NtClose(MemberKeyHandle);
2910 }
2911
2912 LocalFree(MemberSidString);
2913 }
2914
2915
2916 done:
2917 if (NT_SUCCESS(Status))
2918 {
2919 Membership->Count = MaxSidCount;
2920 Membership->Element = RidArray;
2921 }
2922 else
2923 {
2924 if (RidArray != NULL)
2925 midl_user_free(RidArray);
2926 }
2927
2928 if (MembersKeyHandle != NULL)
2929 NtClose(MembersKeyHandle);
2930
2931 if (MembersKeyHandle != NULL)
2932 NtClose(MembersKeyHandle);
2933
2934 if (AliasesKeyHandle != NULL)
2935 NtClose(AliasesKeyHandle);
2936
2937 return Status;
2938 }
2939
2940
2941 /* Function 17 */
2942 NTSTATUS
2943 NTAPI
2944 SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
2945 IN ULONG Count,
2946 IN RPC_UNICODE_STRING Names[],
2947 OUT PSAMPR_ULONG_ARRAY RelativeIds,
2948 OUT PSAMPR_ULONG_ARRAY Use)
2949 {
2950 PSAM_DB_OBJECT DomainObject;
2951 HANDLE AccountsKeyHandle;
2952 HANDLE NamesKeyHandle;
2953 ULONG MappedCount = 0;
2954 ULONG DataLength;
2955 ULONG i;
2956 ULONG RelativeId;
2957 NTSTATUS Status;
2958
2959 TRACE("SamrLookupNamesInDomain(%p %lu %p %p %p)\n",
2960 DomainHandle, Count, Names, RelativeIds, Use);
2961
2962 /* Validate the domain handle */
2963 Status = SampValidateDbObject(DomainHandle,
2964 SamDbDomainObject,
2965 DOMAIN_LOOKUP,
2966 &DomainObject);
2967 if (!NT_SUCCESS(Status))
2968 {
2969 TRACE("failed with status 0x%08lx\n", Status);
2970 return Status;
2971 }
2972
2973 RelativeIds->Count = 0;
2974 Use->Count = 0;
2975
2976 if (Count == 0)
2977 return STATUS_SUCCESS;
2978
2979 /* Allocate the relative IDs array */
2980 RelativeIds->Element = midl_user_allocate(Count * sizeof(ULONG));
2981 if (RelativeIds->Element == NULL)
2982 {
2983 Status = STATUS_INSUFFICIENT_RESOURCES;
2984 goto done;
2985 }
2986
2987 /* Allocate the use array */
2988 Use->Element = midl_user_allocate(Count * sizeof(ULONG));
2989 if (Use->Element == NULL)
2990 {
2991 Status = STATUS_INSUFFICIENT_RESOURCES;
2992 goto done;
2993 }
2994
2995 RelativeIds->Count = Count;
2996 Use->Count = Count;
2997
2998 for (i = 0; i < Count; i++)
2999 {
3000 TRACE("Name: %S\n", Names[i].Buffer);
3001
3002 RelativeId = 0;
3003
3004 /* Lookup aliases */
3005 Status = SampRegOpenKey(DomainObject->KeyHandle,
3006 L"Aliases",
3007 KEY_READ,
3008 &AccountsKeyHandle);
3009 if (NT_SUCCESS(Status))
3010 {
3011 Status = SampRegOpenKey(AccountsKeyHandle,
3012 L"Names",
3013 KEY_READ,
3014 &NamesKeyHandle);
3015 if (NT_SUCCESS(Status))
3016 {
3017 DataLength = sizeof(ULONG);
3018 Status = SampRegQueryValue(NamesKeyHandle,
3019 Names[i].Buffer,
3020 NULL,
3021 &RelativeId,
3022 &DataLength);
3023
3024 SampRegCloseKey(NamesKeyHandle);
3025 }
3026
3027 SampRegCloseKey(AccountsKeyHandle);
3028 }
3029
3030 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3031 break;
3032
3033 /* Return alias account */
3034 if (NT_SUCCESS(Status) && RelativeId != 0)
3035 {
3036 TRACE("Rid: %lu\n", RelativeId);
3037 RelativeIds->Element[i] = RelativeId;
3038 Use->Element[i] = SidTypeAlias;
3039 MappedCount++;
3040 continue;
3041 }
3042
3043 /* Lookup groups */
3044 Status = SampRegOpenKey(DomainObject->KeyHandle,
3045 L"Groups",
3046 KEY_READ,
3047 &AccountsKeyHandle);
3048 if (NT_SUCCESS(Status))
3049 {
3050 Status = SampRegOpenKey(AccountsKeyHandle,
3051 L"Names",
3052 KEY_READ,
3053 &NamesKeyHandle);
3054 if (NT_SUCCESS(Status))
3055 {
3056 DataLength = sizeof(ULONG);
3057 Status = SampRegQueryValue(NamesKeyHandle,
3058 Names[i].Buffer,
3059 NULL,
3060 &RelativeId,
3061 &DataLength);
3062
3063 SampRegCloseKey(NamesKeyHandle);
3064 }
3065
3066 SampRegCloseKey(AccountsKeyHandle);
3067 }
3068
3069 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3070 break;
3071
3072 /* Return group account */
3073 if (NT_SUCCESS(Status) && RelativeId != 0)
3074 {
3075 TRACE("Rid: %lu\n", RelativeId);
3076 RelativeIds->Element[i] = RelativeId;
3077 Use->Element[i] = SidTypeGroup;
3078 MappedCount++;
3079 continue;
3080 }
3081
3082 /* Lookup users */
3083 Status = SampRegOpenKey(DomainObject->KeyHandle,
3084 L"Users",
3085 KEY_READ,
3086 &AccountsKeyHandle);
3087 if (NT_SUCCESS(Status))
3088 {
3089 Status = SampRegOpenKey(AccountsKeyHandle,
3090 L"Names",
3091 KEY_READ,
3092 &NamesKeyHandle);
3093 if (NT_SUCCESS(Status))
3094 {
3095 DataLength = sizeof(ULONG);
3096 Status = SampRegQueryValue(NamesKeyHandle,
3097 Names[i].Buffer,
3098 NULL,
3099 &RelativeId,
3100 &DataLength);
3101
3102 SampRegCloseKey(NamesKeyHandle);
3103 }
3104
3105 SampRegCloseKey(AccountsKeyHandle);
3106 }
3107
3108 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3109 break;
3110
3111 /* Return user account */
3112 if (NT_SUCCESS(Status) && RelativeId != 0)
3113 {
3114 TRACE("Rid: %lu\n", RelativeId);
3115 RelativeIds->Element[i] = RelativeId;
3116 Use->Element[i] = SidTypeUser;
3117 MappedCount++;
3118 continue;
3119 }
3120
3121 /* Return unknown account */
3122 RelativeIds->Element[i] = 0;
3123 Use->Element[i] = SidTypeUnknown;
3124 }
3125
3126 done:
3127 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
3128 Status = STATUS_SUCCESS;
3129
3130 if (NT_SUCCESS(Status))
3131 {
3132 if (MappedCount == 0)
3133 Status = STATUS_NONE_MAPPED;
3134 else if (MappedCount < Count)
3135 Status = STATUS_SOME_NOT_MAPPED;
3136 }
3137 else
3138 {
3139 if (RelativeIds->Element != NULL)
3140 {
3141 midl_user_free(RelativeIds->Element);
3142 RelativeIds->Element = NULL;
3143 }
3144
3145 RelativeIds->Count = 0;
3146
3147 if (Use->Element != NULL)
3148 {
3149 midl_user_free(Use->Element);
3150 Use->Element = NULL;
3151 }
3152
3153 Use->Count = 0;
3154 }
3155
3156 TRACE("Returned Status %lx\n", Status);
3157
3158 return Status;
3159 }
3160
3161
3162 /* Function 18 */
3163 NTSTATUS
3164 NTAPI
3165 SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
3166 IN ULONG Count,
3167 IN ULONG *RelativeIds,
3168 OUT PSAMPR_RETURNED_USTRING_ARRAY Names,
3169 OUT PSAMPR_ULONG_ARRAY Use)
3170 {
3171 PSAM_DB_OBJECT DomainObject;
3172 WCHAR RidString[9];
3173 HANDLE AccountsKeyHandle;
3174 HANDLE AccountKeyHandle;
3175 ULONG MappedCount = 0;
3176 ULONG DataLength;
3177 ULONG i;
3178 NTSTATUS Status;
3179
3180 TRACE("SamrLookupIdsInDomain(%p %lu %p %p %p)\n",
3181 DomainHandle, Count, RelativeIds, Names, Use);
3182
3183 /* Validate the domain handle */
3184 Status = SampValidateDbObject(DomainHandle,
3185 SamDbDomainObject,
3186 DOMAIN_LOOKUP,
3187 &DomainObject);
3188 if (!NT_SUCCESS(Status))
3189 {
3190 TRACE("failed with status 0x%08lx\n", Status);
3191 return Status;
3192 }
3193
3194 Names->Count = 0;
3195 Use->Count = 0;
3196
3197 if (Count == 0)
3198 return STATUS_SUCCESS;
3199
3200 /* Allocate the names array */
3201 Names->Element = midl_user_allocate(Count * sizeof(ULONG));
3202 if (Names->Element == NULL)
3203 {
3204 Status = STATUS_INSUFFICIENT_RESOURCES;
3205 goto done;
3206 }
3207
3208 /* Allocate the use array */
3209 Use->Element = midl_user_allocate(Count * sizeof(ULONG));
3210 if (Use->Element == NULL)
3211 {
3212 Status = STATUS_INSUFFICIENT_RESOURCES;
3213 goto done;
3214 }
3215
3216 Names->Count = Count;
3217 Use->Count = Count;
3218
3219 for (i = 0; i < Count; i++)
3220 {
3221 TRACE("RID: %lu\n", RelativeIds[i]);
3222
3223 swprintf(RidString, L"%08lx", RelativeIds[i]);
3224
3225 /* Lookup aliases */
3226 Status = SampRegOpenKey(DomainObject->KeyHandle,
3227 L"Aliases",
3228 KEY_READ,
3229 &AccountsKeyHandle);
3230 if (NT_SUCCESS(Status))
3231 {
3232 Status = SampRegOpenKey(AccountsKeyHandle,
3233 RidString,
3234 KEY_READ,
3235 &AccountKeyHandle);
3236 if (NT_SUCCESS(Status))
3237 {
3238 DataLength = 0;
3239 Status = SampRegQueryValue(AccountKeyHandle,
3240 L"Name",
3241 NULL,
3242 NULL,
3243 &DataLength);
3244 if (NT_SUCCESS(Status))
3245 {
3246 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3247 if (Names->Element[i].Buffer == NULL)
3248 Status = STATUS_INSUFFICIENT_RESOURCES;
3249
3250 if (NT_SUCCESS(Status))
3251 {
3252 Names->Element[i].MaximumLength = (USHORT)DataLength;
3253 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3254
3255 Status = SampRegQueryValue(AccountKeyHandle,
3256 L"Name",
3257 NULL,
3258 Names->Element[i].Buffer,
3259 &DataLength);
3260 }
3261 }
3262
3263 SampRegCloseKey(AccountKeyHandle);
3264 }
3265
3266 SampRegCloseKey(AccountsKeyHandle);
3267 }
3268
3269 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3270 break;
3271
3272 /* Return alias account */
3273 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3274 {
3275 TRACE("Name: %S\n", Names->Element[i].Buffer);
3276 Use->Element[i] = SidTypeAlias;
3277 MappedCount++;
3278 continue;
3279 }
3280
3281 /* Lookup groups */
3282 Status = SampRegOpenKey(DomainObject->KeyHandle,
3283 L"Groups",
3284 KEY_READ,
3285 &AccountsKeyHandle);
3286 if (NT_SUCCESS(Status))
3287 {
3288 Status = SampRegOpenKey(AccountsKeyHandle,
3289 RidString,
3290 KEY_READ,
3291 &AccountKeyHandle);
3292 if (NT_SUCCESS(Status))
3293 {
3294 DataLength = 0;
3295 Status = SampRegQueryValue(AccountKeyHandle,
3296 L"Name",
3297 NULL,
3298 NULL,
3299 &DataLength);
3300 if (NT_SUCCESS(Status))
3301 {
3302 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3303 if (Names->Element[i].Buffer == NULL)
3304 Status = STATUS_INSUFFICIENT_RESOURCES;
3305
3306 if (NT_SUCCESS(Status))
3307 {
3308 Names->Element[i].MaximumLength = (USHORT)DataLength;
3309 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3310
3311 Status = SampRegQueryValue(AccountKeyHandle,
3312 L"Name",
3313 NULL,
3314 Names->Element[i].Buffer,
3315 &DataLength);
3316 }
3317 }
3318
3319 SampRegCloseKey(AccountKeyHandle);
3320 }
3321
3322 SampRegCloseKey(AccountsKeyHandle);
3323 }
3324
3325 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3326 break;
3327
3328 /* Return group account */
3329 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3330 {
3331 TRACE("Name: %S\n", Names->Element[i].Buffer);
3332 Use->Element[i] = SidTypeGroup;
3333 MappedCount++;
3334 continue;
3335 }
3336
3337 /* Lookup users */
3338 Status = SampRegOpenKey(DomainObject->KeyHandle,
3339 L"Users",
3340 KEY_READ,
3341 &AccountsKeyHandle);
3342 if (NT_SUCCESS(Status))
3343 {
3344 Status = SampRegOpenKey(AccountsKeyHandle,
3345 RidString,
3346 KEY_READ,
3347 &AccountKeyHandle);
3348 if (NT_SUCCESS(Status))
3349 {
3350 DataLength = 0;
3351 Status = SampRegQueryValue(AccountKeyHandle,
3352 L"Name",
3353 NULL,
3354 NULL,
3355 &DataLength);
3356 if (NT_SUCCESS(Status))
3357 {
3358 TRACE("DataLength: %lu\n", DataLength);
3359
3360 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3361 if (Names->Element[i].Buffer == NULL)
3362 Status = STATUS_INSUFFICIENT_RESOURCES;
3363
3364 if (NT_SUCCESS(Status))
3365 {
3366 Names->Element[i].MaximumLength = (USHORT)DataLength;
3367 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3368
3369 Status = SampRegQueryValue(AccountKeyHandle,
3370 L"Name",
3371 NULL,
3372 Names->Element[i].Buffer,
3373 &DataLength);
3374 }
3375 }
3376
3377 SampRegCloseKey(AccountKeyHandle);
3378 }
3379
3380 SampRegCloseKey(AccountsKeyHandle);
3381 }
3382
3383 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3384 break;
3385