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