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