[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 Length = 0;
622 Status = SampGetObjectAttribute(DomainObject,
623 L"OemInformation",
624 NULL,
625 NULL,
626 &Length);
627 if (!NT_SUCCESS(Status))
628 goto done;
629
630 InfoBuffer->General.OemInformation.Length = Length - sizeof(WCHAR);
631 InfoBuffer->General.OemInformation.MaximumLength = Length;
632 InfoBuffer->General.OemInformation.Buffer = midl_user_allocate(Length);
633 if (InfoBuffer->General.OemInformation.Buffer == NULL)
634 {
635 Status = STATUS_INSUFFICIENT_RESOURCES;
636 goto done;
637 }
638
639 Status = SampGetObjectAttribute(DomainObject,
640 L"OemInformation",
641 NULL,
642 (PVOID)InfoBuffer->General.OemInformation.Buffer,
643 &Length);
644 if (!NT_SUCCESS(Status))
645 goto done;
646
647 Length = 0;
648 Status = SampGetObjectAttribute(DomainObject,
649 L"Name",
650 NULL,
651 NULL,
652 &Length);
653 if (!NT_SUCCESS(Status))
654 goto done;
655
656 InfoBuffer->General.DomainName.Length = Length - sizeof(WCHAR);
657 InfoBuffer->General.DomainName.MaximumLength = Length;
658 InfoBuffer->General.DomainName.Buffer = midl_user_allocate(Length);
659 if (InfoBuffer->General.DomainName.Buffer == NULL)
660 {
661 Status = STATUS_INSUFFICIENT_RESOURCES;
662 goto done;
663 }
664
665 Status = SampGetObjectAttribute(DomainObject,
666 L"Name",
667 NULL,
668 (PVOID)InfoBuffer->General.DomainName.Buffer,
669 &Length);
670 if (!NT_SUCCESS(Status))
671 goto done;
672
673 Length = 0;
674 Status = SampGetObjectAttribute(DomainObject,
675 L"ReplicaSourceNodeName",
676 NULL,
677 NULL,
678 &Length);
679 if (!NT_SUCCESS(Status))
680 goto done;
681
682 InfoBuffer->General.ReplicaSourceNodeName.Length = Length - sizeof(WCHAR);
683 InfoBuffer->General.ReplicaSourceNodeName.MaximumLength = Length;
684 InfoBuffer->General.ReplicaSourceNodeName.Buffer = midl_user_allocate(Length);
685 if (InfoBuffer->General.ReplicaSourceNodeName.Buffer == NULL)
686 {
687 Status = STATUS_INSUFFICIENT_RESOURCES;
688 goto done;
689 }
690
691 Status = SampGetObjectAttribute(DomainObject,
692 L"ReplicaSourceNodeName",
693 NULL,
694 (PVOID)InfoBuffer->General.ReplicaSourceNodeName.Buffer,
695 &Length);
696 if (!NT_SUCCESS(Status))
697 goto done;
698
699 InfoBuffer->General.UserCount = 0; /* FIXME */
700 InfoBuffer->General.GroupCount = 0; /* FIXME */
701 InfoBuffer->General.AliasCount = 0; /* FIXME */
702
703 *Buffer = InfoBuffer;
704
705 done:
706 if (!NT_SUCCESS(Status))
707 {
708 if (InfoBuffer != NULL)
709 {
710 if (InfoBuffer->General.OemInformation.Buffer != NULL)
711 midl_user_free(InfoBuffer->General.OemInformation.Buffer);
712
713 if (InfoBuffer->General.DomainName.Buffer != NULL)
714 midl_user_free(InfoBuffer->General.DomainName.Buffer);
715
716 if (InfoBuffer->General.ReplicaSourceNodeName.Buffer != NULL)
717 midl_user_free(InfoBuffer->General.ReplicaSourceNodeName.Buffer);
718
719 midl_user_free(InfoBuffer);
720 }
721 }
722
723 return Status;
724 }
725
726
727 static NTSTATUS
728 SampQueryDomainLogoff(PSAM_DB_OBJECT DomainObject,
729 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
730 {
731 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
732 SAM_DOMAIN_FIXED_DATA FixedData;
733 ULONG Length = 0;
734 NTSTATUS Status;
735
736 *Buffer = NULL;
737
738 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
739 if (InfoBuffer == NULL)
740 return STATUS_INSUFFICIENT_RESOURCES;
741
742 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
743 Status = SampGetObjectAttribute(DomainObject,
744 L"F",
745 NULL,
746 (PVOID)&FixedData,
747 &Length);
748 if (!NT_SUCCESS(Status))
749 goto done;
750
751 InfoBuffer->Logoff.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
752 InfoBuffer->Logoff.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
753
754 *Buffer = InfoBuffer;
755
756 done:
757 if (!NT_SUCCESS(Status))
758 {
759 if (InfoBuffer != NULL)
760 {
761 midl_user_free(InfoBuffer);
762 }
763 }
764
765 return Status;
766 }
767
768
769 static NTSTATUS
770 SampQueryDomainOem(PSAM_DB_OBJECT DomainObject,
771 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
772 {
773 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
774 ULONG Length = 0;
775 NTSTATUS Status;
776
777 *Buffer = NULL;
778
779 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
780 if (InfoBuffer == NULL)
781 return STATUS_INSUFFICIENT_RESOURCES;
782
783 Status = SampGetObjectAttribute(DomainObject,
784 L"OemInformation",
785 NULL,
786 NULL,
787 &Length);
788 if (!NT_SUCCESS(Status))
789 goto done;
790
791 InfoBuffer->Oem.OemInformation.Length = Length - sizeof(WCHAR);
792 InfoBuffer->Oem.OemInformation.MaximumLength = Length;
793 InfoBuffer->Oem.OemInformation.Buffer = midl_user_allocate(Length);
794 if (InfoBuffer->Oem.OemInformation.Buffer == NULL)
795 {
796 Status = STATUS_INSUFFICIENT_RESOURCES;
797 goto done;
798 }
799
800 Status = SampGetObjectAttribute(DomainObject,
801 L"OemInformation",
802 NULL,
803 (PVOID)InfoBuffer->Oem.OemInformation.Buffer,
804 &Length);
805 if (!NT_SUCCESS(Status))
806 goto done;
807
808 *Buffer = InfoBuffer;
809
810 done:
811 if (!NT_SUCCESS(Status))
812 {
813 if (InfoBuffer != NULL)
814 {
815 if (InfoBuffer->Oem.OemInformation.Buffer != NULL)
816 midl_user_free(InfoBuffer->Oem.OemInformation.Buffer);
817
818 midl_user_free(InfoBuffer);
819 }
820 }
821
822 return Status;
823 }
824
825
826 static NTSTATUS
827 SampQueryDomainName(PSAM_DB_OBJECT DomainObject,
828 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
829 {
830 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
831 ULONG Length = 0;
832 NTSTATUS Status;
833
834 *Buffer = NULL;
835
836 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
837 if (InfoBuffer == NULL)
838 return STATUS_INSUFFICIENT_RESOURCES;
839
840 Status = SampGetObjectAttribute(DomainObject,
841 L"Name",
842 NULL,
843 NULL,
844 &Length);
845 if (!NT_SUCCESS(Status))
846 goto done;
847
848 InfoBuffer->Name.DomainName.Length = Length - sizeof(WCHAR);
849 InfoBuffer->Name.DomainName.MaximumLength = Length;
850 InfoBuffer->Name.DomainName.Buffer = midl_user_allocate(Length);
851 if (InfoBuffer->Name.DomainName.Buffer == NULL)
852 {
853 Status = STATUS_INSUFFICIENT_RESOURCES;
854 goto done;
855 }
856
857 Status = SampGetObjectAttribute(DomainObject,
858 L"Name",
859 NULL,
860 (PVOID)InfoBuffer->Name.DomainName.Buffer,
861 &Length);
862 if (!NT_SUCCESS(Status))
863 goto done;
864
865 *Buffer = InfoBuffer;
866
867 done:
868 if (!NT_SUCCESS(Status))
869 {
870 if (InfoBuffer != NULL)
871 {
872 if (InfoBuffer->Name.DomainName.Buffer != NULL)
873 midl_user_free(InfoBuffer->Name.DomainName.Buffer);
874
875 midl_user_free(InfoBuffer);
876 }
877 }
878
879 return Status;
880 }
881
882
883 static NTSTATUS
884 SampQueryDomainReplication(PSAM_DB_OBJECT DomainObject,
885 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
886 {
887 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
888 ULONG Length = 0;
889 NTSTATUS Status;
890
891 *Buffer = NULL;
892
893 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
894 if (InfoBuffer == NULL)
895 return STATUS_INSUFFICIENT_RESOURCES;
896
897 Status = SampGetObjectAttribute(DomainObject,
898 L"ReplicaSourceNodeName",
899 NULL,
900 NULL,
901 &Length);
902 if (!NT_SUCCESS(Status))
903 goto done;
904
905 InfoBuffer->Replication.ReplicaSourceNodeName.Length = Length - sizeof(WCHAR);
906 InfoBuffer->Replication.ReplicaSourceNodeName.MaximumLength = Length;
907 InfoBuffer->Replication.ReplicaSourceNodeName.Buffer = midl_user_allocate(Length);
908 if (InfoBuffer->Replication.ReplicaSourceNodeName.Buffer == NULL)
909 {
910 Status = STATUS_INSUFFICIENT_RESOURCES;
911 goto done;
912 }
913
914 Status = SampGetObjectAttribute(DomainObject,
915 L"ReplicaSourceNodeName",
916 NULL,
917 (PVOID)InfoBuffer->Replication.ReplicaSourceNodeName.Buffer,
918 &Length);
919 if (!NT_SUCCESS(Status))
920 goto done;
921
922 *Buffer = InfoBuffer;
923
924 done:
925 if (!NT_SUCCESS(Status))
926 {
927 if (InfoBuffer != NULL)
928 {
929 if (InfoBuffer->Replication.ReplicaSourceNodeName.Buffer != NULL)
930 midl_user_free(InfoBuffer->Replication.ReplicaSourceNodeName.Buffer);
931
932 midl_user_free(InfoBuffer);
933 }
934 }
935
936 return Status;
937 }
938
939
940 static NTSTATUS
941 SampQueryDomainServerRole(PSAM_DB_OBJECT DomainObject,
942 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
943 {
944 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
945 SAM_DOMAIN_FIXED_DATA FixedData;
946 ULONG Length = 0;
947 NTSTATUS Status;
948
949 *Buffer = NULL;
950
951 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
952 if (InfoBuffer == NULL)
953 return STATUS_INSUFFICIENT_RESOURCES;
954
955 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
956 Status = SampGetObjectAttribute(DomainObject,
957 L"F",
958 NULL,
959 (PVOID)&FixedData,
960 &Length);
961 if (!NT_SUCCESS(Status))
962 goto done;
963
964 InfoBuffer->Role.DomainServerRole = FixedData.DomainServerRole;
965
966 *Buffer = InfoBuffer;
967
968 done:
969 if (!NT_SUCCESS(Status))
970 {
971 if (InfoBuffer != NULL)
972 {
973 midl_user_free(InfoBuffer);
974 }
975 }
976
977 return Status;
978 }
979
980
981 static NTSTATUS
982 SampQueryDomainModified(PSAM_DB_OBJECT DomainObject,
983 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
984 {
985 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
986 SAM_DOMAIN_FIXED_DATA FixedData;
987 ULONG Length = 0;
988 NTSTATUS Status;
989
990 *Buffer = NULL;
991
992 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
993 if (InfoBuffer == NULL)
994 return STATUS_INSUFFICIENT_RESOURCES;
995
996 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
997 Status = SampGetObjectAttribute(DomainObject,
998 L"F",
999 NULL,
1000 (PVOID)&FixedData,
1001 &Length);
1002 if (!NT_SUCCESS(Status))
1003 goto done;
1004
1005 InfoBuffer->Modified.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
1006 InfoBuffer->Modified.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
1007 InfoBuffer->Modified.CreationTime.LowPart = FixedData.CreationTime.LowPart;
1008 InfoBuffer->Modified.CreationTime.HighPart = FixedData.CreationTime.HighPart;
1009
1010 *Buffer = InfoBuffer;
1011
1012 done:
1013 if (!NT_SUCCESS(Status))
1014 {
1015 if (InfoBuffer != NULL)
1016 {
1017 midl_user_free(InfoBuffer);
1018 }
1019 }
1020
1021 return Status;
1022 }
1023
1024
1025 static NTSTATUS
1026 SampQueryDomainState(PSAM_DB_OBJECT DomainObject,
1027 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1028 {
1029 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1030 SAM_DOMAIN_FIXED_DATA FixedData;
1031 ULONG Length = 0;
1032 NTSTATUS Status;
1033
1034 *Buffer = NULL;
1035
1036 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1037 if (InfoBuffer == NULL)
1038 return STATUS_INSUFFICIENT_RESOURCES;
1039
1040 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1041 Status = SampGetObjectAttribute(DomainObject,
1042 L"F",
1043 NULL,
1044 (PVOID)&FixedData,
1045 &Length);
1046 if (!NT_SUCCESS(Status))
1047 goto done;
1048
1049 InfoBuffer->State.DomainServerState = FixedData.DomainServerState;
1050
1051 *Buffer = InfoBuffer;
1052
1053 done:
1054 if (!NT_SUCCESS(Status))
1055 {
1056 if (InfoBuffer != NULL)
1057 {
1058 midl_user_free(InfoBuffer);
1059 }
1060 }
1061
1062 return Status;
1063 }
1064
1065
1066 static NTSTATUS
1067 SampQueryDomainGeneral2(PSAM_DB_OBJECT DomainObject,
1068 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1069 {
1070 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1071 SAM_DOMAIN_FIXED_DATA FixedData;
1072 ULONG Length = 0;
1073 NTSTATUS Status;
1074
1075 *Buffer = NULL;
1076
1077 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1078 if (InfoBuffer == NULL)
1079 return STATUS_INSUFFICIENT_RESOURCES;
1080
1081 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1082 Status = SampGetObjectAttribute(DomainObject,
1083 L"F",
1084 NULL,
1085 (PVOID)&FixedData,
1086 &Length);
1087 if (!NT_SUCCESS(Status))
1088 goto done;
1089
1090 InfoBuffer->General2.I1.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart;
1091 InfoBuffer->General2.I1.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart;
1092 InfoBuffer->General2.I1.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
1093 InfoBuffer->General2.I1.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
1094 InfoBuffer->General2.I1.DomainServerState = FixedData.DomainServerState;
1095 InfoBuffer->General2.I1.DomainServerRole = FixedData.DomainServerRole;
1096 InfoBuffer->General2.I1.UasCompatibilityRequired = FixedData.UasCompatibilityRequired;
1097
1098 InfoBuffer->General2.LockoutDuration = FixedData.LockoutDuration;
1099 InfoBuffer->General2.LockoutObservationWindow = FixedData.LockoutObservationWindow;
1100 InfoBuffer->General2.LockoutThreshold = FixedData.LockoutThreshold;
1101
1102 Length = 0;
1103 Status = SampGetObjectAttribute(DomainObject,
1104 L"OemInformation",
1105 NULL,
1106 NULL,
1107 &Length);
1108 if (!NT_SUCCESS(Status))
1109 goto done;
1110
1111 InfoBuffer->General2.I1.OemInformation.Length = Length - sizeof(WCHAR);
1112 InfoBuffer->General2.I1.OemInformation.MaximumLength = Length;
1113 InfoBuffer->General2.I1.OemInformation.Buffer = midl_user_allocate(Length);
1114 if (InfoBuffer->General2.I1.OemInformation.Buffer == NULL)
1115 {
1116 Status = STATUS_INSUFFICIENT_RESOURCES;
1117 goto done;
1118 }
1119
1120 Status = SampGetObjectAttribute(DomainObject,
1121 L"OemInformation",
1122 NULL,
1123 (PVOID)InfoBuffer->General2.I1.OemInformation.Buffer,
1124 &Length);
1125 if (!NT_SUCCESS(Status))
1126 goto done;
1127
1128 Length = 0;
1129 Status = SampGetObjectAttribute(DomainObject,
1130 L"Name",
1131 NULL,
1132 NULL,
1133 &Length);
1134 if (!NT_SUCCESS(Status))
1135 goto done;
1136
1137 InfoBuffer->General2.I1.DomainName.Length = Length - sizeof(WCHAR);
1138 InfoBuffer->General2.I1.DomainName.MaximumLength = Length;
1139 InfoBuffer->General2.I1.DomainName.Buffer = midl_user_allocate(Length);
1140 if (InfoBuffer->General2.I1.DomainName.Buffer == NULL)
1141 {
1142 Status = STATUS_INSUFFICIENT_RESOURCES;
1143 goto done;
1144 }
1145
1146 Status = SampGetObjectAttribute(DomainObject,
1147 L"Name",
1148 NULL,
1149 (PVOID)InfoBuffer->General2.I1.DomainName.Buffer,
1150 &Length);
1151 if (!NT_SUCCESS(Status))
1152 goto done;
1153
1154 Length = 0;
1155 Status = SampGetObjectAttribute(DomainObject,
1156 L"ReplicaSourceNodeName",
1157 NULL,
1158 NULL,
1159 &Length);
1160 if (!NT_SUCCESS(Status))
1161 goto done;
1162
1163 InfoBuffer->General2.I1.ReplicaSourceNodeName.Length = Length - sizeof(WCHAR);
1164 InfoBuffer->General2.I1.ReplicaSourceNodeName.MaximumLength = Length;
1165 InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer = midl_user_allocate(Length);
1166 if (InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer == NULL)
1167 {
1168 Status = STATUS_INSUFFICIENT_RESOURCES;
1169 goto done;
1170 }
1171
1172 Status = SampGetObjectAttribute(DomainObject,
1173 L"ReplicaSourceNodeName",
1174 NULL,
1175 (PVOID)InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer,
1176 &Length);
1177 if (!NT_SUCCESS(Status))
1178 goto done;
1179
1180 InfoBuffer->General2.I1.UserCount = 0; /* FIXME */
1181 InfoBuffer->General2.I1.GroupCount = 0; /* FIXME */
1182 InfoBuffer->General2.I1.AliasCount = 0; /* FIXME */
1183
1184 *Buffer = InfoBuffer;
1185
1186 done:
1187 if (!NT_SUCCESS(Status))
1188 {
1189 if (InfoBuffer != NULL)
1190 {
1191 if (InfoBuffer->General2.I1.OemInformation.Buffer != NULL)
1192 midl_user_free(InfoBuffer->General2.I1.OemInformation.Buffer);
1193
1194 if (InfoBuffer->General2.I1.DomainName.Buffer != NULL)
1195 midl_user_free(InfoBuffer->General2.I1.DomainName.Buffer);
1196
1197 if (InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer != NULL)
1198 midl_user_free(InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer);
1199
1200 midl_user_free(InfoBuffer);
1201 }
1202 }
1203
1204 return Status;
1205 }
1206
1207
1208 static NTSTATUS
1209 SampQueryDomainLockout(PSAM_DB_OBJECT DomainObject,
1210 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1211 {
1212 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1213 SAM_DOMAIN_FIXED_DATA FixedData;
1214 ULONG Length = 0;
1215 NTSTATUS Status;
1216
1217 *Buffer = NULL;
1218
1219 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1220 if (InfoBuffer == NULL)
1221 return STATUS_INSUFFICIENT_RESOURCES;
1222
1223 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1224 Status = SampGetObjectAttribute(DomainObject,
1225 L"F",
1226 NULL,
1227 (PVOID)&FixedData,
1228 &Length);
1229 if (!NT_SUCCESS(Status))
1230 goto done;
1231
1232 InfoBuffer->Lockout.LockoutDuration = FixedData.LockoutDuration;
1233 InfoBuffer->Lockout.LockoutObservationWindow = FixedData.LockoutObservationWindow;
1234 InfoBuffer->Lockout.LockoutThreshold = FixedData.LockoutThreshold;
1235
1236 *Buffer = InfoBuffer;
1237
1238 done:
1239 if (!NT_SUCCESS(Status))
1240 {
1241 if (InfoBuffer != NULL)
1242 {
1243 midl_user_free(InfoBuffer);
1244 }
1245 }
1246
1247 return Status;
1248 }
1249
1250
1251 static NTSTATUS
1252 SampQueryDomainModified2(PSAM_DB_OBJECT DomainObject,
1253 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1254 {
1255 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
1256 SAM_DOMAIN_FIXED_DATA FixedData;
1257 ULONG Length = 0;
1258 NTSTATUS Status;
1259
1260 *Buffer = NULL;
1261
1262 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
1263 if (InfoBuffer == NULL)
1264 return STATUS_INSUFFICIENT_RESOURCES;
1265
1266 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1267 Status = SampGetObjectAttribute(DomainObject,
1268 L"F",
1269 NULL,
1270 (PVOID)&FixedData,
1271 &Length);
1272 if (!NT_SUCCESS(Status))
1273 goto done;
1274
1275 InfoBuffer->Modified2.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart;
1276 InfoBuffer->Modified2.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart;
1277 InfoBuffer->Modified2.CreationTime.LowPart = FixedData.CreationTime.LowPart;
1278 InfoBuffer->Modified2.CreationTime.HighPart = FixedData.CreationTime.HighPart;
1279 InfoBuffer->Modified2.ModifiedCountAtLastPromotion.LowPart = FixedData.ModifiedCountAtLastPromotion.LowPart;
1280 InfoBuffer->Modified2.ModifiedCountAtLastPromotion.HighPart = FixedData.ModifiedCountAtLastPromotion.HighPart;
1281
1282 *Buffer = InfoBuffer;
1283
1284 done:
1285 if (!NT_SUCCESS(Status))
1286 {
1287 if (InfoBuffer != NULL)
1288 {
1289 midl_user_free(InfoBuffer);
1290 }
1291 }
1292
1293 return Status;
1294 }
1295
1296
1297 /* Function 8 */
1298 NTSTATUS
1299 NTAPI
1300 SamrQueryInformationDomain(IN SAMPR_HANDLE DomainHandle,
1301 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1302 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
1303 {
1304 PSAM_DB_OBJECT DomainObject;
1305 ACCESS_MASK DesiredAccess;
1306 NTSTATUS Status;
1307
1308 TRACE("SamrQueryInformationDomain(%p %lu %p)\n",
1309 DomainHandle, DomainInformationClass, Buffer);
1310
1311 switch (DomainInformationClass)
1312 {
1313 case DomainPasswordInformation:
1314 case DomainLockoutInformation:
1315 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS;
1316 break;
1317
1318 case DomainGeneralInformation:
1319 case DomainLogoffInformation:
1320 case DomainOemInformation:
1321 case DomainNameInformation:
1322 case DomainReplicationInformation:
1323 case DomainServerRoleInformation:
1324 case DomainModifiedInformation:
1325 case DomainStateInformation:
1326 case DomainModifiedInformation2:
1327 DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS;
1328 break;
1329
1330 case DomainGeneralInformation2:
1331 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS |
1332 DOMAIN_READ_OTHER_PARAMETERS;
1333 break;
1334
1335 default:
1336 return STATUS_INVALID_INFO_CLASS;
1337 }
1338
1339 /* Validate the server handle */
1340 Status = SampValidateDbObject(DomainHandle,
1341 SamDbDomainObject,
1342 DesiredAccess,
1343 &DomainObject);
1344 if (!NT_SUCCESS(Status))
1345 return Status;
1346
1347 switch (DomainInformationClass)
1348 {
1349 case DomainPasswordInformation:
1350 Status = SampQueryDomainPassword(DomainObject,
1351 Buffer);
1352 break;
1353
1354 case DomainGeneralInformation:
1355 Status = SampQueryDomainGeneral(DomainObject,
1356 Buffer);
1357 break;
1358
1359 case DomainLogoffInformation:
1360 Status = SampQueryDomainLogoff(DomainObject,
1361 Buffer);
1362 break;
1363
1364 case DomainOemInformation:
1365 Status = SampQueryDomainOem(DomainObject,
1366 Buffer);
1367 break;
1368
1369 case DomainNameInformation:
1370 Status = SampQueryDomainName(DomainObject,
1371 Buffer);
1372 break;
1373
1374 case DomainReplicationInformation:
1375 Status = SampQueryDomainReplication(DomainObject,
1376 Buffer);
1377 break;
1378
1379 case DomainServerRoleInformation:
1380 Status = SampQueryDomainServerRole(DomainObject,
1381 Buffer);
1382 break;
1383
1384 case DomainModifiedInformation:
1385 Status = SampQueryDomainModified(DomainObject,
1386 Buffer);
1387 break;
1388
1389 case DomainStateInformation:
1390 Status = SampQueryDomainState(DomainObject,
1391 Buffer);
1392 break;
1393
1394 case DomainGeneralInformation2:
1395 Status = SampQueryDomainGeneral2(DomainObject,
1396 Buffer);
1397 break;
1398
1399 case DomainLockoutInformation:
1400 Status = SampQueryDomainLockout(DomainObject,
1401 Buffer);
1402 break;
1403
1404 case DomainModifiedInformation2:
1405 Status = SampQueryDomainModified2(DomainObject,
1406 Buffer);
1407 break;
1408
1409 default:
1410 Status = STATUS_NOT_IMPLEMENTED;
1411 }
1412
1413 return Status;
1414 }
1415
1416
1417 static NTSTATUS
1418 SampSetDomainPassword(PSAM_DB_OBJECT DomainObject,
1419 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1420 {
1421 SAM_DOMAIN_FIXED_DATA FixedData;
1422 ULONG Length = 0;
1423 NTSTATUS Status;
1424
1425 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1426 Status = SampGetObjectAttribute(DomainObject,
1427 L"F",
1428 NULL,
1429 (PVOID)&FixedData,
1430 &Length);
1431 if (!NT_SUCCESS(Status))
1432 goto done;
1433
1434 FixedData.MinPasswordLength = Buffer->Password.MinPasswordLength;
1435 FixedData.PasswordHistoryLength = Buffer->Password.PasswordHistoryLength;
1436 FixedData.PasswordProperties = Buffer->Password.PasswordProperties;
1437 FixedData.MaxPasswordAge.LowPart = Buffer->Password.MaxPasswordAge.LowPart;
1438 FixedData.MaxPasswordAge.HighPart = Buffer->Password.MaxPasswordAge.HighPart;
1439 FixedData.MinPasswordAge.LowPart = Buffer->Password.MinPasswordAge.LowPart;
1440 FixedData.MinPasswordAge.HighPart = Buffer->Password.MinPasswordAge.HighPart;
1441
1442 Status = SampSetObjectAttribute(DomainObject,
1443 L"F",
1444 REG_BINARY,
1445 &FixedData,
1446 Length);
1447
1448 done:
1449 return Status;
1450 }
1451
1452
1453 static NTSTATUS
1454 SampSetDomainLogoff(PSAM_DB_OBJECT DomainObject,
1455 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1456 {
1457 SAM_DOMAIN_FIXED_DATA FixedData;
1458 ULONG Length = 0;
1459 NTSTATUS Status;
1460
1461 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1462 Status = SampGetObjectAttribute(DomainObject,
1463 L"F",
1464 NULL,
1465 (PVOID)&FixedData,
1466 &Length);
1467 if (!NT_SUCCESS(Status))
1468 goto done;
1469
1470 FixedData.ForceLogoff.LowPart = Buffer->Logoff.ForceLogoff.LowPart;
1471 FixedData.ForceLogoff.HighPart = Buffer->Logoff.ForceLogoff.HighPart;
1472
1473 Status = SampSetObjectAttribute(DomainObject,
1474 L"F",
1475 REG_BINARY,
1476 &FixedData,
1477 Length);
1478
1479 done:
1480 return Status;
1481 }
1482
1483
1484 static NTSTATUS
1485 SampSetDomainServerRole(PSAM_DB_OBJECT DomainObject,
1486 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1487 {
1488 SAM_DOMAIN_FIXED_DATA FixedData;
1489 ULONG Length = 0;
1490 NTSTATUS Status;
1491
1492 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1493 Status = SampGetObjectAttribute(DomainObject,
1494 L"F",
1495 NULL,
1496 (PVOID)&FixedData,
1497 &Length);
1498 if (!NT_SUCCESS(Status))
1499 goto done;
1500
1501 FixedData.DomainServerRole = Buffer->Role.DomainServerRole;
1502
1503 Status = SampSetObjectAttribute(DomainObject,
1504 L"F",
1505 REG_BINARY,
1506 &FixedData,
1507 Length);
1508
1509 done:
1510 return Status;
1511 }
1512
1513
1514 static NTSTATUS
1515 SampSetDomainState(PSAM_DB_OBJECT DomainObject,
1516 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1517 {
1518 SAM_DOMAIN_FIXED_DATA FixedData;
1519 ULONG Length = 0;
1520 NTSTATUS Status;
1521
1522 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1523 Status = SampGetObjectAttribute(DomainObject,
1524 L"F",
1525 NULL,
1526 (PVOID)&FixedData,
1527 &Length);
1528 if (!NT_SUCCESS(Status))
1529 goto done;
1530
1531 FixedData.DomainServerState = Buffer->State.DomainServerState;
1532
1533 Status = SampSetObjectAttribute(DomainObject,
1534 L"F",
1535 REG_BINARY,
1536 &FixedData,
1537 Length);
1538
1539 done:
1540 return Status;
1541 }
1542
1543
1544 static NTSTATUS
1545 SampSetDomainLockout(PSAM_DB_OBJECT DomainObject,
1546 PSAMPR_DOMAIN_INFO_BUFFER Buffer)
1547 {
1548 SAM_DOMAIN_FIXED_DATA FixedData;
1549 ULONG Length = 0;
1550 NTSTATUS Status;
1551
1552 Length = sizeof(SAM_DOMAIN_FIXED_DATA);
1553 Status = SampGetObjectAttribute(DomainObject,
1554 L"F",
1555 NULL,
1556 (PVOID)&FixedData,
1557 &Length);
1558 if (!NT_SUCCESS(Status))
1559 goto done;
1560
1561 FixedData.LockoutDuration = Buffer->Lockout.LockoutDuration;
1562 FixedData.LockoutObservationWindow = Buffer->Lockout.LockoutObservationWindow;
1563 FixedData.LockoutThreshold = Buffer->Lockout.LockoutThreshold;
1564
1565 Status = SampSetObjectAttribute(DomainObject,
1566 L"F",
1567 REG_BINARY,
1568 &FixedData,
1569 Length);
1570
1571 done:
1572 return Status;
1573 }
1574
1575
1576 /* Function 9 */
1577 NTSTATUS
1578 NTAPI
1579 SamrSetInformationDomain(IN SAMPR_HANDLE DomainHandle,
1580 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
1581 IN PSAMPR_DOMAIN_INFO_BUFFER DomainInformation)
1582 {
1583 PSAM_DB_OBJECT DomainObject;
1584 ACCESS_MASK DesiredAccess;
1585 NTSTATUS Status;
1586
1587 TRACE("SamrSetInformationDomain(%p %lu %p)\n",
1588 DomainHandle, DomainInformationClass, DomainInformation);
1589
1590 switch (DomainInformationClass)
1591 {
1592 case DomainPasswordInformation:
1593 case DomainLockoutInformation:
1594 DesiredAccess = DOMAIN_WRITE_PASSWORD_PARAMS;
1595 break;
1596
1597 case DomainLogoffInformation:
1598 case DomainOemInformation:
1599 case DomainNameInformation:
1600 DesiredAccess = DOMAIN_WRITE_OTHER_PARAMETERS;
1601 break;
1602
1603 case DomainReplicationInformation:
1604 case DomainServerRoleInformation:
1605 case DomainStateInformation:
1606 DesiredAccess = DOMAIN_ADMINISTER_SERVER;
1607 break;
1608
1609 default:
1610 return STATUS_INVALID_INFO_CLASS;
1611 }
1612
1613 /* Validate the server handle */
1614 Status = SampValidateDbObject(DomainHandle,
1615 SamDbDomainObject,
1616 DesiredAccess,
1617 &DomainObject);
1618 if (!NT_SUCCESS(Status))
1619 return Status;
1620
1621 switch (DomainInformationClass)
1622 {
1623 case DomainPasswordInformation:
1624 Status = SampSetDomainPassword(DomainObject,
1625 DomainInformation);
1626 break;
1627
1628 case DomainLogoffInformation:
1629 Status = SampSetDomainLogoff(DomainObject,
1630 DomainInformation);
1631 break;
1632
1633 case DomainOemInformation:
1634 Status = SampSetObjectAttribute(DomainObject,
1635 L"OemInformation",
1636 REG_SZ,
1637 DomainInformation->Oem.OemInformation.Buffer,
1638 DomainInformation->Oem.OemInformation.Length + sizeof(WCHAR));
1639 break;
1640
1641 case DomainNameInformation:
1642 Status = SampSetObjectAttribute(DomainObject,
1643 L"Name",
1644 REG_SZ,
1645 DomainInformation->Name.DomainName.Buffer,
1646 DomainInformation->Name.DomainName.Length + sizeof(WCHAR));
1647 break;
1648
1649 case DomainReplicationInformation:
1650 Status = SampSetObjectAttribute(DomainObject,
1651 L"ReplicaSourceNodeName",
1652 REG_SZ,
1653 DomainInformation->Replication.ReplicaSourceNodeName.Buffer,
1654 DomainInformation->Replication.ReplicaSourceNodeName.Length + sizeof(WCHAR));
1655 break;
1656
1657 case DomainServerRoleInformation:
1658 Status = SampSetDomainServerRole(DomainObject,
1659 DomainInformation);
1660 break;
1661
1662 case DomainStateInformation:
1663 Status = SampSetDomainState(DomainObject,
1664 DomainInformation);
1665 break;
1666
1667 case DomainLockoutInformation:
1668 Status = SampSetDomainLockout(DomainObject,
1669 DomainInformation);
1670 break;
1671
1672 default:
1673 Status = STATUS_NOT_IMPLEMENTED;
1674 }
1675
1676 return Status;
1677 }
1678
1679 /* Function 10 */
1680 NTSTATUS
1681 NTAPI
1682 SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
1683 IN PRPC_UNICODE_STRING Name,
1684 IN ACCESS_MASK DesiredAccess,
1685 OUT SAMPR_HANDLE *GroupHandle,
1686 OUT unsigned long *RelativeId)
1687 {
1688 UNIMPLEMENTED;
1689 return STATUS_NOT_IMPLEMENTED;
1690 }
1691
1692 /* Function 10 */
1693 NTSTATUS
1694 NTAPI
1695 SamrEnumerateGroupsInDomain(IN SAMPR_HANDLE DomainHandle,
1696 IN OUT unsigned long *EnumerationContext,
1697 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
1698 IN unsigned long PreferedMaximumLength,
1699 OUT unsigned long *CountReturned)
1700 {
1701 UNIMPLEMENTED;
1702 return STATUS_NOT_IMPLEMENTED;
1703 }
1704
1705 /* Function 12 */
1706 NTSTATUS
1707 NTAPI
1708 SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
1709 IN PRPC_UNICODE_STRING Name,
1710 IN ACCESS_MASK DesiredAccess,
1711 OUT SAMPR_HANDLE *UserHandle,
1712 OUT unsigned long *RelativeId)
1713 {
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 BOOL bAliasExists = FALSE;
1722 NTSTATUS Status;
1723
1724 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
1725 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
1726
1727 /* Validate the domain handle */
1728 Status = SampValidateDbObject(DomainHandle,
1729 SamDbDomainObject,
1730 DOMAIN_CREATE_USER,
1731 &DomainObject);
1732 if (!NT_SUCCESS(Status))
1733 {
1734 TRACE("failed with status 0x%08lx\n", Status);
1735 return Status;
1736 }
1737
1738 /* Get the fixed domain attributes */
1739 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
1740 Status = SampGetObjectAttribute(DomainObject,
1741 L"F",
1742 NULL,
1743 (PVOID)&FixedDomainData,
1744 &ulSize);
1745 if (!NT_SUCCESS(Status))
1746 {
1747 TRACE("failed with status 0x%08lx\n", Status);
1748 return Status;
1749 }
1750
1751 /* Increment the NextRid attribute */
1752 ulRid = FixedDomainData.NextRid;
1753 FixedDomainData.NextRid++;
1754
1755 /* Store the fixed domain attributes */
1756 Status = SampSetObjectAttribute(DomainObject,
1757 L"F",
1758 REG_BINARY,
1759 &FixedDomainData,
1760 ulSize);
1761 if (!NT_SUCCESS(Status))
1762 {
1763 TRACE("failed with status 0x%08lx\n", Status);
1764 return Status;
1765 }
1766
1767 TRACE("RID: %lx\n", ulRid);
1768
1769 /* Convert the RID into a string (hex) */
1770 swprintf(szRid, L"%08lX", ulRid);
1771
1772 /* Check whether the user name is already in use */
1773 Status = SampCheckDbObjectNameAlias(DomainObject,
1774 L"Users",
1775 Name->Buffer,
1776 &bAliasExists);
1777 if (!NT_SUCCESS(Status))
1778 {
1779 TRACE("failed with status 0x%08lx\n", Status);
1780 return Status;
1781 }
1782
1783 if (bAliasExists)
1784 {
1785 TRACE("The user account %S already exists!\n", Name->Buffer);
1786 return STATUS_USER_EXISTS;
1787 }
1788
1789 /* Create the user object */
1790 Status = SampCreateDbObject(DomainObject,
1791 L"Users",
1792 szRid,
1793 SamDbUserObject,
1794 DesiredAccess,
1795 &UserObject);
1796 if (!NT_SUCCESS(Status))
1797 {
1798 TRACE("failed with status 0x%08lx\n", Status);
1799 return Status;
1800 }
1801
1802 /* Add the name alias for the user object */
1803 Status = SampSetDbObjectNameAlias(DomainObject,
1804 L"Users",
1805 Name->Buffer,
1806 ulRid);
1807 if (!NT_SUCCESS(Status))
1808 {
1809 TRACE("failed with status 0x%08lx\n", Status);
1810 return Status;
1811 }
1812
1813 /* Initialize fixed user data */
1814 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA));
1815 FixedUserData.Version = 1;
1816
1817 FixedUserData.UserId = ulRid;
1818
1819 /* Set fixed user data attribute */
1820 Status = SampSetObjectAttribute(UserObject,
1821 L"F",
1822 REG_BINARY,
1823 (LPVOID)&FixedUserData,
1824 sizeof(SAM_USER_FIXED_DATA));
1825 if (!NT_SUCCESS(Status))
1826 {
1827 TRACE("failed with status 0x%08lx\n", Status);
1828 return Status;
1829 }
1830
1831 /* Set the name attribute */
1832 Status = SampSetObjectAttribute(UserObject,
1833 L"Name",
1834 REG_SZ,
1835 (LPVOID)Name->Buffer,
1836 Name->MaximumLength);
1837 if (!NT_SUCCESS(Status))
1838 {
1839 TRACE("failed with status 0x%08lx\n", Status);
1840 return Status;
1841 }
1842
1843 /* FIXME: Set default user attributes */
1844
1845 if (NT_SUCCESS(Status))
1846 {
1847 *UserHandle = (SAMPR_HANDLE)UserObject;
1848 *RelativeId = ulRid;
1849 }
1850
1851 TRACE("returns with status 0x%08lx\n", Status);
1852
1853 return Status;
1854 }
1855
1856 /* Function 13 */
1857 NTSTATUS
1858 NTAPI
1859 SamrEnumerateUsersInDomain(IN SAMPR_HANDLE DomainHandle,
1860 IN OUT unsigned long *EnumerationContext,
1861 IN unsigned long UserAccountControl,
1862 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
1863 IN unsigned long PreferedMaximumLength,
1864 OUT unsigned long *CountReturned)
1865 {
1866 UNIMPLEMENTED;
1867 return STATUS_NOT_IMPLEMENTED;
1868 }
1869
1870 /* Function 14 */
1871 NTSTATUS
1872 NTAPI
1873 SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
1874 IN PRPC_UNICODE_STRING AccountName,
1875 IN ACCESS_MASK DesiredAccess,
1876 OUT SAMPR_HANDLE *AliasHandle,
1877 OUT unsigned long *RelativeId)
1878 {
1879 SAM_DOMAIN_FIXED_DATA FixedDomainData;
1880 PSAM_DB_OBJECT DomainObject;
1881 PSAM_DB_OBJECT AliasObject;
1882 UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
1883 ULONG ulSize;
1884 ULONG ulRid;
1885 WCHAR szRid[9];
1886 BOOL bAliasExists = FALSE;
1887 NTSTATUS Status;
1888
1889 TRACE("SamrCreateAliasInDomain(%p %p %lx %p %p)\n",
1890 DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId);
1891
1892 /* Validate the domain handle */
1893 Status = SampValidateDbObject(DomainHandle,
1894 SamDbDomainObject,
1895 DOMAIN_CREATE_ALIAS,
1896 &DomainObject);
1897 if (!NT_SUCCESS(Status))
1898 {
1899 TRACE("failed with status 0x%08lx\n", Status);
1900 return Status;
1901 }
1902
1903 /* Get the fixed domain attributes */
1904 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA);
1905 Status = SampGetObjectAttribute(DomainObject,
1906 L"F",
1907 NULL,
1908 (PVOID)&FixedDomainData,
1909 &ulSize);
1910 if (!NT_SUCCESS(Status))
1911 {
1912 TRACE("failed with status 0x%08lx\n", Status);
1913 return Status;
1914 }
1915
1916 /* Increment the NextRid attribute */
1917 ulRid = FixedDomainData.NextRid;
1918 FixedDomainData.NextRid++;
1919
1920 /* Store the fixed domain attributes */
1921 Status = SampSetObjectAttribute(DomainObject,
1922 L"F",
1923 REG_BINARY,
1924 &FixedDomainData,
1925 ulSize);
1926 if (!NT_SUCCESS(Status))
1927 {
1928 TRACE("failed with status 0x%08lx\n", Status);
1929 return Status;
1930 }
1931
1932 TRACE("RID: %lx\n", ulRid);
1933
1934 /* Convert the RID into a string (hex) */
1935 swprintf(szRid, L"%08lX", ulRid);
1936
1937 /* Check whether the user name is already in use */
1938 Status = SampCheckDbObjectNameAlias(DomainObject,
1939 L"Aliases",
1940 AccountName->Buffer,
1941 &bAliasExists);
1942 if (!NT_SUCCESS(Status))
1943 {
1944 TRACE("failed with status 0x%08lx\n", Status);
1945 return Status;
1946 }
1947
1948 if (bAliasExists)
1949 {
1950 TRACE("The alias account %S already exists!\n", AccountName->Buffer);
1951 return STATUS_ALIAS_EXISTS;
1952 }
1953
1954 /* Create the user object */
1955 Status = SampCreateDbObject(DomainObject,
1956 L"Aliases",
1957 szRid,
1958 SamDbAliasObject,
1959 DesiredAccess,
1960 &AliasObject);
1961 if (!NT_SUCCESS(Status))
1962 {
1963 TRACE("failed with status 0x%08lx\n", Status);
1964 return Status;
1965 }
1966
1967 /* Add the name alias for the user object */
1968 Status = SampSetDbObjectNameAlias(DomainObject,
1969 L"Aliases",
1970 AccountName->Buffer,
1971 ulRid);
1972 if (!NT_SUCCESS(Status))
1973 {
1974 TRACE("failed with status 0x%08lx\n", Status);
1975 return Status;
1976 }
1977
1978 /* Set the Name attribute */
1979 Status = SampSetObjectAttribute(AliasObject,
1980 L"Name",
1981 REG_SZ,
1982 (LPVOID)AccountName->Buffer,
1983 AccountName->MaximumLength);
1984 if (!NT_SUCCESS(Status))
1985 {
1986 TRACE("failed with status 0x%08lx\n", Status);
1987 return Status;
1988 }
1989
1990 /* Set the Description attribute */
1991 Status = SampSetObjectAttribute(AliasObject,
1992 L"Description",
1993 REG_SZ,
1994 EmptyString.Buffer,
1995 EmptyString.MaximumLength);
1996 if (!NT_SUCCESS(Status))
1997 {
1998 TRACE("failed with status 0x%08lx\n", Status);
1999 return Status;
2000 }
2001
2002 if (NT_SUCCESS(Status))
2003 {
2004 *AliasHandle = (SAMPR_HANDLE)AliasObject;
2005 *RelativeId = ulRid;
2006 }
2007
2008 TRACE("returns with status 0x%08lx\n", Status);
2009
2010 return Status;
2011 }
2012
2013 /* Function 15 */
2014 NTSTATUS
2015 NTAPI
2016 SamrEnumerateAliasesInDomain(IN SAMPR_HANDLE DomainHandle,
2017 IN OUT unsigned long *EnumerationContext,
2018 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
2019 IN unsigned long PreferedMaximumLength,
2020 OUT unsigned long *CountReturned)
2021 {
2022 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
2023 PSAM_DB_OBJECT DomainObject;
2024 HANDLE AliasesKeyHandle;
2025 WCHAR AliasKeyName[64];
2026 HANDLE AliasKeyHandle;
2027 ULONG EnumIndex;
2028 ULONG EnumCount;
2029 ULONG RequiredLength;
2030 ULONG DataLength;
2031 ULONG i;
2032 BOOLEAN MoreEntries = FALSE;
2033 NTSTATUS Status;
2034
2035 TRACE("SamrEnumerateAliasesInDomain(%p %p %p %lu %p)\n",
2036 DomainHandle, EnumerationContext, Buffer, PreferedMaximumLength,
2037 CountReturned);
2038
2039 /* Validate the domain handle */
2040 Status = SampValidateDbObject(DomainHandle,
2041 SamDbDomainObject,
2042 DOMAIN_LIST_ACCOUNTS,
2043 &DomainObject);
2044 if (!NT_SUCCESS(Status))
2045 return Status;
2046
2047 Status = SampRegOpenKey(DomainObject->KeyHandle,
2048 L"Aliases",
2049 KEY_READ,
2050 &AliasesKeyHandle);
2051 if (!NT_SUCCESS(Status))
2052 return Status;
2053
2054 TRACE("Part 1\n");
2055
2056 EnumIndex = *EnumerationContext;
2057 EnumCount = 0;
2058 RequiredLength = 0;
2059
2060 while (TRUE)
2061 {
2062 Status = SampRegEnumerateSubKey(AliasesKeyHandle,
2063 EnumIndex,
2064 64 * sizeof(WCHAR),
2065 AliasKeyName);
2066 if (!NT_SUCCESS(Status))
2067 {
2068 if (Status == STATUS_NO_MORE_ENTRIES)
2069 Status = STATUS_SUCCESS;
2070 break;
2071 }
2072
2073 TRACE("EnumIndex: %lu\n", EnumIndex);
2074 TRACE("Alias key name: %S\n", AliasKeyName);
2075
2076 Status = SampRegOpenKey(AliasesKeyHandle,
2077 AliasKeyName,
2078 KEY_READ,
2079 &AliasKeyHandle);
2080 TRACE("SampRegOpenKey returned %08lX\n", Status);
2081 if (NT_SUCCESS(Status))
2082 {
2083 DataLength = 0;
2084 Status = SampRegQueryValue(AliasKeyHandle,
2085 L"Name",
2086 NULL,
2087 NULL,
2088 &DataLength);
2089
2090 NtClose(AliasKeyHandle);
2091
2092 TRACE("SampRegQueryValue returned %08lX\n", Status);
2093
2094 if (NT_SUCCESS(Status))
2095 {
2096 TRACE("Data length: %lu\n", DataLength);
2097
2098 if ((RequiredLength + DataLength + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
2099 {
2100 MoreEntries = TRUE;
2101 break;
2102 }
2103
2104 RequiredLength += (DataLength + sizeof(SAMPR_RID_ENUMERATION));
2105 EnumCount++;
2106 }
2107 }
2108
2109 EnumIndex++;
2110 }
2111
2112 TRACE("EnumCount: %lu\n", EnumCount);
2113 TRACE("RequiredLength: %lu\n", RequiredLength);
2114
2115 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
2116 if (EnumBuffer == NULL)
2117 {
2118 Status = STATUS_INSUFFICIENT_RESOURCES;
2119 goto done;
2120 }
2121
2122 EnumBuffer->EntriesRead = EnumCount;
2123 if (EnumCount == 0)
2124 goto done;
2125
2126 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
2127 if (EnumBuffer->Buffer == NULL)
2128 {
2129 Status = STATUS_INSUFFICIENT_RESOURCES;
2130 goto done;
2131 }
2132
2133 TRACE("Part 2\n");
2134
2135 EnumIndex = *EnumerationContext;
2136 for (i = 0; i < EnumCount; i++, EnumIndex++)
2137 {
2138 Status = SampRegEnumerateSubKey(AliasesKeyHandle,
2139 EnumIndex,
2140 64 * sizeof(WCHAR),
2141 AliasKeyName);
2142 if (!NT_SUCCESS(Status))
2143 {
2144 if (Status == STATUS_NO_MORE_ENTRIES)
2145 Status = STATUS_SUCCESS;
2146 break;
2147 }
2148
2149 TRACE("EnumIndex: %lu\n", EnumIndex);
2150 TRACE("Alias key name: %S\n", AliasKeyName);
2151
2152 Status = SampRegOpenKey(AliasesKeyHandle,
2153 AliasKeyName,
2154 KEY_READ,
2155 &AliasKeyHandle);
2156 TRACE("SampRegOpenKey returned %08lX\n", Status);
2157 if (NT_SUCCESS(Status))
2158 {
2159 DataLength = 0;
2160 Status = SampRegQueryValue(AliasKeyHandle,
2161 L"Name",
2162 NULL,
2163 NULL,
2164 &DataLength);
2165 TRACE("SampRegQueryValue returned %08lX\n", Status);
2166 if (NT_SUCCESS(Status))
2167 {
2168 EnumBuffer->Buffer[i].RelativeId = wcstoul(AliasKeyName, NULL, 16);
2169
2170 EnumBuffer->Buffer[i].Name.Length = (USHORT)DataLength - sizeof(WCHAR);
2171 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)DataLength;
2172 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(DataLength);
2173 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
2174 {
2175 NtClose(AliasKeyHandle);
2176 Status = STATUS_INSUFFICIENT_RESOURCES;
2177 goto done;
2178 }
2179
2180 Status = SampRegQueryValue(AliasKeyHandle,
2181 L"Name",
2182 NULL,
2183 EnumBuffer->Buffer[i].Name.Buffer,
2184 &DataLength);
2185 TRACE("SampRegQueryValue returned %08lX\n", Status);
2186 if (NT_SUCCESS(Status))
2187 {
2188 TRACE("Alias name: %S\n", EnumBuffer->Buffer[i].Name.Buffer);
2189 }
2190 }
2191
2192 NtClose(AliasKeyHandle);
2193
2194 if (!NT_SUCCESS(Status))
2195 goto done;
2196 }
2197 }
2198
2199 done:
2200 if (NT_SUCCESS(Status))
2201 {
2202 *EnumerationContext += EnumCount;
2203 *Buffer = EnumBuffer;
2204 *CountReturned = EnumCount;
2205 }
2206
2207 if (!NT_SUCCESS(Status))
2208 {
2209 *EnumerationContext = 0;
2210 *Buffer = NULL;
2211 *CountReturned = 0;
2212
2213 if (EnumBuffer != NULL)
2214 {
2215 if (EnumBuffer->Buffer != NULL)
2216 {
2217 if (EnumBuffer->EntriesRead != 0)
2218 {
2219 for (i = 0; i < EnumBuffer->EntriesRead; i++)
2220 {
2221 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
2222 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
2223 }
2224 }
2225
2226 midl_user_free(EnumBuffer->Buffer);
2227 }
2228
2229 midl_user_free(EnumBuffer);
2230 }
2231 }
2232
2233 NtClose(AliasesKeyHandle);
2234
2235 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
2236 Status = STATUS_MORE_ENTRIES;
2237
2238 return Status;
2239 }
2240
2241 /* Function 16 */
2242 NTSTATUS
2243 NTAPI
2244 SamrGetAliasMembership(IN SAMPR_HANDLE DomainHandle,
2245 IN PSAMPR_PSID_ARRAY SidArray,
2246 OUT PSAMPR_ULONG_ARRAY Membership)
2247 {
2248 PSAM_DB_OBJECT DomainObject;
2249 HANDLE AliasesKeyHandle = NULL;
2250 HANDLE MembersKeyHandle = NULL;
2251 HANDLE MemberKeyHandle = NULL;
2252 LPWSTR MemberSidString = NULL;
2253 PULONG RidArray = NULL;
2254 ULONG MaxSidCount = 0;
2255 ULONG ValueCount;
2256 ULONG DataLength;
2257 ULONG i, j;
2258 NTSTATUS Status;
2259
2260 TRACE("SamrGetAliasMembership(%p %p %p)\n",
2261 DomainHandle, SidArray, Membership);
2262
2263 /* Validate the domain handle */
2264 Status = SampValidateDbObject(DomainHandle,
2265 SamDbDomainObject,
2266 DOMAIN_LOOKUP,
2267 &DomainObject);
2268 if (!NT_SUCCESS(Status))
2269 return Status;
2270
2271 Status = SampRegOpenKey(DomainObject->KeyHandle,
2272 L"Aliases",
2273 KEY_READ,
2274 &AliasesKeyHandle);
2275 TRACE("SampRegOpenKey returned %08lX\n", Status);
2276 if (!NT_SUCCESS(Status))
2277 goto done;
2278
2279 Status = SampRegOpenKey(AliasesKeyHandle,
2280 L"Members",
2281 KEY_READ,
2282 &MembersKeyHandle);
2283 TRACE("SampRegOpenKey returned %08lX\n", Status);
2284 if (!NT_SUCCESS(Status))
2285 goto done;
2286
2287 for (i = 0; i < SidArray->Count; i++)
2288 {
2289 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
2290 TRACE("Open %S\n", MemberSidString);
2291
2292 Status = SampRegOpenKey(MembersKeyHandle,
2293 MemberSidString,
2294 KEY_READ,
2295 &MemberKeyHandle);
2296 TRACE("SampRegOpenKey returned %08lX\n", Status);
2297 if (NT_SUCCESS(Status))
2298 {
2299 Status = SampRegQueryKeyInfo(MemberKeyHandle,
2300 NULL,
2301 &ValueCount);
2302 if (NT_SUCCESS(Status))
2303 {
2304 TRACE("Found %lu values\n", ValueCount);
2305 MaxSidCount += ValueCount;
2306 }
2307
2308
2309 NtClose(MemberKeyHandle);
2310 }
2311
2312 LocalFree(MemberSidString);
2313 }
2314
2315 TRACE("Maximum sid count: %lu\n", MaxSidCount);
2316 RidArray = midl_user_allocate(MaxSidCount * sizeof(ULONG));
2317 if (RidArray == NULL)
2318 {
2319 Status = STATUS_INSUFFICIENT_RESOURCES;
2320 goto done;
2321 }
2322
2323 for (i = 0; i < SidArray->Count; i++)
2324 {
2325 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
2326 TRACE("Open %S\n", MemberSidString);
2327
2328 Status = SampRegOpenKey(MembersKeyHandle,
2329 MemberSidString,
2330 KEY_READ,
2331 &MemberKeyHandle);
2332 TRACE("SampRegOpenKey returned %08lX\n", Status);
2333 if (NT_SUCCESS(Status))
2334 {
2335 Status = SampRegQueryKeyInfo(MemberKeyHandle,
2336 NULL,
2337 &ValueCount);
2338 if (NT_SUCCESS(Status))
2339 {
2340 TRACE("Found %lu values\n", ValueCount);
2341
2342 for (j = 0; j < ValueCount; j++)
2343 {
2344 DataLength = sizeof(ULONG);
2345 Status = SampRegEnumerateValue(MemberKeyHandle,
2346 j,
2347 NULL,
2348 NULL,
2349 NULL,
2350 (PVOID)&RidArray[j],
2351 &DataLength);
2352 }
2353 }
2354
2355 NtClose(MemberKeyHandle);
2356 }
2357
2358 LocalFree(MemberSidString);
2359 }
2360
2361
2362 done:
2363 if (NT_SUCCESS(Status))
2364 {
2365 Membership->Count = MaxSidCount;
2366 Membership->Element = RidArray;
2367 }
2368 else
2369 {
2370 if (RidArray != NULL)
2371 midl_user_free(RidArray);
2372 }
2373
2374 if (MembersKeyHandle != NULL)
2375 NtClose(MembersKeyHandle);
2376
2377 if (MembersKeyHandle != NULL)
2378 NtClose(MembersKeyHandle);
2379
2380 if (AliasesKeyHandle != NULL)
2381 NtClose(AliasesKeyHandle);
2382
2383 return Status;
2384 }
2385
2386 /* Function 17 */
2387 NTSTATUS
2388 NTAPI
2389 SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
2390 IN unsigned long Count,
2391 IN RPC_UNICODE_STRING Names[],
2392 OUT PSAMPR_ULONG_ARRAY RelativeIds,
2393 OUT PSAMPR_ULONG_ARRAY Use)
2394 {
2395 UNIMPLEMENTED;
2396 return STATUS_NOT_IMPLEMENTED;
2397 }
2398
2399 /* Function 18 */
2400 NTSTATUS
2401 NTAPI
2402 SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
2403 IN unsigned long Count,
2404 IN unsigned long *RelativeIds,
2405 OUT PSAMPR_RETURNED_USTRING_ARRAY Names,
2406 OUT PSAMPR_ULONG_ARRAY Use)
2407 {
2408 UNIMPLEMENTED;
2409 return STATUS_NOT_IMPLEMENTED;
2410 }
2411
2412 /* Function 19 */
2413 NTSTATUS
2414 NTAPI
2415 SamrOpenGroup(IN SAMPR_HANDLE DomainHandle,
2416 IN ACCESS_MASK DesiredAccess,
2417 IN unsigned long GroupId,
2418 OUT SAMPR_HANDLE *GroupHandle)
2419 {
2420 UNIMPLEMENTED;
2421 return STATUS_NOT_IMPLEMENTED;
2422 }
2423
2424 /* Function 20 */
2425 NTSTATUS
2426 NTAPI
2427 SamrQueryInformationGroup(IN SAMPR_HANDLE GroupHandle,
2428 IN GROUP_INFORMATION_CLASS GroupInformationClass,
2429 OUT PSAMPR_GROUP_INFO_BUFFER *Buffer)
2430 {
2431 UNIMPLEMENTED;
2432 return STATUS_NOT_IMPLEMENTED;
2433 }
2434
2435 /* Function 21 */
2436 NTSTATUS
2437 NTAPI
2438 SamrSetInformationGroup(IN SAMPR_HANDLE GroupHandle,
2439 IN GROUP_INFORMATION_CLASS GroupInformationClass,
2440 IN PSAMPR_GROUP_INFO_BUFFER Buffer)
2441 {
2442 UNIMPLEMENTED;
2443 return STATUS_NOT_IMPLEMENTED;
2444 }
2445
2446 /* Function 22 */
2447 NTSTATUS
2448 NTAPI
2449 SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle,
2450 IN unsigned long MemberId,
2451 IN unsigned long Attributes)
2452 {
2453 UNIMPLEMENTED;
2454 return STATUS_NOT_IMPLEMENTED;
2455 }
2456
2457 /* Function 21 */
2458 NTSTATUS
2459 NTAPI
2460 SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
2461 {
2462 UNIMPLEMENTED;
2463 return STATUS_NOT_IMPLEMENTED;
2464 }
2465
2466 /* Function 24 */
2467 NTSTATUS
2468 NTAPI
2469 SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle,
2470 IN unsigned long MemberId)
2471 {
2472 UNIMPLEMENTED;
2473 return STATUS_NOT_IMPLEMENTED;
2474 }
2475
2476 /* Function 25 */
2477 NTSTATUS
2478 NTAPI
2479 SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle,
2480 OUT PSAMPR_GET_MEMBERS_BUFFER *Members)
2481 {
2482 UNIMPLEMENTED;
2483 return STATUS_NOT_IMPLEMENTED;
2484 }
2485
2486 /* Function 26 */
2487 NTSTATUS
2488 NTAPI
2489 SamrSetMemberAttributesOfGroup(IN SAMPR_HANDLE GroupHandle,
2490 IN unsigned long MemberId,
2491 IN unsigned long Attributes)
2492 {
2493 UNIMPLEMENTED;
2494 return STATUS_NOT_IMPLEMENTED;
2495 }
2496
2497 /* Function 27 */
2498 NTSTATUS
2499 NTAPI
2500 SamrOpenAlias(IN SAMPR_HANDLE DomainHandle,
2501 IN ACCESS_MASK DesiredAccess,
2502 IN ULONG AliasId,
2503 OUT SAMPR_HANDLE *AliasHandle)
2504 {
2505 PSAM_DB_OBJECT DomainObject;
2506 PSAM_DB_OBJECT AliasObject;
2507 WCHAR szRid[9];
2508 NTSTATUS Status;
2509
2510 TRACE("SamrOpenAlias(%p %lx %lx %p)\n",
2511 DomainHandle, DesiredAccess, AliasId, AliasHandle);
2512
2513 /* Validate the domain handle */
2514 Status = SampValidateDbObject(DomainHandle,
2515 SamDbDomainObject,
2516 DOMAIN_LOOKUP,
2517 &DomainObject);
2518 if (!NT_SUCCESS(Status))
2519 {
2520 TRACE("failed with status 0x%08lx\n", Status);
2521 return Status;
2522 }
2523
2524 /* Convert the RID into a string (hex) */
2525 swprintf(szRid, L"%08lX", AliasId);
2526
2527 /* Create the alias object */
2528 Status = SampOpenDbObject(DomainObject,
2529 L"Aliases",
2530 szRid,
2531 SamDbAliasObject,
2532 DesiredAccess,
2533 &AliasObject);
2534 if (!NT_SUCCESS(Status))
2535 {
2536 TRACE("failed with status 0x%08lx\n", Status);
2537 return Status;
2538 }
2539
2540 *AliasHandle = (SAMPR_HANDLE)AliasObject;
2541
2542 return STATUS_SUCCESS;
2543 }
2544
2545
2546 static NTSTATUS
2547 SampQueryAliasGeneral(PSAM_DB_OBJECT AliasObject,
2548 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
2549 {
2550 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
2551 HANDLE MembersKeyHandle = NULL;
2552 ULONG NameLength = 0;
2553 ULONG DescriptionLength = 0;
2554 NTSTATUS Status;
2555
2556 *Buffer = NULL;
2557
2558 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
2559 if (InfoBuffer == NULL)
2560 return STATUS_INSUFFICIENT_RESOURCES;
2561
2562 Status = SampGetObjectAttribute(AliasObject,
2563 L"Name",
2564 NULL,
2565 NULL,
2566 &NameLength);
2567 TRACE("Status 0x%08lx\n", Status);
2568 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
2569 {
2570 TRACE("Status 0x%08lx\n", Status);
2571 goto done;
2572 }
2573
2574 InfoBuffer->General.Name.Length = NameLength - sizeof(WCHAR);
2575 InfoBuffer->General.Name.MaximumLength = NameLength;
2576 InfoBuffer->General.Name.Buffer = midl_user_allocate(NameLength);
2577 if (InfoBuffer->General.Name.Buffer == NULL)
2578 {
2579 Status = STATUS_INSUFFICIENT_RESOURCES;
2580 goto done;
2581 }
2582
2583 TRACE("Name Length: %lu\n", NameLength);
2584 Status = SampGetObjectAttribute(AliasObject,
2585 L"Name",
2586 NULL,
2587 (PVOID)InfoBuffer->General.Name.Buffer,
2588 &NameLength);
2589 if (!NT_SUCCESS(Status))
2590 {
2591 TRACE("Status 0x%08lx\n", Status);
2592 goto done;
2593 }
2594
2595 Status = SampGetObjectAttribute(AliasObject,
2596 L"Description",
2597 NULL,
2598 NULL,
2599 &DescriptionLength);
2600 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
2601 {
2602 TRACE("Status 0x%08lx\n", Status);
2603 goto done;
2604 }
2605
2606 InfoBuffer->General.AdminComment.Length = DescriptionLength - sizeof(WCHAR);
2607 InfoBuffer->General.AdminComment.MaximumLength = DescriptionLength;
2608 InfoBuffer->General.AdminComment.Buffer = midl_user_allocate(DescriptionLength);
2609 if (InfoBuffer->General.AdminComment.Buffer == NULL)
2610 {
2611 Status = STATUS_INSUFFICIENT_RESOURCES;
2612 goto done;
2613 }
2614
2615 TRACE("Description Length: %lu\n", DescriptionLength);
2616 Status = SampGetObjectAttribute(AliasObject,
2617 L"Description",
2618 NULL,
2619 (PVOID)InfoBuffer->General.AdminComment.Buffer,
2620 &DescriptionLength);
2621 if (!NT_SUCCESS(Status))
2622 {
2623 TRACE("Status 0x%08lx\n", Status);
2624 goto done;
2625 }
2626
2627 /* Open the Members subkey */
2628 Status = SampRegOpenKey(AliasObject->KeyHandle,
2629 L"Members",
2630 KEY_READ,
2631 &MembersKeyHandle);
2632 if (!NT_SUCCESS(Status))
2633 {
2634 TRACE("Status 0x%08lx\n", Status);
2635 goto done;
2636 }
2637
2638 /* Retrieve the number of members of the alias */
2639 Status = SampRegQueryKeyInfo(MembersKeyHandle,
2640 NULL,
2641 &InfoBuffer->General.MemberCount);
2642 if (!NT_SUCCESS(Status))
2643 {
2644 TRACE("Status 0x%08lx\n", Status);
2645 goto done;
2646 }
2647
2648 *Buffer = InfoBuffer;
2649
2650 done:
2651 if (MembersKeyHandle != NULL)
2652 SampRegCloseKey(MembersKeyHandle);
2653
2654 if (!NT_SUCCESS(Status))
2655 {
2656 if (InfoBuffer != NULL)
2657 {
2658 if (InfoBuffer->General.Name.Buffer != NULL)
2659 midl_user_free(InfoBuffer->General.Name.Buffer);
2660
2661 if (InfoBuffer->General.AdminComment.Buffer != NULL)
2662 midl_user_free(InfoBuffer->General.AdminComment.Buffer);
2663
2664 midl_user_free(InfoBuffer);
2665 }
2666 }
2667
2668 return Status;
2669 }
2670
2671
2672 static NTSTATUS
2673 SampQueryAliasName(PSAM_DB_OBJECT AliasObject,
2674 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
2675 {
2676 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
2677 ULONG Length = 0;
2678 NTSTATUS Status;
2679
2680 *Buffer = NULL;
2681
2682 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
2683 if (InfoBuffer == NULL)
2684 return STATUS_INSUFFICIENT_RESOURCES;
2685
2686 Status = SampGetObjectAttribute(AliasObject,
2687 L"Name",
2688 NULL,
2689 NULL,
2690 &Length);
2691 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
2692 {
2693 TRACE("Status 0x%08lx\n", Status);
2694 goto done;
2695 }
2696
2697 InfoBuffer->Name.Name.Length = Length - sizeof(WCHAR);
2698 InfoBuffer->Name.Name.MaximumLength = Length;
2699 InfoBuffer->Name.Name.Buffer = midl_user_allocate(Length);
2700 if (InfoBuffer->Name.Name.Buffer == NULL)
2701 {
2702 Status = STATUS_INSUFFICIENT_RESOURCES;
2703 goto done;
2704 }
2705
2706 TRACE("Length: %lu\n", Length);
2707 Status = SampGetObjectAttribute(AliasObject,
2708 L"Name",
2709 NULL,
2710 (PVOID)InfoBuffer->Name.Name.Buffer,
2711 &Length);
2712 if (!NT_SUCCESS(Status))
2713 {
2714 TRACE("Status 0x%08lx\n", Status);
2715 goto done;
2716 }
2717
2718 *Buffer = InfoBuffer;
2719
2720 done:
2721 if (!NT_SUCCESS(Status))
2722 {
2723 if (InfoBuffer != NULL)
2724 {
2725 if (InfoBuffer->Name.Name.Buffer != NULL)
2726 midl_user_free(InfoBuffer->Name.Name.Buffer);
2727
2728 midl_user_free(InfoBuffer);
2729 }
2730 }
2731
2732 return Status;
2733 }
2734
2735
2736 static NTSTATUS
2737 SampQueryAliasAdminComment(PSAM_DB_OBJECT AliasObject,
2738 PSAMPR_ALIAS_INFO_BUFFER *Buffer)
2739 {
2740 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL;
2741 ULONG Length = 0;
2742 NTSTATUS Status;
2743
2744 *Buffer = NULL;
2745
2746 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER));
2747 if (InfoBuffer == NULL)
2748 return STATUS_INSUFFICIENT_RESOURCES;
2749
2750 Status = SampGetObjectAttribute(AliasObject,
2751 L"Description",
2752 NULL,
2753 NULL,
2754 &Length);
2755 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
2756 goto done;
2757
2758 InfoBuffer->AdminComment.AdminComment.Length = Length - sizeof(WCHAR);
2759 InfoBuffer->AdminComment.AdminComment.MaximumLength = Length;
2760 InfoBuffer->AdminComment.AdminComment.Buffer = midl_user_allocate(Length);
2761 if (InfoBuffer->AdminComment.AdminComment.Buffer == NULL)
2762 {
2763 Status = STATUS_INSUFFICIENT_RESOURCES;
2764 goto done;
2765 }
2766
2767 Status = SampGetObjectAttribute(AliasObject,
2768 L"Description",
2769 NULL,
2770 (PVOID)InfoBuffer->AdminComment.AdminComment.Buffer,
2771 &Length);
2772 if (!NT_SUCCESS(Status))
2773 goto done;
2774
2775 *Buffer = InfoBuffer;
2776
2777 done:
2778 if (!NT_SUCCESS(Status))
2779 {
2780 if (InfoBuffer != NULL)
2781 {
2782 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
2783 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
2784
2785 midl_user_free(InfoBuffer);
2786 }
2787 }
2788
2789 return Status;
2790 }
2791
2792
2793 /* Function 28 */
2794 NTSTATUS
2795 NTAPI
2796 SamrQueryInformationAlias(IN SAMPR_HANDLE AliasHandle,
2797 IN ALIAS_INFORMATION_CLASS AliasInformationClass,
2798 OUT PSAMPR_ALIAS_INFO_BUFFER *Buffer)
2799 {
2800 PSAM_DB_OBJECT AliasObject;
2801 NTSTATUS Status;
2802
2803 TRACE("SamrQueryInformationAlias(%p %lu %p)\n",
2804 AliasHandle, AliasInformationClass, Buffer);
2805
2806 /* Validate the alias handle */
2807 Status = SampValidateDbObject(AliasHandle,
2808 SamDbAliasObject,
2809 ALIAS_READ_INFORMATION,
2810 &AliasObject);
2811 if (!NT_SUCCESS(Status))
2812 return Status;
2813
2814 switch (AliasInformationClass)
2815 {
2816 case AliasGeneralInformation:
2817 Status = SampQueryAliasGeneral(AliasObject,
2818 Buffer);
2819 break;
2820
2821 case AliasNameInformation:
2822 Status = SampQueryAliasName(AliasObject,
2823 Buffer);
2824 break;
2825
2826 case AliasAdminCommentInformation:
2827 Status = SampQueryAliasAdminComment(AliasObject,
2828 Buffer);
2829 break;
2830
2831 default:
2832 Status = STATUS_INVALID_INFO_CLASS;
2833 break;
2834 }
2835
2836 return Status;
2837 }
2838
2839 /* Function 29 */
2840 NTSTATUS
2841 NTAPI
2842 SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle,
2843 IN ALIAS_INFORMATION_CLASS AliasInformationClass,
2844 IN PSAMPR_ALIAS_INFO_BUFFER Buffer)
2845 {
2846 PSAM_DB_OBJECT AliasObject;
2847 NTSTATUS Status;
2848
2849 TRACE("SamrSetInformationAlias(%p %lu %p)\n",
2850 AliasHandle, AliasInformationClass, Buffer);
2851
2852 /* Validate the alias handle */
2853 Status = SampValidateDbObject(AliasHandle,
2854 SamDbAliasObject,
2855 ALIAS_WRITE_ACCOUNT,
2856 &AliasObject);
2857 if (!NT_SUCCESS(Status))
2858 return Status;
2859
2860 switch (AliasInformationClass)
2861 {
2862 case AliasNameInformation:
2863 Status = SampSetObjectAttribute(AliasObject,
2864 L"Name",
2865 REG_SZ,
2866 Buffer->Name.Name.Buffer,
2867 Buffer->Name.Name.Length + sizeof(WCHAR));
2868 break;
2869
2870 case AliasAdminCommentInformation:
2871 Status = SampSetObjectAttribute(AliasObject,
2872 L"Description",
2873 REG_SZ,
2874 Buffer->AdminComment.AdminComment.Buffer,
2875 Buffer->AdminComment.AdminComment.Length + sizeof(WCHAR));
2876 break;
2877
2878 default:
2879 Status = STATUS_INVALID_INFO_CLASS;
2880 break;
2881 }
2882
2883 return Status;
2884 }
2885
2886 /* Function 30 */
2887 NTSTATUS
2888 NTAPI
2889 SamrDeleteAlias(IN OUT SAMPR_HANDLE *AliasHandle)
2890 {
2891 UNIMPLEMENTED;
2892 return STATUS_NOT_IMPLEMENTED;
2893 }
2894
2895 /* Function 31 */
2896 NTSTATUS
2897 NTAPI
2898 SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
2899 IN PRPC_SID MemberId)
2900 {
2901 PSAM_DB_OBJECT AliasObject;
2902 LPWSTR MemberIdString = NULL;
2903 HANDLE MembersKeyHandle = NULL;
2904 HANDLE MemberKeyHandle = NULL;
2905 ULONG MemberIdLength;
2906 NTSTATUS Status;
2907
2908 TRACE("SamrAddMemberToAlias(%p %p)\n",
2909 AliasHandle, MemberId);
2910
2911 /* Validate the domain handle */
2912 Status = SampValidateDbObject(AliasHandle,
2913 SamDbAliasObject,
2914 ALIAS_ADD_MEMBER,
2915 &AliasObject);
2916 if (!NT_SUCCESS(Status))
2917 {
2918 TRACE("failed with status 0x%08lx\n", Status);
2919 return Status;
2920 }
2921
2922 ConvertSidToStringSidW(MemberId, &MemberIdString);
2923 TRACE("Member SID: %S\n", MemberIdString);
2924
2925 MemberIdLength = RtlLengthSid(MemberId);
2926
2927 Status = SampRegCreateKey(AliasObject->KeyHandle,
2928 L"Members",
2929 KEY_WRITE,
2930 &MembersKeyHandle);
2931 if (!NT_SUCCESS(Status))
2932 {
2933 TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
2934 goto done;
2935 }
2936
2937 Status = SampRegSetValue(MembersKeyHandle,
2938 MemberIdString,
2939 REG_BINARY,
2940 MemberId,
2941 MemberIdLength);
2942 if (!NT_SUCCESS(Status))
2943 {
2944 TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
2945 goto done;
2946 }
2947
2948 Status = SampRegCreateKey(AliasObject->MembersKeyHandle,
2949 MemberIdString,
2950 KEY_WRITE,
2951 &MemberKeyHandle);
2952 if (!NT_SUCCESS(Status))
2953 {
2954 TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
2955 goto done;
2956 }
2957
2958 Status = SampRegSetValue(MemberKeyHandle,
2959 AliasObject->Name,
2960 REG_BINARY,
2961 MemberId,
2962 MemberIdLength);
2963 if (!NT_SUCCESS(Status))
2964 {
2965 TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
2966 goto done;
2967 }
2968
2969 done:
2970 if (MemberKeyHandle != NULL)
2971 SampRegCloseKey(MemberKeyHandle);
2972
2973 if (MembersKeyHandle != NULL)
2974 SampRegCloseKey(MembersKeyHandle);
2975
2976 if (MemberIdString != NULL)
2977 LocalFree(MemberIdString);
2978
2979 return Status;
2980 }
2981
2982 /* Function 32 */
2983 NTSTATUS
2984 NTAPI
2985 SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle,
2986 IN PRPC_SID MemberId)
2987 {
2988 UNIMPLEMENTED;
2989 return STATUS_NOT_IMPLEMENTED;
2990 }
2991
2992 /* Function 33 */
2993 NTSTATUS
2994 NTAPI
2995 SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
2996 OUT PSAMPR_PSID_ARRAY_OUT Members)
2997 {
2998 PSAM_DB_OBJECT AliasObject;
2999 HANDLE MembersKeyHandle = NULL;
3000 PSAMPR_SID_INFORMATION MemberArray = NULL;
3001 ULONG ValueCount = 0;
3002 ULONG DataLength;
3003 ULONG Index;
3004 NTSTATUS Status;
3005
3006 TRACE("SamrGetMembersInAlias(%p %p %p)\n",
3007 AliasHandle, Members);
3008
3009 /* Validate the alias handle */
3010 Status = SampValidateDbObject(AliasHandle,
3011 SamDbAliasObject,
3012 ALIAS_LIST_MEMBERS,
3013 &AliasObject);
3014 if (!NT_SUCCESS(Status))
3015 {
3016 ERR("failed with status 0x%08lx\n", Status);
3017 return Status;
3018 }
3019
3020 /* Open the members key of the alias objct */
3021 Status = SampRegOpenKey(AliasObject->KeyHandle,
3022 L"Members",
3023 KEY_READ,
3024 &MembersKeyHandle);
3025 if (!NT_SUCCESS(Status))
3026 {
3027 ERR("SampRegOpenKey failed with status 0x%08lx\n", Status);
3028 return Status;
3029 }
3030
3031 /* Get the number of members */
3032 Status = SampRegQueryKeyInfo(MembersKeyHandle,
3033 NULL,
3034 &ValueCount);
3035 if (!NT_SUCCESS(Status))
3036 {
3037 ERR("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
3038 goto done;
3039 }
3040
3041 /* Allocate the member array */
3042 MemberArray = midl_user_allocate(ValueCount * sizeof(SAMPR_SID_INFORMATION));
3043 if (MemberArray == NULL)
3044 {
3045 Status = STATUS_INSUFFICIENT_RESOURCES;
3046 goto done;
3047 }
3048
3049 /* Enumerate the members */
3050 Index = 0;
3051 while (TRUE)
3052 {
3053 /* Get the size of the next SID */
3054 DataLength = 0;
3055 Status = SampRegEnumerateValue(MembersKeyHandle,
3056 Index,
3057 NULL,
3058 NULL,
3059 NULL,
3060 NULL,
3061 &DataLength);
3062 if (!NT_SUCCESS(Status))
3063 {
3064 if (Status == STATUS_NO_MORE_ENTRIES)
3065 Status = STATUS_SUCCESS;
3066 break;
3067 }
3068
3069 /* Allocate a buffer for the SID */
3070 MemberArray[Index].SidPointer = midl_user_allocate(DataLength);
3071 if (MemberArray[Index].SidPointer == NULL)
3072 {
3073 Status = STATUS_INSUFFICIENT_RESOURCES;
3074 goto done;
3075 }
3076
3077 /* Read the SID into the buffer */
3078 Status = SampRegEnumerateValue(MembersKeyHandle,
3079 Index,
3080 NULL,
3081 NULL,
3082 NULL,
3083 (PVOID)MemberArray[Index].SidPointer,
3084 &DataLength);
3085 if (!NT_SUCCESS(Status))
3086 {
3087 goto done;
3088 }
3089
3090 Index++;
3091 }
3092
3093 /* Return the number of members and the member array */
3094 if (NT_SUCCESS(Status))
3095 {
3096 Members->Count = ValueCount;
3097 Members->Sids = MemberArray;
3098 }
3099
3100 done:
3101 /* Clean up the members array and the SID buffers if something failed */
3102 if (!NT_SUCCESS(Status))
3103 {
3104 if (MemberArray != NULL)
3105 {
3106 for (Index = 0; Index < ValueCount; Index++)
3107 {
3108 if (MemberArray[Index].SidPointer != NULL)
3109 midl_user_free(MemberArray[Index].SidPointer);
3110 }
3111
3112 midl_user_free(MemberArray);
3113 }
3114 }
3115
3116 /* Close the members key */
3117 if (MembersKeyHandle != NULL)
3118 SampRegCloseKey(MembersKeyHandle);
3119
3120 return Status;
3121 }
3122
3123 /* Function 34 */
3124 NTSTATUS
3125 NTAPI
3126 SamrOpenUser(IN SAMPR_HANDLE DomainHandle,
3127 IN ACCESS_MASK DesiredAccess,
3128 IN unsigned long UserId,
3129 OUT SAMPR_HANDLE *UserHandle)
3130 {
3131 PSAM_DB_OBJECT DomainObject;
3132 PSAM_DB_OBJECT UserObject;
3133 WCHAR szRid[9];
3134 NTSTATUS Status;
3135
3136 TRACE("SamrOpenUser(%p %lx %lx %p)\n",
3137 DomainHandle, DesiredAccess, UserId, UserHandle);
3138
3139 /* Validate the domain handle */
3140 Status = SampValidateDbObject(DomainHandle,
3141 SamDbDomainObject,
3142 DOMAIN_LOOKUP,
3143 &DomainObject);
3144 if (!NT_SUCCESS(Status))
3145 {
3146 TRACE("failed with status 0x%08lx\n", Status);
3147 return Status;
3148 }
3149
3150 /* Convert the RID into a string (hex) */
3151 swprintf(szRid, L"%08lX", UserId);
3152
3153 /* Create the user object */
3154 Status = SampOpenDbObject(DomainObject,
3155 L"Users",
3156 szRid,
3157 SamDbUserObject,
3158 DesiredAccess,
3159 &UserObject);
3160 if (!NT_SUCCESS(Status))
3161 {
3162 TRACE("failed with status 0x%08lx\n", Status);
3163 return Status;
3164 }
3165
3166 *UserHandle = (SAMPR_HANDLE)UserObject;
3167
3168 return STATUS_SUCCESS;
3169 }
3170
3171 /* Function 35 */
3172 NTSTATUS
3173 NTAPI
3174 SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle)
3175 {
3176 UNIMPLEMENTED;
3177 return STATUS_NOT_IMPLEMENTED;
3178 }
3179
3180
3181 static
3182 NTSTATUS
3183 SampQueryUserName(PSAM_DB_OBJECT UserObject,
3184 PSAMPR_USER_INFO_BUFFER *Buffer)
3185 {
3186 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3187 ULONG Length = 0;
3188 NTSTATUS Status;
3189
3190 *Buffer = NULL;
3191
3192 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3193 if (InfoBuffer == NULL)
3194 return STATUS_INSUFFICIENT_RESOURCES;
3195
3196 Status = SampGetObjectAttribute(UserObject,
3197 L"Name",
3198 NULL,
3199 NULL,
3200 &Length);
3201 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3202 {
3203 TRACE("Status 0x%08lx\n", Status);
3204 goto done;
3205 }
3206
3207 InfoBuffer->Name.UserName.Length = Length - sizeof(WCHAR);
3208 InfoBuffer->Name.UserName.MaximumLength = Length;
3209 InfoBuffer->Name.UserName.Buffer = midl_user_allocate(Length);
3210 if (InfoBuffer->Name.UserName.Buffer == NULL)
3211 {
3212 Status = STATUS_INSUFFICIENT_RESOURCES;
3213 goto done;
3214 }
3215
3216 TRACE("Length: %lu\n", Length);
3217 Status = SampGetObjectAttribute(UserObject,
3218 L"Name",
3219 NULL,
3220 (PVOID)InfoBuffer->Name.UserName.Buffer,
3221 &Length);
3222 if (!NT_SUCCESS(Status))
3223 {
3224 TRACE("Status 0x%08lx\n", Status);
3225 goto done;
3226 }
3227
3228 Length = 0;
3229 Status = SampGetObjectAttribute(UserObject,
3230 L"FullName",
3231 NULL,
3232 NULL,
3233 &Length);
3234 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3235 {
3236 TRACE("Status 0x%08lx\n", Status);
3237 goto done;
3238 }
3239
3240 InfoBuffer->Name.FullName.Length = Length - sizeof(WCHAR);
3241 InfoBuffer->Name.FullName.MaximumLength = Length;
3242 InfoBuffer->Name.FullName.Buffer = midl_user_allocate(Length);
3243 if (InfoBuffer->Name.FullName.Buffer == NULL)
3244 {
3245 Status = STATUS_INSUFFICIENT_RESOURCES;
3246 goto done;
3247 }
3248
3249 TRACE("Length: %lu\n", Length);
3250 Status = SampGetObjectAttribute(UserObject,
3251 L"FullName",
3252 NULL,
3253 (PVOID)InfoBuffer->Name.FullName.Buffer,
3254 &Length);
3255 if (!NT_SUCCESS(Status))
3256 {
3257 TRACE("Status 0x%08lx\n", Status);
3258 goto done;
3259 }
3260
3261 *Buffer = InfoBuffer;
3262
3263 done:
3264 if (!NT_SUCCESS(Status))
3265 {
3266 if (InfoBuffer != NULL)
3267 {
3268 if (InfoBuffer->Name.UserName.Buffer != NULL)
3269 midl_user_free(InfoBuffer->Name.UserName.Buffer);
3270
3271 if (InfoBuffer->Name.FullName.Buffer != NULL)
3272 midl_user_free(InfoBuffer->Name.FullName.Buffer);
3273
3274 midl_user_free(InfoBuffer);
3275 }
3276 }
3277
3278 return Status;
3279 }
3280
3281
3282 static NTSTATUS
3283 SampQueryUserAccountName(PSAM_DB_OBJECT UserObject,
3284 PSAMPR_USER_INFO_BUFFER *Buffer)
3285 {
3286 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3287 ULONG Length = 0;
3288 NTSTATUS Status;
3289
3290 *Buffer = NULL;
3291
3292 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3293 if (InfoBuffer == NULL)
3294 return STATUS_INSUFFICIENT_RESOURCES;
3295
3296 Status = SampGetObjectAttribute(UserObject,
3297 L"Name",
3298 NULL,
3299 NULL,
3300 &Length);
3301 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3302 {
3303 TRACE("Status 0x%08lx\n", Status);
3304 goto done;
3305 }
3306
3307 InfoBuffer->AccountName.UserName.Length = Length - sizeof(WCHAR);
3308 InfoBuffer->AccountName.UserName.MaximumLength = Length;
3309 InfoBuffer->AccountName.UserName.Buffer = midl_user_allocate(Length);
3310 if (InfoBuffer->AccountName.UserName.Buffer == NULL)
3311 {
3312 Status = STATUS_INSUFFICIENT_RESOURCES;
3313 goto done;
3314 }
3315
3316 TRACE("Length: %lu\n", Length);
3317 Status = SampGetObjectAttribute(UserObject,
3318 L"Name",
3319 NULL,
3320 (PVOID)InfoBuffer->AccountName.UserName.Buffer,
3321 &Length);
3322 if (!NT_SUCCESS(Status))
3323 {
3324 TRACE("Status 0x%08lx\n", Status);
3325 goto done;
3326 }
3327
3328 *Buffer = InfoBuffer;
3329
3330 done:
3331 if (!NT_SUCCESS(Status))
3332 {
3333 if (InfoBuffer != NULL)
3334 {
3335 if (InfoBuffer->AccountName.UserName.Buffer != NULL)
3336 midl_user_free(InfoBuffer->AccountName.UserName.Buffer);
3337
3338 midl_user_free(InfoBuffer);
3339 }
3340 }
3341
3342 return Status;
3343 }
3344
3345
3346 static NTSTATUS
3347 SampQueryUserFullName(PSAM_DB_OBJECT UserObject,
3348 PSAMPR_USER_INFO_BUFFER *Buffer)
3349 {
3350 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3351 ULONG Length = 0;
3352 NTSTATUS Status;
3353
3354 *Buffer = NULL;
3355
3356 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3357 if (InfoBuffer == NULL)
3358 return STATUS_INSUFFICIENT_RESOURCES;
3359
3360 Status = SampGetObjectAttribute(UserObject,
3361 L"FullName",
3362 NULL,
3363 NULL,
3364 &Length);
3365 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3366 {
3367 TRACE("Status 0x%08lx\n", Status);
3368 goto done;
3369 }
3370
3371 InfoBuffer->FullName.FullName.Length = Length - sizeof(WCHAR);
3372 InfoBuffer->FullName.FullName.MaximumLength = Length;
3373 InfoBuffer->FullName.FullName.Buffer = midl_user_allocate(Length);
3374 if (InfoBuffer->FullName.FullName.Buffer == NULL)
3375 {
3376 Status = STATUS_INSUFFICIENT_RESOURCES;
3377 goto done;
3378 }
3379
3380 TRACE("Length: %lu\n", Length);
3381 Status = SampGetObjectAttribute(UserObject,
3382 L"FullName",
3383 NULL,
3384 (PVOID)InfoBuffer->FullName.FullName.Buffer,
3385 &Length);
3386 if (!NT_SUCCESS(Status))
3387 {
3388 TRACE("Status 0x%08lx\n", Status);
3389 goto done;
3390 }
3391
3392 *Buffer = InfoBuffer;
3393
3394 done:
3395 if (!NT_SUCCESS(Status))
3396 {
3397 if (InfoBuffer != NULL)
3398 {
3399 if (InfoBuffer->FullName.FullName.Buffer != NULL)
3400 midl_user_free(InfoBuffer->FullName.FullName.Buffer);
3401
3402 midl_user_free(InfoBuffer);
3403 }
3404 }
3405
3406 return Status;
3407 }
3408
3409
3410 static
3411 NTSTATUS
3412 SampQueryUserPrimaryGroup(PSAM_DB_OBJECT UserObject,
3413 PSAMPR_USER_INFO_BUFFER *Buffer)
3414 {
3415 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3416 SAM_USER_FIXED_DATA FixedData;
3417 ULONG Length = 0;
3418 NTSTATUS Status;
3419
3420 *Buffer = NULL;
3421
3422 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3423 if (InfoBuffer == NULL)
3424 return STATUS_INSUFFICIENT_RESOURCES;
3425
3426 Length = sizeof(SAM_USER_FIXED_DATA);
3427 Status = SampGetObjectAttribute(UserObject,
3428 L"F",
3429 NULL,
3430 (PVOID)&FixedData,
3431 &Length);
3432 if (!NT_SUCCESS(Status))
3433 goto done;
3434
3435 InfoBuffer->PrimaryGroup.PrimaryGroupId = FixedData.PrimaryGroupId;
3436
3437 *Buffer = InfoBuffer;
3438
3439 done:
3440 if (!NT_SUCCESS(Status))
3441 {
3442 if (InfoBuffer != NULL)
3443 {
3444 midl_user_free(InfoBuffer);
3445 }
3446 }
3447
3448 return Status;
3449 }
3450
3451
3452 static NTSTATUS
3453 SampQueryUserHome(PSAM_DB_OBJECT UserObject,
3454 PSAMPR_USER_INFO_BUFFER *Buffer)
3455 {
3456 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3457 ULONG Length = 0;
3458 NTSTATUS Status;
3459
3460 *Buffer = NULL;
3461
3462 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3463 if (InfoBuffer == NULL)
3464 return STATUS_INSUFFICIENT_RESOURCES;
3465
3466 Status = SampGetObjectAttribute(UserObject,
3467 L"HomeDirectory",
3468 NULL,
3469 NULL,
3470 &Length);
3471 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3472 {
3473 TRACE("Status 0x%08lx\n", Status);
3474 goto done;
3475 }
3476
3477 InfoBuffer->Home.HomeDirectory.Length = Length - sizeof(WCHAR);
3478 InfoBuffer->Home.HomeDirectory.MaximumLength = Length;
3479 InfoBuffer->Home.HomeDirectory.Buffer = midl_user_allocate(Length);
3480 if (InfoBuffer->Home.HomeDirectory.Buffer == NULL)
3481 {
3482 Status = STATUS_INSUFFICIENT_RESOURCES;
3483 goto done;
3484 }
3485
3486 TRACE("Length: %lu\n", Length);
3487 Status = SampGetObjectAttribute(UserObject,
3488 L"HomeDirectory",
3489 NULL,
3490 (PVOID)InfoBuffer->Home.HomeDirectory.Buffer,
3491 &Length);
3492 if (!NT_SUCCESS(Status))
3493 {
3494 TRACE("Status 0x%08lx\n", Status);
3495 goto done;
3496 }
3497
3498 Length = 0;
3499 Status = SampGetObjectAttribute(UserObject,
3500 L"HomeDirectoryDrive",
3501 NULL,
3502 NULL,
3503 &Length);
3504 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3505 {
3506 TRACE("Status 0x%08lx\n", Status);
3507 goto done;
3508 }
3509
3510 InfoBuffer->Home.HomeDirectoryDrive.Length = Length - sizeof(WCHAR);
3511 InfoBuffer->Home.HomeDirectoryDrive.MaximumLength = Length;
3512 InfoBuffer->Home.HomeDirectoryDrive.Buffer = midl_user_allocate(Length);
3513 if (InfoBuffer->Home.HomeDirectoryDrive.Buffer == NULL)
3514 {
3515 Status = STATUS_INSUFFICIENT_RESOURCES;
3516 goto done;
3517 }
3518
3519 TRACE("Length: %lu\n", Length);
3520 Status = SampGetObjectAttribute(UserObject,
3521 L"HomeDirectoryDrive",
3522 NULL,
3523 (PVOID)InfoBuffer->Home.HomeDirectoryDrive.Buffer,
3524 &Length);
3525 if (!NT_SUCCESS(Status))
3526 {
3527 TRACE("Status 0x%08lx\n", Status);
3528 goto done;
3529 }
3530
3531 *Buffer = InfoBuffer;
3532
3533 done:
3534 if (!NT_SUCCESS(Status))
3535 {
3536 if (InfoBuffer != NULL)
3537 {
3538 if (InfoBuffer->Home.HomeDirectory.Buffer != NULL)
3539 midl_user_free(InfoBuffer->Home.HomeDirectory.Buffer);
3540
3541 if (InfoBuffer->Home.HomeDirectoryDrive.Buffer != NULL)
3542 midl_user_free(InfoBuffer->Home.HomeDirectoryDrive.Buffer);
3543
3544 midl_user_free(InfoBuffer);
3545 }
3546 }
3547
3548 return Status;
3549 }
3550
3551
3552 static NTSTATUS
3553 SampQueryUserScript(PSAM_DB_OBJECT UserObject,
3554 PSAMPR_USER_INFO_BUFFER *Buffer)
3555 {
3556 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3557 ULONG Length = 0;
3558 NTSTATUS Status;
3559
3560 *Buffer = NULL;
3561
3562 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3563 if (InfoBuffer == NULL)
3564 return STATUS_INSUFFICIENT_RESOURCES;
3565
3566 Status = SampGetObjectAttribute(UserObject,
3567 L"ScriptPath",
3568 NULL,
3569 NULL,
3570 &Length);
3571 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3572 {
3573 TRACE("Status 0x%08lx\n", Status);
3574 goto done;
3575 }
3576
3577 InfoBuffer->Script.ScriptPath.Length = Length - sizeof(WCHAR);
3578 InfoBuffer->Script.ScriptPath.MaximumLength = Length;
3579 InfoBuffer->Script.ScriptPath.Buffer = midl_user_allocate(Length);
3580 if (InfoBuffer->Script.ScriptPath.Buffer == NULL)
3581 {
3582 Status = STATUS_INSUFFICIENT_RESOURCES;
3583 goto done;
3584 }
3585
3586 TRACE("Length: %lu\n", Length);
3587 Status = SampGetObjectAttribute(UserObject,
3588 L"ScriptPath",
3589 NULL,
3590 (PVOID)InfoBuffer->Script.ScriptPath.Buffer,
3591 &Length);
3592 if (!NT_SUCCESS(Status))
3593 {
3594 TRACE("Status 0x%08lx\n", Status);
3595 goto done;
3596 }
3597
3598 *Buffer = InfoBuffer;
3599
3600 done:
3601 if (!NT_SUCCESS(Status))
3602 {
3603 if (InfoBuffer != NULL)
3604 {
3605 if (InfoBuffer->Script.ScriptPath.Buffer != NULL)
3606 midl_user_free(InfoBuffer->Script.ScriptPath.Buffer);
3607
3608 midl_user_free(InfoBuffer);
3609 }
3610 }
3611
3612 return Status;
3613 }
3614
3615
3616 static NTSTATUS
3617 SampQueryUserProfile(PSAM_DB_OBJECT UserObject,
3618 PSAMPR_USER_INFO_BUFFER *Buffer)
3619 {
3620 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3621 ULONG Length = 0;
3622 NTSTATUS Status;
3623
3624 *Buffer = NULL;
3625
3626 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3627 if (InfoBuffer == NULL)
3628 return STATUS_INSUFFICIENT_RESOURCES;
3629
3630 Status = SampGetObjectAttribute(UserObject,
3631 L"ProfilePath",
3632 NULL,
3633 NULL,
3634 &Length);
3635 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3636 {
3637 TRACE("Status 0x%08lx\n", Status);
3638 goto done;
3639 }
3640
3641 InfoBuffer->Profile.ProfilePath.Length = Length - sizeof(WCHAR);
3642 InfoBuffer->Profile.ProfilePath.MaximumLength = Length;
3643 InfoBuffer->Profile.ProfilePath.Buffer = midl_user_allocate(Length);
3644 if (InfoBuffer->Profile.ProfilePath.Buffer == NULL)
3645 {
3646 Status = STATUS_INSUFFICIENT_RESOURCES;
3647 goto done;
3648 }
3649
3650 TRACE("Length: %lu\n", Length);
3651 Status = SampGetObjectAttribute(UserObject,
3652 L"ProfilePath",
3653 NULL,
3654 (PVOID)InfoBuffer->Profile.ProfilePath.Buffer,
3655 &Length);
3656 if (!NT_SUCCESS(Status))
3657 {
3658 TRACE("Status 0x%08lx\n", Status);
3659 goto done;
3660 }
3661
3662 *Buffer = InfoBuffer;
3663
3664 done:
3665 if (!NT_SUCCESS(Status))
3666 {
3667 if (InfoBuffer != NULL)
3668 {
3669 if (InfoBuffer->Profile.ProfilePath.Buffer != NULL)
3670 midl_user_free(InfoBuffer->Profile.ProfilePath.Buffer);
3671
3672 midl_user_free(InfoBuffer);
3673 }
3674 }
3675
3676 return Status;
3677 }
3678
3679
3680 static NTSTATUS
3681 SampQueryUserAdminComment(PSAM_DB_OBJECT UserObject,
3682 PSAMPR_USER_INFO_BUFFER *Buffer)
3683 {
3684 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3685 ULONG Length = 0;
3686 NTSTATUS Status;
3687
3688 *Buffer = NULL;
3689
3690 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3691 if (InfoBuffer == NULL)
3692 return STATUS_INSUFFICIENT_RESOURCES;
3693
3694 Status = SampGetObjectAttribute(UserObject,
3695 L"AdminComment",
3696 NULL,
3697 NULL,
3698 &Length);
3699 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3700 {
3701 TRACE("Status 0x%08lx\n", Status);
3702 goto done;
3703 }
3704
3705 InfoBuffer->AdminComment.AdminComment.Length = Length - sizeof(WCHAR);
3706 InfoBuffer->AdminComment.AdminComment.MaximumLength = Length;
3707 InfoBuffer->AdminComment.AdminComment.Buffer = midl_user_allocate(Length);
3708 if (InfoBuffer->AdminComment.AdminComment.Buffer == NULL)
3709 {
3710 Status = STATUS_INSUFFICIENT_RESOURCES;
3711 goto done;
3712 }
3713
3714 TRACE("Length: %lu\n", Length);
3715 Status = SampGetObjectAttribute(UserObject,
3716 L"AdminComment",
3717 NULL,
3718 (PVOID)InfoBuffer->AdminComment.AdminComment.Buffer,
3719 &Length);
3720 if (!NT_SUCCESS(Status))
3721 {
3722 TRACE("Status 0x%08lx\n", Status);
3723 goto done;
3724 }
3725
3726 *Buffer = InfoBuffer;
3727
3728 done:
3729 if (!NT_SUCCESS(Status))
3730 {
3731 if (InfoBuffer != NULL)
3732 {
3733 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL)
3734 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer);
3735
3736 midl_user_free(InfoBuffer);
3737 }
3738 }
3739
3740 return Status;
3741 }
3742
3743
3744
3745 static NTSTATUS
3746 SampQueryUserWorkStations(PSAM_DB_OBJECT UserObject,
3747 PSAMPR_USER_INFO_BUFFER *Buffer)
3748 {
3749 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3750 ULONG Length = 0;
3751 NTSTATUS Status;
3752
3753 *Buffer = NULL;
3754
3755 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3756 if (InfoBuffer == NULL)
3757 return STATUS_INSUFFICIENT_RESOURCES;
3758
3759 Status = SampGetObjectAttribute(UserObject,
3760 L"WorkStations",
3761 NULL,
3762 NULL,
3763 &Length);
3764 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3765 {
3766 TRACE("Status 0x%08lx\n", Status);
3767 goto done;
3768 }
3769
3770 InfoBuffer->WorkStations.WorkStations.Length = Length - sizeof(WCHAR);
3771 InfoBuffer->WorkStations.WorkStations.MaximumLength = Length;
3772 InfoBuffer->WorkStations.WorkStations.Buffer = midl_user_allocate(Length);
3773 if (InfoBuffer->WorkStations.WorkStations.Buffer == NULL)
3774 {
3775 Status = STATUS_INSUFFICIENT_RESOURCES;
3776 goto done;
3777 }
3778
3779 TRACE("Length: %lu\n", Length);
3780 Status = SampGetObjectAttribute(UserObject,
3781 L"WorkStations",
3782 NULL,
3783 (PVOID)InfoBuffer->WorkStations.WorkStations.Buffer,
3784 &Length);
3785 if (!NT_SUCCESS(Status))
3786 {
3787 TRACE("Status 0x%08lx\n", Status);
3788 goto done;
3789 }
3790
3791 *Buffer = InfoBuffer;
3792
3793 done:
3794 if (!NT_SUCCESS(Status))
3795 {
3796 if (InfoBuffer != NULL)
3797 {
3798 if (InfoBuffer->WorkStations.WorkStations.Buffer != NULL)
3799 midl_user_free(InfoBuffer->WorkStations.WorkStations.Buffer);
3800
3801 midl_user_free(InfoBuffer);
3802 }
3803 }
3804
3805 return Status;
3806 }
3807
3808
3809 static
3810 NTSTATUS
3811 SampQueryUserControl(PSAM_DB_OBJECT UserObject,
3812 PSAMPR_USER_INFO_BUFFER *Buffer)
3813 {
3814 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3815 SAM_USER_FIXED_DATA FixedData;
3816 ULONG Length = 0;
3817 NTSTATUS Status;
3818
3819 *Buffer = NULL;
3820
3821 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3822 if (InfoBuffer == NULL)
3823 return STATUS_INSUFFICIENT_RESOURCES;
3824
3825 Length = sizeof(SAM_USER_FIXED_DATA);
3826 Status = SampGetObjectAttribute(UserObject,
3827 L"F",
3828 NULL,
3829 (PVOID)&FixedData,
3830 &Length);
3831 if (!NT_SUCCESS(Status))
3832 goto done;
3833
3834 InfoBuffer->Control.UserAccountControl = FixedData.UserAccountControl;
3835
3836 *Buffer = InfoBuffer;
3837
3838 done:
3839 if (!NT_SUCCESS(Status))
3840 {
3841 if (InfoBuffer != NULL)
3842 {
3843 midl_user_free(InfoBuffer);
3844 }
3845 }
3846
3847 return Status;
3848 }
3849
3850
3851 static
3852 NTSTATUS
3853 SampQueryUserExpires(PSAM_DB_OBJECT UserObject,
3854 PSAMPR_USER_INFO_BUFFER *Buffer)
3855 {
3856 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL;
3857 SAM_USER_FIXED_DATA FixedData;
3858 ULONG Length = 0;
3859 NTSTATUS Status;
3860
3861 *Buffer = NULL;
3862
3863 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER));
3864 if (InfoBuffer == NULL)
3865 return STATUS_INSUFFICIENT_RESOURCES;
3866
3867 Length = sizeof(SAM_USER_FIXED_DATA);
3868 Status = SampGetObjectAttribute(UserObject,
3869 L"F",
3870 NULL,
3871 (PVOID)&FixedData,
3872 &Length);
3873 if (!NT_SUCCESS(Status))
3874 goto done;
3875
3876 InfoBuffer->Expires.AccountExpires.LowPart = FixedData.AccountExpires.LowPart;
3877 InfoBuffer->Expires.AccountExpires.HighPart = FixedData.AccountExpires.HighPart;
3878
3879 *Buffer = InfoBuffer;
3880
3881 done:
3882 if (!NT_SUCCESS(Status))
3883 {
3884 if (InfoBuffer != NULL)
3885 {
3886 midl_user_free(InfoBuffer);
3887 }
3888 }
3889
3890 return Status;
3891 }
3892
3893
3894 /* Function 36 */
3895 NTSTATUS
3896 NTAPI
3897 SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
3898 IN USER_INFORMATION_CLASS UserInformationClass,
3899 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
3900 {
3901 PSAM_DB_OBJECT UserObject;
3902 ACCESS_MASK DesiredAccess;
3903 NTSTATUS Status;
3904
3905 TRACE("SamrQueryInformationUser(%p %lu %p)\n",
3906 UserHandle, UserInformationClass, Buffer);
3907
3908 switch (UserInformationClass)
3909 {
3910 case UserGeneralInformation:
3911 case UserNameInformation:
3912 case UserAccountNameInformation:
3913 case UserFullNameInformation:
3914 case UserPrimaryGroupInformation:
3915 case UserAdminCommentInformation:
3916 DesiredAccess = USER_READ_GENERAL;
3917 break;
3918
3919 case UserLogonHoursInformation:
3920 case UserHomeInformation:
3921 case UserScriptInformation:
3922 case UserProfileInformation:
3923 case UserWorkStationsInformation:
3924 DesiredAccess = USER_READ_LOGON;
3925 break;
3926
3927 case UserControlInformation:
3928 case UserExpiresInformation:
3929 DesiredAccess = USER_READ_ACCOUNT;
3930 break;
3931
3932 case UserPreferencesInformation:
3933 DesiredAccess = USER_READ_GENERAL |
3934 USER_READ_PREFERENCES;
3935 break;
3936
3937 case UserLogonInformation:
3938 case UserAccountInformation:
3939 DesiredAccess = USER_READ_GENERAL |
3940 USER_READ_PREFERENCES |
3941 USER_READ_LOGON |
3942 USER_READ_ACCOUNT;
3943 break;
3944
3945 default:
3946 return STATUS_INVALID_INFO_CLASS;
3947 }
3948
3949 /* Validate the domain handle */
3950 Status = SampValidateDbObject(UserHandle,
3951 SamDbUserObject,
3952 DesiredAccess,
3953 &UserObject);
3954 if (!NT_SUCCESS(Status))
3955 {
3956 TRACE("failed with status 0x%08lx\n", Status);
3957 return Status;
3958 }
3959
3960 switch (UserInformationClass)
3961 {
3962 // case UserGeneralInformation:
3963 // case UserPreferencesInformation:
3964 // case UserLogonInformation:
3965 // case UserLogonHoursInformation:
3966 // case UserAccountInformation:
3967
3968 case UserNameInformation:
3969 Status = SampQueryUserName(UserObject,
3970 Buffer);
3971 break;
3972
3973 case UserAccountNameInformation:
3974 Status = SampQueryUserAccountName(UserObject,
3975 Buffer);
3976 break;
3977
3978 case UserFullNameInformation:
3979 Status = SampQueryUserFullName(UserObject,
3980 Buffer);
3981 break;
3982
3983 case UserPrimaryGroupInformation:
3984 Status = SampQueryUserPrimaryGroup(UserObject,
3985 Buffer);
3986 break;
3987
3988 case UserHomeInformation:
3989 Status = SampQueryUserHome(UserObject,
3990 Buffer);
3991
3992 case UserScriptInformation:
3993 Status = SampQueryUserScript(UserObject,
3994 Buffer);
3995 break;
3996
3997 case UserProfileInformation:
3998 Status = SampQueryUserProfile(UserObject,
3999 Buffer);
4000 break;
4001
4002 case UserAdminCommentInformation:
4003 Status = SampQueryUserAdminComment(UserObject,
4004 Buffer);
4005 break;
4006
4007 case UserWorkStationsInformation:
4008 Status = SampQueryUserWorkStations(UserObject,
4009 Buffer);
4010 break;
4011
4012 case UserControlInformation:
4013 Status = SampQueryUserControl(UserObject,
4014 Buffer);
4015 break;
4016
4017 case UserExpiresInformation:
4018 Status = SampQueryUserExpires(UserObject,
4019 Buffer);
4020 break;
4021
4022 default:
4023 Status = STATUS_INVALID_INFO_CLASS;
4024 }
4025
4026 return Status;
4027 }
4028
4029 /* Function 37 */
4030 NTSTATUS
4031 NTAPI
4032 SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
4033 IN USER_INFORMATION_CLASS UserInformationClass,
4034 IN PSAMPR_USER_INFO_BUFFER Buffer)
4035 {
4036 PSAM_DB_OBJECT UserObject;
4037 ACCESS_MASK DesiredAccess;
4038 NTSTATUS Status;
4039
4040 TRACE("SamrSetInformationUser(%p %lu %p)\n",
4041 UserHandle, UserInformationClass, Buffer);
4042
4043 switch (UserInformationClass)
4044 {
4045 case UserNameInformation:
4046 case UserAccountNameInformation:
4047 case UserFullNameInformation:
4048 case UserPrimaryGroupInformation:
4049 case UserHomeInformation:
4050 case UserScriptInformation:
4051 case UserProfileInformation:
4052 case UserAdminCommentInformation:
4053 case UserWorkStationsInformation:
4054 case UserControlInformation:
4055 case UserExpiresInformation:
4056 DesiredAccess = USER_WRITE_ACCOUNT;
4057 break;
4058
4059 case UserSetPasswordInformation:
4060 DesiredAccess = USER_FORCE_PASSWORD_CHANGE;
4061 break;
4062
4063 default:
4064 return STATUS_INVALID_INFO_CLASS;
4065 }
4066
4067 /* Validate the domain handle */
4068 Status = SampValidateDbObject(UserHandle,
4069 SamDbUserObject,
4070 DesiredAccess,
4071 &UserObject);
4072 if (!NT_SUCCESS(Status))
4073 {
4074 TRACE("failed with status 0x%08lx\n", Status);
4075 return Status;
4076 }
4077
4078 switch (UserInformationClass)
4079 {
4080 // case UserGeneralInformation:
4081 // case UserPreferencesInformation:
4082 // case UserLogonHoursInformation:
4083
4084 case UserNameInformation:
4085 Status = SampSetObjectAttribute(UserObject,
4086 L"Name",
4087 REG_SZ,
4088 Buffer->Name.UserName.Buffer,
4089 Buffer->Name.UserName.MaximumLength);
4090 if (!NT_SUCCESS(Status))
4091 break;
4092
4093 Status = SampSetObjectAttribute(UserObject,
4094 L"FullName",
4095 REG_SZ,
4096 Buffer->Name.FullName.Buffer,
4097 Buffer->Name.FullName.MaximumLength);
4098 break;
4099
4100 case UserAccountNameInformation:
4101 Status = SampSetObjectAttribute(UserObject,
4102 L"Name",
4103 REG_SZ,
4104 Buffer->AccountName.UserName.Buffer,
4105 Buffer->AccountName.UserName.MaximumLength);
4106 break;
4107
4108 case UserFullNameInformation:
4109 Status = SampSetObjectAttribute(UserObject,
4110 L"FullName",
4111 REG_SZ,
4112 Buffer->FullName.FullName.Buffer,
4113 Buffer->FullName.FullName.MaximumLength);
4114 break;
4115
4116 /*
4117 case UserPrimaryGroupInformation:
4118 Status = SampSetObjectAttribute(UserObject,
4119 L"PrimaryGroupId",
4120 REG_DWORD,
4121 &Buffer->PrimaryGroup.PrimaryGroupId,
4122 sizeof(ULONG));
4123 break;
4124 */
4125
4126 case UserHomeInformation:
4127 Status = SampSetObjectAttribute(UserObject,
4128 L"HomeDirectory",
4129 REG_SZ,
4130 Buffer->Home.HomeDirectory.Buffer,
4131 Buffer->Home.HomeDirectory.MaximumLength);
4132 if (!NT_SUCCESS(Status))
4133 break;
4134
4135 Status = SampSetObjectAttribute(UserObject,
4136 L"HomeDirectoryDrive",
4137 REG_SZ,
4138 Buffer->Home.HomeDirectoryDrive.Buffer,
4139 Buffer->Home.HomeDirectoryDrive.MaximumLength);
4140 break;
4141
4142 case UserScriptInformation:
4143 Status = SampSetObjectAttribute(UserObject,
4144 L"ScriptPath",
4145 REG_SZ,
4146 Buffer->Script.ScriptPath.Buffer,
4147 Buffer->Script.ScriptPath.MaximumLength);
4148 break;
4149
4150 case UserProfileInformation:
4151 Status = SampSetObjectAttribute(UserObject,
4152 L"ProfilePath",
4153 REG_SZ,
4154 Buffer->Profile.ProfilePath.Buffer,
4155 Buffer->Profile.ProfilePath.MaximumLength);
4156 break;
4157
4158 case UserAdminCommentInformation:
4159 Status = SampSetObjectAttribute(UserObject,
4160 L"AdminComment",
4161 REG_SZ,
4162 Buffer->AdminComment.AdminComment.Buffer,
4163 Buffer->AdminComment.AdminComment.MaximumLength);
4164 break;
4165
4166 case UserWorkStationsInformation:
4167 Status = SampSetObjectAttribute(UserObject,
4168 L"WorkStations",
4169 REG_SZ,
4170 Buffer->WorkStations.WorkStations.Buffer,
4171 Buffer->WorkStations.WorkStations.MaximumLength);
4172 break;
4173
4174 case UserSetPasswordInformation:
4175 TRACE("Password: %S\n", Buffer->SetPassword.Password.Buffer);
4176 TRACE("PasswordExpired: %d\n", Buffer->SetPassword.PasswordExpired);
4177
4178 Status = SampSetObjectAttribute(UserObject,
4179 L"Password",
4180 REG_SZ,
4181 Buffer->SetPassword.Password.Buffer,
4182 Buffer->SetPassword.Password.MaximumLength);
4183 break;
4184
4185 /*
4186 case UserControlInformation:
4187 Status = SampSetObjectAttribute(UserObject,
4188 L"UserAccountControl",
4189 REG_DWORD,
4190 &Buffer->Control.UserAccountControl,
4191 sizeof(ULONG));
4192 break;
4193 */
4194 /*
4195 case UserExpiresInformation:
4196 Status = SampSetObjectAttribute(UserObject,
4197 L"AccountExpires",
4198 REG_BINARY,
4199 &Buffer->Expires.AccountExpires,
4200 sizeof(OLD_LARGE_INTEGER));
4201 break;
4202 */
4203
4204 // case UserInternal1Information:
4205 // case UserParametersInformation:
4206 // case UserAllInformation:
4207 // case UserInternal4Information:
4208 // case UserInternal5Information:
4209 // case UserInternal4InformationNew:
4210 // case UserInternal5InformationNew:
4211
4212 default:
4213 Status = STATUS_INVALID_INFO_CLASS;
4214 }
4215
4216 return Status;
4217 }
4218
4219 /* Function 38 */
4220 NTSTATUS
4221 NTAPI
4222 SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
4223 IN unsigned char LmPresent,
4224 IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm,
4225 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm,
4226 IN unsigned char NtPresent,
4227 IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt,
4228 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt,
4229 IN unsigned char NtCrossEncryptionPresent,
4230 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm,
4231 IN unsigned char LmCrossEncryptionPresent,
4232 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt)
4233 {
4234 UNIMPLEMENTED;
4235 return STATUS_NOT_IMPLEMENTED;
4236 }
4237
4238 /* Function 39 */
4239 NTSTATUS
4240 NTAPI
4241 SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle,
4242 OUT PSAMPR_GET_GROUPS_BUFFER *Groups)
4243 {
4244 UNIMPLEMENTED;
4245 return STATUS_NOT_IMPLEMENTED;
4246 }
4247
4248 /* Function 40 */
4249 NTSTATUS
4250 NTAPI
4251 SamrQueryDisplayInformation(IN SAMPR_HANDLE DomainHandle,
4252 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
4253 IN unsigned long Index,
4254 IN unsigned long EntryCount,
4255 IN unsigned long PreferredMaximumLength,
4256 OUT unsigned long *TotalAvailable,
4257 OUT unsigned long *TotalReturned,
4258 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
4259 {
4260 UNIMPLEMENTED;
4261 return STATUS_NOT_IMPLEMENTED;
4262 }
4263
4264 /* Function 41 */
4265 NTSTATUS
4266 NTAPI
4267 SamrGetDisplayEnumerationIndex(IN SAMPR_HANDLE DomainHandle,
4268 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
4269 IN PRPC_UNICODE_STRING Prefix,
4270 OUT unsigned long *Index)
4271 {
4272 UNIMPLEMENTED;
4273 return STATUS_NOT_IMPLEMENTED;
4274 }
4275
4276 /* Function 42 */
4277 NTSTATUS
4278 NTAPI
4279 SamrTestPrivateFunctionsDomain(IN SAMPR_HANDLE DomainHandle)
4280 {
4281 UNIMPLEMENTED;
4282 return STATUS_NOT_IMPLEMENTED;
4283 }
4284
4285 /* Function 43 */
4286 NTSTATUS
4287 NTAPI
4288 SamrTestPrivateFunctionsUser(IN SAMPR_HANDLE UserHandle)
4289 {
4290 UNIMPLEMENTED;
4291 return STATUS_NOT_IMPLEMENTED;
4292 }
4293
4294 /* Function 44 */
4295 NTSTATUS
4296 NTAPI
4297 SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
4298 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
4299 {
4300 UNIMPLEMENTED;
4301 return STATUS_NOT_IMPLEMENTED;
4302 }
4303
4304 /* Function 45 */
4305 NTSTATUS
4306 NTAPI
4307 SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
4308 IN PRPC_SID MemberSid)
4309 {
4310 UNIMPLEMENTED;
4311 return STATUS_NOT_IMPLEMENTED;
4312 }
4313
4314 /* Function 46 */
4315 NTSTATUS
4316 NTAPI
4317 SamrQueryInformationDomain2(IN SAMPR_HANDLE DomainHandle,
4318 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
4319 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
4320 {
4321 UNIMPLEMENTED;
4322 return STATUS_NOT_IMPLEMENTED;
4323 }
4324
4325 /* Function 47 */
4326 NTSTATUS
4327 NTAPI
4328 SamrQueryInformationUser2(IN SAMPR_HANDLE UserHandle,
4329 IN USER_INFORMATION_CLASS UserInformationClass,
4330 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
4331 {
4332 UNIMPLEMENTED;
4333 return STATUS_NOT_IMPLEMENTED;
4334 }
4335
4336 /* Function 48 */
4337 NTSTATUS
4338 NTAPI
4339 SamrQueryDisplayInformation2(IN SAMPR_HANDLE DomainHandle,
4340 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
4341 IN unsigned long Index,
4342 IN unsigned long EntryCount,
4343 IN unsigned long PreferredMaximumLength,
4344 OUT unsigned long *TotalAvailable,
4345 OUT unsigned long *TotalReturned,
4346 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
4347 {
4348 UNIMPLEMENTED;
4349 return STATUS_NOT_IMPLEMENTED;
4350 }
4351
4352 /* Function 49 */
4353 NTSTATUS
4354 NTAPI
4355 SamrGetDisplayEnumerationIndex2(IN SAMPR_HANDLE DomainHandle,
4356 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
4357 IN PRPC_UNICODE_STRING Prefix,
4358 OUT unsigned long *Index)
4359 {
4360 UNIMPLEMENTED;
4361 return STATUS_NOT_IMPLEMENTED;
4362 }
4363
4364 /* Function 50 */
4365 NTSTATUS
4366 NTAPI
4367 SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
4368 IN PRPC_UNICODE_STRING Name,
4369 IN unsigned long AccountType,
4370 IN ACCESS_MASK DesiredAccess,
4371 OUT SAMPR_HANDLE *UserHandle,
4372 OUT unsigned long *GrantedAccess,
4373 OUT unsigned long *RelativeId)
4374 {
4375 UNIMPLEMENTED;
4376 return STATUS_NOT_IMPLEMENTED;
4377 }
4378
4379 /* Function 51 */
4380 NTSTATUS
4381 NTAPI
4382 SamrQueryDisplayInformation3(IN SAMPR_HANDLE DomainHandle,
4383 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
4384 IN unsigned long Index,
4385 IN unsigned long EntryCount,
4386 IN unsigned long PreferredMaximumLength,
4387 OUT unsigned long *TotalAvailable,
4388 OUT unsigned long *TotalReturned,
4389 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
4390 {
4391 UNIMPLEMENTED;
4392 return STATUS_NOT_IMPLEMENTED;
4393 }
4394
4395 /* Function 52 */
4396 NTSTATUS
4397 NTAPI
4398 SamrAddMultipleMembersToAlias(IN SAMPR_HANDLE AliasHandle,
4399 IN PSAMPR_PSID_ARRAY MembersBuffer)
4400 {
4401 UNIMPLEMENTED;
4402 return STATUS_NOT_IMPLEMENTED;
4403 }
4404
4405 /* Function 53 */
4406 NTSTATUS
4407 NTAPI
4408 SamrRemoveMultipleMembersFromAlias(IN SAMPR_HANDLE AliasHandle,
4409 IN PSAMPR_PSID_ARRAY MembersBuffer)
4410 {
4411 UNIMPLEMENTED;
4412 return STATUS_NOT_IMPLEMENTED;
4413 }
4414
4415 /* Function 54 */
4416 NTSTATUS
4417 NTAPI
4418 SamrOemChangePasswordUser2(IN handle_t BindingHandle,
4419 IN PRPC_STRING ServerName,
4420 IN PRPC_STRING UserName,
4421 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
4422 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewLm)
4423 {
4424 UNIMPLEMENTED;
4425 return STATUS_NOT_IMPLEMENTED;
4426 }
4427
4428 /* Function 55 */
4429 NTSTATUS
4430 NTAPI
4431 SamrUnicodeChangePasswordUser2(IN handle_t BindingHandle,
4432 IN PRPC_UNICODE_STRING ServerName,
4433 IN PRPC_UNICODE_STRING UserName,
4434 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldNt,
4435 IN PENCRYPTED_NT_OWF_PASSWORD OldNtOwfPasswordEncryptedWithNewNt,
4436 IN unsigned char LmPresent,
4437 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
4438 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewNt)
4439 {
4440 UNIMPLEMENTED;
4441 return STATUS_NOT_IMPLEMENTED;
4442 }
4443
4444 /* Function 56 */
4445 NTSTATUS
4446 NTAPI
4447 SamrGetDomainPasswordInformation(IN handle_t BindingHandle,
4448 IN PRPC_UNICODE_STRING Unused,
4449 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
4450 {
4451 UNIMPLEMENTED;
4452 return STATUS_NOT_IMPLEMENTED;
4453 }
4454
4455 /* Function 57 */
4456 NTSTATUS
4457 NTAPI
4458 SamrConnect2(IN PSAMPR_SERVER_NAME ServerName,
4459 OUT SAMPR_HANDLE *ServerHandle,
4460 IN ACCESS_MASK DesiredAccess)
4461 {
4462 UNIMPLEMENTED;
4463 return STATUS_NOT_IMPLEMENTED;
4464 }
4465
4466 /* Function 58 */
4467 NTSTATUS
4468 NTAPI
4469 SamrSetInformationUser2(IN SAMPR_HANDLE UserHandle,
4470 IN USER_INFORMATION_CLASS UserInformationClass,
4471 IN PSAMPR_USER_INFO_BUFFER Buffer)
4472 {
4473 UNIMPLEMENTED;
4474 return STATUS_NOT_IMPLEMENTED;
4475 }
4476
4477 /* Function 59 */
4478 NTSTATUS
4479 NTAPI
4480 SamrSetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
4481 {
4482 UNIMPLEMENTED;
4483 return STATUS_NOT_IMPLEMENTED;
4484 }
4485
4486 /* Function 60 */
4487 NTSTATUS
4488 NTAPI
4489 SamrGetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
4490 {
4491 UNIMPLEMENTED;
4492 return STATUS_NOT_IMPLEMENTED;
4493 }
4494
4495 /* Function 61 */
4496 NTSTATUS
4497 NTAPI
4498 SamrConnect3(IN handle_t BindingHandle) /* FIXME */
4499 {
4500 UNIMPLEMENTED;
4501 return STATUS_NOT_IMPLEMENTED;
4502 }
4503
4504 /* Function 62 */
4505 NTSTATUS
4506 NTAPI
4507 SamrConnect4(IN PSAMPR_SERVER_NAME ServerName,
4508 OUT SAMPR_HANDLE *ServerHandle,
4509 IN unsigned long ClientRevision,
4510 IN ACCESS_MASK DesiredAccess)
4511 {
4512 UNIMPLEMENTED;
4513 return STATUS_NOT_IMPLEMENTED;
4514 }
4515
4516 /* Function 63 */
4517 NTSTATUS
4518 NTAPI
4519 SamrUnicodeChangePasswordUser3(IN handle_t BindingHandle) /* FIXME */
4520 {
4521 UNIMPLEMENTED;
4522 return STATUS_NOT_IMPLEMENTED;
4523 }
4524
4525 /* Function 64 */
4526 NTSTATUS
4527 NTAPI
4528 SamrConnect5(IN PSAMPR_SERVER_NAME ServerName,
4529 IN ACCESS_MASK DesiredAccess,
4530 IN unsigned long InVersion,
4531 IN SAMPR_REVISION_INFO *InRevisionInfo,
4532 OUT unsigned long *OutVersion,
4533 OUT SAMPR_REVISION_INFO *OutRevisionInfo,
4534 OUT SAMPR_HANDLE *ServerHandle)
4535 {
4536 UNIMPLEMENTED;
4537 return STATUS_NOT_IMPLEMENTED;
4538 }
4539
4540 /* Function 65 */
4541 NTSTATUS
4542 NTAPI
4543 SamrRidToSid(IN SAMPR_HANDLE ObjectHandle,
4544 IN unsigned long Rid,
4545 OUT PRPC_SID *Sid)
4546 {
4547 UNIMPLEMENTED;
4548 return STATUS_NOT_IMPLEMENTED;
4549 }
4550
4551 /* Function 66 */
4552 NTSTATUS
4553 NTAPI
4554 SamrSetDSRMPassword(IN handle_t BindingHandle,
4555 IN PRPC_UNICODE_STRING Unused,
4556 IN unsigned long UserId,
4557 IN PENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword)
4558 {
4559 UNIMPLEMENTED;
4560 return STATUS_NOT_IMPLEMENTED;
4561 }
4562
4563 /* Function 67 */
4564 NTSTATUS
4565 NTAPI
4566 SamrValidatePassword(IN handle_t Handle,
4567 IN PASSWORD_POLICY_VALIDATION_TYPE ValidationType,
4568 IN PSAM_VALIDATE_INPUT_ARG InputArg,
4569 OUT PSAM_VALIDATE_OUTPUT_ARG *OutputArg)
4570 {
4571 UNIMPLEMENTED;
4572 return STATUS_NOT_IMPLEMENTED;
4573 }
4574
4575 /* EOF */