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