826bdc7f7f278ae0c3ab2737261bdae206d683f4
[reactos.git] / reactos / dll / win32 / samsrv / samrpc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Security Account Manager (SAM) Server
4 * FILE: reactos/dll/win32/samsrv/samrpc.c
5 * PURPOSE: RPC interface functions
6 *
7 * PROGRAMMERS: Eric Kohl
8 */
9
10 /* INCLUDES ****************************************************************/
11
12 #include "samsrv.h"
13
14 WINE_DEFAULT_DEBUG_CHANNEL(samsrv);
15
16 /* GLOBALS ********************************************************************/
17
18 static SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
19
20
21 /* FUNCTIONS ***************************************************************/
22
23 VOID
24 SampStartRpcServer(VOID)
25 {
26 RPC_STATUS Status;
27
28 TRACE("SampStartRpcServer() called\n");
29
30 Status = RpcServerUseProtseqEpW(L"ncacn_np",
31 10,
32 L"\\pipe\\samr",
33 NULL);
34 if (Status != RPC_S_OK)
35 {
36 WARN("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
37 return;
38 }
39
40 Status = RpcServerRegisterIf(samr_v1_0_s_ifspec,
41 NULL,
42 NULL);
43 if (Status != RPC_S_OK)
44 {
45 WARN("RpcServerRegisterIf() failed (Status %lx)\n", Status);
46 return;
47 }
48
49 Status = RpcServerListen(1, 20, TRUE);
50 if (Status != RPC_S_OK)
51 {
52 WARN("RpcServerListen() failed (Status %lx)\n", Status);
53 return;
54 }
55
56 TRACE("SampStartRpcServer() done\n");
57 }
58
59
60 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
61 {
62 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
63 }
64
65
66 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
67 {
68 HeapFree(GetProcessHeap(), 0, ptr);
69 }
70
71 void __RPC_USER SAMPR_HANDLE_rundown(SAMPR_HANDLE hHandle)
72 {
73 }
74
75 /* Function 0 */
76 NTSTATUS
77 NTAPI
78 SamrConnect(IN PSAMPR_SERVER_NAME ServerName,
79 OUT SAMPR_HANDLE *ServerHandle,
80 IN ACCESS_MASK DesiredAccess)
81 {
82 PSAM_DB_OBJECT ServerObject;
83 NTSTATUS Status;
84
85 TRACE("SamrConnect(%p %p %lx)\n",
86 ServerName, ServerHandle, DesiredAccess);
87
88 Status = SampOpenDbObject(NULL,
89 NULL,
90 L"SAM",
91 SamDbServerObject,
92 DesiredAccess,
93 &ServerObject);
94 if (NT_SUCCESS(Status))
95 *ServerHandle = (SAMPR_HANDLE)ServerObject;
96
97 TRACE("SamrConnect done (Status 0x%08lx)\n", Status);
98
99 return Status;
100 }
101
102 /* Function 1 */
103 NTSTATUS
104 NTAPI
105 SamrCloseHandle(IN OUT SAMPR_HANDLE *SamHandle)
106 {
107 PSAM_DB_OBJECT DbObject;
108 NTSTATUS Status = STATUS_SUCCESS;
109
110 TRACE("SamrCloseHandle(%p)\n", SamHandle);
111
112 Status = SampValidateDbObject(*SamHandle,
113 SamDbIgnoreObject,
114 0,
115 &DbObject);
116 if (Status == STATUS_SUCCESS)
117 {
118 Status = SampCloseDbObject(DbObject);
119 *SamHandle = NULL;
120 }
121
122 TRACE("SamrCloseHandle done (Status 0x%08lx)\n", Status);
123
124 return Status;
125 }
126
127 /* Function 2 */
128 NTSTATUS
129 NTAPI
130 SamrSetSecurityObject(IN SAMPR_HANDLE ObjectHandle,
131 IN SECURITY_INFORMATION SecurityInformation,
132 IN PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor)
133 {
134 UNIMPLEMENTED;
135 return STATUS_NOT_IMPLEMENTED;
136 }
137
138 /* Function 3 */
139 NTSTATUS
140 NTAPI
141 SamrQuerySecurityObject(IN SAMPR_HANDLE ObjectHandle,
142 IN SECURITY_INFORMATION SecurityInformation,
143 OUT PSAMPR_SR_SECURITY_DESCRIPTOR * SecurityDescriptor)
144 {
145 UNIMPLEMENTED;
146 return STATUS_NOT_IMPLEMENTED;
147 }
148
149 /* Function 4 */
150 NTSTATUS
151 NTAPI
152 SamrShutdownSamServer(IN SAMPR_HANDLE ServerHandle)
153 {
154 UNIMPLEMENTED;
155 return STATUS_NOT_IMPLEMENTED;
156 }
157
158 /* Function 5 */
159 NTSTATUS
160 NTAPI
161 SamrLookupDomainInSamServer(IN SAMPR_HANDLE ServerHandle,
162 IN PRPC_UNICODE_STRING Name,
163 OUT PRPC_SID *DomainId)
164 {
165 PSAM_DB_OBJECT ServerObject;
166 HANDLE DomainsKeyHandle = NULL;
167 HANDLE DomainKeyHandle = NULL;
168 WCHAR DomainKeyName[64];
169 ULONG Index;
170 WCHAR DomainNameString[MAX_COMPUTERNAME_LENGTH + 1];
171 UNICODE_STRING DomainName;
172 ULONG Length;
173 BOOL Found = FALSE;
174 NTSTATUS Status;
175
176 TRACE("SamrLookupDomainInSamServer(%p %p %p)\n",
177 ServerHandle, Name, DomainId);
178
179 /* Validate the server handle */
180 Status = SampValidateDbObject(ServerHandle,
181 SamDbServerObject,
182 SAM_SERVER_LOOKUP_DOMAIN,
183 &ServerObject);
184 if (!NT_SUCCESS(Status))
185 return Status;
186
187 *DomainId = NULL;
188
189 Status = SampRegOpenKey(ServerObject->KeyHandle,
190 L"Domains",
191 KEY_READ,
192 &DomainsKeyHandle);
193 if (!NT_SUCCESS(Status))
194 return Status;
195
196 Index = 0;
197 while (Found == FALSE)
198 {
199 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
200 Index,
201 64,
202 DomainKeyName);
203 if (!NT_SUCCESS(Status))
204 {
205 if (Status == STATUS_NO_MORE_ENTRIES)
206 Status = STATUS_NO_SUCH_DOMAIN;
207 break;
208 }
209
210 TRACE("Domain key name: %S\n", DomainKeyName);
211
212 Status = SampRegOpenKey(DomainsKeyHandle,
213 DomainKeyName,
214 KEY_READ,
215 &DomainKeyHandle);
216 if (NT_SUCCESS(Status))
217 {
218 Length = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR);
219 Status = SampRegQueryValue(DomainKeyHandle,
220 L"Name",
221 NULL,
222 (PVOID)&DomainNameString,
223 &Length);
224 if (NT_SUCCESS(Status))
225 {
226 TRACE("Domain name: %S\n", DomainNameString);
227
228 RtlInitUnicodeString(&DomainName,
229 DomainNameString);
230 if (RtlEqualUnicodeString(&DomainName, (PUNICODE_STRING)Name, TRUE))
231 {
232 TRACE("Found it!\n");
233 Found = TRUE;
234
235 Status = SampRegQueryValue(DomainKeyHandle,
236 L"SID",
237 NULL,
238 NULL,
239 &Length);
240 if (NT_SUCCESS(Status))
241 {
242 *DomainId = midl_user_allocate(Length);
243
244 SampRegQueryValue(DomainKeyHandle,
245 L"SID",
246 NULL,
247 (PVOID)*DomainId,
248 &Length);
249
250 Status = STATUS_SUCCESS;
251 break;
252 }
253 }
254 }
255
256 NtClose(DomainKeyHandle);
257 }
258
259 Index++;
260 }
261
262 NtClose(DomainsKeyHandle);
263
264 return Status;
265 }
266
267 /* Function 6 */
268 NTSTATUS
269 NTAPI
270 SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle,
271 IN OUT unsigned long *EnumerationContext,
272 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
273 IN ULONG PreferedMaximumLength,
274 OUT PULONG CountReturned)
275 {
276 PSAM_DB_OBJECT ServerObject;
277 WCHAR DomainKeyName[64];
278 HANDLE DomainsKeyHandle;
279 HANDLE DomainKeyHandle;
280 ULONG EnumIndex;
281 ULONG EnumCount;
282 ULONG RequiredLength;
283 ULONG DataLength;
284 ULONG i;
285 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
286 NTSTATUS Status;
287
288 TRACE("SamrEnumerateDomainsInSamServer(%p %p %p %lu %p)\n",
289 ServerHandle, EnumerationContext, Buffer, PreferedMaximumLength,
290 CountReturned);
291
292 /* Validate the server handle */
293 Status = SampValidateDbObject(ServerHandle,
294 SamDbServerObject,
295 SAM_SERVER_ENUMERATE_DOMAINS,
296 &ServerObject);
297 if (!NT_SUCCESS(Status))
298 return Status;
299
300 Status = SampRegOpenKey(ServerObject->KeyHandle,
301 L"Domains",
302 KEY_READ,
303 &DomainsKeyHandle);
304 if (!NT_SUCCESS(Status))
305 return Status;
306
307 EnumIndex = *EnumerationContext;
308 EnumCount = 0;
309 RequiredLength = 0;
310
311 while (TRUE)
312 {
313 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
314 EnumIndex,
315 64 * sizeof(WCHAR),
316 DomainKeyName);
317 if (!NT_SUCCESS(Status))
318 break;
319
320 TRACE("EnumIndex: %lu\n", EnumIndex);
321 TRACE("Domain key name: %S\n", DomainKeyName);
322
323 Status = SampRegOpenKey(DomainsKeyHandle,
324 DomainKeyName,
325 KEY_READ,
326 &DomainKeyHandle);
327 TRACE("SampRegOpenKey returned %08lX\n", Status);
328 if (NT_SUCCESS(Status))
329 {
330 DataLength = 0;
331 Status = SampRegQueryValue(DomainKeyHandle,
332 L"Name",
333 NULL,
334 NULL,
335 &DataLength);
336 TRACE("SampRegQueryValue returned %08lX\n", Status);
337 if (NT_SUCCESS(Status))
338 {
339 TRACE("Data length: %lu\n", DataLength);
340
341 if ((RequiredLength + DataLength + sizeof(UNICODE_STRING)) > PreferedMaximumLength)
342 break;
343
344 RequiredLength += (DataLength + sizeof(UNICODE_STRING));
345 EnumCount++;
346 }
347
348 NtClose(DomainKeyHandle);
349 }
350
351 EnumIndex++;
352 }
353
354 TRACE("EnumCount: %lu\n", EnumCount);
355 TRACE("RequiredLength: %lu\n", RequiredLength);
356
357 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
358 if (EnumBuffer == NULL)
359 {
360 Status = STATUS_INSUFFICIENT_RESOURCES;
361 goto done;
362 }
363
364 EnumBuffer->EntriesRead = EnumCount;
365 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
366 if (EnumBuffer->Buffer == NULL)
367 {
368 Status = STATUS_INSUFFICIENT_RESOURCES;
369 goto done;
370 }
371
372 EnumIndex = *EnumerationContext;
373 for (i = 0; i < EnumCount; i++, EnumIndex++)
374 {
375 Status = SampRegEnumerateSubKey(DomainsKeyHandle,
376 EnumIndex,
377 64 * sizeof(WCHAR),
378 DomainKeyName);
379 if (!NT_SUCCESS(Status))
380 break;
381
382 TRACE("EnumIndex: %lu\n", EnumIndex);
383 TRACE("Domain key name: %S\n", DomainKeyName);
384
385 Status = SampRegOpenKey(DomainsKeyHandle,
386 DomainKeyName,
387 KEY_READ,
388 &DomainKeyHandle);
389 TRACE("SampRegOpenKey returned %08lX\n", Status);
390 if (NT_SUCCESS(Status))
391 {
392 DataLength = 0;
393 Status = SampRegQueryValue(DomainKeyHandle,
394 L"Name",
395 NULL,
396 NULL,
397 &DataLength);
398 TRACE("SampRegQueryValue returned %08lX\n", Status);
399 if (NT_SUCCESS(Status))
400 {
401 EnumBuffer->Buffer[i].RelativeId = 0;
402 EnumBuffer->Buffer[i].Name.Length = (USHORT)DataLength - sizeof(WCHAR);
403 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)DataLength;
404 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(DataLength);
405 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
406 {
407 NtClose(DomainKeyHandle);
408 Status = STATUS_INSUFFICIENT_RESOURCES;
409 goto done;
410 }
411
412 Status = SampRegQueryValue(DomainKeyHandle,
413 L"Name",
414 NULL,
415 EnumBuffer->Buffer[i].Name.Buffer,
416 &DataLength);
417 TRACE("SampRegQueryValue returned %08lX\n", Status);
418 if (NT_SUCCESS(Status))
419 {
420 TRACE("Domain name: %S\n", EnumBuffer->Buffer[i].Name.Buffer);
421 }
422 }
423
424 NtClose(DomainKeyHandle);
425
426 if (!NT_SUCCESS(Status))
427 goto done;
428 }
429 }
430
431 if (NT_SUCCESS(Status))
432 {
433 *EnumerationContext += EnumCount;
434 *Buffer = EnumBuffer;
435 *CountReturned = EnumCount;
436 }
437
438 done:
439 if (!NT_SUCCESS(Status))
440 {
441 *EnumerationContext = 0;
442 *Buffer = NULL;
443 *CountReturned = 0;
444
445 if (EnumBuffer != NULL)
446 {
447 if (EnumBuffer->Buffer != NULL)
448 {
449 if (EnumBuffer->EntriesRead != 0)
450 {
451 for (i = 0; i < EnumBuffer->EntriesRead; i++)
452 {
453 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
454 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
455 }
456 }
457
458 midl_user_free(EnumBuffer->Buffer);
459 }
460
461 midl_user_free(EnumBuffer);
462 }
463 }
464
465 NtClose(DomainsKeyHandle);
466
467 return Status;
468 }
469
470 /* Function 7 */
471 NTSTATUS
472 NTAPI
473 SamrOpenDomain(IN SAMPR_HANDLE ServerHandle,
474 IN ACCESS_MASK DesiredAccess,
475 IN PRPC_SID DomainId,
476 OUT SAMPR_HANDLE *DomainHandle)
477 {
478 PSAM_DB_OBJECT ServerObject;
479 PSAM_DB_OBJECT DomainObject;
480 NTSTATUS Status;
481
482 TRACE("SamrOpenDomain(%p %lx %p %p)\n",
483 ServerHandle, DesiredAccess, DomainId, DomainHandle);
484
485 /* Validate the server handle */
486 Status = SampValidateDbObject(ServerHandle,
487 SamDbServerObject,
488 SAM_SERVER_LOOKUP_DOMAIN,
489 &ServerObject);
490 if (!NT_SUCCESS(Status))
491 return Status;
492
493 /* Validate the Domain SID */
494 if ((DomainId->Revision != SID_REVISION) ||
495 (DomainId->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) ||
496 (memcmp(&DomainId->IdentifierAuthority, &NtSidAuthority, sizeof(SID_IDENTIFIER_AUTHORITY)) != 0))
497 return STATUS_INVALID_PARAMETER;
498
499 /* Open the domain object */
500 if ((DomainId->SubAuthorityCount == 1) &&
501 (DomainId->SubAuthority[0] == SECURITY_BUILTIN_DOMAIN_RID))
502 {
503 /* Builtin domain object */
504 TRACE("Opening the builtin domain object.\n");
505
506 Status = SampOpenDbObject(ServerObject,
507 L"Domains",
508 L"Builtin",
509 SamDbDomainObject,
510 DesiredAccess,
511 &DomainObject);
512 }
513 else if ((DomainId->SubAuthorityCount == 4) &&
514 (DomainId->SubAuthority[0] == SECURITY_NT_NON_UNIQUE))
515 {
516 /* Account domain object */
517 TRACE("Opening the account domain object.\n");
518
519 /* FIXME: Check the account domain sub authorities!!! */
520
521 Status = SampOpenDbObject(ServerObject,
522 L"Domains",
523 L"Account",
524 SamDbDomainObject,
525 DesiredAccess,
526 &DomainObject);
527 }
528 else
529 {
530 /* No vaild domain SID */
531 Status = STATUS_INVALID_PARAMETER;
532 }
533
534 if (NT_SUCCESS(Status))
535 *DomainHandle = (SAMPR_HANDLE)DomainObject;
536
537 TRACE("SamrOpenDomain done (Status 0x%08lx)\n", Status);
538
539 return Status;
540 }
541
542
543 static NTSTATUS
544 SampQueryDomainPassword(PSAM_DB_OBJECT DomainObject,
545 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
546 {
547 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
548 SAM_DOMAIN_FIXED_DATA FixedData;
549 ULONG Length = 0;
550 NTSTATUS Status;
551
552 *Buffer = NULL;
553
554 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
555 if (InfoBuffer == NULL)
556 return STATUS_INSUFFICIENT_RESOURCES;
557
558 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
559 Status = SampGetObjectAttribute(DomainObject,
560 L"F",
561 NULL,
562 (PVOID)&FixedData,
563 &Length);
564 if (!NT_SUCCESS(Status))
565 goto done;
566
567 InfoBuffer->Password.MinPasswordLength = FixedData.MinPasswordLength;
568 InfoBuffer->Password.PasswordHistoryLength = FixedData.PasswordHistoryLength;
569 InfoBuffer->Password.PasswordProperties = FixedData.PasswordProperties;
570 InfoBuffer->Password.MaxPasswordAge.LowPart = FixedData.MaxPasswordAge.LowPart;
571 InfoBuffer->Password.MaxPasswordAge.HighPart = FixedData.MaxPasswordAge.HighPart;
572 InfoBuffer->Password.MinPasswordAge.LowPart = FixedData.MinPasswordAge.LowPart;
573 InfoBuffer->Password.MinPasswordAge.HighPart = FixedData.MinPasswordAge.HighPart;
574
575 *Buffer = InfoBuffer;
576
577 done:
578 if (!NT_SUCCESS(Status))
579 {
580 if (InfoBuffer != NULL)
581 {
582 midl_user_free(InfoBuffer);
583 }
584 }
585
586 return Status;
587 }
588
589
590 static NTSTATUS
591 SampQueryDomainGeneral(PSAM_DB_OBJECT DomainObject,
592 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
593 {
594 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
595 SAM_DOMAIN_FIXED_DATA FixedData;
596 ULONG Length = 0;
597 NTSTATUS Status;
598
599 *Buffer = NULL;
600
601 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
602 if (InfoBuffer == NULL)
603 return STATUS_INSUFFICIENT_RESOURCES;
604
605 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
606 Status = SampGetObjectAttribute(DomainObject,
607 L"F",
608 NULL,
609 (PVOID)&FixedData,
610 &Length);
611 if (!NT_SUCCESS(Status))
612 goto done;
613
614 InfoBuffer->General.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
615 InfoBuffer->General.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
616 InfoBuffer->General.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
617 InfoBuffer->General.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
618 InfoBuffer->General.DomainServerState = FixedData.DomainServerState;
619 InfoBuffer->General.DomainServerRole = FixedData.DomainServerRole;
620 InfoBuffer->General.UasCompatibilityRequired = FixedData.UasCompatibilityRequired;
621
622 /* Get the OemInformation string */
623 Status = SampGetObjectAttributeString(DomainObject,
624 L"OemInformation",
625 &InfoBuffer->General.OemInformation);
626 if (!NT_SUCCESS(Status))
627 {
628 TRACE("Status 0x%08lx\n", Status);
629 goto done;
630 }
631
632 /* Get the Name string */
633 Status = SampGetObjectAttributeString(DomainObject,
634 L"Name",
635 &InfoBuffer->General.DomainName);
636 if (!NT_SUCCESS(Status))
637 {
638 TRACE("Status 0x%08lx\n", Status);
639 goto done;
640 }
641
642 /* Get the ReplicaSourceNodeName string */
643 Status = SampGetObjectAttributeString(DomainObject,
644 L"ReplicaSourceNodeName",
645 &InfoBuffer->General.ReplicaSourceNodeName);
646 if (!NT_SUCCESS(Status))
647 {
648 TRACE("Status 0x%08lx\n", Status);
649 goto done;
650 }
651
652 InfoBuffer->General.UserCount = 0; /* FIXME */
653 InfoBuffer->General.GroupCount = 0; /* FIXME */
654 InfoBuffer->General.AliasCount = 0; /* FIXME */
655
656 *Buffer = InfoBuffer;
657
658 done:
659 if (!NT_SUCCESS(Status))
660 {
661 if (InfoBuffer != NULL)
662 {
663 if (InfoBuffer->General.OemInformation.Buffer != NULL)
664 midl_user_free(InfoBuffer->General.OemInformation.Buffer);
665
666 if (InfoBuffer->General.DomainName.Buffer != NULL)
667 midl_user_free(InfoBuffer->General.DomainName.Buffer);
668
669 if (InfoBuffer->General.ReplicaSourceNodeName.Buffer != NULL)
670 midl_user_free(InfoBuffer->General.ReplicaSourceNodeName.Buffer);
671
672 midl_user_free(InfoBuffer);
673 }
674 }
675
676 return Status;
677 }
678
679
680 static NTSTATUS
681 SampQueryDomainLogoff(PSAM_DB_OBJECT DomainObject,
682 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
683 {
684 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
685 SAM_DOMAIN_FIXED_DATA FixedData;
686 ULONG Length = 0;
687 NTSTATUS Status;
688
689 *Buffer = NULL;
690
691 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
692 if (InfoBuffer == NULL)
693 return STATUS_INSUFFICIENT_RESOURCES;
694
695 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
696 Status = SampGetObjectAttribute(DomainObject,
697 L"F",
698 NULL,
699 (PVOID)&FixedData,
700 &Length);
701 if (!NT_SUCCESS(Status))
702 goto done;
703
704 InfoBuffer->Logoff.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
705 InfoBuffer->Logoff.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
706
707 *Buffer = InfoBuffer;
708
709 done:
710 if (!NT_SUCCESS(Status))
711 {
712 if (InfoBuffer != NULL)
713 {
714 midl_user_free(InfoBuffer);
715 }
716 }
717
718 return Status;
719 }
720
721
722 static NTSTATUS
723 SampQueryDomainOem(PSAM_DB_OBJECT DomainObject,
724 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
725 {
726 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
727 NTSTATUS Status;
728
729 *Buffer = NULL;
730
731 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
732 if (InfoBuffer == NULL)
733 return STATUS_INSUFFICIENT_RESOURCES;
734
735 /* Get the OemInformation string */
736 Status = SampGetObjectAttributeString(DomainObject,
737 L"OemInformation",
738 &InfoBuffer->Oem.OemInformation);
739 if (!NT_SUCCESS(Status))
740 {
741 TRACE("Status 0x%08lx\n", Status);
742 goto done;
743 }
744
745 *Buffer = InfoBuffer;
746
747 done:
748 if (!NT_SUCCESS(Status))
749 {
750 if (InfoBuffer != NULL)
751 {
752 if (InfoBuffer->Oem.OemInformation.Buffer != NULL)
753 midl_user_free(InfoBuffer->Oem.OemInformation.Buffer);
754
755 midl_user_free(InfoBuffer);
756 }
757 }
758
759 return Status;
760 }
761
762
763 static NTSTATUS
764 SampQueryDomainName(PSAM_DB_OBJECT DomainObject,
765 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
766 {
767 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
768 NTSTATUS Status;
769
770 *Buffer = NULL;
771
772 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
773 if (InfoBuffer == NULL)
774 return STATUS_INSUFFICIENT_RESOURCES;
775
776 /* Get the Name string */
777 Status = SampGetObjectAttributeString(DomainObject,
778 L"Name",
779 &InfoBuffer->Name.DomainName);
780 if (!NT_SUCCESS(Status))
781 {
782 TRACE("Status 0x%08lx\n", Status);
783 goto done;
784 }
785
786 *Buffer = InfoBuffer;
787
788 done:
789 if (!NT_SUCCESS(Status))
790 {
791 if (InfoBuffer != NULL)
792 {
793 if (InfoBuffer->Name.DomainName.Buffer != NULL)
794 midl_user_free(InfoBuffer->Name.DomainName.Buffer);
795
796 midl_user_free(InfoBuffer);
797 }
798 }
799
800 return Status;
801 }
802
803
804 static NTSTATUS
805 SampQueryDomainReplication(PSAM_DB_OBJECT DomainObject,
806 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
807 {
808 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
809 NTSTATUS Status;
810
811 *Buffer = NULL;
812
813 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
814 if (InfoBuffer == NULL)
815 return STATUS_INSUFFICIENT_RESOURCES;
816
817 /* Get the ReplicaSourceNodeName string */
818 Status = SampGetObjectAttributeString(DomainObject,
819 L"ReplicaSourceNodeName",
820 &InfoBuffer->Replication.ReplicaSourceNodeName);
821 if (!NT_SUCCESS(Status))
822 {
823 TRACE("Status 0x%08lx\n", Status);
824 goto done;
825 }
826
827 *Buffer = InfoBuffer;
828
829 done:
830 if (!NT_SUCCESS(Status))
831 {
832 if (InfoBuffer != NULL)
833 {
834 if (InfoBuffer->Replication.ReplicaSourceNodeName.Buffer != NULL)
835 midl_user_free(InfoBuffer->Replication.ReplicaSourceNodeName.Buffer);
836
837 midl_user_free(InfoBuffer);
838 }
839 }
840
841 return Status;
842 }
843
844
845 static NTSTATUS
846 SampQueryDomainServerRole(PSAM_DB_OBJECT DomainObject,
847 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
848 {
849 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
850 SAM_DOMAIN_FIXED_DATA FixedData;
851 ULONG Length = 0;
852 NTSTATUS Status;
853
854 *Buffer = NULL;
855
856 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
857 if (InfoBuffer == NULL)
858 return STATUS_INSUFFICIENT_RESOURCES;
859
860 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
861 Status = SampGetObjectAttribute(DomainObject,
862 L"F",
863 NULL,
864 (PVOID)&FixedData,
865 &Length);
866 if (!NT_SUCCESS(Status))
867 goto done;
868
869 InfoBuffer->Role.DomainServerRole = FixedData.DomainServerRole;
870
871 *Buffer = InfoBuffer;
872
873 done:
874 if (!NT_SUCCESS(Status))
875 {
876 if (InfoBuffer != NULL)
877 {
878 midl_user_free(InfoBuffer);
879 }
880 }
881
882 return Status;
883 }
884
885
886 static NTSTATUS
887 SampQueryDomainModified(PSAM_DB_OBJECT DomainObject,
888 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
889 {
890 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
891 SAM_DOMAIN_FIXED_DATA FixedData;
892 ULONG Length = 0;
893 NTSTATUS Status;
894
895 *Buffer = NULL;
896
897 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
898 if (InfoBuffer == NULL)
899 return STATUS_INSUFFICIENT_RESOURCES;
900
901 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
902 Status = SampGetObjectAttribute(DomainObject,
903 L"F",
904 NULL,
905 (PVOID)&FixedData,
906 &Length);
907 if (!NT_SUCCESS(Status))
908 goto done;
909
910 InfoBuffer->Modified.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
911 InfoBuffer->Modified.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
912 InfoBuffer->Modified.CreationTime.LowPart = FixedData.CreationTime.LowPart;
913 InfoBuffer->Modified.CreationTime.HighPart = FixedData.CreationTime.HighPart;
914
915 *Buffer = InfoBuffer;
916
917 done:
918 if (!NT_SUCCESS(Status))
919 {
920 if (InfoBuffer != NULL)
921 {
922 midl_user_free(InfoBuffer);
923 }
924 }
925
926 return Status;
927 }
928
929
930 static NTSTATUS
931 SampQueryDomainState(PSAM_DB_OBJECT DomainObject,
932 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
933 {
934 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
935 SAM_DOMAIN_FIXED_DATA FixedData;
936 ULONG Length = 0;
937 NTSTATUS Status;
938
939 *Buffer = NULL;
940
941 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
942 if (InfoBuffer == NULL)
943 return STATUS_INSUFFICIENT_RESOURCES;
944
945 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
946 Status = SampGetObjectAttribute(DomainObject,
947 L"F",
948 NULL,
949 (PVOID)&FixedData,
950 &Length);
951 if (!NT_SUCCESS(Status))
952 goto done;
953
954 InfoBuffer->State.DomainServerState = FixedData.DomainServerState;
955
956 *Buffer = InfoBuffer;
957
958 done:
959 if (!NT_SUCCESS(Status))
960 {
961 if (InfoBuffer != NULL)
962 {
963 midl_user_free(InfoBuffer);
964 }
965 }
966
967 return Status;
968 }
969
970
971 static NTSTATUS
972 SampQueryDomainGeneral2(PSAM_DB_OBJECT DomainObject,
973 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
974 {
975 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
976 SAM_DOMAIN_FIXED_DATA FixedData;
977 ULONG Length = 0;
978 NTSTATUS Status;
979
980 *Buffer = NULL;
981
982 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
983 if (InfoBuffer == NULL)
984 return STATUS_INSUFFICIENT_RESOURCES;
985
986 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
987 Status = SampGetObjectAttribute(DomainObject,
988 L"F",
989 NULL,
990 (PVOID)&FixedData,
991 &Length);
992 if (!NT_SUCCESS(Status))
993 goto done;
994
995 InfoBuffer->General2.I1.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
996 InfoBuffer->General2.I1.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
997 InfoBuffer->General2.I1.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
998 InfoBuffer->General2.I1.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
999 InfoBuffer->General2.I1.DomainServerState = FixedData.DomainServerState;
1000 InfoBuffer->General2.I1.DomainServerRole = FixedData.DomainServerRole;
1001 InfoBuffer->General2.I1.UasCompatibilityRequired = FixedData.UasCompatibilityRequired;
1002
1003 InfoBuffer->General2.LockoutDuration = FixedData.LockoutDuration;
1004 InfoBuffer->General2.LockoutObservationWindow = FixedData.LockoutObservationWindow;
1005 InfoBuffer->General2.LockoutThreshold = FixedData.LockoutThreshold;
1006
1007 /* Get the OemInformation string */
1008 Status = SampGetObjectAttributeString(DomainObject,
1009 L"OemInformation",
1010 &InfoBuffer->General2.I1.OemInformation);
1011 if (!NT_SUCCESS(Status))
1012 {
1013 TRACE("Status 0x%08lx\n", Status);
1014 goto done;
1015 }
1016
1017 /* Get the Name string */
1018 Status = SampGetObjectAttributeString(DomainObject,
1019 L"Name",
1020 &InfoBuffer->General2.I1.DomainName);
1021 if (!NT_SUCCESS(Status))
1022 {
1023 TRACE("Status 0x%08lx\n", Status);
1024 goto done;
1025 }
1026
1027 /* Get the ReplicaSourceNodeName string */
1028 Status = SampGetObjectAttributeString(DomainObject,
1029 L"ReplicaSourceNodeName",
1030 &InfoBuffer->General2.I1.ReplicaSourceNodeName);
1031 if (!NT_SUCCESS(Status))
1032 {
1033 TRACE("Status 0x%08lx\n", Status);
1034 goto done;
1035 }
1036
1037 InfoBuffer->General2.I1.UserCount = 0; /* FIXME */
1038 InfoBuffer->General2.I1.GroupCount = 0; /* FIXME */
1039 InfoBuffer->General2.I1.AliasCount = 0; /* FIXME */
1040
1041 *Buffer = InfoBuffer;
1042
1043 done:
1044 if (!NT_SUCCESS(Status))
1045 {
1046 if (InfoBuffer != NULL)
1047 {
1048 if (InfoBuffer->General2.I1.OemInformation.Buffer != NULL)
1049 midl_user_free(InfoBuffer->General2.I1.OemInformation.Buffer);
1050
1051 if (InfoBuffer->General2.I1.DomainName.Buffer != NULL)
1052 midl_user_free(InfoBuffer->General2.I1.DomainName.Buffer);
1053
1054 if (InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer != NULL)
1055 midl_user_free(InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer);
1056
1057 midl_user_free(InfoBuffer);
1058 }
1059 }
1060
1061 return Status;
1062 }
1063
1064
1065 static NTSTATUS
1066 SampQueryDomainLockout(PSAM_DB_OBJECT DomainObject,
1067 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1068 {
1069 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1070 SAM_DOMAIN_FIXED_DATA FixedData;
1071 ULONG Length = 0;
1072 NTSTATUS Status;
1073
1074 *Buffer = NULL;
1075
1076 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1077 if (InfoBuffer == NULL)
1078 return STATUS_INSUFFICIENT_RESOURCES;
1079
1080 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1081 Status = SampGetObjectAttribute(DomainObject,
1082 L"F",
1083 NULL,
1084 (PVOID)&FixedData,
1085 &Length);
1086 if (!NT_SUCCESS(Status))
1087 goto done;
1088
1089 InfoBuffer->Lockout.LockoutDuration = FixedData.LockoutDuration;
1090 InfoBuffer->Lockout.LockoutObservationWindow = FixedData.LockoutObservationWindow;
1091 InfoBuffer->Lockout.LockoutThreshold = FixedData.LockoutThreshold;
1092
1093 *Buffer = InfoBuffer;
1094
1095 done:
1096 if (!NT_SUCCESS(Status))
1097 {
1098 if (InfoBuffer != NULL)
1099 {
1100 midl_user_free(InfoBuffer);
1101 }
1102 }
1103
1104 return Status;
1105 }
1106
1107
1108 static NTSTATUS
1109 SampQueryDomainModified2(PSAM_DB_OBJECT DomainObject,
1110 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1111 {
1112 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1113 SAM_DOMAIN_FIXED_DATA FixedData;
1114 ULONG Length = 0;
1115 NTSTATUS Status;
1116
1117 *Buffer = NULL;
1118
1119 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1120 if (InfoBuffer == NULL)
1121 return STATUS_INSUFFICIENT_RESOURCES;
1122
1123 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1124 Status = SampGetObjectAttribute(DomainObject,
1125 L"F",
1126 NULL,
1127 (PVOID)&FixedData,
1128 &Length);
1129 if (!NT_SUCCESS(Status))
1130 goto done;
1131
1132 InfoBuffer->Modified2.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
1133 InfoBuffer->Modified2.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
1134 InfoBuffer->Modified2.CreationTime.LowPart = FixedData.CreationTime.LowPart;
1135 InfoBuffer->Modified2.CreationTime.HighPart = FixedData.CreationTime.HighPart;
1136 InfoBuffer->Modified2.ModifiedCountAtLastPromotion.LowPart = FixedData.ModifiedCountAtLastPromotion.LowPart;
1137 InfoBuffer->Modified2.ModifiedCountAtLastPromotion.HighPart = FixedData.ModifiedCountAtLastPromotion.HighPart;
1138
1139 *Buffer = InfoBuffer;
1140
1141 done:
1142 if (!NT_SUCCESS(Status))
1143 {
1144 if (InfoBuffer != NULL)
1145 {
1146 midl_user_free(InfoBuffer);
1147 }
1148 }
1149
1150 return Status;
1151 }
1152
1153
1154 /* Function 8 */
1155 NTSTATUS
1156 NTAPI
1157 SamrQueryInformationDomain(IN SAMPR_HANDLE DomainHandle,
1158 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1159 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1160 {
1161 PSAM_DB_OBJECT DomainObject;
1162 ACCESS_MASK DesiredAccess;
1163 NTSTATUS Status;
1164
1165 TRACE("SamrQueryInformationDomain(%p %lu %p)\n",
1166 DomainHandle, DomainInformationClass, Buffer);
1167
1168 switch (DomainInformationClass)
1169 {
1170 case DomainPasswordInformation:
1171 case DomainLockoutInformation:
1172 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS;
1173 break;
1174
1175 case DomainGeneralInformation:
1176 case DomainLogoffInformation:
1177 case DomainOemInformation:
1178 case DomainNameInformation:
1179 case DomainReplicationInformation:
1180 case DomainServerRoleInformation:
1181 case DomainModifiedInformation:
1182 case DomainStateInformation:
1183 case DomainModifiedInformation2:
1184 DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS;
1185 break;
1186
1187 case DomainGeneralInformation2:
1188 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS |
1189 DOMAIN_READ_OTHER_PARAMETERS;
1190 break;
1191
1192 default:
1193 return STATUS_INVALID_INFO_CLASS;
1194 }
1195
1196 /* Validate the server handle */
1197 Status = SampValidateDbObject(DomainHandle,
1198 SamDbDomainObject,
1199 DesiredAccess,
1200 &DomainObject);
1201 if (!NT_SUCCESS(Status))
1202 return Status;
1203
1204 switch (DomainInformationClass)
1205 {
1206 case DomainPasswordInformation:
1207 Status = SampQueryDomainPassword(DomainObject,
1208 Buffer);
1209 break;
1210
1211 case DomainGeneralInformation:
1212 Status = SampQueryDomainGeneral(DomainObject,
1213 Buffer);
1214 break;
1215
1216 case DomainLogoffInformation:
1217 Status = SampQueryDomainLogoff(DomainObject,
1218 Buffer);
1219 break;
1220
1221 case DomainOemInformation:
1222 Status = SampQueryDomainOem(DomainObject,
1223 Buffer);
1224 break;
1225
1226 case DomainNameInformation:
1227 Status = SampQueryDomainName(DomainObject,
1228 Buffer);
1229 break;
1230
1231 case DomainReplicationInformation:
1232 Status = SampQueryDomainReplication(DomainObject,
1233 Buffer);
1234 break;
1235
1236 case DomainServerRoleInformation:
1237 Status = SampQueryDomainServerRole(DomainObject,
1238 Buffer);
1239 break;
1240
1241 case DomainModifiedInformation:
1242 Status = SampQueryDomainModified(DomainObject,
1243 Buffer);
1244 break;
1245
1246 case DomainStateInformation:
1247 Status = SampQueryDomainState(DomainObject,
1248 Buffer);
1249 break;
1250
1251 case DomainGeneralInformation2:
1252 Status = SampQueryDomainGeneral2(DomainObject,
1253 Buffer);
1254 break;
1255
1256 case DomainLockoutInformation:
1257 Status = SampQueryDomainLockout(DomainObject,
1258 Buffer);
1259 break;
1260
1261 case DomainModifiedInformation2:
1262 Status = SampQueryDomainModified2(DomainObject,
1263 Buffer);
1264 break;
1265
1266 default:
1267 Status = STATUS_NOT_IMPLEMENTED;
1268 }
1269
1270 return Status;
1271 }
1272
1273
1274 static NTSTATUS
1275 SampSetDomainPassword(PSAM_DB_OBJECT DomainObject,
1276 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1277 {
1278 SAM_DOMAIN_FIXED_DATA FixedData;
1279 ULONG Length = 0;
1280 NTSTATUS Status;
1281
1282 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1283 Status = SampGetObjectAttribute(DomainObject,
1284 L"F",
1285 NULL,
1286 (PVOID)&FixedData,
1287 &Length);
1288 if (!NT_SUCCESS(Status))
1289 goto done;
1290
1291 FixedData.MinPasswordLength = Buffer->Password.MinPasswordLength;
1292 FixedData.PasswordHistoryLength = Buffer->Password.PasswordHistoryLength;
1293 FixedData.PasswordProperties = Buffer->Password.PasswordProperties;
1294 FixedData.MaxPasswordAge.LowPart = Buffer->Password.MaxPasswordAge.LowPart;
1295 FixedData.MaxPasswordAge.HighPart = Buffer->Password.MaxPasswordAge.HighPart;
1296 FixedData.MinPasswordAge.LowPart = Buffer->Password.MinPasswordAge.LowPart;
1297 FixedData.MinPasswordAge.HighPart = Buffer->Password.MinPasswordAge.HighPart;
1298
1299 Status = SampSetObjectAttribute(DomainObject,
1300 L"F",
1301 REG_BINARY,
1302 &FixedData,
1303 Length);
1304
1305 done:
1306 return Status;
1307 }
1308
1309
1310 static NTSTATUS
1311 SampSetDomainLogoff(PSAM_DB_OBJECT DomainObject,
1312 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1313 {
1314 SAM_DOMAIN_FIXED_DATA FixedData;
1315 ULONG Length = 0;
1316 NTSTATUS Status;
1317
1318 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1319 Status = SampGetObjectAttribute(DomainObject,
1320 L"F",
1321 NULL,
1322 (PVOID)&FixedData,
1323 &Length);
1324 if (!NT_SUCCESS(Status))
1325 goto done;
1326
1327 FixedData.ForceLogoff.LowPart = Buffer->Logoff.ForceLogoff.LowPart;
1328 FixedData.ForceLogoff.HighPart = Buffer->Logoff.ForceLogoff.HighPart;
1329
1330 Status = SampSetObjectAttribute(DomainObject,
1331 L"F",
1332 REG_BINARY,
1333 &FixedData,
1334 Length);
1335
1336 done:
1337 return Status;
1338 }
1339
1340
1341 static NTSTATUS
1342 SampSetDomainServerRole(PSAM_DB_OBJECT DomainObject,
1343 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1344 {
1345 SAM_DOMAIN_FIXED_DATA FixedData;
1346 ULONG Length = 0;
1347 NTSTATUS Status;
1348
1349 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1350 Status = SampGetObjectAttribute(DomainObject,
1351 L"F",
1352 NULL,
1353 (PVOID)&FixedData,
1354 &Length);
1355 if (!NT_SUCCESS(Status))
1356 goto done;
1357
1358 FixedData.DomainServerRole = Buffer->Role.DomainServerRole;
1359
1360 Status = SampSetObjectAttribute(DomainObject,
1361 L"F",
1362 REG_BINARY,
1363 &FixedData,
1364 Length);
1365
1366 done:
1367 return Status;
1368 }
1369
1370
1371 static NTSTATUS
1372 SampSetDomainState(PSAM_DB_OBJECT DomainObject,
1373 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1374 {
1375 SAM_DOMAIN_FIXED_DATA FixedData;
1376 ULONG Length = 0;
1377 NTSTATUS Status;
1378
1379 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1380 Status = SampGetObjectAttribute(DomainObject,
1381 L"F",
1382 NULL,
1383 (PVOID)&FixedData,
1384 &Length);
1385 if (!NT_SUCCESS(Status))
1386 goto done;
1387
1388 FixedData.DomainServerState = Buffer->State.DomainServerState;
1389
1390 Status = SampSetObjectAttribute(DomainObject,
1391 L"F",
1392 REG_BINARY,
1393 &FixedData,
1394 Length);
1395
1396 done:
1397 return Status;
1398 }
1399
1400
1401 static NTSTATUS
1402 SampSetDomainLockout(PSAM_DB_OBJECT DomainObject,
1403 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1404 {
1405 SAM_DOMAIN_FIXED_DATA FixedData;
1406 ULONG Length = 0;
1407 NTSTATUS Status;
1408
1409 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1410 Status = SampGetObjectAttribute(DomainObject,
1411 L"F",
1412 NULL,
1413 (PVOID)&FixedData,
1414 &Length);
1415 if (!NT_SUCCESS(Status))
1416 goto done;
1417
1418 FixedData.LockoutDuration = Buffer->Lockout.LockoutDuration;
1419 FixedData.LockoutObservationWindow = Buffer->Lockout.LockoutObservationWindow;
1420 FixedData.LockoutThreshold = Buffer->Lockout.LockoutThreshold;
1421
1422 Status = SampSetObjectAttribute(DomainObject,
1423 L"F",
1424 REG_BINARY,
1425 &FixedData,
1426 Length);
1427
1428 done:
1429 return Status;
1430 }
1431
1432
1433 /* Function 9 */
1434 NTSTATUS
1435 NTAPI
1436 SamrSetInformationDomain(IN SAMPR_HANDLE DomainHandle,
1437 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1438 IN PSAMPR_DOMAIN_INFO_BUFFER DomainInformation)
1439 {
1440 PSAM_DB_OBJECT DomainObject;
1441 ACCESS_MASK DesiredAccess;
1442 NTSTATUS Status;
1443
1444 TRACE("SamrSetInformationDomain(%p %lu %p)\n",
1445 DomainHandle, DomainInformationClass, DomainInformation);
1446
1447 switch (DomainInformationClass)
1448 {
1449 case DomainPasswordInformation:
1450 case DomainLockoutInformation:
1451 DesiredAccess = DOMAIN_WRITE_PASSWORD_PARAMS;
1452 break;
1453
1454 case DomainLogoffInformation:
1455 case DomainOemInformation:
1456 case DomainNameInformation:
1457 DesiredAccess = DOMAIN_WRITE_OTHER_PARAMETERS;
1458 break;
1459
1460 case DomainReplicationInformation:
1461 case DomainServerRoleInformation:
1462 case DomainStateInformation:
1463 DesiredAccess = DOMAIN_ADMINISTER_SERVER;
1464 break;
1465
1466 default:
1467 return STATUS_INVALID_INFO_CLASS;
1468 }
1469
1470 /* Validate the server handle */
1471 Status = SampValidateDbObject(DomainHandle,
1472 SamDbDomainObject,
1473 DesiredAccess,
1474 &DomainObject);
1475 if (!NT_SUCCESS(Status))
1476 return Status;
1477
1478 switch (DomainInformationClass)
1479 {
1480 case DomainPasswordInformation:
1481 Status = SampSetDomainPassword(DomainObject,
1482 DomainInformation);
1483 break;
1484
1485 case DomainLogoffInformation:
1486 Status = SampSetDomainLogoff(DomainObject,
1487 DomainInformation);
1488 break;
1489
1490 case DomainOemInformation:
1491 Status = SampSetObjectAttribute(DomainObject,
1492 L"OemInformation",
1493 REG_SZ,
1494 DomainInformation->Oem.OemInformation.Buffer,
1495 DomainInformation->Oem.OemInformation.Length + sizeof(WCHAR));
1496 break;
1497
1498 case DomainNameInformation:
1499 Status = SampSetObjectAttribute(DomainObject,
1500 L"Name",
1501 REG_SZ,
1502 DomainInformation->Name.DomainName.Buffer,
1503 DomainInformation->Name.DomainName.Length + sizeof(WCHAR));
1504 break;
1505
1506 case DomainReplicationInformation:
1507 Status = SampSetObjectAttribute(DomainObject,
1508 L"ReplicaSourceNodeName",
1509 REG_SZ,
1510 DomainInformation->Replication.ReplicaSourceNodeName.Buffer,
1511 DomainInformation->Replication.ReplicaSourceNodeName.Length + sizeof(WCHAR));
1512 break;
1513
1514 case DomainServerRoleInformation:
1515 Status = SampSetDomainServerRole(DomainObject,
1516 DomainInformation);
1517 break;
1518
1519 case DomainStateInformation:
1520 Status = SampSetDomainState(DomainObject,
1521 DomainInformation);
1522 break;
1523
1524 case DomainLockoutInformation:
1525 Status = SampSetDomainLockout(DomainObject,
1526 DomainInformation);
1527 break;
1528
1529 default:
1530 Status = STATUS_NOT_IMPLEMENTED;
1531 }
1532
1533 return Status;
1534 }
1535
1536 /* Function 10 */
1537 NTSTATUS
1538 NTAPI
1539 SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
1540 IN PRPC_UNICODE_STRING Name,
1541 IN ACCESS_MASK DesiredAccess,
1542 OUT SAMPR_HANDLE *GroupHandle,
1543 OUT unsigned long *RelativeId)
1544 {
1545 UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
1546 SAM_DOMAIN_FIXED_DATA FixedDomainData;
1547 SAM_GROUP_FIXED_DATA FixedGroupData;
1548 PSAM_DB_OBJECT DomainObject;
1549 PSAM_DB_OBJECT GroupObject;
1550 ULONG ulSize;
1551 ULONG ulRid;
1552 WCHAR szRid[9];
1553 NTSTATUS Status;
1554
1555 TRACE("SamrCreateGroupInDomain(%p %p %lx %p %p)\n",
1556 DomainHandle, Name, DesiredAccess, GroupHandle, RelativeId);
1557
1558 /* Validate the domain handle */
1559 Status = SampValidateDbObject(DomainHandle,
1560 SamDbDomainObject,
1561 DOMAIN_CREATE_GROUP,
1562 &DomainObject);
1563 if (!NT_SUCCESS(Status))
1564 {
1565 TRACE("failed with status 0x%08lx\n", Status);
1566 return Status;
1567 }
1568
1569 /* Check if the group name already exists in the domain */
1570 Status = SampCheckAccountNameInDomain(DomainObject,
1571 Name->Buffer);
1572 if (!NT_SUCCESS(Status))
1573 {
1574 TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n",
1575 Name->Buffer, Status);
1576 return Status;
1577 }
1578
1579 /* Get the fixed domain attributes */
1580 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
1581 Status = SampGetObjectAttribute(DomainObject,
1582 L"F",
1583 NULL,
1584 (PVOID)&FixedDomainData,
1585 &ulSize);
1586 if (!NT_SUCCESS(Status))
1587 {
1588 TRACE("failed with status 0x%08lx\n", Status);
1589 return Status;
1590 }
1591
1592 /* Increment the NextRid attribute */
1593 ulRid = FixedDomainData.NextRid;
1594 FixedDomainData.NextRid++;
1595
1596 /* Store the fixed domain attributes */
1597 Status = SampSetObjectAttribute(DomainObject,
1598 L"F",
1599 REG_BINARY,
1600 &FixedDomainData,
1601 ulSize);
1602 if (!NT_SUCCESS(Status))
1603 {
1604 TRACE("failed with status 0x%08lx\n", Status);
1605 return Status;
1606 }
1607
1608 TRACE("RID: %lx\n", ulRid);
1609
1610 /* Convert the RID into a string (hex) */
1611 swprintf(szRid, L"%08lX", ulRid);
1612
1613 /* Create the group object */
1614 Status = SampCreateDbObject(DomainObject,
1615 L"Groups",
1616 szRid,
1617 SamDbGroupObject,
1618 DesiredAccess,
1619 &GroupObject);
1620 if (!NT_SUCCESS(Status))
1621 {
1622 TRACE("failed with status 0x%08lx\n", Status);
1623 return Status;
1624 }
1625
1626 /* Add the account name of the user object */
1627 Status = SampSetAccountNameInDomain(DomainObject,
1628 L"Groups",
1629 Name->Buffer,
1630 ulRid);
1631 if (!NT_SUCCESS(Status))
1632 {
1633 TRACE("failed with status 0x%08lx\n", Status);
1634 return Status;
1635 }
1636
1637 /* Initialize fixed user data */
1638 memset(&FixedGroupData, 0, sizeof(SAM_GROUP_FIXED_DATA));
1639 FixedGroupData.Version = 1;
1640
1641 FixedGroupData.GroupId = ulRid;
1642
1643 /* Set fixed user data attribute */
1644 Status = SampSetObjectAttribute(GroupObject,
1645 L"F",
1646 REG_BINARY,
1647 (LPVOID)&FixedGroupData,
1648 sizeof(SAM_GROUP_FIXED_DATA));
1649 if (!NT_SUCCESS(Status))
1650 {
1651 TRACE("failed with status 0x%08lx\n", Status);
1652 return Status;
1653 }
1654
1655 /* Set the Name attribute */
1656 Status = SampSetObjectAttribute(GroupObject,
1657 L"Name",
1658 REG_SZ,
1659 (LPVOID)Name->Buffer,
1660 Name->MaximumLength);
1661 if (!NT_SUCCESS(Status))
1662 {
1663 TRACE("failed with status 0x%08lx\n", Status);
1664 return Status;
1665 }
1666
1667 /* Set the AdminComment attribute */
1668 Status = SampSetObjectAttribute(GroupObject,
1669 L"AdminComment",
1670 REG_SZ,
1671 EmptyString.Buffer,
1672 EmptyString.MaximumLength);
1673 if (!NT_SUCCESS(Status))
1674 {
1675 TRACE("failed with status 0x%08lx\n", Status);
1676 return Status;
1677 }
1678
1679 if (NT_SUCCESS(Status))
1680 {
1681 *GroupHandle = (SAMPR_HANDLE)GroupObject;
1682 *RelativeId = ulRid;
1683 }
1684
1685 TRACE("returns with status 0x%08lx\n", Status);
1686
1687 return Status;
1688 }
1689
1690
1691 /* Function 11 */
1692 NTSTATUS
1693 NTAPI
1694 SamrEnumerateGroupsInDomain(IN SAMPR_HANDLE DomainHandle,
1695 IN OUT unsigned long *EnumerationContext,
1696 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
1697 IN unsigned long PreferedMaximumLength,
1698 OUT unsigned long *CountReturned)
1699 {
1700 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
1701 PSAM_DB_OBJECT DomainObject;
1702 HANDLE GroupsKeyHandle = NULL;
1703 HANDLE NamesKeyHandle = NULL;
1704 WCHAR GroupName[64];
1705 ULONG EnumIndex;
1706 ULONG EnumCount = 0;
1707 ULONG RequiredLength = 0;
1708 ULONG NameLength;
1709 ULONG DataLength;
1710 ULONG Rid;
1711 ULONG i;
1712 BOOLEAN MoreEntries = FALSE;
1713 NTSTATUS Status;
1714
1715 TRACE("SamrEnumerateUsersInDomain(%p %p %p %lu %p)\n",
1716 DomainHandle, EnumerationContext, Buffer,
1717 PreferedMaximumLength, CountReturned);
1718
1719 /* Validate the domain handle */
1720 Status = SampValidateDbObject(DomainHandle,
1721 SamDbDomainObject,
1722 DOMAIN_LIST_ACCOUNTS,
1723 &DomainObject);
1724 if (!NT_SUCCESS(Status))
1725 return Status;
1726
1727 Status = SampRegOpenKey(DomainObject->KeyHandle,
1728 L"Groups",
1729 KEY_READ,
1730 &GroupsKeyHandle);
1731 if (!NT_SUCCESS(Status))
1732 return Status;
1733
1734 Status = SampRegOpenKey(GroupsKeyHandle,
1735 L"Names",
1736 KEY_READ,
1737 &NamesKeyHandle);
1738 if (!NT_SUCCESS(Status))
1739 goto done;
1740
1741 TRACE("Part 1\n");
1742
1743 EnumIndex = *EnumerationContext;
1744
1745 while (TRUE)
1746 {
1747 NameLength = 64 * sizeof(WCHAR);
1748 Status = SampRegEnumerateValue(NamesKeyHandle,
1749 EnumIndex,
1750 GroupName,
1751 &NameLength,
1752 NULL,
1753 NULL,
1754 NULL);
1755 if (!NT_SUCCESS(Status))
1756 {
1757 if (Status == STATUS_NO_MORE_ENTRIES)
1758 Status = STATUS_SUCCESS;
1759 break;
1760 }
1761
1762 TRACE("EnumIndex: %lu\n", EnumIndex);
1763 TRACE("Group name: %S\n", GroupName);
1764 TRACE("Name length: %lu\n", NameLength);
1765
1766 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
1767 {
1768 MoreEntries = TRUE;
1769 break;
1770 }
1771
1772 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
1773 EnumCount++;
1774
1775 EnumIndex++;
1776 }
1777
1778 TRACE("EnumCount: %lu\n", EnumCount);
1779 TRACE("RequiredLength: %lu\n", RequiredLength);
1780
1781 if (!NT_SUCCESS(Status))
1782 goto done;
1783
1784 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
1785 if (EnumBuffer == NULL)
1786 {
1787 Status = STATUS_INSUFFICIENT_RESOURCES;
1788 goto done;
1789 }
1790
1791 EnumBuffer->EntriesRead = EnumCount;
1792 if (EnumCount == 0)
1793 goto done;
1794
1795 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
1796 if (EnumBuffer->Buffer == NULL)
1797 {
1798 Status = STATUS_INSUFFICIENT_RESOURCES;
1799 goto done;
1800 }
1801
1802 TRACE("Part 2\n");
1803
1804 EnumIndex = *EnumerationContext;
1805 for (i = 0; i < EnumCount; i++, EnumIndex++)
1806 {
1807 NameLength = 64 * sizeof(WCHAR);
1808 DataLength = sizeof(ULONG);
1809 Status = SampRegEnumerateValue(NamesKeyHandle,
1810 EnumIndex,
1811 GroupName,
1812 &NameLength,
1813 NULL,
1814 &Rid,
1815 &DataLength);
1816 if (!NT_SUCCESS(Status))
1817 {
1818 if (Status == STATUS_NO_MORE_ENTRIES)
1819 Status = STATUS_SUCCESS;
1820 break;
1821 }
1822
1823 TRACE("EnumIndex: %lu\n", EnumIndex);
1824 TRACE("Group name: %S\n", GroupName);
1825 TRACE("Name length: %lu\n", NameLength);
1826 TRACE("RID: %lu\n", Rid);
1827
1828 EnumBuffer->Buffer[i].RelativeId = Rid;
1829
1830 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
1831 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(DataLength + sizeof(UNICODE_NULL));
1832
1833 /* FIXME: Disabled because of bugs in widl and rpcrt4 */
1834 #if 0
1835 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
1836 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
1837 {
1838 Status = STATUS_INSUFFICIENT_RESOURCES;
1839 goto done;
1840 }
1841
1842 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
1843 GroupName,
1844 EnumBuffer->Buffer[i].Name.Length);
1845 #endif
1846 }
1847
1848 done:
1849 if (NT_SUCCESS(Status))
1850 {
1851 *EnumerationContext += EnumCount;
1852 *Buffer = EnumBuffer;
1853 *CountReturned = EnumCount;
1854 }
1855 else
1856 {
1857 *EnumerationContext = 0;
1858 *Buffer = NULL;
1859 *CountReturned = 0;
1860
1861 if (EnumBuffer != NULL)
1862 {
1863 if (EnumBuffer->Buffer != NULL)
1864 {
1865 if (EnumBuffer->EntriesRead != 0)
1866 {
1867 for (i = 0; i < EnumBuffer->EntriesRead; i++)
1868 {
1869 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
1870 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
1871 }
1872 }
1873
1874 midl_user_free(EnumBuffer->Buffer);
1875 }
1876
1877 midl_user_free(EnumBuffer);
1878 }
1879 }
1880
1881 if (NamesKeyHandle != NULL)
1882 SampRegCloseKey(NamesKeyHandle);
1883
1884 if (GroupsKeyHandle != NULL)
1885 SampRegCloseKey(GroupsKeyHandle);
1886
1887 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
1888 Status = STATUS_MORE_ENTRIES;
1889
1890 return Status;
1891 }
1892
1893
1894 /* Function 12 */
1895 NTSTATUS
1896 NTAPI
1897 SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
1898 IN PRPC_UNICODE_STRING Name,
1899 IN ACCESS_MASK DesiredAccess,
1900 OUT SAMPR_HANDLE *UserHandle,
1901 OUT unsigned long *RelativeId)
1902 {
1903 UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
1904 SAM_DOMAIN_FIXED_DATA FixedDomainData;
1905 SAM_USER_FIXED_DATA FixedUserData;
1906 PSAM_DB_OBJECT DomainObject;
1907 PSAM_DB_OBJECT UserObject;
1908 ULONG ulSize;
1909 ULONG ulRid;
1910 WCHAR szRid[9];
1911 NTSTATUS Status;
1912
1913 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
1914 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
1915
1916 if (Name == NULL ||
1917 Name->Length == 0 ||
1918 Name->Buffer == NULL ||
1919 UserHandle == NULL ||
1920 RelativeId == NULL)
1921 return STATUS_INVALID_PARAMETER;
1922
1923 /* Validate the domain handle */
1924 Status = SampValidateDbObject(DomainHandle,
1925 SamDbDomainObject,
1926 DOMAIN_CREATE_USER,
1927 &DomainObject);
1928 if (!NT_SUCCESS(Status))
1929 {
1930 TRACE("failed with status 0x%08lx\n", Status);
1931 return Status;
1932 }
1933
1934 /* Check if the user name already exists in the domain */
1935 Status = SampCheckAccountNameInDomain(DomainObject,
1936 Name->Buffer);
1937 if (!NT_SUCCESS(Status))
1938 {
1939 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
1940 Name->Buffer, Status);
1941 return Status;
1942 }
1943
1944 /* Get the fixed domain attributes */
1945 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
1946 Status = SampGetObjectAttribute(DomainObject,
1947 L"F",
1948 NULL,
1949 (PVOID)&FixedDomainData,
1950 &ulSize);
1951 if (!NT_SUCCESS(Status))
1952 {
1953 TRACE("failed with status 0x%08lx\n", Status);
1954 return Status;
1955 }
1956
1957 /* Increment the NextRid attribute */
1958 ulRid = FixedDomainData.NextRid;
1959 FixedDomainData.NextRid++;
1960
1961 /* Store the fixed domain attributes */
1962 Status = SampSetObjectAttribute(DomainObject,
1963 L"F",
1964 REG_BINARY,
1965 &FixedDomainData,
1966 ulSize);
1967 if (!NT_SUCCESS(Status))
1968 {
1969 TRACE("failed with status 0x%08lx\n", Status);
1970 return Status;
1971 }
1972
1973 TRACE("RID: %lx\n", ulRid);
1974
1975 /* Convert the RID into a string (hex) */
1976 swprintf(szRid, L"%08lX", ulRid);
1977
1978 /* Create the user object */
1979 Status = SampCreateDbObject(DomainObject,
1980 L"Users",
1981 szRid,
1982 SamDbUserObject,
1983 DesiredAccess,
1984 &UserObject);
1985 if (!NT_SUCCESS(Status))
1986 {
1987 TRACE("failed with status 0x%08lx\n", Status);
1988 return Status;
1989 }
1990
1991 /* Add the account name for the user object */
1992 Status = SampSetAccountNameInDomain(DomainObject,
1993 L"Users",
1994 Name->Buffer,
1995 ulRid);
1996 if (!NT_SUCCESS(Status))
1997 {
1998 TRACE("failed with status 0x%08lx\n", Status);
1999 return Status;
2000 }
2001
2002 /* Initialize fixed user data */
2003 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
2004 FixedUserData.Version = 1;
2005 FixedUserData.LastLogon.QuadPart = 0;
2006 FixedUserData.LastLogoff.QuadPart = 0;
2007 FixedUserData.PasswordLastSet.QuadPart = 0;
2008 FixedUserData.AccountExpires.LowPart = MAXULONG;
2009 FixedUserData.AccountExpires.HighPart = MAXLONG;
2010 FixedUserData.LastBadPasswordTime.QuadPart = 0;
2011 FixedUserData.UserId = ulRid;
2012 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
2013 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
2014 USER_PASSWORD_NOT_REQUIRED |
2015 USER_NORMAL_ACCOUNT;
2016
2017 /* Set fixed user data attribute */
2018 Status = SampSetObjectAttribute(UserObject,
2019 L"F",
2020 REG_BINARY,
2021 (LPVOID)&FixedUserData,
2022 sizeof(SAM_USER_FIXED_DATA));
2023 if (!NT_SUCCESS(Status))
2024 {
2025 TRACE("failed with status 0x%08lx\n", Status);
2026 return Status;
2027 }
2028
2029 /* Set the Name attribute */
2030 Status = SampSetObjectAttribute(UserObject,
2031 L"Name",
2032 REG_SZ,
2033 (LPVOID)Name->Buffer,
2034 Name->MaximumLength);
2035 if (!NT_SUCCESS(Status))
2036 {
2037 TRACE("failed with status 0x%08lx\n", Status);
2038 return Status;
2039 }
2040
2041 /* Set the FullName attribute */
2042 Status = SampSetObjectAttribute(UserObject,
2043 L"FullName",
2044 REG_SZ,
2045 EmptyString.Buffer,
2046 EmptyString.MaximumLength);
2047 if (!NT_SUCCESS(Status))
2048 {
2049 TRACE("failed with status 0x%08lx\n", Status);
2050 return Status;
2051 }
2052
2053 /* Set the HomeDirectory attribute */
2054 Status = SampSetObjectAttribute(UserObject,
2055 L"HomeDirectory",
2056 REG_SZ,
2057 EmptyString.Buffer,
2058 EmptyString.MaximumLength);
2059 if (!NT_SUCCESS(Status))
2060 {
2061 TRACE("failed with status 0x%08lx\n", Status);
2062 return Status;
2063 }
2064
2065 /* Set the HomeDirectoryDrive attribute */
2066 Status = SampSetObjectAttribute(UserObject,
2067 L"HomeDirectoryDrive",
2068 REG_SZ,
2069 EmptyString.Buffer,
2070 EmptyString.MaximumLength);
2071 if (!NT_SUCCESS(Status))
2072 {
2073 TRACE("failed with status 0x%08lx\n", Status);
2074 return Status;
2075 }
2076
2077 /* Set the ScriptPath attribute */
2078 Status = SampSetObjectAttribute(UserObject,
2079 L"ScriptPath",
2080 REG_SZ,
2081 EmptyString.Buffer,
2082 EmptyString.MaximumLength);
2083 if (!NT_SUCCESS(Status))
2084 {
2085 TRACE("failed with status 0x%08lx\n", Status);
2086 return Status;
2087 }
2088
2089 /* Set the ProfilePath attribute */
2090 Status = SampSetObjectAttribute(UserObject,
2091 L"ProfilePath",
2092 REG_SZ,
2093 EmptyString.Buffer,
2094 EmptyString.MaximumLength);
2095 if (!NT_SUCCESS(Status))
2096 {
2097 TRACE("failed with status 0x%08lx\n", Status);
2098 return Status;
2099 }
2100
2101 /* Set the AdminComment attribute */
2102 Status = SampSetObjectAttribute(UserObject,
2103 L"AdminComment",
2104 REG_SZ,
2105 EmptyString.Buffer,
2106 EmptyString.MaximumLength);
2107 if (!NT_SUCCESS(Status))
2108 {
2109 TRACE("failed with status 0x%08lx\n", Status);
2110 return Status;
2111 }
2112
2113 /* Set the UserComment attribute */
2114 Status = SampSetObjectAttribute(UserObject,
2115 L"UserComment",
2116 REG_SZ,
2117 EmptyString.Buffer,
2118 EmptyString.MaximumLength);
2119 if (!NT_SUCCESS(Status))
2120 {
2121 TRACE("failed with status 0x%08lx\n", Status);
2122 return Status;
2123 }
2124
2125 /* Set the WorkStations attribute */
2126 Status = SampSetObjectAttribute(UserObject,
2127 L"WorkStations",
2128 REG_SZ,
2129 EmptyString.Buffer,
2130 EmptyString.MaximumLength);
2131 if (!NT_SUCCESS(Status))
2132 {
2133 TRACE("failed with status 0x%08lx\n", Status);
2134 return Status;
2135 }
2136
2137 /* FIXME: Set default user attributes */
2138
2139 if (NT_SUCCESS(Status))
2140 {
2141 *UserHandle = (SAMPR_HANDLE)UserObject;
2142 *RelativeId = ulRid;
2143 }
2144
2145 TRACE("returns with status 0x%08lx\n", Status);
2146
2147 return Status;
2148 }
2149
2150
2151 /* Function 13 */
2152 NTSTATUS
2153 NTAPI
2154 SamrEnumerateUsersInDomain(IN SAMPR_HANDLE DomainHandle,
2155 IN OUT unsigned long *EnumerationContext,
2156 IN unsigned long UserAccountControl,
2157 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
2158 IN unsigned long PreferedMaximumLength,
2159 OUT unsigned long *CountReturned)
2160 {
2161 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
2162 PSAM_DB_OBJECT DomainObject;
2163 HANDLE UsersKeyHandle = NULL;
2164 HANDLE NamesKeyHandle = NULL;
2165 WCHAR UserName[64];
2166 ULONG EnumIndex;
2167 ULONG EnumCount = 0;
2168 ULONG RequiredLength = 0;
2169 ULONG NameLength;
2170 ULONG DataLength;
2171 ULONG Rid;
2172 ULONG i;
2173 BOOLEAN MoreEntries = FALSE;
2174 NTSTATUS Status;
2175
2176 TRACE("SamrEnumerateUsersInDomain(%p %p %lx %p %lu %p)\n",
2177 DomainHandle, EnumerationContext, UserAccountControl, Buffer,
2178 PreferedMaximumLength, CountReturned);
2179
2180 /* Validate the domain handle */
2181 Status = SampValidateDbObject(DomainHandle,
2182 SamDbDomainObject,
2183 DOMAIN_LIST_ACCOUNTS,
2184 &DomainObject);
2185 if (!NT_SUCCESS(Status))
2186 return Status;
2187
2188 Status = SampRegOpenKey(DomainObject->KeyHandle,
2189 L"Users",
2190 KEY_READ,
2191 &UsersKeyHandle);
2192 if (!NT_SUCCESS(Status))
2193 return Status;
2194
2195 Status = SampRegOpenKey(UsersKeyHandle,
2196 L"Names",
2197 KEY_READ,
2198 &NamesKeyHandle);
2199 if (!NT_SUCCESS(Status))
2200 goto done;
2201
2202 TRACE("Part 1\n");
2203
2204 EnumIndex = *EnumerationContext;
2205
2206 while (TRUE)
2207 {
2208 NameLength = 64 * sizeof(WCHAR);
2209 Status = SampRegEnumerateValue(NamesKeyHandle,
2210 EnumIndex,
2211 UserName,
2212 &NameLength,
2213 NULL,
2214 NULL,
2215 NULL);
2216 if (!NT_SUCCESS(Status))
2217 {
2218 if (Status == STATUS_NO_MORE_ENTRIES)
2219 Status = STATUS_SUCCESS;
2220 break;
2221 }
2222
2223 TRACE("EnumIndex: %lu\n", EnumIndex);
2224 TRACE("User name: %S\n", UserName);
2225 TRACE("Name length: %lu\n", NameLength);
2226
2227 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
2228 {
2229 MoreEntries = TRUE;
2230 break;
2231 }
2232
2233 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
2234 EnumCount++;
2235
2236 EnumIndex++;
2237 }
2238
2239 TRACE("EnumCount: %lu\n", EnumCount);
2240 TRACE("RequiredLength: %lu\n", RequiredLength);
2241
2242 if (!NT_SUCCESS(Status))
2243 goto done;
2244
2245 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
2246 if (EnumBuffer == NULL)
2247 {
2248 Status = STATUS_INSUFFICIENT_RESOURCES;
2249 goto done;
2250 }
2251
2252 EnumBuffer->EntriesRead = EnumCount;
2253 if (EnumCount == 0)
2254 goto done;
2255
2256 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
2257 if (EnumBuffer->Buffer == NULL)
2258 {
2259 Status = STATUS_INSUFFICIENT_RESOURCES;
2260 goto done;
2261 }
2262
2263 TRACE("Part 2\n");
2264
2265 EnumIndex = *EnumerationContext;
2266 for (i = 0; i < EnumCount; i++, EnumIndex++)
2267 {
2268 NameLength = 64 * sizeof(WCHAR);
2269 DataLength = sizeof(ULONG);
2270 Status = SampRegEnumerateValue(NamesKeyHandle,
2271 EnumIndex,
2272 UserName,
2273 &NameLength,
2274 NULL,
2275 &Rid,
2276 &DataLength);
2277 if (!NT_SUCCESS(Status))
2278 {
2279 if (Status == STATUS_NO_MORE_ENTRIES)
2280 Status = STATUS_SUCCESS;
2281 break;
2282 }
2283
2284 TRACE("EnumIndex: %lu\n", EnumIndex);
2285 TRACE("User name: %S\n", UserName);
2286 TRACE("Name length: %lu\n", NameLength);
2287 TRACE("RID: %lu\n", Rid);
2288
2289 EnumBuffer->Buffer[i].RelativeId = Rid;
2290
2291 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
2292 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(DataLength + sizeof(UNICODE_NULL));
2293
2294 /* FIXME: Disabled because of bugs in widl and rpcrt4 */
2295 #if 0
2296 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
2297 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
2298 {
2299 Status = STATUS_INSUFFICIENT_RESOURCES;
2300 goto done;
2301 }
2302
2303 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
2304 UserName,
2305 EnumBuffer->Buffer[i].Name.Length);
2306 #endif
2307 }
2308
2309 done:
2310 if (NT_SUCCESS(Status))
2311 {
2312 *EnumerationContext += EnumCount;
2313 *Buffer = EnumBuffer;
2314 *CountReturned = EnumCount;
2315 }
2316 else
2317 {
2318 *EnumerationContext = 0;
2319 *Buffer = NULL;
2320 *CountReturned = 0;
2321
2322 if (EnumBuffer != NULL)
2323 {
2324 if (EnumBuffer->Buffer != NULL)
2325 {
2326 if (EnumBuffer->EntriesRead != 0)
2327 {
2328 for (i = 0; i < EnumBuffer->EntriesRead; i++)
2329 {
2330 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
2331 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
2332 }
2333 }
2334
2335 midl_user_free(EnumBuffer->Buffer);
2336 }
2337
2338 midl_user_free(EnumBuffer);
2339 }
2340 }
2341
2342 if (NamesKeyHandle != NULL)
2343 SampRegCloseKey(NamesKeyHandle);
2344
2345 if (UsersKeyHandle != NULL)
2346 SampRegCloseKey(UsersKeyHandle);
2347
2348 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
2349 Status = STATUS_MORE_ENTRIES;
2350
2351 return Status;
2352 }
2353
2354
2355 /* Function 14 */
2356 NTSTATUS
2357 NTAPI
2358 SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
2359 IN PRPC_UNICODE_STRING AccountName,
2360 IN ACCESS_MASK DesiredAccess,
2361 OUT SAMPR_HANDLE *AliasHandle,
2362 OUT unsigned long *RelativeId)
2363 {
2364 SAM_DOMAIN_FIXED_DATA FixedDomainData;
2365 PSAM_DB_OBJECT DomainObject;
2366 PSAM_DB_OBJECT AliasObject;
2367 UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
2368 ULONG ulSize;
2369 ULONG ulRid;
2370 WCHAR szRid[9];
2371 NTSTATUS Status;
2372
2373 TRACE("SamrCreateAliasInDomain(%p %p %lx %p %p)\n",
2374 DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId);
2375
2376 /* Validate the domain handle */
2377 Status = SampValidateDbObject(DomainHandle,
2378 SamDbDomainObject,
2379 DOMAIN_CREATE_ALIAS,
2380 &DomainObject);
2381 if (!NT_SUCCESS(Status))
2382 {
2383 TRACE("failed with status 0x%08lx\n", Status);
2384 return Status;
2385 }
2386
2387 /* Check if the alias name already exists in the domain */
2388 Status = SampCheckAccountNameInDomain(DomainObject,
2389 AccountName->Buffer);
2390 if (!NT_SUCCESS(Status))
2391 {
2392 TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n",
2393 AccountName->Buffer, Status);
2394 return Status;
2395 }
2396
2397 /* Get the fixed domain attributes */
2398 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
2399 Status = SampGetObjectAttribute(DomainObject,
2400 L"F",
2401 NULL,
2402 (PVOID)&FixedDomainData,
2403 &ulSize);
2404 if (!NT_SUCCESS(Status))
2405 {
2406 TRACE("failed with status 0x%08lx\n", Status);
2407 return Status;
2408 }
2409
2410 /* Increment the NextRid attribute */
2411 ulRid = FixedDomainData.NextRid;
2412 FixedDomainData.NextRid++;
2413
2414 /* Store the fixed domain attributes */
2415 Status = SampSetObjectAttribute(DomainObject,
2416 L"F",
2417 REG_BINARY,
2418 &FixedDomainData,
2419 ulSize);
2420 if (!NT_SUCCESS(Status))
2421 {
2422 TRACE("failed with status 0x%08lx\n", Status);
2423 return Status;
2424 }
2425
2426 TRACE("RID: %lx\n", ulRid);
2427
2428 /* Convert the RID into a string (hex) */
2429 swprintf(szRid, L"%08lX", ulRid);
2430
2431 /* Create the alias object */
2432 Status = SampCreateDbObject(DomainObject,
2433 L"Aliases",
2434 szRid,
2435 SamDbAliasObject,
2436 DesiredAccess,
2437 &AliasObject);
2438 if (!NT_SUCCESS(Status))
2439 {
2440 TRACE("failed with status 0x%08lx\n", Status);
2441 return Status;
2442 }
2443
2444 /* Add the account name for the alias object */
2445 Status = SampSetAccountNameInDomain(DomainObject,
2446 L"Aliases",
2447 AccountName->Buffer,
2448 ulRid);
2449 if (!NT_SUCCESS(Status))
2450 {
2451 TRACE("failed with status 0x%08lx\n", Status);
2452 return Status;
2453 }
2454
2455 /* Set the Name attribute */
2456 Status = SampSetObjectAttribute(AliasObject,
2457 L"Name",
2458 REG_SZ,
2459 (LPVOID)AccountName->Buffer,
2460 AccountName->MaximumLength);
2461 if (!NT_SUCCESS(Status))
2462 {
2463 TRACE("failed with status 0x%08lx\n", Status);
2464 return Status;
2465 }
2466
2467 /* Set the Description attribute */
2468 Status = SampSetObjectAttribute(AliasObject,
2469 L"Description",
2470 REG_SZ,
2471 EmptyString.Buffer,
2472 EmptyString.MaximumLength);
2473 if (!NT_SUCCESS(Status))
2474 {
2475 TRACE("failed with status 0x%08lx\n", Status);
2476 return Status;
2477 }
2478
2479 if (NT_SUCCESS(Status))
2480 {
2481 *AliasHandle = (SAMPR_HANDLE)AliasObject;
2482 *RelativeId = ulRid;
2483 }
2484
2485 TRACE("returns with status 0x%08lx\n", Status);
2486
2487 return Status;
2488 }
2489
2490
2491 /* Function 15 */
2492 NTSTATUS
2493 NTAPI
2494 SamrEnumerateAliasesInDomain(IN SAMPR_HANDLE DomainHandle,
2495 IN OUT unsigned long *EnumerationContext,
2496 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
2497 IN unsigned long PreferedMaximumLength,
2498 OUT unsigned long *CountReturned)
2499 {
2500 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
2501 PSAM_DB_OBJECT DomainObject;
2502 HANDLE AliasesKeyHandle = NULL;
2503 HANDLE NamesKeyHandle = NULL;
2504 WCHAR AliasName[64];
2505 ULONG EnumIndex;
2506 ULONG EnumCount = 0;
2507 ULONG RequiredLength = 0;
2508 ULONG NameLength;
2509 ULONG DataLength;
2510 ULONG Rid;
2511 ULONG i;
2512 BOOLEAN MoreEntries = FALSE;
2513 NTSTATUS Status;
2514
2515 TRACE("SamrEnumerateAliasesInDomain(%p %p %p %lu %p)\n",
2516 DomainHandle, EnumerationContext, Buffer,
2517 PreferedMaximumLength, CountReturned);
2518
2519 /* Validate the domain handle */
2520 Status = SampValidateDbObject(DomainHandle,
2521 SamDbDomainObject,
2522 DOMAIN_LIST_ACCOUNTS,
2523 &DomainObject);
2524 if (!NT_SUCCESS(Status))
2525 return Status;
2526
2527 Status = SampRegOpenKey(DomainObject->KeyHandle,
2528 L"Aliases",
2529 KEY_READ,
2530 &AliasesKeyHandle);
2531 if (!NT_SUCCESS(Status))
2532 return Status;
2533
2534 Status = SampRegOpenKey(AliasesKeyHandle,
2535 L"Names",
2536 KEY_READ,
2537 &NamesKeyHandle);
2538 if (!NT_SUCCESS(Status))
2539 goto done;
2540
2541 TRACE("Part 1\n");
2542
2543 EnumIndex = *EnumerationContext;
2544
2545 while (TRUE)
2546 {
2547 NameLength = 64 * sizeof(WCHAR);
2548 Status = SampRegEnumerateValue(NamesKeyHandle,
2549 EnumIndex,
2550 AliasName,
2551 &NameLength,
2552 NULL,
2553 NULL,
2554 NULL);
2555 if (!NT_SUCCESS(Status))
2556 {
2557 if (Status == STATUS_NO_MORE_ENTRIES)
2558 Status = STATUS_SUCCESS;
2559 break;
2560 }
2561
2562 TRACE("EnumIndex: %lu\n", EnumIndex);
2563 TRACE("Alias name: %S\n", AliasName);
2564 TRACE("Name length: %lu\n", NameLength);
2565
2566 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
2567 {
2568 MoreEntries = TRUE;
2569 break;
2570 }
2571
2572 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION));
2573 EnumCount++;
2574
2575 EnumIndex++;
2576 }
2577
2578 TRACE("EnumCount: %lu\n", EnumCount);
2579 TRACE("RequiredLength: %lu\n", RequiredLength);
2580
2581 if (!NT_SUCCESS(Status))
2582 goto done;
2583
2584 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
2585 if (EnumBuffer == NULL)
2586 {
2587 Status = STATUS_INSUFFICIENT_RESOURCES;
2588 goto done;
2589 }
2590
2591 EnumBuffer->EntriesRead = EnumCount;
2592 if (EnumCount == 0)
2593 goto done;
2594
2595 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
2596 if (EnumBuffer->Buffer == NULL)
2597 {
2598 Status = STATUS_INSUFFICIENT_RESOURCES;
2599 goto done;
2600 }
2601
2602 TRACE("Part 2\n");
2603
2604 EnumIndex = *EnumerationContext;
2605 for (i = 0; i < EnumCount; i++, EnumIndex++)
2606 {
2607 NameLength = 64 * sizeof(WCHAR);
2608 DataLength = sizeof(ULONG);
2609 Status = SampRegEnumerateValue(NamesKeyHandle,
2610 EnumIndex,
2611 AliasName,
2612 &NameLength,
2613 NULL,
2614 &Rid,
2615 &DataLength);
2616 if (!NT_SUCCESS(Status))
2617 {
2618 if (Status == STATUS_NO_MORE_ENTRIES)
2619 Status = STATUS_SUCCESS;
2620 break;
2621 }
2622
2623 TRACE("EnumIndex: %lu\n", EnumIndex);
2624 TRACE("Alias name: %S\n", AliasName);
2625 TRACE("Name length: %lu\n", NameLength);
2626 TRACE("RID: %lu\n", Rid);
2627
2628 EnumBuffer->Buffer[i].RelativeId = Rid;
2629
2630 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength;
2631 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(DataLength + sizeof(UNICODE_NULL));
2632
2633 /* FIXME: Disabled because of bugs in widl and rpcrt4 */
2634 #if 0
2635 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength);
2636 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
2637 {
2638 Status = STATUS_INSUFFICIENT_RESOURCES;
2639 goto done;
2640 }
2641
2642 memcpy(EnumBuffer->Buffer[i].Name.Buffer,
2643 AliasName,
2644 EnumBuffer->Buffer[i].Name.Length);
2645 #endif
2646 }
2647
2648 done:
2649 if (NT_SUCCESS(Status))
2650 {
2651 *EnumerationContext += EnumCount;
2652 *Buffer = EnumBuffer;
2653 *CountReturned = EnumCount;
2654 }
2655 else
2656 {
2657 *EnumerationContext = 0;
2658 *Buffer = NULL;
2659 *CountReturned = 0;
2660
2661 if (EnumBuffer != NULL)
2662 {
2663 if (EnumBuffer->Buffer != NULL)
2664 {
2665 if (EnumBuffer->EntriesRead != 0)
2666 {
2667 for (i = 0; i < EnumBuffer->EntriesRead; i++)
2668 {
2669 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
2670 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
2671 }
2672 }
2673
2674 midl_user_free(EnumBuffer->Buffer);
2675 }
2676
2677 midl_user_free(EnumBuffer);
2678 }
2679 }
2680
2681 if (NamesKeyHandle != NULL)
2682 SampRegCloseKey(NamesKeyHandle);
2683
2684 if (AliasesKeyHandle != NULL)
2685 SampRegCloseKey(AliasesKeyHandle);
2686
2687 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
2688 Status = STATUS_MORE_ENTRIES;
2689
2690 return Status;
2691 }
2692
2693
2694 /* Function 16 */
2695 NTSTATUS
2696 NTAPI
2697 SamrGetAliasMembership(IN SAMPR_HANDLE DomainHandle,
2698 IN PSAMPR_PSID_ARRAY SidArray,
2699 OUT PSAMPR_ULONG_ARRAY Membership)
2700 {
2701 PSAM_DB_OBJECT DomainObject;
2702 HANDLE AliasesKeyHandle = NULL;
2703 HANDLE MembersKeyHandle = NULL;
2704 HANDLE MemberKeyHandle = NULL;
2705 LPWSTR MemberSidString = NULL;
2706 PULONG RidArray = NULL;
2707 ULONG MaxSidCount = 0;
2708 ULONG ValueCount;
2709 ULONG DataLength;
2710 ULONG i, j;
2711 NTSTATUS Status;
2712
2713 TRACE("SamrGetAliasMembership(%p %p %p)\n",
2714 DomainHandle, SidArray, Membership);
2715
2716 /* Validate the domain handle */
2717 Status = SampValidateDbObject(DomainHandle,
2718 SamDbDomainObject,
2719 DOMAIN_LOOKUP,
2720 &DomainObject);
2721 if (!NT_SUCCESS(Status))
2722 return Status;
2723
2724 Status = SampRegOpenKey(DomainObject->KeyHandle,
2725 L"Aliases",
2726 KEY_READ,
2727 &AliasesKeyHandle);
2728 TRACE("SampRegOpenKey returned %08lX\n", Status);
2729 if (!NT_SUCCESS(Status))
2730 goto done;
2731
2732 Status = SampRegOpenKey(AliasesKeyHandle,
2733 L"Members",
2734 KEY_READ,
2735 &MembersKeyHandle);
2736 TRACE("SampRegOpenKey returned %08lX\n", Status);
2737 if (!NT_SUCCESS(Status))
2738 goto done;
2739
2740 for (i = 0; i < SidArray->Count; i++)
2741 {
2742 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
2743 TRACE("Open %S\n", MemberSidString);
2744
2745 Status = SampRegOpenKey(MembersKeyHandle,
2746 MemberSidString,
2747 KEY_READ,
2748 &MemberKeyHandle);
2749 TRACE("SampRegOpenKey returned %08lX\n", Status);
2750 if (NT_SUCCESS(Status))
2751 {
2752 Status = SampRegQueryKeyInfo(MemberKeyHandle,
2753 NULL,
2754 &ValueCount);
2755 if (NT_SUCCESS(Status))
2756 {
2757 TRACE("Found %lu values\n", ValueCount);
2758 MaxSidCount += ValueCount;
2759 }
2760
2761
2762 NtClose(MemberKeyHandle);
2763 }
2764
2765 LocalFree(MemberSidString);
2766 }
2767
2768 TRACE("Maximum sid count: %lu\n", MaxSidCount);
2769 RidArray = midl_user_allocate(MaxSidCount * sizeof(ULONG));
2770 if (RidArray == NULL)
2771 {
2772 Status = STATUS_INSUFFICIENT_RESOURCES;
2773 goto done;
2774 }
2775
2776 for (i = 0; i < SidArray->Count; i++)
2777 {
2778 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
2779 TRACE("Open %S\n", MemberSidString);
2780
2781 Status = SampRegOpenKey(MembersKeyHandle,
2782 MemberSidString,
2783 KEY_READ,
2784 &MemberKeyHandle);
2785 TRACE("SampRegOpenKey returned %08lX\n", Status);
2786 if (NT_SUCCESS(Status))
2787 {
2788 Status = SampRegQueryKeyInfo(MemberKeyHandle,
2789 NULL,
2790 &ValueCount);
2791 if (NT_SUCCESS(Status))
2792 {
2793 TRACE("Found %lu values\n", ValueCount);
2794
2795 for (j = 0; j < ValueCount; j++)
2796 {
2797 DataLength = sizeof(ULONG);
2798 Status = SampRegEnumerateValue(MemberKeyHandle,
2799 j,
2800 NULL,
2801 NULL,
2802 NULL,
2803 (PVOID)&RidArray[j],
2804 &DataLength);
2805 }
2806 }
2807
2808 NtClose(MemberKeyHandle);
2809 }
2810
2811 LocalFree(MemberSidString);
2812 }
2813
2814
2815 done:
2816 if (NT_SUCCESS(Status))
2817 {
2818 Membership->Count = MaxSidCount;
2819 Membership->Element = RidArray;
2820 }
2821 else
2822 {
2823 if (RidArray != NULL)
2824 midl_user_free(RidArray);
2825 }
2826
2827 if (MembersKeyHandle != NULL)
2828 NtClose(MembersKeyHandle);
2829
2830 if (MembersKeyHandle != NULL)
2831 NtClose(MembersKeyHandle);
2832
2833 if (AliasesKeyHandle != NULL)
2834 NtClose(AliasesKeyHandle);
2835
2836 return Status;
2837 }
2838
2839
2840 /* Function 17 */
2841 NTSTATUS
2842 NTAPI
2843 SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
2844 IN ULONG Count,
2845 IN RPC_UNICODE_STRING Names[],
2846 OUT PSAMPR_ULONG_ARRAY RelativeIds,
2847 OUT PSAMPR_ULONG_ARRAY Use)
2848 {
2849 PSAM_DB_OBJECT DomainObject;
2850 HANDLE AccountsKeyHandle;
2851 HANDLE NamesKeyHandle;
2852 ULONG MappedCount = 0;
2853 ULONG DataLength;
2854 ULONG i;
2855 ULONG RelativeId;
2856 NTSTATUS Status;
2857
2858 TRACE("SamrLookupNamesInDomain(%p %lu %p %p %p)\n",
2859 DomainHandle, Count, Names, RelativeIds, Use);
2860
2861 /* Validate the domain handle */
2862 Status = SampValidateDbObject(DomainHandle,
2863 SamDbDomainObject,
2864 DOMAIN_LOOKUP,
2865 &DomainObject);
2866 if (!NT_SUCCESS(Status))
2867 {
2868 TRACE("failed with status 0x%08lx\n", Status);
2869 return Status;
2870 }
2871
2872 RelativeIds->Count = 0;
2873 Use->Count = 0;
2874
2875 if (Count == 0)
2876 return STATUS_SUCCESS;
2877
2878 /* Allocate the relative IDs array */
2879 RelativeIds->Element = midl_user_allocate(Count * sizeof(ULONG));
2880 if (RelativeIds->Element == NULL)
2881 {
2882 Status = STATUS_INSUFFICIENT_RESOURCES;
2883 goto done;
2884 }
2885
2886 /* Allocate the use array */
2887 Use->Element = midl_user_allocate(Count * sizeof(ULONG));
2888 if (Use->Element == NULL)
2889 {
2890 Status = STATUS_INSUFFICIENT_RESOURCES;
2891 goto done;
2892 }
2893
2894 RelativeIds->Count = Count;
2895 Use->Count = Count;
2896
2897 for (i = 0; i < Count; i++)
2898 {
2899 TRACE("Name: %S\n", Names[i].Buffer);
2900
2901 RelativeId = 0;
2902
2903 /* Lookup aliases */
2904 Status = SampRegOpenKey(DomainObject->KeyHandle,
2905 L"Aliases",
2906 KEY_READ,
2907 &AccountsKeyHandle);
2908 if (NT_SUCCESS(Status))
2909 {
2910 Status = SampRegOpenKey(AccountsKeyHandle,
2911 L"Names",
2912 KEY_READ,
2913 &NamesKeyHandle);
2914 if (NT_SUCCESS(Status))
2915 {
2916 DataLength = sizeof(ULONG);
2917 Status = SampRegQueryValue(NamesKeyHandle,
2918 Names[i].Buffer,
2919 NULL,
2920 &RelativeId,
2921 &DataLength);
2922
2923 SampRegCloseKey(NamesKeyHandle);
2924 }
2925
2926 SampRegCloseKey(AccountsKeyHandle);
2927 }
2928
2929 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
2930 break;
2931
2932 /* Return alias account */
2933 if (NT_SUCCESS(Status) && RelativeId != 0)
2934 {
2935 TRACE("Rid: %lu\n", RelativeId);
2936 RelativeIds->Element[i] = RelativeId;
2937 Use->Element[i] = SidTypeAlias;
2938 MappedCount++;
2939 continue;
2940 }
2941
2942 /* Lookup groups */
2943 Status = SampRegOpenKey(DomainObject->KeyHandle,
2944 L"Groups",
2945 KEY_READ,
2946 &AccountsKeyHandle);
2947 if (NT_SUCCESS(Status))
2948 {
2949 Status = SampRegOpenKey(AccountsKeyHandle,
2950 L"Names",
2951 KEY_READ,
2952 &NamesKeyHandle);
2953 if (NT_SUCCESS(Status))
2954 {
2955 DataLength = sizeof(ULONG);
2956 Status = SampRegQueryValue(NamesKeyHandle,
2957 Names[i].Buffer,
2958 NULL,
2959 &RelativeId,
2960 &DataLength);
2961
2962 SampRegCloseKey(NamesKeyHandle);
2963 }
2964
2965 SampRegCloseKey(AccountsKeyHandle);
2966 }
2967
2968 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
2969 break;
2970
2971 /* Return group account */
2972 if (NT_SUCCESS(Status) && RelativeId != 0)
2973 {
2974 TRACE("Rid: %lu\n", RelativeId);
2975 RelativeIds->Element[i] = RelativeId;
2976 Use->Element[i] = SidTypeGroup;
2977 MappedCount++;
2978 continue;
2979 }
2980
2981 /* Lookup users */
2982 Status = SampRegOpenKey(DomainObject->KeyHandle,
2983 L"Users",
2984 KEY_READ,
2985 &AccountsKeyHandle);
2986 if (NT_SUCCESS(Status))
2987 {
2988 Status = SampRegOpenKey(AccountsKeyHandle,
2989 L"Names",
2990 KEY_READ,
2991 &NamesKeyHandle);
2992 if (NT_SUCCESS(Status))
2993 {
2994 DataLength = sizeof(ULONG);
2995 Status = SampRegQueryValue(NamesKeyHandle,
2996 Names[i].Buffer,
2997 NULL,
2998 &RelativeId,
2999 &DataLength);
3000
3001 SampRegCloseKey(NamesKeyHandle);
3002 }
3003
3004 SampRegCloseKey(AccountsKeyHandle);
3005 }
3006
3007 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3008 break;
3009
3010 /* Return user account */
3011 if (NT_SUCCESS(Status) && RelativeId != 0)
3012 {
3013 TRACE("Rid: %lu\n", RelativeId);
3014 RelativeIds->Element[i] = RelativeId;
3015 Use->Element[i] = SidTypeUser;
3016 MappedCount++;
3017 continue;
3018 }
3019
3020 /* Return unknown account */
3021 RelativeIds->Element[i] = 0;
3022 Use->Element[i] = SidTypeUnknown;
3023 }
3024
3025 done:
3026 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
3027 Status = STATUS_SUCCESS;
3028
3029 if (NT_SUCCESS(Status))
3030 {
3031 if (MappedCount == 0)
3032 Status = STATUS_NONE_MAPPED;
3033 else if (MappedCount < Count)
3034 Status = STATUS_SOME_NOT_MAPPED;
3035 }
3036 else
3037 {
3038 if (RelativeIds->Element != NULL)
3039 {
3040 midl_user_free(RelativeIds->Element);
3041 RelativeIds->Element = NULL;
3042 }
3043
3044 RelativeIds->Count = 0;
3045
3046 if (Use->Element != NULL)
3047 {
3048 midl_user_free(Use->Element);
3049 Use->Element = NULL;
3050 }
3051
3052 Use->Count = 0;
3053 }
3054
3055 TRACE("Returned Status %lx\n", Status);
3056
3057 return Status;
3058 }
3059
3060
3061 /* Function 18 */
3062 NTSTATUS
3063 NTAPI
3064 SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
3065 IN ULONG Count,
3066 IN ULONG *RelativeIds,
3067 OUT PSAMPR_RETURNED_USTRING_ARRAY Names,
3068 OUT PSAMPR_ULONG_ARRAY Use)
3069 {
3070 PSAM_DB_OBJECT DomainObject;
3071 WCHAR RidString[9];
3072 HANDLE AccountsKeyHandle;
3073 HANDLE AccountKeyHandle;
3074 ULONG MappedCount = 0;
3075 ULONG DataLength;
3076 ULONG i;
3077 NTSTATUS Status;
3078
3079 TRACE("SamrLookupIdsInDomain(%p %lu %p %p %p)\n",
3080 DomainHandle, Count, RelativeIds, Names, Use);
3081
3082 /* Validate the domain handle */
3083 Status = SampValidateDbObject(DomainHandle,
3084 SamDbDomainObject,
3085 DOMAIN_LOOKUP,
3086 &DomainObject);
3087 if (!NT_SUCCESS(Status))
3088 {
3089 TRACE("failed with status 0x%08lx\n", Status);
3090 return Status;
3091 }
3092
3093 Names->Count = 0;
3094 Use->Count = 0;
3095
3096 if (Count == 0)
3097 return STATUS_SUCCESS;
3098
3099 /* Allocate the names array */
3100 Names->Element = midl_user_allocate(Count * sizeof(ULONG));
3101 if (Names->Element == NULL)
3102 {
3103 Status = STATUS_INSUFFICIENT_RESOURCES;
3104 goto done;
3105 }
3106
3107 /* Allocate the use array */
3108 Use->Element = midl_user_allocate(Count * sizeof(ULONG));
3109 if (Use->Element == NULL)
3110 {
3111 Status = STATUS_INSUFFICIENT_RESOURCES;
3112 goto done;
3113 }
3114
3115 Names->Count = Count;
3116 Use->Count = Count;
3117
3118 for (i = 0; i < Count; i++)
3119 {
3120 TRACE("RID: %lu\n", RelativeIds[i]);
3121
3122 swprintf(RidString, L"%08lx", RelativeIds[i]);
3123
3124 /* Lookup aliases */
3125 Status = SampRegOpenKey(DomainObject->KeyHandle,
3126 L"Aliases",
3127 KEY_READ,
3128 &AccountsKeyHandle);
3129 if (NT_SUCCESS(Status))
3130 {
3131 Status = SampRegOpenKey(AccountsKeyHandle,
3132 RidString,
3133 KEY_READ,
3134 &AccountKeyHandle);
3135 if (NT_SUCCESS(Status))
3136 {
3137 DataLength = 0;
3138 Status = SampRegQueryValue(AccountKeyHandle,
3139 L"Name",
3140 NULL,
3141 NULL,
3142 &DataLength);
3143 if (NT_SUCCESS(Status))
3144 {
3145 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3146 if (Names->Element[i].Buffer == NULL)
3147 Status = STATUS_INSUFFICIENT_RESOURCES;
3148
3149 if (NT_SUCCESS(Status))
3150 {
3151 Names->Element[i].MaximumLength = (USHORT)DataLength;
3152 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3153
3154 Status = SampRegQueryValue(AccountKeyHandle,
3155 L"Name",
3156 NULL,
3157 Names->Element[i].Buffer,
3158 &DataLength);
3159 }
3160 }
3161
3162 SampRegCloseKey(AccountKeyHandle);
3163 }
3164
3165 SampRegCloseKey(AccountsKeyHandle);
3166 }
3167
3168 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3169 break;
3170
3171 /* Return alias account */
3172 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3173 {
3174 TRACE("Name: %S\n", Names->Element[i].Buffer);
3175 Use->Element[i] = SidTypeAlias;
3176 MappedCount++;
3177 continue;
3178 }
3179
3180 /* Lookup groups */
3181 Status = SampRegOpenKey(DomainObject->KeyHandle,
3182 L"Groups",
3183 KEY_READ,
3184 &AccountsKeyHandle);
3185 if (NT_SUCCESS(Status))
3186 {
3187 Status = SampRegOpenKey(AccountsKeyHandle,
3188 RidString,
3189 KEY_READ,
3190 &AccountKeyHandle);
3191 if (NT_SUCCESS(Status))
3192 {
3193 DataLength = 0;
3194 Status = SampRegQueryValue(AccountKeyHandle,
3195 L"Name",
3196 NULL,
3197 NULL,
3198 &DataLength);
3199 if (NT_SUCCESS(Status))
3200 {
3201 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3202 if (Names->Element[i].Buffer == NULL)
3203 Status = STATUS_INSUFFICIENT_RESOURCES;
3204
3205 if (NT_SUCCESS(Status))
3206 {
3207 Names->Element[i].MaximumLength = (USHORT)DataLength;
3208 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3209
3210 Status = SampRegQueryValue(AccountKeyHandle,
3211 L"Name",
3212 NULL,
3213 Names->Element[i].Buffer,
3214 &DataLength);
3215 }
3216 }
3217
3218 SampRegCloseKey(AccountKeyHandle);
3219 }
3220
3221 SampRegCloseKey(AccountsKeyHandle);
3222 }
3223
3224 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3225 break;
3226
3227 /* Return group account */
3228 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3229 {
3230 TRACE("Name: %S\n", Names->Element[i].Buffer);
3231 Use->Element[i] = SidTypeGroup;
3232 MappedCount++;
3233 continue;
3234 }
3235
3236 /* Lookup users */
3237 Status = SampRegOpenKey(DomainObject->KeyHandle,
3238 L"Users",
3239 KEY_READ,
3240 &AccountsKeyHandle);
3241 if (NT_SUCCESS(Status))
3242 {
3243 Status = SampRegOpenKey(AccountsKeyHandle,
3244 RidString,
3245 KEY_READ,
3246 &AccountKeyHandle);
3247 if (NT_SUCCESS(Status))
3248 {
3249 DataLength = 0;
3250 Status = SampRegQueryValue(AccountKeyHandle,
3251 L"Name",
3252 NULL,
3253 NULL,
3254 &DataLength);
3255 if (NT_SUCCESS(Status))
3256 {
3257 TRACE("DataLength: %lu\n", DataLength);
3258
3259 Names->Element[i].Buffer = midl_user_allocate(DataLength);
3260 if (Names->Element[i].Buffer == NULL)
3261 Status = STATUS_INSUFFICIENT_RESOURCES;
3262
3263 if (NT_SUCCESS(Status))
3264 {
3265 Names->Element[i].MaximumLength = (USHORT)DataLength;
3266 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR));
3267
3268 Status = SampRegQueryValue(AccountKeyHandle,
3269 L"Name",
3270 NULL,
3271 Names->Element[i].Buffer,
3272 &DataLength);
3273 }
3274 }
3275
3276 SampRegCloseKey(AccountKeyHandle);
3277 }
3278
3279 SampRegCloseKey(AccountsKeyHandle);
3280 }
3281
3282 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
3283 break;
3284
3285 /* Return user account */
3286 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL)
3287 {
3288 TRACE("Name: %S\n", Names->Element[i].Buffer);
3289 Use->Element[i] = SidTypeUser;
3290 MappedCount++;
3291 continue;
3292 }
3293
3294 /* Return unknown account */
3295 Use->Element[i] = SidTypeUnknown;
3296 }
3297
3298 done:
3299 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
3300 Status = STATUS_SUCCESS;
3301
3302 if (NT_SUCCESS(Status))
3303 {
3304 if (MappedCount == 0)
3305 Status = STATUS_NONE_MAPPED;
3306 else if (MappedCount < Count)
3307 Status = STATUS_SOME_NOT_MAPPED;
3308 }
3309 else
3310 {
3311 if (Names->Element != NULL)
3312 {
3313 for (i = 0; i < Count; i++)
3314 {
3315 if (Names->Element[i].Buffer != NULL)
3316 midl_user_free(Names->Element[i].Buffer);
3317 }
3318
3319 midl_user_free(Names->Element);
3320 Names->Element = NULL;
3321 }
3322
3323 Names->Count = 0;
3324
3325 if (Use->Element != NULL)
3326 {
3327 midl_user_free(Use->Element);
3328 Use->Element = NULL;
3329 }
3330
3331 Use->Count = 0;
3332 }
3333
3334 return Status;
3335 }
3336
3337
3338 /* Function 19 */
3339 NTSTATUS
3340 NTAPI
3341 SamrOpenGroup(IN SAMPR_HANDLE DomainHandle,
3342 IN ACCESS_MASK DesiredAccess,
3343 IN unsigned long GroupId,
3344 OUT SAMPR_HANDLE *GroupHandle)
3345 {
3346 PSAM_DB_OBJECT DomainObject;
3347 PSAM_DB_OBJECT GroupObject;
3348 WCHAR szRid[9];
3349 NTSTATUS Status;
3350
3351 TRACE("SamrOpenGroup(%p %lx %lx %p)\n",
3352 DomainHandle, DesiredAccess, GroupId, GroupHandle);
3353
3354 /* Validate the domain handle */
3355 Status = SampValidateDbObject(DomainHandle,
3356 SamDbDomainObject,
3357 DOMAIN_LOOKUP,
3358 &DomainObject);
3359 if (!NT_SUCCESS(Status))
3360 {
3361 TRACE("failed with status 0x%08lx\n", Status);
3362 return Status;
3363 }
3364
3365 /* Convert the RID into a string (hex) */
3366 swprintf(szRid, L"%08lX", GroupId);
3367
3368 /* Create the group object */
3369 Status = SampOpenDbObject(DomainObject,
3370 L"Groups",
3371 szRid,
3372 SamDbGroupObject,
3373 DesiredAccess,
3374 &GroupObject);
3375 if (!NT_SUCCESS(Status))
3376 {
3377 TRACE("failed with status 0x%08lx\n", Status);
3378 return Status;
3379 }
3380
3381 *GroupHandle = (SAMPR_HANDLE)GroupObject;
3382
3383 return STATUS_SUCCESS;
3384 }
3385
3386
3387 static NTSTATUS
3388 SampQueryGroupGeneral(PSAM_DB_OBJECT GroupObject,
3389 PSAMPR_GROUP_INFO_BUFFER *Buffer)
3390 {
3391 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
3392 HANDLE MembersKeyHandle = NULL;
3393 SAM_GROUP_FIXED_DATA FixedData;
3394 ULONG Length = 0;
3395 NTSTATUS Status;
3396
3397 *Buffer = NULL;
3398
3399 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
3400 if (InfoBuffer == NULL)
3401 return STATUS_INSUFFICIENT_RESOURCES;
3402
3403 Status = SampGetObjectAttributeString(GroupObject,
3404 L"Name",
3405 &InfoBuffer->General.Name);
3406 if (!NT_SUCCESS(Status))
3407 {
3408 TRACE("Status 0x%08lx\n", Status);
3409 goto done;
3410 }
3411
3412 Status = SampGetObjectAttributeString(GroupObject,
3413 L"Description",
3414 &InfoBuffer->General.AdminComment);
3415 if (!NT_SUCCESS(Status))
3416 {
3417 TRACE("Status 0x%08lx\n", Status);
3418 goto done;
3419 }
3420
3421 Length = sizeof(SAM_GROUP_FIXED_DATA);
3422 Status = SampGetObjectAttribute(GroupObject,
3423 L"F",
3424 NULL,
3425 (PVOID)&FixedData,
3426 &Length);
3427 if (!NT_SUCCESS(Status))
3428 goto done;
3429
3430 InfoBuffer->General.Attributes = FixedData.Attributes;
3431
3432 /* Open the Members subkey */
3433 Status = SampRegOpenKey(GroupObject->KeyHandle,
3434 L"Members",
3435 KEY_READ,
3436 &MembersKeyHandle);
3437 if (!NT_SUCCESS(Status))
3438 {
3439 TRACE("Status 0x%08lx\n", Status);
3440 goto done;
3441 }
3442
3443 /* Retrieve the number of members of the alias */
3444 Status = SampRegQueryKeyInfo(MembersKeyHandle,
3445 NULL,
3446 &InfoBuffer->General.MemberCount);
3447 if (!NT_SUCCESS(Status))
3448 {
3449 TRACE("Status 0x%08lx\n", Status);
3450 goto done;
3451 }
3452
3453 *Buffer = InfoBuffer;
3454
3455 done:
3456 if (MembersKeyHandle != NULL)
3457 SampRegCloseKey(MembersKeyHandle);
3458
3459 if (!NT_SUCCESS(Status))
3460 {
3461 if (InfoBuffer != NULL)
3462 {
3463 if (InfoBuffer->General.Name.Buffer != NULL)
3464 midl_user_free(InfoBuffer->General.Name.Buffer);
3465
3466 if (InfoBuffer->General.AdminComment.Buffer != NULL)
3467 midl_user_free(InfoBuffer->General.AdminComment.Buffer);
3468
3469 midl_user_free(InfoBuffer);
3470 }
3471 }
3472
3473 return Status;
3474 }
3475
3476
3477 static NTSTATUS
3478 SampQueryGroupName(PSAM_DB_OBJECT GroupObject,
3479 PSAMPR_GROUP_INFO_BUFFER *Buffer)
3480 {
3481 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
3482 NTSTATUS Status;
3483
3484 *Buffer = NULL;
3485
3486 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
3487 if (InfoBuffer == NULL)
3488 return STATUS_INSUFFICIENT_RESOURCES;
3489
3490 Status = SampGetObjectAttributeString(GroupObject,
3491 L"Name",
3492 &InfoBuffer->Name.Name);
3493 if (!NT_SUCCESS(Status))
3494 {
3495 TRACE("Status 0x%08lx\n", Status);
3496 goto done;
3497 }
3498
3499 *Buffer = InfoBuffer;
3500
3501 done:
3502 if (!NT_SUCCESS(Status))
3503 {
3504 if (InfoBuffer != NULL)
3505 {
3506 if (InfoBuffer->Name.Name.Buffer != NULL)
3507 midl_user_free(InfoBuffer->Name.Name.Buffer);
3508
3509 midl_user_free(InfoBuffer);
3510 }
3511 }
3512
3513 return Status;
3514 }
3515
3516
3517 static NTSTATUS
3518 SampQueryGroupAttribute(PSAM_DB_OBJECT GroupObject,
3519 PSAMPR_GROUP_INFO_BUFFER *Buffer)
3520 {
3521 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
3522 SAM_GROUP_FIXED_DATA FixedData;
3523 ULONG Length = 0;
3524 NTSTATUS Status;
3525
3526 *Buffer = NULL;
3527
3528 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
3529 if (InfoBuffer == NULL)
3530 return STATUS_INSUFFICIENT_RESOURCES;
3531
3532 Length = sizeof(SAM_GROUP_FIXED_DATA);
3533 Status = SampGetObjectAttribute(GroupObject,
3534 L"F",
3535 NULL,
3536 (PVOID)&FixedData,
3537 &Length);
3538 if (!NT_SUCCESS(Status))
3539 goto done;
3540
3541 InfoBuffer->Attribute.Attributes = FixedData.Attributes;
3542
3543 *Buffer = InfoBuffer;
3544
3545 done:
3546 if (!NT_SUCCESS(Status))
3547 {
3548 if (InfoBuffer != NULL)
3549 {
3550 midl_user_free(InfoBuffer);
3551 }
3552 }
3553
3554 return Status;
3555 }
3556
3557
3558 static NTSTATUS
3559 SampQueryGroupAdminComment(PSAM_DB_OBJECT GroupObject,
3560 PSAMPR_GROUP_INFO_BUFFER *Buffer)
3561 {
3562 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
3563 NTSTATUS Status;
3564
3565 *Buffer = NULL;
3566
3567 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
3568 if (InfoBuffer == NULL)
3569 return STATUS_INSUFFICIENT_RESOURCES;
3570
3571 Status = SampGetObjectAttributeString(GroupObject,
3572 L"Description",
3573 &InfoBuffer->AdminComment.AdminComment);
3574 if (!NT_SUCCESS(Status))
3575 {
3576 TRACE("Status 0x%08lx\n", Status);
3577 goto done;
3578 }
3579
3580 *Buffer = InfoBuffer;
3581
3582 done:
3583 if (!NT_SUCCESS(Status))
3584 {
3585 if (InfoBuffer != NULL)
3586 {
3587 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
3588 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
3589
3590 midl_user_free(InfoBuffer);
3591 }
3592 }
3593
3594 return Status;
3595 }
3596
3597
3598 /* Function 20 */
3599 NTSTATUS
3600 NTAPI
3601 SamrQueryInformationGroup(IN SAMPR_HANDLE GroupHandle,
3602 IN GROUP_INFORMATION_CLASS GroupInformationClass,
3603 OUT PSAMPR_GROUP_INFO_BUFFER *Buffer)
3604 {
3605 PSAM_DB_OBJECT GroupObject;
3606 NTSTATUS Status;
3607
3608 TRACE("SamrQueryInformationGroup(%p %lu %p)\n",
3609 GroupHandle, GroupInformationClass, Buffer);
3610
3611 /* Validate the group handle */
3612 Status = SampValidateDbObject(GroupHandle,
3613 SamDbGroupObject,
3614 GROUP_READ_INFORMATION,
3615 &GroupObject);
3616 if (!NT_SUCCESS(Status))
3617 return Status;
3618
3619 switch (GroupInformationClass)
3620 {
3621 case GroupGeneralInformation:
3622 Status = SampQueryGroupGeneral(GroupObject,
3623 Buffer);
3624 break;
3625
3626 case GroupNameInformation:
3627 Status = SampQueryGroupName(GroupObject,
3628 Buffer);
3629 break;
3630
3631 case GroupAttributeInformation:
3632 Status = SampQueryGroupAttribute(GroupObject,
3633 Buffer);
3634 break;
3635
3636 case GroupAdminCommentInformation:
3637 Status = SampQueryGroupAdminComment(GroupObject,
3638 Buffer);
3639 break;
3640
3641 default:
3642 Status = STATUS_INVALID_INFO_CLASS;
3643 break;
3644 }
3645
3646 return Status;
3647 }
3648
3649
3650 static NTSTATUS
3651 SampSetGroupAttribute(PSAM_DB_OBJECT GroupObject,
3652 PSAMPR_GROUP_INFO_BUFFER Buffer)
3653 {
3654 SAM_GROUP_FIXED_DATA FixedData;
3655 ULONG Length = 0;
3656 NTSTATUS Status;
3657
3658 Length = sizeof(SAM_GROUP_FIXED_DATA);
3659 Status = SampGetObjectAttribute(GroupObject,
3660 L"F",
3661 NULL,
3662 (PVOID)&FixedData,
3663 &Length);
3664 if (!NT_SUCCESS(Status))
3665 goto done;
3666
3667 FixedData.Attributes = Buffer->Attribute.Attributes;
3668
3669 Status = SampSetObjectAttribute(GroupObject,
3670 L"F",
3671 REG_BINARY,
3672 &FixedData,
3673 Length);
3674
3675 done:
3676 return Status;
3677 }
3678
3679
3680 /* Function 21 */
3681 NTSTATUS
3682 NTAPI
3683 SamrSetInformationGroup(IN SAMPR_HANDLE GroupHandle,
3684 IN GROUP_INFORMATION_CLASS GroupInformationClass,
3685 IN PSAMPR_GROUP_INFO_BUFFER Buffer)
3686 {
3687 PSAM_DB_OBJECT GroupObject;
3688 NTSTATUS Status;
3689
3690 TRACE("SamrSetInformationGroup(%p %lu %p)\n",
3691 GroupHandle, GroupInformationClass, Buffer);
3692
3693 /* Validate the group handle */
3694 Status = SampValidateDbObject(GroupHandle,
3695 SamDbGroupObject,
3696 GROUP_WRITE_ACCOUNT,
3697 &GroupObject);
3698 if (!NT_SUCCESS(Status))
3699 return Status;
3700
3701 switch (GroupInformationClass)
3702 {
3703 case GroupNameInformation:
3704 Status = SampSetObjectAttribute(GroupObject,
3705 L"Name",
3706 REG_SZ,
3707 Buffer->Name.Name.Buffer,
3708 Buffer->Name.Name.Length + sizeof(WCHAR));
3709 break;
3710
3711 case GroupAttributeInformation:
3712 Status = SampSetGroupAttribute(GroupObject,
3713 Buffer);
3714 break;
3715
3716 case GroupAdminCommentInformation:
3717 Status = SampSetObjectAttribute(GroupObject,
3718 L"Description",
3719 REG_SZ,
3720 Buffer->AdminComment.AdminComment.Buffer,
3721 Buffer->AdminComment.AdminComment.Length + sizeof(WCHAR));
3722 break;
3723
3724 default:
3725 Status = STATUS_INVALID_INFO_CLASS;
3726 break;
3727 }
3728
3729 return Status;
3730 }
3731
3732
3733 /* Function 22 */
3734 NTSTATUS
3735 NTAPI
3736 SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle,
3737 IN unsigned long MemberId,
3738 IN unsigned long Attributes)
3739 {
3740 UNIMPLEMENTED;
3741 return STATUS_NOT_IMPLEMENTED;
3742 }
3743
3744 /* Function 21 */
3745 NTSTATUS
3746 NTAPI
3747 SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
3748 {
3749 UNIMPLEMENTED;
3750 return STATUS_NOT_IMPLEMENTED;
3751 }
3752
3753 /* Function 24 */
3754 NTSTATUS
3755 NTAPI
3756 SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle,
3757 IN unsigned long MemberId)
3758 {
3759 UNIMPLEMENTED;
3760 return STATUS_NOT_IMPLEMENTED;
3761 }
3762
3763 /* Function 25 */
3764 NTSTATUS
3765 NTAPI
3766 SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle,
3767 OUT PSAMPR_GET_MEMBERS_BUFFER *Members)
3768 {
3769 UNIMPLEMENTED;
3770 return STATUS_NOT_IMPLEMENTED;
3771 }
3772
3773 /* Function 26 */
3774 NTSTATUS
3775 NTAPI
3776 SamrSetMemberAttributesOfGroup(IN SAMPR_HANDLE GroupHandle,
3777 IN unsigned long MemberId,
3778 IN unsigned long Attributes)
3779 {
3780 UNIMPLEMENTED;
3781 return STATUS_NOT_IMPLEMENTED;
3782 }
3783
3784
3785 /* Function 27 */
3786 NTSTATUS
3787 NTAPI
3788 SamrOpenAlias(IN SAMPR_HANDLE DomainHandle,
3789 IN ACCESS_MASK DesiredAccess,
3790 IN ULONG AliasId,
3791 OUT SAMPR_HANDLE *AliasHandle)
3792 {
3793 PSAM_DB_OBJECT DomainObject;
3794 PSAM_DB_OBJECT AliasObject;
3795 WCHAR szRid[9];
3796 NTSTATUS Status;
3797
3798 TRACE("SamrOpenAlias(%p %lx %lx %p)\n",
3799 DomainHandle, DesiredAccess, AliasId, AliasHandle);
3800
3801 /* Validate the domain handle */
3802 Status = SampValidateDbObject(DomainHandle,
3803 SamDbDomainObject,
3804 DOMAIN_LOOKUP,
3805 &DomainObject);
3806 if (!NT_SUCCESS(Status))
3807 {
3808 TRACE("failed with status 0x%08lx\n", Status);
3809 return Status;
3810 }
3811
3812 /* Convert the RID into a string (hex) */
3813 swprintf(szRid, L"%08lX", AliasId);
3814
3815 /* Create the alias object */
3816 Status = SampOpenDbObject(DomainObject,
3817 L"Aliases",
3818 szRid,
3819 SamDbAliasObject,
3820 DesiredAccess,
3821 &AliasObject);
3822 if (!NT_SUCCESS(Status))
3823 {
3824 TRACE("failed with status 0x%08lx\n", Status);
3825 return Status;
3826 }
3827
3828 *AliasHandle = (SAMPR_HANDLE)AliasObject;
3829
3830 return STATUS_SUCCESS;
3831 }
3832
3833
3834 static NTSTATUS
3835 SampQueryAliasGeneral(PSAM_DB_OBJECT AliasObject,
3836 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
3837 {
3838 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
3839 HANDLE MembersKeyHandle = NULL;
3840 NTSTATUS Status;
3841
3842 *Buffer = NULL;
3843
3844 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
3845 if (InfoBuffer == NULL)
3846 return STATUS_INSUFFICIENT_RESOURCES;
3847
3848 Status = SampGetObjectAttributeString(AliasObject,
3849 L"Name",
3850 &InfoBuffer->General.Name);
3851 if (!NT_SUCCESS(Status))
3852 {
3853 TRACE("Status 0x%08lx\n", Status);
3854 goto done;
3855 }
3856
3857 Status = SampGetObjectAttributeString(AliasObject,
3858 L"Description",
3859 &InfoBuffer->General.AdminComment);
3860 if (!NT_SUCCESS(Status))
3861 {
3862 TRACE("Status 0x%08lx\n", Status);
3863 goto done;
3864 }
3865
3866 /* Open the Members subkey */
3867 Status = SampRegOpenKey(AliasObject->KeyHandle,
3868 L"Members",
3869 KEY_READ,
3870 &MembersKeyHandle);
3871 if (!NT_SUCCESS(Status))
3872 {
3873 TRACE("Status 0x%08lx\n", Status);
3874 goto done;
3875 }
3876
3877 /* Retrieve the number of members of the alias */
3878 Status = SampRegQueryKeyInfo(MembersKeyHandle,
3879 NULL,
3880 &InfoBuffer->General.MemberCount);
3881 if (!NT_SUCCESS(Status))
3882 {
3883 TRACE("Status 0x%08lx\n", Status);
3884 goto done;
3885 }
3886
3887 *Buffer = InfoBuffer;
3888
3889 done:
3890 if (MembersKeyHandle != NULL)
3891 SampRegCloseKey(MembersKeyHandle);
3892
3893 if (!NT_SUCCESS(Status))
3894 {
3895 if (InfoBuffer != NULL)
3896 {
3897 if (InfoBuffer->General.Name.Buffer != NULL)
3898 midl_user_free(InfoBuffer->General.Name.Buffer);
3899
3900 if (InfoBuffer->General.AdminComment.Buffer != NULL)
3901 midl_user_free(InfoBuffer->General.AdminComment.Buffer);
3902
3903 midl_user_free(InfoBuffer);
3904 }
3905 }
3906
3907 return Status;
3908 }
3909
3910
3911 static NTSTATUS
3912 SampQueryAliasName(PSAM_DB_OBJECT AliasObject,
3913 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
3914 {
3915 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
3916 NTSTATUS Status;
3917
3918 *Buffer = NULL;
3919
3920 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
3921 if (InfoBuffer == NULL)
3922 return STATUS_INSUFFICIENT_RESOURCES;
3923
3924 Status = SampGetObjectAttributeString(AliasObject,
3925 L"Name",
3926 &InfoBuffer->Name.Name);
3927 if (!NT_SUCCESS(Status))
3928 {
3929 TRACE("Status 0x%08lx\n", Status);
3930 goto done;
3931 }
3932
3933 *Buffer = InfoBuffer;
3934
3935 done:
3936 if (!NT_SUCCESS(Status))
3937 {
3938 if (InfoBuffer != NULL)
3939 {
3940 if (InfoBuffer->Name.Name.Buffer != NULL)
3941 midl_user_free(InfoBuffer->Name.Name.Buffer);
3942
3943 midl_user_free(InfoBuffer);
3944 }
3945 }
3946
3947 return Status;
3948 }
3949
3950
3951 static NTSTATUS
3952 SampQueryAliasAdminComment(PSAM_DB_OBJECT AliasObject,
3953 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
3954 {
3955 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
3956 NTSTATUS Status;
3957
3958 *Buffer = NULL;
3959
3960 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
3961 if (InfoBuffer == NULL)
3962 return STATUS_INSUFFICIENT_RESOURCES;
3963
3964 Status = SampGetObjectAttributeString(AliasObject,
3965 L"Description",
3966 &InfoBuffer->AdminComment.AdminComment);
3967 if (!NT_SUCCESS(Status))
3968 {
3969 TRACE("Status 0x%08lx\n", Status);
3970 goto done;
3971 }
3972
3973 *Buffer = InfoBuffer;
3974
3975 done:
3976 if (!NT_SUCCESS(Status))
3977 {
3978 if (InfoBuffer != NULL)
3979 {
3980 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
3981 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
3982
3983 midl_user_free(InfoBuffer);
3984 }
3985 }
3986
3987 return Status;
3988 }
3989
3990
3991 /* Function 28 */
3992 NTSTATUS
3993 NTAPI
3994 SamrQueryInformationAlias(IN SAMPR_HANDLE AliasHandle,
3995 IN ALIAS_INFORMATION_CLASS AliasInformationClass,
3996 OUT PSAMPR_ALIAS_INFO_BUFFER *Buffer)
3997 {
3998 PSAM_DB_OBJECT AliasObject;
3999 NTSTATUS Status;
4000
4001 TRACE("SamrQueryInformationAlias(%p %lu %p)\n",
4002 AliasHandle, AliasInformationClass, Buffer);
4003
4004 /* Validate the alias handle */
4005 Status = SampValidateDbObject(AliasHandle,
4006 SamDbAliasObject,
4007 ALIAS_READ_INFORMATION,
4008 &AliasObject);
4009 if (!NT_SUCCESS(Status))
4010 return Status;
4011
4012 switch (AliasInformationClass)
4013 {
4014 case AliasGeneralInformation:
4015 Status = SampQueryAliasGeneral(AliasObject,
4016 Buffer);
4017 break;
4018
4019 case AliasNameInformation:
4020 Status = SampQueryAliasName(AliasObject,
4021 Buffer);
4022 break;
4023
4024 case AliasAdminCommentInformation:
4025 Status = SampQueryAliasAdminComment(AliasObject,
4026 Buffer);
4027 break;
4028
4029 default:
4030 Status = STATUS_INVALID_INFO_CLASS;
4031 break;
4032 }
4033
4034 return Status;
4035 }
4036
4037
4038 /* Function 29 */
4039 NTSTATUS
4040 NTAPI
4041 SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle,
4042 IN ALIAS_INFORMATION_CLASS AliasInformationClass,
4043 IN PSAMPR_ALIAS_INFO_BUFFER Buffer)
4044 {
4045 PSAM_DB_OBJECT AliasObject;
4046 NTSTATUS Status;
4047
4048 TRACE("SamrSetInformationAlias(%p %lu %p)\n",
4049 AliasHandle, AliasInformationClass, Buffer);
4050
4051 /* Validate the alias handle */
4052 Status = SampValidateDbObject(AliasHandle,
4053 SamDbAliasObject,
4054 ALIAS_WRITE_ACCOUNT,
4055 &AliasObject);
4056 if (!NT_SUCCESS(Status))
4057 return Status;
4058
4059 switch (AliasInformationClass)
4060 {
4061 case AliasNameInformation:
4062 Status = SampSetObjectAttribute(AliasObject,
4063 L"Name",
4064 REG_SZ,
4065 Buffer->Name.Name.Buffer,
4066 Buffer->Name.Name.Length + sizeof(WCHAR));
4067 break;
4068
4069 case AliasAdminCommentInformation:
4070 Status = SampSetObjectAttribute(AliasObject,
4071 L"Description",
4072 REG_SZ,
4073 Buffer->AdminComment.AdminComment.Buffer,
4074 Buffer->AdminComment.AdminComment.Length + sizeof(WCHAR));
4075 break;
4076
4077 default:
4078 Status = STATUS_INVALID_INFO_CLASS;
4079 break;
4080 }
4081
4082 return Status;
4083 }
4084
4085
4086 /* Function 30 */
4087 NTSTATUS
4088 NTAPI
4089 SamrDeleteAlias(IN OUT SAMPR_HANDLE *AliasHandle)
4090 {
4091 UNIMPLEMENTED;
4092 return STATUS_NOT_IMPLEMENTED;
4093 }
4094
4095
4096 /* Function 31 */
4097 NTSTATUS
4098 NTAPI
4099 SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
4100 IN PRPC_SID MemberId)
4101 {
4102 PSAM_DB_OBJECT AliasObject;
4103 LPWSTR MemberIdString = NULL;
4104 HANDLE MembersKeyHandle = NULL;
4105 HANDLE MemberKeyHandle = NULL;
4106 ULONG MemberIdLength;
4107 NTSTATUS Status;
4108
4109 TRACE("SamrAddMemberToAlias(%p %p)\n",
4110 AliasHandle, MemberId);
4111
4112 /* Validate the alias handle */
4113 Status = SampValidateDbObject(AliasHandle,
4114 SamDbAliasObject,
4115 ALIAS_ADD_MEMBER,
4116 &AliasObject);
4117 if (!NT_SUCCESS(Status))
4118 {
4119 TRACE("failed with status 0x%08lx\n", Status);
4120 return Status;
4121 }
4122
4123 ConvertSidToStringSidW(MemberId, &MemberIdString);
4124 TRACE("Member SID: %S\n", MemberIdString);
4125
4126 MemberIdLength = RtlLengthSid(MemberId);
4127
4128 Status = SampRegCreateKey(AliasObject->KeyHandle,
4129 L"Members",
4130 KEY_WRITE,
4131 &MembersKeyHandle);
4132 if (!NT_SUCCESS(Status))
4133 {
4134 TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
4135 goto done;
4136 }
4137
4138 Status = SampRegSetValue(MembersKeyHandle,
4139 MemberIdString,
4140 REG_BINARY,
4141 MemberId,
4142 MemberIdLength);
4143 if (!NT_SUCCESS(Status))
4144 {
4145 TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
4146 goto done;
4147 }
4148
4149 Status = SampRegCreateKey(AliasObject->MembersKeyHandle,
4150 MemberIdString,
4151 KEY_WRITE,
4152 &MemberKeyHandle);
4153 if (!NT_SUCCESS(Status))
4154 {
4155 TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
4156 goto done;
4157 }
4158
4159 Status = SampRegSetValue(MemberKeyHandle,
4160 AliasObject->Name,
4161 REG_BINARY,
4162 MemberId,
4163 MemberIdLength);
4164 if (!NT_SUCCESS(Status))
4165 {
4166 TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
4167 goto done;
4168 }
4169
4170 done:
4171 if (MemberKeyHandle != NULL)
4172 SampRegCloseKey(MemberKeyHandle);
4173
4174 if (MembersKeyHandle != NULL)
4175 SampRegCloseKey(MembersKeyHandle);
4176
4177 if (MemberIdString != NULL)
4178 LocalFree(MemberIdString);
4179
4180 return Status;
4181 }
4182
4183
4184 /* Function 32 */
4185 NTSTATUS
4186 NTAPI
4187 SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle,
4188 IN PRPC_SID MemberId)
4189 {
4190 UNIMPLEMENTED;
4191 return STATUS_NOT_IMPLEMENTED;
4192 }
4193
4194 /* Function 33 */
4195 NTSTATUS
4196 NTAPI
4197 SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
4198 OUT PSAMPR_PSID_ARRAY_OUT Members)
4199 {
4200 PSAM_DB_OBJECT AliasObject;
4201 HANDLE MembersKeyHandle = NULL;
4202 PSAMPR_SID_INFORMATION MemberArray = NULL;
4203 ULONG ValueCount = 0;
4204 ULONG DataLength;
4205 ULONG Index;
4206 NTSTATUS Status;
4207
4208 TRACE("SamrGetMembersInAlias(%p %p %p)\n",
4209 AliasHandle, Members);
4210
4211 /* Validate the alias handle */
4212 Status = SampValidateDbObject(AliasHandle,
4213 SamDbAliasObject,
4214 ALIAS_LIST_MEMBERS,
4215 &AliasObject);
4216 if (!NT_SUCCESS(Status))
4217 {
4218 ERR("failed with status 0x%08lx\n", Status);
4219 return Status;
4220 }
4221
4222 /* Open the members key of the alias objct */
4223 Status = SampRegOpenKey(AliasObject->KeyHandle,
4224 L"Members",
4225 KEY_READ,
4226 &MembersKeyHandle);
4227 if (!NT_SUCCESS(Status))
4228 {
4229 ERR("SampRegOpenKey failed with status 0x%08lx\n", Status);
4230 return Status;
4231 }
4232
4233 /* Get the number of members */
4234 Status = SampRegQueryKeyInfo(MembersKeyHandle,
4235 NULL,
4236 &ValueCount);
4237 if (!NT_SUCCESS(Status))
4238 {
4239 ERR("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
4240 goto done;
4241 }
4242
4243 /* Allocate the member array */
4244 MemberArray = midl_user_allocate(ValueCount * sizeof(SAMPR_SID_INFORMATION));
4245 if (MemberArray == NULL)
4246 {
4247 Status = STATUS_INSUFFICIENT_RESOURCES;
4248 goto done;
4249 }
4250
4251 /* Enumerate the members */
4252 Index = 0;
4253 while (TRUE)
4254 {
4255 /* Get the size of the next SID */
4256 DataLength = 0;
4257 Status = SampRegEnumerateValue(MembersKeyHandle,
4258 Index,
4259 NULL,
4260 NULL,
4261 NULL,
4262 NULL,
4263 &DataLength);
4264 if (!NT_SUCCESS(Status))
4265 {
4266 if (Status == STATUS_NO_MORE_ENTRIES)
4267 Status = STATUS_SUCCESS;
4268 break;
4269 }
4270
4271 /* Allocate a buffer for the SID */
4272 MemberArray[Index].SidPointer = midl_user_allocate(DataLength);
4273 if (MemberArray[Index].SidPointer == NULL)
4274 {
4275 Status = STATUS_INSUFFICIENT_RESOURCES;
4276 goto done;
4277 }
4278
4279 /* Read the SID into the buffer */
4280 Status = SampRegEnumerateValue(MembersKeyHandle,
4281 Index,
4282 NULL,
4283 NULL,
4284 NULL,
4285 (PVOID)MemberArray[Index].SidPointer,
4286 &DataLength);
4287 if (!NT_SUCCESS(Status))
4288 {
4289 goto done;
4290 }
4291
4292 Index++;
4293 }
4294
4295 /* Return the number of members and the member array */
4296 if (NT_SUCCESS(Status))
4297 {
4298 Members->Count = ValueCount;
4299 Members->Sids = MemberArray;
4300 }
4301
4302 done:
4303 /* Clean up the members array and the SID buffers if something failed */
4304 if (!NT_SUCCESS(Status))
4305 {
4306 if (MemberArray != NULL)
4307 {
4308 for (Index = 0; Index < ValueCount; Index++)
4309 {
4310 if (MemberArray[Index].SidPointer != NULL)
4311 midl_user_free(MemberArray[Index].SidPointer);
4312 }
4313
4314 midl_user_free(MemberArray);
4315 }
4316 }
4317
4318 /* Close the members key */
4319 if (MembersKeyHandle != NULL)
4320 SampRegCloseKey(MembersKeyHandle);
4321
4322 return Status;
4323 }
4324
4325
4326 /* Function 34 */
4327 NTSTATUS
4328 NTAPI
4329 SamrOpenUser(IN SAMPR_HANDLE DomainHandle,
4330 IN ACCESS_MASK DesiredAccess,
4331 IN unsigned long UserId,
4332 OUT SAMPR_HANDLE *UserHandle)
4333 {
4334 PSAM_DB_OBJECT DomainObject;
4335 PSAM_DB_OBJECT UserObject;
4336 WCHAR szRid[9];
4337 NTSTATUS Status;
4338
4339 TRACE("SamrOpenUser(%p %lx %lx %p)\n",
4340 DomainHandle, DesiredAccess, UserId, UserHandle);
4341
4342 /* Validate the domain handle */
4343 Status = SampValidateDbObject(DomainHandle,
4344 SamDbDomainObject,
4345 DOMAIN_LOOKUP,
4346 &DomainObject);
4347 if (!NT_SUCCESS(Status))
4348 {
4349 TRACE("failed with status 0x%08lx\n", Status);
4350 return Status;
4351 }
4352
4353 /* Convert the RID into a string (hex) */
4354 swprintf(szRid, L"%08lX", UserId);
4355
4356 /* Create the user object */
4357 Status = SampOpenDbObject(DomainObject,
4358 L"Users",
4359 szRid,
4360 SamDbUserObject,
4361 DesiredAccess,
4362 &UserObject);
4363 if (!NT_SUCCESS(Status))
4364 {
4365 TRACE("failed with status 0x%08lx\n", Status);
4366 return Status;
4367 }
4368
4369 *UserHandle = (SAMPR_HANDLE)UserObject;
4370
4371 return STATUS_SUCCESS;
4372 }
4373
4374
4375 /* Function 35 */
4376 NTSTATUS
4377 NTAPI
4378 SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle)
4379 {
4380 UNIMPLEMENTED;
4381 return STATUS_NOT_IMPLEMENTED;
4382 }
4383
4384
4385 static
4386 NTSTATUS
4387 SampQueryUserGeneral(PSAM_DB_OBJECT UserObject,
4388 PSAMPR_USER_INFO_BUFFER *Buffer)
4389 {
4390 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4391 SAM_USER_FIXED_DATA FixedData;
4392 ULONG Length = 0;
4393 NTSTATUS Status;
4394
4395 *Buffer = NULL;
4396
4397 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
4398 if (InfoBuffer == NULL)
4399 return STATUS_INSUFFICIENT_RESOURCES;
4400
4401 Length = sizeof(SAM_USER_FIXED_DATA);
4402 Status = SampGetObjectAttribute(UserObject,
4403 L"F",
4404 NULL,
4405 (PVOID)&FixedData,
4406 &Length);
4407 if (!NT_SUCCESS(Status))
4408 goto done;
4409
4410 InfoBuffer->General.PrimaryGroupId = FixedData.PrimaryGroupId;
4411
4412 /* Get the Name string */
4413 Status = SampGetObjectAttributeString(UserObject,
4414 L"Name",
4415 &InfoBuffer->General.UserName);
4416 if (!NT_SUCCESS(Status))
4417 {
4418 TRACE("Status 0x%08lx\n", Status);
4419 goto done;
4420 }
4421
4422 /* Get the FullName string */
4423 Status = SampGetObjectAttributeString(UserObject,
4424 L"FullName",
4425 &InfoBuffer->General.FullName);
4426 if (!NT_SUCCESS(Status))
4427 {
4428 TRACE("Status 0x%08lx\n", Status);
4429 goto done;
4430 }
4431
4432 /* Get the AdminComment string */
4433 Status = SampGetObjectAttributeString(UserObject,
4434 L"AdminComment",
4435 &InfoBuffer->General.AdminComment);
4436 if (!NT_SUCCESS(Status))
4437 {
4438 TRACE("Status 0x%08lx\n", Status);
4439 goto done;
4440 }
4441
4442 /* Get the UserComment string */
4443 Status = SampGetObjectAttributeString(UserObject,
4444 L"UserComment",
4445 &InfoBuffer->General.UserComment);
4446 if (!NT_SUCCESS(Status))
4447 {
4448 TRACE("Status 0x%08lx\n", Status);
4449 goto done;
4450 }
4451
4452 *Buffer = InfoBuffer;
4453
4454 done:
4455 if (!NT_SUCCESS(Status))
4456 {
4457 if (InfoBuffer != NULL)
4458 {
4459 if (InfoBuffer->General.UserName.Buffer != NULL)
4460 midl_user_free(InfoBuffer->General.UserName.Buffer);
4461
4462 if (InfoBuffer->General.FullName.Buffer != NULL)
4463 midl_user_free(InfoBuffer->General.FullName.Buffer);
4464
4465 if (InfoBuffer->General.AdminComment.Buffer != NULL)
4466 midl_user_free(InfoBuffer->General.AdminComment.Buffer);
4467
4468 if (InfoBuffer->General.UserComment.Buffer != NULL)
4469 midl_user_free(InfoBuffer->General.UserComment.Buffer);
4470
4471 midl_user_free(InfoBuffer);
4472 }
4473 }
4474
4475 return Status;
4476 }
4477
4478
4479 static
4480 NTSTATUS
4481 SampQueryUserPreferences(PSAM_DB_OBJECT UserObject,
4482 PSAMPR_USER_INFO_BUFFER *Buffer)
4483 {
4484 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4485 SAM_USER_FIXED_DATA FixedData;
4486 ULONG Length = 0;
4487 NTSTATUS Status;
4488
4489 *Buffer = NULL;
4490
4491 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
4492 if (InfoBuffer == NULL)
4493 return STATUS_INSUFFICIENT_RESOURCES;
4494
4495 Length = sizeof(SAM_USER_FIXED_DATA);
4496 Status = SampGetObjectAttribute(UserObject,
4497 L"F",
4498 NULL,
4499 (PVOID)&FixedData,
4500 &Length);
4501 if (!NT_SUCCESS(Status))
4502 goto done;
4503
4504 InfoBuffer->Preferences.CountryCode = FixedData.CountryCode;
4505 InfoBuffer->Preferences.CodePage = FixedData.CodePage;
4506
4507 /* Get the UserComment string */
4508 Status = SampGetObjectAttributeString(UserObject,
4509 L"UserComment",
4510 &InfoBuffer->Preferences.UserComment);
4511 if (!NT_SUCCESS(Status))
4512 {
4513 TRACE("Status 0x%08lx\n", Status);
4514 goto done;
4515 }
4516
4517 *Buffer = InfoBuffer;
4518
4519 done:
4520 if (!NT_SUCCESS(Status))
4521 {
4522 if (InfoBuffer != NULL)
4523 {
4524 if (InfoBuffer->Preferences.UserComment.Buffer != NULL)
4525 midl_user_free(InfoBuffer->Preferences.UserComment.Buffer);
4526
4527 midl_user_free(InfoBuffer);
4528 }
4529 }
4530
4531 return Status;
4532 }
4533
4534
4535 static
4536 NTSTATUS
4537 SampQueryUserLogon(PSAM_DB_OBJECT UserObject,
4538 PSAMPR_USER_INFO_BUFFER *Buffer)
4539 {
4540 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4541 SAM_USER_FIXED_DATA FixedData;
4542 ULONG Length = 0;
4543 NTSTATUS Status;
4544
4545 *Buffer = NULL;
4546
4547 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
4548 if (InfoBuffer == NULL)
4549 return STATUS_INSUFFICIENT_RESOURCES;
4550
4551 Length = sizeof(SAM_USER_FIXED_DATA);
4552 Status = SampGetObjectAttribute(UserObject,
4553 L"F",
4554 NULL,
4555 (PVOID)&FixedData,
4556 &Length);
4557 if (!NT_SUCCESS(Status))
4558 goto done;
4559
4560 InfoBuffer->Logon.UserId = FixedData.UserId;
4561 InfoBuffer->Logon.PrimaryGroupId = FixedData.PrimaryGroupId;
4562 InfoBuffer->Logon.LastLogon.LowPart = FixedData.LastLogon.LowPart;
4563 InfoBuffer->Logon.LastLogon.HighPart = FixedData.LastLogon.HighPart;
4564 InfoBuffer->Logon.LastLogoff.LowPart = FixedData.LastLogoff.LowPart;
4565 InfoBuffer->Logon.LastLogoff.HighPart = FixedData.LastLogoff.HighPart;
4566 InfoBuffer->Logon.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart;
4567 InfoBuffer->Logon.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart;
4568 InfoBuffer->Logon.BadPasswordCount = FixedData.BadPasswordCount;
4569 InfoBuffer->Logon.LogonCount = FixedData.LogonCount;
4570 InfoBuffer->Logon.UserAccountControl = FixedData.UserAccountControl;
4571
4572 // OLD_LARGE_INTEGER PasswordCanChange;
4573 // OLD_LARGE_INTEGER PasswordMustChange;
4574
4575 /* Get the Name string */
4576 Status = SampGetObjectAttributeString(UserObject,
4577 L"Name",
4578 &InfoBuffer->Logon.UserName);
4579 if (!NT_SUCCESS(Status))
4580 {
4581 TRACE("Status 0x%08lx\n", Status);
4582 goto done;
4583 }
4584
4585 /* Get the FullName string */
4586 Status = SampGetObjectAttributeString(UserObject,
4587 L"FullName",
4588 &InfoBuffer->Logon.FullName);
4589 if (!NT_SUCCESS(Status))
4590 {
4591 TRACE("Status 0x%08lx\n", Status);
4592 goto done;
4593 }
4594
4595 /* Get the HomeDirectory string */
4596 Status = SampGetObjectAttributeString(UserObject,
4597 L"HomeDirectory",
4598 &InfoBuffer->Logon.HomeDirectory);
4599 if (!NT_SUCCESS(Status))
4600 {
4601 TRACE("Status 0x%08lx\n", Status);
4602 goto done;
4603 }
4604
4605 /* Get the HomeDirectoryDrive string */
4606 Status = SampGetObjectAttributeString(UserObject,
4607 L"HomeDirectoryDrive",
4608 &InfoBuffer->Logon.HomeDirectoryDrive);
4609 if (!NT_SUCCESS(Status))
4610 {
4611 TRACE("Status 0x%08lx\n", Status);
4612 goto done;
4613 }
4614
4615 /* Get the ScriptPath string */
4616 Status = SampGetObjectAttributeString(UserObject,
4617 L"ScriptPath",
4618 &InfoBuffer->Logon.ScriptPath);
4619 if (!NT_SUCCESS(Status))
4620 {
4621 TRACE("Status 0x%08lx\n", Status);
4622 goto done;
4623 }
4624
4625 /* Get the ProfilePath string */
4626 Status = SampGetObjectAttributeString(UserObject,
4627 L"ProfilePath",
4628 &InfoBuffer->Logon.ProfilePath);
4629 if (!NT_SUCCESS(Status))
4630 {
4631 TRACE("Status 0x%08lx\n", Status);
4632 goto done;
4633 }
4634
4635 /* Get the WorkStations string */
4636 Status = SampGetObjectAttributeString(UserObject,
4637 L"WorkStations",
4638 &InfoBuffer->Logon.WorkStations);
4639 if (!NT_SUCCESS(Status))
4640 {
4641 TRACE("Status 0x%08lx\n", Status);
4642 goto done;
4643 }
4644
4645 /* FIXME: LogonHours */
4646
4647 *Buffer = InfoBuffer;
4648
4649 done:
4650 if (!NT_SUCCESS(Status))
4651 {
4652 if (InfoBuffer != NULL)
4653 {
4654 if (InfoBuffer->Logon.UserName.Buffer != NULL)
4655 midl_user_free(InfoBuffer->Logon.UserName.Buffer);
4656
4657 if (InfoBuffer->Logon.FullName.Buffer != NULL)
4658 midl_user_free(InfoBuffer->Logon.FullName.Buffer);
4659
4660 if (InfoBuffer->Logon.HomeDirectory.Buffer != NULL)
4661 midl_user_free(InfoBuffer->Logon.HomeDirectory.Buffer);
4662
4663 if (InfoBuffer->Logon.HomeDirectoryDrive.Buffer != NULL)
4664 midl_user_free(InfoBuffer->Logon.HomeDirectoryDrive.Buffer);
4665
4666 if (InfoBuffer->Logon.ScriptPath.Buffer != NULL)
4667 midl_user_free(InfoBuffer->Logon.ScriptPath.Buffer);
4668
4669 if (InfoBuffer->Logon.ProfilePath.Buffer != NULL)
4670 midl_user_free(InfoBuffer->Logon.ProfilePath.Buffer);
4671
4672 if (InfoBuffer->Logon.WorkStations.Buffer != NULL)
4673 midl_user_free(InfoBuffer->Logon.WorkStations.Buffer);
4674
4675 if (InfoBuffer->Logon.LogonHours.LogonHours != NULL)
4676 midl_user_free(InfoBuffer->Logon.LogonHours.LogonHours);
4677
4678 midl_user_free(InfoBuffer);
4679 }
4680 }
4681
4682 return Status;
4683 }
4684
4685
4686 static
4687 NTSTATUS
4688 SampQueryUserAccount(PSAM_DB_OBJECT UserObject,
4689 PSAMPR_USER_INFO_BUFFER *Buffer)
4690 {
4691 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4692 SAM_USER_FIXED_DATA FixedData;
4693 ULONG Length = 0;
4694 NTSTATUS Status;
4695
4696 *Buffer = NULL;
4697
4698 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
4699 if (InfoBuffer == NULL)
4700 return STATUS_INSUFFICIENT_RESOURCES;
4701
4702 Length = sizeof(SAM_USER_FIXED_DATA);
4703 Status = SampGetObjectAttribute(UserObject,
4704 L"F",
4705 NULL,
4706 (PVOID)&FixedData,
4707 &Length);
4708 if (!NT_SUCCESS(Status))
4709 goto done;
4710
4711 InfoBuffer->Account.UserId = FixedData.UserId;
4712 InfoBuffer->Account.PrimaryGroupId = FixedData.PrimaryGroupId;
4713 InfoBuffer->Account.LastLogon.LowPart = FixedData.LastLogon.LowPart;
4714 InfoBuffer->Account.LastLogon.HighPart = FixedData.LastLogon.HighPart;
4715 InfoBuffer->Account.LastLogoff.LowPart = FixedData.LastLogoff.LowPart;
4716 InfoBuffer->Account.LastLogoff.HighPart = FixedData.LastLogoff.HighPart;
4717 InfoBuffer->Account.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart;
4718 InfoBuffer->Account.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart;
4719 InfoBuffer->Account.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
4720 InfoBuffer->Account.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
4721 InfoBuffer->Account.BadPasswordCount = FixedData.BadPasswordCount;
4722 InfoBuffer->Account.LogonCount = FixedData.LogonCount;
4723 InfoBuffer->Account.UserAccountControl = FixedData.UserAccountControl;
4724
4725 /* Get the Name string */
4726 Status = SampGetObjectAttributeString(UserObject,
4727 L"Name",
4728 &InfoBuffer->Account.UserName);
4729 if (!NT_SUCCESS(Status))
4730 {
4731 TRACE("Status 0x%08lx\n", Status);
4732 goto done;
4733 }
4734
4735 /* Get the FullName string */
4736 Status = SampGetObjectAttributeString(UserObject,
4737 L"FullName",
4738 &InfoBuffer->Account.FullName);
4739 if (!NT_SUCCESS(Status))
4740 {
4741 TRACE("Status 0x%08lx\n", Status);
4742 goto done;
4743 }
4744
4745 /* Get the HomeDirectory string */
4746 Status = SampGetObjectAttributeString(UserObject,
4747 L"HomeDirectory",
4748 &InfoBuffer->Account.HomeDirectory);
4749 if (!NT_SUCCESS(Status))
4750 {
4751 TRACE("Status 0x%08lx\n", Status);
4752 goto done;
4753 }
4754
4755 /* Get the HomeDirectoryDrive string */
4756 Status = SampGetObjectAttributeString(UserObject,
4757 L"HomeDirectoryDrive",
4758 &InfoBuffer->Account.HomeDirectoryDrive);
4759 if (!NT_SUCCESS(Status))
4760 {
4761 TRACE("Status 0x%08lx\n", Status);
4762 goto done;
4763 }
4764
4765 /* Get the ScriptPath string */
4766 Status = SampGetObjectAttributeString(UserObject,
4767 L"ScriptPath",
4768 &InfoBuffer->Account.ScriptPath);
4769 if (!NT_SUCCESS(Status))
4770 {
4771 TRACE("Status 0x%08lx\n", Status);
4772 goto done;
4773 }
4774
4775 /* Get the ProfilePath string */
4776 Status = SampGetObjectAttributeString(UserObject,
4777 L"ProfilePath",
4778 &InfoBuffer->Account.ProfilePath);
4779 if (!NT_SUCCESS(Status))
4780 {
4781 TRACE("Status 0x%08lx\n", Status);
4782 goto done;
4783 }
4784
4785 /* Get the AdminComment string */
4786 Status = SampGetObjectAttributeString(UserObject,
4787 L"AdminComment",
4788 &InfoBuffer->Account.AdminComment);
4789 if (!NT_SUCCESS(Status))
4790 {
4791 TRACE("Status 0x%08lx\n", Status);
4792 goto done;
4793 }
4794
4795 /* Get the WorkStations string */
4796 Status = SampGetObjectAttributeString(UserObject,
4797 L"WorkStations",
4798 &InfoBuffer->Account.WorkStations);
4799 if (!NT_SUCCESS(Status))
4800 {
4801 TRACE("Status 0x%08lx\n", Status);
4802 goto done;
4803 }
4804
4805 /* FIXME: LogonHours */
4806
4807 *Buffer = InfoBuffer;
4808
4809 done:
4810 if (!NT_SUCCESS(Status))
4811 {
4812 if (InfoBuffer != NULL)
4813 {
4814 if (InfoBuffer->Account.UserName.Buffer != NULL)
4815 midl_user_free(InfoBuffer->Account.UserName.Buffer);
4816
4817 if (InfoBuffer->Account.FullName.Buffer != NULL)
4818 midl_user_free(InfoBuffer->Account.FullName.Buffer);
4819
4820 if (InfoBuffer->Account.HomeDirectory.Buffer != NULL)
4821 midl_user_free(InfoBuffer->Account.HomeDirectory.Buffer);
4822
4823 if (InfoBuffer->Account.HomeDirectoryDrive.Buffer != NULL)
4824 midl_user_free(InfoBuffer->Account.HomeDirectoryDrive.Buffer);
4825
4826 if (InfoBuffer->Account.ScriptPath.Buffer != NULL)
4827 midl_user_free(InfoBuffer->Account.ScriptPath.Buffer);
4828
4829 if (InfoBuffer->Account.ProfilePath.Buffer != NULL)
4830 midl_user_free(InfoBuffer->Account.ProfilePath.Buffer);
4831
4832 if (InfoBuffer->Account.AdminComment.Buffer != NULL)
4833 midl_user_free(InfoBuffer->Account.AdminComment.Buffer);
4834
4835 if (InfoBuffer->Account.WorkStations.Buffer != NULL)
4836 midl_user_free(InfoBuffer->Account.WorkStations.Buffer);
4837
4838 if (InfoBuffer->Account.LogonHours.LogonHours != NULL)
4839 midl_user_free(InfoBuffer->Account.LogonHours.LogonHours);
4840
4841 midl_user_free(InfoBuffer);
4842 }
4843 }
4844
4845 return Status;
4846 }
4847
4848 /* FIXME: SampQueryUserLogonHours */
4849
4850 static
4851 NTSTATUS
4852 SampQueryUserName(PSAM_DB_OBJECT UserObject,
4853 PSAMPR_USER_INFO_BUFFER *Buffer)
4854 {
4855 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4856 NTSTATUS Status;
4857
4858 *Buffer = NULL;
4859
4860 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
4861 if (InfoBuffer == NULL)
4862 return STATUS_INSUFFICIENT_RESOURCES;
4863
4864 /* Get the Name string */
4865 Status = SampGetObjectAttributeString(UserObject,
4866 L"Name",
4867 &InfoBuffer->Name.UserName);
4868 if (!NT_SUCCESS(Status))
4869 {
4870 TRACE("Status 0x%08lx\n", Status);
4871 goto done;
4872 }
4873
4874 /* Get the FullName string */
4875 Status = SampGetObjectAttributeString(UserObject,
4876 L"FullName",
4877 &InfoBuffer->Name.FullName);
4878 if (!NT_SUCCESS(Status))
4879 {
4880 TRACE("Status 0x%08lx\n", Status);
4881 goto done;
4882 }
4883
4884 *Buffer = InfoBuffer;
4885
4886 done:
4887 if (!NT_SUCCESS(Status))
4888 {
4889 if (InfoBuffer != NULL)
4890 {
4891 if (InfoBuffer->Name.UserName.Buffer != NULL)
4892 midl_user_free(InfoBuffer->Name.UserName.Buffer);
4893
4894 if (InfoBuffer->Name.FullName.Buffer != NULL)
4895 midl_user_free(InfoBuffer->Name.FullName.Buffer);
4896
4897 midl_user_free(InfoBuffer);
4898 }
4899 }
4900
4901 return Status;
4902 }
4903
4904
4905 static NTSTATUS
4906 SampQueryUserAccountName(PSAM_DB_OBJECT UserObject,
4907 PSAMPR_USER_INFO_BUFFER *Buffer)
4908 {
4909 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4910 NTSTATUS Status;
4911
4912 *Buffer = NULL;
4913
4914 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
4915 if (InfoBuffer == NULL)
4916 return STATUS_INSUFFICIENT_RESOURCES;
4917
4918 /* Get the Name string */
4919 Status = SampGetObjectAttributeString(UserObject,
4920 L"Name",
4921 &InfoBuffer->AccountName.UserName);
4922 if (!NT_SUCCESS(Status))
4923 {
4924 TRACE("Status 0x%08lx\n", Status);
4925 goto done;
4926 }
4927
4928 *Buffer = InfoBuffer;
4929
4930 done:
4931 if (!NT_SUCCESS(Status))
4932 {
4933 if (InfoBuffer != NULL)
4934 {
4935 if (InfoBuffer->AccountName.UserName.Buffer != NULL)
4936 midl_user_free(InfoBuffer->AccountName.UserName.Buffer);
4937
4938 midl_user_free(InfoBuffer);
4939 }
4940 }
4941
4942 return Status;
4943 }
4944
4945
4946 static NTSTATUS
4947 SampQueryUserFullName(PSAM_DB_OBJECT UserObject,
4948 PSAMPR_USER_INFO_BUFFER *Buffer)
4949 {
4950 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4951 NTSTATUS Status;
4952
4953 *Buffer = NULL;
4954
4955 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
4956 if (InfoBuffer == NULL)
4957 return STATUS_INSUFFICIENT_RESOURCES;
4958
4959 /* Get the FullName string */
4960 Status = SampGetObjectAttributeString(UserObject,
4961 L"FullName",
4962 &InfoBuffer->FullName.FullName);
4963 if (!NT_SUCCESS(Status))
4964 {
4965 TRACE("Status 0x%08lx\n", Status);
4966 goto done;
4967 }
4968
4969 *Buffer = InfoBuffer;
4970
4971 done:
4972 if (!NT_SUCCESS(Status))
4973 {
4974 if (InfoBuffer != NULL)
4975 {
4976 if (InfoBuffer->FullName.FullName.Buffer != NULL)
4977 midl_user_free(InfoBuffer->FullName.FullName.Buffer);
4978
4979 midl_user_free(InfoBuffer);
4980 }
4981 }
4982
4983 return Status;
4984 }
4985
4986
4987 static
4988 NTSTATUS
4989 SampQueryUserPrimaryGroup(PSAM_DB_OBJECT UserObject,
4990 PSAMPR_USER_INFO_BUFFER *Buffer)
4991 {
4992 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4993 SAM_USER_FIXED_DATA FixedData;
4994 ULONG Length = 0;
4995 NTSTATUS Status;
4996
4997 *Buffer = NULL;
4998
4999 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5000 if (InfoBuffer == NULL)
5001 return STATUS_INSUFFICIENT_RESOURCES;
5002
5003 Length = sizeof(SAM_USER_FIXED_DATA);
5004 Status = SampGetObjectAttribute(UserObject,
5005 L"F",
5006 NULL,
5007 (PVOID)&FixedData,
5008 &Length);
5009 if (!NT_SUCCESS(Status))
5010 goto done;
5011
5012 InfoBuffer->PrimaryGroup.PrimaryGroupId = FixedData.PrimaryGroupId;
5013
5014 *Buffer = InfoBuffer;
5015
5016 done:
5017 if (!NT_SUCCESS(Status))
5018 {
5019 if (InfoBuffer != NULL)
5020 {
5021 midl_user_free(InfoBuffer);
5022 }
5023 }
5024
5025 return Status;
5026 }
5027
5028
5029 static NTSTATUS
5030 SampQueryUserHome(PSAM_DB_OBJECT UserObject,
5031 PSAMPR_USER_INFO_BUFFER *Buffer)
5032 {
5033 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5034 NTSTATUS Status;
5035
5036 *Buffer = NULL;
5037
5038 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5039 if (InfoBuffer == NULL)
5040 return STATUS_INSUFFICIENT_RESOURCES;
5041
5042 /* Get the HomeDirectory string */
5043 Status = SampGetObjectAttributeString(UserObject,
5044 L"HomeDirectory",
5045 &InfoBuffer->Home.HomeDirectory);
5046 if (!NT_SUCCESS(Status))
5047 {
5048 TRACE("Status 0x%08lx\n", Status);
5049 goto done;
5050 }
5051
5052 /* Get the HomeDirectoryDrive string */
5053 Status = SampGetObjectAttributeString(UserObject,
5054 L"HomeDirectoryDrive",
5055 &InfoBuffer->Home.HomeDirectoryDrive);
5056 if (!NT_SUCCESS(Status))
5057 {
5058 TRACE("Status 0x%08lx\n", Status);
5059 goto done;
5060 }
5061
5062 *Buffer = InfoBuffer;
5063
5064 done:
5065 if (!NT_SUCCESS(Status))
5066 {
5067 if (InfoBuffer != NULL)
5068 {
5069 if (InfoBuffer->Home.HomeDirectory.Buffer != NULL)
5070 midl_user_free(InfoBuffer->Home.HomeDirectory.Buffer);
5071
5072 if (InfoBuffer->Home.HomeDirectoryDrive.Buffer != NULL)
5073 midl_user_free(InfoBuffer->Home.HomeDirectoryDrive.Buffer);
5074
5075 midl_user_free(InfoBuffer);
5076 }
5077 }
5078
5079 return Status;
5080 }
5081
5082
5083 static NTSTATUS
5084 SampQueryUserScript(PSAM_DB_OBJECT UserObject,
5085 PSAMPR_USER_INFO_BUFFER *Buffer)
5086 {
5087 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5088 NTSTATUS Status;
5089
5090 *Buffer = NULL;
5091
5092 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5093 if (InfoBuffer == NULL)
5094 return STATUS_INSUFFICIENT_RESOURCES;
5095
5096 /* Get the ScriptPath string */
5097 Status = SampGetObjectAttributeString(UserObject,
5098 L"ScriptPath",
5099 &InfoBuffer->Script.ScriptPath);
5100 if (!NT_SUCCESS(Status))
5101 {
5102 TRACE("Status 0x%08lx\n", Status);
5103 goto done;
5104 }
5105
5106 *Buffer = InfoBuffer;
5107
5108 done:
5109 if (!NT_SUCCESS(Status))
5110 {
5111 if (InfoBuffer != NULL)
5112 {
5113 if (InfoBuffer->Script.ScriptPath.Buffer != NULL)
5114 midl_user_free(InfoBuffer->Script.ScriptPath.Buffer);
5115
5116 midl_user_free(InfoBuffer);
5117 }
5118 }
5119
5120 return Status;
5121 }
5122
5123
5124 static NTSTATUS
5125 SampQueryUserProfile(PSAM_DB_OBJECT UserObject,
5126 PSAMPR_USER_INFO_BUFFER *Buffer)
5127 {
5128 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5129 NTSTATUS Status;
5130
5131 *Buffer = NULL;
5132
5133 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5134 if (InfoBuffer == NULL)
5135 return STATUS_INSUFFICIENT_RESOURCES;
5136
5137 /* Get the ProfilePath string */
5138 Status = SampGetObjectAttributeString(UserObject,
5139 L"ProfilePath",
5140 &InfoBuffer->Profile.ProfilePath);
5141 if (!NT_SUCCESS(Status))
5142 {
5143 TRACE("Status 0x%08lx\n", Status);
5144 goto done;
5145 }
5146
5147 *Buffer = InfoBuffer;
5148
5149 done:
5150 if (!NT_SUCCESS(Status))
5151 {
5152 if (InfoBuffer != NULL)
5153 {
5154 if (InfoBuffer->Profile.ProfilePath.Buffer != NULL)
5155 midl_user_free(InfoBuffer->Profile.ProfilePath.Buffer);
5156
5157 midl_user_free(InfoBuffer);
5158 }
5159 }
5160
5161 return Status;
5162 }
5163
5164
5165 static NTSTATUS
5166 SampQueryUserAdminComment(PSAM_DB_OBJECT UserObject,
5167 PSAMPR_USER_INFO_BUFFER *Buffer)
5168 {
5169 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5170 NTSTATUS Status;
5171
5172 *Buffer = NULL;
5173
5174 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5175 if (InfoBuffer == NULL)
5176 return STATUS_INSUFFICIENT_RESOURCES;
5177
5178 /* Get the AdminComment string */
5179 Status = SampGetObjectAttributeString(UserObject,
5180 L"AdminComment",
5181 &InfoBuffer->AdminComment.AdminComment);
5182 if (!NT_SUCCESS(Status))
5183 {
5184 TRACE("Status 0x%08lx\n", Status);
5185 goto done;
5186 }
5187
5188 *Buffer = InfoBuffer;
5189
5190 done:
5191 if (!NT_SUCCESS(Status))
5192 {
5193 if (InfoBuffer != NULL)
5194 {
5195 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
5196 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
5197
5198 midl_user_free(InfoBuffer);
5199 }
5200 }
5201
5202 return Status;
5203 }
5204
5205
5206 static NTSTATUS
5207 SampQueryUserWorkStations(PSAM_DB_OBJECT UserObject,
5208 PSAMPR_USER_INFO_BUFFER *Buffer)
5209 {
5210 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5211 NTSTATUS Status;
5212
5213 *Buffer = NULL;
5214
5215 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5216 if (InfoBuffer == NULL)
5217 return STATUS_INSUFFICIENT_RESOURCES;
5218
5219 /* Get the WorkStations string */
5220 Status = SampGetObjectAttributeString(UserObject,
5221 L"WorkStations",
5222 &InfoBuffer->WorkStations.WorkStations);
5223 if (!NT_SUCCESS(Status))
5224 {
5225 TRACE("Status 0x%08lx\n", Status);
5226 goto done;
5227 }
5228
5229 *Buffer = InfoBuffer;
5230
5231 done:
5232 if (!NT_SUCCESS(Status))
5233 {
5234 if (InfoBuffer != NULL)
5235 {
5236 if (InfoBuffer->WorkStations.WorkStations.Buffer != NULL)
5237 midl_user_free(InfoBuffer->WorkStations.WorkStations.Buffer);
5238
5239 midl_user_free(InfoBuffer);
5240 }
5241 }
5242
5243 return Status;
5244 }
5245
5246
5247 static
5248 NTSTATUS
5249 SampQueryUserControl(PSAM_DB_OBJECT UserObject,
5250 PSAMPR_USER_INFO_BUFFER *Buffer)
5251 {
5252 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5253 SAM_USER_FIXED_DATA FixedData;
5254 ULONG Length = 0;
5255 NTSTATUS Status;
5256
5257 *Buffer = NULL;
5258
5259 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5260 if (InfoBuffer == NULL)
5261 return STATUS_INSUFFICIENT_RESOURCES;
5262
5263 Length = sizeof(SAM_USER_FIXED_DATA);
5264 Status = SampGetObjectAttribute(UserObject,
5265 L"F",
5266 NULL,
5267 (PVOID)&FixedData,
5268 &Length);
5269 if (!NT_SUCCESS(Status))
5270 goto done;
5271
5272 InfoBuffer->Control.UserAccountControl = FixedData.UserAccountControl;
5273
5274 *Buffer = InfoBuffer;
5275
5276 done:
5277 if (!NT_SUCCESS(Status))
5278 {
5279 if (InfoBuffer != NULL)
5280 {
5281 midl_user_free(InfoBuffer);
5282 }
5283 }
5284
5285 return Status;
5286 }
5287
5288
5289 static
5290 NTSTATUS
5291 SampQueryUserExpires(PSAM_DB_OBJECT UserObject,
5292 PSAMPR_USER_INFO_BUFFER *Buffer)
5293 {
5294 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5295 SAM_USER_FIXED_DATA FixedData;
5296 ULONG Length = 0;
5297 NTSTATUS Status;
5298
5299 *Buffer = NULL;
5300
5301 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5302 if (InfoBuffer == NULL)
5303 return STATUS_INSUFFICIENT_RESOURCES;
5304
5305 Length = sizeof(SAM_USER_FIXED_DATA);
5306 Status = SampGetObjectAttribute(UserObject,
5307 L"F",
5308 NULL,
5309 (PVOID)&FixedData,
5310 &Length);
5311 if (!NT_SUCCESS(Status))
5312 goto done;
5313
5314 InfoBuffer->Expires.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
5315 InfoBuffer->Expires.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
5316
5317 *Buffer = InfoBuffer;
5318
5319 done:
5320 if (!NT_SUCCESS(Status))
5321 {
5322 if (InfoBuffer != NULL)
5323 {
5324 midl_user_free(InfoBuffer);
5325 }
5326 }
5327
5328 return Status;
5329 }
5330
5331
5332 /* Function 36 */
5333 NTSTATUS
5334 NTAPI
5335 SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
5336 IN USER_INFORMATION_CLASS UserInformationClass,
5337 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
5338 {
5339 PSAM_DB_OBJECT UserObject;
5340 ACCESS_MASK DesiredAccess;
5341 NTSTATUS Status;
5342
5343 TRACE("SamrQueryInformationUser(%p %lu %p)\n",
5344 UserHandle, UserInformationClass, Buffer);
5345
5346 switch (UserInformationClass)
5347 {
5348 case UserGeneralInformation:
5349 case UserNameInformation:
5350 case UserAccountNameInformation:
5351 case UserFullNameInformation:
5352 case UserPrimaryGroupInformation:
5353 case UserAdminCommentInformation:
5354 DesiredAccess = USER_READ_GENERAL;
5355 break;
5356
5357 case UserLogonHoursInformation:
5358 case UserHomeInformation:
5359 case UserScriptInformation:
5360 case UserProfileInformation:
5361 case UserWorkStationsInformation:
5362 DesiredAccess = USER_READ_LOGON;
5363 break;
5364
5365 case UserControlInformation:
5366 case UserExpiresInformation:
5367 DesiredAccess = USER_READ_ACCOUNT;
5368 break;
5369
5370 case UserPreferencesInformation:
5371 DesiredAccess = USER_READ_GENERAL |
5372 USER_READ_PREFERENCES;
5373 break;
5374
5375 case UserLogonInformation:
5376 case UserAccountInformation:
5377 DesiredAccess = USER_READ_GENERAL |
5378 USER_READ_PREFERENCES |
5379 USER_READ_LOGON |
5380 USER_READ_ACCOUNT;
5381 break;
5382
5383 default:
5384 return STATUS_INVALID_INFO_CLASS;
5385 }
5386
5387 /* Validate the domain handle */
5388 Status = SampValidateDbObject(UserHandle,
5389 SamDbUserObject,
5390 DesiredAccess,
5391 &UserObject);
5392 if (!NT_SUCCESS(Status))
5393 {
5394 TRACE("failed with status 0x%08lx\n", Status);
5395 return Status;
5396 }
5397
5398 switch (UserInformationClass)
5399 {
5400 case UserGeneralInformation:
5401 Status = SampQueryUserGeneral(UserObject,
5402 Buffer);
5403 break;
5404
5405 case UserPreferencesInformation:
5406 Status = SampQueryUserPreferences(UserObject,
5407 Buffer);
5408 break;
5409
5410 case UserLogonInformation:
5411 Status = SampQueryUserLogon(UserObject,
5412 Buffer);
5413 break;
5414
5415 // case UserLogonHoursInformation:
5416 // Status = SampQueryUserLogonHours(UserObject,
5417 // Buffer);
5418 // break;
5419
5420 case UserAccountInformation:
5421 Status = SampQueryUserAccount(UserObject,
5422 Buffer);
5423 break;
5424
5425 case UserNameInformation:
5426 Status = SampQueryUserName(UserObject,
5427 Buffer);
5428 break;
5429
5430 case UserAccountNameInformation:
5431 Status = SampQueryUserAccountName(UserObject,
5432 Buffer);
5433 break;
5434
5435 case UserFullNameInformation:
5436 Status = SampQueryUserFullName(UserObject,
5437 Buffer);
5438 break;
5439
5440 case UserPrimaryGroupInformation:
5441 Status = SampQueryUserPrimaryGroup(UserObject,
5442 Buffer);
5443 break;
5444
5445 case UserHomeInformation:
5446 Status = SampQueryUserHome(UserObject,
5447 Buffer);
5448
5449 case UserScriptInformation:
5450 Status = SampQueryUserScript(UserObject,
5451 Buffer);
5452 break;
5453
5454 case UserProfileInformation:
5455 Status = SampQueryUserProfile(UserObject,
5456 Buffer);
5457 break;
5458
5459 case UserAdminCommentInformation:
5460 Status = SampQueryUserAdminComment(UserObject,
5461 Buffer);
5462 break;
5463
5464 case UserWorkStationsInformation:
5465 Status = SampQueryUserWorkStations(UserObject,
5466 Buffer);
5467 break;
5468
5469 case UserControlInformation:
5470 Status = SampQueryUserControl(UserObject,
5471 Buffer);
5472 break;
5473
5474 case UserExpiresInformation:
5475 Status = SampQueryUserExpires(UserObject,
5476 Buffer);
5477 break;
5478
5479 default:
5480 Status = STATUS_INVALID_INFO_CLASS;
5481 }
5482
5483 return Status;
5484 }
5485
5486
5487 static NTSTATUS
5488 SampSetUserGeneral(PSAM_DB_OBJECT UserObject,
5489 PSAMPR_USER_INFO_BUFFER Buffer)
5490 {
5491 SAM_USER_FIXED_DATA FixedData;
5492 ULONG Length = 0;
5493 NTSTATUS Status;
5494
5495 Length = sizeof(SAM_USER_FIXED_DATA);
5496 Status = SampGetObjectAttribute(UserObject,
5497 L"F",
5498 NULL,
5499 (PVOID)&FixedData,
5500 &Length);
5501 if (!NT_SUCCESS(Status))
5502 goto done;
5503
5504 FixedData.PrimaryGroupId = Buffer->General.PrimaryGroupId;
5505
5506 Status = SampSetObjectAttribute(UserObject,
5507 L"F",
5508 REG_BINARY,
5509 &FixedData,
5510 Length);
5511 if (!NT_SUCCESS(Status))
5512 goto done;
5513
5514 Status = SampSetObjectAttribute(UserObject,
5515 L"Name",
5516 REG_SZ,
5517 Buffer->General.UserName.Buffer,
5518 Buffer->General.UserName.MaximumLength);
5519 if (!NT_SUCCESS(Status))
5520 goto done;
5521
5522 Status = SampSetObjectAttribute(UserObject,
5523 L"FullName",
5524 REG_SZ,
5525 Buffer->General.FullName.Buffer,
5526 Buffer->General.FullName.MaximumLength);
5527 if (!NT_SUCCESS(Status))
5528 goto done;
5529
5530 Status = SampSetObjectAttribute(UserObject,
5531 L"AdminComment",
5532 REG_SZ,
5533 Buffer->General.AdminComment.Buffer,
5534 Buffer->General.AdminComment.MaximumLength);
5535 if (!NT_SUCCESS(Status))
5536 goto done;
5537
5538 Status = SampSetObjectAttribute(UserObject,
5539 L"UserComment",
5540 REG_SZ,
5541 Buffer->General.UserComment.Buffer,
5542 Buffer->General.UserComment.MaximumLength);
5543
5544 done:
5545 return Status;
5546 }
5547
5548
5549 static NTSTATUS
5550 SampSetUserPreferences(PSAM_DB_OBJECT UserObject,
5551 PSAMPR_USER_INFO_BUFFER Buffer)
5552 {
5553 SAM_USER_FIXED_DATA FixedData;
5554 ULONG Length = 0;
5555 NTSTATUS Status;
5556
5557 Length = sizeof(SAM_USER_FIXED_DATA);
5558 Status = SampGetObjectAttribute(UserObject,
5559 L"F",
5560 NULL,
5561 (PVOID)&FixedData,
5562 &Length);
5563 if (!NT_SUCCESS(Status))
5564 goto done;
5565
5566 FixedData.CountryCode = Buffer->Preferences.CountryCode;
5567 FixedData.CodePage = Buffer->Preferences.CodePage;
5568
5569 Status = SampSetObjectAttribute(UserObject,
5570 L"F",
5571 REG_BINARY,
5572 &FixedData,
5573 Length);
5574 if (!NT_SUCCESS(Status))
5575 goto done;
5576
5577 Status = SampSetObjectAttribute(UserObject,
5578 L"UserComment",
5579 REG_SZ,
5580 Buffer->Preferences.UserComment.Buffer,
5581 Buffer->Preferences.UserComment.MaximumLength);
5582
5583 done:
5584 return Status;
5585 }
5586
5587
5588 static NTSTATUS
5589 SampSetUserPrimaryGroup(PSAM_DB_OBJECT UserObject,
5590 PSAMPR_USER_INFO_BUFFER Buffer)
5591 {
5592 SAM_USER_FIXED_DATA FixedData;
5593 ULONG Length = 0;
5594 NTSTATUS Status;
5595
5596 Length = sizeof(SAM_USER_FIXED_DATA);
5597 Status = SampGetObjectAttribute(UserObject,
5598 L"F",
5599 NULL,
5600 (PVOID)&FixedData,
5601 &Length);
5602 if (!NT_SUCCESS(Status))
5603 goto done;
5604
5605 FixedData.PrimaryGroupId = Buffer->PrimaryGroup.PrimaryGroupId;
5606
5607 Status = SampSetObjectAttribute(UserObject,
5608 L"F",
5609 REG_BINARY,
5610 &FixedData,
5611 Length);
5612
5613 done:
5614 return Status;
5615 }
5616
5617
5618 static NTSTATUS
5619 SampSetUserControl(PSAM_DB_OBJECT UserObject,
5620 PSAMPR_USER_INFO_BUFFER Buffer)
5621 {
5622 SAM_USER_FIXED_DATA FixedData;
5623 ULONG Length = 0;
5624 NTSTATUS Status;
5625
5626 Length = sizeof(SAM_USER_FIXED_DATA);
5627 Status = SampGetObjectAttribute(UserObject,
5628 L"F",
5629 NULL,
5630 (PVOID)&FixedData,
5631 &Length);
5632 if (!NT_SUCCESS(Status))
5633 goto done;
5634
5635 FixedData.UserAccountControl = Buffer->Control.UserAccountControl;
5636
5637 Status = SampSetObjectAttribute(UserObject,
5638 L"F",
5639 REG_BINARY,
5640 &FixedData,
5641 Length);
5642
5643 done:
5644 return Status;
5645 }
5646
5647
5648 static NTSTATUS
5649 SampSetUserExpires(PSAM_DB_OBJECT UserObject,
5650 PSAMPR_USER_INFO_BUFFER Buffer)
5651 {
5652 SAM_USER_FIXED_DATA FixedData;
5653 ULONG Length = 0;
5654 NTSTATUS Status;
5655
5656 Length = sizeof(SAM_USER_FIXED_DATA);
5657 Status = SampGetObjectAttribute(UserObject,
5658 L"F",
5659 NULL,
5660 (PVOID)&FixedData,
5661 &Length);
5662 if (!NT_SUCCESS(Status))
5663 goto done;
5664
5665 FixedData.AccountExpires.LowPart = Buffer->Expires.AccountExpires.LowPart;
5666 FixedData.AccountExpires.HighPart = Buffer->Expires.AccountExpires.HighPart;
5667
5668 Status = SampSetObjectAttribute(UserObject,
5669 L"F",
5670 REG_BINARY,
5671 &FixedData,
5672 Length);
5673
5674 done:
5675 return Status;
5676 }
5677
5678
5679 /* Function 37 */
5680 NTSTATUS
5681 NTAPI
5682 SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
5683 IN USER_INFORMATION_CLASS UserInformationClass,
5684 IN PSAMPR_USER_INFO_BUFFER Buffer)
5685 {
5686 PSAM_DB_OBJECT UserObject;
5687 ACCESS_MASK DesiredAccess;
5688 NTSTATUS Status;
5689
5690 TRACE("SamrSetInformationUser(%p %lu %p)\n",
5691 UserHandle, UserInformationClass, Buffer);
5692
5693 switch (UserInformationClass)
5694 {
5695 case UserLogonHoursInformation:
5696 case UserNameInformation:
5697 case UserAccountNameInformation:
5698 case UserFullNameInformation:
5699 case UserPrimaryGroupInformation:
5700 case UserHomeInformation:
5701 case UserScriptInformation:
5702 case UserProfileInformation:
5703 case UserAdminCommentInformation:
5704 case UserWorkStationsInformation:
5705 case UserControlInformation:
5706 case UserExpiresInformation:
5707 DesiredAccess = USER_WRITE_ACCOUNT;
5708 break;
5709
5710 case UserGeneralInformation:
5711 DesiredAccess = USER_WRITE_ACCOUNT |
5712 USER_WRITE_PREFERENCES;
5713 break;
5714
5715 case UserPreferencesInformation:
5716 DesiredAccess = USER_WRITE_PREFERENCES;
5717 break;
5718
5719 case UserSetPasswordInformation:
5720 DesiredAccess = USER_FORCE_PASSWORD_CHANGE;
5721 break;
5722
5723 default:
5724 return STATUS_INVALID_INFO_CLASS;
5725 }
5726
5727 /* Validate the domain handle */
5728 Status = SampValidateDbObject(UserHandle,
5729 SamDbUserObject,
5730 DesiredAccess,
5731 &UserObject);
5732 if (!NT_SUCCESS(Status))
5733 {
5734 TRACE("failed with status 0x%08lx\n", Status);
5735 return Status;
5736 }
5737
5738 switch (UserInformationClass)
5739 {
5740 case UserGeneralInformation:
5741 Status = SampSetUserGeneral(UserObject,
5742 Buffer);
5743 break;
5744
5745 case UserPreferencesInformation:
5746 Status = SampSetUserPreferences(UserObject,
5747 Buffer);
5748 break;
5749 /*
5750 case UserLogonHoursInformation:
5751 Status = SampSetUserLogonHours(UserObject,
5752 Buffer);
5753 break;
5754 */
5755 case UserNameInformation:
5756 Status = SampSetObjectAttribute(UserObject,
5757 L"Name",
5758 REG_SZ,
5759 Buffer->Name.UserName.Buffer,
5760 Buffer->Name.UserName.MaximumLength);
5761 if (!NT_SUCCESS(Status))
5762 break;
5763
5764 Status = SampSetObjectAttribute(UserObject,
5765 L"FullName",
5766 REG_SZ,
5767 Buffer->Name.FullName.Buffer,
5768 Buffer->Name.FullName.MaximumLength);
5769 break;
5770
5771 case UserAccountNameInformation:
5772 Status = SampSetObjectAttribute(UserObject,
5773 L"Name",
5774 REG_SZ,
5775 Buffer->AccountName.UserName.Buffer,
5776 Buffer->AccountName.UserName.MaximumLength);
5777 break;
5778
5779 case UserFullNameInformation:
5780 Status = SampSetObjectAttribute(UserObject,
5781 L"FullName",
5782 REG_SZ,
5783 Buffer->FullName.FullName.Buffer,
5784 Buffer->FullName.FullName.MaximumLength);
5785 break;
5786
5787 case UserPrimaryGroupInformation:
5788 Status = SampSetUserPrimaryGroup(UserObject,
5789 Buffer);
5790 break;
5791
5792 case UserHomeInformation:
5793 Status = SampSetObjectAttribute(UserObject,
5794 L"HomeDirectory",
5795 REG_SZ,
5796 Buffer->Home.HomeDirectory.Buffer,
5797 Buffer->Home.HomeDirectory.MaximumLength);
5798 if (!NT_SUCCESS(Status))
5799 break;
5800
5801 Status = SampSetObjectAttribute(UserObject,
5802 L"HomeDirectoryDrive",
5803 REG_SZ,
5804 Buffer->Home.HomeDirectoryDrive.Buffer,
5805 Buffer->Home.HomeDirectoryDrive.MaximumLength);
5806 break;
5807
5808 case UserScriptInformation:
5809 Status = SampSetObjectAttribute(UserObject,
5810 L"ScriptPath",
5811 REG_SZ,
5812 Buffer->Script.ScriptPath.Buffer,
5813 Buffer->Script.ScriptPath.MaximumLength);
5814 break;
5815
5816 case UserProfileInformation:
5817 Status = SampSetObjectAttribute(UserObject,
5818 L"ProfilePath",
5819 REG_SZ,
5820 Buffer->Profile.ProfilePath.Buffer,
5821 Buffer->Profile.ProfilePath.MaximumLength);
5822 break;
5823
5824 case UserAdminCommentInformation:
5825 Status = SampSetObjectAttribute(UserObject,
5826 L"AdminComment",
5827 REG_SZ,
5828 Buffer->AdminComment.AdminComment.Buffer,
5829 Buffer->AdminComment.AdminComment.MaximumLength);
5830 break;
5831
5832 case UserWorkStationsInformation:
5833 Status = SampSetObjectAttribute(UserObject,
5834 L"WorkStations",
5835 REG_SZ,
5836 Buffer->WorkStations.WorkStations.Buffer,
5837 Buffer->WorkStations.WorkStations.MaximumLength);
5838 break;
5839
5840 case UserSetPasswordInformation:
5841 TRACE("Password: %S\n", Buffer->SetPassword.Password.Buffer);
5842 TRACE("PasswordExpired: %d\n", Buffer->SetPassword.PasswordExpired);
5843
5844 Status = SampSetObjectAttribute(UserObject,
5845 L"Password",
5846 REG_SZ,
5847 Buffer->SetPassword.Password.Buffer,
5848 Buffer->SetPassword.Password.MaximumLength);
5849 break;
5850
5851 case UserControlInformation:
5852 Status = SampSetUserControl(UserObject,
5853 Buffer);
5854 break;
5855
5856 case UserExpiresInformation:
5857 Status = SampSetUserExpires(UserObject,
5858 Buffer);
5859 break;
5860
5861 // case UserInternal1Information:
5862 // case UserParametersInformation:
5863 // case UserAllInformation:
5864 // case UserInternal4Information:
5865 // case UserInternal5Information:
5866 // case UserInternal4InformationNew:
5867 // case UserInternal5InformationNew:
5868
5869 default:
5870 Status = STATUS_INVALID_INFO_CLASS;
5871 }
5872
5873 return Status;
5874 }
5875
5876 /* Function 38 */
5877 NTSTATUS
5878 NTAPI
5879 SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
5880 IN unsigned char LmPresent,
5881 IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm,
5882 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm,
5883 IN unsigned char NtPresent,
5884 IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt,
5885 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt,
5886 IN unsigned char NtCrossEncryptionPresent,
5887 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm,
5888 IN unsigned char LmCrossEncryptionPresent,
5889 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt)
5890 {
5891 UNIMPLEMENTED;
5892 return STATUS_NOT_IMPLEMENTED;
5893 }
5894
5895 /* Function 39 */
5896 NTSTATUS
5897 NTAPI
5898 SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle,
5899 OUT PSAMPR_GET_GROUPS_BUFFER *Groups)
5900 {
5901 UNIMPLEMENTED;
5902 return STATUS_NOT_IMPLEMENTED;
5903 }
5904
5905 /* Function 40 */
5906 NTSTATUS
5907 NTAPI
5908 SamrQueryDisplayInformation(IN SAMPR_HANDLE DomainHandle,
5909 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
5910 IN unsigned long Index,
5911 IN unsigned long EntryCount,
5912 IN unsigned long PreferredMaximumLength,
5913 OUT unsigned long *TotalAvailable,
5914 OUT unsigned long *TotalReturned,
5915 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
5916 {
5917 UNIMPLEMENTED;
5918 return STATUS_NOT_IMPLEMENTED;
5919 }
5920
5921 /* Function 41 */
5922 NTSTATUS
5923 NTAPI
5924 SamrGetDisplayEnumerationIndex(IN SAMPR_HANDLE DomainHandle,
5925 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
5926 IN PRPC_UNICODE_STRING Prefix,
5927 OUT unsigned long *Index)
5928 {
5929 UNIMPLEMENTED;
5930 return STATUS_NOT_IMPLEMENTED;
5931 }
5932
5933 /* Function 42 */
5934 NTSTATUS
5935 NTAPI
5936 SamrTestPrivateFunctionsDomain(IN SAMPR_HANDLE DomainHandle)
5937 {
5938 UNIMPLEMENTED;
5939 return STATUS_NOT_IMPLEMENTED;
5940 }
5941
5942 /* Function 43 */
5943 NTSTATUS
5944 NTAPI
5945 SamrTestPrivateFunctionsUser(IN SAMPR_HANDLE UserHandle)
5946 {
5947 UNIMPLEMENTED;
5948 return STATUS_NOT_IMPLEMENTED;
5949 }
5950
5951 /* Function 44 */
5952 NTSTATUS
5953 NTAPI
5954 SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
5955 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
5956 {
5957 UNIMPLEMENTED;
5958 return STATUS_NOT_IMPLEMENTED;
5959 }
5960
5961 /* Function 45 */
5962 NTSTATUS
5963 NTAPI
5964 SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
5965 IN PRPC_SID MemberSid)
5966 {
5967 UNIMPLEMENTED;
5968 return STATUS_NOT_IMPLEMENTED;
5969 }
5970
5971 /* Function 46 */
5972 NTSTATUS
5973 NTAPI
5974 SamrQueryInformationDomain2(IN SAMPR_HANDLE DomainHandle,
5975 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
5976 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
5977 {
5978 UNIMPLEMENTED;
5979 return STATUS_NOT_IMPLEMENTED;
5980 }
5981
5982 /* Function 47 */
5983 NTSTATUS
5984 NTAPI
5985 SamrQueryInformationUser2(IN SAMPR_HANDLE UserHandle,
5986 IN USER_INFORMATION_CLASS UserInformationClass,
5987 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
5988 {
5989 UNIMPLEMENTED;
5990 return STATUS_NOT_IMPLEMENTED;
5991 }
5992
5993 /* Function 48 */
5994 NTSTATUS
5995 NTAPI
5996 SamrQueryDisplayInformation2(IN SAMPR_HANDLE DomainHandle,
5997 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
5998 IN unsigned long Index,
5999 IN unsigned long EntryCount,
6000 IN unsigned long PreferredMaximumLength,
6001 OUT unsigned long *TotalAvailable,
6002 OUT unsigned long *TotalReturned,
6003 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
6004 {
6005 UNIMPLEMENTED;
6006 return STATUS_NOT_IMPLEMENTED;
6007 }
6008
6009 /* Function 49 */
6010 NTSTATUS
6011 NTAPI
6012 SamrGetDisplayEnumerationIndex2(IN SAMPR_HANDLE DomainHandle,
6013 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
6014 IN PRPC_UNICODE_STRING Prefix,
6015 OUT unsigned long *Index)
6016 {
6017 UNIMPLEMENTED;
6018 return STATUS_NOT_IMPLEMENTED;
6019 }
6020
6021
6022 /* Function 50 */
6023 NTSTATUS
6024 NTAPI
6025 SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
6026 IN PRPC_UNICODE_STRING Name,
6027 IN unsigned long AccountType,
6028 IN ACCESS_MASK DesiredAccess,
6029 OUT SAMPR_HANDLE *UserHandle,
6030 OUT unsigned long *GrantedAccess,
6031 OUT unsigned long *RelativeId)
6032 {
6033 UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
6034 SAM_DOMAIN_FIXED_DATA FixedDomainData;
6035 SAM_USER_FIXED_DATA FixedUserData;
6036 PSAM_DB_OBJECT DomainObject;
6037 PSAM_DB_OBJECT UserObject;
6038 ULONG ulSize;
6039 ULONG ulRid;
6040 WCHAR szRid[9];
6041 NTSTATUS Status;
6042
6043 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
6044 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
6045
6046 if (Name == NULL ||
6047 Name->Length == 0 ||
6048 Name->Buffer == NULL ||
6049 UserHandle == NULL ||
6050 RelativeId == NULL)
6051 return STATUS_INVALID_PARAMETER;
6052
6053 /* Check for valid account type */
6054 if (AccountType != USER_NORMAL_ACCOUNT &&
6055 AccountType != USER_WORKSTATION_TRUST_ACCOUNT &&
6056 AccountType != USER_INTERDOMAIN_TRUST_ACCOUNT &&
6057 AccountType != USER_SERVER_TRUST_ACCOUNT &&
6058 AccountType != USER_TEMP_DUPLICATE_ACCOUNT)
6059 return STATUS_INVALID_PARAMETER;
6060
6061 /* Validate the domain handle */
6062 Status = SampValidateDbObject(DomainHandle,
6063 SamDbDomainObject,
6064 DOMAIN_CREATE_USER,
6065 &DomainObject);
6066 if (!NT_SUCCESS(Status))
6067 {
6068 TRACE("failed with status 0x%08lx\n", Status);
6069 return Status;
6070 }
6071
6072 /* Check if the user name already exists in the domain */
6073 Status = SampCheckAccountNameInDomain(DomainObject,
6074 Name->Buffer);
6075 if (!NT_SUCCESS(Status))
6076 {
6077 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
6078 Name->Buffer, Status);
6079 return Status;
6080 }
6081
6082 /* Get the fixed domain attributes */
6083 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
6084 Status = SampGetObjectAttribute(DomainObject,
6085 L"F",
6086 NULL,
6087 (PVOID)&FixedDomainData,
6088 &ulSize);
6089 if (!NT_SUCCESS(Status))
6090 {
6091 TRACE("failed with status 0x%08lx\n", Status);
6092 return Status;
6093 }
6094
6095 /* Increment the NextRid attribute */
6096 ulRid = FixedDomainData.NextRid;
6097 FixedDomainData.NextRid++;
6098
6099 /* Store the fixed domain attributes */
6100 Status = SampSetObjectAttribute(DomainObject,
6101 L"F",
6102 REG_BINARY,
6103 &FixedDomainData,
6104 ulSize);
6105 if (!NT_SUCCESS(Status))
6106 {
6107 TRACE("failed with status 0x%08lx\n", Status);
6108 return Status;
6109 }
6110
6111 TRACE("RID: %lx\n", ulRid);
6112
6113 /* Convert the RID into a string (hex) */
6114 swprintf(szRid, L"%08lX", ulRid);
6115
6116 /* Create the user object */
6117 Status = SampCreateDbObject(DomainObject,
6118 L"Users",
6119 szRid,
6120 SamDbUserObject,
6121 DesiredAccess,
6122 &UserObject);
6123 if (!NT_SUCCESS(Status))
6124 {
6125 TRACE("failed with status 0x%08lx\n", Status);
6126 return Status;
6127 }
6128
6129 /* Add the account name for the user object */
6130 Status = SampSetAccountNameInDomain(DomainObject,
6131 L"Users",
6132 Name->Buffer,
6133 ulRid);
6134 if (!NT_SUCCESS(Status))
6135 {
6136 TRACE("failed with status 0x%08lx\n", Status);
6137 return Status;
6138 }
6139
6140 /* Initialize fixed user data */
6141 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
6142 FixedUserData.Version = 1;
6143 FixedUserData.LastLogon.QuadPart = 0;
6144 FixedUserData.LastLogoff.QuadPart = 0;
6145 FixedUserData.PasswordLastSet.QuadPart = 0;
6146 FixedUserData.AccountExpires.LowPart = MAXULONG;
6147 FixedUserData.AccountExpires.HighPart = MAXLONG;
6148 FixedUserData.LastBadPasswordTime.QuadPart = 0;
6149 FixedUserData.UserId = ulRid;
6150 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
6151 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
6152 USER_PASSWORD_NOT_REQUIRED |
6153 AccountType;
6154
6155 /* Set fixed user data attribute */
6156 Status = SampSetObjectAttribute(UserObject,
6157 L"F",
6158 REG_BINARY,
6159 (LPVOID)&FixedUserData,
6160 sizeof(SAM_USER_FIXED_DATA));
6161 if (!NT_SUCCESS(Status))
6162 {
6163 TRACE("failed with status 0x%08lx\n", Status);
6164 return Status;
6165 }
6166
6167 /* Set the Name attribute */
6168 Status = SampSetObjectAttribute(UserObject,
6169 L"Name",
6170 REG_SZ,
6171 (LPVOID)Name->Buffer,
6172 Name->MaximumLength);
6173 if (!NT_SUCCESS(Status))
6174 {
6175 TRACE("failed with status 0x%08lx\n", Status);
6176 return Status;
6177 }
6178
6179 /* Set the FullName attribute */
6180 Status = SampSetObjectAttribute(UserObject,
6181 L"FullName",
6182 REG_SZ,
6183 EmptyString.Buffer,
6184 EmptyString.MaximumLength);
6185 if (!NT_SUCCESS(Status))
6186 {
6187 TRACE("failed with status 0x%08lx\n", Status);
6188 return Status;
6189 }
6190
6191 /* Set the HomeDirectory attribute */
6192 Status = SampSetObjectAttribute(UserObject,
6193 L"HomeDirectory",
6194 REG_SZ,
6195 EmptyString.Buffer,
6196 EmptyString.MaximumLength);
6197 if (!NT_SUCCESS(Status))
6198 {
6199 TRACE("failed with status 0x%08lx\n", Status);
6200 return Status;
6201 }
6202
6203 /* Set the HomeDirectoryDrive attribute */
6204 Status = SampSetObjectAttribute(UserObject,
6205 L"HomeDirectoryDrive",
6206 REG_SZ,
6207 EmptyString.Buffer,
6208 EmptyString.MaximumLength);
6209 if (!NT_SUCCESS(Status))
6210 {
6211 TRACE("failed with status 0x%08lx\n", Status);
6212 return Status;
6213 }
6214
6215 /* Set the ScriptPath attribute */
6216 Status = SampSetObjectAttribute(UserObject,
6217 L"ScriptPath",
6218 REG_SZ,
6219 EmptyString.Buffer,
6220 EmptyString.MaximumLength);
6221 if (!NT_SUCCESS(Status))
6222 {
6223 TRACE("failed with status 0x%08lx\n", Status);
6224 return Status;
6225 }
6226
6227 /* Set the ProfilePath attribute */
6228 Status = SampSetObjectAttribute(UserObject,
6229 L"ProfilePath",
6230 REG_SZ,
6231 EmptyString.Buffer,
6232 EmptyString.MaximumLength);
6233 if (!NT_SUCCESS(Status))
6234 {
6235 TRACE("failed with status 0x%08lx\n", Status);
6236 return Status;
6237 }
6238
6239 /* Set the AdminComment attribute */
6240 Status = SampSetObjectAttribute(UserObject,
6241 L"AdminComment",
6242 REG_SZ,
6243 EmptyString.Buffer,
6244 EmptyString.MaximumLength);
6245 if (!NT_SUCCESS(Status))
6246 {
6247 TRACE("failed with status 0x%08lx\n", Status);
6248 return Status;
6249 }
6250
6251 /* Set the UserComment attribute */
6252 Status = SampSetObjectAttribute(UserObject,
6253 L"UserComment",
6254 REG_SZ,
6255 EmptyString.Buffer,
6256 EmptyString.MaximumLength);
6257 if (!NT_SUCCESS(Status))
6258 {
6259 TRACE("failed with status 0x%08lx\n", Status);
6260 return Status;
6261 }
6262
6263 /* Set the WorkStations attribute */
6264 Status = SampSetObjectAttribute(UserObject,
6265 L"WorkStations",
6266 REG_SZ,
6267 EmptyString.Buffer,
6268 EmptyString.MaximumLength);
6269 if (!NT_SUCCESS(Status))
6270 {
6271 TRACE("failed with status 0x%08lx\n", Status);
6272 return Status;
6273 }
6274
6275 /* FIXME: Set default user attributes */
6276
6277 if (NT_SUCCESS(Status))
6278 {
6279 *UserHandle = (SAMPR_HANDLE)UserObject;
6280 *RelativeId = ulRid;
6281 *GrantedAccess = UserObject->Access;
6282 }
6283
6284 TRACE("returns with status 0x%08lx\n", Status);
6285
6286 return Status;
6287 }
6288
6289
6290 /* Function 51 */
6291 NTSTATUS
6292 NTAPI
6293 SamrQueryDisplayInformation3(IN SAMPR_HANDLE DomainHandle,
6294 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
6295 IN unsigned long Index,
6296 IN unsigned long EntryCount,
6297 IN unsigned long PreferredMaximumLength,
6298 OUT unsigned long *TotalAvailable,
6299 OUT unsigned long *TotalReturned,
6300 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
6301 {
6302 UNIMPLEMENTED;
6303 return STATUS_NOT_IMPLEMENTED;
6304 }
6305
6306
6307 /* Function 52 */
6308 NTSTATUS
6309 NTAPI
6310 SamrAddMultipleMembersToAlias(IN SAMPR_HANDLE AliasHandle,
6311 IN PSAMPR_PSID_ARRAY MembersBuffer)
6312 {
6313 ULONG i;
6314 NTSTATUS Status = STATUS_SUCCESS;
6315
6316 TRACE("SamrAddMultipleMembersToAlias(%p %p)\n",
6317 AliasHandle, MembersBuffer);
6318
6319 for (i = 0; i < MembersBuffer->Count; i++)
6320 {
6321 Status = SamrAddMemberToAlias(AliasHandle,
6322 ((PSID *)MembersBuffer->Sids)[i]);
6323
6324 if (Status == STATUS_MEMBER_IN_ALIAS)
6325 Status = STATUS_SUCCESS;
6326
6327 if (!NT_SUCCESS(Status))
6328 break;
6329 }
6330
6331 return Status;
6332 }
6333
6334
6335 /* Function 53 */
6336 NTSTATUS
6337 NTAPI
6338 SamrRemoveMultipleMembersFromAlias(IN SAMPR_HANDLE AliasHandle,
6339 IN PSAMPR_PSID_ARRAY MembersBuffer)
6340 {
6341 UNIMPLEMENTED;
6342 return STATUS_NOT_IMPLEMENTED;
6343 }
6344
6345 /* Function 54 */
6346 NTSTATUS
6347 NTAPI
6348 SamrOemChangePasswordUser2(IN handle_t BindingHandle,
6349 IN PRPC_STRING ServerName,
6350 IN PRPC_STRING UserName,
6351 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
6352 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewLm)
6353 {
6354 UNIMPLEMENTED;
6355 return STATUS_NOT_IMPLEMENTED;
6356 }
6357
6358 /* Function 55 */
6359 NTSTATUS
6360 NTAPI
6361 SamrUnicodeChangePasswordUser2(IN handle_t BindingHandle,
6362 IN PRPC_UNICODE_STRING ServerName,
6363 IN PRPC_UNICODE_STRING UserName,
6364 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldNt,
6365 IN PENCRYPTED_NT_OWF_PASSWORD OldNtOwfPasswordEncryptedWithNewNt,
6366 IN unsigned char LmPresent,
6367 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
6368 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewNt)
6369 {
6370 UNIMPLEMENTED;
6371 return STATUS_NOT_IMPLEMENTED;
6372 }
6373
6374 /* Function 56 */
6375 NTSTATUS
6376 NTAPI
6377 SamrGetDomainPasswordInformation(IN handle_t BindingHandle,
6378 IN PRPC_UNICODE_STRING Unused,
6379 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
6380 {
6381 UNIMPLEMENTED;
6382 return STATUS_NOT_IMPLEMENTED;
6383 }
6384
6385 /* Function 57 */
6386 NTSTATUS
6387 NTAPI
6388 SamrConnect2(IN PSAMPR_SERVER_NAME ServerName,
6389 OUT SAMPR_HANDLE *ServerHandle,
6390 IN ACCESS_MASK DesiredAccess)
6391 {
6392 UNIMPLEMENTED;
6393 return STATUS_NOT_IMPLEMENTED;
6394 }
6395
6396 /* Function 58 */
6397 NTSTATUS
6398 NTAPI
6399 SamrSetInformationUser2(IN SAMPR_HANDLE UserHandle,
6400 IN USER_INFORMATION_CLASS UserInformationClass,
6401 IN PSAMPR_USER_INFO_BUFFER Buffer)
6402 {
6403 UNIMPLEMENTED;
6404 return STATUS_NOT_IMPLEMENTED;
6405 }
6406
6407 /* Function 59 */
6408 NTSTATUS
6409 NTAPI
6410 SamrSetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
6411 {
6412 UNIMPLEMENTED;
6413 return STATUS_NOT_IMPLEMENTED;
6414 }
6415
6416 /* Function 60 */
6417 NTSTATUS
6418 NTAPI
6419 SamrGetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
6420 {
6421 UNIMPLEMENTED;
6422 return STATUS_NOT_IMPLEMENTED;
6423 }
6424
6425 /* Function 61 */
6426 NTSTATUS
6427 NTAPI
6428 SamrConnect3(IN handle_t BindingHandle) /* FIXME */
6429 {
6430 UNIMPLEMENTED;
6431 return STATUS_NOT_IMPLEMENTED;
6432 }
6433
6434 /* Function 62 */
6435 NTSTATUS
6436 NTAPI
6437 SamrConnect4(IN PSAMPR_SERVER_NAME ServerName,
6438 OUT SAMPR_HANDLE *ServerHandle,
6439 IN unsigned long ClientRevision,
6440 IN ACCESS_MASK DesiredAccess)
6441 {
6442 UNIMPLEMENTED;
6443 return STATUS_NOT_IMPLEMENTED;
6444 }
6445
6446 /* Function 63 */
6447 NTSTATUS
6448 NTAPI
6449 SamrUnicodeChangePasswordUser3(IN handle_t BindingHandle) /* FIXME */
6450 {
6451 UNIMPLEMENTED;
6452 return STATUS_NOT_IMPLEMENTED;
6453 }
6454
6455 /* Function 64 */
6456 NTSTATUS
6457 NTAPI
6458 SamrConnect5(IN PSAMPR_SERVER_NAME ServerName,
6459 IN ACCESS_MASK DesiredAccess,
6460 IN unsigned long InVersion,
6461 IN SAMPR_REVISION_INFO *InRevisionInfo,
6462 OUT unsigned long *OutVersion,
6463 OUT SAMPR_REVISION_INFO *OutRevisionInfo,
6464 OUT SAMPR_HANDLE *ServerHandle)
6465 {
6466 UNIMPLEMENTED;
6467 return STATUS_NOT_IMPLEMENTED;
6468 }
6469
6470 /* Function 65 */
6471 NTSTATUS
6472 NTAPI
6473 SamrRidToSid(IN SAMPR_HANDLE ObjectHandle,
6474 IN unsigned long Rid,
6475 OUT PRPC_SID *Sid)
6476 {
6477 UNIMPLEMENTED;
6478 return STATUS_NOT_IMPLEMENTED;
6479 }
6480
6481 /* Function 66 */
6482 NTSTATUS
6483 NTAPI
6484 SamrSetDSRMPassword(IN handle_t BindingHandle,
6485 IN PRPC_UNICODE_STRING Unused,
6486 IN unsigned long UserId,
6487 IN PENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword)
6488 {
6489 UNIMPLEMENTED;
6490 return STATUS_NOT_IMPLEMENTED;
6491 }
6492
6493 /* Function 67 */
6494 NTSTATUS
6495 NTAPI
6496 SamrValidatePassword(IN handle_t Handle,
6497 IN PASSWORD_POLICY_VALIDATION_TYPE ValidationType,
6498 IN PSAM_VALIDATE_INPUT_ARG InputArg,
6499 OUT PSAM_VALIDATE_OUTPUT_ARG *OutputArg)
6500 {
6501 UNIMPLEMENTED;
6502 return STATUS_NOT_IMPLEMENTED;
6503 }
6504
6505 /* EOF */