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