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