[SAMLIB]
[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 SampQueryDomainName(PSAM_DB_OBJECT DomainObject,
544 PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
545 {
546 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL;
547 ULONG Length = 0;
548 NTSTATUS Status;
549
550 *Buffer = NULL;
551
552 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER));
553 if (InfoBuffer == NULL)
554 return STATUS_INSUFFICIENT_RESOURCES;
555
556 Status = SampGetObjectAttribute(DomainObject,
557 L"Name",
558 NULL,
559 NULL,
560 &Length);
561 if (!NT_SUCCESS(Status))
562 goto done;
563
564 InfoBuffer->Name.DomainName.Length = Length - sizeof(WCHAR);
565 InfoBuffer->Name.DomainName.MaximumLength = Length;
566 InfoBuffer->Name.DomainName.Buffer = midl_user_allocate(Length);
567 if (InfoBuffer->Name.DomainName.Buffer == NULL)
568 {
569 Status = STATUS_INSUFFICIENT_RESOURCES;
570 goto done;
571 }
572
573 Status = SampGetObjectAttribute(DomainObject,
574 L"Name",
575 NULL,
576 (PVOID)InfoBuffer->Name.DomainName.Buffer,
577 &Length);
578 if (!NT_SUCCESS(Status))
579 goto done;
580
581 *Buffer = InfoBuffer;
582
583 done:
584 if (!NT_SUCCESS(Status))
585 {
586 if (InfoBuffer != NULL)
587 {
588 if (InfoBuffer->Name.DomainName.Buffer != NULL)
589 midl_user_free(InfoBuffer->Name.DomainName.Buffer);
590
591 midl_user_free(InfoBuffer);
592 }
593 }
594
595 return Status;
596 }
597
598
599 /* Function 8 */
600 NTSTATUS
601 NTAPI
602 SamrQueryInformationDomain(IN SAMPR_HANDLE DomainHandle,
603 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
604 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
605 {
606 PSAM_DB_OBJECT DomainObject;
607 NTSTATUS Status;
608
609 TRACE("SamrQueryInformationDomain(%p %lu %p)\n",
610 DomainHandle, DomainInformationClass, Buffer);
611
612 /* Validate the server handle */
613 Status = SampValidateDbObject(DomainHandle,
614 SamDbDomainObject,
615 DOMAIN_READ_OTHER_PARAMETERS,
616 &DomainObject);
617 if (!NT_SUCCESS(Status))
618 return Status;
619
620 switch (DomainInformationClass)
621 {
622 case DomainNameInformation:
623 Status = SampQueryDomainName(DomainObject,
624 Buffer);
625 break;
626
627 default:
628 Status = STATUS_NOT_IMPLEMENTED;
629 }
630
631 return Status;
632 }
633
634 static NTSTATUS
635 SampSetDomainName(PSAM_DB_OBJECT DomainObject,
636 PSAMPR_DOMAIN_NAME_INFORMATION DomainNameInfo)
637 {
638 NTSTATUS Status;
639
640 Status = SampSetObjectAttribute(DomainObject,
641 L"Name",
642 REG_SZ,
643 DomainNameInfo->DomainName.Buffer,
644 DomainNameInfo->DomainName.Length + sizeof(WCHAR));
645
646 return Status;
647 }
648
649 /* Function 9 */
650 NTSTATUS
651 NTAPI
652 SamrSetInformationDomain(IN SAMPR_HANDLE DomainHandle,
653 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
654 IN PSAMPR_DOMAIN_INFO_BUFFER DomainInformation)
655 {
656 PSAM_DB_OBJECT DomainObject;
657 NTSTATUS Status;
658
659 TRACE("SamrSetInformationDomain(%p %lu %p)\n",
660 DomainHandle, DomainInformationClass, DomainInformation);
661
662 /* Validate the server handle */
663 Status = SampValidateDbObject(DomainHandle,
664 SamDbDomainObject,
665 DOMAIN_WRITE_OTHER_PARAMETERS,
666 &DomainObject);
667 if (!NT_SUCCESS(Status))
668 return Status;
669
670 switch (DomainInformationClass)
671 {
672 case DomainNameInformation:
673 Status = SampSetDomainName(DomainObject,
674 &DomainInformation->Name);
675 break;
676
677 default:
678 Status = STATUS_NOT_IMPLEMENTED;
679 }
680
681 return Status;
682 }
683
684 /* Function 10 */
685 NTSTATUS
686 NTAPI
687 SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle,
688 IN PRPC_UNICODE_STRING Name,
689 IN ACCESS_MASK DesiredAccess,
690 OUT SAMPR_HANDLE *GroupHandle,
691 OUT unsigned long *RelativeId)
692 {
693 UNIMPLEMENTED;
694 return STATUS_NOT_IMPLEMENTED;
695 }
696
697 /* Function 10 */
698 NTSTATUS
699 NTAPI
700 SamrEnumerateGroupsInDomain(IN SAMPR_HANDLE DomainHandle,
701 IN OUT unsigned long *EnumerationContext,
702 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
703 IN unsigned long PreferedMaximumLength,
704 OUT unsigned long *CountReturned)
705 {
706 UNIMPLEMENTED;
707 return STATUS_NOT_IMPLEMENTED;
708 }
709
710 /* Function 12 */
711 NTSTATUS
712 NTAPI
713 SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle,
714 IN PRPC_UNICODE_STRING Name,
715 IN ACCESS_MASK DesiredAccess,
716 OUT SAMPR_HANDLE *UserHandle,
717 OUT unsigned long *RelativeId)
718 {
719 PSAM_DB_OBJECT DomainObject;
720 PSAM_DB_OBJECT UserObject;
721 ULONG ulSize;
722 ULONG ulRid;
723 WCHAR szRid[9];
724 BOOL bAliasExists = FALSE;
725 NTSTATUS Status;
726
727 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n",
728 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId);
729
730 /* Validate the domain handle */
731 Status = SampValidateDbObject(DomainHandle,
732 SamDbDomainObject,
733 DOMAIN_CREATE_USER,
734 &DomainObject);
735 if (!NT_SUCCESS(Status))
736 {
737 TRACE("failed with status 0x%08lx\n", Status);
738 return Status;
739 }
740
741 /* Get the NextRID attribute */
742 ulSize = sizeof(ULONG);
743 Status = SampGetObjectAttribute(DomainObject,
744 L"NextRID",
745 NULL,
746 (LPVOID)&ulRid,
747 &ulSize);
748 if (!NT_SUCCESS(Status))
749 ulRid = DOMAIN_USER_RID_MAX + 1;
750
751 TRACE("RID: %lx\n", ulRid);
752
753 /* Convert the RID into a string (hex) */
754 swprintf(szRid, L"%08lX", ulRid);
755
756 /* Check whether the user name is already in use */
757 Status = SampCheckDbObjectNameAlias(DomainObject,
758 L"Users",
759 Name->Buffer,
760 &bAliasExists);
761 if (!NT_SUCCESS(Status))
762 {
763 TRACE("failed with status 0x%08lx\n", Status);
764 return Status;
765 }
766
767 if (bAliasExists)
768 {
769 TRACE("The user account %S already exists!\n", Name->Buffer);
770 return STATUS_USER_EXISTS;
771 }
772
773 /* Create the user object */
774 Status = SampCreateDbObject(DomainObject,
775 L"Users",
776 szRid,
777 SamDbUserObject,
778 DesiredAccess,
779 &UserObject);
780 if (!NT_SUCCESS(Status))
781 {
782 TRACE("failed with status 0x%08lx\n", Status);
783 return Status;
784 }
785
786 /* Add the name alias for the user object */
787 Status = SampSetDbObjectNameAlias(DomainObject,
788 L"Users",
789 Name->Buffer,
790 ulRid);
791 if (!NT_SUCCESS(Status))
792 {
793 TRACE("failed with status 0x%08lx\n", Status);
794 return Status;
795 }
796
797 /* Set the name attribute */
798 Status = SampSetObjectAttribute(UserObject,
799 L"Name",
800 REG_SZ,
801 (LPVOID)Name->Buffer,
802 Name->MaximumLength);
803 if (!NT_SUCCESS(Status))
804 {
805 TRACE("failed with status 0x%08lx\n", Status);
806 return Status;
807 }
808
809 /* FIXME: Set default user attributes */
810
811 if (NT_SUCCESS(Status))
812 {
813 *UserHandle = (SAMPR_HANDLE)UserObject;
814 *RelativeId = ulRid;
815 }
816
817 /* Increment the NextRID attribute */
818 ulRid++;
819 ulSize = sizeof(ULONG);
820 SampSetObjectAttribute(DomainObject,
821 L"NextRID",
822 REG_DWORD,
823 (LPVOID)&ulRid,
824 ulSize);
825
826 TRACE("returns with status 0x%08lx\n", Status);
827
828 return Status;
829 }
830
831 /* Function 13 */
832 NTSTATUS
833 NTAPI
834 SamrEnumerateUsersInDomain(IN SAMPR_HANDLE DomainHandle,
835 IN OUT unsigned long *EnumerationContext,
836 IN unsigned long UserAccountControl,
837 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
838 IN unsigned long PreferedMaximumLength,
839 OUT unsigned long *CountReturned)
840 {
841 UNIMPLEMENTED;
842 return STATUS_NOT_IMPLEMENTED;
843 }
844
845 /* Function 14 */
846 NTSTATUS
847 NTAPI
848 SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle,
849 IN PRPC_UNICODE_STRING AccountName,
850 IN ACCESS_MASK DesiredAccess,
851 OUT SAMPR_HANDLE *AliasHandle,
852 OUT unsigned long *RelativeId)
853 {
854 PSAM_DB_OBJECT DomainObject;
855 PSAM_DB_OBJECT AliasObject;
856 UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
857 ULONG ulSize;
858 ULONG ulRid;
859 WCHAR szRid[9];
860 BOOL bAliasExists = FALSE;
861 NTSTATUS Status;
862
863 TRACE("SamrCreateAliasInDomain(%p %p %lx %p %p)\n",
864 DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId);
865
866 /* Validate the domain handle */
867 Status = SampValidateDbObject(DomainHandle,
868 SamDbDomainObject,
869 DOMAIN_CREATE_ALIAS,
870 &DomainObject);
871 if (!NT_SUCCESS(Status))
872 {
873 TRACE("failed with status 0x%08lx\n", Status);
874 return Status;
875 }
876
877 /* Get the NextRID attribute */
878 ulSize = sizeof(ULONG);
879 Status = SampGetObjectAttribute(DomainObject,
880 L"NextRID",
881 NULL,
882 (LPVOID)&ulRid,
883 &ulSize);
884 if (!NT_SUCCESS(Status))
885 ulRid = DOMAIN_USER_RID_MAX + 1;
886
887 TRACE("RID: %lx\n", ulRid);
888
889 /* Convert the RID into a string (hex) */
890 swprintf(szRid, L"%08lX", ulRid);
891
892 /* Check whether the user name is already in use */
893 Status = SampCheckDbObjectNameAlias(DomainObject,
894 L"Aliases",
895 AccountName->Buffer,
896 &bAliasExists);
897 if (!NT_SUCCESS(Status))
898 {
899 TRACE("failed with status 0x%08lx\n", Status);
900 return Status;
901 }
902
903 if (bAliasExists)
904 {
905 TRACE("The alias account %S already exists!\n", AccountName->Buffer);
906 return STATUS_ALIAS_EXISTS;
907 }
908
909 /* Create the user object */
910 Status = SampCreateDbObject(DomainObject,
911 L"Aliases",
912 szRid,
913 SamDbAliasObject,
914 DesiredAccess,
915 &AliasObject);
916 if (!NT_SUCCESS(Status))
917 {
918 TRACE("failed with status 0x%08lx\n", Status);
919 return Status;
920 }
921
922 /* Add the name alias for the user object */
923 Status = SampSetDbObjectNameAlias(DomainObject,
924 L"Aliases",
925 AccountName->Buffer,
926 ulRid);
927 if (!NT_SUCCESS(Status))
928 {
929 TRACE("failed with status 0x%08lx\n", Status);
930 return Status;
931 }
932
933 /* Set the Name attribute */
934 Status = SampSetObjectAttribute(AliasObject,
935 L"Name",
936 REG_SZ,
937 (LPVOID)AccountName->Buffer,
938 AccountName->MaximumLength);
939 if (!NT_SUCCESS(Status))
940 {
941 TRACE("failed with status 0x%08lx\n", Status);
942 return Status;
943 }
944
945 /* Set the Description attribute */
946 Status = SampSetObjectAttribute(AliasObject,
947 L"Description",
948 REG_SZ,
949 EmptyString.Buffer,
950 EmptyString.MaximumLength);
951 if (!NT_SUCCESS(Status))
952 {
953 TRACE("failed with status 0x%08lx\n", Status);
954 return Status;
955 }
956
957 if (NT_SUCCESS(Status))
958 {
959 *AliasHandle = (SAMPR_HANDLE)AliasObject;
960 *RelativeId = ulRid;
961 }
962
963 /* Increment the NextRID attribute */
964 ulRid++;
965 ulSize = sizeof(ULONG);
966 SampSetObjectAttribute(DomainObject,
967 L"NextRID",
968 REG_DWORD,
969 (LPVOID)&ulRid,
970 ulSize);
971
972 TRACE("returns with status 0x%08lx\n", Status);
973
974 return Status;
975 }
976
977 /* Function 15 */
978 NTSTATUS
979 NTAPI
980 SamrEnumerateAliasesInDomain(IN SAMPR_HANDLE DomainHandle,
981 IN OUT unsigned long *EnumerationContext,
982 OUT PSAMPR_ENUMERATION_BUFFER *Buffer,
983 IN unsigned long PreferedMaximumLength,
984 OUT unsigned long *CountReturned)
985 {
986 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL;
987 PSAM_DB_OBJECT DomainObject;
988 HANDLE AliasesKeyHandle;
989 WCHAR AliasKeyName[64];
990 HANDLE AliasKeyHandle;
991 ULONG EnumIndex;
992 ULONG EnumCount;
993 ULONG RequiredLength;
994 ULONG DataLength;
995 ULONG i;
996 BOOLEAN MoreEntries = FALSE;
997 NTSTATUS Status;
998
999 TRACE("SamrEnumerateAliasesInDomain(%p %p %p %lu %p)\n",
1000 DomainHandle, EnumerationContext, Buffer, PreferedMaximumLength,
1001 CountReturned);
1002
1003 /* Validate the domain handle */
1004 Status = SampValidateDbObject(DomainHandle,
1005 SamDbDomainObject,
1006 DOMAIN_LIST_ACCOUNTS,
1007 &DomainObject);
1008 if (!NT_SUCCESS(Status))
1009 return Status;
1010
1011 Status = SampRegOpenKey(DomainObject->KeyHandle,
1012 L"Aliases",
1013 KEY_READ,
1014 &AliasesKeyHandle);
1015 if (!NT_SUCCESS(Status))
1016 return Status;
1017
1018 TRACE("Part 1\n");
1019
1020 EnumIndex = *EnumerationContext;
1021 EnumCount = 0;
1022 RequiredLength = 0;
1023
1024 while (TRUE)
1025 {
1026 Status = SampRegEnumerateSubKey(AliasesKeyHandle,
1027 EnumIndex,
1028 64 * sizeof(WCHAR),
1029 AliasKeyName);
1030 if (!NT_SUCCESS(Status))
1031 {
1032 if (Status == STATUS_NO_MORE_ENTRIES)
1033 Status = STATUS_SUCCESS;
1034 break;
1035 }
1036
1037 TRACE("EnumIndex: %lu\n", EnumIndex);
1038 TRACE("Alias key name: %S\n", AliasKeyName);
1039
1040 Status = SampRegOpenKey(AliasesKeyHandle,
1041 AliasKeyName,
1042 KEY_READ,
1043 &AliasKeyHandle);
1044 TRACE("SampRegOpenKey returned %08lX\n", Status);
1045 if (NT_SUCCESS(Status))
1046 {
1047 DataLength = 0;
1048 Status = SampRegQueryValue(AliasKeyHandle,
1049 L"Name",
1050 NULL,
1051 NULL,
1052 &DataLength);
1053
1054 NtClose(AliasKeyHandle);
1055
1056 TRACE("SampRegQueryValue returned %08lX\n", Status);
1057
1058 if (NT_SUCCESS(Status))
1059 {
1060 TRACE("Data length: %lu\n", DataLength);
1061
1062 if ((RequiredLength + DataLength + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength)
1063 {
1064 MoreEntries = TRUE;
1065 break;
1066 }
1067
1068 RequiredLength += (DataLength + sizeof(SAMPR_RID_ENUMERATION));
1069 EnumCount++;
1070 }
1071 }
1072
1073 EnumIndex++;
1074 }
1075
1076 TRACE("EnumCount: %lu\n", EnumCount);
1077 TRACE("RequiredLength: %lu\n", RequiredLength);
1078
1079 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER));
1080 if (EnumBuffer == NULL)
1081 {
1082 Status = STATUS_INSUFFICIENT_RESOURCES;
1083 goto done;
1084 }
1085
1086 EnumBuffer->EntriesRead = EnumCount;
1087 if (EnumCount == 0)
1088 goto done;
1089
1090 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION));
1091 if (EnumBuffer->Buffer == NULL)
1092 {
1093 Status = STATUS_INSUFFICIENT_RESOURCES;
1094 goto done;
1095 }
1096
1097 TRACE("Part 2\n");
1098
1099 EnumIndex = *EnumerationContext;
1100 for (i = 0; i < EnumCount; i++, EnumIndex++)
1101 {
1102 Status = SampRegEnumerateSubKey(AliasesKeyHandle,
1103 EnumIndex,
1104 64 * sizeof(WCHAR),
1105 AliasKeyName);
1106 if (!NT_SUCCESS(Status))
1107 {
1108 if (Status == STATUS_NO_MORE_ENTRIES)
1109 Status = STATUS_SUCCESS;
1110 break;
1111 }
1112
1113 TRACE("EnumIndex: %lu\n", EnumIndex);
1114 TRACE("Alias key name: %S\n", AliasKeyName);
1115
1116 Status = SampRegOpenKey(AliasesKeyHandle,
1117 AliasKeyName,
1118 KEY_READ,
1119 &AliasKeyHandle);
1120 TRACE("SampRegOpenKey returned %08lX\n", Status);
1121 if (NT_SUCCESS(Status))
1122 {
1123 DataLength = 0;
1124 Status = SampRegQueryValue(AliasKeyHandle,
1125 L"Name",
1126 NULL,
1127 NULL,
1128 &DataLength);
1129 TRACE("SampRegQueryValue returned %08lX\n", Status);
1130 if (NT_SUCCESS(Status))
1131 {
1132 EnumBuffer->Buffer[i].RelativeId = wcstoul(AliasKeyName, NULL, 16);
1133
1134 EnumBuffer->Buffer[i].Name.Length = (USHORT)DataLength - sizeof(WCHAR);
1135 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)DataLength;
1136 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(DataLength);
1137 if (EnumBuffer->Buffer[i].Name.Buffer == NULL)
1138 {
1139 NtClose(AliasKeyHandle);
1140 Status = STATUS_INSUFFICIENT_RESOURCES;
1141 goto done;
1142 }
1143
1144 Status = SampRegQueryValue(AliasKeyHandle,
1145 L"Name",
1146 NULL,
1147 EnumBuffer->Buffer[i].Name.Buffer,
1148 &DataLength);
1149 TRACE("SampRegQueryValue returned %08lX\n", Status);
1150 if (NT_SUCCESS(Status))
1151 {
1152 TRACE("Alias name: %S\n", EnumBuffer->Buffer[i].Name.Buffer);
1153 }
1154 }
1155
1156 NtClose(AliasKeyHandle);
1157
1158 if (!NT_SUCCESS(Status))
1159 goto done;
1160 }
1161 }
1162
1163 done:
1164 if (NT_SUCCESS(Status))
1165 {
1166 *EnumerationContext += EnumCount;
1167 *Buffer = EnumBuffer;
1168 *CountReturned = EnumCount;
1169 }
1170
1171 if (!NT_SUCCESS(Status))
1172 {
1173 *EnumerationContext = 0;
1174 *Buffer = NULL;
1175 *CountReturned = 0;
1176
1177 if (EnumBuffer != NULL)
1178 {
1179 if (EnumBuffer->Buffer != NULL)
1180 {
1181 if (EnumBuffer->EntriesRead != 0)
1182 {
1183 for (i = 0; i < EnumBuffer->EntriesRead; i++)
1184 {
1185 if (EnumBuffer->Buffer[i].Name.Buffer != NULL)
1186 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer);
1187 }
1188 }
1189
1190 midl_user_free(EnumBuffer->Buffer);
1191 }
1192
1193 midl_user_free(EnumBuffer);
1194 }
1195 }
1196
1197 NtClose(AliasesKeyHandle);
1198
1199 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
1200 Status = STATUS_MORE_ENTRIES;
1201
1202 return Status;
1203 }
1204
1205 /* Function 16 */
1206 NTSTATUS
1207 NTAPI
1208 SamrGetAliasMembership(IN SAMPR_HANDLE DomainHandle,
1209 IN PSAMPR_PSID_ARRAY SidArray,
1210 OUT PSAMPR_ULONG_ARRAY Membership)
1211 {
1212 PSAM_DB_OBJECT DomainObject;
1213 HANDLE AliasesKeyHandle = NULL;
1214 HANDLE MembersKeyHandle = NULL;
1215 HANDLE MemberKeyHandle = NULL;
1216 LPWSTR MemberSidString = NULL;
1217 PULONG RidArray = NULL;
1218 ULONG MaxSidCount = 0;
1219 ULONG ValueCount;
1220 ULONG DataLength;
1221 ULONG i, j;
1222 NTSTATUS Status;
1223
1224 TRACE("SamrGetAliasMembership(%p %p %p)\n",
1225 DomainHandle, SidArray, Membership);
1226
1227 /* Validate the domain handle */
1228 Status = SampValidateDbObject(DomainHandle,
1229 SamDbDomainObject,
1230 DOMAIN_LOOKUP,
1231 &DomainObject);
1232 if (!NT_SUCCESS(Status))
1233 return Status;
1234
1235 Status = SampRegOpenKey(DomainObject->KeyHandle,
1236 L"Aliases",
1237 KEY_READ,
1238 &AliasesKeyHandle);
1239 TRACE("SampRegOpenKey returned %08lX\n", Status);
1240 if (!NT_SUCCESS(Status))
1241 goto done;
1242
1243 Status = SampRegOpenKey(AliasesKeyHandle,
1244 L"Members",
1245 KEY_READ,
1246 &MembersKeyHandle);
1247 TRACE("SampRegOpenKey returned %08lX\n", Status);
1248 if (!NT_SUCCESS(Status))
1249 goto done;
1250
1251 for (i = 0; i < SidArray->Count; i++)
1252 {
1253 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
1254 TRACE("Open %S\n", MemberSidString);
1255
1256 Status = SampRegOpenKey(MembersKeyHandle,
1257 MemberSidString,
1258 KEY_READ,
1259 &MemberKeyHandle);
1260 TRACE("SampRegOpenKey returned %08lX\n", Status);
1261 if (NT_SUCCESS(Status))
1262 {
1263 Status = SampRegQueryKeyInfo(MemberKeyHandle,
1264 NULL,
1265 &ValueCount);
1266 if (NT_SUCCESS(Status))
1267 {
1268 TRACE("Found %lu values\n", ValueCount);
1269 MaxSidCount += ValueCount;
1270 }
1271
1272
1273 NtClose(MemberKeyHandle);
1274 }
1275
1276 LocalFree(MemberSidString);
1277 }
1278
1279 TRACE("Maximum sid count: %lu\n", MaxSidCount);
1280 RidArray = midl_user_allocate(MaxSidCount * sizeof(ULONG));
1281 if (RidArray == NULL)
1282 {
1283 Status = STATUS_INSUFFICIENT_RESOURCES;
1284 goto done;
1285 }
1286
1287 for (i = 0; i < SidArray->Count; i++)
1288 {
1289 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString);
1290 TRACE("Open %S\n", MemberSidString);
1291
1292 Status = SampRegOpenKey(MembersKeyHandle,
1293 MemberSidString,
1294 KEY_READ,
1295 &MemberKeyHandle);
1296 TRACE("SampRegOpenKey returned %08lX\n", Status);
1297 if (NT_SUCCESS(Status))
1298 {
1299 Status = SampRegQueryKeyInfo(MemberKeyHandle,
1300 NULL,
1301 &ValueCount);
1302 if (NT_SUCCESS(Status))
1303 {
1304 TRACE("Found %lu values\n", ValueCount);
1305
1306 for (j = 0; j < ValueCount; j++)
1307 {
1308 DataLength = sizeof(ULONG);
1309 Status = SampRegEnumerateValue(MemberKeyHandle,
1310 j,
1311 NULL,
1312 NULL,
1313 NULL,
1314 (PVOID)&RidArray[j],
1315 &DataLength);
1316 }
1317 }
1318
1319 NtClose(MemberKeyHandle);
1320 }
1321
1322 LocalFree(MemberSidString);
1323 }
1324
1325
1326 done:
1327 if (NT_SUCCESS(Status))
1328 {
1329 Membership->Count = MaxSidCount;
1330 Membership->Element = RidArray;
1331 }
1332 else
1333 {
1334 if (RidArray != NULL)
1335 midl_user_free(RidArray);
1336 }
1337
1338 if (MembersKeyHandle != NULL)
1339 NtClose(MembersKeyHandle);
1340
1341 if (MembersKeyHandle != NULL)
1342 NtClose(MembersKeyHandle);
1343
1344 if (AliasesKeyHandle != NULL)
1345 NtClose(AliasesKeyHandle);
1346
1347 return Status;
1348 }
1349
1350 /* Function 17 */
1351 NTSTATUS
1352 NTAPI
1353 SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle,
1354 IN unsigned long Count,
1355 IN RPC_UNICODE_STRING Names[],
1356 OUT PSAMPR_ULONG_ARRAY RelativeIds,
1357 OUT PSAMPR_ULONG_ARRAY Use)
1358 {
1359 UNIMPLEMENTED;
1360 return STATUS_NOT_IMPLEMENTED;
1361 }
1362
1363 /* Function 18 */
1364 NTSTATUS
1365 NTAPI
1366 SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle,
1367 IN unsigned long Count,
1368 IN unsigned long *RelativeIds,
1369 OUT PSAMPR_RETURNED_USTRING_ARRAY Names,
1370 OUT PSAMPR_ULONG_ARRAY Use)
1371 {
1372 UNIMPLEMENTED;
1373 return STATUS_NOT_IMPLEMENTED;
1374 }
1375
1376 /* Function 19 */
1377 NTSTATUS
1378 NTAPI
1379 SamrOpenGroup(IN SAMPR_HANDLE DomainHandle,
1380 IN ACCESS_MASK DesiredAccess,
1381 IN unsigned long GroupId,
1382 OUT SAMPR_HANDLE *GroupHandle)
1383 {
1384 UNIMPLEMENTED;
1385 return STATUS_NOT_IMPLEMENTED;
1386 }
1387
1388 /* Function 20 */
1389 NTSTATUS
1390 NTAPI
1391 SamrQueryInformationGroup(IN SAMPR_HANDLE GroupHandle,
1392 IN GROUP_INFORMATION_CLASS GroupInformationClass,
1393 OUT PSAMPR_GROUP_INFO_BUFFER *Buffer)
1394 {
1395 UNIMPLEMENTED;
1396 return STATUS_NOT_IMPLEMENTED;
1397 }
1398
1399 /* Function 21 */
1400 NTSTATUS
1401 NTAPI
1402 SamrSetInformationGroup(IN SAMPR_HANDLE GroupHandle,
1403 IN GROUP_INFORMATION_CLASS GroupInformationClass,
1404 IN PSAMPR_GROUP_INFO_BUFFER Buffer)
1405 {
1406 UNIMPLEMENTED;
1407 return STATUS_NOT_IMPLEMENTED;
1408 }
1409
1410 /* Function 22 */
1411 NTSTATUS
1412 NTAPI
1413 SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle,
1414 IN unsigned long MemberId,
1415 IN unsigned long Attributes)
1416 {
1417 UNIMPLEMENTED;
1418 return STATUS_NOT_IMPLEMENTED;
1419 }
1420
1421 /* Function 21 */
1422 NTSTATUS
1423 NTAPI
1424 SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle)
1425 {
1426 UNIMPLEMENTED;
1427 return STATUS_NOT_IMPLEMENTED;
1428 }
1429
1430 /* Function 24 */
1431 NTSTATUS
1432 NTAPI
1433 SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle,
1434 IN unsigned long MemberId)
1435 {
1436 UNIMPLEMENTED;
1437 return STATUS_NOT_IMPLEMENTED;
1438 }
1439
1440 /* Function 25 */
1441 NTSTATUS
1442 NTAPI
1443 SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle,
1444 OUT PSAMPR_GET_MEMBERS_BUFFER *Members)
1445 {
1446 UNIMPLEMENTED;
1447 return STATUS_NOT_IMPLEMENTED;
1448 }
1449
1450 /* Function 26 */
1451 NTSTATUS
1452 NTAPI
1453 SamrSetMemberAttributesOfGroup(IN SAMPR_HANDLE GroupHandle,
1454 IN unsigned long MemberId,
1455 IN unsigned long Attributes)
1456 {
1457 UNIMPLEMENTED;
1458 return STATUS_NOT_IMPLEMENTED;
1459 }
1460
1461 /* Function 27 */
1462 NTSTATUS
1463 NTAPI
1464 SamrOpenAlias(IN SAMPR_HANDLE DomainHandle,
1465 IN ACCESS_MASK DesiredAccess,
1466 IN ULONG AliasId,
1467 OUT SAMPR_HANDLE *AliasHandle)
1468 {
1469 PSAM_DB_OBJECT DomainObject;
1470 PSAM_DB_OBJECT AliasObject;
1471 WCHAR szRid[9];
1472 NTSTATUS Status;
1473
1474 TRACE("SamrOpenAlias(%p %lx %lx %p)\n",
1475 DomainHandle, DesiredAccess, AliasId, AliasHandle);
1476
1477 /* Validate the domain handle */
1478 Status = SampValidateDbObject(DomainHandle,
1479 SamDbDomainObject,
1480 DOMAIN_LOOKUP,
1481 &DomainObject);
1482 if (!NT_SUCCESS(Status))
1483 {
1484 TRACE("failed with status 0x%08lx\n", Status);
1485 return Status;
1486 }
1487
1488 /* Convert the RID into a string (hex) */
1489 swprintf(szRid, L"%08lX", AliasId);
1490
1491 /* Create the alias object */
1492 Status = SampOpenDbObject(DomainObject,
1493 L"Aliases",
1494 szRid,
1495 SamDbAliasObject,
1496 DesiredAccess,
1497 &AliasObject);
1498 if (!NT_SUCCESS(Status))
1499 {
1500 TRACE("failed with status 0x%08lx\n", Status);
1501 return Status;
1502 }
1503
1504 *AliasHandle = (SAMPR_HANDLE)AliasObject;
1505
1506 return STATUS_SUCCESS;
1507 }
1508
1509 /* Function 28 */
1510 NTSTATUS
1511 NTAPI
1512 SamrQueryInformationAlias(IN SAMPR_HANDLE AliasHandle,
1513 IN ALIAS_INFORMATION_CLASS AliasInformationClass,
1514 OUT PSAMPR_ALIAS_INFO_BUFFER *Buffer)
1515 {
1516 PSAM_DB_OBJECT AliasObject;
1517 NTSTATUS Status;
1518
1519 TRACE("SamrQueryInformationAlias(%p %lu %p)\n",
1520 AliasHandle, AliasInformationClass, Buffer);
1521
1522 /* Validate the alias handle */
1523 Status = SampValidateDbObject(AliasHandle,
1524 SamDbAliasObject,
1525 ALIAS_READ_INFORMATION,
1526 &AliasObject);
1527 if (!NT_SUCCESS(Status))
1528 return Status;
1529
1530 switch (AliasInformationClass)
1531 {
1532 #if 0
1533 case AliasGeneralInformation:
1534 Status = SampQueryAliasGeneral(AliasObject,
1535 &Buffer->General);
1536 break;
1537
1538 case AliasNameInformation:
1539 Status = SampQueryAliasName(AliasObject,
1540 &Buffer->Name);
1541 break;
1542
1543 case AliasAdminCommentInformation:
1544 Status = SampQueryAliasAdminComment(AliasObject,
1545 &Buffer->AdminComment);
1546 break;
1547 #endif
1548
1549 default:
1550 Status = STATUS_INVALID_INFO_CLASS;
1551 break;
1552 }
1553
1554 return Status;
1555 }
1556
1557
1558 static NTSTATUS
1559 SampSetAliasName(PSAM_DB_OBJECT AliasObject,
1560 PSAMPR_ALIAS_NAME_INFORMATION AliasNameInfo)
1561 {
1562 NTSTATUS Status;
1563
1564 Status = SampSetObjectAttribute(AliasObject,
1565 L"Name",
1566 REG_SZ,
1567 AliasNameInfo->Name.Buffer,
1568 AliasNameInfo->Name.Length + sizeof(WCHAR));
1569
1570 return Status;
1571 }
1572
1573 static NTSTATUS
1574 SampSetAliasAdminComment(PSAM_DB_OBJECT AliasObject,
1575 PSAMPR_ALIAS_ADM_COMMENT_INFORMATION AliasAdminCommentInfo)
1576 {
1577 NTSTATUS Status;
1578
1579 Status = SampSetObjectAttribute(AliasObject,
1580 L"Description",
1581 REG_SZ,
1582 AliasAdminCommentInfo->AdminComment.Buffer,
1583 AliasAdminCommentInfo->AdminComment.Length + sizeof(WCHAR));
1584
1585 return Status;
1586 }
1587
1588 /* Function 29 */
1589 NTSTATUS
1590 NTAPI
1591 SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle,
1592 IN ALIAS_INFORMATION_CLASS AliasInformationClass,
1593 IN PSAMPR_ALIAS_INFO_BUFFER Buffer)
1594 {
1595 PSAM_DB_OBJECT AliasObject;
1596 NTSTATUS Status;
1597
1598 TRACE("SamrSetInformationAlias(%p %lu %p)\n",
1599 AliasHandle, AliasInformationClass, Buffer);
1600
1601 /* Validate the alias handle */
1602 Status = SampValidateDbObject(AliasHandle,
1603 SamDbAliasObject,
1604 ALIAS_WRITE_ACCOUNT,
1605 &AliasObject);
1606 if (!NT_SUCCESS(Status))
1607 return Status;
1608
1609 switch (AliasInformationClass)
1610 {
1611 case AliasNameInformation:
1612 Status = SampSetAliasName(AliasObject,
1613 &Buffer->Name);
1614 break;
1615
1616 case AliasAdminCommentInformation:
1617 Status = SampSetAliasAdminComment(AliasObject,
1618 &Buffer->AdminComment);
1619 break;
1620
1621 default:
1622 Status = STATUS_INVALID_INFO_CLASS;
1623 break;
1624 }
1625
1626 return Status;
1627 }
1628
1629 /* Function 30 */
1630 NTSTATUS
1631 NTAPI
1632 SamrDeleteAlias(IN OUT SAMPR_HANDLE *AliasHandle)
1633 {
1634 UNIMPLEMENTED;
1635 return STATUS_NOT_IMPLEMENTED;
1636 }
1637
1638 /* Function 31 */
1639 NTSTATUS
1640 NTAPI
1641 SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle,
1642 IN PRPC_SID MemberId)
1643 {
1644 PSAM_DB_OBJECT AliasObject;
1645 LPWSTR MemberIdString = NULL;
1646 HANDLE MembersKeyHandle = NULL;
1647 HANDLE MemberKeyHandle = NULL;
1648 ULONG MemberIdLength;
1649 NTSTATUS Status;
1650
1651 TRACE("SamrAddMemberToAlias(%p %p)\n",
1652 AliasHandle, MemberId);
1653
1654 /* Validate the domain handle */
1655 Status = SampValidateDbObject(AliasHandle,
1656 SamDbAliasObject,
1657 ALIAS_ADD_MEMBER,
1658 &AliasObject);
1659 if (!NT_SUCCESS(Status))
1660 {
1661 TRACE("failed with status 0x%08lx\n", Status);
1662 return Status;
1663 }
1664
1665 ConvertSidToStringSidW(MemberId, &MemberIdString);
1666 TRACE("Member SID: %S\n", MemberIdString);
1667
1668 MemberIdLength = RtlLengthSid(MemberId);
1669
1670 Status = SampRegCreateKey(AliasObject->KeyHandle,
1671 L"Members",
1672 KEY_WRITE,
1673 &MembersKeyHandle);
1674 if (!NT_SUCCESS(Status))
1675 {
1676 TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
1677 goto done;
1678 }
1679
1680 Status = SampRegSetValue(MembersKeyHandle,
1681 MemberIdString,
1682 REG_BINARY,
1683 MemberId,
1684 MemberIdLength);
1685 if (!NT_SUCCESS(Status))
1686 {
1687 TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
1688 goto done;
1689 }
1690
1691 Status = SampRegCreateKey(AliasObject->MembersKeyHandle,
1692 MemberIdString,
1693 KEY_WRITE,
1694 &MemberKeyHandle);
1695 if (!NT_SUCCESS(Status))
1696 {
1697 TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
1698 goto done;
1699 }
1700
1701 Status = SampRegSetValue(MemberKeyHandle,
1702 AliasObject->Name,
1703 REG_BINARY,
1704 MemberId,
1705 MemberIdLength);
1706 if (!NT_SUCCESS(Status))
1707 {
1708 TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
1709 goto done;
1710 }
1711
1712 done:
1713 if (MemberKeyHandle != NULL)
1714 SampRegCloseKey(MemberKeyHandle);
1715
1716 if (MembersKeyHandle != NULL)
1717 SampRegCloseKey(MembersKeyHandle);
1718
1719 if (MemberIdString != NULL)
1720 LocalFree(MemberIdString);
1721
1722 return Status;
1723 }
1724
1725 /* Function 32 */
1726 NTSTATUS
1727 NTAPI
1728 SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle,
1729 IN PRPC_SID MemberId)
1730 {
1731 UNIMPLEMENTED;
1732 return STATUS_NOT_IMPLEMENTED;
1733 }
1734
1735 /* Function 33 */
1736 NTSTATUS
1737 NTAPI
1738 SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle,
1739 OUT PSAMPR_PSID_ARRAY_OUT Members)
1740 {
1741 PSAM_DB_OBJECT AliasObject;
1742 HANDLE MembersKeyHandle = NULL;
1743 PSAMPR_SID_INFORMATION MemberArray = NULL;
1744 ULONG ValueCount = 0;
1745 ULONG DataLength;
1746 ULONG Index;
1747 NTSTATUS Status;
1748
1749 TRACE("SamrGetMembersInAlias(%p %p %p)\n",
1750 AliasHandle, Members);
1751
1752 /* Validate the alias handle */
1753 Status = SampValidateDbObject(AliasHandle,
1754 SamDbAliasObject,
1755 ALIAS_LIST_MEMBERS,
1756 &AliasObject);
1757 if (!NT_SUCCESS(Status))
1758 {
1759 ERR("failed with status 0x%08lx\n", Status);
1760 return Status;
1761 }
1762
1763 /* Open the members key of the alias objct */
1764 Status = SampRegOpenKey(AliasObject->KeyHandle,
1765 L"Members",
1766 KEY_READ,
1767 &MembersKeyHandle);
1768 if (!NT_SUCCESS(Status))
1769 {
1770 ERR("SampRegOpenKey failed with status 0x%08lx\n", Status);
1771 return Status;
1772 }
1773
1774 /* Get the number of members */
1775 Status = SampRegQueryKeyInfo(MembersKeyHandle,
1776 NULL,
1777 &ValueCount);
1778 if (!NT_SUCCESS(Status))
1779 {
1780 ERR("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
1781 goto done;
1782 }
1783
1784 /* Allocate the member array */
1785 MemberArray = midl_user_allocate(ValueCount * sizeof(SAMPR_SID_INFORMATION));
1786 if (MemberArray == NULL)
1787 {
1788 Status = STATUS_INSUFFICIENT_RESOURCES;
1789 goto done;
1790 }
1791
1792 /* Enumerate the members */
1793 Index = 0;
1794 while (TRUE)
1795 {
1796 /* Get the size of the next SID */
1797 DataLength = 0;
1798 Status = SampRegEnumerateValue(MembersKeyHandle,
1799 Index,
1800 NULL,
1801 NULL,
1802 NULL,
1803 NULL,
1804 &DataLength);
1805 if (!NT_SUCCESS(Status))
1806 {
1807 if (Status == STATUS_NO_MORE_ENTRIES)
1808 Status = STATUS_SUCCESS;
1809 break;
1810 }
1811
1812 /* Allocate a buffer for the SID */
1813 MemberArray[Index].SidPointer = midl_user_allocate(DataLength);
1814 if (MemberArray[Index].SidPointer == NULL)
1815 {
1816 Status = STATUS_INSUFFICIENT_RESOURCES;
1817 goto done;
1818 }
1819
1820 /* Read the SID into the buffer */
1821 Status = SampRegEnumerateValue(MembersKeyHandle,
1822 Index,
1823 NULL,
1824 NULL,
1825 NULL,
1826 (PVOID)MemberArray[Index].SidPointer,
1827 &DataLength);
1828 if (!NT_SUCCESS(Status))
1829 {
1830 goto done;
1831 }
1832
1833 Index++;
1834 }
1835
1836 /* Return the number of members and the member array */
1837 if (NT_SUCCESS(Status))
1838 {
1839 Members->Count = ValueCount;
1840 Members->Sids = MemberArray;
1841 }
1842
1843 done:
1844 /* Clean up the members array and the SID buffers if something failed */
1845 if (!NT_SUCCESS(Status))
1846 {
1847 if (MemberArray != NULL)
1848 {
1849 for (Index = 0; Index < ValueCount; Index++)
1850 {
1851 if (MemberArray[Index].SidPointer != NULL)
1852 midl_user_free(MemberArray[Index].SidPointer);
1853 }
1854
1855 midl_user_free(MemberArray);
1856 }
1857 }
1858
1859 /* Close the members key */
1860 if (MembersKeyHandle != NULL)
1861 SampRegCloseKey(MembersKeyHandle);
1862
1863 return Status;
1864 }
1865
1866 /* Function 34 */
1867 NTSTATUS
1868 NTAPI
1869 SamrOpenUser(IN SAMPR_HANDLE DomainHandle,
1870 IN ACCESS_MASK DesiredAccess,
1871 IN unsigned long UserId,
1872 OUT SAMPR_HANDLE *UserHandle)
1873 {
1874 PSAM_DB_OBJECT DomainObject;
1875 PSAM_DB_OBJECT UserObject;
1876 WCHAR szRid[9];
1877 NTSTATUS Status;
1878
1879 TRACE("SamrOpenUser(%p %lx %lx %p)\n",
1880 DomainHandle, DesiredAccess, UserId, UserHandle);
1881
1882 /* Validate the domain handle */
1883 Status = SampValidateDbObject(DomainHandle,
1884 SamDbDomainObject,
1885 DOMAIN_LOOKUP,
1886 &DomainObject);
1887 if (!NT_SUCCESS(Status))
1888 {
1889 TRACE("failed with status 0x%08lx\n", Status);
1890 return Status;
1891 }
1892
1893 /* Convert the RID into a string (hex) */
1894 swprintf(szRid, L"%08lX", UserId);
1895
1896 /* Create the user object */
1897 Status = SampOpenDbObject(DomainObject,
1898 L"Users",
1899 szRid,
1900 SamDbUserObject,
1901 DesiredAccess,
1902 &UserObject);
1903 if (!NT_SUCCESS(Status))
1904 {
1905 TRACE("failed with status 0x%08lx\n", Status);
1906 return Status;
1907 }
1908
1909 *UserHandle = (SAMPR_HANDLE)UserObject;
1910
1911 return STATUS_SUCCESS;
1912 }
1913
1914 /* Function 35 */
1915 NTSTATUS
1916 NTAPI
1917 SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle)
1918 {
1919 UNIMPLEMENTED;
1920 return STATUS_NOT_IMPLEMENTED;
1921 }
1922
1923 /* Function 36 */
1924 NTSTATUS
1925 NTAPI
1926 SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle,
1927 IN USER_INFORMATION_CLASS UserInformationClass,
1928 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
1929 {
1930 UNIMPLEMENTED;
1931 return STATUS_NOT_IMPLEMENTED;
1932 }
1933
1934
1935 static
1936 NTSTATUS
1937 SampSetPasswordInformation(PSAM_DB_OBJECT UserObject,
1938 PSAMPR_USER_SET_PASSWORD_INFORMATION PasswordInfo)
1939 {
1940 NTSTATUS Status;
1941
1942 TRACE("Password: %S\n", PasswordInfo->Password.Buffer);
1943 TRACE("PasswordExpired: %d\n", PasswordInfo->PasswordExpired);
1944
1945 Status = SampSetObjectAttribute(UserObject,
1946 L"Password",
1947 REG_SZ,
1948 PasswordInfo->Password.Buffer,
1949 PasswordInfo->Password.MaximumLength);
1950
1951 return Status;
1952 }
1953
1954
1955 /* Function 37 */
1956 NTSTATUS
1957 NTAPI
1958 SamrSetInformationUser(IN SAMPR_HANDLE UserHandle,
1959 IN USER_INFORMATION_CLASS UserInformationClass,
1960 IN PSAMPR_USER_INFO_BUFFER Buffer)
1961 {
1962 PSAM_DB_OBJECT UserObject;
1963 NTSTATUS Status;
1964
1965 TRACE("SamrSetInformationUser(%p %lu %p)\n",
1966 UserHandle, UserInformationClass, Buffer);
1967
1968 /* Validate the domain handle */
1969 Status = SampValidateDbObject(UserHandle,
1970 SamDbUserObject,
1971 USER_FORCE_PASSWORD_CHANGE,
1972 &UserObject);
1973 if (!NT_SUCCESS(Status))
1974 {
1975 TRACE("failed with status 0x%08lx\n", Status);
1976 return Status;
1977 }
1978
1979 switch (UserInformationClass)
1980 {
1981 case UserSetPasswordInformation:
1982 Status = SampSetPasswordInformation(UserObject,
1983 (PSAMPR_USER_SET_PASSWORD_INFORMATION)Buffer);
1984 break;
1985
1986 default:
1987 Status = STATUS_INVALID_INFO_CLASS;
1988 break;
1989 }
1990
1991 return Status;
1992 }
1993
1994 /* Function 38 */
1995 NTSTATUS
1996 NTAPI
1997 SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle,
1998 IN unsigned char LmPresent,
1999 IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm,
2000 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm,
2001 IN unsigned char NtPresent,
2002 IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt,
2003 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt,
2004 IN unsigned char NtCrossEncryptionPresent,
2005 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm,
2006 IN unsigned char LmCrossEncryptionPresent,
2007 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt)
2008 {
2009 UNIMPLEMENTED;
2010 return STATUS_NOT_IMPLEMENTED;
2011 }
2012
2013 /* Function 39 */
2014 NTSTATUS
2015 NTAPI
2016 SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle,
2017 OUT PSAMPR_GET_GROUPS_BUFFER *Groups)
2018 {
2019 UNIMPLEMENTED;
2020 return STATUS_NOT_IMPLEMENTED;
2021 }
2022
2023 /* Function 40 */
2024 NTSTATUS
2025 NTAPI
2026 SamrQueryDisplayInformation(IN SAMPR_HANDLE DomainHandle,
2027 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
2028 IN unsigned long Index,
2029 IN unsigned long EntryCount,
2030 IN unsigned long PreferredMaximumLength,
2031 OUT unsigned long *TotalAvailable,
2032 OUT unsigned long *TotalReturned,
2033 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
2034 {
2035 UNIMPLEMENTED;
2036 return STATUS_NOT_IMPLEMENTED;
2037 }
2038
2039 /* Function 41 */
2040 NTSTATUS
2041 NTAPI
2042 SamrGetDisplayEnumerationIndex(IN SAMPR_HANDLE DomainHandle,
2043 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
2044 IN PRPC_UNICODE_STRING Prefix,
2045 OUT unsigned long *Index)
2046 {
2047 UNIMPLEMENTED;
2048 return STATUS_NOT_IMPLEMENTED;
2049 }
2050
2051 /* Function 42 */
2052 NTSTATUS
2053 NTAPI
2054 SamrTestPrivateFunctionsDomain(IN SAMPR_HANDLE DomainHandle)
2055 {
2056 UNIMPLEMENTED;
2057 return STATUS_NOT_IMPLEMENTED;
2058 }
2059
2060 /* Function 43 */
2061 NTSTATUS
2062 NTAPI
2063 SamrTestPrivateFunctionsUser(IN SAMPR_HANDLE UserHandle)
2064 {
2065 UNIMPLEMENTED;
2066 return STATUS_NOT_IMPLEMENTED;
2067 }
2068
2069 /* Function 44 */
2070 NTSTATUS
2071 NTAPI
2072 SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle,
2073 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
2074 {
2075 UNIMPLEMENTED;
2076 return STATUS_NOT_IMPLEMENTED;
2077 }
2078
2079 /* Function 45 */
2080 NTSTATUS
2081 NTAPI
2082 SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle,
2083 IN PRPC_SID MemberSid)
2084 {
2085 UNIMPLEMENTED;
2086 return STATUS_NOT_IMPLEMENTED;
2087 }
2088
2089 /* Function 46 */
2090 NTSTATUS
2091 NTAPI
2092 SamrQueryInformationDomain2(IN SAMPR_HANDLE DomainHandle,
2093 IN DOMAIN_INFORMATION_CLASS DomainInformationClass,
2094 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer)
2095 {
2096 UNIMPLEMENTED;
2097 return STATUS_NOT_IMPLEMENTED;
2098 }
2099
2100 /* Function 47 */
2101 NTSTATUS
2102 NTAPI
2103 SamrQueryInformationUser2(IN SAMPR_HANDLE UserHandle,
2104 IN USER_INFORMATION_CLASS UserInformationClass,
2105 OUT PSAMPR_USER_INFO_BUFFER *Buffer)
2106 {
2107 UNIMPLEMENTED;
2108 return STATUS_NOT_IMPLEMENTED;
2109 }
2110
2111 /* Function 48 */
2112 NTSTATUS
2113 NTAPI
2114 SamrQueryDisplayInformation2(IN SAMPR_HANDLE DomainHandle,
2115 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
2116 IN unsigned long Index,
2117 IN unsigned long EntryCount,
2118 IN unsigned long PreferredMaximumLength,
2119 OUT unsigned long *TotalAvailable,
2120 OUT unsigned long *TotalReturned,
2121 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
2122 {
2123 UNIMPLEMENTED;
2124 return STATUS_NOT_IMPLEMENTED;
2125 }
2126
2127 /* Function 49 */
2128 NTSTATUS
2129 NTAPI
2130 SamrGetDisplayEnumerationIndex2(IN SAMPR_HANDLE DomainHandle,
2131 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
2132 IN PRPC_UNICODE_STRING Prefix,
2133 OUT unsigned long *Index)
2134 {
2135 UNIMPLEMENTED;
2136 return STATUS_NOT_IMPLEMENTED;
2137 }
2138
2139 /* Function 50 */
2140 NTSTATUS
2141 NTAPI
2142 SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle,
2143 IN PRPC_UNICODE_STRING Name,
2144 IN unsigned long AccountType,
2145 IN ACCESS_MASK DesiredAccess,
2146 OUT SAMPR_HANDLE *UserHandle,
2147 OUT unsigned long *GrantedAccess,
2148 OUT unsigned long *RelativeId)
2149 {
2150 UNIMPLEMENTED;
2151 return STATUS_NOT_IMPLEMENTED;
2152 }
2153
2154 /* Function 51 */
2155 NTSTATUS
2156 NTAPI
2157 SamrQueryDisplayInformation3(IN SAMPR_HANDLE DomainHandle,
2158 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass,
2159 IN unsigned long Index,
2160 IN unsigned long EntryCount,
2161 IN unsigned long PreferredMaximumLength,
2162 OUT unsigned long *TotalAvailable,
2163 OUT unsigned long *TotalReturned,
2164 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer)
2165 {
2166 UNIMPLEMENTED;
2167 return STATUS_NOT_IMPLEMENTED;
2168 }
2169
2170 /* Function 52 */
2171 NTSTATUS
2172 NTAPI
2173 SamrAddMultipleMembersToAlias(IN SAMPR_HANDLE AliasHandle,
2174 IN PSAMPR_PSID_ARRAY MembersBuffer)
2175 {
2176 UNIMPLEMENTED;
2177 return STATUS_NOT_IMPLEMENTED;
2178 }
2179
2180 /* Function 53 */
2181 NTSTATUS
2182 NTAPI
2183 SamrRemoveMultipleMembersFromAlias(IN SAMPR_HANDLE AliasHandle,
2184 IN PSAMPR_PSID_ARRAY MembersBuffer)
2185 {
2186 UNIMPLEMENTED;
2187 return STATUS_NOT_IMPLEMENTED;
2188 }
2189
2190 /* Function 54 */
2191 NTSTATUS
2192 NTAPI
2193 SamrOemChangePasswordUser2(IN handle_t BindingHandle,
2194 IN PRPC_STRING ServerName,
2195 IN PRPC_STRING UserName,
2196 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
2197 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewLm)
2198 {
2199 UNIMPLEMENTED;
2200 return STATUS_NOT_IMPLEMENTED;
2201 }
2202
2203 /* Function 55 */
2204 NTSTATUS
2205 NTAPI
2206 SamrUnicodeChangePasswordUser2(IN handle_t BindingHandle,
2207 IN PRPC_UNICODE_STRING ServerName,
2208 IN PRPC_UNICODE_STRING UserName,
2209 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldNt,
2210 IN PENCRYPTED_NT_OWF_PASSWORD OldNtOwfPasswordEncryptedWithNewNt,
2211 IN unsigned char LmPresent,
2212 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm,
2213 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewNt)
2214 {
2215 UNIMPLEMENTED;
2216 return STATUS_NOT_IMPLEMENTED;
2217 }
2218
2219 /* Function 56 */
2220 NTSTATUS
2221 NTAPI
2222 SamrGetDomainPasswordInformation(IN handle_t BindingHandle,
2223 IN PRPC_UNICODE_STRING Unused,
2224 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation)
2225 {
2226 UNIMPLEMENTED;
2227 return STATUS_NOT_IMPLEMENTED;
2228 }
2229
2230 /* Function 57 */
2231 NTSTATUS
2232 NTAPI
2233 SamrConnect2(IN PSAMPR_SERVER_NAME ServerName,
2234 OUT SAMPR_HANDLE *ServerHandle,
2235 IN ACCESS_MASK DesiredAccess)
2236 {
2237 UNIMPLEMENTED;
2238 return STATUS_NOT_IMPLEMENTED;
2239 }
2240
2241 /* Function 58 */
2242 NTSTATUS
2243 NTAPI
2244 SamrSetInformationUser2(IN SAMPR_HANDLE UserHandle,
2245 IN USER_INFORMATION_CLASS UserInformationClass,
2246 IN PSAMPR_USER_INFO_BUFFER Buffer)
2247 {
2248 UNIMPLEMENTED;
2249 return STATUS_NOT_IMPLEMENTED;
2250 }
2251
2252 /* Function 59 */
2253 NTSTATUS
2254 NTAPI
2255 SamrSetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
2256 {
2257 UNIMPLEMENTED;
2258 return STATUS_NOT_IMPLEMENTED;
2259 }
2260
2261 /* Function 60 */
2262 NTSTATUS
2263 NTAPI
2264 SamrGetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */
2265 {
2266 UNIMPLEMENTED;
2267 return STATUS_NOT_IMPLEMENTED;
2268 }
2269
2270 /* Function 61 */
2271 NTSTATUS
2272 NTAPI
2273 SamrConnect3(IN handle_t BindingHandle) /* FIXME */
2274 {
2275 UNIMPLEMENTED;
2276 return STATUS_NOT_IMPLEMENTED;
2277 }
2278
2279 /* Function 62 */
2280 NTSTATUS
2281 NTAPI
2282 SamrConnect4(IN PSAMPR_SERVER_NAME ServerName,
2283 OUT SAMPR_HANDLE *ServerHandle,
2284 IN unsigned long ClientRevision,
2285 IN ACCESS_MASK DesiredAccess)
2286 {
2287 UNIMPLEMENTED;
2288 return STATUS_NOT_IMPLEMENTED;
2289 }
2290
2291 /* Function 63 */
2292 NTSTATUS
2293 NTAPI
2294 SamrUnicodeChangePasswordUser3(IN handle_t BindingHandle) /* FIXME */
2295 {
2296 UNIMPLEMENTED;
2297 return STATUS_NOT_IMPLEMENTED;
2298 }
2299
2300 /* Function 64 */
2301 NTSTATUS
2302 NTAPI
2303 SamrConnect5(IN PSAMPR_SERVER_NAME ServerName,
2304 IN ACCESS_MASK DesiredAccess,
2305 IN unsigned long InVersion,
2306 IN SAMPR_REVISION_INFO *InRevisionInfo,
2307 OUT unsigned long *OutVersion,
2308 OUT SAMPR_REVISION_INFO *OutRevisionInfo,
2309 OUT SAMPR_HANDLE *ServerHandle)
2310 {
2311 UNIMPLEMENTED;
2312 return STATUS_NOT_IMPLEMENTED;
2313 }
2314
2315 /* Function 65 */
2316 NTSTATUS
2317 NTAPI
2318 SamrRidToSid(IN SAMPR_HANDLE ObjectHandle,
2319 IN unsigned long Rid,
2320 OUT PRPC_SID *Sid)
2321 {
2322 UNIMPLEMENTED;
2323 return STATUS_NOT_IMPLEMENTED;
2324 }
2325
2326 /* Function 66 */
2327 NTSTATUS
2328 NTAPI
2329 SamrSetDSRMPassword(IN handle_t BindingHandle,
2330 IN PRPC_UNICODE_STRING Unused,
2331 IN unsigned long UserId,
2332 IN PENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword)
2333 {
2334 UNIMPLEMENTED;
2335 return STATUS_NOT_IMPLEMENTED;
2336 }
2337
2338 /* Function 67 */
2339 NTSTATUS
2340 NTAPI
2341 SamrValidatePassword(IN handle_t Handle,
2342 IN PASSWORD_POLICY_VALIDATION_TYPE ValidationType,
2343 IN PSAM_VALIDATE_INPUT_ARG InputArg,
2344 OUT PSAM_VALIDATE_OUTPUT_ARG *OutputArg)
2345 {
2346 UNIMPLEMENTED;
2347 return STATUS_NOT_IMPLEMENTED;
2348 }
2349
2350 /* EOF */