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