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