Sync with trunk r58151 to bring the latest changes from Amine and Timo.
[reactos.git] / dll / win32 / samsrv / samrpc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Security Account Manager (SAM) Server
4 * FILE: reactos/dll/win32/samsrv/samrpc.c
5 * PURPOSE: RPC interface functions
6 *
7 * PROGRAMMERS: Eric Kohl
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include "samsrv.h"
13
14 WINE_DEFAULT_DEBUG_CHANNEL(samsrv);
15
16 /* GLOBALS *******************************************************************/
17
18 static SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
19
20 static GENERIC_MAPPING ServerMapping =
21 {
22 SAM_SERVER_READ,
23 SAM_SERVER_WRITE,
24 SAM_SERVER_EXECUTE,
25 SAM_SERVER_ALL_ACCESS
26 };
27
28 static GENERIC_MAPPING DomainMapping =
29 {
30 DOMAIN_READ,
31 DOMAIN_WRITE,
32 DOMAIN_EXECUTE,
33 DOMAIN_ALL_ACCESS
34 };
35
36 static GENERIC_MAPPING AliasMapping =
37 {
38 ALIAS_READ,
39 ALIAS_WRITE,
40 ALIAS_EXECUTE,
41 ALIAS_ALL_ACCESS
42 };
43
44 static GENERIC_MAPPING GroupMapping =
45 {
46 GROUP_READ,
47 GROUP_WRITE,
48 GROUP_EXECUTE,
49 GROUP_ALL_ACCESS
50 };
51
52 static GENERIC_MAPPING UserMapping =
53 {
54 USER_READ,
55 USER_WRITE,
56 USER_EXECUTE,
57 USER_ALL_ACCESS
58 };
59
60
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 HANDLE MembersKeyHandle = NULL;
3597 SAM_GROUP_FIXED_DATA FixedData;
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 /* Open the Members subkey */
3637 Status = SampRegOpenKey(GroupObject->KeyHandle,
3638 L"Members",
3639 KEY_READ,
3640 &MembersKeyHandle);
3641 if (!NT_SUCCESS(Status))
3642 {
3643 TRACE("Status 0x%08lx\n", Status);
3644 goto done;
3645 }
3646
3647 /* Retrieve the number of members of the alias */
3648 Status = SampRegQueryKeyInfo(MembersKeyHandle,
3649 NULL,
3650 &InfoBuffer->General.MemberCount);
3651 if (!NT_SUCCESS(Status))
3652 {
3653 TRACE("Status 0x%08lx\n", Status);
3654 goto done;
3655 }
3656
3657 *Buffer = InfoBuffer;
3658
3659 done:
3660 if (MembersKeyHandle != NULL)
3661 SampRegCloseKey(MembersKeyHandle);
3662
3663 if (!NT_SUCCESS(Status))
3664 {
3665 if (InfoBuffer != NULL)
3666 {
3667 if (InfoBuffer->General.Name.Buffer != NULL)
3668 midl_user_free(InfoBuffer->General.Name.Buffer);
3669
3670 if (InfoBuffer->General.AdminComment.Buffer != NULL)
3671 midl_user_free(InfoBuffer->General.AdminComment.Buffer);
3672
3673 midl_user_free(InfoBuffer);
3674 }
3675 }
3676
3677 return Status;
3678 }
3679
3680
3681 static NTSTATUS
3682 SampQueryGroupName(PSAM_DB_OBJECT GroupObject,
3683 PSAMPR_GROUP_INFO_BUFFER *Buffer)
3684 {
3685 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
3686 NTSTATUS Status;
3687
3688 *Buffer = NULL;
3689
3690 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
3691 if (InfoBuffer == NULL)
3692 return STATUS_INSUFFICIENT_RESOURCES;
3693
3694 Status = SampGetObjectAttributeString(GroupObject,
3695 L"Name",
3696 &InfoBuffer->Name.Name);
3697 if (!NT_SUCCESS(Status))
3698 {
3699 TRACE("Status 0x%08lx\n", Status);
3700 goto done;
3701 }
3702
3703 *Buffer = InfoBuffer;
3704
3705 done:
3706 if (!NT_SUCCESS(Status))
3707 {
3708 if (InfoBuffer != NULL)
3709 {
3710 if (InfoBuffer->Name.Name.Buffer != NULL)
3711 midl_user_free(InfoBuffer->Name.Name.Buffer);
3712
3713 midl_user_free(InfoBuffer);
3714 }
3715 }
3716
3717 return Status;
3718 }
3719
3720
3721 static NTSTATUS
3722 SampQueryGroupAttribute(PSAM_DB_OBJECT GroupObject,
3723 PSAMPR_GROUP_INFO_BUFFER *Buffer)
3724 {
3725 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
3726 SAM_GROUP_FIXED_DATA FixedData;
3727 ULONG Length = 0;
3728 NTSTATUS Status;
3729
3730 *Buffer = NULL;
3731
3732 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
3733 if (InfoBuffer == NULL)
3734 return STATUS_INSUFFICIENT_RESOURCES;
3735
3736 Length = sizeof(SAM_GROUP_FIXED_DATA);
3737 Status = SampGetObjectAttribute(GroupObject,
3738 L"F",
3739 NULL,
3740 (PVOID)&FixedData,
3741 &Length);
3742 if (!NT_SUCCESS(Status))
3743 goto done;
3744
3745 InfoBuffer->Attribute.Attributes = FixedData.Attributes;
3746
3747 *Buffer = InfoBuffer;
3748
3749 done:
3750 if (!NT_SUCCESS(Status))
3751 {
3752 if (InfoBuffer != NULL)
3753 {
3754 midl_user_free(InfoBuffer);
3755 }
3756 }
3757
3758 return Status;
3759 }
3760
3761
3762 static NTSTATUS
3763 SampQueryGroupAdminComment(PSAM_DB_OBJECT GroupObject,
3764 PSAMPR_GROUP_INFO_BUFFER *Buffer)
3765 {
3766 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL;
3767 NTSTATUS Status;
3768
3769 *Buffer = NULL;
3770
3771 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER));
3772 if (InfoBuffer == NULL)
3773 return STATUS_INSUFFICIENT_RESOURCES;
3774
3775 Status = SampGetObjectAttributeString(GroupObject,
3776 L"Description",
3777 &InfoBuffer->AdminComment.AdminComment);
3778 if (!NT_SUCCESS(Status))
3779 {
3780 TRACE("Status 0x%08lx\n", Status);
3781 goto done;
3782 }
3783
3784 *Buffer = InfoBuffer;
3785
3786 done:
3787 if (!NT_SUCCESS(Status))
3788 {
3789 if (InfoBuffer != NULL)
3790 {
3791 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
3792 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
3793
3794 midl_user_free(InfoBuffer);
3795 }
3796 }
3797
3798 return Status;
3799 }
3800
3801
3802 /* Function 20 */
3803 NTSTATUS
3804 NTAPI
3805 SamrQueryInformationGroup(IN SAMPR_HANDLE GroupHandle,
3806 IN GROUP_INFORMATION_CLASS GroupInformationClass,
3807 OUT PSAMPR_GROUP_INFO_BUFFER *Buffer)
3808 {
3809 PSAM_DB_OBJECT GroupObject;
3810 NTSTATUS Status;
3811
3812 TRACE("SamrQueryInformationGroup(%p %lu %p)\n",
3813 GroupHandle, GroupInformationClass, Buffer);
3814
3815 /* Validate the group handle */
3816 Status = SampValidateDbObject(GroupHandle,
3817 SamDbGroupObject,
3818 GROUP_READ_INFORMATION,
3819 &GroupObject);
3820 if (!NT_SUCCESS(Status))
3821 return Status;
3822
3823 switch (GroupInformationClass)
3824 {
3825 case GroupGeneralInformation:
3826 Status = SampQueryGroupGeneral(GroupObject,
3827 Buffer);
3828 break;
3829
3830 case GroupNameInformation:
3831 Status = SampQueryGroupName(GroupObject,
3832 Buffer);
3833 break;
3834
3835 case GroupAttributeInformation:
3836 Status = SampQueryGroupAttribute(GroupObject,
3837 Buffer);
3838 break;
3839
3840 case GroupAdminCommentInformation:
3841 Status = SampQueryGroupAdminComment(GroupObject,
3842 Buffer);
3843 break;
3844
3845 default:
3846 Status = STATUS_INVALID_INFO_CLASS;
3847 break;
3848 }
3849
3850 return Status;
3851 }
3852
3853
3854 static NTSTATUS
3855 SampSetGroupAttribute(PSAM_DB_OBJECT GroupObject,
3856 PSAMPR_GROUP_INFO_BUFFER Buffer)
3857 {
3858 SAM_GROUP_FIXED_DATA FixedData;
3859 ULONG Length = 0;
3860 NTSTATUS Status;
3861
3862 Length = sizeof(SAM_GROUP_FIXED_DATA);
3863 Status = SampGetObjectAttribute(GroupObject,
3864 L"F",
3865 NULL,
3866 (PVOID)&FixedData,
3867 &Length);
3868 if (!NT_SUCCESS(Status))
3869 goto done;
3870
3871 FixedData.Attributes = Buffer->Attribute.Attributes;
3872
3873 Status = SampSetObjectAttribute(GroupObject,
3874 L"F",
3875 REG_BINARY,
3876 &FixedData,
3877 Length);
3878
3879 done:
3880 return Status;
3881 }
3882
3883
3884 /* Function 21 */
3885 NTSTATUS
3886 NTAPI
3887 SamrSetInformationGroup(IN SAMPR_HANDLE GroupHandle,
3888 IN GROUP_INFORMATION_CLASS GroupInformationClass,
3889 IN PSAMPR_GROUP_INFO_BUFFER Buffer)
3890 {
3891 PSAM_DB_OBJECT GroupObject;
3892 NTSTATUS Status;
3893
3894 TRACE("SamrSetInformationGroup(%p %lu %p)\n",
3895 GroupHandle, GroupInformationClass, Buffer);
3896
3897 /* Validate the group handle */
3898 Status = SampValidateDbObject(GroupHandle,
3899 SamDbGroupObject,
3900 GROUP_WRITE_ACCOUNT,
3901 &GroupObject);
3902 if (!NT_SUCCESS(Status))
3903 return Status;
3904
3905 switch (GroupInformationClass)
3906 {
3907 case GroupNameInformation:
3908 Status = SampSetObjectAttribute(GroupObject,
3909 L"Name",
3910 REG_SZ,
3911 Buffer->Name.Name.Buffer,
3912 Buffer->Name.Name.Length + sizeof(WCHAR));
3913 break;
3914
3915 case GroupAttributeInformation:
3916 Status = SampSetGroupAttribute(GroupObject,
3917 Buffer);
3918 break;
3919
3920 case GroupAdminCommentInformation:
3921 Status = SampSetObjectAttribute(GroupObject,
3922 L"Description",
3923 REG_SZ,
3924 Buffer->AdminComment.AdminComment.Buffer,
3925 Buffer->AdminComment.AdminComment.Length + sizeof(WCHAR));
3926 break;
3927
3928 default:
3929 Status = STATUS_INVALID_INFO_CLASS;
3930 break;
3931 }
3932
3933 return Status;
3934 }
3935
3936
3937 /* Function 22 */
3938 NTSTATUS
3939 NTAPI
3940 SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle,
3941 IN unsigned long MemberId,
3942 IN unsigned long Attributes)
3943 {
3944 UNIMPLEMENTED;
3945 return STATUS_NOT_IMPLEMENTED;
3946 }
3947
3948 /* Function 21 */
3949 NTSTATUS
3950 NTAPI
3951 SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
3952 {
3953 UNIMPLEMENTED;
3954 return STATUS_NOT_IMPLEMENTED;
3955 }
3956
3957 /* Function 24 */
3958 NTSTATUS
3959 NTAPI
3960 SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle,
3961 IN unsigned long MemberId)
3962 {
3963 UNIMPLEMENTED;
3964 return STATUS_NOT_IMPLEMENTED;
3965 }
3966
3967 /* Function 25 */
3968 NTSTATUS
3969 NTAPI
3970 SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle,
3971 OUT PSAMPR_GET_MEMBERS_BUFFER *Members)
3972 {
3973 UNIMPLEMENTED;
3974 return STATUS_NOT_IMPLEMENTED;
3975 }
3976
3977 /* Function 26 */
3978 NTSTATUS
3979 NTAPI
3980 SamrSetMemberAttributesOfGroup(IN SAMPR_HANDLE GroupHandle,
3981 IN unsigned long MemberId,
3982 IN unsigned long Attributes)
3983 {
3984 UNIMPLEMENTED;
3985 return STATUS_NOT_IMPLEMENTED;
3986 }
3987
3988
3989 /* Function 27 */
3990 NTSTATUS
3991 NTAPI
3992 SamrOpenAlias(IN SAMPR_HANDLE DomainHandle,
3993 IN ACCESS_MASK DesiredAccess,
3994 IN ULONG AliasId,
3995 OUT SAMPR_HANDLE *AliasHandle)
3996 {
3997 PSAM_DB_OBJECT DomainObject;
3998 PSAM_DB_OBJECT AliasObject;
3999 WCHAR szRid[9];
4000 NTSTATUS Status;
4001
4002 TRACE("SamrOpenAlias(%p %lx %lx %p)\n",
4003 DomainHandle, DesiredAccess, AliasId, AliasHandle);
4004
4005 /* Map generic access rights */
4006 RtlMapGenericMask(&DesiredAccess,
4007 &AliasMapping);
4008
4009 /* Validate the domain handle */
4010 Status = SampValidateDbObject(DomainHandle,
4011 SamDbDomainObject,
4012 DOMAIN_LOOKUP,
4013 &DomainObject);
4014 if (!NT_SUCCESS(Status))
4015 {
4016 TRACE("failed with status 0x%08lx\n", Status);
4017 return Status;
4018 }
4019
4020 /* Convert the RID into a string (hex) */
4021 swprintf(szRid, L"%08lX", AliasId);
4022
4023 /* Create the alias object */
4024 Status = SampOpenDbObject(DomainObject,
4025 L"Aliases",
4026 szRid,
4027 AliasId,
4028 SamDbAliasObject,
4029 DesiredAccess,
4030 &AliasObject);
4031 if (!NT_SUCCESS(Status))
4032 {
4033 TRACE("failed with status 0x%08lx\n", Status);
4034 return Status;
4035 }
4036
4037 *AliasHandle = (SAMPR_HANDLE)AliasObject;
4038
4039 return STATUS_SUCCESS;
4040 }
4041
4042
4043 static NTSTATUS
4044 SampQueryAliasGeneral(PSAM_DB_OBJECT AliasObject,
4045 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
4046 {
4047 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
4048 HANDLE MembersKeyHandle = NULL;
4049 NTSTATUS Status;
4050
4051 *Buffer = NULL;
4052
4053 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
4054 if (InfoBuffer == NULL)
4055 return STATUS_INSUFFICIENT_RESOURCES;
4056
4057 Status = SampGetObjectAttributeString(AliasObject,
4058 L"Name",
4059 &InfoBuffer->General.Name);
4060 if (!NT_SUCCESS(Status))
4061 {
4062 TRACE("Status 0x%08lx\n", Status);
4063 goto done;
4064 }
4065
4066 Status = SampGetObjectAttributeString(AliasObject,
4067 L"Description",
4068 &InfoBuffer->General.AdminComment);
4069 if (!NT_SUCCESS(Status))
4070 {
4071 TRACE("Status 0x%08lx\n", Status);
4072 goto done;
4073 }
4074
4075 /* Open the Members subkey */
4076 Status = SampRegOpenKey(AliasObject->KeyHandle,
4077 L"Members",
4078 KEY_READ,
4079 &MembersKeyHandle);
4080 if (NT_SUCCESS(Status))
4081 {
4082 /* Retrieve the number of members of the alias */
4083 Status = SampRegQueryKeyInfo(MembersKeyHandle,
4084 NULL,
4085 &InfoBuffer->General.MemberCount);
4086 if (!NT_SUCCESS(Status))
4087 {
4088 TRACE("Status 0x%08lx\n", Status);
4089 goto done;
4090 }
4091 }
4092 else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
4093 {
4094 InfoBuffer->General.MemberCount = 0;
4095 Status = STATUS_SUCCESS;
4096 }
4097 else
4098 {
4099 TRACE("Status 0x%08lx\n", Status);
4100 goto done;
4101 }
4102
4103 *Buffer = InfoBuffer;
4104
4105 done:
4106 if (MembersKeyHandle != NULL)
4107 SampRegCloseKey(MembersKeyHandle);
4108
4109 if (!NT_SUCCESS(Status))
4110 {
4111 if (InfoBuffer != NULL)
4112 {
4113 if (InfoBuffer->General.Name.Buffer != NULL)
4114 midl_user_free(InfoBuffer->General.Name.Buffer);
4115
4116 if (InfoBuffer->General.AdminComment.Buffer != NULL)
4117 midl_user_free(InfoBuffer->General.AdminComment.Buffer);
4118
4119 midl_user_free(InfoBuffer);
4120 }
4121 }
4122
4123 return Status;
4124 }
4125
4126
4127 static NTSTATUS
4128 SampQueryAliasName(PSAM_DB_OBJECT AliasObject,
4129 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
4130 {
4131 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
4132 NTSTATUS Status;
4133
4134 *Buffer = NULL;
4135
4136 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
4137 if (InfoBuffer == NULL)
4138 return STATUS_INSUFFICIENT_RESOURCES;
4139
4140 Status = SampGetObjectAttributeString(AliasObject,
4141 L"Name",
4142 &InfoBuffer->Name.Name);
4143 if (!NT_SUCCESS(Status))
4144 {
4145 TRACE("Status 0x%08lx\n", Status);
4146 goto done;
4147 }
4148
4149 *Buffer = InfoBuffer;
4150
4151 done:
4152 if (!NT_SUCCESS(Status))
4153 {
4154 if (InfoBuffer != NULL)
4155 {
4156 if (InfoBuffer->Name.Name.Buffer != NULL)
4157 midl_user_free(InfoBuffer->Name.Name.Buffer);
4158
4159 midl_user_free(InfoBuffer);
4160 }
4161 }
4162
4163 return Status;
4164 }
4165
4166
4167 static NTSTATUS
4168 SampQueryAliasAdminComment(PSAM_DB_OBJECT AliasObject,
4169 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
4170 {
4171 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
4172 NTSTATUS Status;
4173
4174 *Buffer = NULL;
4175
4176 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
4177 if (InfoBuffer == NULL)
4178 return STATUS_INSUFFICIENT_RESOURCES;
4179
4180 Status = SampGetObjectAttributeString(AliasObject,
4181 L"Description",
4182 &InfoBuffer->AdminComment.AdminComment);
4183 if (!NT_SUCCESS(Status))
4184 {
4185 TRACE("Status 0x%08lx\n", Status);
4186 goto done;
4187 }
4188
4189 *Buffer = InfoBuffer;
4190
4191 done:
4192 if (!NT_SUCCESS(Status))
4193 {
4194 if (InfoBuffer != NULL)
4195 {
4196 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
4197 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
4198
4199 midl_user_free(InfoBuffer);
4200 }
4201 }
4202
4203 return Status;
4204 }
4205
4206
4207 /* Function 28 */
4208 NTSTATUS
4209 NTAPI
4210 SamrQueryInformationAlias(IN SAMPR_HANDLE AliasHandle,
4211 IN ALIAS_INFORMATION_CLASS AliasInformationClass,
4212 OUT PSAMPR_ALIAS_INFO_BUFFER *Buffer)
4213 {
4214 PSAM_DB_OBJECT AliasObject;
4215 NTSTATUS Status;
4216
4217 TRACE("SamrQueryInformationAlias(%p %lu %p)\n",
4218 AliasHandle, AliasInformationClass, Buffer);
4219
4220 /* Validate the alias handle */
4221 Status = SampValidateDbObject(AliasHandle,
4222 SamDbAliasObject,
4223 ALIAS_READ_INFORMATION,
4224 &AliasObject);
4225 if (!NT_SUCCESS(Status))
4226 return Status;
4227
4228 switch (AliasInformationClass)
4229 {
4230 case AliasGeneralInformation:
4231 Status = SampQueryAliasGeneral(AliasObject,
4232 Buffer);
4233 break;
4234
4235 case AliasNameInformation:
4236 Status = SampQueryAliasName(AliasObject,
4237 Buffer);
4238 break;
4239
4240 case AliasAdminCommentInformation:
4241 Status = SampQueryAliasAdminComment(AliasObject,
4242 Buffer);
4243 break;
4244
4245 default:
4246 Status = STATUS_INVALID_INFO_CLASS;
4247 break;
4248 }
4249
4250 return Status;
4251 }
4252
4253
4254 /* Function 29 */
4255 NTSTATUS
4256 NTAPI
4257 SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle,
4258 IN ALIAS_INFORMATION_CLASS AliasInformationClass,
4259 IN PSAMPR_ALIAS_INFO_BUFFER Buffer)
4260 {
4261 PSAM_DB_OBJECT AliasObject;
4262 NTSTATUS Status;
4263
4264 TRACE("SamrSetInformationAlias(%p %lu %p)\n",
4265 AliasHandle, AliasInformationClass, Buffer);
4266
4267 /* Validate the alias handle */
4268 Status = SampValidateDbObject(AliasHandle,
4269 SamDbAliasObject,
4270 ALIAS_WRITE_ACCOUNT,
4271 &AliasObject);
4272 if (!NT_SUCCESS(Status))
4273 return Status;
4274
4275 switch (AliasInformationClass)
4276 {
4277 case AliasNameInformation:
4278 Status = SampSetObjectAttribute(AliasObject,
4279 L"Name",
4280 REG_SZ,
4281 Buffer->Name.Name.Buffer,
4282 Buffer->Name.Name.Length + sizeof(WCHAR));
4283 break;
4284
4285 case AliasAdminCommentInformation:
4286 Status = SampSetObjectAttribute(AliasObject,
4287 L"Description",
4288 REG_SZ,
4289 Buffer->AdminComment.AdminComment.Buffer,
4290 Buffer->AdminComment.AdminComment.Length + sizeof(WCHAR));
4291 break;
4292
4293 default:
4294 Status = STATUS_INVALID_INFO_CLASS;
4295 break;
4296 }
4297
4298 return Status;
4299 }
4300
4301
4302 /* Function 30 */
4303 NTSTATUS
4304 NTAPI
4305 SamrDeleteAlias(IN OUT SAMPR_HANDLE *AliasHandle)
4306 {
4307 UNIMPLEMENTED;
4308 return STATUS_NOT_IMPLEMENTED;
4309 }
4310
4311
4312 /* Function 31 */
4313 NTSTATUS
4314 NTAPI
4315 SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
4316 IN PRPC_SID MemberId)
4317 {
4318 PSAM_DB_OBJECT AliasObject;
4319 LPWSTR MemberIdString = NULL;
4320 HANDLE MembersKeyHandle = NULL;
4321 HANDLE MemberKeyHandle = NULL;
4322 ULONG MemberIdLength;
4323 NTSTATUS Status;
4324
4325 TRACE("SamrAddMemberToAlias(%p %p)\n",
4326 AliasHandle, MemberId);
4327
4328 /* Validate the alias handle */
4329 Status = SampValidateDbObject(AliasHandle,
4330 SamDbAliasObject,
4331 ALIAS_ADD_MEMBER,
4332 &AliasObject);
4333 if (!NT_SUCCESS(Status))
4334 {
4335 TRACE("failed with status 0x%08lx\n", Status);
4336 return Status;
4337 }
4338
4339 ConvertSidToStringSidW(MemberId, &MemberIdString);
4340 TRACE("Member SID: %S\n", MemberIdString);
4341
4342 MemberIdLength = RtlLengthSid(MemberId);
4343
4344 Status = SampRegCreateKey(AliasObject->KeyHandle,
4345 L"Members",
4346 KEY_WRITE,
4347 &MembersKeyHandle);
4348 if (!NT_SUCCESS(Status))
4349 {
4350 TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
4351 goto done;
4352 }
4353
4354 Status = SampRegSetValue(MembersKeyHandle,
4355 MemberIdString,
4356 REG_BINARY,
4357 MemberId,
4358 MemberIdLength);
4359 if (!NT_SUCCESS(Status))
4360 {
4361 TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
4362 goto done;
4363 }
4364
4365 Status = SampRegCreateKey(AliasObject->MembersKeyHandle,
4366 MemberIdString,
4367 KEY_WRITE,
4368 &MemberKeyHandle);
4369 if (!NT_SUCCESS(Status))
4370 {
4371 TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
4372 goto done;
4373 }
4374
4375 Status = SampRegSetValue(MemberKeyHandle,
4376 AliasObject->Name,
4377 REG_BINARY,
4378 MemberId,
4379 MemberIdLength);
4380 if (!NT_SUCCESS(Status))
4381 {
4382 TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
4383 goto done;
4384 }
4385
4386 done:
4387 if (MemberKeyHandle != NULL)
4388 SampRegCloseKey(MemberKeyHandle);
4389
4390 if (MembersKeyHandle != NULL)
4391 SampRegCloseKey(MembersKeyHandle);
4392
4393 if (MemberIdString != NULL)
4394 LocalFree(MemberIdString);
4395
4396 return Status;
4397 }
4398
4399
4400 /* Function 32 */
4401 NTSTATUS
4402 NTAPI
4403 SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle,
4404 IN PRPC_SID MemberId)
4405 {
4406 PSAM_DB_OBJECT AliasObject;
4407 LPWSTR MemberIdString = NULL;
4408 HANDLE MembersKeyHandle = NULL;
4409 HANDLE MemberKeyHandle = NULL;
4410 ULONG ulValueCount;
4411 NTSTATUS Status;
4412
4413 TRACE("SamrRemoveMemberFromAlias(%p %p)\n",
4414 AliasHandle, MemberId);
4415
4416 /* Validate the alias handle */
4417 Status = SampValidateDbObject(AliasHandle,
4418 SamDbAliasObject,
4419 ALIAS_REMOVE_MEMBER,
4420 &AliasObject);
4421 if (!NT_SUCCESS(Status))
4422 {
4423 TRACE("failed with status 0x%08lx\n", Status);
4424 return Status;
4425 }
4426
4427 ConvertSidToStringSidW(MemberId, &MemberIdString);
4428 TRACE("Member SID: %S\n", MemberIdString);
4429
4430 Status = SampRegOpenKey(AliasObject->MembersKeyHandle,
4431 MemberIdString,
4432 KEY_WRITE | KEY_QUERY_VALUE,
4433 &MemberKeyHandle);
4434 if (!NT_SUCCESS(Status))
4435 {
4436 TRACE("SampRegOpenKey failed with status 0x%08lx\n", Status);
4437 goto done;
4438 }
4439
4440 Status = SampRegDeleteValue(MemberKeyHandle,
4441 AliasObject->Name);
4442 if (!NT_SUCCESS(Status))
4443 {
4444 TRACE("SampRegDeleteValue failed with status 0x%08lx\n", Status);
4445 goto done;
4446 }
4447
4448 Status = SampRegQueryKeyInfo(MemberKeyHandle,
4449 NULL,
4450 &ulValueCount);
4451 if (!NT_SUCCESS(Status))
4452 {
4453 TRACE("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
4454 goto done;
4455 }
4456
4457 if (ulValueCount == 0)
4458 {
4459 SampRegCloseKey(MemberKeyHandle);
4460 MemberKeyHandle = NULL;
4461
4462 Status = SampRegDeleteKey(AliasObject->MembersKeyHandle,
4463 MemberIdString);
4464 if (!NT_SUCCESS(Status))
4465 {
4466 TRACE("SampRegDeleteKey failed with status 0x%08lx\n", Status);
4467 goto done;
4468 }
4469 }
4470
4471 Status = SampRegOpenKey(AliasObject->KeyHandle,
4472 L"Members",
4473 KEY_WRITE | KEY_QUERY_VALUE,
4474 &MembersKeyHandle);
4475 if (!NT_SUCCESS(Status))
4476 {
4477 TRACE("SampRegOpenKey failed with status 0x%08lx\n", Status);
4478 goto done;
4479 }
4480
4481 Status = SampRegDeleteValue(MembersKeyHandle,
4482 MemberIdString);
4483 if (!NT_SUCCESS(Status))
4484 {
4485 TRACE("SampRegDeleteValue failed with status 0x%08lx\n", Status);
4486 goto done;
4487 }
4488
4489 Status = SampRegQueryKeyInfo(MembersKeyHandle,
4490 NULL,
4491 &ulValueCount);
4492 if (!NT_SUCCESS(Status))
4493 {
4494 TRACE("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
4495 goto done;
4496 }
4497
4498 if (ulValueCount == 0)
4499 {
4500 SampRegCloseKey(MembersKeyHandle);
4501 MembersKeyHandle = NULL;
4502
4503 Status = SampRegDeleteKey(AliasObject->KeyHandle,
4504 L"Members");
4505 if (!NT_SUCCESS(Status))
4506 {
4507 TRACE("SampRegDeleteKey failed with status 0x%08lx\n", Status);
4508 goto done;
4509 }
4510 }
4511
4512 done:
4513 if (MemberKeyHandle != NULL)
4514 SampRegCloseKey(MemberKeyHandle);
4515
4516 if (MembersKeyHandle != NULL)
4517 SampRegCloseKey(MembersKeyHandle);
4518
4519 if (MemberIdString != NULL)
4520 LocalFree(MemberIdString);
4521
4522 return Status;
4523 }
4524
4525
4526 /* Function 33 */
4527 NTSTATUS
4528 NTAPI
4529 SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
4530 OUT PSAMPR_PSID_ARRAY_OUT Members)
4531 {
4532 PSAM_DB_OBJECT AliasObject;
4533 HANDLE MembersKeyHandle = NULL;
4534 PSAMPR_SID_INFORMATION MemberArray = NULL;
4535 ULONG ValueCount = 0;
4536 ULONG DataLength;
4537 ULONG Index;
4538 NTSTATUS Status;
4539
4540 TRACE("SamrGetMembersInAlias(%p %p %p)\n",
4541 AliasHandle, Members);
4542
4543 /* Validate the alias handle */
4544 Status = SampValidateDbObject(AliasHandle,
4545 SamDbAliasObject,
4546 ALIAS_LIST_MEMBERS,
4547 &AliasObject);
4548 if (!NT_SUCCESS(Status))
4549 {
4550 ERR("failed with status 0x%08lx\n", Status);
4551 return Status;
4552 }
4553
4554 /* Open the members key of the alias objct */
4555 Status = SampRegOpenKey(AliasObject->KeyHandle,
4556 L"Members",
4557 KEY_READ,
4558 &MembersKeyHandle);
4559 if (!NT_SUCCESS(Status))
4560 {
4561 ERR("SampRegOpenKey failed with status 0x%08lx\n", Status);
4562 return Status;
4563 }
4564
4565 /* Get the number of members */
4566 Status = SampRegQueryKeyInfo(MembersKeyHandle,
4567 NULL,
4568 &ValueCount);
4569 if (!NT_SUCCESS(Status))
4570 {
4571 ERR("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
4572 goto done;
4573 }
4574
4575 /* Allocate the member array */
4576 MemberArray = midl_user_allocate(ValueCount * sizeof(SAMPR_SID_INFORMATION));
4577 if (MemberArray == NULL)
4578 {
4579 Status = STATUS_INSUFFICIENT_RESOURCES;
4580 goto done;
4581 }
4582
4583 /* Enumerate the members */
4584 Index = 0;
4585 while (TRUE)
4586 {
4587 /* Get the size of the next SID */
4588 DataLength = 0;
4589 Status = SampRegEnumerateValue(MembersKeyHandle,
4590 Index,
4591 NULL,
4592 NULL,
4593 NULL,
4594 NULL,
4595 &DataLength);
4596 if (!NT_SUCCESS(Status))
4597 {
4598 if (Status == STATUS_NO_MORE_ENTRIES)
4599 Status = STATUS_SUCCESS;
4600 break;
4601 }
4602
4603 /* Allocate a buffer for the SID */
4604 MemberArray[Index].SidPointer = midl_user_allocate(DataLength);
4605 if (MemberArray[Index].SidPointer == NULL)
4606 {
4607 Status = STATUS_INSUFFICIENT_RESOURCES;
4608 goto done;
4609 }
4610
4611 /* Read the SID into the buffer */
4612 Status = SampRegEnumerateValue(MembersKeyHandle,
4613 Index,
4614 NULL,
4615 NULL,
4616 NULL,
4617 (PVOID)MemberArray[Index].SidPointer,
4618 &DataLength);
4619 if (!NT_SUCCESS(Status))
4620 {
4621 goto done;
4622 }
4623
4624 Index++;
4625 }
4626
4627 /* Return the number of members and the member array */
4628 if (NT_SUCCESS(Status))
4629 {
4630 Members->Count = ValueCount;
4631 Members->Sids = MemberArray;
4632 }
4633
4634 done:
4635 /* Clean up the members array and the SID buffers if something failed */
4636 if (!NT_SUCCESS(Status))
4637 {
4638 if (MemberArray != NULL)
4639 {
4640 for (Index = 0; Index < ValueCount; Index++)
4641 {
4642 if (MemberArray[Index].SidPointer != NULL)
4643 midl_user_free(MemberArray[Index].SidPointer);
4644 }
4645
4646 midl_user_free(MemberArray);
4647 }
4648 }
4649
4650 /* Close the members key */
4651 if (MembersKeyHandle != NULL)
4652 SampRegCloseKey(MembersKeyHandle);
4653
4654 return Status;
4655 }
4656
4657
4658 /* Function 34 */
4659 NTSTATUS
4660 NTAPI
4661 SamrOpenUser(IN SAMPR_HANDLE DomainHandle,
4662 IN ACCESS_MASK DesiredAccess,
4663 IN unsigned long UserId,
4664 OUT SAMPR_HANDLE *UserHandle)
4665 {
4666 PSAM_DB_OBJECT DomainObject;
4667 PSAM_DB_OBJECT UserObject;
4668 WCHAR szRid[9];
4669 NTSTATUS Status;
4670
4671 TRACE("SamrOpenUser(%p %lx %lx %p)\n",
4672 DomainHandle, DesiredAccess, UserId, UserHandle);
4673
4674 /* Map generic access rights */
4675 RtlMapGenericMask(&DesiredAccess,
4676 &UserMapping);
4677
4678 /* Validate the domain handle */
4679 Status = SampValidateDbObject(DomainHandle,
4680 SamDbDomainObject,
4681 DOMAIN_LOOKUP,
4682 &DomainObject);
4683 if (!NT_SUCCESS(Status))
4684 {
4685 TRACE("failed with status 0x%08lx\n", Status);
4686 return Status;
4687 }
4688
4689 /* Convert the RID into a string (hex) */
4690 swprintf(szRid, L"%08lX", UserId);
4691
4692 /* Create the user object */
4693 Status = SampOpenDbObject(DomainObject,
4694 L"Users",
4695 szRid,
4696 UserId,
4697 SamDbUserObject,
4698 DesiredAccess,
4699 &UserObject);
4700 if (!NT_SUCCESS(Status))
4701 {
4702 TRACE("failed with status 0x%08lx\n", Status);
4703 return Status;
4704 }
4705
4706 *UserHandle = (SAMPR_HANDLE)UserObject;
4707
4708 return STATUS_SUCCESS;
4709 }
4710
4711
4712 /* Function 35 */
4713 NTSTATUS
4714 NTAPI
4715 SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle)
4716 {
4717 UNIMPLEMENTED;
4718 return STATUS_NOT_IMPLEMENTED;
4719 }
4720
4721
4722 static
4723 NTSTATUS
4724 SampQueryUserGeneral(PSAM_DB_OBJECT UserObject,
4725 PSAMPR_USER_INFO_BUFFER *Buffer)
4726 {
4727 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4728 SAM_USER_FIXED_DATA FixedData;
4729 ULONG Length = 0;
4730 NTSTATUS Status;
4731
4732 *Buffer = NULL;
4733
4734 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
4735 if (InfoBuffer == NULL)
4736 return STATUS_INSUFFICIENT_RESOURCES;
4737
4738 Length = sizeof(SAM_USER_FIXED_DATA);
4739 Status = SampGetObjectAttribute(UserObject,
4740 L"F",
4741 NULL,
4742 (PVOID)&FixedData,
4743 &Length);
4744 if (!NT_SUCCESS(Status))
4745 goto done;
4746
4747 InfoBuffer->General.PrimaryGroupId = FixedData.PrimaryGroupId;
4748
4749 /* Get the Name string */
4750 Status = SampGetObjectAttributeString(UserObject,
4751 L"Name",
4752 &InfoBuffer->General.UserName);
4753 if (!NT_SUCCESS(Status))
4754 {
4755 TRACE("Status 0x%08lx\n", Status);
4756 goto done;
4757 }
4758
4759 /* Get the FullName string */
4760 Status = SampGetObjectAttributeString(UserObject,
4761 L"FullName",
4762 &InfoBuffer->General.FullName);
4763 if (!NT_SUCCESS(Status))
4764 {
4765 TRACE("Status 0x%08lx\n", Status);
4766 goto done;
4767 }
4768
4769 /* Get the AdminComment string */
4770 Status = SampGetObjectAttributeString(UserObject,
4771 L"AdminComment",
4772 &InfoBuffer->General.AdminComment);
4773 if (!NT_SUCCESS(Status))
4774 {
4775 TRACE("Status 0x%08lx\n", Status);
4776 goto done;
4777 }
4778
4779 /* Get the UserComment string */
4780 Status = SampGetObjectAttributeString(UserObject,
4781 L"UserComment",
4782 &InfoBuffer->General.UserComment);
4783 if (!NT_SUCCESS(Status))
4784 {
4785 TRACE("Status 0x%08lx\n", Status);
4786 goto done;
4787 }
4788
4789 *Buffer = InfoBuffer;
4790
4791 done:
4792 if (!NT_SUCCESS(Status))
4793 {
4794 if (InfoBuffer != NULL)
4795 {
4796 if (InfoBuffer->General.UserName.Buffer != NULL)
4797 midl_user_free(InfoBuffer->General.UserName.Buffer);
4798
4799 if (InfoBuffer->General.FullName.Buffer != NULL)
4800 midl_user_free(InfoBuffer->General.FullName.Buffer);
4801
4802 if (InfoBuffer->General.AdminComment.Buffer != NULL)
4803 midl_user_free(InfoBuffer->General.AdminComment.Buffer);
4804
4805 if (InfoBuffer->General.UserComment.Buffer != NULL)
4806 midl_user_free(InfoBuffer->General.UserComment.Buffer);
4807
4808 midl_user_free(InfoBuffer);
4809 }
4810 }
4811
4812 return Status;
4813 }
4814
4815
4816 static
4817 NTSTATUS
4818 SampQueryUserPreferences(PSAM_DB_OBJECT UserObject,
4819 PSAMPR_USER_INFO_BUFFER *Buffer)
4820 {
4821 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4822 SAM_USER_FIXED_DATA FixedData;
4823 ULONG Length = 0;
4824 NTSTATUS Status;
4825
4826 *Buffer = NULL;
4827
4828 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
4829 if (InfoBuffer == NULL)
4830 return STATUS_INSUFFICIENT_RESOURCES;
4831
4832 Length = sizeof(SAM_USER_FIXED_DATA);
4833 Status = SampGetObjectAttribute(UserObject,
4834 L"F",
4835 NULL,
4836 (PVOID)&FixedData,
4837 &Length);
4838 if (!NT_SUCCESS(Status))
4839 goto done;
4840
4841 InfoBuffer->Preferences.CountryCode = FixedData.CountryCode;
4842 InfoBuffer->Preferences.CodePage = FixedData.CodePage;
4843
4844 /* Get the UserComment string */
4845 Status = SampGetObjectAttributeString(UserObject,
4846 L"UserComment",
4847 &InfoBuffer->Preferences.UserComment);
4848 if (!NT_SUCCESS(Status))
4849 {
4850 TRACE("Status 0x%08lx\n", Status);
4851 goto done;
4852 }
4853
4854 *Buffer = InfoBuffer;
4855
4856 done:
4857 if (!NT_SUCCESS(Status))
4858 {
4859 if (InfoBuffer != NULL)
4860 {
4861 if (InfoBuffer->Preferences.UserComment.Buffer != NULL)
4862 midl_user_free(InfoBuffer->Preferences.UserComment.Buffer);
4863
4864 midl_user_free(InfoBuffer);
4865 }
4866 }
4867
4868 return Status;
4869 }
4870
4871
4872 static
4873 NTSTATUS
4874 SampQueryUserLogon(PSAM_DB_OBJECT UserObject,
4875 PSAMPR_USER_INFO_BUFFER *Buffer)
4876 {
4877 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
4878 SAM_USER_FIXED_DATA FixedData;
4879 ULONG Length = 0;
4880 NTSTATUS Status;
4881
4882 *Buffer = NULL;
4883
4884 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
4885 if (InfoBuffer == NULL)
4886 return STATUS_INSUFFICIENT_RESOURCES;
4887
4888 Length = sizeof(SAM_USER_FIXED_DATA);
4889 Status = SampGetObjectAttribute(UserObject,
4890 L"F",
4891 NULL,
4892 (PVOID)&FixedData,
4893 &Length);
4894 if (!NT_SUCCESS(Status))
4895 goto done;
4896
4897 InfoBuffer->Logon.UserId = FixedData.UserId;
4898 InfoBuffer->Logon.PrimaryGroupId = FixedData.PrimaryGroupId;
4899 InfoBuffer->Logon.LastLogon.LowPart = FixedData.LastLogon.LowPart;
4900 InfoBuffer->Logon.LastLogon.HighPart = FixedData.LastLogon.HighPart;
4901 InfoBuffer->Logon.LastLogoff.LowPart = FixedData.LastLogoff.LowPart;
4902 InfoBuffer->Logon.LastLogoff.HighPart = FixedData.LastLogoff.HighPart;
4903 InfoBuffer->Logon.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart;
4904 InfoBuffer->Logon.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart;
4905 InfoBuffer->Logon.BadPasswordCount = FixedData.BadPasswordCount;
4906 InfoBuffer->Logon.LogonCount = FixedData.LogonCount;
4907 InfoBuffer->Logon.UserAccountControl = FixedData.UserAccountControl;
4908
4909 // OLD_LARGE_INTEGER PasswordCanChange;
4910 // OLD_LARGE_INTEGER PasswordMustChange;
4911
4912 /* Get the Name string */
4913 Status = SampGetObjectAttributeString(UserObject,
4914 L"Name",
4915 &InfoBuffer->Logon.UserName);
4916 if (!NT_SUCCESS(Status))
4917 {
4918 TRACE("Status 0x%08lx\n", Status);
4919 goto done;
4920 }
4921
4922 /* Get the FullName string */
4923 Status = SampGetObjectAttributeString(UserObject,
4924 L"FullName",
4925 &InfoBuffer->Logon.FullName);
4926 if (!NT_SUCCESS(Status))
4927 {
4928 TRACE("Status 0x%08lx\n", Status);
4929 goto done;
4930 }
4931
4932 /* Get the HomeDirectory string */
4933 Status = SampGetObjectAttributeString(UserObject,
4934 L"HomeDirectory",
4935 &InfoBuffer->Logon.HomeDirectory);
4936 if (!NT_SUCCESS(Status))
4937 {
4938 TRACE("Status 0x%08lx\n", Status);
4939 goto done;
4940 }
4941
4942 /* Get the HomeDirectoryDrive string */
4943 Status = SampGetObjectAttributeString(UserObject,
4944 L"HomeDirectoryDrive",
4945 &InfoBuffer->Logon.HomeDirectoryDrive);
4946 if (!NT_SUCCESS(Status))
4947 {
4948 TRACE("Status 0x%08lx\n", Status);
4949 goto done;
4950 }
4951
4952 /* Get the ScriptPath string */
4953 Status = SampGetObjectAttributeString(UserObject,
4954 L"ScriptPath",
4955 &InfoBuffer->Logon.ScriptPath);
4956 if (!NT_SUCCESS(Status))
4957 {
4958 TRACE("Status 0x%08lx\n", Status);
4959 goto done;
4960 }
4961
4962 /* Get the ProfilePath string */
4963 Status = SampGetObjectAttributeString(UserObject,
4964 L"ProfilePath",
4965 &InfoBuffer->Logon.ProfilePath);
4966 if (!NT_SUCCESS(Status))
4967 {
4968 TRACE("Status 0x%08lx\n", Status);
4969 goto done;
4970 }
4971
4972 /* Get the WorkStations string */
4973 Status = SampGetObjectAttributeString(UserObject,
4974 L"WorkStations",
4975 &InfoBuffer->Logon.WorkStations);
4976 if (!NT_SUCCESS(Status))
4977 {
4978 TRACE("Status 0x%08lx\n", Status);
4979 goto done;
4980 }
4981
4982 /* FIXME: LogonHours */
4983
4984 *Buffer = InfoBuffer;
4985
4986 done:
4987 if (!NT_SUCCESS(Status))
4988 {
4989 if (InfoBuffer != NULL)
4990 {
4991 if (InfoBuffer->Logon.UserName.Buffer != NULL)
4992 midl_user_free(InfoBuffer->Logon.UserName.Buffer);
4993
4994 if (InfoBuffer->Logon.FullName.Buffer != NULL)
4995 midl_user_free(InfoBuffer->Logon.FullName.Buffer);
4996
4997 if (InfoBuffer->Logon.HomeDirectory.Buffer != NULL)
4998 midl_user_free(InfoBuffer->Logon.HomeDirectory.Buffer);
4999
5000 if (InfoBuffer->Logon.HomeDirectoryDrive.Buffer != NULL)
5001 midl_user_free(InfoBuffer->Logon.HomeDirectoryDrive.Buffer);
5002
5003 if (InfoBuffer->Logon.ScriptPath.Buffer != NULL)
5004 midl_user_free(InfoBuffer->Logon.ScriptPath.Buffer);
5005
5006 if (InfoBuffer->Logon.ProfilePath.Buffer != NULL)
5007 midl_user_free(InfoBuffer->Logon.ProfilePath.Buffer);
5008
5009 if (InfoBuffer->Logon.WorkStations.Buffer != NULL)
5010 midl_user_free(InfoBuffer->Logon.WorkStations.Buffer);
5011
5012 if (InfoBuffer->Logon.LogonHours.LogonHours != NULL)
5013 midl_user_free(InfoBuffer->Logon.LogonHours.LogonHours);
5014
5015 midl_user_free(InfoBuffer);
5016 }
5017 }
5018
5019 return Status;
5020 }
5021
5022
5023 static
5024 NTSTATUS
5025 SampQueryUserAccount(PSAM_DB_OBJECT UserObject,
5026 PSAMPR_USER_INFO_BUFFER *Buffer)
5027 {
5028 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5029 SAM_USER_FIXED_DATA FixedData;
5030 ULONG Length = 0;
5031 NTSTATUS Status;
5032
5033 *Buffer = NULL;
5034
5035 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5036 if (InfoBuffer == NULL)
5037 return STATUS_INSUFFICIENT_RESOURCES;
5038
5039 Length = sizeof(SAM_USER_FIXED_DATA);
5040 Status = SampGetObjectAttribute(UserObject,
5041 L"F",
5042 NULL,
5043 (PVOID)&FixedData,
5044 &Length);
5045 if (!NT_SUCCESS(Status))
5046 goto done;
5047
5048 InfoBuffer->Account.UserId = FixedData.UserId;
5049 InfoBuffer->Account.PrimaryGroupId = FixedData.PrimaryGroupId;
5050 InfoBuffer->Account.LastLogon.LowPart = FixedData.LastLogon.LowPart;
5051 InfoBuffer->Account.LastLogon.HighPart = FixedData.LastLogon.HighPart;
5052 InfoBuffer->Account.LastLogoff.LowPart = FixedData.LastLogoff.LowPart;
5053 InfoBuffer->Account.LastLogoff.HighPart = FixedData.LastLogoff.HighPart;
5054 InfoBuffer->Account.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart;
5055 InfoBuffer->Account.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart;
5056 InfoBuffer->Account.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
5057 InfoBuffer->Account.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
5058 InfoBuffer->Account.BadPasswordCount = FixedData.BadPasswordCount;
5059 InfoBuffer->Account.LogonCount = FixedData.LogonCount;
5060 InfoBuffer->Account.UserAccountControl = FixedData.UserAccountControl;
5061
5062 /* Get the Name string */
5063 Status = SampGetObjectAttributeString(UserObject,
5064 L"Name",
5065 &InfoBuffer->Account.UserName);
5066 if (!NT_SUCCESS(Status))
5067 {
5068 TRACE("Status 0x%08lx\n", Status);
5069 goto done;
5070 }
5071
5072 /* Get the FullName string */
5073 Status = SampGetObjectAttributeString(UserObject,
5074 L"FullName",
5075 &InfoBuffer->Account.FullName);
5076 if (!NT_SUCCESS(Status))
5077 {
5078 TRACE("Status 0x%08lx\n", Status);
5079 goto done;
5080 }
5081
5082 /* Get the HomeDirectory string */
5083 Status = SampGetObjectAttributeString(UserObject,
5084 L"HomeDirectory",
5085 &InfoBuffer->Account.HomeDirectory);
5086 if (!NT_SUCCESS(Status))
5087 {
5088 TRACE("Status 0x%08lx\n", Status);
5089 goto done;
5090 }
5091
5092 /* Get the HomeDirectoryDrive string */
5093 Status = SampGetObjectAttributeString(UserObject,
5094 L"HomeDirectoryDrive",
5095 &InfoBuffer->Account.HomeDirectoryDrive);
5096 if (!NT_SUCCESS(Status))
5097 {
5098 TRACE("Status 0x%08lx\n", Status);
5099 goto done;
5100 }
5101
5102 /* Get the ScriptPath string */
5103 Status = SampGetObjectAttributeString(UserObject,
5104 L"ScriptPath",
5105 &InfoBuffer->Account.ScriptPath);
5106 if (!NT_SUCCESS(Status))
5107 {
5108 TRACE("Status 0x%08lx\n", Status);
5109 goto done;
5110 }
5111
5112 /* Get the ProfilePath string */
5113 Status = SampGetObjectAttributeString(UserObject,
5114 L"ProfilePath",
5115 &InfoBuffer->Account.ProfilePath);
5116 if (!NT_SUCCESS(Status))
5117 {
5118 TRACE("Status 0x%08lx\n", Status);
5119 goto done;
5120 }
5121
5122 /* Get the AdminComment string */
5123 Status = SampGetObjectAttributeString(UserObject,
5124 L"AdminComment",
5125 &InfoBuffer->Account.AdminComment);
5126 if (!NT_SUCCESS(Status))
5127 {
5128 TRACE("Status 0x%08lx\n", Status);
5129 goto done;
5130 }
5131
5132 /* Get the WorkStations string */
5133 Status = SampGetObjectAttributeString(UserObject,
5134 L"WorkStations",
5135 &InfoBuffer->Account.WorkStations);
5136 if (!NT_SUCCESS(Status))
5137 {
5138 TRACE("Status 0x%08lx\n", Status);
5139 goto done;
5140 }
5141
5142 /* FIXME: LogonHours */
5143
5144 *Buffer = InfoBuffer;
5145
5146 done:
5147 if (!NT_SUCCESS(Status))
5148 {
5149 if (InfoBuffer != NULL)
5150 {
5151 if (InfoBuffer->Account.UserName.Buffer != NULL)
5152 midl_user_free(InfoBuffer->Account.UserName.Buffer);
5153
5154 if (InfoBuffer->Account.FullName.Buffer != NULL)
5155 midl_user_free(InfoBuffer->Account.FullName.Buffer);
5156
5157 if (InfoBuffer->Account.HomeDirectory.Buffer != NULL)
5158 midl_user_free(InfoBuffer->Account.HomeDirectory.Buffer);
5159
5160 if (InfoBuffer->Account.HomeDirectoryDrive.Buffer != NULL)
5161 midl_user_free(InfoBuffer->Account.HomeDirectoryDrive.Buffer);
5162
5163 if (InfoBuffer->Account.ScriptPath.Buffer != NULL)
5164 midl_user_free(InfoBuffer->Account.ScriptPath.Buffer);
5165
5166 if (InfoBuffer->Account.ProfilePath.Buffer != NULL)
5167 midl_user_free(InfoBuffer->Account.ProfilePath.Buffer);
5168
5169 if (InfoBuffer->Account.AdminComment.Buffer != NULL)
5170 midl_user_free(InfoBuffer->Account.AdminComment.Buffer);
5171
5172 if (InfoBuffer->Account.WorkStations.Buffer != NULL)
5173 midl_user_free(InfoBuffer->Account.WorkStations.Buffer);
5174
5175 if (InfoBuffer->Account.LogonHours.LogonHours != NULL)
5176 midl_user_free(InfoBuffer->Account.LogonHours.LogonHours);
5177
5178 midl_user_free(InfoBuffer);
5179 }
5180 }
5181
5182 return Status;
5183 }
5184
5185 /* FIXME: SampQueryUserLogonHours */
5186
5187 static
5188 NTSTATUS
5189 SampQueryUserName(PSAM_DB_OBJECT UserObject,
5190 PSAMPR_USER_INFO_BUFFER *Buffer)
5191 {
5192 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5193 NTSTATUS Status;
5194
5195 *Buffer = NULL;
5196
5197 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5198 if (InfoBuffer == NULL)
5199 return STATUS_INSUFFICIENT_RESOURCES;
5200
5201 /* Get the Name string */
5202 Status = SampGetObjectAttributeString(UserObject,
5203 L"Name",
5204 &InfoBuffer->Name.UserName);
5205 if (!NT_SUCCESS(Status))
5206 {
5207 TRACE("Status 0x%08lx\n", Status);
5208 goto done;
5209 }
5210
5211 /* Get the FullName string */
5212 Status = SampGetObjectAttributeString(UserObject,
5213 L"FullName",
5214 &InfoBuffer->Name.FullName);
5215 if (!NT_SUCCESS(Status))
5216 {
5217 TRACE("Status 0x%08lx\n", Status);
5218 goto done;
5219 }
5220
5221 *Buffer = InfoBuffer;
5222
5223 done:
5224 if (!NT_SUCCESS(Status))
5225 {
5226 if (InfoBuffer != NULL)
5227 {
5228 if (InfoBuffer->Name.UserName.Buffer != NULL)
5229 midl_user_free(InfoBuffer->Name.UserName.Buffer);
5230
5231 if (InfoBuffer->Name.FullName.Buffer != NULL)
5232 midl_user_free(InfoBuffer->Name.FullName.Buffer);
5233
5234 midl_user_free(InfoBuffer);
5235 }
5236 }
5237
5238 return Status;
5239 }
5240
5241
5242 static NTSTATUS
5243 SampQueryUserAccountName(PSAM_DB_OBJECT UserObject,
5244 PSAMPR_USER_INFO_BUFFER *Buffer)
5245 {
5246 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5247 NTSTATUS Status;
5248
5249 *Buffer = NULL;
5250
5251 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5252 if (InfoBuffer == NULL)
5253 return STATUS_INSUFFICIENT_RESOURCES;
5254
5255 /* Get the Name string */
5256 Status = SampGetObjectAttributeString(UserObject,
5257 L"Name",
5258 &InfoBuffer->AccountName.UserName);
5259 if (!NT_SUCCESS(Status))
5260 {
5261 TRACE("Status 0x%08lx\n", Status);
5262 goto done;
5263 }
5264
5265 *Buffer = InfoBuffer;
5266
5267 done:
5268 if (!NT_SUCCESS(Status))
5269 {
5270 if (InfoBuffer != NULL)
5271 {
5272 if (InfoBuffer->AccountName.UserName.Buffer != NULL)
5273 midl_user_free(InfoBuffer->AccountName.UserName.Buffer);
5274
5275 midl_user_free(InfoBuffer);
5276 }
5277 }
5278
5279 return Status;
5280 }
5281
5282
5283 static NTSTATUS
5284 SampQueryUserFullName(PSAM_DB_OBJECT UserObject,
5285 PSAMPR_USER_INFO_BUFFER *Buffer)
5286 {
5287 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5288 NTSTATUS Status;
5289
5290 *Buffer = NULL;
5291
5292 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5293 if (InfoBuffer == NULL)
5294 return STATUS_INSUFFICIENT_RESOURCES;
5295
5296 /* Get the FullName string */
5297 Status = SampGetObjectAttributeString(UserObject,
5298 L"FullName",
5299 &InfoBuffer->FullName.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->FullName.FullName.Buffer != NULL)
5314 midl_user_free(InfoBuffer->FullName.FullName.Buffer);
5315
5316 midl_user_free(InfoBuffer);
5317 }
5318 }
5319
5320 return Status;
5321 }
5322
5323
5324 static
5325 NTSTATUS
5326 SampQueryUserPrimaryGroup(PSAM_DB_OBJECT UserObject,
5327 PSAMPR_USER_INFO_BUFFER *Buffer)
5328 {
5329 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5330 SAM_USER_FIXED_DATA FixedData;
5331 ULONG Length = 0;
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 Length = sizeof(SAM_USER_FIXED_DATA);
5341 Status = SampGetObjectAttribute(UserObject,
5342 L"F",
5343 NULL,
5344 (PVOID)&FixedData,
5345 &Length);
5346 if (!NT_SUCCESS(Status))
5347 goto done;
5348
5349 InfoBuffer->PrimaryGroup.PrimaryGroupId = FixedData.PrimaryGroupId;
5350
5351 *Buffer = InfoBuffer;
5352
5353 done:
5354 if (!NT_SUCCESS(Status))
5355 {
5356 if (InfoBuffer != NULL)
5357 {
5358 midl_user_free(InfoBuffer);
5359 }
5360 }
5361
5362 return Status;
5363 }
5364
5365
5366 static NTSTATUS
5367 SampQueryUserHome(PSAM_DB_OBJECT UserObject,
5368 PSAMPR_USER_INFO_BUFFER *Buffer)
5369 {
5370 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5371 NTSTATUS Status;
5372
5373 *Buffer = NULL;
5374
5375 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5376 if (InfoBuffer == NULL)
5377 return STATUS_INSUFFICIENT_RESOURCES;
5378
5379 /* Get the HomeDirectory string */
5380 Status = SampGetObjectAttributeString(UserObject,
5381 L"HomeDirectory",
5382 &InfoBuffer->Home.HomeDirectory);
5383 if (!NT_SUCCESS(Status))
5384 {
5385 TRACE("Status 0x%08lx\n", Status);
5386 goto done;
5387 }
5388
5389 /* Get the HomeDirectoryDrive string */
5390 Status = SampGetObjectAttributeString(UserObject,
5391 L"HomeDirectoryDrive",
5392 &InfoBuffer->Home.HomeDirectoryDrive);
5393 if (!NT_SUCCESS(Status))
5394 {
5395 TRACE("Status 0x%08lx\n", Status);
5396 goto done;
5397 }
5398
5399 *Buffer = InfoBuffer;
5400
5401 done:
5402 if (!NT_SUCCESS(Status))
5403 {
5404 if (InfoBuffer != NULL)
5405 {
5406 if (InfoBuffer->Home.HomeDirectory.Buffer != NULL)
5407 midl_user_free(InfoBuffer->Home.HomeDirectory.Buffer);
5408
5409 if (InfoBuffer->Home.HomeDirectoryDrive.Buffer != NULL)
5410 midl_user_free(InfoBuffer->Home.HomeDirectoryDrive.Buffer);
5411
5412 midl_user_free(InfoBuffer);
5413 }
5414 }
5415
5416 return Status;
5417 }
5418
5419
5420 static NTSTATUS
5421 SampQueryUserScript(PSAM_DB_OBJECT UserObject,
5422 PSAMPR_USER_INFO_BUFFER *Buffer)
5423 {
5424 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5425 NTSTATUS Status;
5426
5427 *Buffer = NULL;
5428
5429 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5430 if (InfoBuffer == NULL)
5431 return STATUS_INSUFFICIENT_RESOURCES;
5432
5433 /* Get the ScriptPath string */
5434 Status = SampGetObjectAttributeString(UserObject,
5435 L"ScriptPath",
5436 &InfoBuffer->Script.ScriptPath);
5437 if (!NT_SUCCESS(Status))
5438 {
5439 TRACE("Status 0x%08lx\n", Status);
5440 goto done;
5441 }
5442
5443 *Buffer = InfoBuffer;
5444
5445 done:
5446 if (!NT_SUCCESS(Status))
5447 {
5448 if (InfoBuffer != NULL)
5449 {
5450 if (InfoBuffer->Script.ScriptPath.Buffer != NULL)
5451 midl_user_free(InfoBuffer->Script.ScriptPath.Buffer);
5452
5453 midl_user_free(InfoBuffer);
5454 }
5455 }
5456
5457 return Status;
5458 }
5459
5460
5461 static NTSTATUS
5462 SampQueryUserProfile(PSAM_DB_OBJECT UserObject,
5463 PSAMPR_USER_INFO_BUFFER *Buffer)
5464 {
5465 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5466 NTSTATUS Status;
5467
5468 *Buffer = NULL;
5469
5470 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5471 if (InfoBuffer == NULL)
5472 return STATUS_INSUFFICIENT_RESOURCES;
5473
5474 /* Get the ProfilePath string */
5475 Status = SampGetObjectAttributeString(UserObject,
5476 L"ProfilePath",
5477 &InfoBuffer->Profile.ProfilePath);
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->Profile.ProfilePath.Buffer != NULL)
5492 midl_user_free(InfoBuffer->Profile.ProfilePath.Buffer);
5493
5494 midl_user_free(InfoBuffer);
5495 }
5496 }
5497
5498 return Status;
5499 }
5500
5501
5502 static NTSTATUS
5503 SampQueryUserAdminComment(PSAM_DB_OBJECT UserObject,
5504 PSAMPR_USER_INFO_BUFFER *Buffer)
5505 {
5506 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5507 NTSTATUS Status;
5508
5509 *Buffer = NULL;
5510
5511 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5512 if (InfoBuffer == NULL)
5513 return STATUS_INSUFFICIENT_RESOURCES;
5514
5515 /* Get the AdminComment string */
5516 Status = SampGetObjectAttributeString(UserObject,
5517 L"AdminComment",
5518 &InfoBuffer->AdminComment.AdminComment);
5519 if (!NT_SUCCESS(Status))
5520 {
5521 TRACE("Status 0x%08lx\n", Status);
5522 goto done;
5523 }
5524
5525 *Buffer = InfoBuffer;
5526
5527 done:
5528 if (!NT_SUCCESS(Status))
5529 {
5530 if (InfoBuffer != NULL)
5531 {
5532 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
5533 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
5534
5535 midl_user_free(InfoBuffer);
5536 }
5537 }
5538
5539 return Status;
5540 }
5541
5542
5543 static NTSTATUS
5544 SampQueryUserWorkStations(PSAM_DB_OBJECT UserObject,
5545 PSAMPR_USER_INFO_BUFFER *Buffer)
5546 {
5547 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5548 NTSTATUS Status;
5549
5550 *Buffer = NULL;
5551
5552 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5553 if (InfoBuffer == NULL)
5554 return STATUS_INSUFFICIENT_RESOURCES;
5555
5556 /* Get the WorkStations string */
5557 Status = SampGetObjectAttributeString(UserObject,
5558 L"WorkStations",
5559 &InfoBuffer->WorkStations.WorkStations);
5560 if (!NT_SUCCESS(Status))
5561 {
5562 TRACE("Status 0x%08lx\n", Status);
5563 goto done;
5564 }
5565
5566 *Buffer = InfoBuffer;
5567
5568 done:
5569 if (!NT_SUCCESS(Status))
5570 {
5571 if (InfoBuffer != NULL)
5572 {
5573 if (InfoBuffer->WorkStations.WorkStations.Buffer != NULL)
5574 midl_user_free(InfoBuffer->WorkStations.WorkStations.Buffer);
5575
5576 midl_user_free(InfoBuffer);
5577 }
5578 }
5579
5580 return Status;
5581 }
5582
5583
5584 static
5585 NTSTATUS
5586 SampQueryUserControl(PSAM_DB_OBJECT UserObject,
5587 PSAMPR_USER_INFO_BUFFER *Buffer)
5588 {
5589 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5590 SAM_USER_FIXED_DATA FixedData;
5591 ULONG Length = 0;
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 Length = sizeof(SAM_USER_FIXED_DATA);
5601 Status = SampGetObjectAttribute(UserObject,
5602 L"F",
5603 NULL,
5604 (PVOID)&FixedData,
5605 &Length);
5606 if (!NT_SUCCESS(Status))
5607 goto done;
5608
5609 InfoBuffer->Control.UserAccountControl = FixedData.UserAccountControl;
5610
5611 *Buffer = InfoBuffer;
5612
5613 done:
5614 if (!NT_SUCCESS(Status))
5615 {
5616 if (InfoBuffer != NULL)
5617 {
5618 midl_user_free(InfoBuffer);
5619 }
5620 }
5621
5622 return Status;
5623 }
5624
5625
5626 static
5627 NTSTATUS
5628 SampQueryUserExpires(PSAM_DB_OBJECT UserObject,
5629 PSAMPR_USER_INFO_BUFFER *Buffer)
5630 {
5631 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5632 SAM_USER_FIXED_DATA FixedData;
5633 ULONG Length = 0;
5634 NTSTATUS Status;
5635
5636 *Buffer = NULL;
5637
5638 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5639 if (InfoBuffer == NULL)
5640 return STATUS_INSUFFICIENT_RESOURCES;
5641
5642 Length = sizeof(SAM_USER_FIXED_DATA);
5643 Status = SampGetObjectAttribute(UserObject,
5644 L"F",
5645 NULL,
5646 (PVOID)&FixedData,
5647 &Length);
5648 if (!NT_SUCCESS(Status))
5649 goto done;
5650
5651 InfoBuffer->Expires.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
5652 InfoBuffer->Expires.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
5653
5654 *Buffer = InfoBuffer;
5655
5656 done:
5657 if (!NT_SUCCESS(Status))
5658 {
5659 if (InfoBuffer != NULL)
5660 {
5661 midl_user_free(InfoBuffer);
5662 }
5663 }
5664
5665 return Status;
5666 }
5667
5668
5669 static NTSTATUS
5670 SampQueryUserParameters(PSAM_DB_OBJECT UserObject,
5671 PSAMPR_USER_INFO_BUFFER *Buffer)
5672 {
5673 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
5674 NTSTATUS Status;
5675
5676 *Buffer = NULL;
5677
5678 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
5679 if (InfoBuffer == NULL)
5680 return STATUS_INSUFFICIENT_RESOURCES;
5681
5682 /* Get the Parameters string */
5683 Status = SampGetObjectAttributeString(UserObject,
5684 L"Parameters",
5685 &InfoBuffer->Parameters.Parameters);
5686 if (!NT_SUCCESS(Status))
5687 {
5688 TRACE("Status 0x%08lx\n", Status);
5689 goto done;
5690 }
5691
5692 *Buffer = InfoBuffer;
5693
5694 done:
5695 if (!NT_SUCCESS(Status))
5696 {
5697 if (InfoBuffer != NULL)
5698 {
5699 if (InfoBuffer->Parameters.Parameters.Buffer != NULL)
5700 midl_user_free(InfoBuffer->Parameters.Parameters.Buffer);
5701
5702 midl_user_free(InfoBuffer);
5703 }
5704 }
5705
5706 return Status;
5707 }
5708
5709
5710 /* Function 36 */
5711 NTSTATUS
5712 NTAPI
5713 SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
5714 IN USER_INFORMATION_CLASS UserInformationClass,
5715 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
5716 {
5717 PSAM_DB_OBJECT UserObject;
5718 ACCESS_MASK DesiredAccess;
5719 NTSTATUS Status;
5720
5721 TRACE("SamrQueryInformationUser(%p %lu %p)\n",
5722 UserHandle, UserInformationClass, Buffer);
5723
5724 switch (UserInformationClass)
5725 {
5726 case UserGeneralInformation:
5727 case UserNameInformation:
5728 case UserAccountNameInformation:
5729 case UserFullNameInformation:
5730 case UserPrimaryGroupInformation:
5731 case UserAdminCommentInformation:
5732 DesiredAccess = USER_READ_GENERAL;
5733 break;
5734
5735 case UserLogonHoursInformation:
5736 case UserHomeInformation:
5737 case UserScriptInformation:
5738 case UserProfileInformation:
5739 case UserWorkStationsInformation:
5740 DesiredAccess = USER_READ_LOGON;
5741 break;
5742
5743 case UserControlInformation:
5744 case UserExpiresInformation:
5745 case UserParametersInformation:
5746 DesiredAccess = USER_READ_ACCOUNT;
5747 break;
5748
5749 case UserPreferencesInformation:
5750 DesiredAccess = USER_READ_GENERAL |
5751 USER_READ_PREFERENCES;
5752 break;
5753
5754 case UserLogonInformation:
5755 case UserAccountInformation:
5756 DesiredAccess = USER_READ_GENERAL |
5757 USER_READ_PREFERENCES |
5758 USER_READ_LOGON |
5759 USER_READ_ACCOUNT;
5760 break;
5761
5762 default:
5763 return STATUS_INVALID_INFO_CLASS;
5764 }
5765
5766 /* Validate the domain handle */
5767 Status = SampValidateDbObject(UserHandle,
5768 SamDbUserObject,
5769 DesiredAccess,
5770 &UserObject);
5771 if (!NT_SUCCESS(Status))
5772 {
5773 TRACE("failed with status 0x%08lx\n", Status);
5774 return Status;
5775 }
5776
5777 switch (UserInformationClass)
5778 {
5779 case UserGeneralInformation:
5780 Status = SampQueryUserGeneral(UserObject,
5781 Buffer);
5782 break;
5783
5784 case UserPreferencesInformation:
5785 Status = SampQueryUserPreferences(UserObject,
5786 Buffer);
5787 break;
5788
5789 case UserLogonInformation:
5790 Status = SampQueryUserLogon(UserObject,
5791 Buffer);
5792 break;
5793
5794 // case UserLogonHoursInformation:
5795 // Status = SampQueryUserLogonHours(UserObject,
5796 // Buffer);
5797 // break;
5798
5799 case UserAccountInformation:
5800 Status = SampQueryUserAccount(UserObject,
5801 Buffer);
5802 break;
5803
5804 case UserNameInformation:
5805 Status = SampQueryUserName(UserObject,
5806 Buffer);
5807 break;
5808
5809 case UserAccountNameInformation:
5810 Status = SampQueryUserAccountName(UserObject,
5811 Buffer);
5812 break;
5813
5814 case UserFullNameInformation:
5815 Status = SampQueryUserFullName(UserObject,
5816 Buffer);
5817 break;
5818
5819 case UserPrimaryGroupInformation:
5820 Status = SampQueryUserPrimaryGroup(UserObject,
5821 Buffer);
5822 break;
5823
5824 case UserHomeInformation:
5825 Status = SampQueryUserHome(UserObject,
5826 Buffer);
5827
5828 case UserScriptInformation:
5829 Status = SampQueryUserScript(UserObject,
5830 Buffer);
5831 break;
5832
5833 case UserProfileInformation:
5834 Status = SampQueryUserProfile(UserObject,
5835 Buffer);
5836 break;
5837
5838 case UserAdminCommentInformation:
5839 Status = SampQueryUserAdminComment(UserObject,
5840 Buffer);
5841 break;
5842
5843 case UserWorkStationsInformation:
5844 Status = SampQueryUserWorkStations(UserObject,
5845 Buffer);
5846 break;
5847
5848 case UserControlInformation:
5849 Status = SampQueryUserControl(UserObject,
5850 Buffer);
5851 break;
5852
5853 case UserExpiresInformation:
5854 Status = SampQueryUserExpires(UserObject,
5855 Buffer);
5856 break;
5857
5858 // case UserInternal1Information:
5859
5860 case UserParametersInformation:
5861 Status = SampQueryUserParameters(UserObject,
5862 Buffer);
5863 break;
5864
5865 // case UserAllInformation:
5866 // case UserInternal4Information:
5867 // case UserInternal5Information:
5868 // case UserInternal4InformationNew:
5869 // case UserInternal5InformationNew:
5870
5871 default:
5872 Status = STATUS_INVALID_INFO_CLASS;
5873 }
5874
5875 return Status;
5876 }
5877
5878
5879 static NTSTATUS
5880 SampSetUserGeneral(PSAM_DB_OBJECT UserObject,
5881 PSAMPR_USER_INFO_BUFFER Buffer)
5882 {
5883 SAM_USER_FIXED_DATA FixedData;
5884 ULONG Length = 0;
5885 NTSTATUS Status;
5886
5887 Length = sizeof(SAM_USER_FIXED_DATA);
5888 Status = SampGetObjectAttribute(UserObject,
5889 L"F",
5890 NULL,
5891 (PVOID)&FixedData,
5892 &Length);
5893 if (!NT_SUCCESS(Status))
5894 goto done;
5895
5896 FixedData.PrimaryGroupId = Buffer->General.PrimaryGroupId;
5897
5898 Status = SampSetObjectAttribute(UserObject,
5899 L"F",
5900 REG_BINARY,
5901 &FixedData,
5902 Length);
5903 if (!NT_SUCCESS(Status))
5904 goto done;
5905
5906 Status = SampSetObjectAttribute(UserObject,
5907 L"Name",
5908 REG_SZ,
5909 Buffer->General.UserName.Buffer,
5910 Buffer->General.UserName.MaximumLength);
5911 if (!NT_SUCCESS(Status))
5912 goto done;
5913
5914 Status = SampSetObjectAttribute(UserObject,
5915 L"FullName",
5916 REG_SZ,
5917 Buffer->General.FullName.Buffer,
5918 Buffer->General.FullName.MaximumLength);
5919 if (!NT_SUCCESS(Status))
5920 goto done;
5921
5922 Status = SampSetObjectAttribute(UserObject,
5923 L"AdminComment",
5924 REG_SZ,
5925 Buffer->General.AdminComment.Buffer,
5926 Buffer->General.AdminComment.MaximumLength);
5927 if (!NT_SUCCESS(Status))
5928 goto done;
5929
5930 Status = SampSetObjectAttribute(UserObject,
5931 L"UserComment",
5932 REG_SZ,
5933 Buffer->General.UserComment.Buffer,
5934 Buffer->General.UserComment.MaximumLength);
5935
5936 done:
5937 return Status;
5938 }
5939
5940
5941 static NTSTATUS
5942 SampSetUserPreferences(PSAM_DB_OBJECT UserObject,
5943 PSAMPR_USER_INFO_BUFFER Buffer)
5944 {
5945 SAM_USER_FIXED_DATA FixedData;
5946 ULONG Length = 0;
5947 NTSTATUS Status;
5948
5949 Length = sizeof(SAM_USER_FIXED_DATA);
5950 Status = SampGetObjectAttribute(UserObject,
5951 L"F",
5952 NULL,
5953 (PVOID)&FixedData,
5954 &Length);
5955 if (!NT_SUCCESS(Status))
5956 goto done;
5957
5958 FixedData.CountryCode = Buffer->Preferences.CountryCode;
5959 FixedData.CodePage = Buffer->Preferences.CodePage;
5960
5961 Status = SampSetObjectAttribute(UserObject,
5962 L"F",
5963 REG_BINARY,
5964 &FixedData,
5965 Length);
5966 if (!NT_SUCCESS(Status))
5967 goto done;
5968
5969 Status = SampSetObjectAttribute(UserObject,
5970 L"UserComment",
5971 REG_SZ,
5972 Buffer->Preferences.UserComment.Buffer,
5973 Buffer->Preferences.UserComment.MaximumLength);
5974
5975 done:
5976 return Status;
5977 }
5978
5979
5980 static NTSTATUS
5981 SampSetUserPrimaryGroup(PSAM_DB_OBJECT UserObject,
5982 PSAMPR_USER_INFO_BUFFER Buffer)
5983 {
5984 SAM_USER_FIXED_DATA FixedData;
5985 ULONG Length = 0;
5986 NTSTATUS Status;
5987
5988 Length = sizeof(SAM_USER_FIXED_DATA);
5989 Status = SampGetObjectAttribute(UserObject,
5990 L"F",
5991 NULL,
5992 (PVOID)&FixedData,
5993 &Length);
5994 if (!NT_SUCCESS(Status))
5995 goto done;
5996
5997 FixedData.PrimaryGroupId = Buffer->PrimaryGroup.PrimaryGroupId;
5998
5999 Status = SampSetObjectAttribute(UserObject,
6000 L"F",
6001 REG_BINARY,
6002 &FixedData,
6003 Length);
6004
6005 done:
6006 return Status;
6007 }
6008
6009
6010 static NTSTATUS
6011 SampSetUserControl(PSAM_DB_OBJECT UserObject,
6012 PSAMPR_USER_INFO_BUFFER Buffer)
6013 {
6014 SAM_USER_FIXED_DATA FixedData;
6015 ULONG Length = 0;
6016 NTSTATUS Status;
6017
6018 Length = sizeof(SAM_USER_FIXED_DATA);
6019 Status = SampGetObjectAttribute(UserObject,
6020 L"F",
6021 NULL,
6022 (PVOID)&FixedData,
6023 &Length);
6024 if (!NT_SUCCESS(Status))
6025 goto done;
6026
6027 FixedData.UserAccountControl = Buffer->Control.UserAccountControl;
6028
6029 Status = SampSetObjectAttribute(UserObject,
6030 L"F",
6031 REG_BINARY,
6032 &FixedData,
6033 Length);
6034
6035 done:
6036 return Status;
6037 }
6038
6039
6040 static NTSTATUS
6041 SampSetUserExpires(PSAM_DB_OBJECT UserObject,
6042 PSAMPR_USER_INFO_BUFFER Buffer)
6043 {
6044 SAM_USER_FIXED_DATA FixedData;
6045 ULONG Length = 0;
6046 NTSTATUS Status;
6047
6048 Length = sizeof(SAM_USER_FIXED_DATA);
6049 Status = SampGetObjectAttribute(UserObject,
6050 L"F",
6051 NULL,
6052 (PVOID)&FixedData,
6053 &Length);
6054 if (!NT_SUCCESS(Status))
6055 goto done;
6056
6057 FixedData.AccountExpires.LowPart = Buffer->Expires.AccountExpires.LowPart;
6058 FixedData.AccountExpires.HighPart = Buffer->Expires.AccountExpires.HighPart;
6059
6060 Status = SampSetObjectAttribute(UserObject,
6061 L"F",
6062 REG_BINARY,
6063 &FixedData,
6064 Length);
6065
6066 done:
6067 return Status;
6068 }
6069
6070
6071 static NTSTATUS
6072 SampSetUserAll(PSAM_DB_OBJECT UserObject,
6073 PSAMPR_USER_INFO_BUFFER Buffer)
6074 {
6075 SAM_USER_FIXED_DATA FixedData;
6076 ULONG Length = 0;
6077 ULONG WhichFields;
6078 NTSTATUS Status = STATUS_SUCCESS;
6079
6080 WhichFields = Buffer->All.WhichFields;
6081
6082 if (WhichFields & USER_ALL_USERNAME)
6083 {
6084 Status = SampSetObjectAttribute(UserObject,
6085 L"Name",
6086 REG_SZ,
6087 Buffer->All.UserName.Buffer,
6088 Buffer->All.UserName.MaximumLength);
6089 if (!NT_SUCCESS(Status))
6090 goto done;
6091 }
6092
6093 if (WhichFields & USER_ALL_FULLNAME)
6094 {
6095 Status = SampSetObjectAttribute(UserObject,
6096 L"FullName",
6097 REG_SZ,
6098 Buffer->All.FullName.Buffer,
6099 Buffer->All.FullName.MaximumLength);
6100 if (!NT_SUCCESS(Status))
6101 goto done;
6102 }
6103
6104 if (WhichFields & USER_ALL_ADMINCOMMENT)
6105 {
6106 Status = SampSetObjectAttribute(UserObject,
6107 L"AdminComment",
6108 REG_SZ,
6109 Buffer->All.AdminComment.Buffer,
6110 Buffer->All.AdminComment.MaximumLength);
6111 if (!NT_SUCCESS(Status))
6112 goto done;
6113 }
6114
6115 if (WhichFields & USER_ALL_USERCOMMENT)
6116 {
6117 Status = SampSetObjectAttribute(UserObject,
6118 L"UserComment",
6119 REG_SZ,
6120 Buffer->All.UserComment.Buffer,
6121 Buffer->All.UserComment.MaximumLength);
6122 if (!NT_SUCCESS(Status))
6123 goto done;
6124 }
6125
6126 if (WhichFields & USER_ALL_HOMEDIRECTORY)
6127 {
6128 Status = SampSetObjectAttribute(UserObject,
6129 L"HomeDirectory",
6130 REG_SZ,
6131 Buffer->All.HomeDirectory.Buffer,
6132 Buffer->All.HomeDirectory.MaximumLength);
6133 if (!NT_SUCCESS(Status))
6134 goto done;
6135 }
6136
6137 if (WhichFields & USER_ALL_HOMEDIRECTORYDRIVE)
6138 {
6139 Status = SampSetObjectAttribute(UserObject,
6140 L"HomeDirectoryDrive",
6141 REG_SZ,
6142 Buffer->All.HomeDirectoryDrive.Buffer,
6143 Buffer->All.HomeDirectoryDrive.MaximumLength);
6144 if (!NT_SUCCESS(Status))
6145 goto done;
6146 }
6147
6148 if (WhichFields & USER_ALL_SCRIPTPATH)
6149 {
6150 Status = SampSetObjectAttribute(UserObject,
6151 L"ScriptPath",
6152 REG_SZ,
6153 Buffer->All.ScriptPath.Buffer,
6154 Buffer->All.ScriptPath.MaximumLength);
6155 if (!NT_SUCCESS(Status))
6156 goto done;
6157 }
6158
6159 if (WhichFields & USER_ALL_PROFILEPATH)
6160 {
6161 Status = SampSetObjectAttribute(UserObject,
6162 L"ProfilePath",
6163 REG_SZ,
6164 Buffer->All.ProfilePath.Buffer,
6165 Buffer->All.ProfilePath.MaximumLength);
6166 if (!NT_SUCCESS(Status))
6167 goto done;
6168 }
6169
6170 if (WhichFields & USER_ALL_WORKSTATIONS)
6171 {
6172 Status = SampSetObjectAttribute(UserObject,
6173 L"WorkStations",
6174 REG_SZ,
6175 Buffer->All.WorkStations.Buffer,
6176 Buffer->All.WorkStations.MaximumLength);
6177 if (!NT_SUCCESS(Status))
6178 goto done;
6179 }
6180
6181 if (WhichFields & USER_ALL_PARAMETERS)
6182 {
6183 Status = SampSetObjectAttribute(UserObject,
6184 L"Parameters",
6185 REG_SZ,
6186 Buffer->All.Parameters.Buffer,
6187 Buffer->All.Parameters.MaximumLength);
6188 }
6189
6190 if (WhichFields & (USER_ALL_PRIMARYGROUPID |
6191 USER_ALL_ACCOUNTEXPIRES |
6192 USER_ALL_USERACCOUNTCONTROL |
6193 USER_ALL_COUNTRYCODE |
6194 USER_ALL_CODEPAGE))
6195 {
6196 Length = sizeof(SAM_USER_FIXED_DATA);
6197 Status = SampGetObjectAttribute(UserObject,
6198 L"F",
6199 NULL,
6200 (PVOID)&FixedData,
6201 &Length);
6202 if (!NT_SUCCESS(Status))
6203 goto done;
6204
6205 if (WhichFields & USER_ALL_PRIMARYGROUPID)
6206 FixedData.PrimaryGroupId = Buffer->All.PrimaryGroupId;
6207
6208 if (WhichFields & USER_ALL_ACCOUNTEXPIRES)
6209 {
6210 FixedData.AccountExpires.LowPart = Buffer->All.AccountExpires.LowPart;
6211 FixedData.AccountExpires.HighPart = Buffer->All.AccountExpires.HighPart;
6212 }
6213
6214 if (WhichFields & USER_ALL_USERACCOUNTCONTROL)
6215 FixedData.UserAccountControl = Buffer->All.UserAccountControl;
6216
6217 if (WhichFields & USER_ALL_COUNTRYCODE)
6218 FixedData.CountryCode = Buffer->Preferences.CountryCode;
6219
6220 if (WhichFields & USER_ALL_CODEPAGE)
6221 FixedData.CodePage = Buffer->Preferences.CodePage;
6222
6223 Status = SampSetObjectAttribute(UserObject,
6224 L"F",
6225 REG_BINARY,
6226 &FixedData,
6227 Length);
6228 if (!NT_SUCCESS(Status))
6229 goto done;
6230 }
6231
6232 /*
6233 FIXME:
6234 USER_ALL_LOGONHOURS
6235 USER_ALL_NTPASSWORDPRESENT
6236 USER_ALL_LMPASSWORDPRESENT
6237 USER_ALL_PASSWORDEXPIRED
6238 */
6239
6240 done:
6241
6242 return Status;
6243 }
6244
6245
6246 /* Function 37 */
6247 NTSTATUS
6248 NTAPI
6249 SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
6250 IN USER_INFORMATION_CLASS UserInformationClass,
6251 IN PSAMPR_USER_INFO_BUFFER Buffer)
6252 {
6253 PSAM_DB_OBJECT UserObject;
6254 ACCESS_MASK DesiredAccess;
6255 NTSTATUS Status;
6256
6257 TRACE("SamrSetInformationUser(%p %lu %p)\n",
6258 UserHandle, UserInformationClass, Buffer);
6259
6260 switch (UserInformationClass)
6261 {
6262 case UserLogonHoursInformation:
6263 case UserNameInformation:
6264 case UserAccountNameInformation:
6265 case UserFullNameInformation:
6266 case UserPrimaryGroupInformation:
6267 case UserHomeInformation:
6268 case UserScriptInformation:
6269 case UserProfileInformation:
6270 case UserAdminCommentInformation:
6271 case UserWorkStationsInformation:
6272 case UserControlInformation:
6273 case UserExpiresInformation:
6274 case UserParametersInformation:
6275 DesiredAccess = USER_WRITE_ACCOUNT;
6276 break;
6277
6278 case UserGeneralInformation:
6279 DesiredAccess = USER_WRITE_ACCOUNT |
6280 USER_WRITE_PREFERENCES;
6281 break;
6282
6283 case UserPreferencesInformation:
6284 DesiredAccess = USER_WRITE_PREFERENCES;
6285 break;
6286
6287 case UserSetPasswordInformation:
6288 DesiredAccess = USER_FORCE_PASSWORD_CHANGE;
6289 break;
6290
6291 case UserAllInformation:
6292 DesiredAccess = 0; /* FIXME */
6293 break;
6294
6295 default:
6296 return STATUS_INVALID_INFO_CLASS;
6297 }
6298
6299 /* Validate the domain handle */
6300 Status = SampValidateDbObject(UserHandle,
6301 SamDbUserObject,
6302 DesiredAccess,
6303 &UserObject);
6304 if (!NT_SUCCESS(Status))
6305 {
6306 TRACE("failed with status 0x%08lx\n", Status);
6307 return Status;
6308 }
6309
6310 switch (UserInformationClass)
6311 {
6312 case UserGeneralInformation:
6313 Status = SampSetUserGeneral(UserObject,
6314 Buffer);
6315 break;
6316
6317 case UserPreferencesInformation:
6318 Status = SampSetUserPreferences(UserObject,
6319 Buffer);
6320 break;
6321 /*
6322 case UserLogonHoursInformation:
6323 Status = SampSetUserLogonHours(UserObject,
6324 Buffer);
6325 break;
6326 */
6327 case UserNameInformation:
6328 Status = SampSetObjectAttribute(UserObject,
6329 L"Name",
6330 REG_SZ,
6331 Buffer->Name.UserName.Buffer,
6332 Buffer->Name.UserName.MaximumLength);
6333 if (!NT_SUCCESS(Status))
6334 break;
6335
6336 Status = SampSetObjectAttribute(UserObject,
6337 L"FullName",
6338 REG_SZ,
6339 Buffer->Name.FullName.Buffer,
6340 Buffer->Name.FullName.MaximumLength);
6341 break;
6342
6343 case UserAccountNameInformation:
6344 Status = SampSetObjectAttribute(UserObject,
6345 L"Name",
6346 REG_SZ,
6347 Buffer->AccountName.UserName.Buffer,
6348 Buffer->AccountName.UserName.MaximumLength);
6349 break;
6350
6351 case UserFullNameInformation:
6352 Status = SampSetObjectAttribute(UserObject,
6353 L"FullName",
6354 REG_SZ,
6355 Buffer->FullName.FullName.Buffer,
6356 Buffer->FullName.FullName.MaximumLength);
6357 break;
6358
6359 case UserPrimaryGroupInformation:
6360 Status = SampSetUserPrimaryGroup(UserObject,
6361 Buffer);
6362 break;
6363
6364 case UserHomeInformation:
6365 Status = SampSetObjectAttribute(UserObject,
6366 L"HomeDirectory",
6367 REG_SZ,
6368 Buffer->Home.HomeDirectory.Buffer,
6369 Buffer->Home.HomeDirectory.MaximumLength);
6370 if (!NT_SUCCESS(Status))
6371 break;
6372
6373 Status = SampSetObjectAttribute(UserObject,
6374 L"HomeDirectoryDrive",
6375 REG_SZ,
6376 Buffer->Home.HomeDirectoryDrive.Buffer,
6377 Buffer->Home.HomeDirectoryDrive.MaximumLength);
6378 break;
6379
6380 case UserScriptInformation:
6381 Status = SampSetObjectAttribute(UserObject,
6382 L"ScriptPath",
6383 REG_SZ,
6384 Buffer->Script.ScriptPath.Buffer,
6385 Buffer->Script.ScriptPath.MaximumLength);
6386 break;
6387
6388 case UserProfileInformation:
6389 Status = SampSetObjectAttribute(UserObject,
6390 L"ProfilePath",
6391 REG_SZ,
6392 Buffer->Profile.ProfilePath.Buffer,
6393 Buffer->Profile.ProfilePath.MaximumLength);
6394 break;
6395
6396 case UserAdminCommentInformation:
6397 Status = SampSetObjectAttribute(UserObject,
6398 L"AdminComment",
6399 REG_SZ,
6400 Buffer->AdminComment.AdminComment.Buffer,
6401 Buffer->AdminComment.AdminComment.MaximumLength);
6402 break;
6403
6404 case UserWorkStationsInformation:
6405 Status = SampSetObjectAttribute(UserObject,
6406 L"WorkStations",
6407 REG_SZ,
6408 Buffer->WorkStations.WorkStations.Buffer,
6409 Buffer->WorkStations.WorkStations.MaximumLength);
6410 break;
6411
6412 case UserSetPasswordInformation:
6413 TRACE("Password: %S\n", Buffer->SetPassword.Password.Buffer);
6414 TRACE("PasswordExpired: %d\n", Buffer->SetPassword.PasswordExpired);
6415
6416 Status = SampSetObjectAttribute(UserObject,
6417 L"Password",
6418 REG_SZ,
6419 Buffer->SetPassword.Password.Buffer,
6420 Buffer->SetPassword.Password.MaximumLength);
6421 break;
6422
6423 case UserControlInformation:
6424 Status = SampSetUserControl(UserObject,
6425 Buffer);
6426 break;
6427
6428 case UserExpiresInformation:
6429 Status = SampSetUserExpires(UserObject,
6430 Buffer);
6431 break;
6432
6433 // case UserInternal1Information:
6434
6435 case UserParametersInformation:
6436 Status = SampSetObjectAttribute(UserObject,
6437 L"Parameters",
6438 REG_SZ,
6439 Buffer->Parameters.Parameters.Buffer,
6440 Buffer->Parameters.Parameters.MaximumLength);
6441 break;
6442
6443 case UserAllInformation:
6444 Status = SampSetUserAll(UserObject,
6445 Buffer);
6446 break;
6447
6448 // case UserInternal4Information:
6449 // case UserInternal5Information:
6450 // case UserInternal4InformationNew:
6451 // case UserInternal5InformationNew:
6452
6453 default:
6454 Status = STATUS_INVALID_INFO_CLASS;
6455 }
6456
6457 return Status;
6458 }
6459
6460
6461 /* Function 38 */
6462 NTSTATUS
6463 NTAPI
6464 SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
6465 IN unsigned char LmPresent,
6466 IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm,
6467 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm,
6468 IN unsigned char NtPresent,
6469 IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt,
6470 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt,
6471 IN unsigned char NtCrossEncryptionPresent,
6472 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm,
6473 IN unsigned char LmCrossEncryptionPresent,
6474 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt)
6475 {
6476 UNIMPLEMENTED;
6477 return STATUS_NOT_IMPLEMENTED;
6478 }
6479
6480 /* Function 39 */
6481 NTSTATUS
6482 NTAPI
6483 SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle,
6484 OUT PSAMPR_GET_GROUPS_BUFFER *Groups)
6485 {
6486 UNIMPLEMENTED;
6487 return STATUS_NOT_IMPLEMENTED;
6488 }
6489
6490 /* Function 40 */
6491 NTSTATUS
6492 NTAPI
6493 SamrQueryDisplayInformation(IN SAMPR_HANDLE DomainHandle,
6494 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
6495 IN unsigned long Index,
6496 IN unsigned long EntryCount,
6497 IN unsigned long PreferredMaximumLength,
6498 OUT unsigned long *TotalAvailable,
6499 OUT unsigned long *TotalReturned,
6500 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
6501 {
6502 UNIMPLEMENTED;
6503 return STATUS_NOT_IMPLEMENTED;
6504 }
6505
6506 /* Function 41 */
6507 NTSTATUS
6508 NTAPI
6509 SamrGetDisplayEnumerationIndex(IN SAMPR_HANDLE DomainHandle,
6510 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
6511 IN PRPC_UNICODE_STRING Prefix,
6512 OUT unsigned long *Index)
6513 {
6514 UNIMPLEMENTED;
6515 return STATUS_NOT_IMPLEMENTED;
6516 }
6517
6518 /* Function 42 */
6519 NTSTATUS
6520 NTAPI
6521 SamrTestPrivateFunctionsDomain(IN SAMPR_HANDLE DomainHandle)
6522 {
6523 UNIMPLEMENTED;
6524 return STATUS_NOT_IMPLEMENTED;
6525 }
6526
6527 /* Function 43 */
6528 NTSTATUS
6529 NTAPI
6530 SamrTestPrivateFunctionsUser(IN SAMPR_HANDLE UserHandle)
6531 {
6532 UNIMPLEMENTED;
6533 return STATUS_NOT_IMPLEMENTED;
6534 }
6535
6536 /* Function 44 */
6537 NTSTATUS
6538 NTAPI
6539 SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
6540 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
6541 {
6542 UNIMPLEMENTED;
6543 return STATUS_NOT_IMPLEMENTED;
6544 }
6545
6546 /* Function 45 */
6547 NTSTATUS
6548 NTAPI
6549 SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
6550 IN PRPC_SID MemberSid)
6551 {
6552 UNIMPLEMENTED;
6553 return STATUS_NOT_IMPLEMENTED;
6554 }
6555
6556 /* Function 46 */
6557 NTSTATUS
6558 NTAPI
6559 SamrQueryInformationDomain2(IN SAMPR_HANDLE DomainHandle,
6560 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
6561 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
6562 {
6563 UNIMPLEMENTED;
6564 return STATUS_NOT_IMPLEMENTED;
6565 }
6566
6567 /* Function 47 */
6568 NTSTATUS
6569 NTAPI
6570 SamrQueryInformationUser2(IN SAMPR_HANDLE UserHandle,
6571 IN USER_INFORMATION_CLASS UserInformationClass,
6572 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
6573 {
6574 UNIMPLEMENTED;
6575 return STATUS_NOT_IMPLEMENTED;
6576 }
6577
6578 /* Function 48 */
6579 NTSTATUS
6580 NTAPI
6581 SamrQueryDisplayInformation2(IN SAMPR_HANDLE DomainHandle,
6582 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
6583 IN unsigned long Index,
6584 IN unsigned long EntryCount,
6585 IN unsigned long PreferredMaximumLength,
6586 OUT unsigned long *TotalAvailable,
6587 OUT unsigned long *TotalReturned,
6588 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
6589 {
6590 UNIMPLEMENTED;
6591 return STATUS_NOT_IMPLEMENTED;
6592 }
6593
6594 /* Function 49 */
6595 NTSTATUS
6596 NTAPI
6597 SamrGetDisplayEnumerationIndex2(IN SAMPR_HANDLE DomainHandle,
6598 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
6599 IN PRPC_UNICODE_STRING Prefix,
6600 OUT unsigned long *Index)
6601 {
6602 UNIMPLEMENTED;
6603 return STATUS_NOT_IMPLEMENTED;
6604 }
6605
6606
6607 /* Function 50 */
6608 NTSTATUS
6609 NTAPI
6610 SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
6611 IN PRPC_UNICODE_STRING Name,
6612 IN unsigned long AccountType,
6613 IN ACCESS_MASK DesiredAccess,
6614 OUT SAMPR_HANDLE *UserHandle,
6615 OUT unsigned long *GrantedAccess,
6616 OUT unsigned long *RelativeId)
6617 {
6618 UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
6619 SAM_DOMAIN_FIXED_DATA FixedDomainData;
6620 SAM_USER_FIXED_DATA FixedUserData;
6621 PSAM_DB_OBJECT DomainObject;
6622 PSAM_DB_OBJECT UserObject;
6623 ULONG ulSize;
6624 ULONG ulRid;
6625 WCHAR szRid[9];
6626 NTSTATUS Status;
6627
6628 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
6629 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
6630
6631 if (Name == NULL ||
6632 Name->Length == 0 ||
6633 Name->Buffer == NULL ||
6634 UserHandle == NULL ||
6635 RelativeId == NULL)
6636 return STATUS_INVALID_PARAMETER;
6637
6638 /* Check for valid account type */
6639 if (AccountType != USER_NORMAL_ACCOUNT &&
6640 AccountType != USER_WORKSTATION_TRUST_ACCOUNT &&
6641 AccountType != USER_INTERDOMAIN_TRUST_ACCOUNT &&
6642 AccountType != USER_SERVER_TRUST_ACCOUNT &&
6643 AccountType != USER_TEMP_DUPLICATE_ACCOUNT)
6644 return STATUS_INVALID_PARAMETER;
6645
6646 /* Map generic access rights */
6647 RtlMapGenericMask(&DesiredAccess,
6648 &UserMapping);
6649
6650 /* Validate the domain handle */
6651 Status = SampValidateDbObject(DomainHandle,
6652 SamDbDomainObject,
6653 DOMAIN_CREATE_USER,
6654 &DomainObject);
6655 if (!NT_SUCCESS(Status))
6656 {
6657 TRACE("failed with status 0x%08lx\n", Status);
6658 return Status;
6659 }
6660
6661 /* Check if the user name already exists in the domain */
6662 Status = SampCheckAccountNameInDomain(DomainObject,
6663 Name->Buffer);
6664 if (!NT_SUCCESS(Status))
6665 {
6666 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n",
6667 Name->Buffer, Status);
6668 return Status;
6669 }
6670
6671 /* Get the fixed domain attributes */
6672 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
6673 Status = SampGetObjectAttribute(DomainObject,
6674 L"F",
6675 NULL,
6676 (PVOID)&FixedDomainData,
6677 &ulSize);
6678 if (!NT_SUCCESS(Status))
6679 {
6680 TRACE("failed with status 0x%08lx\n", Status);
6681 return Status;
6682 }
6683
6684 /* Increment the NextRid attribute */
6685 ulRid = FixedDomainData.NextRid;
6686 FixedDomainData.NextRid++;
6687
6688 /* Store the fixed domain attributes */
6689 Status = SampSetObjectAttribute(DomainObject,
6690 L"F",
6691 REG_BINARY,
6692 &FixedDomainData,
6693 ulSize);
6694 if (!NT_SUCCESS(Status))
6695 {
6696 TRACE("failed with status 0x%08lx\n", Status);
6697 return Status;
6698 }
6699
6700 TRACE("RID: %lx\n", ulRid);
6701
6702 /* Convert the RID into a string (hex) */
6703 swprintf(szRid, L"%08lX", ulRid);
6704
6705 /* Create the user object */
6706 Status = SampCreateDbObject(DomainObject,
6707 L"Users",
6708 szRid,
6709 ulRid,
6710 SamDbUserObject,
6711 DesiredAccess,
6712 &UserObject);
6713 if (!NT_SUCCESS(Status))
6714 {
6715 TRACE("failed with status 0x%08lx\n", Status);
6716 return Status;
6717 }
6718
6719 /* Add the account name for the user object */
6720 Status = SampSetAccountNameInDomain(DomainObject,
6721 L"Users",
6722 Name->Buffer,
6723 ulRid);
6724 if (!NT_SUCCESS(Status))
6725 {
6726 TRACE("failed with status 0x%08lx\n", Status);
6727 return Status;
6728 }
6729
6730 /* Initialize fixed user data */
6731 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
6732 FixedUserData.Version = 1;
6733 FixedUserData.LastLogon.QuadPart = 0;
6734 FixedUserData.LastLogoff.QuadPart = 0;
6735 FixedUserData.PasswordLastSet.QuadPart = 0;
6736 FixedUserData.AccountExpires.LowPart = MAXULONG;
6737 FixedUserData.AccountExpires.HighPart = MAXLONG;
6738 FixedUserData.LastBadPasswordTime.QuadPart = 0;
6739 FixedUserData.UserId = ulRid;
6740 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS;
6741 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED |
6742 USER_PASSWORD_NOT_REQUIRED |
6743 AccountType;
6744
6745 /* Set fixed user data attribute */
6746 Status = SampSetObjectAttribute(UserObject,
6747 L"F",
6748 REG_BINARY,
6749 (LPVOID)&FixedUserData,
6750 sizeof(SAM_USER_FIXED_DATA));
6751 if (!NT_SUCCESS(Status))
6752 {
6753 TRACE("failed with status 0x%08lx\n", Status);
6754 return Status;
6755 }
6756
6757 /* Set the Name attribute */
6758 Status = SampSetObjectAttribute(UserObject,
6759 L"Name",
6760 REG_SZ,
6761 (LPVOID)Name->Buffer,
6762 Name->MaximumLength);
6763 if (!NT_SUCCESS(Status))
6764 {
6765 TRACE("failed with status 0x%08lx\n", Status);
6766 return Status;
6767 }
6768
6769 /* Set the FullName attribute */
6770 Status = SampSetObjectAttribute(UserObject,
6771 L"FullName",
6772 REG_SZ,
6773 EmptyString.Buffer,
6774 EmptyString.MaximumLength);
6775 if (!NT_SUCCESS(Status))
6776 {
6777 TRACE("failed with status 0x%08lx\n", Status);
6778 return Status;
6779 }
6780
6781 /* Set the HomeDirectory attribute */
6782 Status = SampSetObjectAttribute(UserObject,
6783 L"HomeDirectory",
6784 REG_SZ,
6785 EmptyString.Buffer,
6786 EmptyString.MaximumLength);
6787 if (!NT_SUCCESS(Status))
6788 {
6789 TRACE("failed with status 0x%08lx\n", Status);
6790 return Status;
6791 }
6792
6793 /* Set the HomeDirectoryDrive attribute */
6794 Status = SampSetObjectAttribute(UserObject,
6795 L"HomeDirectoryDrive",
6796 REG_SZ,
6797 EmptyString.Buffer,
6798 EmptyString.MaximumLength);
6799 if (!NT_SUCCESS(Status))
6800 {
6801 TRACE("failed with status 0x%08lx\n", Status);
6802 return Status;
6803 }
6804
6805 /* Set the ScriptPath attribute */
6806 Status = SampSetObjectAttribute(UserObject,
6807 L"ScriptPath",
6808 REG_SZ,
6809 EmptyString.Buffer,
6810 EmptyString.MaximumLength);
6811 if (!NT_SUCCESS(Status))
6812 {
6813 TRACE("failed with status 0x%08lx\n", Status);
6814 return Status;
6815 }
6816
6817 /* Set the ProfilePath attribute */
6818 Status = SampSetObjectAttribute(UserObject,
6819 L"ProfilePath",
6820 REG_SZ,
6821 EmptyString.Buffer,
6822 EmptyString.MaximumLength);
6823 if (!NT_SUCCESS(Status))
6824 {
6825 TRACE("failed with status 0x%08lx\n", Status);
6826 return Status;
6827 }
6828
6829 /* Set the AdminComment attribute */
6830 Status = SampSetObjectAttribute(UserObject,
6831 L"AdminComment",
6832 REG_SZ,
6833 EmptyString.Buffer,
6834 EmptyString.MaximumLength);
6835 if (!NT_SUCCESS(Status))
6836 {
6837 TRACE("failed with status 0x%08lx\n", Status);
6838 return Status;
6839 }
6840
6841 /* Set the UserComment attribute */
6842 Status = SampSetObjectAttribute(UserObject,
6843 L"UserComment",
6844 REG_SZ,
6845 EmptyString.Buffer,
6846 EmptyString.MaximumLength);
6847 if (!NT_SUCCESS(Status))
6848 {
6849 TRACE("failed with status 0x%08lx\n", Status);
6850 return Status;
6851 }
6852
6853 /* Set the WorkStations attribute */
6854 Status = SampSetObjectAttribute(UserObject,
6855 L"WorkStations",
6856 REG_SZ,
6857 EmptyString.Buffer,
6858 EmptyString.MaximumLength);
6859 if (!NT_SUCCESS(Status))
6860 {
6861 TRACE("failed with status 0x%08lx\n", Status);
6862 return Status;
6863 }
6864
6865 /* FIXME: Set default user attributes */
6866
6867 if (NT_SUCCESS(Status))
6868 {
6869 *UserHandle = (SAMPR_HANDLE)UserObject;
6870 *RelativeId = ulRid;
6871 *GrantedAccess = UserObject->Access;
6872 }
6873
6874 TRACE("returns with status 0x%08lx\n", Status);
6875
6876 return Status;
6877 }
6878
6879
6880 /* Function 51 */
6881 NTSTATUS
6882 NTAPI
6883 SamrQueryDisplayInformation3(IN SAMPR_HANDLE DomainHandle,
6884 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
6885 IN unsigned long Index,
6886 IN unsigned long EntryCount,
6887 IN unsigned long PreferredMaximumLength,
6888 OUT unsigned long *TotalAvailable,
6889 OUT unsigned long *TotalReturned,
6890 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
6891 {
6892 UNIMPLEMENTED;
6893 return STATUS_NOT_IMPLEMENTED;
6894 }
6895
6896
6897 /* Function 52 */
6898 NTSTATUS
6899 NTAPI
6900 SamrAddMultipleMembersToAlias(IN SAMPR_HANDLE AliasHandle,
6901 IN PSAMPR_PSID_ARRAY MembersBuffer)
6902 {
6903 ULONG i;
6904 NTSTATUS Status = STATUS_SUCCESS;
6905
6906 TRACE("SamrAddMultipleMembersToAlias(%p %p)\n",
6907 AliasHandle, MembersBuffer);
6908
6909 for (i = 0; i < MembersBuffer->Count; i++)
6910 {
6911 Status = SamrAddMemberToAlias(AliasHandle,
6912 ((PSID *)MembersBuffer->Sids)[i]);
6913
6914 if (Status == STATUS_MEMBER_IN_ALIAS)
6915 Status = STATUS_SUCCESS;
6916
6917 if (!NT_SUCCESS(Status))
6918 break;
6919 }
6920
6921 return Status;
6922 }
6923
6924
6925 /* Function 53 */
6926 NTSTATUS
6927 NTAPI
6928 SamrRemoveMultipleMembersFromAlias(IN SAMPR_HANDLE AliasHandle,
6929 IN PSAMPR_PSID_ARRAY MembersBuffer)
6930 {
6931 ULONG i;
6932 NTSTATUS Status = STATUS_SUCCESS;
6933
6934 TRACE("SamrRemoveMultipleMembersFromAlias(%p %p)\n",
6935 AliasHandle, MembersBuffer);
6936
6937 for (i = 0; i < MembersBuffer->Count; i++)
6938 {
6939 Status = SamrRemoveMemberFromAlias(AliasHandle,
6940 ((PSID *)MembersBuffer->Sids)[i]);
6941
6942 if (Status == STATUS_MEMBER_IN_ALIAS)
6943 Status = STATUS_SUCCESS;
6944
6945 if (!NT_SUCCESS(Status))
6946 break;
6947 }
6948
6949 return Status;
6950 }
6951
6952
6953 /* Function 54 */
6954 NTSTATUS
6955 NTAPI
6956 SamrOemChangePasswordUser2(IN handle_t BindingHandle,
6957 IN PRPC_STRING ServerName,
6958 IN PRPC_STRING UserName,
6959 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
6960 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewLm)
6961 {
6962 UNIMPLEMENTED;
6963 return STATUS_NOT_IMPLEMENTED;
6964 }
6965
6966 /* Function 55 */
6967 NTSTATUS
6968 NTAPI
6969 SamrUnicodeChangePasswordUser2(IN handle_t BindingHandle,
6970 IN PRPC_UNICODE_STRING ServerName,
6971 IN PRPC_UNICODE_STRING UserName,
6972 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldNt,
6973 IN PENCRYPTED_NT_OWF_PASSWORD OldNtOwfPasswordEncryptedWithNewNt,
6974 IN unsigned char LmPresent,
6975 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
6976 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewNt)
6977 {
6978 UNIMPLEMENTED;
6979 return STATUS_NOT_IMPLEMENTED;
6980 }
6981
6982 /* Function 56 */
6983 NTSTATUS
6984 NTAPI
6985 SamrGetDomainPasswordInformation(IN handle_t BindingHandle,
6986 IN PRPC_UNICODE_STRING Unused,
6987 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
6988 {
6989 UNIMPLEMENTED;
6990 return STATUS_NOT_IMPLEMENTED;
6991 }
6992
6993 /* Function 57 */
6994 NTSTATUS
6995 NTAPI
6996 SamrConnect2(IN PSAMPR_SERVER_NAME ServerName,
6997 OUT SAMPR_HANDLE *ServerHandle,
6998 IN ACCESS_MASK DesiredAccess)
6999 {
7000 UNIMPLEMENTED;
7001 return STATUS_NOT_IMPLEMENTED;
7002 }
7003
7004
7005 /* Function 58 */
7006 NTSTATUS
7007 NTAPI
7008 SamrSetInformationUser2(IN SAMPR_HANDLE UserHandle,
7009 IN USER_INFORMATION_CLASS UserInformationClass,
7010 IN PSAMPR_USER_INFO_BUFFER Buffer)
7011 {
7012 TRACE("(%p %lu %p)\n", UserHandle, UserInformationClass, Buffer);
7013
7014 return SamrSetInformationUser(UserHandle,
7015 UserInformationClass,
7016 Buffer);
7017 }
7018
7019
7020 /* Function 59 */
7021 NTSTATUS
7022 NTAPI
7023 SamrSetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
7024 {
7025 UNIMPLEMENTED;
7026 return STATUS_NOT_IMPLEMENTED;
7027 }
7028
7029 /* Function 60 */
7030 NTSTATUS
7031 NTAPI
7032 SamrGetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
7033 {
7034 UNIMPLEMENTED;
7035 return STATUS_NOT_IMPLEMENTED;
7036 }
7037
7038 /* Function 61 */
7039 NTSTATUS
7040 NTAPI
7041 SamrConnect3(IN handle_t BindingHandle) /* FIXME */
7042 {
7043 UNIMPLEMENTED;
7044 return STATUS_NOT_IMPLEMENTED;
7045 }
7046
7047 /* Function 62 */
7048 NTSTATUS
7049 NTAPI
7050 SamrConnect4(IN PSAMPR_SERVER_NAME ServerName,
7051 OUT SAMPR_HANDLE *ServerHandle,
7052 IN unsigned long ClientRevision,
7053 IN ACCESS_MASK DesiredAccess)
7054 {
7055 UNIMPLEMENTED;
7056 return STATUS_NOT_IMPLEMENTED;
7057 }
7058
7059 /* Function 63 */
7060 NTSTATUS
7061 NTAPI
7062 SamrUnicodeChangePasswordUser3(IN handle_t BindingHandle) /* FIXME */
7063 {
7064 UNIMPLEMENTED;
7065 return STATUS_NOT_IMPLEMENTED;
7066 }
7067
7068 /* Function 64 */
7069 NTSTATUS
7070 NTAPI
7071 SamrConnect5(IN PSAMPR_SERVER_NAME ServerName,
7072 IN ACCESS_MASK DesiredAccess,
7073 IN unsigned long InVersion,
7074 IN SAMPR_REVISION_INFO *InRevisionInfo,
7075 OUT unsigned long *OutVersion,
7076 OUT SAMPR_REVISION_INFO *OutRevisionInfo,
7077 OUT SAMPR_HANDLE *ServerHandle)
7078 {
7079 UNIMPLEMENTED;
7080 return STATUS_NOT_IMPLEMENTED;
7081 }
7082
7083 /* Function 65 */
7084 NTSTATUS
7085 NTAPI
7086 SamrRidToSid(IN SAMPR_HANDLE ObjectHandle,
7087 IN unsigned long Rid,
7088 OUT PRPC_SID *Sid)
7089 {
7090 UNIMPLEMENTED;
7091 return STATUS_NOT_IMPLEMENTED;
7092 }
7093
7094 /* Function 66 */
7095 NTSTATUS
7096 NTAPI
7097 SamrSetDSRMPassword(IN handle_t BindingHandle,
7098 IN PRPC_UNICODE_STRING Unused,
7099 IN unsigned long UserId,
7100 IN PENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword)
7101 {
7102 UNIMPLEMENTED;
7103 return STATUS_NOT_IMPLEMENTED;
7104 }
7105
7106 /* Function 67 */
7107 NTSTATUS
7108 NTAPI
7109 SamrValidatePassword(IN handle_t Handle,
7110 IN PASSWORD_POLICY_VALIDATION_TYPE ValidationType,
7111 IN PSAM_VALIDATE_INPUT_ARG InputArg,
7112 OUT PSAM_VALIDATE_OUTPUT_ARG *OutputArg)
7113 {
7114 UNIMPLEMENTED;
7115 return STATUS_NOT_IMPLEMENTED;
7116 }
7117
7118 /* EOF */