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