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 #include "samsrv.h" 11 12 /* GLOBALS *******************************************************************/ 13 14 static SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY}; 15 16 static GENERIC_MAPPING ServerMapping = 17 { 18 SAM_SERVER_READ, 19 SAM_SERVER_WRITE, 20 SAM_SERVER_EXECUTE, 21 SAM_SERVER_ALL_ACCESS 22 }; 23 24 static GENERIC_MAPPING DomainMapping = 25 { 26 DOMAIN_READ, 27 DOMAIN_WRITE, 28 DOMAIN_EXECUTE, 29 DOMAIN_ALL_ACCESS 30 }; 31 32 static GENERIC_MAPPING AliasMapping = 33 { 34 ALIAS_READ, 35 ALIAS_WRITE, 36 ALIAS_EXECUTE, 37 ALIAS_ALL_ACCESS 38 }; 39 40 static GENERIC_MAPPING GroupMapping = 41 { 42 GROUP_READ, 43 GROUP_WRITE, 44 GROUP_EXECUTE, 45 GROUP_ALL_ACCESS 46 }; 47 48 static GENERIC_MAPPING UserMapping = 49 { 50 USER_READ, 51 USER_WRITE, 52 USER_EXECUTE, 53 USER_ALL_ACCESS 54 }; 55 56 PGENERIC_MAPPING pServerMapping = &ServerMapping; 57 58 59 /* FUNCTIONS *****************************************************************/ 60 61 static 62 LARGE_INTEGER 63 SampAddRelativeTimeToTime(IN LARGE_INTEGER AbsoluteTime, 64 IN LARGE_INTEGER RelativeTime) 65 { 66 LARGE_INTEGER NewTime; 67 68 NewTime.QuadPart = AbsoluteTime.QuadPart - RelativeTime.QuadPart; 69 70 if (NewTime.QuadPart < 0) 71 NewTime.QuadPart = 0; 72 73 return NewTime; 74 } 75 76 77 VOID 78 SampStartRpcServer(VOID) 79 { 80 RPC_STATUS Status; 81 82 TRACE("SampStartRpcServer() called\n"); 83 84 Status = RpcServerUseProtseqEpW(L"ncacn_np", 85 RPC_C_PROTSEQ_MAX_REQS_DEFAULT, 86 L"\\pipe\\samr", 87 NULL); 88 if (Status != RPC_S_OK) 89 { 90 WARN("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); 91 return; 92 } 93 94 Status = RpcServerRegisterIf(samr_v1_0_s_ifspec, 95 NULL, 96 NULL); 97 if (Status != RPC_S_OK) 98 { 99 WARN("RpcServerRegisterIf() failed (Status %lx)\n", Status); 100 return; 101 } 102 103 Status = RpcServerListen(1, 20, TRUE); 104 if (Status != RPC_S_OK) 105 { 106 WARN("RpcServerListen() failed (Status %lx)\n", Status); 107 return; 108 } 109 110 TRACE("SampStartRpcServer() done\n"); 111 } 112 113 114 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len) 115 { 116 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 117 } 118 119 120 void __RPC_USER midl_user_free(void __RPC_FAR * ptr) 121 { 122 HeapFree(GetProcessHeap(), 0, ptr); 123 } 124 125 126 void __RPC_USER SAMPR_HANDLE_rundown(SAMPR_HANDLE hHandle) 127 { 128 } 129 130 131 /* Function 0 */ 132 NTSTATUS 133 NTAPI 134 SamrConnect(IN PSAMPR_SERVER_NAME ServerName, 135 OUT SAMPR_HANDLE *ServerHandle, 136 IN ACCESS_MASK DesiredAccess) 137 { 138 SAMPR_REVISION_INFO InRevisionInfo, OutRevisionInfo; 139 ULONG OutVersion; 140 141 TRACE("SamrConnect(%p %p %lx)\n", 142 ServerName, ServerHandle, DesiredAccess); 143 144 InRevisionInfo.V1.Revision = 0; 145 InRevisionInfo.V1.SupportedFeatures = 0; 146 147 return SamrConnect5(ServerName, 148 DesiredAccess, 149 1, 150 &InRevisionInfo, 151 &OutVersion, 152 &OutRevisionInfo, 153 ServerHandle); 154 } 155 156 157 /* Function 1 */ 158 NTSTATUS 159 NTAPI 160 SamrCloseHandle(IN OUT SAMPR_HANDLE *SamHandle) 161 { 162 PSAM_DB_OBJECT DbObject; 163 NTSTATUS Status = STATUS_SUCCESS; 164 165 TRACE("SamrCloseHandle(%p)\n", SamHandle); 166 167 RtlAcquireResourceShared(&SampResource, 168 TRUE); 169 170 Status = SampValidateDbObject(*SamHandle, 171 SamDbIgnoreObject, 172 0, 173 &DbObject); 174 if (Status == STATUS_SUCCESS) 175 { 176 Status = SampCloseDbObject(DbObject); 177 *SamHandle = NULL; 178 } 179 180 RtlReleaseResource(&SampResource); 181 182 TRACE("SamrCloseHandle done (Status 0x%08lx)\n", Status); 183 184 return Status; 185 } 186 187 188 /* Function 2 */ 189 NTSTATUS 190 NTAPI 191 SamrSetSecurityObject(IN SAMPR_HANDLE ObjectHandle, 192 IN SECURITY_INFORMATION SecurityInformation, 193 IN PSAMPR_SR_SECURITY_DESCRIPTOR SecurityDescriptor) 194 { 195 PSAM_DB_OBJECT DbObject = NULL; 196 ACCESS_MASK DesiredAccess = 0; 197 PSECURITY_DESCRIPTOR RelativeSd = NULL; 198 ULONG RelativeSdSize = 0; 199 HANDLE TokenHandle = NULL; 200 PGENERIC_MAPPING Mapping; 201 NTSTATUS Status; 202 203 TRACE("SamrSetSecurityObject(%p %lx %p)\n", 204 ObjectHandle, SecurityInformation, SecurityDescriptor); 205 206 if ((SecurityDescriptor == NULL) || 207 (SecurityDescriptor->SecurityDescriptor == NULL) || 208 !RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)SecurityDescriptor->SecurityDescriptor)) 209 return ERROR_INVALID_PARAMETER; 210 211 if (SecurityInformation == 0 || 212 SecurityInformation & ~(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION 213 | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)) 214 return ERROR_INVALID_PARAMETER; 215 216 if (SecurityInformation & SACL_SECURITY_INFORMATION) 217 DesiredAccess |= ACCESS_SYSTEM_SECURITY; 218 219 if (SecurityInformation & DACL_SECURITY_INFORMATION) 220 DesiredAccess |= WRITE_DAC; 221 222 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) 223 DesiredAccess |= WRITE_OWNER; 224 225 if ((SecurityInformation & OWNER_SECURITY_INFORMATION) && 226 (((PISECURITY_DESCRIPTOR)SecurityDescriptor)->Owner == NULL)) 227 return ERROR_INVALID_PARAMETER; 228 229 if ((SecurityInformation & GROUP_SECURITY_INFORMATION) && 230 (((PISECURITY_DESCRIPTOR)SecurityDescriptor)->Group == NULL)) 231 return ERROR_INVALID_PARAMETER; 232 233 /* Validate the server handle */ 234 Status = SampValidateDbObject(ObjectHandle, 235 SamDbIgnoreObject, 236 DesiredAccess, 237 &DbObject); 238 if (!NT_SUCCESS(Status)) 239 goto done; 240 241 /* Get the mapping for the object type */ 242 switch (DbObject->ObjectType) 243 { 244 case SamDbServerObject: 245 Mapping = &ServerMapping; 246 break; 247 248 case SamDbDomainObject: 249 Mapping = &DomainMapping; 250 break; 251 252 case SamDbAliasObject: 253 Mapping = &AliasMapping; 254 break; 255 256 case SamDbGroupObject: 257 Mapping = &GroupMapping; 258 break; 259 260 case SamDbUserObject: 261 Mapping = &UserMapping; 262 break; 263 264 default: 265 return STATUS_INVALID_HANDLE; 266 } 267 268 /* Get the size of the SD */ 269 Status = SampGetObjectAttribute(DbObject, 270 L"SecDesc", 271 NULL, 272 NULL, 273 &RelativeSdSize); 274 if (!NT_SUCCESS(Status)) 275 return Status; 276 277 /* Allocate a buffer for the SD */ 278 RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(), 0, RelativeSdSize); 279 if (RelativeSd == NULL) 280 return STATUS_INSUFFICIENT_RESOURCES; 281 282 /* Get the SD */ 283 Status = SampGetObjectAttribute(DbObject, 284 L"SecDesc", 285 NULL, 286 RelativeSd, 287 &RelativeSdSize); 288 if (!NT_SUCCESS(Status)) 289 goto done; 290 291 /* Build the new security descriptor */ 292 Status = RtlSetSecurityObject(SecurityInformation, 293 (PSECURITY_DESCRIPTOR)SecurityDescriptor->SecurityDescriptor, 294 &RelativeSd, 295 Mapping, 296 TokenHandle); 297 if (!NT_SUCCESS(Status)) 298 { 299 ERR("RtlSetSecurityObject failed (Status 0x%08lx)\n", Status); 300 goto done; 301 } 302 303 /* Set the modified SD */ 304 Status = SampSetObjectAttribute(DbObject, 305 L"SecDesc", 306 REG_BINARY, 307 RelativeSd, 308 RtlLengthSecurityDescriptor(RelativeSd)); 309 if (!NT_SUCCESS(Status)) 310 { 311 ERR("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status); 312 } 313 314 done: 315 if (TokenHandle != NULL) 316 NtClose(TokenHandle); 317 318 if (RelativeSd != NULL) 319 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); 320 321 return Status; 322 } 323 324 325 /* Function 3 */ 326 NTSTATUS 327 NTAPI 328 SamrQuerySecurityObject(IN SAMPR_HANDLE ObjectHandle, 329 IN SECURITY_INFORMATION SecurityInformation, 330 OUT PSAMPR_SR_SECURITY_DESCRIPTOR *SecurityDescriptor) 331 { 332 PSAM_DB_OBJECT SamObject; 333 PSAMPR_SR_SECURITY_DESCRIPTOR SdData = NULL; 334 PSECURITY_DESCRIPTOR RelativeSd = NULL; 335 PSECURITY_DESCRIPTOR ResultSd = NULL; 336 ACCESS_MASK DesiredAccess = 0; 337 ULONG RelativeSdSize = 0; 338 ULONG ResultSdSize = 0; 339 NTSTATUS Status; 340 341 TRACE("SamrQuerySecurityObject(%p %lx %p)\n", 342 ObjectHandle, SecurityInformation, SecurityDescriptor); 343 344 *SecurityDescriptor = NULL; 345 346 RtlAcquireResourceShared(&SampResource, 347 TRUE); 348 349 if (SecurityInformation & (DACL_SECURITY_INFORMATION | 350 OWNER_SECURITY_INFORMATION | 351 GROUP_SECURITY_INFORMATION)) 352 DesiredAccess |= READ_CONTROL; 353 354 if (SecurityInformation & SACL_SECURITY_INFORMATION) 355 DesiredAccess |= ACCESS_SYSTEM_SECURITY; 356 357 /* Validate the server handle */ 358 Status = SampValidateDbObject(ObjectHandle, 359 SamDbIgnoreObject, 360 DesiredAccess, 361 &SamObject); 362 if (!NT_SUCCESS(Status)) 363 goto done; 364 365 /* Get the size of the SD */ 366 Status = SampGetObjectAttribute(SamObject, 367 L"SecDesc", 368 NULL, 369 NULL, 370 &RelativeSdSize); 371 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) 372 { 373 TRACE("Status 0x%08lx\n", Status); 374 goto done; 375 } 376 377 /* Allocate a buffer for the SD */ 378 RelativeSd = midl_user_allocate(RelativeSdSize); 379 if (RelativeSd == NULL) 380 { 381 Status = STATUS_INSUFFICIENT_RESOURCES; 382 goto done; 383 } 384 385 /* Get the SD */ 386 Status = SampGetObjectAttribute(SamObject, 387 L"SecDesc", 388 NULL, 389 RelativeSd, 390 &RelativeSdSize); 391 if (!NT_SUCCESS(Status)) 392 { 393 TRACE("Status 0x%08lx\n", Status); 394 goto done; 395 } 396 397 /* Invalidate the SD information that was not requested */ 398 if (!(SecurityInformation & OWNER_SECURITY_INFORMATION)) 399 ((PISECURITY_DESCRIPTOR)RelativeSd)->Owner = NULL; 400 401 if (!(SecurityInformation & GROUP_SECURITY_INFORMATION)) 402 ((PISECURITY_DESCRIPTOR)RelativeSd)->Group = NULL; 403 404 if (!(SecurityInformation & DACL_SECURITY_INFORMATION)) 405 ((PISECURITY_DESCRIPTOR)RelativeSd)->Control &= ~SE_DACL_PRESENT; 406 407 if (!(SecurityInformation & SACL_SECURITY_INFORMATION)) 408 ((PISECURITY_DESCRIPTOR)RelativeSd)->Control &= ~SE_SACL_PRESENT; 409 410 /* Calculate the required SD size */ 411 Status = RtlMakeSelfRelativeSD(RelativeSd, 412 NULL, 413 &ResultSdSize); 414 if (Status != STATUS_BUFFER_TOO_SMALL) 415 goto done; 416 417 /* Allocate a buffer for the new SD */ 418 ResultSd = MIDL_user_allocate(ResultSdSize); 419 if (ResultSd == NULL) 420 { 421 Status = STATUS_INSUFFICIENT_RESOURCES; 422 goto done; 423 } 424 425 /* Build the new SD */ 426 Status = RtlMakeSelfRelativeSD(RelativeSd, 427 ResultSd, 428 &ResultSdSize); 429 if (!NT_SUCCESS(Status)) 430 goto done; 431 432 /* Allocate the SD data buffer */ 433 SdData = midl_user_allocate(sizeof(SAMPR_SR_SECURITY_DESCRIPTOR)); 434 if (SdData == NULL) 435 { 436 Status = STATUS_INSUFFICIENT_RESOURCES; 437 goto done; 438 } 439 440 /* Fill the SD data buffer and return it to the caller */ 441 SdData->Length = RelativeSdSize; 442 SdData->SecurityDescriptor = (PBYTE)ResultSd; 443 444 *SecurityDescriptor = SdData; 445 446 done: 447 RtlReleaseResource(&SampResource); 448 449 if (!NT_SUCCESS(Status)) 450 { 451 if (ResultSd != NULL) 452 MIDL_user_free(ResultSd); 453 } 454 455 if (RelativeSd != NULL) 456 MIDL_user_free(RelativeSd); 457 458 return Status; 459 } 460 461 462 /* Function 4 */ 463 NTSTATUS 464 NTAPI 465 SamrShutdownSamServer(IN SAMPR_HANDLE ServerHandle) 466 { 467 PSAM_DB_OBJECT ServerObject; 468 NTSTATUS Status; 469 470 TRACE("SamrShutdownSamServer(%p)\n", 471 ServerHandle); 472 473 RtlAcquireResourceShared(&SampResource, 474 TRUE); 475 476 /* Validate the server handle */ 477 Status = SampValidateDbObject(ServerHandle, 478 SamDbServerObject, 479 SAM_SERVER_SHUTDOWN, 480 &ServerObject); 481 482 RtlReleaseResource(&SampResource); 483 484 if (!NT_SUCCESS(Status)) 485 return Status; 486 487 /* Shut the server down */ 488 RpcMgmtStopServerListening(0); 489 490 return STATUS_SUCCESS; 491 } 492 493 494 /* Function 5 */ 495 NTSTATUS 496 NTAPI 497 SamrLookupDomainInSamServer(IN SAMPR_HANDLE ServerHandle, 498 IN PRPC_UNICODE_STRING Name, 499 OUT PRPC_SID *DomainId) 500 { 501 PSAM_DB_OBJECT ServerObject; 502 HANDLE DomainsKeyHandle = NULL; 503 HANDLE DomainKeyHandle = NULL; 504 WCHAR DomainKeyName[64]; 505 ULONG Index; 506 WCHAR DomainNameString[MAX_COMPUTERNAME_LENGTH + 1]; 507 UNICODE_STRING DomainName; 508 ULONG Length; 509 BOOL Found = FALSE; 510 NTSTATUS Status; 511 512 TRACE("SamrLookupDomainInSamServer(%p %p %p)\n", 513 ServerHandle, Name, DomainId); 514 515 RtlAcquireResourceShared(&SampResource, 516 TRUE); 517 518 /* Validate the server handle */ 519 Status = SampValidateDbObject(ServerHandle, 520 SamDbServerObject, 521 SAM_SERVER_LOOKUP_DOMAIN, 522 &ServerObject); 523 if (!NT_SUCCESS(Status)) 524 goto done; 525 526 *DomainId = NULL; 527 528 Status = SampRegOpenKey(ServerObject->KeyHandle, 529 L"Domains", 530 KEY_READ, 531 &DomainsKeyHandle); 532 if (!NT_SUCCESS(Status)) 533 goto done; 534 535 Index = 0; 536 while (Found == FALSE) 537 { 538 Status = SampRegEnumerateSubKey(DomainsKeyHandle, 539 Index, 540 64, 541 DomainKeyName); 542 if (!NT_SUCCESS(Status)) 543 { 544 if (Status == STATUS_NO_MORE_ENTRIES) 545 Status = STATUS_NO_SUCH_DOMAIN; 546 break; 547 } 548 549 TRACE("Domain key name: %S\n", DomainKeyName); 550 551 Status = SampRegOpenKey(DomainsKeyHandle, 552 DomainKeyName, 553 KEY_READ, 554 &DomainKeyHandle); 555 if (NT_SUCCESS(Status)) 556 { 557 Length = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR); 558 Status = SampRegQueryValue(DomainKeyHandle, 559 L"Name", 560 NULL, 561 (PVOID)&DomainNameString, 562 &Length); 563 if (NT_SUCCESS(Status)) 564 { 565 TRACE("Domain name: %S\n", DomainNameString); 566 567 RtlInitUnicodeString(&DomainName, 568 DomainNameString); 569 if (RtlEqualUnicodeString(&DomainName, (PUNICODE_STRING)Name, TRUE)) 570 { 571 TRACE("Found it!\n"); 572 Found = TRUE; 573 574 Status = SampRegQueryValue(DomainKeyHandle, 575 L"SID", 576 NULL, 577 NULL, 578 &Length); 579 if (NT_SUCCESS(Status)) 580 { 581 *DomainId = midl_user_allocate(Length); 582 583 SampRegQueryValue(DomainKeyHandle, 584 L"SID", 585 NULL, 586 (PVOID)*DomainId, 587 &Length); 588 589 Status = STATUS_SUCCESS; 590 break; 591 } 592 } 593 } 594 595 SampRegCloseKey(&DomainKeyHandle); 596 } 597 598 Index++; 599 } 600 601 done: 602 SampRegCloseKey(&DomainKeyHandle); 603 SampRegCloseKey(&DomainsKeyHandle); 604 605 RtlReleaseResource(&SampResource); 606 607 return Status; 608 } 609 610 611 /* Function 6 */ 612 NTSTATUS 613 NTAPI 614 SamrEnumerateDomainsInSamServer(IN SAMPR_HANDLE ServerHandle, 615 IN OUT unsigned long *EnumerationContext, 616 OUT PSAMPR_ENUMERATION_BUFFER *Buffer, 617 IN ULONG PreferedMaximumLength, 618 OUT PULONG CountReturned) 619 { 620 PSAM_DB_OBJECT ServerObject; 621 WCHAR DomainKeyName[64]; 622 HANDLE DomainsKeyHandle = NULL; 623 HANDLE DomainKeyHandle = NULL; 624 ULONG EnumIndex; 625 ULONG EnumCount; 626 ULONG RequiredLength; 627 ULONG DataLength; 628 ULONG i; 629 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL; 630 NTSTATUS Status; 631 632 TRACE("SamrEnumerateDomainsInSamServer(%p %p %p %lu %p)\n", 633 ServerHandle, EnumerationContext, Buffer, PreferedMaximumLength, 634 CountReturned); 635 636 RtlAcquireResourceShared(&SampResource, 637 TRUE); 638 639 /* Validate the server handle */ 640 Status = SampValidateDbObject(ServerHandle, 641 SamDbServerObject, 642 SAM_SERVER_ENUMERATE_DOMAINS, 643 &ServerObject); 644 if (!NT_SUCCESS(Status)) 645 goto done; 646 647 Status = SampRegOpenKey(ServerObject->KeyHandle, 648 L"Domains", 649 KEY_READ, 650 &DomainsKeyHandle); 651 if (!NT_SUCCESS(Status)) 652 goto done; 653 654 EnumIndex = *EnumerationContext; 655 EnumCount = 0; 656 RequiredLength = 0; 657 658 while (TRUE) 659 { 660 Status = SampRegEnumerateSubKey(DomainsKeyHandle, 661 EnumIndex, 662 64 * sizeof(WCHAR), 663 DomainKeyName); 664 if (!NT_SUCCESS(Status)) 665 break; 666 667 TRACE("EnumIndex: %lu\n", EnumIndex); 668 TRACE("Domain key name: %S\n", DomainKeyName); 669 670 Status = SampRegOpenKey(DomainsKeyHandle, 671 DomainKeyName, 672 KEY_READ, 673 &DomainKeyHandle); 674 TRACE("SampRegOpenKey returned %08lX\n", Status); 675 if (NT_SUCCESS(Status)) 676 { 677 DataLength = 0; 678 Status = SampRegQueryValue(DomainKeyHandle, 679 L"Name", 680 NULL, 681 NULL, 682 &DataLength); 683 TRACE("SampRegQueryValue returned %08lX\n", Status); 684 if (NT_SUCCESS(Status)) 685 { 686 TRACE("Data length: %lu\n", DataLength); 687 688 if ((RequiredLength + DataLength + sizeof(UNICODE_STRING)) > PreferedMaximumLength) 689 break; 690 691 RequiredLength += (DataLength + sizeof(UNICODE_STRING)); 692 EnumCount++; 693 } 694 695 SampRegCloseKey(&DomainKeyHandle); 696 } 697 698 EnumIndex++; 699 } 700 701 TRACE("EnumCount: %lu\n", EnumCount); 702 TRACE("RequiredLength: %lu\n", RequiredLength); 703 704 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER)); 705 if (EnumBuffer == NULL) 706 { 707 Status = STATUS_INSUFFICIENT_RESOURCES; 708 goto done; 709 } 710 711 EnumBuffer->EntriesRead = EnumCount; 712 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION)); 713 if (EnumBuffer->Buffer == NULL) 714 { 715 Status = STATUS_INSUFFICIENT_RESOURCES; 716 goto done; 717 } 718 719 EnumIndex = *EnumerationContext; 720 for (i = 0; i < EnumCount; i++, EnumIndex++) 721 { 722 Status = SampRegEnumerateSubKey(DomainsKeyHandle, 723 EnumIndex, 724 64 * sizeof(WCHAR), 725 DomainKeyName); 726 if (!NT_SUCCESS(Status)) 727 break; 728 729 TRACE("EnumIndex: %lu\n", EnumIndex); 730 TRACE("Domain key name: %S\n", DomainKeyName); 731 732 Status = SampRegOpenKey(DomainsKeyHandle, 733 DomainKeyName, 734 KEY_READ, 735 &DomainKeyHandle); 736 TRACE("SampRegOpenKey returned %08lX\n", Status); 737 if (NT_SUCCESS(Status)) 738 { 739 DataLength = 0; 740 Status = SampRegQueryValue(DomainKeyHandle, 741 L"Name", 742 NULL, 743 NULL, 744 &DataLength); 745 TRACE("SampRegQueryValue returned %08lX\n", Status); 746 if (NT_SUCCESS(Status)) 747 { 748 EnumBuffer->Buffer[i].RelativeId = 0; 749 EnumBuffer->Buffer[i].Name.Length = (USHORT)DataLength - sizeof(WCHAR); 750 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)DataLength; 751 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(DataLength); 752 if (EnumBuffer->Buffer[i].Name.Buffer == NULL) 753 { 754 SampRegCloseKey(&DomainKeyHandle); 755 Status = STATUS_INSUFFICIENT_RESOURCES; 756 goto done; 757 } 758 759 Status = SampRegQueryValue(DomainKeyHandle, 760 L"Name", 761 NULL, 762 EnumBuffer->Buffer[i].Name.Buffer, 763 &DataLength); 764 TRACE("SampRegQueryValue returned %08lX\n", Status); 765 if (NT_SUCCESS(Status)) 766 { 767 TRACE("Domain name: %S\n", EnumBuffer->Buffer[i].Name.Buffer); 768 } 769 } 770 771 SampRegCloseKey(&DomainKeyHandle); 772 773 if (!NT_SUCCESS(Status)) 774 goto done; 775 } 776 } 777 778 if (NT_SUCCESS(Status)) 779 { 780 *EnumerationContext += EnumCount; 781 *Buffer = EnumBuffer; 782 *CountReturned = EnumCount; 783 } 784 785 done: 786 SampRegCloseKey(&DomainKeyHandle); 787 SampRegCloseKey(&DomainsKeyHandle); 788 789 if (!NT_SUCCESS(Status)) 790 { 791 *EnumerationContext = 0; 792 *Buffer = NULL; 793 *CountReturned = 0; 794 795 if (EnumBuffer != NULL) 796 { 797 if (EnumBuffer->Buffer != NULL) 798 { 799 if (EnumBuffer->EntriesRead != 0) 800 { 801 for (i = 0; i < EnumBuffer->EntriesRead; i++) 802 { 803 if (EnumBuffer->Buffer[i].Name.Buffer != NULL) 804 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer); 805 } 806 } 807 808 midl_user_free(EnumBuffer->Buffer); 809 } 810 811 midl_user_free(EnumBuffer); 812 } 813 } 814 815 RtlReleaseResource(&SampResource); 816 817 return Status; 818 } 819 820 821 /* Function 7 */ 822 NTSTATUS 823 NTAPI 824 SamrOpenDomain(IN SAMPR_HANDLE ServerHandle, 825 IN ACCESS_MASK DesiredAccess, 826 IN PRPC_SID DomainId, 827 OUT SAMPR_HANDLE *DomainHandle) 828 { 829 PSAM_DB_OBJECT ServerObject; 830 PSAM_DB_OBJECT DomainObject; 831 NTSTATUS Status; 832 833 TRACE("SamrOpenDomain(%p %lx %p %p)\n", 834 ServerHandle, DesiredAccess, DomainId, DomainHandle); 835 836 /* Map generic access rights */ 837 RtlMapGenericMask(&DesiredAccess, 838 &DomainMapping); 839 840 RtlAcquireResourceShared(&SampResource, 841 TRUE); 842 843 /* Validate the server handle */ 844 Status = SampValidateDbObject(ServerHandle, 845 SamDbServerObject, 846 SAM_SERVER_LOOKUP_DOMAIN, 847 &ServerObject); 848 if (!NT_SUCCESS(Status)) 849 return Status; 850 851 /* Validate the Domain SID */ 852 if ((DomainId->Revision != SID_REVISION) || 853 (DomainId->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) || 854 (memcmp(&DomainId->IdentifierAuthority, &NtSidAuthority, sizeof(SID_IDENTIFIER_AUTHORITY)) != 0)) 855 return STATUS_INVALID_PARAMETER; 856 857 /* Open the domain object */ 858 if ((DomainId->SubAuthorityCount == 1) && 859 (DomainId->SubAuthority[0] == SECURITY_BUILTIN_DOMAIN_RID)) 860 { 861 /* Builtin domain object */ 862 TRACE("Opening the builtin domain object.\n"); 863 864 Status = SampOpenDbObject(ServerObject, 865 L"Domains", 866 L"Builtin", 867 0, 868 SamDbDomainObject, 869 DesiredAccess, 870 &DomainObject); 871 } 872 else if ((DomainId->SubAuthorityCount == 4) && 873 (DomainId->SubAuthority[0] == SECURITY_NT_NON_UNIQUE)) 874 { 875 /* Account domain object */ 876 TRACE("Opening the account domain object.\n"); 877 878 /* FIXME: Check the account domain sub authorities!!! */ 879 880 Status = SampOpenDbObject(ServerObject, 881 L"Domains", 882 L"Account", 883 0, 884 SamDbDomainObject, 885 DesiredAccess, 886 &DomainObject); 887 } 888 else 889 { 890 /* No valid domain SID */ 891 Status = STATUS_INVALID_PARAMETER; 892 } 893 894 if (NT_SUCCESS(Status)) 895 *DomainHandle = (SAMPR_HANDLE)DomainObject; 896 897 RtlReleaseResource(&SampResource); 898 899 TRACE("SamrOpenDomain done (Status 0x%08lx)\n", Status); 900 901 return Status; 902 } 903 904 905 static NTSTATUS 906 SampQueryDomainPassword(PSAM_DB_OBJECT DomainObject, 907 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 908 { 909 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 910 SAM_DOMAIN_FIXED_DATA FixedData; 911 ULONG Length = 0; 912 NTSTATUS Status; 913 914 *Buffer = NULL; 915 916 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 917 if (InfoBuffer == NULL) 918 return STATUS_INSUFFICIENT_RESOURCES; 919 920 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 921 Status = SampGetObjectAttribute(DomainObject, 922 L"F", 923 NULL, 924 (PVOID)&FixedData, 925 &Length); 926 if (!NT_SUCCESS(Status)) 927 goto done; 928 929 InfoBuffer->Password.MinPasswordLength = FixedData.MinPasswordLength; 930 InfoBuffer->Password.PasswordHistoryLength = FixedData.PasswordHistoryLength; 931 InfoBuffer->Password.PasswordProperties = FixedData.PasswordProperties; 932 InfoBuffer->Password.MaxPasswordAge.LowPart = FixedData.MaxPasswordAge.LowPart; 933 InfoBuffer->Password.MaxPasswordAge.HighPart = FixedData.MaxPasswordAge.HighPart; 934 InfoBuffer->Password.MinPasswordAge.LowPart = FixedData.MinPasswordAge.LowPart; 935 InfoBuffer->Password.MinPasswordAge.HighPart = FixedData.MinPasswordAge.HighPart; 936 937 *Buffer = InfoBuffer; 938 939 done: 940 if (!NT_SUCCESS(Status)) 941 { 942 if (InfoBuffer != NULL) 943 { 944 midl_user_free(InfoBuffer); 945 } 946 } 947 948 return Status; 949 } 950 951 952 static NTSTATUS 953 SampGetNumberOfAccounts(PSAM_DB_OBJECT DomainObject, 954 LPCWSTR AccountType, 955 PULONG Count) 956 { 957 HANDLE AccountKeyHandle = NULL; 958 HANDLE NamesKeyHandle = NULL; 959 NTSTATUS Status; 960 961 *Count = 0; 962 963 Status = SampRegOpenKey(DomainObject->KeyHandle, 964 AccountType, 965 KEY_READ, 966 &AccountKeyHandle); 967 if (!NT_SUCCESS(Status)) 968 return Status; 969 970 Status = SampRegOpenKey(AccountKeyHandle, 971 L"Names", 972 KEY_READ, 973 &NamesKeyHandle); 974 if (!NT_SUCCESS(Status)) 975 goto done; 976 977 Status = SampRegQueryKeyInfo(NamesKeyHandle, 978 NULL, 979 Count); 980 981 done: 982 SampRegCloseKey(&NamesKeyHandle); 983 SampRegCloseKey(&AccountKeyHandle); 984 985 return Status; 986 } 987 988 989 static NTSTATUS 990 SampQueryDomainGeneral(PSAM_DB_OBJECT DomainObject, 991 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 992 { 993 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 994 SAM_DOMAIN_FIXED_DATA FixedData; 995 ULONG Length = 0; 996 NTSTATUS Status; 997 998 *Buffer = NULL; 999 1000 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1001 if (InfoBuffer == NULL) 1002 return STATUS_INSUFFICIENT_RESOURCES; 1003 1004 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1005 Status = SampGetObjectAttribute(DomainObject, 1006 L"F", 1007 NULL, 1008 (PVOID)&FixedData, 1009 &Length); 1010 if (!NT_SUCCESS(Status)) 1011 goto done; 1012 1013 InfoBuffer->General.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart; 1014 InfoBuffer->General.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart; 1015 InfoBuffer->General.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart; 1016 InfoBuffer->General.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart; 1017 InfoBuffer->General.DomainServerState = FixedData.DomainServerState; 1018 InfoBuffer->General.DomainServerRole = FixedData.DomainServerRole; 1019 InfoBuffer->General.UasCompatibilityRequired = FixedData.UasCompatibilityRequired; 1020 1021 /* Get the OemInformation string */ 1022 Status = SampGetObjectAttributeString(DomainObject, 1023 L"OemInformation", 1024 &InfoBuffer->General.OemInformation); 1025 if (!NT_SUCCESS(Status)) 1026 { 1027 TRACE("Status 0x%08lx\n", Status); 1028 goto done; 1029 } 1030 1031 /* Get the Name string */ 1032 Status = SampGetObjectAttributeString(DomainObject, 1033 L"Name", 1034 &InfoBuffer->General.DomainName); 1035 if (!NT_SUCCESS(Status)) 1036 { 1037 TRACE("Status 0x%08lx\n", Status); 1038 goto done; 1039 } 1040 1041 /* Get the ReplicaSourceNodeName string */ 1042 Status = SampGetObjectAttributeString(DomainObject, 1043 L"ReplicaSourceNodeName", 1044 &InfoBuffer->General.ReplicaSourceNodeName); 1045 if (!NT_SUCCESS(Status)) 1046 { 1047 TRACE("Status 0x%08lx\n", Status); 1048 goto done; 1049 } 1050 1051 /* Get the number of Users in the Domain */ 1052 Status = SampGetNumberOfAccounts(DomainObject, 1053 L"Users", 1054 &InfoBuffer->General.UserCount); 1055 if (!NT_SUCCESS(Status)) 1056 { 1057 TRACE("Status 0x%08lx\n", Status); 1058 goto done; 1059 } 1060 1061 /* Get the number of Groups in the Domain */ 1062 Status = SampGetNumberOfAccounts(DomainObject, 1063 L"Groups", 1064 &InfoBuffer->General.GroupCount); 1065 if (!NT_SUCCESS(Status)) 1066 { 1067 TRACE("Status 0x%08lx\n", Status); 1068 goto done; 1069 } 1070 1071 /* Get the number of Aliases in the Domain */ 1072 Status = SampGetNumberOfAccounts(DomainObject, 1073 L"Aliases", 1074 &InfoBuffer->General.AliasCount); 1075 if (!NT_SUCCESS(Status)) 1076 { 1077 TRACE("Status 0x%08lx\n", Status); 1078 goto done; 1079 } 1080 1081 *Buffer = InfoBuffer; 1082 1083 done: 1084 if (!NT_SUCCESS(Status)) 1085 { 1086 if (InfoBuffer != NULL) 1087 { 1088 if (InfoBuffer->General.OemInformation.Buffer != NULL) 1089 midl_user_free(InfoBuffer->General.OemInformation.Buffer); 1090 1091 if (InfoBuffer->General.DomainName.Buffer != NULL) 1092 midl_user_free(InfoBuffer->General.DomainName.Buffer); 1093 1094 if (InfoBuffer->General.ReplicaSourceNodeName.Buffer != NULL) 1095 midl_user_free(InfoBuffer->General.ReplicaSourceNodeName.Buffer); 1096 1097 midl_user_free(InfoBuffer); 1098 } 1099 } 1100 1101 return Status; 1102 } 1103 1104 1105 static NTSTATUS 1106 SampQueryDomainLogoff(PSAM_DB_OBJECT DomainObject, 1107 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1108 { 1109 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 1110 SAM_DOMAIN_FIXED_DATA FixedData; 1111 ULONG Length = 0; 1112 NTSTATUS Status; 1113 1114 *Buffer = NULL; 1115 1116 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1117 if (InfoBuffer == NULL) 1118 return STATUS_INSUFFICIENT_RESOURCES; 1119 1120 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1121 Status = SampGetObjectAttribute(DomainObject, 1122 L"F", 1123 NULL, 1124 (PVOID)&FixedData, 1125 &Length); 1126 if (!NT_SUCCESS(Status)) 1127 goto done; 1128 1129 InfoBuffer->Logoff.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart; 1130 InfoBuffer->Logoff.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart; 1131 1132 *Buffer = InfoBuffer; 1133 1134 done: 1135 if (!NT_SUCCESS(Status)) 1136 { 1137 if (InfoBuffer != NULL) 1138 { 1139 midl_user_free(InfoBuffer); 1140 } 1141 } 1142 1143 return Status; 1144 } 1145 1146 1147 static NTSTATUS 1148 SampQueryDomainOem(PSAM_DB_OBJECT DomainObject, 1149 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1150 { 1151 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 1152 NTSTATUS Status; 1153 1154 *Buffer = NULL; 1155 1156 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1157 if (InfoBuffer == NULL) 1158 return STATUS_INSUFFICIENT_RESOURCES; 1159 1160 /* Get the OemInformation string */ 1161 Status = SampGetObjectAttributeString(DomainObject, 1162 L"OemInformation", 1163 &InfoBuffer->Oem.OemInformation); 1164 if (!NT_SUCCESS(Status)) 1165 { 1166 TRACE("Status 0x%08lx\n", Status); 1167 goto done; 1168 } 1169 1170 *Buffer = InfoBuffer; 1171 1172 done: 1173 if (!NT_SUCCESS(Status)) 1174 { 1175 if (InfoBuffer != NULL) 1176 { 1177 if (InfoBuffer->Oem.OemInformation.Buffer != NULL) 1178 midl_user_free(InfoBuffer->Oem.OemInformation.Buffer); 1179 1180 midl_user_free(InfoBuffer); 1181 } 1182 } 1183 1184 return Status; 1185 } 1186 1187 1188 static NTSTATUS 1189 SampQueryDomainName(PSAM_DB_OBJECT DomainObject, 1190 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1191 { 1192 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 1193 NTSTATUS Status; 1194 1195 *Buffer = NULL; 1196 1197 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1198 if (InfoBuffer == NULL) 1199 return STATUS_INSUFFICIENT_RESOURCES; 1200 1201 /* Get the Name string */ 1202 Status = SampGetObjectAttributeString(DomainObject, 1203 L"Name", 1204 &InfoBuffer->Name.DomainName); 1205 if (!NT_SUCCESS(Status)) 1206 { 1207 TRACE("Status 0x%08lx\n", Status); 1208 goto done; 1209 } 1210 1211 *Buffer = InfoBuffer; 1212 1213 done: 1214 if (!NT_SUCCESS(Status)) 1215 { 1216 if (InfoBuffer != NULL) 1217 { 1218 if (InfoBuffer->Name.DomainName.Buffer != NULL) 1219 midl_user_free(InfoBuffer->Name.DomainName.Buffer); 1220 1221 midl_user_free(InfoBuffer); 1222 } 1223 } 1224 1225 return Status; 1226 } 1227 1228 1229 static NTSTATUS 1230 SampQueryDomainReplication(PSAM_DB_OBJECT DomainObject, 1231 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1232 { 1233 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 1234 NTSTATUS Status; 1235 1236 *Buffer = NULL; 1237 1238 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1239 if (InfoBuffer == NULL) 1240 return STATUS_INSUFFICIENT_RESOURCES; 1241 1242 /* Get the ReplicaSourceNodeName string */ 1243 Status = SampGetObjectAttributeString(DomainObject, 1244 L"ReplicaSourceNodeName", 1245 &InfoBuffer->Replication.ReplicaSourceNodeName); 1246 if (!NT_SUCCESS(Status)) 1247 { 1248 TRACE("Status 0x%08lx\n", Status); 1249 goto done; 1250 } 1251 1252 *Buffer = InfoBuffer; 1253 1254 done: 1255 if (!NT_SUCCESS(Status)) 1256 { 1257 if (InfoBuffer != NULL) 1258 { 1259 if (InfoBuffer->Replication.ReplicaSourceNodeName.Buffer != NULL) 1260 midl_user_free(InfoBuffer->Replication.ReplicaSourceNodeName.Buffer); 1261 1262 midl_user_free(InfoBuffer); 1263 } 1264 } 1265 1266 return Status; 1267 } 1268 1269 1270 static NTSTATUS 1271 SampQueryDomainServerRole(PSAM_DB_OBJECT DomainObject, 1272 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1273 { 1274 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 1275 SAM_DOMAIN_FIXED_DATA FixedData; 1276 ULONG Length = 0; 1277 NTSTATUS Status; 1278 1279 *Buffer = NULL; 1280 1281 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1282 if (InfoBuffer == NULL) 1283 return STATUS_INSUFFICIENT_RESOURCES; 1284 1285 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1286 Status = SampGetObjectAttribute(DomainObject, 1287 L"F", 1288 NULL, 1289 (PVOID)&FixedData, 1290 &Length); 1291 if (!NT_SUCCESS(Status)) 1292 goto done; 1293 1294 InfoBuffer->Role.DomainServerRole = FixedData.DomainServerRole; 1295 1296 *Buffer = InfoBuffer; 1297 1298 done: 1299 if (!NT_SUCCESS(Status)) 1300 { 1301 if (InfoBuffer != NULL) 1302 { 1303 midl_user_free(InfoBuffer); 1304 } 1305 } 1306 1307 return Status; 1308 } 1309 1310 1311 static NTSTATUS 1312 SampQueryDomainModified(PSAM_DB_OBJECT DomainObject, 1313 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1314 { 1315 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 1316 SAM_DOMAIN_FIXED_DATA FixedData; 1317 ULONG Length = 0; 1318 NTSTATUS Status; 1319 1320 *Buffer = NULL; 1321 1322 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1323 if (InfoBuffer == NULL) 1324 return STATUS_INSUFFICIENT_RESOURCES; 1325 1326 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1327 Status = SampGetObjectAttribute(DomainObject, 1328 L"F", 1329 NULL, 1330 (PVOID)&FixedData, 1331 &Length); 1332 if (!NT_SUCCESS(Status)) 1333 goto done; 1334 1335 InfoBuffer->Modified.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart; 1336 InfoBuffer->Modified.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart; 1337 InfoBuffer->Modified.CreationTime.LowPart = FixedData.CreationTime.LowPart; 1338 InfoBuffer->Modified.CreationTime.HighPart = FixedData.CreationTime.HighPart; 1339 1340 *Buffer = InfoBuffer; 1341 1342 done: 1343 if (!NT_SUCCESS(Status)) 1344 { 1345 if (InfoBuffer != NULL) 1346 { 1347 midl_user_free(InfoBuffer); 1348 } 1349 } 1350 1351 return Status; 1352 } 1353 1354 1355 static NTSTATUS 1356 SampQueryDomainState(PSAM_DB_OBJECT DomainObject, 1357 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1358 { 1359 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 1360 SAM_DOMAIN_FIXED_DATA FixedData; 1361 ULONG Length = 0; 1362 NTSTATUS Status; 1363 1364 *Buffer = NULL; 1365 1366 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1367 if (InfoBuffer == NULL) 1368 return STATUS_INSUFFICIENT_RESOURCES; 1369 1370 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1371 Status = SampGetObjectAttribute(DomainObject, 1372 L"F", 1373 NULL, 1374 (PVOID)&FixedData, 1375 &Length); 1376 if (!NT_SUCCESS(Status)) 1377 goto done; 1378 1379 InfoBuffer->State.DomainServerState = FixedData.DomainServerState; 1380 1381 *Buffer = InfoBuffer; 1382 1383 done: 1384 if (!NT_SUCCESS(Status)) 1385 { 1386 if (InfoBuffer != NULL) 1387 { 1388 midl_user_free(InfoBuffer); 1389 } 1390 } 1391 1392 return Status; 1393 } 1394 1395 1396 static NTSTATUS 1397 SampQueryDomainGeneral2(PSAM_DB_OBJECT DomainObject, 1398 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1399 { 1400 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 1401 SAM_DOMAIN_FIXED_DATA FixedData; 1402 ULONG Length = 0; 1403 NTSTATUS Status; 1404 1405 *Buffer = NULL; 1406 1407 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1408 if (InfoBuffer == NULL) 1409 return STATUS_INSUFFICIENT_RESOURCES; 1410 1411 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1412 Status = SampGetObjectAttribute(DomainObject, 1413 L"F", 1414 NULL, 1415 (PVOID)&FixedData, 1416 &Length); 1417 if (!NT_SUCCESS(Status)) 1418 goto done; 1419 1420 InfoBuffer->General2.I1.ForceLogoff.LowPart = FixedData.ForceLogoff.LowPart; 1421 InfoBuffer->General2.I1.ForceLogoff.HighPart = FixedData.ForceLogoff.HighPart; 1422 InfoBuffer->General2.I1.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart; 1423 InfoBuffer->General2.I1.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart; 1424 InfoBuffer->General2.I1.DomainServerState = FixedData.DomainServerState; 1425 InfoBuffer->General2.I1.DomainServerRole = FixedData.DomainServerRole; 1426 InfoBuffer->General2.I1.UasCompatibilityRequired = FixedData.UasCompatibilityRequired; 1427 1428 InfoBuffer->General2.LockoutDuration = FixedData.LockoutDuration; 1429 InfoBuffer->General2.LockoutObservationWindow = FixedData.LockoutObservationWindow; 1430 InfoBuffer->General2.LockoutThreshold = FixedData.LockoutThreshold; 1431 1432 /* Get the OemInformation string */ 1433 Status = SampGetObjectAttributeString(DomainObject, 1434 L"OemInformation", 1435 &InfoBuffer->General2.I1.OemInformation); 1436 if (!NT_SUCCESS(Status)) 1437 { 1438 TRACE("Status 0x%08lx\n", Status); 1439 goto done; 1440 } 1441 1442 /* Get the Name string */ 1443 Status = SampGetObjectAttributeString(DomainObject, 1444 L"Name", 1445 &InfoBuffer->General2.I1.DomainName); 1446 if (!NT_SUCCESS(Status)) 1447 { 1448 TRACE("Status 0x%08lx\n", Status); 1449 goto done; 1450 } 1451 1452 /* Get the ReplicaSourceNodeName string */ 1453 Status = SampGetObjectAttributeString(DomainObject, 1454 L"ReplicaSourceNodeName", 1455 &InfoBuffer->General2.I1.ReplicaSourceNodeName); 1456 if (!NT_SUCCESS(Status)) 1457 { 1458 TRACE("Status 0x%08lx\n", Status); 1459 goto done; 1460 } 1461 1462 /* Get the number of Users in the Domain */ 1463 Status = SampGetNumberOfAccounts(DomainObject, 1464 L"Users", 1465 &InfoBuffer->General2.I1.UserCount); 1466 if (!NT_SUCCESS(Status)) 1467 { 1468 TRACE("Status 0x%08lx\n", Status); 1469 goto done; 1470 } 1471 1472 /* Get the number of Groups in the Domain */ 1473 Status = SampGetNumberOfAccounts(DomainObject, 1474 L"Groups", 1475 &InfoBuffer->General2.I1.GroupCount); 1476 if (!NT_SUCCESS(Status)) 1477 { 1478 TRACE("Status 0x%08lx\n", Status); 1479 goto done; 1480 } 1481 1482 /* Get the number of Aliases in the Domain */ 1483 Status = SampGetNumberOfAccounts(DomainObject, 1484 L"Aliases", 1485 &InfoBuffer->General2.I1.AliasCount); 1486 if (!NT_SUCCESS(Status)) 1487 { 1488 TRACE("Status 0x%08lx\n", Status); 1489 goto done; 1490 } 1491 1492 *Buffer = InfoBuffer; 1493 1494 done: 1495 if (!NT_SUCCESS(Status)) 1496 { 1497 if (InfoBuffer != NULL) 1498 { 1499 if (InfoBuffer->General2.I1.OemInformation.Buffer != NULL) 1500 midl_user_free(InfoBuffer->General2.I1.OemInformation.Buffer); 1501 1502 if (InfoBuffer->General2.I1.DomainName.Buffer != NULL) 1503 midl_user_free(InfoBuffer->General2.I1.DomainName.Buffer); 1504 1505 if (InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer != NULL) 1506 midl_user_free(InfoBuffer->General2.I1.ReplicaSourceNodeName.Buffer); 1507 1508 midl_user_free(InfoBuffer); 1509 } 1510 } 1511 1512 return Status; 1513 } 1514 1515 1516 static NTSTATUS 1517 SampQueryDomainLockout(PSAM_DB_OBJECT DomainObject, 1518 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1519 { 1520 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 1521 SAM_DOMAIN_FIXED_DATA FixedData; 1522 ULONG Length = 0; 1523 NTSTATUS Status; 1524 1525 *Buffer = NULL; 1526 1527 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1528 if (InfoBuffer == NULL) 1529 return STATUS_INSUFFICIENT_RESOURCES; 1530 1531 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1532 Status = SampGetObjectAttribute(DomainObject, 1533 L"F", 1534 NULL, 1535 (PVOID)&FixedData, 1536 &Length); 1537 if (!NT_SUCCESS(Status)) 1538 goto done; 1539 1540 InfoBuffer->Lockout.LockoutDuration = FixedData.LockoutDuration; 1541 InfoBuffer->Lockout.LockoutObservationWindow = FixedData.LockoutObservationWindow; 1542 InfoBuffer->Lockout.LockoutThreshold = FixedData.LockoutThreshold; 1543 1544 *Buffer = InfoBuffer; 1545 1546 done: 1547 if (!NT_SUCCESS(Status)) 1548 { 1549 if (InfoBuffer != NULL) 1550 { 1551 midl_user_free(InfoBuffer); 1552 } 1553 } 1554 1555 return Status; 1556 } 1557 1558 1559 static NTSTATUS 1560 SampQueryDomainModified2(PSAM_DB_OBJECT DomainObject, 1561 PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1562 { 1563 PSAMPR_DOMAIN_INFO_BUFFER InfoBuffer = NULL; 1564 SAM_DOMAIN_FIXED_DATA FixedData; 1565 ULONG Length = 0; 1566 NTSTATUS Status; 1567 1568 *Buffer = NULL; 1569 1570 InfoBuffer = midl_user_allocate(sizeof(SAMPR_DOMAIN_INFO_BUFFER)); 1571 if (InfoBuffer == NULL) 1572 return STATUS_INSUFFICIENT_RESOURCES; 1573 1574 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1575 Status = SampGetObjectAttribute(DomainObject, 1576 L"F", 1577 NULL, 1578 (PVOID)&FixedData, 1579 &Length); 1580 if (!NT_SUCCESS(Status)) 1581 goto done; 1582 1583 InfoBuffer->Modified2.DomainModifiedCount.LowPart = FixedData.DomainModifiedCount.LowPart; 1584 InfoBuffer->Modified2.DomainModifiedCount.HighPart = FixedData.DomainModifiedCount.HighPart; 1585 InfoBuffer->Modified2.CreationTime.LowPart = FixedData.CreationTime.LowPart; 1586 InfoBuffer->Modified2.CreationTime.HighPart = FixedData.CreationTime.HighPart; 1587 InfoBuffer->Modified2.ModifiedCountAtLastPromotion.LowPart = FixedData.ModifiedCountAtLastPromotion.LowPart; 1588 InfoBuffer->Modified2.ModifiedCountAtLastPromotion.HighPart = FixedData.ModifiedCountAtLastPromotion.HighPart; 1589 1590 *Buffer = InfoBuffer; 1591 1592 done: 1593 if (!NT_SUCCESS(Status)) 1594 { 1595 if (InfoBuffer != NULL) 1596 { 1597 midl_user_free(InfoBuffer); 1598 } 1599 } 1600 1601 return Status; 1602 } 1603 1604 1605 /* Function 8 */ 1606 NTSTATUS 1607 NTAPI 1608 SamrQueryInformationDomain(IN SAMPR_HANDLE DomainHandle, 1609 IN DOMAIN_INFORMATION_CLASS DomainInformationClass, 1610 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 1611 { 1612 PSAM_DB_OBJECT DomainObject; 1613 ACCESS_MASK DesiredAccess; 1614 NTSTATUS Status; 1615 1616 TRACE("SamrQueryInformationDomain(%p %lu %p)\n", 1617 DomainHandle, DomainInformationClass, Buffer); 1618 1619 switch (DomainInformationClass) 1620 { 1621 case DomainPasswordInformation: 1622 case DomainLockoutInformation: 1623 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS; 1624 break; 1625 1626 case DomainGeneralInformation: 1627 case DomainLogoffInformation: 1628 case DomainOemInformation: 1629 case DomainNameInformation: 1630 case DomainReplicationInformation: 1631 case DomainServerRoleInformation: 1632 case DomainModifiedInformation: 1633 case DomainStateInformation: 1634 case DomainModifiedInformation2: 1635 DesiredAccess = DOMAIN_READ_OTHER_PARAMETERS; 1636 break; 1637 1638 case DomainGeneralInformation2: 1639 DesiredAccess = DOMAIN_READ_PASSWORD_PARAMETERS | 1640 DOMAIN_READ_OTHER_PARAMETERS; 1641 break; 1642 1643 default: 1644 return STATUS_INVALID_INFO_CLASS; 1645 } 1646 1647 RtlAcquireResourceShared(&SampResource, 1648 TRUE); 1649 1650 /* Validate the server handle */ 1651 Status = SampValidateDbObject(DomainHandle, 1652 SamDbDomainObject, 1653 DesiredAccess, 1654 &DomainObject); 1655 if (!NT_SUCCESS(Status)) 1656 goto done; 1657 1658 switch (DomainInformationClass) 1659 { 1660 case DomainPasswordInformation: 1661 Status = SampQueryDomainPassword(DomainObject, 1662 Buffer); 1663 break; 1664 1665 case DomainGeneralInformation: 1666 Status = SampQueryDomainGeneral(DomainObject, 1667 Buffer); 1668 break; 1669 1670 case DomainLogoffInformation: 1671 Status = SampQueryDomainLogoff(DomainObject, 1672 Buffer); 1673 break; 1674 1675 case DomainOemInformation: 1676 Status = SampQueryDomainOem(DomainObject, 1677 Buffer); 1678 break; 1679 1680 case DomainNameInformation: 1681 Status = SampQueryDomainName(DomainObject, 1682 Buffer); 1683 break; 1684 1685 case DomainReplicationInformation: 1686 Status = SampQueryDomainReplication(DomainObject, 1687 Buffer); 1688 break; 1689 1690 case DomainServerRoleInformation: 1691 Status = SampQueryDomainServerRole(DomainObject, 1692 Buffer); 1693 break; 1694 1695 case DomainModifiedInformation: 1696 Status = SampQueryDomainModified(DomainObject, 1697 Buffer); 1698 break; 1699 1700 case DomainStateInformation: 1701 Status = SampQueryDomainState(DomainObject, 1702 Buffer); 1703 break; 1704 1705 case DomainGeneralInformation2: 1706 Status = SampQueryDomainGeneral2(DomainObject, 1707 Buffer); 1708 break; 1709 1710 case DomainLockoutInformation: 1711 Status = SampQueryDomainLockout(DomainObject, 1712 Buffer); 1713 break; 1714 1715 case DomainModifiedInformation2: 1716 Status = SampQueryDomainModified2(DomainObject, 1717 Buffer); 1718 break; 1719 1720 default: 1721 Status = STATUS_NOT_IMPLEMENTED; 1722 } 1723 1724 done: 1725 RtlReleaseResource(&SampResource); 1726 1727 return Status; 1728 } 1729 1730 1731 static NTSTATUS 1732 SampSetDomainPassword(PSAM_DB_OBJECT DomainObject, 1733 PSAMPR_DOMAIN_INFO_BUFFER Buffer) 1734 { 1735 SAM_DOMAIN_FIXED_DATA FixedData; 1736 ULONG Length = 0; 1737 NTSTATUS Status; 1738 1739 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1740 Status = SampGetObjectAttribute(DomainObject, 1741 L"F", 1742 NULL, 1743 (PVOID)&FixedData, 1744 &Length); 1745 if (!NT_SUCCESS(Status)) 1746 goto done; 1747 1748 FixedData.MinPasswordLength = Buffer->Password.MinPasswordLength; 1749 FixedData.PasswordHistoryLength = Buffer->Password.PasswordHistoryLength; 1750 FixedData.PasswordProperties = Buffer->Password.PasswordProperties; 1751 FixedData.MaxPasswordAge.LowPart = Buffer->Password.MaxPasswordAge.LowPart; 1752 FixedData.MaxPasswordAge.HighPart = Buffer->Password.MaxPasswordAge.HighPart; 1753 FixedData.MinPasswordAge.LowPart = Buffer->Password.MinPasswordAge.LowPart; 1754 FixedData.MinPasswordAge.HighPart = Buffer->Password.MinPasswordAge.HighPart; 1755 1756 Status = SampSetObjectAttribute(DomainObject, 1757 L"F", 1758 REG_BINARY, 1759 &FixedData, 1760 Length); 1761 1762 done: 1763 return Status; 1764 } 1765 1766 1767 static NTSTATUS 1768 SampSetDomainLogoff(PSAM_DB_OBJECT DomainObject, 1769 PSAMPR_DOMAIN_INFO_BUFFER Buffer) 1770 { 1771 SAM_DOMAIN_FIXED_DATA FixedData; 1772 ULONG Length = 0; 1773 NTSTATUS Status; 1774 1775 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1776 Status = SampGetObjectAttribute(DomainObject, 1777 L"F", 1778 NULL, 1779 (PVOID)&FixedData, 1780 &Length); 1781 if (!NT_SUCCESS(Status)) 1782 goto done; 1783 1784 FixedData.ForceLogoff.LowPart = Buffer->Logoff.ForceLogoff.LowPart; 1785 FixedData.ForceLogoff.HighPart = Buffer->Logoff.ForceLogoff.HighPart; 1786 1787 Status = SampSetObjectAttribute(DomainObject, 1788 L"F", 1789 REG_BINARY, 1790 &FixedData, 1791 Length); 1792 1793 done: 1794 return Status; 1795 } 1796 1797 1798 static NTSTATUS 1799 SampSetDomainServerRole(PSAM_DB_OBJECT DomainObject, 1800 PSAMPR_DOMAIN_INFO_BUFFER Buffer) 1801 { 1802 SAM_DOMAIN_FIXED_DATA FixedData; 1803 ULONG Length = 0; 1804 NTSTATUS Status; 1805 1806 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1807 Status = SampGetObjectAttribute(DomainObject, 1808 L"F", 1809 NULL, 1810 (PVOID)&FixedData, 1811 &Length); 1812 if (!NT_SUCCESS(Status)) 1813 goto done; 1814 1815 FixedData.DomainServerRole = Buffer->Role.DomainServerRole; 1816 1817 Status = SampSetObjectAttribute(DomainObject, 1818 L"F", 1819 REG_BINARY, 1820 &FixedData, 1821 Length); 1822 1823 done: 1824 return Status; 1825 } 1826 1827 1828 static NTSTATUS 1829 SampSetDomainState(PSAM_DB_OBJECT DomainObject, 1830 PSAMPR_DOMAIN_INFO_BUFFER Buffer) 1831 { 1832 SAM_DOMAIN_FIXED_DATA FixedData; 1833 ULONG Length = 0; 1834 NTSTATUS Status; 1835 1836 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1837 Status = SampGetObjectAttribute(DomainObject, 1838 L"F", 1839 NULL, 1840 (PVOID)&FixedData, 1841 &Length); 1842 if (!NT_SUCCESS(Status)) 1843 goto done; 1844 1845 FixedData.DomainServerState = Buffer->State.DomainServerState; 1846 1847 Status = SampSetObjectAttribute(DomainObject, 1848 L"F", 1849 REG_BINARY, 1850 &FixedData, 1851 Length); 1852 1853 done: 1854 return Status; 1855 } 1856 1857 1858 static NTSTATUS 1859 SampSetDomainLockout(PSAM_DB_OBJECT DomainObject, 1860 PSAMPR_DOMAIN_INFO_BUFFER Buffer) 1861 { 1862 SAM_DOMAIN_FIXED_DATA FixedData; 1863 ULONG Length = 0; 1864 NTSTATUS Status; 1865 1866 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 1867 Status = SampGetObjectAttribute(DomainObject, 1868 L"F", 1869 NULL, 1870 (PVOID)&FixedData, 1871 &Length); 1872 if (!NT_SUCCESS(Status)) 1873 goto done; 1874 1875 FixedData.LockoutDuration = Buffer->Lockout.LockoutDuration; 1876 FixedData.LockoutObservationWindow = Buffer->Lockout.LockoutObservationWindow; 1877 FixedData.LockoutThreshold = Buffer->Lockout.LockoutThreshold; 1878 1879 Status = SampSetObjectAttribute(DomainObject, 1880 L"F", 1881 REG_BINARY, 1882 &FixedData, 1883 Length); 1884 1885 done: 1886 return Status; 1887 } 1888 1889 1890 /* Function 9 */ 1891 NTSTATUS 1892 NTAPI 1893 SamrSetInformationDomain(IN SAMPR_HANDLE DomainHandle, 1894 IN DOMAIN_INFORMATION_CLASS DomainInformationClass, 1895 IN PSAMPR_DOMAIN_INFO_BUFFER DomainInformation) 1896 { 1897 PSAM_DB_OBJECT DomainObject; 1898 ACCESS_MASK DesiredAccess; 1899 NTSTATUS Status; 1900 1901 TRACE("SamrSetInformationDomain(%p %lu %p)\n", 1902 DomainHandle, DomainInformationClass, DomainInformation); 1903 1904 switch (DomainInformationClass) 1905 { 1906 case DomainPasswordInformation: 1907 case DomainLockoutInformation: 1908 DesiredAccess = DOMAIN_WRITE_PASSWORD_PARAMS; 1909 break; 1910 1911 case DomainLogoffInformation: 1912 case DomainOemInformation: 1913 case DomainNameInformation: 1914 DesiredAccess = DOMAIN_WRITE_OTHER_PARAMETERS; 1915 break; 1916 1917 case DomainReplicationInformation: 1918 case DomainServerRoleInformation: 1919 case DomainStateInformation: 1920 DesiredAccess = DOMAIN_ADMINISTER_SERVER; 1921 break; 1922 1923 default: 1924 return STATUS_INVALID_INFO_CLASS; 1925 } 1926 1927 RtlAcquireResourceExclusive(&SampResource, 1928 TRUE); 1929 1930 /* Validate the server handle */ 1931 Status = SampValidateDbObject(DomainHandle, 1932 SamDbDomainObject, 1933 DesiredAccess, 1934 &DomainObject); 1935 if (!NT_SUCCESS(Status)) 1936 goto done; 1937 1938 switch (DomainInformationClass) 1939 { 1940 case DomainPasswordInformation: 1941 Status = SampSetDomainPassword(DomainObject, 1942 DomainInformation); 1943 break; 1944 1945 case DomainLogoffInformation: 1946 Status = SampSetDomainLogoff(DomainObject, 1947 DomainInformation); 1948 break; 1949 1950 case DomainOemInformation: 1951 Status = SampSetObjectAttributeString(DomainObject, 1952 L"OemInformation", 1953 &DomainInformation->Oem.OemInformation); 1954 break; 1955 1956 case DomainNameInformation: 1957 Status = SampSetObjectAttributeString(DomainObject, 1958 L"Name", 1959 &DomainInformation->Name.DomainName); 1960 break; 1961 1962 case DomainReplicationInformation: 1963 Status = SampSetObjectAttributeString(DomainObject, 1964 L"ReplicaSourceNodeName", 1965 &DomainInformation->Replication.ReplicaSourceNodeName); 1966 break; 1967 1968 case DomainServerRoleInformation: 1969 Status = SampSetDomainServerRole(DomainObject, 1970 DomainInformation); 1971 break; 1972 1973 case DomainStateInformation: 1974 Status = SampSetDomainState(DomainObject, 1975 DomainInformation); 1976 break; 1977 1978 case DomainLockoutInformation: 1979 Status = SampSetDomainLockout(DomainObject, 1980 DomainInformation); 1981 break; 1982 1983 default: 1984 Status = STATUS_NOT_IMPLEMENTED; 1985 } 1986 1987 done: 1988 RtlReleaseResource(&SampResource); 1989 1990 return Status; 1991 } 1992 1993 1994 /* Function 10 */ 1995 NTSTATUS 1996 NTAPI 1997 SamrCreateGroupInDomain(IN SAMPR_HANDLE DomainHandle, 1998 IN PRPC_UNICODE_STRING Name, 1999 IN ACCESS_MASK DesiredAccess, 2000 OUT SAMPR_HANDLE *GroupHandle, 2001 OUT unsigned long *RelativeId) 2002 { 2003 SAM_DOMAIN_FIXED_DATA FixedDomainData; 2004 SAM_GROUP_FIXED_DATA FixedGroupData; 2005 PSAM_DB_OBJECT DomainObject; 2006 PSAM_DB_OBJECT GroupObject; 2007 PSECURITY_DESCRIPTOR Sd = NULL; 2008 ULONG SdSize = 0; 2009 ULONG ulSize; 2010 ULONG ulRid; 2011 WCHAR szRid[9]; 2012 NTSTATUS Status; 2013 2014 TRACE("SamrCreateGroupInDomain(%p %p %lx %p %p)\n", 2015 DomainHandle, Name, DesiredAccess, GroupHandle, RelativeId); 2016 2017 /* Map generic access rights */ 2018 RtlMapGenericMask(&DesiredAccess, 2019 &GroupMapping); 2020 2021 RtlAcquireResourceExclusive(&SampResource, 2022 TRUE); 2023 2024 /* Validate the domain handle */ 2025 Status = SampValidateDbObject(DomainHandle, 2026 SamDbDomainObject, 2027 DOMAIN_CREATE_GROUP, 2028 &DomainObject); 2029 if (!NT_SUCCESS(Status)) 2030 { 2031 TRACE("failed with status 0x%08lx\n", Status); 2032 goto done; 2033 } 2034 2035 /* Check the group account name */ 2036 Status = SampCheckAccountName(Name, 256); 2037 if (!NT_SUCCESS(Status)) 2038 { 2039 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 2040 goto done; 2041 } 2042 2043 /* Check if the group name already exists in the domain */ 2044 Status = SampCheckAccountNameInDomain(DomainObject, 2045 Name->Buffer); 2046 if (!NT_SUCCESS(Status)) 2047 { 2048 TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n", 2049 Name->Buffer, Status); 2050 goto done; 2051 } 2052 2053 /* Create the security descriptor */ 2054 Status = SampCreateGroupSD(&Sd, 2055 &SdSize); 2056 if (!NT_SUCCESS(Status)) 2057 { 2058 TRACE("SampCreateGroupSD failed (Status 0x%08lx)\n", Status); 2059 goto done; 2060 } 2061 2062 /* Get the fixed domain attributes */ 2063 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA); 2064 Status = SampGetObjectAttribute(DomainObject, 2065 L"F", 2066 NULL, 2067 (PVOID)&FixedDomainData, 2068 &ulSize); 2069 if (!NT_SUCCESS(Status)) 2070 { 2071 TRACE("failed with status 0x%08lx\n", Status); 2072 goto done; 2073 } 2074 2075 /* Increment the NextRid attribute */ 2076 ulRid = FixedDomainData.NextRid; 2077 FixedDomainData.NextRid++; 2078 2079 /* Store the fixed domain attributes */ 2080 Status = SampSetObjectAttribute(DomainObject, 2081 L"F", 2082 REG_BINARY, 2083 &FixedDomainData, 2084 ulSize); 2085 if (!NT_SUCCESS(Status)) 2086 { 2087 TRACE("failed with status 0x%08lx\n", Status); 2088 goto done; 2089 } 2090 2091 TRACE("RID: %lx\n", ulRid); 2092 2093 /* Convert the RID into a string (hex) */ 2094 swprintf(szRid, L"%08lX", ulRid); 2095 2096 /* Create the group object */ 2097 Status = SampCreateDbObject(DomainObject, 2098 L"Groups", 2099 szRid, 2100 ulRid, 2101 SamDbGroupObject, 2102 DesiredAccess, 2103 &GroupObject); 2104 if (!NT_SUCCESS(Status)) 2105 { 2106 TRACE("failed with status 0x%08lx\n", Status); 2107 goto done; 2108 } 2109 2110 /* Add the account name of the user object */ 2111 Status = SampSetAccountNameInDomain(DomainObject, 2112 L"Groups", 2113 Name->Buffer, 2114 ulRid); 2115 if (!NT_SUCCESS(Status)) 2116 { 2117 TRACE("failed with status 0x%08lx\n", Status); 2118 goto done; 2119 } 2120 2121 /* Initialize fixed user data */ 2122 memset(&FixedGroupData, 0, sizeof(SAM_GROUP_FIXED_DATA)); 2123 FixedGroupData.Version = 1; 2124 FixedGroupData.GroupId = ulRid; 2125 2126 /* Set fixed user data attribute */ 2127 Status = SampSetObjectAttribute(GroupObject, 2128 L"F", 2129 REG_BINARY, 2130 (LPVOID)&FixedGroupData, 2131 sizeof(SAM_GROUP_FIXED_DATA)); 2132 if (!NT_SUCCESS(Status)) 2133 { 2134 TRACE("failed with status 0x%08lx\n", Status); 2135 goto done; 2136 } 2137 2138 /* Set the Name attribute */ 2139 Status = SampSetObjectAttributeString(GroupObject, 2140 L"Name", 2141 Name); 2142 if (!NT_SUCCESS(Status)) 2143 { 2144 TRACE("failed with status 0x%08lx\n", Status); 2145 goto done; 2146 } 2147 2148 /* Set the AdminComment attribute */ 2149 Status = SampSetObjectAttributeString(GroupObject, 2150 L"AdminComment", 2151 NULL); 2152 if (!NT_SUCCESS(Status)) 2153 { 2154 TRACE("failed with status 0x%08lx\n", Status); 2155 goto done; 2156 } 2157 2158 /* Set the SecDesc attribute*/ 2159 Status = SampSetObjectAttribute(GroupObject, 2160 L"SecDesc", 2161 REG_BINARY, 2162 Sd, 2163 SdSize); 2164 if (!NT_SUCCESS(Status)) 2165 { 2166 TRACE("failed with status 0x%08lx\n", Status); 2167 goto done; 2168 } 2169 2170 if (NT_SUCCESS(Status)) 2171 { 2172 *GroupHandle = (SAMPR_HANDLE)GroupObject; 2173 *RelativeId = ulRid; 2174 } 2175 2176 done: 2177 if (Sd != NULL) 2178 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd); 2179 2180 RtlReleaseResource(&SampResource); 2181 2182 TRACE("returns with status 0x%08lx\n", Status); 2183 2184 return Status; 2185 } 2186 2187 2188 /* Function 11 */ 2189 NTSTATUS 2190 NTAPI 2191 SamrEnumerateGroupsInDomain(IN SAMPR_HANDLE DomainHandle, 2192 IN OUT unsigned long *EnumerationContext, 2193 OUT PSAMPR_ENUMERATION_BUFFER *Buffer, 2194 IN unsigned long PreferedMaximumLength, 2195 OUT unsigned long *CountReturned) 2196 { 2197 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL; 2198 PSAM_DB_OBJECT DomainObject; 2199 HANDLE GroupsKeyHandle = NULL; 2200 HANDLE NamesKeyHandle = NULL; 2201 WCHAR GroupName[64]; 2202 ULONG EnumIndex; 2203 ULONG EnumCount = 0; 2204 ULONG RequiredLength = 0; 2205 ULONG NameLength; 2206 ULONG DataLength; 2207 ULONG Rid; 2208 ULONG i; 2209 BOOLEAN MoreEntries = FALSE; 2210 NTSTATUS Status; 2211 2212 TRACE("SamrEnumerateUsersInDomain(%p %p %p %lu %p)\n", 2213 DomainHandle, EnumerationContext, Buffer, 2214 PreferedMaximumLength, CountReturned); 2215 2216 RtlAcquireResourceShared(&SampResource, 2217 TRUE); 2218 2219 /* Validate the domain handle */ 2220 Status = SampValidateDbObject(DomainHandle, 2221 SamDbDomainObject, 2222 DOMAIN_LIST_ACCOUNTS, 2223 &DomainObject); 2224 if (!NT_SUCCESS(Status)) 2225 goto done; 2226 2227 Status = SampRegOpenKey(DomainObject->KeyHandle, 2228 L"Groups", 2229 KEY_READ, 2230 &GroupsKeyHandle); 2231 if (!NT_SUCCESS(Status)) 2232 goto done; 2233 2234 Status = SampRegOpenKey(GroupsKeyHandle, 2235 L"Names", 2236 KEY_READ, 2237 &NamesKeyHandle); 2238 if (!NT_SUCCESS(Status)) 2239 goto done; 2240 2241 TRACE("Part 1\n"); 2242 2243 EnumIndex = *EnumerationContext; 2244 2245 while (TRUE) 2246 { 2247 NameLength = 64 * sizeof(WCHAR); 2248 Status = SampRegEnumerateValue(NamesKeyHandle, 2249 EnumIndex, 2250 GroupName, 2251 &NameLength, 2252 NULL, 2253 NULL, 2254 NULL); 2255 if (!NT_SUCCESS(Status)) 2256 { 2257 if (Status == STATUS_NO_MORE_ENTRIES) 2258 Status = STATUS_SUCCESS; 2259 break; 2260 } 2261 2262 TRACE("EnumIndex: %lu\n", EnumIndex); 2263 TRACE("Group name: %S\n", GroupName); 2264 TRACE("Name length: %lu\n", NameLength); 2265 2266 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength) 2267 { 2268 MoreEntries = TRUE; 2269 break; 2270 } 2271 2272 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)); 2273 EnumCount++; 2274 2275 EnumIndex++; 2276 } 2277 2278 TRACE("EnumCount: %lu\n", EnumCount); 2279 TRACE("RequiredLength: %lu\n", RequiredLength); 2280 2281 if (!NT_SUCCESS(Status)) 2282 goto done; 2283 2284 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER)); 2285 if (EnumBuffer == NULL) 2286 { 2287 Status = STATUS_INSUFFICIENT_RESOURCES; 2288 goto done; 2289 } 2290 2291 EnumBuffer->EntriesRead = EnumCount; 2292 if (EnumCount == 0) 2293 { 2294 Status = STATUS_NO_MORE_ENTRIES; 2295 goto done; 2296 } 2297 2298 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION)); 2299 if (EnumBuffer->Buffer == NULL) 2300 { 2301 Status = STATUS_INSUFFICIENT_RESOURCES; 2302 goto done; 2303 } 2304 2305 TRACE("Part 2\n"); 2306 2307 EnumIndex = *EnumerationContext; 2308 for (i = 0; i < EnumCount; i++, EnumIndex++) 2309 { 2310 NameLength = 64 * sizeof(WCHAR); 2311 DataLength = sizeof(ULONG); 2312 Status = SampRegEnumerateValue(NamesKeyHandle, 2313 EnumIndex, 2314 GroupName, 2315 &NameLength, 2316 NULL, 2317 &Rid, 2318 &DataLength); 2319 if (!NT_SUCCESS(Status)) 2320 { 2321 if (Status == STATUS_NO_MORE_ENTRIES) 2322 Status = STATUS_SUCCESS; 2323 break; 2324 } 2325 2326 TRACE("EnumIndex: %lu\n", EnumIndex); 2327 TRACE("Group name: %S\n", GroupName); 2328 TRACE("Name length: %lu\n", NameLength); 2329 TRACE("RID: %lu\n", Rid); 2330 2331 EnumBuffer->Buffer[i].RelativeId = Rid; 2332 2333 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength; 2334 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(NameLength + sizeof(UNICODE_NULL)); 2335 2336 /* FIXME: Disabled because of bugs in widl and rpcrt4 */ 2337 #if 0 2338 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength); 2339 if (EnumBuffer->Buffer[i].Name.Buffer == NULL) 2340 { 2341 Status = STATUS_INSUFFICIENT_RESOURCES; 2342 goto done; 2343 } 2344 2345 memcpy(EnumBuffer->Buffer[i].Name.Buffer, 2346 GroupName, 2347 EnumBuffer->Buffer[i].Name.Length); 2348 #endif 2349 } 2350 2351 done: 2352 if (NT_SUCCESS(Status)) 2353 { 2354 *EnumerationContext += EnumCount; 2355 *Buffer = EnumBuffer; 2356 *CountReturned = EnumCount; 2357 } 2358 else 2359 { 2360 *EnumerationContext = 0; 2361 *Buffer = NULL; 2362 *CountReturned = 0; 2363 2364 if (EnumBuffer != NULL) 2365 { 2366 if (EnumBuffer->Buffer != NULL) 2367 { 2368 if (EnumBuffer->EntriesRead != 0) 2369 { 2370 for (i = 0; i < EnumBuffer->EntriesRead; i++) 2371 { 2372 if (EnumBuffer->Buffer[i].Name.Buffer != NULL) 2373 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer); 2374 } 2375 } 2376 2377 midl_user_free(EnumBuffer->Buffer); 2378 } 2379 2380 midl_user_free(EnumBuffer); 2381 } 2382 } 2383 2384 SampRegCloseKey(&NamesKeyHandle); 2385 SampRegCloseKey(&GroupsKeyHandle); 2386 2387 if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE)) 2388 Status = STATUS_MORE_ENTRIES; 2389 2390 RtlReleaseResource(&SampResource); 2391 2392 return Status; 2393 } 2394 2395 2396 /* Function 12 */ 2397 NTSTATUS 2398 NTAPI 2399 SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle, 2400 IN PRPC_UNICODE_STRING Name, 2401 IN ACCESS_MASK DesiredAccess, 2402 OUT SAMPR_HANDLE *UserHandle, 2403 OUT unsigned long *RelativeId) 2404 { 2405 SAM_DOMAIN_FIXED_DATA FixedDomainData; 2406 SAM_USER_FIXED_DATA FixedUserData; 2407 PSAM_DB_OBJECT DomainObject; 2408 PSAM_DB_OBJECT UserObject; 2409 GROUP_MEMBERSHIP GroupMembership; 2410 UCHAR LogonHours[23]; 2411 ULONG ulSize; 2412 ULONG ulRid; 2413 WCHAR szRid[9]; 2414 PSECURITY_DESCRIPTOR Sd = NULL; 2415 ULONG SdSize = 0; 2416 PSID UserSid = NULL; 2417 NTSTATUS Status; 2418 2419 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n", 2420 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId); 2421 2422 if (Name == NULL || 2423 Name->Length == 0 || 2424 Name->Buffer == NULL || 2425 UserHandle == NULL || 2426 RelativeId == NULL) 2427 return STATUS_INVALID_PARAMETER; 2428 2429 /* Map generic access rights */ 2430 RtlMapGenericMask(&DesiredAccess, 2431 &UserMapping); 2432 2433 RtlAcquireResourceExclusive(&SampResource, 2434 TRUE); 2435 2436 /* Validate the domain handle */ 2437 Status = SampValidateDbObject(DomainHandle, 2438 SamDbDomainObject, 2439 DOMAIN_CREATE_USER, 2440 &DomainObject); 2441 if (!NT_SUCCESS(Status)) 2442 { 2443 TRACE("failed with status 0x%08lx\n", Status); 2444 goto done; 2445 } 2446 2447 /* Check the user account name */ 2448 Status = SampCheckAccountName(Name, 20); 2449 if (!NT_SUCCESS(Status)) 2450 { 2451 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 2452 goto done; 2453 } 2454 2455 /* Check if the user name already exists in the domain */ 2456 Status = SampCheckAccountNameInDomain(DomainObject, 2457 Name->Buffer); 2458 if (!NT_SUCCESS(Status)) 2459 { 2460 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n", 2461 Name->Buffer, Status); 2462 goto done; 2463 } 2464 2465 /* Get the fixed domain attributes */ 2466 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA); 2467 Status = SampGetObjectAttribute(DomainObject, 2468 L"F", 2469 NULL, 2470 (PVOID)&FixedDomainData, 2471 &ulSize); 2472 if (!NT_SUCCESS(Status)) 2473 { 2474 TRACE("failed with status 0x%08lx\n", Status); 2475 goto done; 2476 } 2477 2478 /* Increment the NextRid attribute */ 2479 ulRid = FixedDomainData.NextRid; 2480 FixedDomainData.NextRid++; 2481 2482 TRACE("RID: %lx\n", ulRid); 2483 2484 /* Create the user SID */ 2485 Status = SampCreateAccountSid(DomainObject, 2486 ulRid, 2487 &UserSid); 2488 if (!NT_SUCCESS(Status)) 2489 { 2490 TRACE("SampCreateAccountSid failed (Status 0x%08lx)\n", Status); 2491 goto done; 2492 } 2493 2494 /* Create the security descriptor */ 2495 Status = SampCreateUserSD(UserSid, 2496 &Sd, 2497 &SdSize); 2498 if (!NT_SUCCESS(Status)) 2499 { 2500 TRACE("SampCreateUserSD failed (Status 0x%08lx)\n", Status); 2501 goto done; 2502 } 2503 2504 /* Store the fixed domain attributes */ 2505 Status = SampSetObjectAttribute(DomainObject, 2506 L"F", 2507 REG_BINARY, 2508 &FixedDomainData, 2509 ulSize); 2510 if (!NT_SUCCESS(Status)) 2511 { 2512 TRACE("failed with status 0x%08lx\n", Status); 2513 goto done; 2514 } 2515 2516 /* Convert the RID into a string (hex) */ 2517 swprintf(szRid, L"%08lX", ulRid); 2518 2519 /* Create the user object */ 2520 Status = SampCreateDbObject(DomainObject, 2521 L"Users", 2522 szRid, 2523 ulRid, 2524 SamDbUserObject, 2525 DesiredAccess, 2526 &UserObject); 2527 if (!NT_SUCCESS(Status)) 2528 { 2529 TRACE("failed with status 0x%08lx\n", Status); 2530 goto done; 2531 } 2532 2533 /* Add the account name for the user object */ 2534 Status = SampSetAccountNameInDomain(DomainObject, 2535 L"Users", 2536 Name->Buffer, 2537 ulRid); 2538 if (!NT_SUCCESS(Status)) 2539 { 2540 TRACE("failed with status 0x%08lx\n", Status); 2541 goto done; 2542 } 2543 2544 /* Initialize fixed user data */ 2545 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA)); 2546 FixedUserData.Version = 1; 2547 FixedUserData.Reserved = 0; 2548 FixedUserData.LastLogon.QuadPart = 0; 2549 FixedUserData.LastLogoff.QuadPart = 0; 2550 FixedUserData.PasswordLastSet.QuadPart = 0; 2551 FixedUserData.AccountExpires.QuadPart = MAXLONGLONG; 2552 FixedUserData.LastBadPasswordTime.QuadPart = 0; 2553 FixedUserData.UserId = ulRid; 2554 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS; 2555 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED | 2556 USER_PASSWORD_NOT_REQUIRED | 2557 USER_NORMAL_ACCOUNT; 2558 FixedUserData.CountryCode = 0; 2559 FixedUserData.CodePage = 0; 2560 FixedUserData.BadPasswordCount = 0; 2561 FixedUserData.LogonCount = 0; 2562 FixedUserData.AdminCount = 0; 2563 FixedUserData.OperatorCount = 0; 2564 2565 /* Set fixed user data attribute */ 2566 Status = SampSetObjectAttribute(UserObject, 2567 L"F", 2568 REG_BINARY, 2569 (LPVOID)&FixedUserData, 2570 sizeof(SAM_USER_FIXED_DATA)); 2571 if (!NT_SUCCESS(Status)) 2572 { 2573 TRACE("failed with status 0x%08lx\n", Status); 2574 goto done; 2575 } 2576 2577 /* Set the Name attribute */ 2578 Status = SampSetObjectAttributeString(UserObject, 2579 L"Name", 2580 Name); 2581 if (!NT_SUCCESS(Status)) 2582 { 2583 TRACE("failed with status 0x%08lx\n", Status); 2584 goto done; 2585 } 2586 2587 /* Set the FullName attribute */ 2588 Status = SampSetObjectAttributeString(UserObject, 2589 L"FullName", 2590 NULL); 2591 if (!NT_SUCCESS(Status)) 2592 { 2593 TRACE("failed with status 0x%08lx\n", Status); 2594 goto done; 2595 } 2596 2597 /* Set the HomeDirectory attribute */ 2598 Status = SampSetObjectAttributeString(UserObject, 2599 L"HomeDirectory", 2600 NULL); 2601 if (!NT_SUCCESS(Status)) 2602 { 2603 TRACE("failed with status 0x%08lx\n", Status); 2604 goto done; 2605 } 2606 2607 /* Set the HomeDirectoryDrive attribute */ 2608 Status = SampSetObjectAttributeString(UserObject, 2609 L"HomeDirectoryDrive", 2610 NULL); 2611 if (!NT_SUCCESS(Status)) 2612 { 2613 TRACE("failed with status 0x%08lx\n", Status); 2614 goto done; 2615 } 2616 2617 /* Set the ScriptPath attribute */ 2618 Status = SampSetObjectAttributeString(UserObject, 2619 L"ScriptPath", 2620 NULL); 2621 if (!NT_SUCCESS(Status)) 2622 { 2623 TRACE("failed with status 0x%08lx\n", Status); 2624 goto done; 2625 } 2626 2627 /* Set the ProfilePath attribute */ 2628 Status = SampSetObjectAttributeString(UserObject, 2629 L"ProfilePath", 2630 NULL); 2631 if (!NT_SUCCESS(Status)) 2632 { 2633 TRACE("failed with status 0x%08lx\n", Status); 2634 goto done; 2635 } 2636 2637 /* Set the AdminComment attribute */ 2638 Status = SampSetObjectAttributeString(UserObject, 2639 L"AdminComment", 2640 NULL); 2641 if (!NT_SUCCESS(Status)) 2642 { 2643 TRACE("failed with status 0x%08lx\n", Status); 2644 goto done; 2645 } 2646 2647 /* Set the UserComment attribute */ 2648 Status = SampSetObjectAttributeString(UserObject, 2649 L"UserComment", 2650 NULL); 2651 if (!NT_SUCCESS(Status)) 2652 { 2653 TRACE("failed with status 0x%08lx\n", Status); 2654 goto done; 2655 } 2656 2657 /* Set the WorkStations attribute */ 2658 Status = SampSetObjectAttributeString(UserObject, 2659 L"WorkStations", 2660 NULL); 2661 if (!NT_SUCCESS(Status)) 2662 { 2663 TRACE("failed with status 0x%08lx\n", Status); 2664 goto done; 2665 } 2666 2667 /* Set the Parameters attribute */ 2668 Status = SampSetObjectAttributeString(UserObject, 2669 L"Parameters", 2670 NULL); 2671 if (!NT_SUCCESS(Status)) 2672 { 2673 TRACE("failed with status 0x%08lx\n", Status); 2674 goto done; 2675 } 2676 2677 /* Set LogonHours attribute*/ 2678 *((PUSHORT)LogonHours) = 168; 2679 memset(&(LogonHours[2]), 0xff, 21); 2680 2681 Status = SampSetObjectAttribute(UserObject, 2682 L"LogonHours", 2683 REG_BINARY, 2684 &LogonHours, 2685 sizeof(LogonHours)); 2686 if (!NT_SUCCESS(Status)) 2687 { 2688 TRACE("failed with status 0x%08lx\n", Status); 2689 goto done; 2690 } 2691 2692 /* Set Groups attribute*/ 2693 GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS; 2694 GroupMembership.Attributes = SE_GROUP_MANDATORY | 2695 SE_GROUP_ENABLED | 2696 SE_GROUP_ENABLED_BY_DEFAULT; 2697 2698 Status = SampSetObjectAttribute(UserObject, 2699 L"Groups", 2700 REG_BINARY, 2701 &GroupMembership, 2702 sizeof(GROUP_MEMBERSHIP)); 2703 if (!NT_SUCCESS(Status)) 2704 { 2705 TRACE("failed with status 0x%08lx\n", Status); 2706 goto done; 2707 } 2708 2709 /* Set LMPwd attribute*/ 2710 Status = SampSetObjectAttribute(UserObject, 2711 L"LMPwd", 2712 REG_BINARY, 2713 &EmptyLmHash, 2714 sizeof(ENCRYPTED_LM_OWF_PASSWORD)); 2715 if (!NT_SUCCESS(Status)) 2716 { 2717 TRACE("failed with status 0x%08lx\n", Status); 2718 goto done; 2719 } 2720 2721 /* Set NTPwd attribute*/ 2722 Status = SampSetObjectAttribute(UserObject, 2723 L"NTPwd", 2724 REG_BINARY, 2725 &EmptyNtHash, 2726 sizeof(ENCRYPTED_NT_OWF_PASSWORD)); 2727 if (!NT_SUCCESS(Status)) 2728 { 2729 TRACE("failed with status 0x%08lx\n", Status); 2730 goto done; 2731 } 2732 2733 /* Set LMPwdHistory attribute*/ 2734 Status = SampSetObjectAttribute(UserObject, 2735 L"LMPwdHistory", 2736 REG_BINARY, 2737 NULL, 2738 0); 2739 if (!NT_SUCCESS(Status)) 2740 { 2741 TRACE("failed with status 0x%08lx\n", Status); 2742 goto done; 2743 } 2744 2745 /* Set NTPwdHistory attribute*/ 2746 Status = SampSetObjectAttribute(UserObject, 2747 L"NTPwdHistory", 2748 REG_BINARY, 2749 NULL, 2750 0); 2751 if (!NT_SUCCESS(Status)) 2752 { 2753 TRACE("failed with status 0x%08lx\n", Status); 2754 goto done; 2755 } 2756 2757 /* Set the PrivateData attribute */ 2758 Status = SampSetObjectAttributeString(UserObject, 2759 L"PrivateData", 2760 NULL); 2761 if (!NT_SUCCESS(Status)) 2762 { 2763 TRACE("failed with status 0x%08lx\n", Status); 2764 goto done; 2765 } 2766 2767 /* Set the SecDesc attribute*/ 2768 Status = SampSetObjectAttribute(UserObject, 2769 L"SecDesc", 2770 REG_BINARY, 2771 Sd, 2772 SdSize); 2773 if (!NT_SUCCESS(Status)) 2774 { 2775 TRACE("failed with status 0x%08lx\n", Status); 2776 goto done; 2777 } 2778 2779 if (NT_SUCCESS(Status)) 2780 { 2781 *UserHandle = (SAMPR_HANDLE)UserObject; 2782 *RelativeId = ulRid; 2783 } 2784 2785 done: 2786 if (Sd != NULL) 2787 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd); 2788 2789 if (UserSid != NULL) 2790 RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid); 2791 2792 RtlReleaseResource(&SampResource); 2793 2794 TRACE("returns with status 0x%08lx\n", Status); 2795 2796 return Status; 2797 } 2798 2799 2800 /* Function 13 */ 2801 NTSTATUS 2802 NTAPI 2803 SamrEnumerateUsersInDomain(IN SAMPR_HANDLE DomainHandle, 2804 IN OUT unsigned long *EnumerationContext, 2805 IN unsigned long UserAccountControl, 2806 OUT PSAMPR_ENUMERATION_BUFFER *Buffer, 2807 IN unsigned long PreferedMaximumLength, 2808 OUT unsigned long *CountReturned) 2809 { 2810 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL; 2811 PSAM_DB_OBJECT DomainObject; 2812 HANDLE UsersKeyHandle = NULL; 2813 HANDLE NamesKeyHandle = NULL; 2814 WCHAR UserName[64]; 2815 ULONG EnumIndex; 2816 ULONG EnumCount = 0; 2817 ULONG RequiredLength = 0; 2818 ULONG NameLength; 2819 ULONG DataLength; 2820 ULONG Rid; 2821 ULONG i; 2822 BOOLEAN MoreEntries = FALSE; 2823 NTSTATUS Status; 2824 2825 TRACE("SamrEnumerateUsersInDomain(%p %p %lx %p %lu %p)\n", 2826 DomainHandle, EnumerationContext, UserAccountControl, Buffer, 2827 PreferedMaximumLength, CountReturned); 2828 2829 RtlAcquireResourceShared(&SampResource, 2830 TRUE); 2831 2832 /* Validate the domain handle */ 2833 Status = SampValidateDbObject(DomainHandle, 2834 SamDbDomainObject, 2835 DOMAIN_LIST_ACCOUNTS, 2836 &DomainObject); 2837 if (!NT_SUCCESS(Status)) 2838 goto done; 2839 2840 Status = SampRegOpenKey(DomainObject->KeyHandle, 2841 L"Users", 2842 KEY_READ, 2843 &UsersKeyHandle); 2844 if (!NT_SUCCESS(Status)) 2845 goto done; 2846 2847 Status = SampRegOpenKey(UsersKeyHandle, 2848 L"Names", 2849 KEY_READ, 2850 &NamesKeyHandle); 2851 if (!NT_SUCCESS(Status)) 2852 goto done; 2853 2854 TRACE("Part 1\n"); 2855 2856 EnumIndex = *EnumerationContext; 2857 2858 while (TRUE) 2859 { 2860 NameLength = 64 * sizeof(WCHAR); 2861 Status = SampRegEnumerateValue(NamesKeyHandle, 2862 EnumIndex, 2863 UserName, 2864 &NameLength, 2865 NULL, 2866 NULL, 2867 NULL); 2868 if (!NT_SUCCESS(Status)) 2869 { 2870 if (Status == STATUS_NO_MORE_ENTRIES) 2871 Status = STATUS_SUCCESS; 2872 break; 2873 } 2874 2875 TRACE("EnumIndex: %lu\n", EnumIndex); 2876 TRACE("User name: %S\n", UserName); 2877 TRACE("Name length: %lu\n", NameLength); 2878 2879 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength) 2880 { 2881 MoreEntries = TRUE; 2882 break; 2883 } 2884 2885 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)); 2886 EnumCount++; 2887 2888 EnumIndex++; 2889 } 2890 2891 TRACE("EnumCount: %lu\n", EnumCount); 2892 TRACE("RequiredLength: %lu\n", RequiredLength); 2893 2894 if (!NT_SUCCESS(Status)) 2895 goto done; 2896 2897 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER)); 2898 if (EnumBuffer == NULL) 2899 { 2900 Status = STATUS_INSUFFICIENT_RESOURCES; 2901 goto done; 2902 } 2903 2904 EnumBuffer->EntriesRead = EnumCount; 2905 if (EnumCount == 0) 2906 { 2907 Status = STATUS_NO_MORE_ENTRIES; 2908 goto done; 2909 } 2910 2911 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION)); 2912 if (EnumBuffer->Buffer == NULL) 2913 { 2914 Status = STATUS_INSUFFICIENT_RESOURCES; 2915 goto done; 2916 } 2917 2918 TRACE("Part 2\n"); 2919 2920 EnumIndex = *EnumerationContext; 2921 for (i = 0; i < EnumCount; i++, EnumIndex++) 2922 { 2923 NameLength = 64 * sizeof(WCHAR); 2924 DataLength = sizeof(ULONG); 2925 Status = SampRegEnumerateValue(NamesKeyHandle, 2926 EnumIndex, 2927 UserName, 2928 &NameLength, 2929 NULL, 2930 &Rid, 2931 &DataLength); 2932 if (!NT_SUCCESS(Status)) 2933 { 2934 if (Status == STATUS_NO_MORE_ENTRIES) 2935 Status = STATUS_SUCCESS; 2936 break; 2937 } 2938 2939 TRACE("EnumIndex: %lu\n", EnumIndex); 2940 TRACE("User name: %S\n", UserName); 2941 TRACE("Name length: %lu\n", NameLength); 2942 TRACE("RID: %lu\n", Rid); 2943 2944 EnumBuffer->Buffer[i].RelativeId = Rid; 2945 2946 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength; 2947 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(NameLength + sizeof(UNICODE_NULL)); 2948 2949 /* FIXME: Disabled because of bugs in widl and rpcrt4 */ 2950 #if 0 2951 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength); 2952 if (EnumBuffer->Buffer[i].Name.Buffer == NULL) 2953 { 2954 Status = STATUS_INSUFFICIENT_RESOURCES; 2955 goto done; 2956 } 2957 2958 memcpy(EnumBuffer->Buffer[i].Name.Buffer, 2959 UserName, 2960 EnumBuffer->Buffer[i].Name.Length); 2961 #endif 2962 } 2963 2964 done: 2965 if (NT_SUCCESS(Status)) 2966 { 2967 *EnumerationContext += EnumCount; 2968 *Buffer = EnumBuffer; 2969 *CountReturned = EnumCount; 2970 } 2971 else 2972 { 2973 *EnumerationContext = 0; 2974 *Buffer = NULL; 2975 *CountReturned = 0; 2976 2977 if (EnumBuffer != NULL) 2978 { 2979 if (EnumBuffer->Buffer != NULL) 2980 { 2981 if (EnumBuffer->EntriesRead != 0) 2982 { 2983 for (i = 0; i < EnumBuffer->EntriesRead; i++) 2984 { 2985 if (EnumBuffer->Buffer[i].Name.Buffer != NULL) 2986 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer); 2987 } 2988 } 2989 2990 midl_user_free(EnumBuffer->Buffer); 2991 } 2992 2993 midl_user_free(EnumBuffer); 2994 } 2995 } 2996 2997 SampRegCloseKey(&NamesKeyHandle); 2998 SampRegCloseKey(&UsersKeyHandle); 2999 3000 if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE)) 3001 Status = STATUS_MORE_ENTRIES; 3002 3003 RtlReleaseResource(&SampResource); 3004 3005 return Status; 3006 } 3007 3008 3009 /* Function 14 */ 3010 NTSTATUS 3011 NTAPI 3012 SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle, 3013 IN PRPC_UNICODE_STRING AccountName, 3014 IN ACCESS_MASK DesiredAccess, 3015 OUT SAMPR_HANDLE *AliasHandle, 3016 OUT unsigned long *RelativeId) 3017 { 3018 SAM_DOMAIN_FIXED_DATA FixedDomainData; 3019 PSAM_DB_OBJECT DomainObject; 3020 PSAM_DB_OBJECT AliasObject; 3021 PSECURITY_DESCRIPTOR Sd = NULL; 3022 ULONG SdSize = 0; 3023 ULONG ulSize; 3024 ULONG ulRid; 3025 WCHAR szRid[9]; 3026 NTSTATUS Status; 3027 3028 TRACE("SamrCreateAliasInDomain(%p %p %lx %p %p)\n", 3029 DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId); 3030 3031 /* Map generic access rights */ 3032 RtlMapGenericMask(&DesiredAccess, 3033 &AliasMapping); 3034 3035 RtlAcquireResourceExclusive(&SampResource, 3036 TRUE); 3037 3038 /* Validate the domain handle */ 3039 Status = SampValidateDbObject(DomainHandle, 3040 SamDbDomainObject, 3041 DOMAIN_CREATE_ALIAS, 3042 &DomainObject); 3043 if (!NT_SUCCESS(Status)) 3044 { 3045 TRACE("failed with status 0x%08lx\n", Status); 3046 goto done; 3047 } 3048 3049 /* Check the alias account name */ 3050 Status = SampCheckAccountName(AccountName, 256); 3051 if (!NT_SUCCESS(Status)) 3052 { 3053 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 3054 goto done; 3055 } 3056 3057 /* Check if the alias name already exists in the domain */ 3058 Status = SampCheckAccountNameInDomain(DomainObject, 3059 AccountName->Buffer); 3060 if (!NT_SUCCESS(Status)) 3061 { 3062 TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n", 3063 AccountName->Buffer, Status); 3064 goto done; 3065 } 3066 3067 /* Create the security descriptor */ 3068 Status = SampCreateAliasSD(&Sd, 3069 &SdSize); 3070 if (!NT_SUCCESS(Status)) 3071 { 3072 TRACE("SampCreateAliasSD failed (Status 0x%08lx)\n", Status); 3073 goto done; 3074 } 3075 3076 /* Get the fixed domain attributes */ 3077 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA); 3078 Status = SampGetObjectAttribute(DomainObject, 3079 L"F", 3080 NULL, 3081 (PVOID)&FixedDomainData, 3082 &ulSize); 3083 if (!NT_SUCCESS(Status)) 3084 { 3085 TRACE("failed with status 0x%08lx\n", Status); 3086 goto done; 3087 } 3088 3089 /* Increment the NextRid attribute */ 3090 ulRid = FixedDomainData.NextRid; 3091 FixedDomainData.NextRid++; 3092 3093 /* Store the fixed domain attributes */ 3094 Status = SampSetObjectAttribute(DomainObject, 3095 L"F", 3096 REG_BINARY, 3097 &FixedDomainData, 3098 ulSize); 3099 if (!NT_SUCCESS(Status)) 3100 { 3101 TRACE("failed with status 0x%08lx\n", Status); 3102 goto done; 3103 } 3104 3105 TRACE("RID: %lx\n", ulRid); 3106 3107 /* Convert the RID into a string (hex) */ 3108 swprintf(szRid, L"%08lX", ulRid); 3109 3110 /* Create the alias object */ 3111 Status = SampCreateDbObject(DomainObject, 3112 L"Aliases", 3113 szRid, 3114 ulRid, 3115 SamDbAliasObject, 3116 DesiredAccess, 3117 &AliasObject); 3118 if (!NT_SUCCESS(Status)) 3119 { 3120 TRACE("failed with status 0x%08lx\n", Status); 3121 goto done; 3122 } 3123 3124 /* Add the account name for the alias object */ 3125 Status = SampSetAccountNameInDomain(DomainObject, 3126 L"Aliases", 3127 AccountName->Buffer, 3128 ulRid); 3129 if (!NT_SUCCESS(Status)) 3130 { 3131 TRACE("failed with status 0x%08lx\n", Status); 3132 goto done; 3133 } 3134 3135 /* Set the Name attribute */ 3136 Status = SampSetObjectAttributeString(AliasObject, 3137 L"Name", 3138 AccountName); 3139 if (!NT_SUCCESS(Status)) 3140 { 3141 TRACE("failed with status 0x%08lx\n", Status); 3142 goto done; 3143 } 3144 3145 /* Set the Description attribute */ 3146 Status = SampSetObjectAttributeString(AliasObject, 3147 L"Description", 3148 NULL); 3149 if (!NT_SUCCESS(Status)) 3150 { 3151 TRACE("failed with status 0x%08lx\n", Status); 3152 goto done; 3153 } 3154 3155 /* Set the SecDesc attribute*/ 3156 Status = SampSetObjectAttribute(AliasObject, 3157 L"SecDesc", 3158 REG_BINARY, 3159 Sd, 3160 SdSize); 3161 if (!NT_SUCCESS(Status)) 3162 { 3163 TRACE("failed with status 0x%08lx\n", Status); 3164 goto done; 3165 } 3166 3167 if (NT_SUCCESS(Status)) 3168 { 3169 *AliasHandle = (SAMPR_HANDLE)AliasObject; 3170 *RelativeId = ulRid; 3171 } 3172 3173 done: 3174 if (Sd != NULL) 3175 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd); 3176 3177 RtlReleaseResource(&SampResource); 3178 3179 TRACE("returns with status 0x%08lx\n", Status); 3180 3181 return Status; 3182 } 3183 3184 3185 /* Function 15 */ 3186 NTSTATUS 3187 NTAPI 3188 SamrEnumerateAliasesInDomain(IN SAMPR_HANDLE DomainHandle, 3189 IN OUT unsigned long *EnumerationContext, 3190 OUT PSAMPR_ENUMERATION_BUFFER *Buffer, 3191 IN unsigned long PreferedMaximumLength, 3192 OUT unsigned long *CountReturned) 3193 { 3194 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL; 3195 PSAM_DB_OBJECT DomainObject; 3196 HANDLE AliasesKeyHandle = NULL; 3197 HANDLE NamesKeyHandle = NULL; 3198 WCHAR AliasName[64]; 3199 ULONG EnumIndex; 3200 ULONG EnumCount = 0; 3201 ULONG RequiredLength = 0; 3202 ULONG NameLength; 3203 ULONG DataLength; 3204 ULONG Rid; 3205 ULONG i; 3206 BOOLEAN MoreEntries = FALSE; 3207 NTSTATUS Status; 3208 3209 TRACE("SamrEnumerateAliasesInDomain(%p %p %p %lu %p)\n", 3210 DomainHandle, EnumerationContext, Buffer, 3211 PreferedMaximumLength, CountReturned); 3212 3213 RtlAcquireResourceShared(&SampResource, 3214 TRUE); 3215 3216 /* Validate the domain handle */ 3217 Status = SampValidateDbObject(DomainHandle, 3218 SamDbDomainObject, 3219 DOMAIN_LIST_ACCOUNTS, 3220 &DomainObject); 3221 if (!NT_SUCCESS(Status)) 3222 goto done; 3223 3224 Status = SampRegOpenKey(DomainObject->KeyHandle, 3225 L"Aliases", 3226 KEY_READ, 3227 &AliasesKeyHandle); 3228 if (!NT_SUCCESS(Status)) 3229 goto done; 3230 3231 Status = SampRegOpenKey(AliasesKeyHandle, 3232 L"Names", 3233 KEY_READ, 3234 &NamesKeyHandle); 3235 if (!NT_SUCCESS(Status)) 3236 goto done; 3237 3238 TRACE("Part 1\n"); 3239 3240 EnumIndex = *EnumerationContext; 3241 3242 while (TRUE) 3243 { 3244 NameLength = 64 * sizeof(WCHAR); 3245 Status = SampRegEnumerateValue(NamesKeyHandle, 3246 EnumIndex, 3247 AliasName, 3248 &NameLength, 3249 NULL, 3250 NULL, 3251 NULL); 3252 if (!NT_SUCCESS(Status)) 3253 { 3254 if (Status == STATUS_NO_MORE_ENTRIES) 3255 Status = STATUS_SUCCESS; 3256 break; 3257 } 3258 3259 TRACE("EnumIndex: %lu\n", EnumIndex); 3260 TRACE("Alias name: %S\n", AliasName); 3261 TRACE("Name length: %lu\n", NameLength); 3262 3263 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength) 3264 { 3265 MoreEntries = TRUE; 3266 break; 3267 } 3268 3269 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)); 3270 EnumCount++; 3271 3272 EnumIndex++; 3273 } 3274 3275 TRACE("EnumCount: %lu\n", EnumCount); 3276 TRACE("RequiredLength: %lu\n", RequiredLength); 3277 3278 if (!NT_SUCCESS(Status)) 3279 goto done; 3280 3281 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER)); 3282 if (EnumBuffer == NULL) 3283 { 3284 Status = STATUS_INSUFFICIENT_RESOURCES; 3285 goto done; 3286 } 3287 3288 EnumBuffer->EntriesRead = EnumCount; 3289 if (EnumCount == 0) 3290 { 3291 Status = STATUS_NO_MORE_ENTRIES; 3292 goto done; 3293 } 3294 3295 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION)); 3296 if (EnumBuffer->Buffer == NULL) 3297 { 3298 Status = STATUS_INSUFFICIENT_RESOURCES; 3299 goto done; 3300 } 3301 3302 TRACE("Part 2\n"); 3303 3304 EnumIndex = *EnumerationContext; 3305 for (i = 0; i < EnumCount; i++, EnumIndex++) 3306 { 3307 NameLength = 64 * sizeof(WCHAR); 3308 DataLength = sizeof(ULONG); 3309 Status = SampRegEnumerateValue(NamesKeyHandle, 3310 EnumIndex, 3311 AliasName, 3312 &NameLength, 3313 NULL, 3314 &Rid, 3315 &DataLength); 3316 if (!NT_SUCCESS(Status)) 3317 { 3318 if (Status == STATUS_NO_MORE_ENTRIES) 3319 Status = STATUS_SUCCESS; 3320 break; 3321 } 3322 3323 TRACE("EnumIndex: %lu\n", EnumIndex); 3324 TRACE("Alias name: %S\n", AliasName); 3325 TRACE("Name length: %lu\n", NameLength); 3326 TRACE("RID: %lu\n", Rid); 3327 3328 EnumBuffer->Buffer[i].RelativeId = Rid; 3329 3330 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength; 3331 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(NameLength + sizeof(UNICODE_NULL)); 3332 3333 /* FIXME: Disabled because of bugs in widl and rpcrt4 */ 3334 #if 0 3335 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength); 3336 if (EnumBuffer->Buffer[i].Name.Buffer == NULL) 3337 { 3338 Status = STATUS_INSUFFICIENT_RESOURCES; 3339 goto done; 3340 } 3341 3342 memcpy(EnumBuffer->Buffer[i].Name.Buffer, 3343 AliasName, 3344 EnumBuffer->Buffer[i].Name.Length); 3345 #endif 3346 } 3347 3348 done: 3349 if (NT_SUCCESS(Status)) 3350 { 3351 *EnumerationContext += EnumCount; 3352 *Buffer = EnumBuffer; 3353 *CountReturned = EnumCount; 3354 } 3355 else 3356 { 3357 *EnumerationContext = 0; 3358 *Buffer = NULL; 3359 *CountReturned = 0; 3360 3361 if (EnumBuffer != NULL) 3362 { 3363 if (EnumBuffer->Buffer != NULL) 3364 { 3365 if (EnumBuffer->EntriesRead != 0) 3366 { 3367 for (i = 0; i < EnumBuffer->EntriesRead; i++) 3368 { 3369 if (EnumBuffer->Buffer[i].Name.Buffer != NULL) 3370 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer); 3371 } 3372 } 3373 3374 midl_user_free(EnumBuffer->Buffer); 3375 } 3376 3377 midl_user_free(EnumBuffer); 3378 } 3379 } 3380 3381 SampRegCloseKey(&NamesKeyHandle); 3382 SampRegCloseKey(&AliasesKeyHandle); 3383 3384 if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE)) 3385 Status = STATUS_MORE_ENTRIES; 3386 3387 RtlReleaseResource(&SampResource); 3388 3389 return Status; 3390 } 3391 3392 3393 /* Function 16 */ 3394 NTSTATUS 3395 NTAPI 3396 SamrGetAliasMembership(IN SAMPR_HANDLE DomainHandle, 3397 IN PSAMPR_PSID_ARRAY SidArray, 3398 OUT PSAMPR_ULONG_ARRAY Membership) 3399 { 3400 PSAM_DB_OBJECT DomainObject; 3401 HANDLE AliasesKeyHandle = NULL; 3402 HANDLE MembersKeyHandle = NULL; 3403 HANDLE MemberKeyHandle = NULL; 3404 LPWSTR MemberSidString = NULL; 3405 PULONG RidArray = NULL; 3406 ULONG MaxSidCount = 0; 3407 ULONG ValueCount; 3408 ULONG DataLength; 3409 ULONG i, j; 3410 ULONG RidIndex; 3411 NTSTATUS Status; 3412 WCHAR NameBuffer[9]; 3413 3414 TRACE("SamrGetAliasMembership(%p %p %p)\n", 3415 DomainHandle, SidArray, Membership); 3416 3417 RtlAcquireResourceShared(&SampResource, 3418 TRUE); 3419 3420 /* Validate the domain handle */ 3421 Status = SampValidateDbObject(DomainHandle, 3422 SamDbDomainObject, 3423 DOMAIN_GET_ALIAS_MEMBERSHIP, 3424 &DomainObject); 3425 if (!NT_SUCCESS(Status)) 3426 goto done; 3427 3428 Status = SampRegOpenKey(DomainObject->KeyHandle, 3429 L"Aliases", 3430 KEY_READ, 3431 &AliasesKeyHandle); 3432 TRACE("SampRegOpenKey returned %08lX\n", Status); 3433 if (!NT_SUCCESS(Status)) 3434 goto done; 3435 3436 Status = SampRegOpenKey(AliasesKeyHandle, 3437 L"Members", 3438 KEY_READ, 3439 &MembersKeyHandle); 3440 TRACE("SampRegOpenKey returned %08lX\n", Status); 3441 3442 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 3443 { 3444 Status = STATUS_SUCCESS; 3445 goto done; 3446 } 3447 3448 if (!NT_SUCCESS(Status)) 3449 goto done; 3450 3451 for (i = 0; i < SidArray->Count; i++) 3452 { 3453 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString); 3454 TRACE("Open %S\n", MemberSidString); 3455 3456 Status = SampRegOpenKey(MembersKeyHandle, 3457 MemberSidString, 3458 KEY_READ, 3459 &MemberKeyHandle); 3460 TRACE("SampRegOpenKey returned %08lX\n", Status); 3461 if (NT_SUCCESS(Status)) 3462 { 3463 Status = SampRegQueryKeyInfo(MemberKeyHandle, 3464 NULL, 3465 &ValueCount); 3466 if (NT_SUCCESS(Status)) 3467 { 3468 TRACE("Found %lu values\n", ValueCount); 3469 MaxSidCount += ValueCount; 3470 } 3471 3472 SampRegCloseKey(&MemberKeyHandle); 3473 } 3474 3475 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 3476 Status = STATUS_SUCCESS; 3477 3478 LocalFree(MemberSidString); 3479 } 3480 3481 if (MaxSidCount == 0) 3482 { 3483 Status = STATUS_SUCCESS; 3484 goto done; 3485 } 3486 3487 TRACE("Maximum sid count: %lu\n", MaxSidCount); 3488 RidArray = midl_user_allocate(MaxSidCount * sizeof(ULONG)); 3489 if (RidArray == NULL) 3490 { 3491 Status = STATUS_INSUFFICIENT_RESOURCES; 3492 goto done; 3493 } 3494 3495 RidIndex = 0; 3496 for (i = 0; i < SidArray->Count; i++) 3497 { 3498 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString); 3499 TRACE("Open %S\n", MemberSidString); 3500 3501 Status = SampRegOpenKey(MembersKeyHandle, 3502 MemberSidString, 3503 KEY_READ, 3504 &MemberKeyHandle); 3505 TRACE("SampRegOpenKey returned %08lX\n", Status); 3506 if (NT_SUCCESS(Status)) 3507 { 3508 Status = SampRegQueryKeyInfo(MemberKeyHandle, 3509 NULL, 3510 &ValueCount); 3511 if (NT_SUCCESS(Status)) 3512 { 3513 TRACE("Found %lu values\n", ValueCount); 3514 3515 for (j = 0; j < ValueCount; j++) 3516 { 3517 DataLength = 9 * sizeof(WCHAR); 3518 Status = SampRegEnumerateValue(MemberKeyHandle, 3519 j, 3520 NameBuffer, 3521 &DataLength, 3522 NULL, 3523 NULL, 3524 NULL); 3525 if (NT_SUCCESS(Status)) 3526 { 3527 /* FIXME: Do not return each RID more than once. */ 3528 RidArray[RidIndex] = wcstoul(NameBuffer, NULL, 16); 3529 RidIndex++; 3530 } 3531 } 3532 } 3533 3534 SampRegCloseKey(&MemberKeyHandle); 3535 } 3536 3537 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 3538 Status = STATUS_SUCCESS; 3539 3540 LocalFree(MemberSidString); 3541 } 3542 3543 done: 3544 SampRegCloseKey(&MembersKeyHandle); 3545 SampRegCloseKey(&AliasesKeyHandle); 3546 3547 if (NT_SUCCESS(Status)) 3548 { 3549 Membership->Count = MaxSidCount; 3550 Membership->Element = RidArray; 3551 } 3552 else 3553 { 3554 if (RidArray != NULL) 3555 midl_user_free(RidArray); 3556 } 3557 3558 RtlReleaseResource(&SampResource); 3559 3560 return Status; 3561 } 3562 3563 3564 /* Function 17 */ 3565 NTSTATUS 3566 NTAPI 3567 SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle, 3568 IN ULONG Count, 3569 IN RPC_UNICODE_STRING Names[], 3570 OUT PSAMPR_ULONG_ARRAY RelativeIds, 3571 OUT PSAMPR_ULONG_ARRAY Use) 3572 { 3573 PSAM_DB_OBJECT DomainObject; 3574 HANDLE AccountsKeyHandle = NULL; 3575 HANDLE NamesKeyHandle = NULL; 3576 ULONG MappedCount = 0; 3577 ULONG DataLength; 3578 ULONG i; 3579 ULONG RelativeId; 3580 NTSTATUS Status; 3581 3582 TRACE("SamrLookupNamesInDomain(%p %lu %p %p %p)\n", 3583 DomainHandle, Count, Names, RelativeIds, Use); 3584 3585 RtlAcquireResourceShared(&SampResource, 3586 TRUE); 3587 3588 /* Validate the domain handle */ 3589 Status = SampValidateDbObject(DomainHandle, 3590 SamDbDomainObject, 3591 DOMAIN_LOOKUP, 3592 &DomainObject); 3593 if (!NT_SUCCESS(Status)) 3594 { 3595 TRACE("failed with status 0x%08lx\n", Status); 3596 goto done; 3597 } 3598 3599 RelativeIds->Count = 0; 3600 Use->Count = 0; 3601 3602 if (Count == 0) 3603 { 3604 Status = STATUS_SUCCESS; 3605 goto done; 3606 } 3607 3608 /* Allocate the relative IDs array */ 3609 RelativeIds->Element = midl_user_allocate(Count * sizeof(ULONG)); 3610 if (RelativeIds->Element == NULL) 3611 { 3612 Status = STATUS_INSUFFICIENT_RESOURCES; 3613 goto done; 3614 } 3615 3616 /* Allocate the use array */ 3617 Use->Element = midl_user_allocate(Count * sizeof(ULONG)); 3618 if (Use->Element == NULL) 3619 { 3620 Status = STATUS_INSUFFICIENT_RESOURCES; 3621 goto done; 3622 } 3623 3624 RelativeIds->Count = Count; 3625 Use->Count = Count; 3626 3627 for (i = 0; i < Count; i++) 3628 { 3629 TRACE("Name: %S\n", Names[i].Buffer); 3630 3631 RelativeId = 0; 3632 3633 /* Lookup aliases */ 3634 Status = SampRegOpenKey(DomainObject->KeyHandle, 3635 L"Aliases", 3636 KEY_READ, 3637 &AccountsKeyHandle); 3638 if (NT_SUCCESS(Status)) 3639 { 3640 Status = SampRegOpenKey(AccountsKeyHandle, 3641 L"Names", 3642 KEY_READ, 3643 &NamesKeyHandle); 3644 if (NT_SUCCESS(Status)) 3645 { 3646 DataLength = sizeof(ULONG); 3647 Status = SampRegQueryValue(NamesKeyHandle, 3648 Names[i].Buffer, 3649 NULL, 3650 &RelativeId, 3651 &DataLength); 3652 3653 SampRegCloseKey(&NamesKeyHandle); 3654 } 3655 3656 SampRegCloseKey(&AccountsKeyHandle); 3657 } 3658 3659 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 3660 break; 3661 3662 /* Return alias account */ 3663 if (NT_SUCCESS(Status) && RelativeId != 0) 3664 { 3665 TRACE("Rid: %lu\n", RelativeId); 3666 RelativeIds->Element[i] = RelativeId; 3667 Use->Element[i] = SidTypeAlias; 3668 MappedCount++; 3669 continue; 3670 } 3671 3672 /* Lookup groups */ 3673 Status = SampRegOpenKey(DomainObject->KeyHandle, 3674 L"Groups", 3675 KEY_READ, 3676 &AccountsKeyHandle); 3677 if (NT_SUCCESS(Status)) 3678 { 3679 Status = SampRegOpenKey(AccountsKeyHandle, 3680 L"Names", 3681 KEY_READ, 3682 &NamesKeyHandle); 3683 if (NT_SUCCESS(Status)) 3684 { 3685 DataLength = sizeof(ULONG); 3686 Status = SampRegQueryValue(NamesKeyHandle, 3687 Names[i].Buffer, 3688 NULL, 3689 &RelativeId, 3690 &DataLength); 3691 3692 SampRegCloseKey(&NamesKeyHandle); 3693 } 3694 3695 SampRegCloseKey(&AccountsKeyHandle); 3696 } 3697 3698 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 3699 break; 3700 3701 /* Return group account */ 3702 if (NT_SUCCESS(Status) && RelativeId != 0) 3703 { 3704 TRACE("Rid: %lu\n", RelativeId); 3705 RelativeIds->Element[i] = RelativeId; 3706 Use->Element[i] = SidTypeGroup; 3707 MappedCount++; 3708 continue; 3709 } 3710 3711 /* Lookup users */ 3712 Status = SampRegOpenKey(DomainObject->KeyHandle, 3713 L"Users", 3714 KEY_READ, 3715 &AccountsKeyHandle); 3716 if (NT_SUCCESS(Status)) 3717 { 3718 Status = SampRegOpenKey(AccountsKeyHandle, 3719 L"Names", 3720 KEY_READ, 3721 &NamesKeyHandle); 3722 if (NT_SUCCESS(Status)) 3723 { 3724 DataLength = sizeof(ULONG); 3725 Status = SampRegQueryValue(NamesKeyHandle, 3726 Names[i].Buffer, 3727 NULL, 3728 &RelativeId, 3729 &DataLength); 3730 3731 SampRegCloseKey(&NamesKeyHandle); 3732 } 3733 3734 SampRegCloseKey(&AccountsKeyHandle); 3735 } 3736 3737 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 3738 break; 3739 3740 /* Return user account */ 3741 if (NT_SUCCESS(Status) && RelativeId != 0) 3742 { 3743 TRACE("Rid: %lu\n", RelativeId); 3744 RelativeIds->Element[i] = RelativeId; 3745 Use->Element[i] = SidTypeUser; 3746 MappedCount++; 3747 continue; 3748 } 3749 3750 /* Return unknown account */ 3751 RelativeIds->Element[i] = 0; 3752 Use->Element[i] = SidTypeUnknown; 3753 } 3754 3755 done: 3756 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 3757 Status = STATUS_SUCCESS; 3758 3759 if (NT_SUCCESS(Status)) 3760 { 3761 if (MappedCount == 0) 3762 Status = STATUS_NONE_MAPPED; 3763 else if (MappedCount < Count) 3764 Status = STATUS_SOME_NOT_MAPPED; 3765 } 3766 else 3767 { 3768 if (RelativeIds->Element != NULL) 3769 { 3770 midl_user_free(RelativeIds->Element); 3771 RelativeIds->Element = NULL; 3772 } 3773 3774 RelativeIds->Count = 0; 3775 3776 if (Use->Element != NULL) 3777 { 3778 midl_user_free(Use->Element); 3779 Use->Element = NULL; 3780 } 3781 3782 Use->Count = 0; 3783 } 3784 3785 RtlReleaseResource(&SampResource); 3786 3787 TRACE("Returned Status %lx\n", Status); 3788 3789 return Status; 3790 } 3791 3792 3793 /* Function 18 */ 3794 NTSTATUS 3795 NTAPI 3796 SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle, 3797 IN ULONG Count, 3798 IN ULONG *RelativeIds, 3799 OUT PSAMPR_RETURNED_USTRING_ARRAY Names, 3800 OUT PSAMPR_ULONG_ARRAY Use) 3801 { 3802 PSAM_DB_OBJECT DomainObject; 3803 WCHAR RidString[9]; 3804 HANDLE AccountsKeyHandle = NULL; 3805 HANDLE AccountKeyHandle = NULL; 3806 ULONG MappedCount = 0; 3807 ULONG DataLength; 3808 ULONG i; 3809 NTSTATUS Status; 3810 3811 TRACE("SamrLookupIdsInDomain(%p %lu %p %p %p)\n", 3812 DomainHandle, Count, RelativeIds, Names, Use); 3813 3814 RtlAcquireResourceShared(&SampResource, 3815 TRUE); 3816 3817 /* Validate the domain handle */ 3818 Status = SampValidateDbObject(DomainHandle, 3819 SamDbDomainObject, 3820 DOMAIN_LOOKUP, 3821 &DomainObject); 3822 if (!NT_SUCCESS(Status)) 3823 { 3824 TRACE("failed with status 0x%08lx\n", Status); 3825 goto done; 3826 } 3827 3828 Names->Count = 0; 3829 Use->Count = 0; 3830 3831 if (Count == 0) 3832 { 3833 Status = STATUS_SUCCESS; 3834 goto done; 3835 } 3836 3837 /* Allocate the names array */ 3838 Names->Element = midl_user_allocate(Count * sizeof(*Names->Element)); 3839 if (Names->Element == NULL) 3840 { 3841 Status = STATUS_INSUFFICIENT_RESOURCES; 3842 goto done; 3843 } 3844 3845 /* Allocate the use array */ 3846 Use->Element = midl_user_allocate(Count * sizeof(*Use->Element)); 3847 if (Use->Element == NULL) 3848 { 3849 Status = STATUS_INSUFFICIENT_RESOURCES; 3850 goto done; 3851 } 3852 3853 Names->Count = Count; 3854 Use->Count = Count; 3855 3856 for (i = 0; i < Count; i++) 3857 { 3858 TRACE("RID: %lu\n", RelativeIds[i]); 3859 3860 swprintf(RidString, L"%08lx", RelativeIds[i]); 3861 3862 /* Lookup aliases */ 3863 Status = SampRegOpenKey(DomainObject->KeyHandle, 3864 L"Aliases", 3865 KEY_READ, 3866 &AccountsKeyHandle); 3867 if (NT_SUCCESS(Status)) 3868 { 3869 Status = SampRegOpenKey(AccountsKeyHandle, 3870 RidString, 3871 KEY_READ, 3872 &AccountKeyHandle); 3873 if (NT_SUCCESS(Status)) 3874 { 3875 DataLength = 0; 3876 Status = SampRegQueryValue(AccountKeyHandle, 3877 L"Name", 3878 NULL, 3879 NULL, 3880 &DataLength); 3881 if (NT_SUCCESS(Status)) 3882 { 3883 Names->Element[i].Buffer = midl_user_allocate(DataLength); 3884 if (Names->Element[i].Buffer == NULL) 3885 Status = STATUS_INSUFFICIENT_RESOURCES; 3886 3887 if (NT_SUCCESS(Status)) 3888 { 3889 Names->Element[i].MaximumLength = (USHORT)DataLength; 3890 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR)); 3891 3892 Status = SampRegQueryValue(AccountKeyHandle, 3893 L"Name", 3894 NULL, 3895 Names->Element[i].Buffer, 3896 &DataLength); 3897 } 3898 } 3899 3900 SampRegCloseKey(&AccountKeyHandle); 3901 } 3902 3903 SampRegCloseKey(&AccountsKeyHandle); 3904 } 3905 3906 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 3907 break; 3908 3909 /* Return alias account */ 3910 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL) 3911 { 3912 TRACE("Name: %S\n", Names->Element[i].Buffer); 3913 Use->Element[i] = SidTypeAlias; 3914 MappedCount++; 3915 continue; 3916 } 3917 3918 /* Lookup groups */ 3919 Status = SampRegOpenKey(DomainObject->KeyHandle, 3920 L"Groups", 3921 KEY_READ, 3922 &AccountsKeyHandle); 3923 if (NT_SUCCESS(Status)) 3924 { 3925 Status = SampRegOpenKey(AccountsKeyHandle, 3926 RidString, 3927 KEY_READ, 3928 &AccountKeyHandle); 3929 if (NT_SUCCESS(Status)) 3930 { 3931 DataLength = 0; 3932 Status = SampRegQueryValue(AccountKeyHandle, 3933 L"Name", 3934 NULL, 3935 NULL, 3936 &DataLength); 3937 if (NT_SUCCESS(Status)) 3938 { 3939 Names->Element[i].Buffer = midl_user_allocate(DataLength); 3940 if (Names->Element[i].Buffer == NULL) 3941 Status = STATUS_INSUFFICIENT_RESOURCES; 3942 3943 if (NT_SUCCESS(Status)) 3944 { 3945 Names->Element[i].MaximumLength = (USHORT)DataLength; 3946 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR)); 3947 3948 Status = SampRegQueryValue(AccountKeyHandle, 3949 L"Name", 3950 NULL, 3951 Names->Element[i].Buffer, 3952 &DataLength); 3953 } 3954 } 3955 3956 SampRegCloseKey(&AccountKeyHandle); 3957 } 3958 3959 SampRegCloseKey(&AccountsKeyHandle); 3960 } 3961 3962 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 3963 break; 3964 3965 /* Return group account */ 3966 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL) 3967 { 3968 TRACE("Name: %S\n", Names->Element[i].Buffer); 3969 Use->Element[i] = SidTypeGroup; 3970 MappedCount++; 3971 continue; 3972 } 3973 3974 /* Lookup users */ 3975 Status = SampRegOpenKey(DomainObject->KeyHandle, 3976 L"Users", 3977 KEY_READ, 3978 &AccountsKeyHandle); 3979 if (NT_SUCCESS(Status)) 3980 { 3981 Status = SampRegOpenKey(AccountsKeyHandle, 3982 RidString, 3983 KEY_READ, 3984 &AccountKeyHandle); 3985 if (NT_SUCCESS(Status)) 3986 { 3987 DataLength = 0; 3988 Status = SampRegQueryValue(AccountKeyHandle, 3989 L"Name", 3990 NULL, 3991 NULL, 3992 &DataLength); 3993 if (NT_SUCCESS(Status)) 3994 { 3995 TRACE("DataLength: %lu\n", DataLength); 3996 3997 Names->Element[i].Buffer = midl_user_allocate(DataLength); 3998 if (Names->Element[i].Buffer == NULL) 3999 Status = STATUS_INSUFFICIENT_RESOURCES; 4000 4001 if (NT_SUCCESS(Status)) 4002 { 4003 Names->Element[i].MaximumLength = (USHORT)DataLength; 4004 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR)); 4005 4006 Status = SampRegQueryValue(AccountKeyHandle, 4007 L"Name", 4008 NULL, 4009 Names->Element[i].Buffer, 4010 &DataLength); 4011 } 4012 } 4013 4014 SampRegCloseKey(&AccountKeyHandle); 4015 } 4016 4017 SampRegCloseKey(&AccountsKeyHandle); 4018 } 4019 4020 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 4021 break; 4022 4023 /* Return user account */ 4024 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL) 4025 { 4026 TRACE("Name: %S\n", Names->Element[i].Buffer); 4027 Use->Element[i] = SidTypeUser; 4028 MappedCount++; 4029 continue; 4030 } 4031 4032 /* Return unknown account */ 4033 Use->Element[i] = SidTypeUnknown; 4034 } 4035 4036 done: 4037 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 4038 Status = STATUS_SUCCESS; 4039 4040 if (NT_SUCCESS(Status)) 4041 { 4042 if (MappedCount == 0) 4043 Status = STATUS_NONE_MAPPED; 4044 else if (MappedCount < Count) 4045 Status = STATUS_SOME_NOT_MAPPED; 4046 } 4047 else 4048 { 4049 if (Names->Element != NULL) 4050 { 4051 for (i = 0; i < Count; i++) 4052 { 4053 if (Names->Element[i].Buffer != NULL) 4054 midl_user_free(Names->Element[i].Buffer); 4055 } 4056 4057 midl_user_free(Names->Element); 4058 Names->Element = NULL; 4059 } 4060 4061 Names->Count = 0; 4062 4063 if (Use->Element != NULL) 4064 { 4065 midl_user_free(Use->Element); 4066 Use->Element = NULL; 4067 } 4068 4069 Use->Count = 0; 4070 } 4071 4072 RtlReleaseResource(&SampResource); 4073 4074 return Status; 4075 } 4076 4077 4078 /* Function 19 */ 4079 NTSTATUS 4080 NTAPI 4081 SamrOpenGroup(IN SAMPR_HANDLE DomainHandle, 4082 IN ACCESS_MASK DesiredAccess, 4083 IN unsigned long GroupId, 4084 OUT SAMPR_HANDLE *GroupHandle) 4085 { 4086 PSAM_DB_OBJECT DomainObject; 4087 PSAM_DB_OBJECT GroupObject; 4088 WCHAR szRid[9]; 4089 NTSTATUS Status; 4090 4091 TRACE("SamrOpenGroup(%p %lx %lx %p)\n", 4092 DomainHandle, DesiredAccess, GroupId, GroupHandle); 4093 4094 /* Map generic access rights */ 4095 RtlMapGenericMask(&DesiredAccess, 4096 &GroupMapping); 4097 4098 RtlAcquireResourceShared(&SampResource, 4099 TRUE); 4100 4101 /* Validate the domain handle */ 4102 Status = SampValidateDbObject(DomainHandle, 4103 SamDbDomainObject, 4104 DOMAIN_LOOKUP, 4105 &DomainObject); 4106 if (!NT_SUCCESS(Status)) 4107 { 4108 TRACE("failed with status 0x%08lx\n", Status); 4109 goto done; 4110 } 4111 4112 /* Convert the RID into a string (hex) */ 4113 swprintf(szRid, L"%08lX", GroupId); 4114 4115 /* Create the group object */ 4116 Status = SampOpenDbObject(DomainObject, 4117 L"Groups", 4118 szRid, 4119 GroupId, 4120 SamDbGroupObject, 4121 DesiredAccess, 4122 &GroupObject); 4123 if (!NT_SUCCESS(Status)) 4124 { 4125 TRACE("failed with status 0x%08lx\n", Status); 4126 goto done; 4127 } 4128 4129 *GroupHandle = (SAMPR_HANDLE)GroupObject; 4130 4131 done: 4132 RtlReleaseResource(&SampResource); 4133 4134 return Status; 4135 } 4136 4137 4138 static NTSTATUS 4139 SampQueryGroupGeneral(PSAM_DB_OBJECT GroupObject, 4140 PSAMPR_GROUP_INFO_BUFFER *Buffer) 4141 { 4142 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL; 4143 SAM_GROUP_FIXED_DATA FixedData; 4144 ULONG MembersLength = 0; 4145 ULONG Length = 0; 4146 NTSTATUS Status; 4147 4148 *Buffer = NULL; 4149 4150 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER)); 4151 if (InfoBuffer == NULL) 4152 return STATUS_INSUFFICIENT_RESOURCES; 4153 4154 Status = SampGetObjectAttributeString(GroupObject, 4155 L"Name", 4156 &InfoBuffer->General.Name); 4157 if (!NT_SUCCESS(Status)) 4158 { 4159 TRACE("Status 0x%08lx\n", Status); 4160 goto done; 4161 } 4162 4163 Status = SampGetObjectAttributeString(GroupObject, 4164 L"AdminComment", 4165 &InfoBuffer->General.AdminComment); 4166 if (!NT_SUCCESS(Status)) 4167 { 4168 TRACE("Status 0x%08lx\n", Status); 4169 goto done; 4170 } 4171 4172 Length = sizeof(SAM_GROUP_FIXED_DATA); 4173 Status = SampGetObjectAttribute(GroupObject, 4174 L"F", 4175 NULL, 4176 (PVOID)&FixedData, 4177 &Length); 4178 if (!NT_SUCCESS(Status)) 4179 { 4180 TRACE("Status 0x%08lx\n", Status); 4181 goto done; 4182 } 4183 4184 InfoBuffer->General.Attributes = FixedData.Attributes; 4185 4186 Status = SampGetObjectAttribute(GroupObject, 4187 L"Members", 4188 NULL, 4189 NULL, 4190 &MembersLength); 4191 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 4192 { 4193 TRACE("Status 0x%08lx\n", Status); 4194 goto done; 4195 } 4196 4197 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 4198 { 4199 InfoBuffer->General.MemberCount = 0; 4200 Status = STATUS_SUCCESS; 4201 } 4202 else 4203 { 4204 InfoBuffer->General.MemberCount = MembersLength / sizeof(ULONG); 4205 } 4206 4207 *Buffer = InfoBuffer; 4208 4209 done: 4210 if (!NT_SUCCESS(Status)) 4211 { 4212 if (InfoBuffer != NULL) 4213 { 4214 if (InfoBuffer->General.Name.Buffer != NULL) 4215 midl_user_free(InfoBuffer->General.Name.Buffer); 4216 4217 if (InfoBuffer->General.AdminComment.Buffer != NULL) 4218 midl_user_free(InfoBuffer->General.AdminComment.Buffer); 4219 4220 midl_user_free(InfoBuffer); 4221 } 4222 } 4223 4224 return Status; 4225 } 4226 4227 4228 static NTSTATUS 4229 SampQueryGroupName(PSAM_DB_OBJECT GroupObject, 4230 PSAMPR_GROUP_INFO_BUFFER *Buffer) 4231 { 4232 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL; 4233 NTSTATUS Status; 4234 4235 *Buffer = NULL; 4236 4237 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER)); 4238 if (InfoBuffer == NULL) 4239 return STATUS_INSUFFICIENT_RESOURCES; 4240 4241 Status = SampGetObjectAttributeString(GroupObject, 4242 L"Name", 4243 &InfoBuffer->Name.Name); 4244 if (!NT_SUCCESS(Status)) 4245 { 4246 TRACE("Status 0x%08lx\n", Status); 4247 goto done; 4248 } 4249 4250 *Buffer = InfoBuffer; 4251 4252 done: 4253 if (!NT_SUCCESS(Status)) 4254 { 4255 if (InfoBuffer != NULL) 4256 { 4257 if (InfoBuffer->Name.Name.Buffer != NULL) 4258 midl_user_free(InfoBuffer->Name.Name.Buffer); 4259 4260 midl_user_free(InfoBuffer); 4261 } 4262 } 4263 4264 return Status; 4265 } 4266 4267 4268 static NTSTATUS 4269 SampQueryGroupAttribute(PSAM_DB_OBJECT GroupObject, 4270 PSAMPR_GROUP_INFO_BUFFER *Buffer) 4271 { 4272 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL; 4273 SAM_GROUP_FIXED_DATA FixedData; 4274 ULONG Length = 0; 4275 NTSTATUS Status; 4276 4277 *Buffer = NULL; 4278 4279 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER)); 4280 if (InfoBuffer == NULL) 4281 return STATUS_INSUFFICIENT_RESOURCES; 4282 4283 Length = sizeof(SAM_GROUP_FIXED_DATA); 4284 Status = SampGetObjectAttribute(GroupObject, 4285 L"F", 4286 NULL, 4287 (PVOID)&FixedData, 4288 &Length); 4289 if (!NT_SUCCESS(Status)) 4290 { 4291 TRACE("Status 0x%08lx\n", Status); 4292 goto done; 4293 } 4294 4295 InfoBuffer->Attribute.Attributes = FixedData.Attributes; 4296 4297 *Buffer = InfoBuffer; 4298 4299 done: 4300 if (!NT_SUCCESS(Status)) 4301 { 4302 if (InfoBuffer != NULL) 4303 { 4304 midl_user_free(InfoBuffer); 4305 } 4306 } 4307 4308 return Status; 4309 } 4310 4311 4312 static NTSTATUS 4313 SampQueryGroupAdminComment(PSAM_DB_OBJECT GroupObject, 4314 PSAMPR_GROUP_INFO_BUFFER *Buffer) 4315 { 4316 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL; 4317 NTSTATUS Status; 4318 4319 *Buffer = NULL; 4320 4321 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER)); 4322 if (InfoBuffer == NULL) 4323 return STATUS_INSUFFICIENT_RESOURCES; 4324 4325 Status = SampGetObjectAttributeString(GroupObject, 4326 L"AdminComment", 4327 &InfoBuffer->AdminComment.AdminComment); 4328 if (!NT_SUCCESS(Status)) 4329 { 4330 TRACE("Status 0x%08lx\n", Status); 4331 goto done; 4332 } 4333 4334 *Buffer = InfoBuffer; 4335 4336 done: 4337 if (!NT_SUCCESS(Status)) 4338 { 4339 if (InfoBuffer != NULL) 4340 { 4341 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL) 4342 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer); 4343 4344 midl_user_free(InfoBuffer); 4345 } 4346 } 4347 4348 return Status; 4349 } 4350 4351 4352 /* Function 20 */ 4353 NTSTATUS 4354 NTAPI 4355 SamrQueryInformationGroup(IN SAMPR_HANDLE GroupHandle, 4356 IN GROUP_INFORMATION_CLASS GroupInformationClass, 4357 OUT PSAMPR_GROUP_INFO_BUFFER *Buffer) 4358 { 4359 PSAM_DB_OBJECT GroupObject; 4360 NTSTATUS Status; 4361 4362 TRACE("SamrQueryInformationGroup(%p %lu %p)\n", 4363 GroupHandle, GroupInformationClass, Buffer); 4364 4365 RtlAcquireResourceShared(&SampResource, 4366 TRUE); 4367 4368 /* Validate the group handle */ 4369 Status = SampValidateDbObject(GroupHandle, 4370 SamDbGroupObject, 4371 GROUP_READ_INFORMATION, 4372 &GroupObject); 4373 if (!NT_SUCCESS(Status)) 4374 goto done; 4375 4376 switch (GroupInformationClass) 4377 { 4378 case GroupGeneralInformation: 4379 Status = SampQueryGroupGeneral(GroupObject, 4380 Buffer); 4381 break; 4382 4383 case GroupNameInformation: 4384 Status = SampQueryGroupName(GroupObject, 4385 Buffer); 4386 break; 4387 4388 case GroupAttributeInformation: 4389 Status = SampQueryGroupAttribute(GroupObject, 4390 Buffer); 4391 break; 4392 4393 case GroupAdminCommentInformation: 4394 Status = SampQueryGroupAdminComment(GroupObject, 4395 Buffer); 4396 break; 4397 4398 default: 4399 Status = STATUS_INVALID_INFO_CLASS; 4400 break; 4401 } 4402 4403 done: 4404 RtlReleaseResource(&SampResource); 4405 4406 return Status; 4407 } 4408 4409 4410 static NTSTATUS 4411 SampSetGroupName(PSAM_DB_OBJECT GroupObject, 4412 PSAMPR_GROUP_INFO_BUFFER Buffer) 4413 { 4414 UNICODE_STRING OldGroupName = {0, 0, NULL}; 4415 UNICODE_STRING NewGroupName; 4416 NTSTATUS Status; 4417 4418 Status = SampGetObjectAttributeString(GroupObject, 4419 L"Name", 4420 (PRPC_UNICODE_STRING)&OldGroupName); 4421 if (!NT_SUCCESS(Status)) 4422 { 4423 TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status); 4424 goto done; 4425 } 4426 4427 /* Check the new account name */ 4428 Status = SampCheckAccountName(&Buffer->Name.Name, 256); 4429 if (!NT_SUCCESS(Status)) 4430 { 4431 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 4432 return Status; 4433 } 4434 4435 NewGroupName.Length = Buffer->Name.Name.Length; 4436 NewGroupName.MaximumLength = Buffer->Name.Name.MaximumLength; 4437 NewGroupName.Buffer = Buffer->Name.Name.Buffer; 4438 4439 if (!RtlEqualUnicodeString(&OldGroupName, &NewGroupName, TRUE)) 4440 { 4441 Status = SampCheckAccountNameInDomain(GroupObject->ParentObject, 4442 NewGroupName.Buffer); 4443 if (!NT_SUCCESS(Status)) 4444 { 4445 TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n", 4446 NewGroupName.Buffer, Status); 4447 goto done; 4448 } 4449 } 4450 4451 Status = SampSetAccountNameInDomain(GroupObject->ParentObject, 4452 L"Groups", 4453 NewGroupName.Buffer, 4454 GroupObject->RelativeId); 4455 if (!NT_SUCCESS(Status)) 4456 { 4457 TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status); 4458 goto done; 4459 } 4460 4461 Status = SampRemoveAccountNameFromDomain(GroupObject->ParentObject, 4462 L"Groups", 4463 OldGroupName.Buffer); 4464 if (!NT_SUCCESS(Status)) 4465 { 4466 TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status); 4467 goto done; 4468 } 4469 4470 Status = SampSetObjectAttributeString(GroupObject, 4471 L"Name", 4472 (PRPC_UNICODE_STRING)&NewGroupName); 4473 if (!NT_SUCCESS(Status)) 4474 { 4475 TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status); 4476 } 4477 4478 done: 4479 if (OldGroupName.Buffer != NULL) 4480 midl_user_free(OldGroupName.Buffer); 4481 4482 return Status; 4483 } 4484 4485 4486 static NTSTATUS 4487 SampSetGroupAttribute(PSAM_DB_OBJECT GroupObject, 4488 PSAMPR_GROUP_INFO_BUFFER Buffer) 4489 { 4490 SAM_GROUP_FIXED_DATA FixedData; 4491 ULONG Length = 0; 4492 NTSTATUS Status; 4493 4494 Length = sizeof(SAM_GROUP_FIXED_DATA); 4495 Status = SampGetObjectAttribute(GroupObject, 4496 L"F", 4497 NULL, 4498 (PVOID)&FixedData, 4499 &Length); 4500 if (!NT_SUCCESS(Status)) 4501 goto done; 4502 4503 FixedData.Attributes = Buffer->Attribute.Attributes; 4504 4505 Status = SampSetObjectAttribute(GroupObject, 4506 L"F", 4507 REG_BINARY, 4508 &FixedData, 4509 Length); 4510 4511 done: 4512 return Status; 4513 } 4514 4515 4516 /* Function 21 */ 4517 NTSTATUS 4518 NTAPI 4519 SamrSetInformationGroup(IN SAMPR_HANDLE GroupHandle, 4520 IN GROUP_INFORMATION_CLASS GroupInformationClass, 4521 IN PSAMPR_GROUP_INFO_BUFFER Buffer) 4522 { 4523 PSAM_DB_OBJECT GroupObject; 4524 NTSTATUS Status; 4525 4526 TRACE("SamrSetInformationGroup(%p %lu %p)\n", 4527 GroupHandle, GroupInformationClass, Buffer); 4528 4529 RtlAcquireResourceExclusive(&SampResource, 4530 TRUE); 4531 4532 /* Validate the group handle */ 4533 Status = SampValidateDbObject(GroupHandle, 4534 SamDbGroupObject, 4535 GROUP_WRITE_ACCOUNT, 4536 &GroupObject); 4537 if (!NT_SUCCESS(Status)) 4538 goto done; 4539 4540 switch (GroupInformationClass) 4541 { 4542 case GroupNameInformation: 4543 Status = SampSetGroupName(GroupObject, 4544 Buffer); 4545 break; 4546 4547 case GroupAttributeInformation: 4548 Status = SampSetGroupAttribute(GroupObject, 4549 Buffer); 4550 break; 4551 4552 case GroupAdminCommentInformation: 4553 Status = SampSetObjectAttributeString(GroupObject, 4554 L"AdminComment", 4555 &Buffer->AdminComment.AdminComment); 4556 break; 4557 4558 default: 4559 Status = STATUS_INVALID_INFO_CLASS; 4560 break; 4561 } 4562 4563 done: 4564 RtlReleaseResource(&SampResource); 4565 4566 return Status; 4567 } 4568 4569 4570 /* Function 22 */ 4571 NTSTATUS 4572 NTAPI 4573 SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle, 4574 IN unsigned long MemberId, 4575 IN unsigned long Attributes) 4576 { 4577 PSAM_DB_OBJECT GroupObject; 4578 PSAM_DB_OBJECT UserObject = NULL; 4579 NTSTATUS Status; 4580 4581 TRACE("SamrAddMemberToGroup(%p %lu %lx)\n", 4582 GroupHandle, MemberId, Attributes); 4583 4584 RtlAcquireResourceExclusive(&SampResource, 4585 TRUE); 4586 4587 /* Validate the group handle */ 4588 Status = SampValidateDbObject(GroupHandle, 4589 SamDbGroupObject, 4590 GROUP_ADD_MEMBER, 4591 &GroupObject); 4592 if (!NT_SUCCESS(Status)) 4593 goto done; 4594 4595 /* Open the user object in the same domain */ 4596 Status = SampOpenUserObject(GroupObject->ParentObject, 4597 MemberId, 4598 0, 4599 &UserObject); 4600 if (!NT_SUCCESS(Status)) 4601 { 4602 TRACE("SampOpenUserObject() failed (Status 0x%08lx)\n", Status); 4603 goto done; 4604 } 4605 4606 /* Add group membership to the user object */ 4607 Status = SampAddGroupMembershipToUser(UserObject, 4608 GroupObject->RelativeId, 4609 Attributes); 4610 if (!NT_SUCCESS(Status)) 4611 { 4612 TRACE("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status); 4613 goto done; 4614 } 4615 4616 /* Add the member to the group object */ 4617 Status = SampAddMemberToGroup(GroupObject, 4618 MemberId); 4619 if (!NT_SUCCESS(Status)) 4620 { 4621 TRACE("SampAddMemberToGroup() failed (Status 0x%08lx)\n", Status); 4622 } 4623 4624 done: 4625 if (UserObject) 4626 SampCloseDbObject(UserObject); 4627 4628 RtlReleaseResource(&SampResource); 4629 4630 return Status; 4631 } 4632 4633 4634 /* Function 23 */ 4635 NTSTATUS 4636 NTAPI 4637 SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle) 4638 { 4639 PSAM_DB_OBJECT GroupObject; 4640 ULONG Length = 0; 4641 NTSTATUS Status; 4642 4643 TRACE("SamrDeleteGroup(%p)\n", GroupHandle); 4644 4645 RtlAcquireResourceExclusive(&SampResource, 4646 TRUE); 4647 4648 /* Validate the group handle */ 4649 Status = SampValidateDbObject(*GroupHandle, 4650 SamDbGroupObject, 4651 DELETE, 4652 &GroupObject); 4653 if (!NT_SUCCESS(Status)) 4654 { 4655 TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status); 4656 goto done; 4657 } 4658 4659 /* Fail, if the group is built-in */ 4660 if (GroupObject->RelativeId < 1000) 4661 { 4662 TRACE("You can not delete a special account!\n"); 4663 Status = STATUS_SPECIAL_ACCOUNT; 4664 goto done; 4665 } 4666 4667 /* Get the length of the Members attribute */ 4668 SampGetObjectAttribute(GroupObject, 4669 L"Members", 4670 NULL, 4671 NULL, 4672 &Length); 4673 4674 /* Fail, if the group has members */ 4675 if (Length != 0) 4676 { 4677 TRACE("There are still members in the group!\n"); 4678 Status = STATUS_MEMBER_IN_GROUP; 4679 goto done; 4680 } 4681 4682 /* FIXME: Remove the group from all aliases */ 4683 4684 /* Delete the group from the database */ 4685 Status = SampDeleteAccountDbObject(GroupObject); 4686 if (!NT_SUCCESS(Status)) 4687 { 4688 TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status); 4689 goto done; 4690 } 4691 4692 /* Invalidate the handle */ 4693 *GroupHandle = NULL; 4694 4695 done: 4696 RtlReleaseResource(&SampResource); 4697 4698 return Status; 4699 } 4700 4701 4702 /* Function 24 */ 4703 NTSTATUS 4704 NTAPI 4705 SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle, 4706 IN unsigned long MemberId) 4707 { 4708 PSAM_DB_OBJECT GroupObject; 4709 PSAM_DB_OBJECT UserObject = NULL; 4710 NTSTATUS Status; 4711 4712 TRACE("SamrRemoveMemberFromGroup(%p %lu)\n", 4713 GroupHandle, MemberId); 4714 4715 RtlAcquireResourceExclusive(&SampResource, 4716 TRUE); 4717 4718 /* Validate the group handle */ 4719 Status = SampValidateDbObject(GroupHandle, 4720 SamDbGroupObject, 4721 GROUP_REMOVE_MEMBER, 4722 &GroupObject); 4723 if (!NT_SUCCESS(Status)) 4724 goto done; 4725 4726 /* Open the user object in the same domain */ 4727 Status = SampOpenUserObject(GroupObject->ParentObject, 4728 MemberId, 4729 0, 4730 &UserObject); 4731 if (!NT_SUCCESS(Status)) 4732 { 4733 ERR("SampOpenUserObject() failed (Status 0x%08lx)\n", Status); 4734 goto done; 4735 } 4736 4737 /* Remove group membership from the user object */ 4738 Status = SampRemoveGroupMembershipFromUser(UserObject, 4739 GroupObject->RelativeId); 4740 if (!NT_SUCCESS(Status)) 4741 { 4742 ERR("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status); 4743 goto done; 4744 } 4745 4746 /* Remove the member from the group object */ 4747 Status = SampRemoveMemberFromGroup(GroupObject, 4748 MemberId); 4749 if (!NT_SUCCESS(Status)) 4750 { 4751 ERR("SampRemoveMemberFromGroup() failed (Status 0x%08lx)\n", Status); 4752 } 4753 4754 done: 4755 if (UserObject) 4756 SampCloseDbObject(UserObject); 4757 4758 RtlReleaseResource(&SampResource); 4759 4760 return Status; 4761 } 4762 4763 4764 /* Function 25 */ 4765 NTSTATUS 4766 NTAPI 4767 SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle, 4768 OUT PSAMPR_GET_MEMBERS_BUFFER *Members) 4769 { 4770 PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL; 4771 PSAM_DB_OBJECT GroupObject; 4772 ULONG Length = 0; 4773 ULONG i; 4774 NTSTATUS Status; 4775 4776 TRACE("SamrGetMembersInGroup(%p %p)\n", 4777 GroupHandle, Members); 4778 4779 RtlAcquireResourceShared(&SampResource, 4780 TRUE); 4781 4782 /* Validate the group handle */ 4783 Status = SampValidateDbObject(GroupHandle, 4784 SamDbGroupObject, 4785 GROUP_LIST_MEMBERS, 4786 &GroupObject); 4787 if (!NT_SUCCESS(Status)) 4788 goto done; 4789 4790 MembersBuffer = midl_user_allocate(sizeof(SAMPR_GET_MEMBERS_BUFFER)); 4791 if (MembersBuffer == NULL) 4792 { 4793 Status = STATUS_INSUFFICIENT_RESOURCES; 4794 goto done; 4795 } 4796 4797 SampGetObjectAttribute(GroupObject, 4798 L"Members", 4799 NULL, 4800 NULL, 4801 &Length); 4802 4803 if (Length == 0) 4804 { 4805 MembersBuffer->MemberCount = 0; 4806 MembersBuffer->Members = NULL; 4807 MembersBuffer->Attributes = NULL; 4808 4809 *Members = MembersBuffer; 4810 4811 Status = STATUS_SUCCESS; 4812 goto done; 4813 } 4814 4815 MembersBuffer->Members = midl_user_allocate(Length); 4816 if (MembersBuffer->Members == NULL) 4817 { 4818 Status = STATUS_INSUFFICIENT_RESOURCES; 4819 goto done; 4820 } 4821 4822 MembersBuffer->Attributes = midl_user_allocate(Length); 4823 if (MembersBuffer->Attributes == NULL) 4824 { 4825 Status = STATUS_INSUFFICIENT_RESOURCES; 4826 goto done; 4827 } 4828 4829 Status = SampGetObjectAttribute(GroupObject, 4830 L"Members", 4831 NULL, 4832 MembersBuffer->Members, 4833 &Length); 4834 if (!NT_SUCCESS(Status)) 4835 { 4836 TRACE("SampGetObjectAttributes() failed (Status 0x%08lx)\n", Status); 4837 goto done; 4838 } 4839 4840 MembersBuffer->MemberCount = Length / sizeof(ULONG); 4841 4842 for (i = 0; i < MembersBuffer->MemberCount; i++) 4843 { 4844 Status = SampGetUserGroupAttributes(GroupObject->ParentObject, 4845 MembersBuffer->Members[i], 4846 GroupObject->RelativeId, 4847 &(MembersBuffer->Attributes[i])); 4848 if (!NT_SUCCESS(Status)) 4849 { 4850 TRACE("SampGetUserGroupAttributes() failed (Status 0x%08lx)\n", Status); 4851 goto done; 4852 } 4853 } 4854 4855 *Members = MembersBuffer; 4856 4857 done: 4858 if (!NT_SUCCESS(Status)) 4859 { 4860 if (MembersBuffer != NULL) 4861 { 4862 if (MembersBuffer->Members != NULL) 4863 midl_user_free(MembersBuffer->Members); 4864 4865 if (MembersBuffer->Attributes != NULL) 4866 midl_user_free(MembersBuffer->Attributes); 4867 4868 midl_user_free(MembersBuffer); 4869 } 4870 } 4871 4872 RtlReleaseResource(&SampResource); 4873 4874 return Status; 4875 } 4876 4877 4878 /* Function 26 */ 4879 NTSTATUS 4880 NTAPI 4881 SamrSetMemberAttributesOfGroup(IN SAMPR_HANDLE GroupHandle, 4882 IN unsigned long MemberId, 4883 IN unsigned long Attributes) 4884 { 4885 PSAM_DB_OBJECT GroupObject; 4886 NTSTATUS Status; 4887 4888 TRACE("SamrSetMemberAttributesOfGroup(%p %lu %lx)\n", 4889 GroupHandle, MemberId, Attributes); 4890 4891 RtlAcquireResourceExclusive(&SampResource, 4892 TRUE); 4893 4894 /* Validate the group handle */ 4895 Status = SampValidateDbObject(GroupHandle, 4896 SamDbGroupObject, 4897 GROUP_ADD_MEMBER, 4898 &GroupObject); 4899 if (!NT_SUCCESS(Status)) 4900 { 4901 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 4902 goto done; 4903 } 4904 4905 Status = SampSetUserGroupAttributes(GroupObject->ParentObject, 4906 MemberId, 4907 GroupObject->RelativeId, 4908 Attributes); 4909 if (!NT_SUCCESS(Status)) 4910 { 4911 TRACE("SampSetUserGroupAttributes failed with status 0x%08lx\n", Status); 4912 } 4913 4914 done: 4915 RtlReleaseResource(&SampResource); 4916 4917 return Status; 4918 } 4919 4920 4921 /* Function 27 */ 4922 NTSTATUS 4923 NTAPI 4924 SamrOpenAlias(IN SAMPR_HANDLE DomainHandle, 4925 IN ACCESS_MASK DesiredAccess, 4926 IN ULONG AliasId, 4927 OUT SAMPR_HANDLE *AliasHandle) 4928 { 4929 PSAM_DB_OBJECT DomainObject; 4930 PSAM_DB_OBJECT AliasObject; 4931 WCHAR szRid[9]; 4932 NTSTATUS Status; 4933 4934 TRACE("SamrOpenAlias(%p %lx %lx %p)\n", 4935 DomainHandle, DesiredAccess, AliasId, AliasHandle); 4936 4937 /* Map generic access rights */ 4938 RtlMapGenericMask(&DesiredAccess, 4939 &AliasMapping); 4940 4941 RtlAcquireResourceShared(&SampResource, 4942 TRUE); 4943 4944 /* Validate the domain handle */ 4945 Status = SampValidateDbObject(DomainHandle, 4946 SamDbDomainObject, 4947 DOMAIN_LOOKUP, 4948 &DomainObject); 4949 if (!NT_SUCCESS(Status)) 4950 { 4951 TRACE("failed with status 0x%08lx\n", Status); 4952 goto done; 4953 } 4954 4955 /* Convert the RID into a string (hex) */ 4956 swprintf(szRid, L"%08lX", AliasId); 4957 4958 /* Create the alias object */ 4959 Status = SampOpenDbObject(DomainObject, 4960 L"Aliases", 4961 szRid, 4962 AliasId, 4963 SamDbAliasObject, 4964 DesiredAccess, 4965 &AliasObject); 4966 if (!NT_SUCCESS(Status)) 4967 { 4968 TRACE("failed with status 0x%08lx\n", Status); 4969 goto done; 4970 } 4971 4972 *AliasHandle = (SAMPR_HANDLE)AliasObject; 4973 4974 done: 4975 RtlReleaseResource(&SampResource); 4976 4977 return Status; 4978 } 4979 4980 4981 static NTSTATUS 4982 SampQueryAliasGeneral(PSAM_DB_OBJECT AliasObject, 4983 PSAMPR_ALIAS_INFO_BUFFER *Buffer) 4984 { 4985 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL; 4986 HANDLE MembersKeyHandle = NULL; 4987 NTSTATUS Status; 4988 4989 *Buffer = NULL; 4990 4991 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER)); 4992 if (InfoBuffer == NULL) 4993 return STATUS_INSUFFICIENT_RESOURCES; 4994 4995 Status = SampGetObjectAttributeString(AliasObject, 4996 L"Name", 4997 &InfoBuffer->General.Name); 4998 if (!NT_SUCCESS(Status)) 4999 { 5000 TRACE("Status 0x%08lx\n", Status); 5001 goto done; 5002 } 5003 5004 Status = SampGetObjectAttributeString(AliasObject, 5005 L"Description", 5006 &InfoBuffer->General.AdminComment); 5007 if (!NT_SUCCESS(Status)) 5008 { 5009 TRACE("Status 0x%08lx\n", Status); 5010 goto done; 5011 } 5012 5013 /* Open the Members subkey */ 5014 Status = SampRegOpenKey(AliasObject->KeyHandle, 5015 L"Members", 5016 KEY_READ, 5017 &MembersKeyHandle); 5018 if (NT_SUCCESS(Status)) 5019 { 5020 /* Retrieve the number of members of the alias */ 5021 Status = SampRegQueryKeyInfo(MembersKeyHandle, 5022 NULL, 5023 &InfoBuffer->General.MemberCount); 5024 if (!NT_SUCCESS(Status)) 5025 { 5026 TRACE("Status 0x%08lx\n", Status); 5027 goto done; 5028 } 5029 } 5030 else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 5031 { 5032 InfoBuffer->General.MemberCount = 0; 5033 Status = STATUS_SUCCESS; 5034 } 5035 else 5036 { 5037 TRACE("Status 0x%08lx\n", Status); 5038 goto done; 5039 } 5040 5041 *Buffer = InfoBuffer; 5042 5043 done: 5044 SampRegCloseKey(&MembersKeyHandle); 5045 5046 if (!NT_SUCCESS(Status)) 5047 { 5048 if (InfoBuffer != NULL) 5049 { 5050 if (InfoBuffer->General.Name.Buffer != NULL) 5051 midl_user_free(InfoBuffer->General.Name.Buffer); 5052 5053 if (InfoBuffer->General.AdminComment.Buffer != NULL) 5054 midl_user_free(InfoBuffer->General.AdminComment.Buffer); 5055 5056 midl_user_free(InfoBuffer); 5057 } 5058 } 5059 5060 return Status; 5061 } 5062 5063 5064 static NTSTATUS 5065 SampQueryAliasName(PSAM_DB_OBJECT AliasObject, 5066 PSAMPR_ALIAS_INFO_BUFFER *Buffer) 5067 { 5068 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL; 5069 NTSTATUS Status; 5070 5071 *Buffer = NULL; 5072 5073 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER)); 5074 if (InfoBuffer == NULL) 5075 return STATUS_INSUFFICIENT_RESOURCES; 5076 5077 Status = SampGetObjectAttributeString(AliasObject, 5078 L"Name", 5079 &InfoBuffer->Name.Name); 5080 if (!NT_SUCCESS(Status)) 5081 { 5082 TRACE("Status 0x%08lx\n", Status); 5083 goto done; 5084 } 5085 5086 *Buffer = InfoBuffer; 5087 5088 done: 5089 if (!NT_SUCCESS(Status)) 5090 { 5091 if (InfoBuffer != NULL) 5092 { 5093 if (InfoBuffer->Name.Name.Buffer != NULL) 5094 midl_user_free(InfoBuffer->Name.Name.Buffer); 5095 5096 midl_user_free(InfoBuffer); 5097 } 5098 } 5099 5100 return Status; 5101 } 5102 5103 5104 static NTSTATUS 5105 SampQueryAliasAdminComment(PSAM_DB_OBJECT AliasObject, 5106 PSAMPR_ALIAS_INFO_BUFFER *Buffer) 5107 { 5108 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL; 5109 NTSTATUS Status; 5110 5111 *Buffer = NULL; 5112 5113 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER)); 5114 if (InfoBuffer == NULL) 5115 return STATUS_INSUFFICIENT_RESOURCES; 5116 5117 Status = SampGetObjectAttributeString(AliasObject, 5118 L"Description", 5119 &InfoBuffer->AdminComment.AdminComment); 5120 if (!NT_SUCCESS(Status)) 5121 { 5122 TRACE("Status 0x%08lx\n", Status); 5123 goto done; 5124 } 5125 5126 *Buffer = InfoBuffer; 5127 5128 done: 5129 if (!NT_SUCCESS(Status)) 5130 { 5131 if (InfoBuffer != NULL) 5132 { 5133 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL) 5134 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer); 5135 5136 midl_user_free(InfoBuffer); 5137 } 5138 } 5139 5140 return Status; 5141 } 5142 5143 5144 /* Function 28 */ 5145 NTSTATUS 5146 NTAPI 5147 SamrQueryInformationAlias(IN SAMPR_HANDLE AliasHandle, 5148 IN ALIAS_INFORMATION_CLASS AliasInformationClass, 5149 OUT PSAMPR_ALIAS_INFO_BUFFER *Buffer) 5150 { 5151 PSAM_DB_OBJECT AliasObject; 5152 NTSTATUS Status; 5153 5154 TRACE("SamrQueryInformationAlias(%p %lu %p)\n", 5155 AliasHandle, AliasInformationClass, Buffer); 5156 5157 RtlAcquireResourceShared(&SampResource, 5158 TRUE); 5159 5160 /* Validate the alias handle */ 5161 Status = SampValidateDbObject(AliasHandle, 5162 SamDbAliasObject, 5163 ALIAS_READ_INFORMATION, 5164 &AliasObject); 5165 if (!NT_SUCCESS(Status)) 5166 goto done; 5167 5168 switch (AliasInformationClass) 5169 { 5170 case AliasGeneralInformation: 5171 Status = SampQueryAliasGeneral(AliasObject, 5172 Buffer); 5173 break; 5174 5175 case AliasNameInformation: 5176 Status = SampQueryAliasName(AliasObject, 5177 Buffer); 5178 break; 5179 5180 case AliasAdminCommentInformation: 5181 Status = SampQueryAliasAdminComment(AliasObject, 5182 Buffer); 5183 break; 5184 5185 default: 5186 Status = STATUS_INVALID_INFO_CLASS; 5187 break; 5188 } 5189 5190 done: 5191 RtlReleaseResource(&SampResource); 5192 5193 return Status; 5194 } 5195 5196 5197 static NTSTATUS 5198 SampSetAliasName(PSAM_DB_OBJECT AliasObject, 5199 PSAMPR_ALIAS_INFO_BUFFER Buffer) 5200 { 5201 UNICODE_STRING OldAliasName = {0, 0, NULL}; 5202 UNICODE_STRING NewAliasName; 5203 NTSTATUS Status; 5204 5205 Status = SampGetObjectAttributeString(AliasObject, 5206 L"Name", 5207 (PRPC_UNICODE_STRING)&OldAliasName); 5208 if (!NT_SUCCESS(Status)) 5209 { 5210 TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status); 5211 goto done; 5212 } 5213 5214 /* Check the new account name */ 5215 Status = SampCheckAccountName(&Buffer->Name.Name, 256); 5216 if (!NT_SUCCESS(Status)) 5217 { 5218 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 5219 return Status; 5220 } 5221 5222 NewAliasName.Length = Buffer->Name.Name.Length; 5223 NewAliasName.MaximumLength = Buffer->Name.Name.MaximumLength; 5224 NewAliasName.Buffer = Buffer->Name.Name.Buffer; 5225 5226 if (!RtlEqualUnicodeString(&OldAliasName, &NewAliasName, TRUE)) 5227 { 5228 Status = SampCheckAccountNameInDomain(AliasObject->ParentObject, 5229 NewAliasName.Buffer); 5230 if (!NT_SUCCESS(Status)) 5231 { 5232 TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n", 5233 NewAliasName.Buffer, Status); 5234 goto done; 5235 } 5236 } 5237 5238 Status = SampSetAccountNameInDomain(AliasObject->ParentObject, 5239 L"Aliases", 5240 NewAliasName.Buffer, 5241 AliasObject->RelativeId); 5242 if (!NT_SUCCESS(Status)) 5243 { 5244 TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status); 5245 goto done; 5246 } 5247 5248 Status = SampRemoveAccountNameFromDomain(AliasObject->ParentObject, 5249 L"Aliases", 5250 OldAliasName.Buffer); 5251 if (!NT_SUCCESS(Status)) 5252 { 5253 TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status); 5254 goto done; 5255 } 5256 5257 Status = SampSetObjectAttributeString(AliasObject, 5258 L"Name", 5259 (PRPC_UNICODE_STRING)&NewAliasName); 5260 if (!NT_SUCCESS(Status)) 5261 { 5262 TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status); 5263 } 5264 5265 done: 5266 if (OldAliasName.Buffer != NULL) 5267 midl_user_free(OldAliasName.Buffer); 5268 5269 return Status; 5270 } 5271 5272 5273 /* Function 29 */ 5274 NTSTATUS 5275 NTAPI 5276 SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle, 5277 IN ALIAS_INFORMATION_CLASS AliasInformationClass, 5278 IN PSAMPR_ALIAS_INFO_BUFFER Buffer) 5279 { 5280 PSAM_DB_OBJECT AliasObject; 5281 NTSTATUS Status; 5282 5283 TRACE("SamrSetInformationAlias(%p %lu %p)\n", 5284 AliasHandle, AliasInformationClass, Buffer); 5285 5286 RtlAcquireResourceExclusive(&SampResource, 5287 TRUE); 5288 5289 /* Validate the alias handle */ 5290 Status = SampValidateDbObject(AliasHandle, 5291 SamDbAliasObject, 5292 ALIAS_WRITE_ACCOUNT, 5293 &AliasObject); 5294 if (!NT_SUCCESS(Status)) 5295 goto done; 5296 5297 switch (AliasInformationClass) 5298 { 5299 case AliasNameInformation: 5300 Status = SampSetAliasName(AliasObject, 5301 Buffer); 5302 break; 5303 5304 case AliasAdminCommentInformation: 5305 Status = SampSetObjectAttributeString(AliasObject, 5306 L"Description", 5307 &Buffer->AdminComment.AdminComment); 5308 break; 5309 5310 default: 5311 Status = STATUS_INVALID_INFO_CLASS; 5312 break; 5313 } 5314 5315 done: 5316 RtlReleaseResource(&SampResource); 5317 5318 return Status; 5319 } 5320 5321 5322 /* Function 30 */ 5323 NTSTATUS 5324 NTAPI 5325 SamrDeleteAlias(IN OUT SAMPR_HANDLE *AliasHandle) 5326 { 5327 PSAM_DB_OBJECT AliasObject; 5328 NTSTATUS Status; 5329 5330 TRACE("SamrDeleteAlias(%p)\n", AliasHandle); 5331 5332 RtlAcquireResourceExclusive(&SampResource, 5333 TRUE); 5334 5335 /* Validate the alias handle */ 5336 Status = SampValidateDbObject(*AliasHandle, 5337 SamDbAliasObject, 5338 DELETE, 5339 &AliasObject); 5340 if (!NT_SUCCESS(Status)) 5341 { 5342 TRACE("SampValidateDbObject failed (Status 0x%08lx)\n", Status); 5343 goto done; 5344 } 5345 5346 /* Fail, if the alias is built-in */ 5347 if (AliasObject->RelativeId < 1000) 5348 { 5349 TRACE("You can not delete a special account!\n"); 5350 Status = STATUS_SPECIAL_ACCOUNT; 5351 goto done; 5352 } 5353 5354 /* Remove all members from the alias */ 5355 Status = SampRemoveAllMembersFromAlias(AliasObject); 5356 if (!NT_SUCCESS(Status)) 5357 { 5358 TRACE("SampRemoveAllMembersFromAlias() failed (Status 0x%08lx)\n", Status); 5359 goto done; 5360 } 5361 5362 /* Delete the alias from the database */ 5363 Status = SampDeleteAccountDbObject(AliasObject); 5364 if (!NT_SUCCESS(Status)) 5365 { 5366 TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status); 5367 goto done; 5368 } 5369 5370 /* Invalidate the handle */ 5371 *AliasHandle = NULL; 5372 5373 done: 5374 RtlReleaseResource(&SampResource); 5375 5376 return Status; 5377 } 5378 5379 5380 /* Function 31 */ 5381 NTSTATUS 5382 NTAPI 5383 SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle, 5384 IN PRPC_SID MemberId) 5385 { 5386 PSAM_DB_OBJECT AliasObject; 5387 NTSTATUS Status; 5388 5389 TRACE("SamrAddMemberToAlias(%p %p)\n", 5390 AliasHandle, MemberId); 5391 5392 RtlAcquireResourceExclusive(&SampResource, 5393 TRUE); 5394 5395 /* Validate the alias handle */ 5396 Status = SampValidateDbObject(AliasHandle, 5397 SamDbAliasObject, 5398 ALIAS_ADD_MEMBER, 5399 &AliasObject); 5400 if (!NT_SUCCESS(Status)) 5401 { 5402 TRACE("failed with status 0x%08lx\n", Status); 5403 goto done; 5404 } 5405 5406 Status = SampAddMemberToAlias(AliasObject, 5407 MemberId); 5408 if (!NT_SUCCESS(Status)) 5409 { 5410 TRACE("failed with status 0x%08lx\n", Status); 5411 } 5412 5413 done: 5414 RtlReleaseResource(&SampResource); 5415 5416 return Status; 5417 } 5418 5419 5420 /* Function 32 */ 5421 NTSTATUS 5422 NTAPI 5423 SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle, 5424 IN PRPC_SID MemberId) 5425 { 5426 PSAM_DB_OBJECT AliasObject; 5427 NTSTATUS Status; 5428 5429 TRACE("SamrRemoveMemberFromAlias(%p %p)\n", 5430 AliasHandle, MemberId); 5431 5432 RtlAcquireResourceExclusive(&SampResource, 5433 TRUE); 5434 5435 /* Validate the alias handle */ 5436 Status = SampValidateDbObject(AliasHandle, 5437 SamDbAliasObject, 5438 ALIAS_REMOVE_MEMBER, 5439 &AliasObject); 5440 if (!NT_SUCCESS(Status)) 5441 { 5442 TRACE("failed with status 0x%08lx\n", Status); 5443 goto done; 5444 } 5445 5446 Status = SampRemoveMemberFromAlias(AliasObject, 5447 MemberId); 5448 if (!NT_SUCCESS(Status)) 5449 { 5450 TRACE("failed with status 0x%08lx\n", Status); 5451 } 5452 5453 done: 5454 RtlReleaseResource(&SampResource); 5455 5456 return Status; 5457 } 5458 5459 5460 /* Function 33 */ 5461 NTSTATUS 5462 NTAPI 5463 SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle, 5464 OUT PSAMPR_PSID_ARRAY_OUT Members) 5465 { 5466 PSAM_DB_OBJECT AliasObject; 5467 PSAMPR_SID_INFORMATION MemberArray = NULL; 5468 ULONG MemberCount = 0; 5469 ULONG Index; 5470 NTSTATUS Status; 5471 5472 TRACE("SamrGetMembersInAlias(%p %p %p)\n", 5473 AliasHandle, Members); 5474 5475 RtlAcquireResourceShared(&SampResource, 5476 TRUE); 5477 5478 /* Validate the alias handle */ 5479 Status = SampValidateDbObject(AliasHandle, 5480 SamDbAliasObject, 5481 ALIAS_LIST_MEMBERS, 5482 &AliasObject); 5483 if (!NT_SUCCESS(Status)) 5484 { 5485 ERR("failed with status 0x%08lx\n", Status); 5486 goto done; 5487 } 5488 5489 Status = SampGetMembersInAlias(AliasObject, 5490 &MemberCount, 5491 &MemberArray); 5492 5493 /* Return the number of members and the member array */ 5494 if (NT_SUCCESS(Status)) 5495 { 5496 Members->Count = MemberCount; 5497 Members->Sids = MemberArray; 5498 } 5499 5500 done: 5501 /* Clean up the members array and the SID buffers if something failed */ 5502 if (!NT_SUCCESS(Status)) 5503 { 5504 if (MemberArray != NULL) 5505 { 5506 for (Index = 0; Index < MemberCount; Index++) 5507 { 5508 if (MemberArray[Index].SidPointer != NULL) 5509 midl_user_free(MemberArray[Index].SidPointer); 5510 } 5511 5512 midl_user_free(MemberArray); 5513 } 5514 } 5515 5516 RtlReleaseResource(&SampResource); 5517 5518 return Status; 5519 } 5520 5521 5522 /* Function 34 */ 5523 NTSTATUS 5524 NTAPI 5525 SamrOpenUser(IN SAMPR_HANDLE DomainHandle, 5526 IN ACCESS_MASK DesiredAccess, 5527 IN unsigned long UserId, 5528 OUT SAMPR_HANDLE *UserHandle) 5529 { 5530 PSAM_DB_OBJECT DomainObject; 5531 PSAM_DB_OBJECT UserObject; 5532 WCHAR szRid[9]; 5533 NTSTATUS Status; 5534 5535 TRACE("SamrOpenUser(%p %lx %lx %p)\n", 5536 DomainHandle, DesiredAccess, UserId, UserHandle); 5537 5538 /* Map generic access rights */ 5539 RtlMapGenericMask(&DesiredAccess, 5540 &UserMapping); 5541 5542 RtlAcquireResourceShared(&SampResource, 5543 TRUE); 5544 5545 /* Validate the domain handle */ 5546 Status = SampValidateDbObject(DomainHandle, 5547 SamDbDomainObject, 5548 DOMAIN_LOOKUP, 5549 &DomainObject); 5550 if (!NT_SUCCESS(Status)) 5551 { 5552 TRACE("failed with status 0x%08lx\n", Status); 5553 goto done; 5554 } 5555 5556 /* Convert the RID into a string (hex) */ 5557 swprintf(szRid, L"%08lX", UserId); 5558 5559 /* Create the user object */ 5560 Status = SampOpenDbObject(DomainObject, 5561 L"Users", 5562 szRid, 5563 UserId, 5564 SamDbUserObject, 5565 DesiredAccess, 5566 &UserObject); 5567 if (!NT_SUCCESS(Status)) 5568 { 5569 TRACE("failed with status 0x%08lx\n", Status); 5570 goto done; 5571 } 5572 5573 *UserHandle = (SAMPR_HANDLE)UserObject; 5574 5575 done: 5576 RtlReleaseResource(&SampResource); 5577 5578 return Status; 5579 } 5580 5581 5582 /* Function 35 */ 5583 NTSTATUS 5584 NTAPI 5585 SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle) 5586 { 5587 PSAM_DB_OBJECT UserObject; 5588 NTSTATUS Status; 5589 5590 TRACE("SamrDeleteUser(%p)\n", UserHandle); 5591 5592 RtlAcquireResourceExclusive(&SampResource, 5593 TRUE); 5594 5595 /* Validate the user handle */ 5596 Status = SampValidateDbObject(*UserHandle, 5597 SamDbUserObject, 5598 DELETE, 5599 &UserObject); 5600 if (!NT_SUCCESS(Status)) 5601 { 5602 TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status); 5603 goto done; 5604 } 5605 5606 /* Fail, if the user is built-in */ 5607 if (UserObject->RelativeId < 1000) 5608 { 5609 TRACE("You can not delete a special account!\n"); 5610 Status = STATUS_SPECIAL_ACCOUNT; 5611 goto done; 5612 } 5613 5614 /* Remove the user from all groups */ 5615 Status = SampRemoveUserFromAllGroups(UserObject); 5616 if (!NT_SUCCESS(Status)) 5617 { 5618 TRACE("SampRemoveUserFromAllGroups() failed (Status 0x%08lx)\n", Status); 5619 goto done; 5620 } 5621 5622 /* Remove the user from all aliases */ 5623 Status = SampRemoveUserFromAllAliases(UserObject); 5624 if (!NT_SUCCESS(Status)) 5625 { 5626 TRACE("SampRemoveUserFromAllAliases() failed (Status 0x%08lx)\n", Status); 5627 goto done; 5628 } 5629 5630 /* Delete the user from the database */ 5631 Status = SampDeleteAccountDbObject(UserObject); 5632 if (!NT_SUCCESS(Status)) 5633 { 5634 TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status); 5635 goto done; 5636 } 5637 5638 /* Invalidate the handle */ 5639 *UserHandle = NULL; 5640 5641 done: 5642 RtlReleaseResource(&SampResource); 5643 5644 return Status; 5645 } 5646 5647 5648 static 5649 NTSTATUS 5650 SampQueryUserGeneral(PSAM_DB_OBJECT UserObject, 5651 PSAMPR_USER_INFO_BUFFER *Buffer) 5652 { 5653 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 5654 SAM_USER_FIXED_DATA FixedData; 5655 ULONG Length = 0; 5656 NTSTATUS Status; 5657 5658 *Buffer = NULL; 5659 5660 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 5661 if (InfoBuffer == NULL) 5662 return STATUS_INSUFFICIENT_RESOURCES; 5663 5664 Length = sizeof(SAM_USER_FIXED_DATA); 5665 Status = SampGetObjectAttribute(UserObject, 5666 L"F", 5667 NULL, 5668 (PVOID)&FixedData, 5669 &Length); 5670 if (!NT_SUCCESS(Status)) 5671 goto done; 5672 5673 InfoBuffer->General.PrimaryGroupId = FixedData.PrimaryGroupId; 5674 5675 /* Get the Name string */ 5676 Status = SampGetObjectAttributeString(UserObject, 5677 L"Name", 5678 &InfoBuffer->General.UserName); 5679 if (!NT_SUCCESS(Status)) 5680 { 5681 TRACE("Status 0x%08lx\n", Status); 5682 goto done; 5683 } 5684 5685 /* Get the FullName string */ 5686 Status = SampGetObjectAttributeString(UserObject, 5687 L"FullName", 5688 &InfoBuffer->General.FullName); 5689 if (!NT_SUCCESS(Status)) 5690 { 5691 TRACE("Status 0x%08lx\n", Status); 5692 goto done; 5693 } 5694 5695 /* Get the AdminComment string */ 5696 Status = SampGetObjectAttributeString(UserObject, 5697 L"AdminComment", 5698 &InfoBuffer->General.AdminComment); 5699 if (!NT_SUCCESS(Status)) 5700 { 5701 TRACE("Status 0x%08lx\n", Status); 5702 goto done; 5703 } 5704 5705 /* Get the UserComment string */ 5706 Status = SampGetObjectAttributeString(UserObject, 5707 L"UserComment", 5708 &InfoBuffer->General.UserComment); 5709 if (!NT_SUCCESS(Status)) 5710 { 5711 TRACE("Status 0x%08lx\n", Status); 5712 goto done; 5713 } 5714 5715 *Buffer = InfoBuffer; 5716 5717 done: 5718 if (!NT_SUCCESS(Status)) 5719 { 5720 if (InfoBuffer != NULL) 5721 { 5722 if (InfoBuffer->General.UserName.Buffer != NULL) 5723 midl_user_free(InfoBuffer->General.UserName.Buffer); 5724 5725 if (InfoBuffer->General.FullName.Buffer != NULL) 5726 midl_user_free(InfoBuffer->General.FullName.Buffer); 5727 5728 if (InfoBuffer->General.AdminComment.Buffer != NULL) 5729 midl_user_free(InfoBuffer->General.AdminComment.Buffer); 5730 5731 if (InfoBuffer->General.UserComment.Buffer != NULL) 5732 midl_user_free(InfoBuffer->General.UserComment.Buffer); 5733 5734 midl_user_free(InfoBuffer); 5735 } 5736 } 5737 5738 return Status; 5739 } 5740 5741 5742 static 5743 NTSTATUS 5744 SampQueryUserPreferences(PSAM_DB_OBJECT UserObject, 5745 PSAMPR_USER_INFO_BUFFER *Buffer) 5746 { 5747 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 5748 SAM_USER_FIXED_DATA FixedData; 5749 ULONG Length = 0; 5750 NTSTATUS Status; 5751 5752 *Buffer = NULL; 5753 5754 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 5755 if (InfoBuffer == NULL) 5756 return STATUS_INSUFFICIENT_RESOURCES; 5757 5758 Length = sizeof(SAM_USER_FIXED_DATA); 5759 Status = SampGetObjectAttribute(UserObject, 5760 L"F", 5761 NULL, 5762 (PVOID)&FixedData, 5763 &Length); 5764 if (!NT_SUCCESS(Status)) 5765 goto done; 5766 5767 InfoBuffer->Preferences.CountryCode = FixedData.CountryCode; 5768 InfoBuffer->Preferences.CodePage = FixedData.CodePage; 5769 5770 /* Get the UserComment string */ 5771 Status = SampGetObjectAttributeString(UserObject, 5772 L"UserComment", 5773 &InfoBuffer->Preferences.UserComment); 5774 if (!NT_SUCCESS(Status)) 5775 { 5776 TRACE("Status 0x%08lx\n", Status); 5777 goto done; 5778 } 5779 5780 *Buffer = InfoBuffer; 5781 5782 done: 5783 if (!NT_SUCCESS(Status)) 5784 { 5785 if (InfoBuffer != NULL) 5786 { 5787 if (InfoBuffer->Preferences.UserComment.Buffer != NULL) 5788 midl_user_free(InfoBuffer->Preferences.UserComment.Buffer); 5789 5790 midl_user_free(InfoBuffer); 5791 } 5792 } 5793 5794 return Status; 5795 } 5796 5797 5798 static 5799 NTSTATUS 5800 SampQueryUserLogon(PSAM_DB_OBJECT UserObject, 5801 PSAMPR_USER_INFO_BUFFER *Buffer) 5802 { 5803 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 5804 SAM_DOMAIN_FIXED_DATA DomainFixedData; 5805 SAM_USER_FIXED_DATA FixedData; 5806 LARGE_INTEGER PasswordCanChange; 5807 LARGE_INTEGER PasswordMustChange; 5808 ULONG Length = 0; 5809 NTSTATUS Status; 5810 5811 *Buffer = NULL; 5812 5813 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 5814 if (InfoBuffer == NULL) 5815 return STATUS_INSUFFICIENT_RESOURCES; 5816 5817 /* Get the fixed size domain data */ 5818 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 5819 Status = SampGetObjectAttribute(UserObject->ParentObject, 5820 L"F", 5821 NULL, 5822 (PVOID)&DomainFixedData, 5823 &Length); 5824 if (!NT_SUCCESS(Status)) 5825 goto done; 5826 5827 /* Get the fixed size user data */ 5828 Length = sizeof(SAM_USER_FIXED_DATA); 5829 Status = SampGetObjectAttribute(UserObject, 5830 L"F", 5831 NULL, 5832 (PVOID)&FixedData, 5833 &Length); 5834 if (!NT_SUCCESS(Status)) 5835 goto done; 5836 5837 InfoBuffer->Logon.UserId = FixedData.UserId; 5838 InfoBuffer->Logon.PrimaryGroupId = FixedData.PrimaryGroupId; 5839 InfoBuffer->Logon.LastLogon.LowPart = FixedData.LastLogon.LowPart; 5840 InfoBuffer->Logon.LastLogon.HighPart = FixedData.LastLogon.HighPart; 5841 InfoBuffer->Logon.LastLogoff.LowPart = FixedData.LastLogoff.LowPart; 5842 InfoBuffer->Logon.LastLogoff.HighPart = FixedData.LastLogoff.HighPart; 5843 InfoBuffer->Logon.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart; 5844 InfoBuffer->Logon.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart; 5845 InfoBuffer->Logon.BadPasswordCount = FixedData.BadPasswordCount; 5846 InfoBuffer->Logon.LogonCount = FixedData.LogonCount; 5847 InfoBuffer->Logon.UserAccountControl = FixedData.UserAccountControl; 5848 5849 PasswordCanChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet, 5850 DomainFixedData.MinPasswordAge); 5851 InfoBuffer->Logon.PasswordCanChange.LowPart = PasswordCanChange.LowPart; 5852 InfoBuffer->Logon.PasswordCanChange.HighPart = PasswordCanChange.HighPart; 5853 5854 PasswordMustChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet, 5855 DomainFixedData.MaxPasswordAge); 5856 InfoBuffer->Logon.PasswordMustChange.LowPart = PasswordMustChange.LowPart; 5857 InfoBuffer->Logon.PasswordMustChange.HighPart = PasswordMustChange.HighPart; 5858 5859 /* Get the Name string */ 5860 Status = SampGetObjectAttributeString(UserObject, 5861 L"Name", 5862 &InfoBuffer->Logon.UserName); 5863 if (!NT_SUCCESS(Status)) 5864 { 5865 TRACE("Status 0x%08lx\n", Status); 5866 goto done; 5867 } 5868 5869 /* Get the FullName string */ 5870 Status = SampGetObjectAttributeString(UserObject, 5871 L"FullName", 5872 &InfoBuffer->Logon.FullName); 5873 if (!NT_SUCCESS(Status)) 5874 { 5875 TRACE("Status 0x%08lx\n", Status); 5876 goto done; 5877 } 5878 5879 /* Get the HomeDirectory string */ 5880 Status = SampGetObjectAttributeString(UserObject, 5881 L"HomeDirectory", 5882 &InfoBuffer->Logon.HomeDirectory); 5883 if (!NT_SUCCESS(Status)) 5884 { 5885 TRACE("Status 0x%08lx\n", Status); 5886 goto done; 5887 } 5888 5889 /* Get the HomeDirectoryDrive string */ 5890 Status = SampGetObjectAttributeString(UserObject, 5891 L"HomeDirectoryDrive", 5892 &InfoBuffer->Logon.HomeDirectoryDrive); 5893 if (!NT_SUCCESS(Status)) 5894 { 5895 TRACE("Status 0x%08lx\n", Status); 5896 goto done; 5897 } 5898 5899 /* Get the ScriptPath string */ 5900 Status = SampGetObjectAttributeString(UserObject, 5901 L"ScriptPath", 5902 &InfoBuffer->Logon.ScriptPath); 5903 if (!NT_SUCCESS(Status)) 5904 { 5905 TRACE("Status 0x%08lx\n", Status); 5906 goto done; 5907 } 5908 5909 /* Get the ProfilePath string */ 5910 Status = SampGetObjectAttributeString(UserObject, 5911 L"ProfilePath", 5912 &InfoBuffer->Logon.ProfilePath); 5913 if (!NT_SUCCESS(Status)) 5914 { 5915 TRACE("Status 0x%08lx\n", Status); 5916 goto done; 5917 } 5918 5919 /* Get the WorkStations string */ 5920 Status = SampGetObjectAttributeString(UserObject, 5921 L"WorkStations", 5922 &InfoBuffer->Logon.WorkStations); 5923 if (!NT_SUCCESS(Status)) 5924 { 5925 TRACE("Status 0x%08lx\n", Status); 5926 goto done; 5927 } 5928 5929 /* Get the LogonHours attribute */ 5930 Status = SampGetLogonHoursAttribute(UserObject, 5931 &InfoBuffer->Logon.LogonHours); 5932 if (!NT_SUCCESS(Status)) 5933 { 5934 TRACE("Status 0x%08lx\n", Status); 5935 goto done; 5936 } 5937 5938 *Buffer = InfoBuffer; 5939 5940 done: 5941 if (!NT_SUCCESS(Status)) 5942 { 5943 if (InfoBuffer != NULL) 5944 { 5945 if (InfoBuffer->Logon.UserName.Buffer != NULL) 5946 midl_user_free(InfoBuffer->Logon.UserName.Buffer); 5947 5948 if (InfoBuffer->Logon.FullName.Buffer != NULL) 5949 midl_user_free(InfoBuffer->Logon.FullName.Buffer); 5950 5951 if (InfoBuffer->Logon.HomeDirectory.Buffer != NULL) 5952 midl_user_free(InfoBuffer->Logon.HomeDirectory.Buffer); 5953 5954 if (InfoBuffer->Logon.HomeDirectoryDrive.Buffer != NULL) 5955 midl_user_free(InfoBuffer->Logon.HomeDirectoryDrive.Buffer); 5956 5957 if (InfoBuffer->Logon.ScriptPath.Buffer != NULL) 5958 midl_user_free(InfoBuffer->Logon.ScriptPath.Buffer); 5959 5960 if (InfoBuffer->Logon.ProfilePath.Buffer != NULL) 5961 midl_user_free(InfoBuffer->Logon.ProfilePath.Buffer); 5962 5963 if (InfoBuffer->Logon.WorkStations.Buffer != NULL) 5964 midl_user_free(InfoBuffer->Logon.WorkStations.Buffer); 5965 5966 if (InfoBuffer->Logon.LogonHours.LogonHours != NULL) 5967 midl_user_free(InfoBuffer->Logon.LogonHours.LogonHours); 5968 5969 midl_user_free(InfoBuffer); 5970 } 5971 } 5972 5973 return Status; 5974 } 5975 5976 5977 static 5978 NTSTATUS 5979 SampQueryUserAccount(PSAM_DB_OBJECT UserObject, 5980 PSAMPR_USER_INFO_BUFFER *Buffer) 5981 { 5982 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 5983 SAM_USER_FIXED_DATA FixedData; 5984 ULONG Length = 0; 5985 NTSTATUS Status; 5986 5987 *Buffer = NULL; 5988 5989 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 5990 if (InfoBuffer == NULL) 5991 return STATUS_INSUFFICIENT_RESOURCES; 5992 5993 Length = sizeof(SAM_USER_FIXED_DATA); 5994 Status = SampGetObjectAttribute(UserObject, 5995 L"F", 5996 NULL, 5997 (PVOID)&FixedData, 5998 &Length); 5999 if (!NT_SUCCESS(Status)) 6000 goto done; 6001 6002 InfoBuffer->Account.UserId = FixedData.UserId; 6003 InfoBuffer->Account.PrimaryGroupId = FixedData.PrimaryGroupId; 6004 InfoBuffer->Account.LastLogon.LowPart = FixedData.LastLogon.LowPart; 6005 InfoBuffer->Account.LastLogon.HighPart = FixedData.LastLogon.HighPart; 6006 InfoBuffer->Account.LastLogoff.LowPart = FixedData.LastLogoff.LowPart; 6007 InfoBuffer->Account.LastLogoff.HighPart = FixedData.LastLogoff.HighPart; 6008 InfoBuffer->Account.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart; 6009 InfoBuffer->Account.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart; 6010 InfoBuffer->Account.AccountExpires.LowPart = FixedData.AccountExpires.LowPart; 6011 InfoBuffer->Account.AccountExpires.HighPart = FixedData.AccountExpires.HighPart; 6012 InfoBuffer->Account.BadPasswordCount = FixedData.BadPasswordCount; 6013 InfoBuffer->Account.LogonCount = FixedData.LogonCount; 6014 InfoBuffer->Account.UserAccountControl = FixedData.UserAccountControl; 6015 6016 /* Get the Name string */ 6017 Status = SampGetObjectAttributeString(UserObject, 6018 L"Name", 6019 &InfoBuffer->Account.UserName); 6020 if (!NT_SUCCESS(Status)) 6021 { 6022 TRACE("Status 0x%08lx\n", Status); 6023 goto done; 6024 } 6025 6026 /* Get the FullName string */ 6027 Status = SampGetObjectAttributeString(UserObject, 6028 L"FullName", 6029 &InfoBuffer->Account.FullName); 6030 if (!NT_SUCCESS(Status)) 6031 { 6032 TRACE("Status 0x%08lx\n", Status); 6033 goto done; 6034 } 6035 6036 /* Get the HomeDirectory string */ 6037 Status = SampGetObjectAttributeString(UserObject, 6038 L"HomeDirectory", 6039 &InfoBuffer->Account.HomeDirectory); 6040 if (!NT_SUCCESS(Status)) 6041 { 6042 TRACE("Status 0x%08lx\n", Status); 6043 goto done; 6044 } 6045 6046 /* Get the HomeDirectoryDrive string */ 6047 Status = SampGetObjectAttributeString(UserObject, 6048 L"HomeDirectoryDrive", 6049 &InfoBuffer->Account.HomeDirectoryDrive); 6050 if (!NT_SUCCESS(Status)) 6051 { 6052 TRACE("Status 0x%08lx\n", Status); 6053 goto done; 6054 } 6055 6056 /* Get the ScriptPath string */ 6057 Status = SampGetObjectAttributeString(UserObject, 6058 L"ScriptPath", 6059 &InfoBuffer->Account.ScriptPath); 6060 if (!NT_SUCCESS(Status)) 6061 { 6062 TRACE("Status 0x%08lx\n", Status); 6063 goto done; 6064 } 6065 6066 /* Get the ProfilePath string */ 6067 Status = SampGetObjectAttributeString(UserObject, 6068 L"ProfilePath", 6069 &InfoBuffer->Account.ProfilePath); 6070 if (!NT_SUCCESS(Status)) 6071 { 6072 TRACE("Status 0x%08lx\n", Status); 6073 goto done; 6074 } 6075 6076 /* Get the AdminComment string */ 6077 Status = SampGetObjectAttributeString(UserObject, 6078 L"AdminComment", 6079 &InfoBuffer->Account.AdminComment); 6080 if (!NT_SUCCESS(Status)) 6081 { 6082 TRACE("Status 0x%08lx\n", Status); 6083 goto done; 6084 } 6085 6086 /* Get the WorkStations string */ 6087 Status = SampGetObjectAttributeString(UserObject, 6088 L"WorkStations", 6089 &InfoBuffer->Account.WorkStations); 6090 if (!NT_SUCCESS(Status)) 6091 { 6092 TRACE("Status 0x%08lx\n", Status); 6093 goto done; 6094 } 6095 6096 /* Get the LogonHours attribute */ 6097 Status = SampGetLogonHoursAttribute(UserObject, 6098 &InfoBuffer->Account.LogonHours); 6099 if (!NT_SUCCESS(Status)) 6100 { 6101 TRACE("Status 0x%08lx\n", Status); 6102 goto done; 6103 } 6104 6105 *Buffer = InfoBuffer; 6106 6107 done: 6108 if (!NT_SUCCESS(Status)) 6109 { 6110 if (InfoBuffer != NULL) 6111 { 6112 if (InfoBuffer->Account.UserName.Buffer != NULL) 6113 midl_user_free(InfoBuffer->Account.UserName.Buffer); 6114 6115 if (InfoBuffer->Account.FullName.Buffer != NULL) 6116 midl_user_free(InfoBuffer->Account.FullName.Buffer); 6117 6118 if (InfoBuffer->Account.HomeDirectory.Buffer != NULL) 6119 midl_user_free(InfoBuffer->Account.HomeDirectory.Buffer); 6120 6121 if (InfoBuffer->Account.HomeDirectoryDrive.Buffer != NULL) 6122 midl_user_free(InfoBuffer->Account.HomeDirectoryDrive.Buffer); 6123 6124 if (InfoBuffer->Account.ScriptPath.Buffer != NULL) 6125 midl_user_free(InfoBuffer->Account.ScriptPath.Buffer); 6126 6127 if (InfoBuffer->Account.ProfilePath.Buffer != NULL) 6128 midl_user_free(InfoBuffer->Account.ProfilePath.Buffer); 6129 6130 if (InfoBuffer->Account.AdminComment.Buffer != NULL) 6131 midl_user_free(InfoBuffer->Account.AdminComment.Buffer); 6132 6133 if (InfoBuffer->Account.WorkStations.Buffer != NULL) 6134 midl_user_free(InfoBuffer->Account.WorkStations.Buffer); 6135 6136 if (InfoBuffer->Account.LogonHours.LogonHours != NULL) 6137 midl_user_free(InfoBuffer->Account.LogonHours.LogonHours); 6138 6139 midl_user_free(InfoBuffer); 6140 } 6141 } 6142 6143 return Status; 6144 } 6145 6146 6147 static 6148 NTSTATUS 6149 SampQueryUserLogonHours(PSAM_DB_OBJECT UserObject, 6150 PSAMPR_USER_INFO_BUFFER *Buffer) 6151 { 6152 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6153 NTSTATUS Status; 6154 6155 TRACE("(%p %p)\n", UserObject, Buffer); 6156 6157 *Buffer = NULL; 6158 6159 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6160 if (InfoBuffer == NULL) 6161 { 6162 TRACE("Failed to allocate InfoBuffer!\n"); 6163 return STATUS_INSUFFICIENT_RESOURCES; 6164 } 6165 6166 Status = SampGetLogonHoursAttribute(UserObject, 6167 &InfoBuffer->LogonHours.LogonHours); 6168 if (!NT_SUCCESS(Status)) 6169 { 6170 TRACE("SampGetLogonHoursAttribute failed (Status 0x%08lx)\n", Status); 6171 goto done; 6172 } 6173 6174 *Buffer = InfoBuffer; 6175 6176 done: 6177 if (!NT_SUCCESS(Status)) 6178 { 6179 if (InfoBuffer != NULL) 6180 { 6181 if (InfoBuffer->LogonHours.LogonHours.LogonHours != NULL) 6182 midl_user_free(InfoBuffer->LogonHours.LogonHours.LogonHours); 6183 6184 midl_user_free(InfoBuffer); 6185 } 6186 } 6187 6188 return Status; 6189 } 6190 6191 6192 static 6193 NTSTATUS 6194 SampQueryUserName(PSAM_DB_OBJECT UserObject, 6195 PSAMPR_USER_INFO_BUFFER *Buffer) 6196 { 6197 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6198 NTSTATUS Status; 6199 6200 *Buffer = NULL; 6201 6202 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6203 if (InfoBuffer == NULL) 6204 return STATUS_INSUFFICIENT_RESOURCES; 6205 6206 /* Get the Name string */ 6207 Status = SampGetObjectAttributeString(UserObject, 6208 L"Name", 6209 &InfoBuffer->Name.UserName); 6210 if (!NT_SUCCESS(Status)) 6211 { 6212 TRACE("Status 0x%08lx\n", Status); 6213 goto done; 6214 } 6215 6216 /* Get the FullName string */ 6217 Status = SampGetObjectAttributeString(UserObject, 6218 L"FullName", 6219 &InfoBuffer->Name.FullName); 6220 if (!NT_SUCCESS(Status)) 6221 { 6222 TRACE("Status 0x%08lx\n", Status); 6223 goto done; 6224 } 6225 6226 *Buffer = InfoBuffer; 6227 6228 done: 6229 if (!NT_SUCCESS(Status)) 6230 { 6231 if (InfoBuffer != NULL) 6232 { 6233 if (InfoBuffer->Name.UserName.Buffer != NULL) 6234 midl_user_free(InfoBuffer->Name.UserName.Buffer); 6235 6236 if (InfoBuffer->Name.FullName.Buffer != NULL) 6237 midl_user_free(InfoBuffer->Name.FullName.Buffer); 6238 6239 midl_user_free(InfoBuffer); 6240 } 6241 } 6242 6243 return Status; 6244 } 6245 6246 6247 static NTSTATUS 6248 SampQueryUserAccountName(PSAM_DB_OBJECT UserObject, 6249 PSAMPR_USER_INFO_BUFFER *Buffer) 6250 { 6251 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6252 NTSTATUS Status; 6253 6254 *Buffer = NULL; 6255 6256 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6257 if (InfoBuffer == NULL) 6258 return STATUS_INSUFFICIENT_RESOURCES; 6259 6260 /* Get the Name string */ 6261 Status = SampGetObjectAttributeString(UserObject, 6262 L"Name", 6263 &InfoBuffer->AccountName.UserName); 6264 if (!NT_SUCCESS(Status)) 6265 { 6266 TRACE("Status 0x%08lx\n", Status); 6267 goto done; 6268 } 6269 6270 *Buffer = InfoBuffer; 6271 6272 done: 6273 if (!NT_SUCCESS(Status)) 6274 { 6275 if (InfoBuffer != NULL) 6276 { 6277 if (InfoBuffer->AccountName.UserName.Buffer != NULL) 6278 midl_user_free(InfoBuffer->AccountName.UserName.Buffer); 6279 6280 midl_user_free(InfoBuffer); 6281 } 6282 } 6283 6284 return Status; 6285 } 6286 6287 6288 static NTSTATUS 6289 SampQueryUserFullName(PSAM_DB_OBJECT UserObject, 6290 PSAMPR_USER_INFO_BUFFER *Buffer) 6291 { 6292 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6293 NTSTATUS Status; 6294 6295 *Buffer = NULL; 6296 6297 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6298 if (InfoBuffer == NULL) 6299 return STATUS_INSUFFICIENT_RESOURCES; 6300 6301 /* Get the FullName string */ 6302 Status = SampGetObjectAttributeString(UserObject, 6303 L"FullName", 6304 &InfoBuffer->FullName.FullName); 6305 if (!NT_SUCCESS(Status)) 6306 { 6307 TRACE("Status 0x%08lx\n", Status); 6308 goto done; 6309 } 6310 6311 *Buffer = InfoBuffer; 6312 6313 done: 6314 if (!NT_SUCCESS(Status)) 6315 { 6316 if (InfoBuffer != NULL) 6317 { 6318 if (InfoBuffer->FullName.FullName.Buffer != NULL) 6319 midl_user_free(InfoBuffer->FullName.FullName.Buffer); 6320 6321 midl_user_free(InfoBuffer); 6322 } 6323 } 6324 6325 return Status; 6326 } 6327 6328 6329 static 6330 NTSTATUS 6331 SampQueryUserPrimaryGroup(PSAM_DB_OBJECT UserObject, 6332 PSAMPR_USER_INFO_BUFFER *Buffer) 6333 { 6334 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6335 SAM_USER_FIXED_DATA FixedData; 6336 ULONG Length = 0; 6337 NTSTATUS Status; 6338 6339 *Buffer = NULL; 6340 6341 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6342 if (InfoBuffer == NULL) 6343 return STATUS_INSUFFICIENT_RESOURCES; 6344 6345 Length = sizeof(SAM_USER_FIXED_DATA); 6346 Status = SampGetObjectAttribute(UserObject, 6347 L"F", 6348 NULL, 6349 (PVOID)&FixedData, 6350 &Length); 6351 if (!NT_SUCCESS(Status)) 6352 goto done; 6353 6354 InfoBuffer->PrimaryGroup.PrimaryGroupId = FixedData.PrimaryGroupId; 6355 6356 *Buffer = InfoBuffer; 6357 6358 done: 6359 if (!NT_SUCCESS(Status)) 6360 { 6361 if (InfoBuffer != NULL) 6362 { 6363 midl_user_free(InfoBuffer); 6364 } 6365 } 6366 6367 return Status; 6368 } 6369 6370 6371 static NTSTATUS 6372 SampQueryUserHome(PSAM_DB_OBJECT UserObject, 6373 PSAMPR_USER_INFO_BUFFER *Buffer) 6374 { 6375 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6376 NTSTATUS Status; 6377 6378 *Buffer = NULL; 6379 6380 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6381 if (InfoBuffer == NULL) 6382 return STATUS_INSUFFICIENT_RESOURCES; 6383 6384 /* Get the HomeDirectory string */ 6385 Status = SampGetObjectAttributeString(UserObject, 6386 L"HomeDirectory", 6387 &InfoBuffer->Home.HomeDirectory); 6388 if (!NT_SUCCESS(Status)) 6389 { 6390 TRACE("Status 0x%08lx\n", Status); 6391 goto done; 6392 } 6393 6394 /* Get the HomeDirectoryDrive string */ 6395 Status = SampGetObjectAttributeString(UserObject, 6396 L"HomeDirectoryDrive", 6397 &InfoBuffer->Home.HomeDirectoryDrive); 6398 if (!NT_SUCCESS(Status)) 6399 { 6400 TRACE("Status 0x%08lx\n", Status); 6401 goto done; 6402 } 6403 6404 *Buffer = InfoBuffer; 6405 6406 done: 6407 if (!NT_SUCCESS(Status)) 6408 { 6409 if (InfoBuffer != NULL) 6410 { 6411 if (InfoBuffer->Home.HomeDirectory.Buffer != NULL) 6412 midl_user_free(InfoBuffer->Home.HomeDirectory.Buffer); 6413 6414 if (InfoBuffer->Home.HomeDirectoryDrive.Buffer != NULL) 6415 midl_user_free(InfoBuffer->Home.HomeDirectoryDrive.Buffer); 6416 6417 midl_user_free(InfoBuffer); 6418 } 6419 } 6420 6421 return Status; 6422 } 6423 6424 6425 static NTSTATUS 6426 SampQueryUserScript(PSAM_DB_OBJECT UserObject, 6427 PSAMPR_USER_INFO_BUFFER *Buffer) 6428 { 6429 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6430 NTSTATUS Status; 6431 6432 *Buffer = NULL; 6433 6434 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6435 if (InfoBuffer == NULL) 6436 return STATUS_INSUFFICIENT_RESOURCES; 6437 6438 /* Get the ScriptPath string */ 6439 Status = SampGetObjectAttributeString(UserObject, 6440 L"ScriptPath", 6441 &InfoBuffer->Script.ScriptPath); 6442 if (!NT_SUCCESS(Status)) 6443 { 6444 TRACE("Status 0x%08lx\n", Status); 6445 goto done; 6446 } 6447 6448 *Buffer = InfoBuffer; 6449 6450 done: 6451 if (!NT_SUCCESS(Status)) 6452 { 6453 if (InfoBuffer != NULL) 6454 { 6455 if (InfoBuffer->Script.ScriptPath.Buffer != NULL) 6456 midl_user_free(InfoBuffer->Script.ScriptPath.Buffer); 6457 6458 midl_user_free(InfoBuffer); 6459 } 6460 } 6461 6462 return Status; 6463 } 6464 6465 6466 static NTSTATUS 6467 SampQueryUserProfile(PSAM_DB_OBJECT UserObject, 6468 PSAMPR_USER_INFO_BUFFER *Buffer) 6469 { 6470 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6471 NTSTATUS Status; 6472 6473 *Buffer = NULL; 6474 6475 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6476 if (InfoBuffer == NULL) 6477 return STATUS_INSUFFICIENT_RESOURCES; 6478 6479 /* Get the ProfilePath string */ 6480 Status = SampGetObjectAttributeString(UserObject, 6481 L"ProfilePath", 6482 &InfoBuffer->Profile.ProfilePath); 6483 if (!NT_SUCCESS(Status)) 6484 { 6485 TRACE("Status 0x%08lx\n", Status); 6486 goto done; 6487 } 6488 6489 *Buffer = InfoBuffer; 6490 6491 done: 6492 if (!NT_SUCCESS(Status)) 6493 { 6494 if (InfoBuffer != NULL) 6495 { 6496 if (InfoBuffer->Profile.ProfilePath.Buffer != NULL) 6497 midl_user_free(InfoBuffer->Profile.ProfilePath.Buffer); 6498 6499 midl_user_free(InfoBuffer); 6500 } 6501 } 6502 6503 return Status; 6504 } 6505 6506 6507 static NTSTATUS 6508 SampQueryUserAdminComment(PSAM_DB_OBJECT UserObject, 6509 PSAMPR_USER_INFO_BUFFER *Buffer) 6510 { 6511 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6512 NTSTATUS Status; 6513 6514 *Buffer = NULL; 6515 6516 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6517 if (InfoBuffer == NULL) 6518 return STATUS_INSUFFICIENT_RESOURCES; 6519 6520 /* Get the AdminComment string */ 6521 Status = SampGetObjectAttributeString(UserObject, 6522 L"AdminComment", 6523 &InfoBuffer->AdminComment.AdminComment); 6524 if (!NT_SUCCESS(Status)) 6525 { 6526 TRACE("Status 0x%08lx\n", Status); 6527 goto done; 6528 } 6529 6530 *Buffer = InfoBuffer; 6531 6532 done: 6533 if (!NT_SUCCESS(Status)) 6534 { 6535 if (InfoBuffer != NULL) 6536 { 6537 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL) 6538 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer); 6539 6540 midl_user_free(InfoBuffer); 6541 } 6542 } 6543 6544 return Status; 6545 } 6546 6547 6548 static NTSTATUS 6549 SampQueryUserWorkStations(PSAM_DB_OBJECT UserObject, 6550 PSAMPR_USER_INFO_BUFFER *Buffer) 6551 { 6552 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6553 NTSTATUS Status; 6554 6555 *Buffer = NULL; 6556 6557 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6558 if (InfoBuffer == NULL) 6559 return STATUS_INSUFFICIENT_RESOURCES; 6560 6561 /* Get the WorkStations string */ 6562 Status = SampGetObjectAttributeString(UserObject, 6563 L"WorkStations", 6564 &InfoBuffer->WorkStations.WorkStations); 6565 if (!NT_SUCCESS(Status)) 6566 { 6567 TRACE("Status 0x%08lx\n", Status); 6568 goto done; 6569 } 6570 6571 *Buffer = InfoBuffer; 6572 6573 done: 6574 if (!NT_SUCCESS(Status)) 6575 { 6576 if (InfoBuffer != NULL) 6577 { 6578 if (InfoBuffer->WorkStations.WorkStations.Buffer != NULL) 6579 midl_user_free(InfoBuffer->WorkStations.WorkStations.Buffer); 6580 6581 midl_user_free(InfoBuffer); 6582 } 6583 } 6584 6585 return Status; 6586 } 6587 6588 6589 static 6590 NTSTATUS 6591 SampQueryUserControl(PSAM_DB_OBJECT UserObject, 6592 PSAMPR_USER_INFO_BUFFER *Buffer) 6593 { 6594 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6595 SAM_USER_FIXED_DATA FixedData; 6596 ULONG Length = 0; 6597 NTSTATUS Status; 6598 6599 *Buffer = NULL; 6600 6601 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6602 if (InfoBuffer == NULL) 6603 return STATUS_INSUFFICIENT_RESOURCES; 6604 6605 Length = sizeof(SAM_USER_FIXED_DATA); 6606 Status = SampGetObjectAttribute(UserObject, 6607 L"F", 6608 NULL, 6609 (PVOID)&FixedData, 6610 &Length); 6611 if (!NT_SUCCESS(Status)) 6612 goto done; 6613 6614 InfoBuffer->Control.UserAccountControl = FixedData.UserAccountControl; 6615 6616 *Buffer = InfoBuffer; 6617 6618 done: 6619 if (!NT_SUCCESS(Status)) 6620 { 6621 if (InfoBuffer != NULL) 6622 { 6623 midl_user_free(InfoBuffer); 6624 } 6625 } 6626 6627 return Status; 6628 } 6629 6630 6631 static 6632 NTSTATUS 6633 SampQueryUserExpires(PSAM_DB_OBJECT UserObject, 6634 PSAMPR_USER_INFO_BUFFER *Buffer) 6635 { 6636 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6637 SAM_USER_FIXED_DATA FixedData; 6638 ULONG Length = 0; 6639 NTSTATUS Status; 6640 6641 *Buffer = NULL; 6642 6643 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6644 if (InfoBuffer == NULL) 6645 return STATUS_INSUFFICIENT_RESOURCES; 6646 6647 Length = sizeof(SAM_USER_FIXED_DATA); 6648 Status = SampGetObjectAttribute(UserObject, 6649 L"F", 6650 NULL, 6651 (PVOID)&FixedData, 6652 &Length); 6653 if (!NT_SUCCESS(Status)) 6654 goto done; 6655 6656 InfoBuffer->Expires.AccountExpires.LowPart = FixedData.AccountExpires.LowPart; 6657 InfoBuffer->Expires.AccountExpires.HighPart = FixedData.AccountExpires.HighPart; 6658 6659 *Buffer = InfoBuffer; 6660 6661 done: 6662 if (!NT_SUCCESS(Status)) 6663 { 6664 if (InfoBuffer != NULL) 6665 { 6666 midl_user_free(InfoBuffer); 6667 } 6668 } 6669 6670 return Status; 6671 } 6672 6673 6674 static 6675 NTSTATUS 6676 SampQueryUserInternal1(PSAM_DB_OBJECT UserObject, 6677 PSAMPR_USER_INFO_BUFFER *Buffer) 6678 { 6679 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6680 ULONG Length = 0; 6681 NTSTATUS Status = STATUS_SUCCESS; 6682 6683 /* Fail, if the caller is not a trusted caller */ 6684 if (UserObject->Trusted == FALSE) 6685 return STATUS_INVALID_INFO_CLASS; 6686 6687 *Buffer = NULL; 6688 6689 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6690 if (InfoBuffer == NULL) 6691 return STATUS_INSUFFICIENT_RESOURCES; 6692 6693 InfoBuffer->Internal1.LmPasswordPresent = FALSE; 6694 InfoBuffer->Internal1.NtPasswordPresent = FALSE; 6695 6696 /* Get the NT password */ 6697 Length = 0; 6698 SampGetObjectAttribute(UserObject, 6699 L"NTPwd", 6700 NULL, 6701 NULL, 6702 &Length); 6703 6704 if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD)) 6705 { 6706 Status = SampGetObjectAttribute(UserObject, 6707 L"NTPwd", 6708 NULL, 6709 (PVOID)&InfoBuffer->Internal1.EncryptedNtOwfPassword, 6710 &Length); 6711 if (!NT_SUCCESS(Status)) 6712 goto done; 6713 6714 if (memcmp(&InfoBuffer->Internal1.EncryptedNtOwfPassword, 6715 &EmptyNtHash, 6716 sizeof(ENCRYPTED_NT_OWF_PASSWORD))) 6717 InfoBuffer->Internal1.NtPasswordPresent = TRUE; 6718 } 6719 6720 6721 /* Get the LM password */ 6722 Length = 0; 6723 SampGetObjectAttribute(UserObject, 6724 L"LMPwd", 6725 NULL, 6726 NULL, 6727 &Length); 6728 6729 if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD)) 6730 { 6731 Status = SampGetObjectAttribute(UserObject, 6732 L"LMPwd", 6733 NULL, 6734 (PVOID)&InfoBuffer->Internal1.EncryptedLmOwfPassword, 6735 &Length); 6736 if (!NT_SUCCESS(Status)) 6737 goto done; 6738 6739 if (memcmp(&InfoBuffer->Internal1.EncryptedLmOwfPassword, 6740 &EmptyLmHash, 6741 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 6742 InfoBuffer->Internal1.LmPasswordPresent = TRUE; 6743 } 6744 6745 InfoBuffer->Internal1.PasswordExpired = FALSE; 6746 6747 *Buffer = InfoBuffer; 6748 6749 done: 6750 if (!NT_SUCCESS(Status)) 6751 { 6752 if (InfoBuffer != NULL) 6753 { 6754 midl_user_free(InfoBuffer); 6755 } 6756 } 6757 6758 return Status; 6759 } 6760 6761 6762 static 6763 NTSTATUS 6764 SampQueryUserInternal2(PSAM_DB_OBJECT UserObject, 6765 PSAMPR_USER_INFO_BUFFER *Buffer) 6766 { 6767 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6768 SAM_USER_FIXED_DATA FixedData; 6769 ULONG Length = 0; 6770 NTSTATUS Status; 6771 6772 *Buffer = NULL; 6773 6774 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6775 if (InfoBuffer == NULL) 6776 return STATUS_INSUFFICIENT_RESOURCES; 6777 6778 Length = sizeof(SAM_USER_FIXED_DATA); 6779 Status = SampGetObjectAttribute(UserObject, 6780 L"F", 6781 NULL, 6782 (PVOID)&FixedData, 6783 &Length); 6784 if (!NT_SUCCESS(Status)) 6785 goto done; 6786 6787 InfoBuffer->Internal2.Flags = 0; 6788 InfoBuffer->Internal2.LastLogon.LowPart = FixedData.LastLogon.LowPart; 6789 InfoBuffer->Internal2.LastLogon.HighPart = FixedData.LastLogon.HighPart; 6790 InfoBuffer->Internal2.LastLogoff.LowPart = FixedData.LastLogoff.LowPart; 6791 InfoBuffer->Internal2.LastLogoff.HighPart = FixedData.LastLogoff.HighPart; 6792 InfoBuffer->Internal2.BadPasswordCount = FixedData.BadPasswordCount; 6793 InfoBuffer->Internal2.LogonCount = FixedData.LogonCount; 6794 6795 *Buffer = InfoBuffer; 6796 6797 done: 6798 if (!NT_SUCCESS(Status)) 6799 { 6800 if (InfoBuffer != NULL) 6801 { 6802 midl_user_free(InfoBuffer); 6803 } 6804 } 6805 6806 return Status; 6807 } 6808 6809 6810 static NTSTATUS 6811 SampQueryUserParameters(PSAM_DB_OBJECT UserObject, 6812 PSAMPR_USER_INFO_BUFFER *Buffer) 6813 { 6814 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6815 NTSTATUS Status; 6816 6817 *Buffer = NULL; 6818 6819 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6820 if (InfoBuffer == NULL) 6821 return STATUS_INSUFFICIENT_RESOURCES; 6822 6823 /* Get the Parameters string */ 6824 Status = SampGetObjectAttributeString(UserObject, 6825 L"Parameters", 6826 &InfoBuffer->Parameters.Parameters); 6827 if (!NT_SUCCESS(Status)) 6828 { 6829 TRACE("Status 0x%08lx\n", Status); 6830 goto done; 6831 } 6832 6833 *Buffer = InfoBuffer; 6834 6835 done: 6836 if (!NT_SUCCESS(Status)) 6837 { 6838 if (InfoBuffer != NULL) 6839 { 6840 if (InfoBuffer->Parameters.Parameters.Buffer != NULL) 6841 midl_user_free(InfoBuffer->Parameters.Parameters.Buffer); 6842 6843 midl_user_free(InfoBuffer); 6844 } 6845 } 6846 6847 return Status; 6848 } 6849 6850 6851 static NTSTATUS 6852 SampQueryUserAll(PSAM_DB_OBJECT UserObject, 6853 PSAMPR_USER_INFO_BUFFER *Buffer) 6854 { 6855 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6856 SAM_DOMAIN_FIXED_DATA DomainFixedData; 6857 SAM_USER_FIXED_DATA FixedData; 6858 LARGE_INTEGER PasswordCanChange; 6859 LARGE_INTEGER PasswordMustChange; 6860 ULONG Length = 0; 6861 NTSTATUS Status; 6862 6863 *Buffer = NULL; 6864 6865 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6866 if (InfoBuffer == NULL) 6867 return STATUS_INSUFFICIENT_RESOURCES; 6868 6869 /* Get the fixed size domain data */ 6870 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 6871 Status = SampGetObjectAttribute(UserObject->ParentObject, 6872 L"F", 6873 NULL, 6874 (PVOID)&DomainFixedData, 6875 &Length); 6876 if (!NT_SUCCESS(Status)) 6877 goto done; 6878 6879 /* Get the fixed size user data */ 6880 Length = sizeof(SAM_USER_FIXED_DATA); 6881 Status = SampGetObjectAttribute(UserObject, 6882 L"F", 6883 NULL, 6884 (PVOID)&FixedData, 6885 &Length); 6886 if (!NT_SUCCESS(Status)) 6887 goto done; 6888 6889 /* Set the fields to be returned */ 6890 if (UserObject->Trusted) 6891 { 6892 InfoBuffer->All.WhichFields = USER_ALL_READ_GENERAL_MASK | 6893 USER_ALL_READ_LOGON_MASK | 6894 USER_ALL_READ_ACCOUNT_MASK | 6895 USER_ALL_READ_PREFERENCES_MASK | 6896 USER_ALL_READ_TRUSTED_MASK; 6897 } 6898 else 6899 { 6900 InfoBuffer->All.WhichFields = 0; 6901 6902 if (UserObject->Access & USER_READ_GENERAL) 6903 InfoBuffer->All.WhichFields |= USER_ALL_READ_GENERAL_MASK; 6904 6905 if (UserObject->Access & USER_READ_LOGON) 6906 InfoBuffer->All.WhichFields |= USER_ALL_READ_LOGON_MASK; 6907 6908 if (UserObject->Access & USER_READ_ACCOUNT) 6909 InfoBuffer->All.WhichFields |= USER_ALL_READ_ACCOUNT_MASK; 6910 6911 if (UserObject->Access & USER_READ_PREFERENCES) 6912 InfoBuffer->All.WhichFields |= USER_ALL_READ_PREFERENCES_MASK; 6913 } 6914 6915 /* Fail, if no fields are to be returned */ 6916 if (InfoBuffer->All.WhichFields == 0) 6917 { 6918 Status = STATUS_ACCESS_DENIED; 6919 goto done; 6920 } 6921 6922 /* Get the UserName attribute */ 6923 if (InfoBuffer->All.WhichFields & USER_ALL_USERNAME) 6924 { 6925 Status = SampGetObjectAttributeString(UserObject, 6926 L"Name", 6927 &InfoBuffer->All.UserName); 6928 if (!NT_SUCCESS(Status)) 6929 { 6930 TRACE("Status 0x%08lx\n", Status); 6931 goto done; 6932 } 6933 } 6934 6935 /* Get the FullName attribute */ 6936 if (InfoBuffer->All.WhichFields & USER_ALL_FULLNAME) 6937 { 6938 Status = SampGetObjectAttributeString(UserObject, 6939 L"FullName", 6940 &InfoBuffer->All.FullName); 6941 if (!NT_SUCCESS(Status)) 6942 { 6943 TRACE("Status 0x%08lx\n", Status); 6944 goto done; 6945 } 6946 } 6947 6948 /* Get the UserId attribute */ 6949 if (InfoBuffer->All.WhichFields & USER_ALL_USERID) 6950 { 6951 InfoBuffer->All.UserId = FixedData.UserId; 6952 } 6953 6954 /* Get the PrimaryGroupId attribute */ 6955 if (InfoBuffer->All.WhichFields & USER_ALL_PRIMARYGROUPID) 6956 { 6957 InfoBuffer->All.PrimaryGroupId = FixedData.PrimaryGroupId; 6958 } 6959 6960 /* Get the AdminComment attribute */ 6961 if (InfoBuffer->All.WhichFields & USER_ALL_ADMINCOMMENT) 6962 { 6963 Status = SampGetObjectAttributeString(UserObject, 6964 L"AdminComment", 6965 &InfoBuffer->All.AdminComment); 6966 if (!NT_SUCCESS(Status)) 6967 { 6968 TRACE("Status 0x%08lx\n", Status); 6969 goto done; 6970 } 6971 } 6972 6973 /* Get the UserComment attribute */ 6974 if (InfoBuffer->All.WhichFields & USER_ALL_USERCOMMENT) 6975 { 6976 Status = SampGetObjectAttributeString(UserObject, 6977 L"UserComment", 6978 &InfoBuffer->All.UserComment); 6979 if (!NT_SUCCESS(Status)) 6980 { 6981 TRACE("Status 0x%08lx\n", Status); 6982 goto done; 6983 } 6984 } 6985 6986 /* Get the HomeDirectory attribute */ 6987 if (InfoBuffer->All.WhichFields & USER_ALL_HOMEDIRECTORY) 6988 { 6989 Status = SampGetObjectAttributeString(UserObject, 6990 L"HomeDirectory", 6991 &InfoBuffer->All.HomeDirectory); 6992 if (!NT_SUCCESS(Status)) 6993 { 6994 TRACE("Status 0x%08lx\n", Status); 6995 goto done; 6996 } 6997 } 6998 6999 /* Get the HomeDirectoryDrive attribute */ 7000 if (InfoBuffer->All.WhichFields & USER_ALL_HOMEDIRECTORYDRIVE) 7001 { 7002 Status = SampGetObjectAttributeString(UserObject, 7003 L"HomeDirectoryDrive", 7004 &InfoBuffer->Home.HomeDirectoryDrive); 7005 if (!NT_SUCCESS(Status)) 7006 { 7007 TRACE("Status 0x%08lx\n", Status); 7008 goto done; 7009 } 7010 } 7011 7012 /* Get the ScriptPath attribute */ 7013 if (InfoBuffer->All.WhichFields & USER_ALL_SCRIPTPATH) 7014 { 7015 Status = SampGetObjectAttributeString(UserObject, 7016 L"ScriptPath", 7017 &InfoBuffer->All.ScriptPath); 7018 if (!NT_SUCCESS(Status)) 7019 { 7020 TRACE("Status 0x%08lx\n", Status); 7021 goto done; 7022 } 7023 } 7024 7025 /* Get the ProfilePath attribute */ 7026 if (InfoBuffer->All.WhichFields & USER_ALL_PROFILEPATH) 7027 { 7028 Status = SampGetObjectAttributeString(UserObject, 7029 L"ProfilePath", 7030 &InfoBuffer->All.ProfilePath); 7031 if (!NT_SUCCESS(Status)) 7032 { 7033 TRACE("Status 0x%08lx\n", Status); 7034 goto done; 7035 } 7036 } 7037 7038 /* Get the WorkStations attribute */ 7039 if (InfoBuffer->All.WhichFields & USER_ALL_WORKSTATIONS) 7040 { 7041 Status = SampGetObjectAttributeString(UserObject, 7042 L"WorkStations", 7043 &InfoBuffer->All.WorkStations); 7044 if (!NT_SUCCESS(Status)) 7045 { 7046 TRACE("Status 0x%08lx\n", Status); 7047 goto done; 7048 } 7049 } 7050 7051 /* Get the LastLogon attribute */ 7052 if (InfoBuffer->All.WhichFields & USER_ALL_LASTLOGON) 7053 { 7054 InfoBuffer->All.LastLogon.LowPart = FixedData.LastLogon.LowPart; 7055 InfoBuffer->All.LastLogon.HighPart = FixedData.LastLogon.HighPart; 7056 } 7057 7058 /* Get the LastLogoff attribute */ 7059 if (InfoBuffer->All.WhichFields & USER_ALL_LASTLOGOFF) 7060 { 7061 InfoBuffer->All.LastLogoff.LowPart = FixedData.LastLogoff.LowPart; 7062 InfoBuffer->All.LastLogoff.HighPart = FixedData.LastLogoff.HighPart; 7063 } 7064 7065 /* Get the LogonHours attribute */ 7066 if (InfoBuffer->All.WhichFields & USER_ALL_LOGONHOURS) 7067 { 7068 Status = SampGetLogonHoursAttribute(UserObject, 7069 &InfoBuffer->All.LogonHours); 7070 if (!NT_SUCCESS(Status)) 7071 { 7072 TRACE("Status 0x%08lx\n", Status); 7073 goto done; 7074 } 7075 } 7076 7077 /* Get the BadPasswordCount attribute */ 7078 if (InfoBuffer->All.WhichFields & USER_ALL_BADPASSWORDCOUNT) 7079 { 7080 InfoBuffer->All.BadPasswordCount = FixedData.BadPasswordCount; 7081 } 7082 7083 /* Get the LogonCount attribute */ 7084 if (InfoBuffer->All.WhichFields & USER_ALL_LOGONCOUNT) 7085 { 7086 InfoBuffer->All.LogonCount = FixedData.LogonCount; 7087 } 7088 7089 /* Get the PasswordCanChange attribute */ 7090 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDCANCHANGE) 7091 { 7092 PasswordCanChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet, 7093 DomainFixedData.MinPasswordAge); 7094 InfoBuffer->All.PasswordCanChange.LowPart = PasswordCanChange.LowPart; 7095 InfoBuffer->All.PasswordCanChange.HighPart = PasswordCanChange.HighPart; 7096 } 7097 7098 /* Get the PasswordMustChange attribute */ 7099 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDMUSTCHANGE) 7100 { 7101 PasswordMustChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet, 7102 DomainFixedData.MaxPasswordAge); 7103 InfoBuffer->All.PasswordMustChange.LowPart = PasswordMustChange.LowPart; 7104 InfoBuffer->All.PasswordMustChange.HighPart = PasswordMustChange.HighPart; 7105 } 7106 7107 /* Get the PasswordLastSet attribute */ 7108 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDLASTSET) 7109 { 7110 InfoBuffer->All.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart; 7111 InfoBuffer->All.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart; 7112 } 7113 7114 /* Get the AccountExpires attribute */ 7115 if (InfoBuffer->All.WhichFields & USER_ALL_ACCOUNTEXPIRES) 7116 { 7117 InfoBuffer->All.AccountExpires.LowPart = FixedData.AccountExpires.LowPart; 7118 InfoBuffer->All.AccountExpires.HighPart = FixedData.AccountExpires.HighPart; 7119 } 7120 7121 /* Get the UserAccountControl attribute */ 7122 if (InfoBuffer->All.WhichFields & USER_ALL_USERACCOUNTCONTROL) 7123 { 7124 InfoBuffer->All.UserAccountControl = FixedData.UserAccountControl; 7125 } 7126 7127 /* Get the Parameters attribute */ 7128 if (InfoBuffer->All.WhichFields & USER_ALL_PARAMETERS) 7129 { 7130 Status = SampGetObjectAttributeString(UserObject, 7131 L"Parameters", 7132 &InfoBuffer->All.Parameters); 7133 if (!NT_SUCCESS(Status)) 7134 { 7135 TRACE("Status 0x%08lx\n", Status); 7136 goto done; 7137 } 7138 } 7139 7140 /* Get the CountryCode attribute */ 7141 if (InfoBuffer->All.WhichFields & USER_ALL_COUNTRYCODE) 7142 { 7143 InfoBuffer->All.CountryCode = FixedData.CountryCode; 7144 } 7145 7146 /* Get the CodePage attribute */ 7147 if (InfoBuffer->All.WhichFields & USER_ALL_CODEPAGE) 7148 { 7149 InfoBuffer->All.CodePage = FixedData.CodePage; 7150 } 7151 7152 /* Get the LmPassword and NtPassword attributes */ 7153 if (InfoBuffer->All.WhichFields & (USER_ALL_NTPASSWORDPRESENT | USER_ALL_LMPASSWORDPRESENT)) 7154 { 7155 InfoBuffer->All.LmPasswordPresent = FALSE; 7156 InfoBuffer->All.NtPasswordPresent = FALSE; 7157 7158 /* Get the NT password */ 7159 Length = 0; 7160 SampGetObjectAttribute(UserObject, 7161 L"NTPwd", 7162 NULL, 7163 NULL, 7164 &Length); 7165 7166 if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD)) 7167 { 7168 InfoBuffer->All.NtOwfPassword.Buffer = midl_user_allocate(sizeof(ENCRYPTED_NT_OWF_PASSWORD)); 7169 if (InfoBuffer->All.NtOwfPassword.Buffer == NULL) 7170 { 7171 Status = STATUS_INSUFFICIENT_RESOURCES; 7172 goto done; 7173 } 7174 7175 InfoBuffer->All.NtOwfPassword.Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD); 7176 InfoBuffer->All.NtOwfPassword.MaximumLength = sizeof(ENCRYPTED_NT_OWF_PASSWORD); 7177 7178 Status = SampGetObjectAttribute(UserObject, 7179 L"NTPwd", 7180 NULL, 7181 (PVOID)InfoBuffer->All.NtOwfPassword.Buffer, 7182 &Length); 7183 if (!NT_SUCCESS(Status)) 7184 goto done; 7185 7186 if (memcmp(InfoBuffer->All.NtOwfPassword.Buffer, 7187 &EmptyNtHash, 7188 sizeof(ENCRYPTED_NT_OWF_PASSWORD))) 7189 InfoBuffer->All.NtPasswordPresent = TRUE; 7190 } 7191 7192 /* Get the LM password */ 7193 Length = 0; 7194 SampGetObjectAttribute(UserObject, 7195 L"LMPwd", 7196 NULL, 7197 NULL, 7198 &Length); 7199 7200 if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD)) 7201 { 7202 InfoBuffer->All.LmOwfPassword.Buffer = midl_user_allocate(sizeof(ENCRYPTED_LM_OWF_PASSWORD)); 7203 if (InfoBuffer->All.LmOwfPassword.Buffer == NULL) 7204 { 7205 Status = STATUS_INSUFFICIENT_RESOURCES; 7206 goto done; 7207 } 7208 7209 InfoBuffer->All.LmOwfPassword.Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD); 7210 InfoBuffer->All.LmOwfPassword.MaximumLength = sizeof(ENCRYPTED_LM_OWF_PASSWORD); 7211 7212 Status = SampGetObjectAttribute(UserObject, 7213 L"LMPwd", 7214 NULL, 7215 (PVOID)InfoBuffer->All.LmOwfPassword.Buffer, 7216 &Length); 7217 if (!NT_SUCCESS(Status)) 7218 goto done; 7219 7220 if (memcmp(InfoBuffer->All.LmOwfPassword.Buffer, 7221 &EmptyLmHash, 7222 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 7223 InfoBuffer->All.LmPasswordPresent = TRUE; 7224 } 7225 } 7226 7227 if (InfoBuffer->All.WhichFields & USER_ALL_PRIVATEDATA) 7228 { 7229 Status = SampGetObjectAttributeString(UserObject, 7230 L"PrivateData", 7231 &InfoBuffer->All.PrivateData); 7232 if (!NT_SUCCESS(Status)) 7233 { 7234 TRACE("Status 0x%08lx\n", Status); 7235 goto done; 7236 } 7237 } 7238 7239 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDEXPIRED) 7240 { 7241 /* FIXME */ 7242 } 7243 7244 if (InfoBuffer->All.WhichFields & USER_ALL_SECURITYDESCRIPTOR) 7245 { 7246 Length = 0; 7247 SampGetObjectAttribute(UserObject, 7248 L"SecDesc", 7249 NULL, 7250 NULL, 7251 &Length); 7252 7253 if (Length > 0) 7254 { 7255 InfoBuffer->All.SecurityDescriptor.SecurityDescriptor = midl_user_allocate(Length); 7256 if (InfoBuffer->All.SecurityDescriptor.SecurityDescriptor == NULL) 7257 { 7258 Status = STATUS_INSUFFICIENT_RESOURCES; 7259 goto done; 7260 } 7261 7262 InfoBuffer->All.SecurityDescriptor.Length = Length; 7263 7264 Status = SampGetObjectAttribute(UserObject, 7265 L"SecDesc", 7266 NULL, 7267 (PVOID)InfoBuffer->All.SecurityDescriptor.SecurityDescriptor, 7268 &Length); 7269 if (!NT_SUCCESS(Status)) 7270 goto done; 7271 } 7272 } 7273 7274 *Buffer = InfoBuffer; 7275 7276 done: 7277 if (!NT_SUCCESS(Status)) 7278 { 7279 if (InfoBuffer != NULL) 7280 { 7281 if (InfoBuffer->All.UserName.Buffer != NULL) 7282 midl_user_free(InfoBuffer->All.UserName.Buffer); 7283 7284 if (InfoBuffer->All.FullName.Buffer != NULL) 7285 midl_user_free(InfoBuffer->All.FullName.Buffer); 7286 7287 if (InfoBuffer->All.AdminComment.Buffer != NULL) 7288 midl_user_free(InfoBuffer->All.AdminComment.Buffer); 7289 7290 if (InfoBuffer->All.UserComment.Buffer != NULL) 7291 midl_user_free(InfoBuffer->All.UserComment.Buffer); 7292 7293 if (InfoBuffer->All.HomeDirectory.Buffer != NULL) 7294 midl_user_free(InfoBuffer->All.HomeDirectory.Buffer); 7295 7296 if (InfoBuffer->All.HomeDirectoryDrive.Buffer != NULL) 7297 midl_user_free(InfoBuffer->All.HomeDirectoryDrive.Buffer); 7298 7299 if (InfoBuffer->All.ScriptPath.Buffer != NULL) 7300 midl_user_free(InfoBuffer->All.ScriptPath.Buffer); 7301 7302 if (InfoBuffer->All.ProfilePath.Buffer != NULL) 7303 midl_user_free(InfoBuffer->All.ProfilePath.Buffer); 7304 7305 if (InfoBuffer->All.WorkStations.Buffer != NULL) 7306 midl_user_free(InfoBuffer->All.WorkStations.Buffer); 7307 7308 if (InfoBuffer->All.LogonHours.LogonHours != NULL) 7309 midl_user_free(InfoBuffer->All.LogonHours.LogonHours); 7310 7311 if (InfoBuffer->All.Parameters.Buffer != NULL) 7312 midl_user_free(InfoBuffer->All.Parameters.Buffer); 7313 7314 if (InfoBuffer->All.LmOwfPassword.Buffer != NULL) 7315 midl_user_free(InfoBuffer->All.LmOwfPassword.Buffer); 7316 7317 if (InfoBuffer->All.NtOwfPassword.Buffer != NULL) 7318 midl_user_free(InfoBuffer->All.NtOwfPassword.Buffer); 7319 7320 if (InfoBuffer->All.PrivateData.Buffer != NULL) 7321 midl_user_free(InfoBuffer->All.PrivateData.Buffer); 7322 7323 if (InfoBuffer->All.SecurityDescriptor.SecurityDescriptor != NULL) 7324 midl_user_free(InfoBuffer->All.SecurityDescriptor.SecurityDescriptor); 7325 7326 midl_user_free(InfoBuffer); 7327 } 7328 } 7329 7330 return Status; 7331 } 7332 7333 7334 /* Function 36 */ 7335 NTSTATUS 7336 NTAPI 7337 SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle, 7338 IN USER_INFORMATION_CLASS UserInformationClass, 7339 OUT PSAMPR_USER_INFO_BUFFER *Buffer) 7340 { 7341 PSAM_DB_OBJECT UserObject; 7342 ACCESS_MASK DesiredAccess; 7343 NTSTATUS Status; 7344 7345 TRACE("SamrQueryInformationUser(%p %lu %p)\n", 7346 UserHandle, UserInformationClass, Buffer); 7347 7348 switch (UserInformationClass) 7349 { 7350 case UserGeneralInformation: 7351 case UserNameInformation: 7352 case UserAccountNameInformation: 7353 case UserFullNameInformation: 7354 case UserPrimaryGroupInformation: 7355 case UserAdminCommentInformation: 7356 DesiredAccess = USER_READ_GENERAL; 7357 break; 7358 7359 case UserLogonHoursInformation: 7360 case UserHomeInformation: 7361 case UserScriptInformation: 7362 case UserProfileInformation: 7363 case UserWorkStationsInformation: 7364 DesiredAccess = USER_READ_LOGON; 7365 break; 7366 7367 case UserControlInformation: 7368 case UserExpiresInformation: 7369 case UserParametersInformation: 7370 DesiredAccess = USER_READ_ACCOUNT; 7371 break; 7372 7373 case UserPreferencesInformation: 7374 DesiredAccess = USER_READ_GENERAL | 7375 USER_READ_PREFERENCES; 7376 break; 7377 7378 case UserLogonInformation: 7379 case UserAccountInformation: 7380 DesiredAccess = USER_READ_GENERAL | 7381 USER_READ_PREFERENCES | 7382 USER_READ_LOGON | 7383 USER_READ_ACCOUNT; 7384 break; 7385 7386 case UserInternal1Information: 7387 case UserInternal2Information: 7388 case UserAllInformation: 7389 DesiredAccess = 0; 7390 break; 7391 7392 default: 7393 return STATUS_INVALID_INFO_CLASS; 7394 } 7395 7396 RtlAcquireResourceShared(&SampResource, 7397 TRUE); 7398 7399 /* Validate the domain handle */ 7400 Status = SampValidateDbObject(UserHandle, 7401 SamDbUserObject, 7402 DesiredAccess, 7403 &UserObject); 7404 if (!NT_SUCCESS(Status)) 7405 { 7406 TRACE("failed with status 0x%08lx\n", Status); 7407 goto done; 7408 } 7409 7410 switch (UserInformationClass) 7411 { 7412 case UserGeneralInformation: 7413 Status = SampQueryUserGeneral(UserObject, 7414 Buffer); 7415 break; 7416 7417 case UserPreferencesInformation: 7418 Status = SampQueryUserPreferences(UserObject, 7419 Buffer); 7420 break; 7421 7422 case UserLogonInformation: 7423 Status = SampQueryUserLogon(UserObject, 7424 Buffer); 7425 break; 7426 7427 case UserLogonHoursInformation: 7428 Status = SampQueryUserLogonHours(UserObject, 7429 Buffer); 7430 break; 7431 7432 case UserAccountInformation: 7433 Status = SampQueryUserAccount(UserObject, 7434 Buffer); 7435 break; 7436 7437 case UserNameInformation: 7438 Status = SampQueryUserName(UserObject, 7439 Buffer); 7440 break; 7441 7442 case UserAccountNameInformation: 7443 Status = SampQueryUserAccountName(UserObject, 7444 Buffer); 7445 break; 7446 7447 case UserFullNameInformation: 7448 Status = SampQueryUserFullName(UserObject, 7449 Buffer); 7450 break; 7451 7452 case UserPrimaryGroupInformation: 7453 Status = SampQueryUserPrimaryGroup(UserObject, 7454 Buffer); 7455 break; 7456 7457 case UserHomeInformation: 7458 Status = SampQueryUserHome(UserObject, 7459 Buffer); 7460 break; 7461 7462 case UserScriptInformation: 7463 Status = SampQueryUserScript(UserObject, 7464 Buffer); 7465 break; 7466 7467 case UserProfileInformation: 7468 Status = SampQueryUserProfile(UserObject, 7469 Buffer); 7470 break; 7471 7472 case UserAdminCommentInformation: 7473 Status = SampQueryUserAdminComment(UserObject, 7474 Buffer); 7475 break; 7476 7477 case UserWorkStationsInformation: 7478 Status = SampQueryUserWorkStations(UserObject, 7479 Buffer); 7480 break; 7481 7482 case UserControlInformation: 7483 Status = SampQueryUserControl(UserObject, 7484 Buffer); 7485 break; 7486 7487 case UserExpiresInformation: 7488 Status = SampQueryUserExpires(UserObject, 7489 Buffer); 7490 break; 7491 7492 case UserInternal1Information: 7493 Status = SampQueryUserInternal1(UserObject, 7494 Buffer); 7495 break; 7496 7497 case UserInternal2Information: 7498 Status = SampQueryUserInternal2(UserObject, 7499 Buffer); 7500 break; 7501 7502 case UserParametersInformation: 7503 Status = SampQueryUserParameters(UserObject, 7504 Buffer); 7505 break; 7506 7507 case UserAllInformation: 7508 Status = SampQueryUserAll(UserObject, 7509 Buffer); 7510 break; 7511 7512 // case UserInternal4Information: 7513 // case UserInternal5Information: 7514 // case UserInternal4InformationNew: 7515 // case UserInternal5InformationNew: 7516 7517 default: 7518 Status = STATUS_INVALID_INFO_CLASS; 7519 } 7520 7521 done: 7522 RtlReleaseResource(&SampResource); 7523 7524 return Status; 7525 } 7526 7527 7528 static NTSTATUS 7529 SampSetUserName(PSAM_DB_OBJECT UserObject, 7530 PRPC_UNICODE_STRING NewUserName) 7531 { 7532 UNICODE_STRING OldUserName = {0, 0, NULL}; 7533 NTSTATUS Status; 7534 7535 /* Check the account name */ 7536 Status = SampCheckAccountName(NewUserName, 20); 7537 if (!NT_SUCCESS(Status)) 7538 { 7539 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 7540 return Status; 7541 } 7542 7543 Status = SampGetObjectAttributeString(UserObject, 7544 L"Name", 7545 (PRPC_UNICODE_STRING)&OldUserName); 7546 if (!NT_SUCCESS(Status)) 7547 { 7548 TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status); 7549 goto done; 7550 } 7551 7552 if (!RtlEqualUnicodeString(&OldUserName, (PCUNICODE_STRING)NewUserName, TRUE)) 7553 { 7554 Status = SampCheckAccountNameInDomain(UserObject->ParentObject, 7555 NewUserName->Buffer); 7556 if (!NT_SUCCESS(Status)) 7557 { 7558 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n", 7559 NewUserName->Buffer, Status); 7560 goto done; 7561 } 7562 } 7563 7564 Status = SampSetAccountNameInDomain(UserObject->ParentObject, 7565 L"Users", 7566 NewUserName->Buffer, 7567 UserObject->RelativeId); 7568 if (!NT_SUCCESS(Status)) 7569 { 7570 TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status); 7571 goto done; 7572 } 7573 7574 Status = SampRemoveAccountNameFromDomain(UserObject->ParentObject, 7575 L"Users", 7576 OldUserName.Buffer); 7577 if (!NT_SUCCESS(Status)) 7578 { 7579 TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status); 7580 goto done; 7581 } 7582 7583 Status = SampSetObjectAttributeString(UserObject, 7584 L"Name", 7585 NewUserName); 7586 if (!NT_SUCCESS(Status)) 7587 { 7588 TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status); 7589 } 7590 7591 done: 7592 if (OldUserName.Buffer != NULL) 7593 midl_user_free(OldUserName.Buffer); 7594 7595 return Status; 7596 } 7597 7598 7599 static NTSTATUS 7600 SampSetUserGeneral(PSAM_DB_OBJECT UserObject, 7601 PSAMPR_USER_INFO_BUFFER Buffer) 7602 { 7603 SAM_USER_FIXED_DATA FixedData; 7604 ULONG Length = 0; 7605 NTSTATUS Status; 7606 7607 Length = sizeof(SAM_USER_FIXED_DATA); 7608 Status = SampGetObjectAttribute(UserObject, 7609 L"F", 7610 NULL, 7611 (PVOID)&FixedData, 7612 &Length); 7613 if (!NT_SUCCESS(Status)) 7614 goto done; 7615 7616 FixedData.PrimaryGroupId = Buffer->General.PrimaryGroupId; 7617 7618 Status = SampSetObjectAttribute(UserObject, 7619 L"F", 7620 REG_BINARY, 7621 &FixedData, 7622 Length); 7623 if (!NT_SUCCESS(Status)) 7624 goto done; 7625 7626 Status = SampSetUserName(UserObject, 7627 &Buffer->General.UserName); 7628 if (!NT_SUCCESS(Status)) 7629 goto done; 7630 7631 Status = SampSetObjectAttributeString(UserObject, 7632 L"FullName", 7633 &Buffer->General.FullName); 7634 if (!NT_SUCCESS(Status)) 7635 goto done; 7636 7637 Status = SampSetObjectAttributeString(UserObject, 7638 L"AdminComment", 7639 &Buffer->General.AdminComment); 7640 if (!NT_SUCCESS(Status)) 7641 goto done; 7642 7643 Status = SampSetObjectAttributeString(UserObject, 7644 L"UserComment", 7645 &Buffer->General.UserComment); 7646 7647 done: 7648 return Status; 7649 } 7650 7651 7652 static NTSTATUS 7653 SampSetUserPreferences(PSAM_DB_OBJECT UserObject, 7654 PSAMPR_USER_INFO_BUFFER Buffer) 7655 { 7656 SAM_USER_FIXED_DATA FixedData; 7657 ULONG Length = 0; 7658 NTSTATUS Status; 7659 7660 Length = sizeof(SAM_USER_FIXED_DATA); 7661 Status = SampGetObjectAttribute(UserObject, 7662 L"F", 7663 NULL, 7664 (PVOID)&FixedData, 7665 &Length); 7666 if (!NT_SUCCESS(Status)) 7667 goto done; 7668 7669 FixedData.CountryCode = Buffer->Preferences.CountryCode; 7670 FixedData.CodePage = Buffer->Preferences.CodePage; 7671 7672 Status = SampSetObjectAttribute(UserObject, 7673 L"F", 7674 REG_BINARY, 7675 &FixedData, 7676 Length); 7677 if (!NT_SUCCESS(Status)) 7678 goto done; 7679 7680 Status = SampSetObjectAttributeString(UserObject, 7681 L"UserComment", 7682 &Buffer->Preferences.UserComment); 7683 7684 done: 7685 return Status; 7686 } 7687 7688 7689 static NTSTATUS 7690 SampSetUserPrimaryGroup(PSAM_DB_OBJECT UserObject, 7691 PSAMPR_USER_INFO_BUFFER Buffer) 7692 { 7693 SAM_USER_FIXED_DATA FixedData; 7694 ULONG Length = 0; 7695 NTSTATUS Status; 7696 7697 Length = sizeof(SAM_USER_FIXED_DATA); 7698 Status = SampGetObjectAttribute(UserObject, 7699 L"F", 7700 NULL, 7701 (PVOID)&FixedData, 7702 &Length); 7703 if (!NT_SUCCESS(Status)) 7704 goto done; 7705 7706 FixedData.PrimaryGroupId = Buffer->PrimaryGroup.PrimaryGroupId; 7707 7708 Status = SampSetObjectAttribute(UserObject, 7709 L"F", 7710 REG_BINARY, 7711 &FixedData, 7712 Length); 7713 7714 done: 7715 return Status; 7716 } 7717 7718 7719 static NTSTATUS 7720 SampSetUserControl(PSAM_DB_OBJECT UserObject, 7721 PSAMPR_USER_INFO_BUFFER Buffer) 7722 { 7723 SAM_USER_FIXED_DATA FixedData; 7724 ULONG Length = 0; 7725 NTSTATUS Status; 7726 7727 Length = sizeof(SAM_USER_FIXED_DATA); 7728 Status = SampGetObjectAttribute(UserObject, 7729 L"F", 7730 NULL, 7731 (PVOID)&FixedData, 7732 &Length); 7733 if (!NT_SUCCESS(Status)) 7734 goto done; 7735 7736 FixedData.UserAccountControl = Buffer->Control.UserAccountControl; 7737 7738 Status = SampSetObjectAttribute(UserObject, 7739 L"F", 7740 REG_BINARY, 7741 &FixedData, 7742 Length); 7743 7744 done: 7745 return Status; 7746 } 7747 7748 7749 static NTSTATUS 7750 SampSetUserExpires(PSAM_DB_OBJECT UserObject, 7751 PSAMPR_USER_INFO_BUFFER Buffer) 7752 { 7753 SAM_USER_FIXED_DATA FixedData; 7754 ULONG Length = 0; 7755 NTSTATUS Status; 7756 7757 Length = sizeof(SAM_USER_FIXED_DATA); 7758 Status = SampGetObjectAttribute(UserObject, 7759 L"F", 7760 NULL, 7761 (PVOID)&FixedData, 7762 &Length); 7763 if (!NT_SUCCESS(Status)) 7764 goto done; 7765 7766 FixedData.AccountExpires.LowPart = Buffer->Expires.AccountExpires.LowPart; 7767 FixedData.AccountExpires.HighPart = Buffer->Expires.AccountExpires.HighPart; 7768 7769 Status = SampSetObjectAttribute(UserObject, 7770 L"F", 7771 REG_BINARY, 7772 &FixedData, 7773 Length); 7774 7775 done: 7776 return Status; 7777 } 7778 7779 7780 static NTSTATUS 7781 SampSetUserInternal1(PSAM_DB_OBJECT UserObject, 7782 PSAMPR_USER_INFO_BUFFER Buffer) 7783 { 7784 SAM_USER_FIXED_DATA FixedData; 7785 ULONG Length = 0; 7786 NTSTATUS Status = STATUS_SUCCESS; 7787 7788 /* FIXME: Decrypt NT password */ 7789 /* FIXME: Decrypt LM password */ 7790 7791 Status = SampSetUserPassword(UserObject, 7792 &Buffer->Internal1.EncryptedNtOwfPassword, 7793 Buffer->Internal1.NtPasswordPresent, 7794 &Buffer->Internal1.EncryptedLmOwfPassword, 7795 Buffer->Internal1.LmPasswordPresent); 7796 if (!NT_SUCCESS(Status)) 7797 goto done; 7798 7799 /* Get the fixed user attributes */ 7800 Length = sizeof(SAM_USER_FIXED_DATA); 7801 Status = SampGetObjectAttribute(UserObject, 7802 L"F", 7803 NULL, 7804 (PVOID)&FixedData, 7805 &Length); 7806 if (!NT_SUCCESS(Status)) 7807 goto done; 7808 7809 if (Buffer->Internal1.PasswordExpired) 7810 { 7811 /* The password was last set ages ago */ 7812 FixedData.PasswordLastSet.LowPart = 0; 7813 FixedData.PasswordLastSet.HighPart = 0; 7814 } 7815 else 7816 { 7817 /* The password was last set right now */ 7818 Status = NtQuerySystemTime(&FixedData.PasswordLastSet); 7819 if (!NT_SUCCESS(Status)) 7820 goto done; 7821 } 7822 7823 /* Set the fixed user attributes */ 7824 Status = SampSetObjectAttribute(UserObject, 7825 L"F", 7826 REG_BINARY, 7827 &FixedData, 7828 Length); 7829 7830 done: 7831 return Status; 7832 } 7833 7834 7835 static NTSTATUS 7836 SampSetUserInternal2(PSAM_DB_OBJECT UserObject, 7837 PSAMPR_USER_INFO_BUFFER Buffer) 7838 { 7839 SAM_USER_FIXED_DATA FixedData; 7840 ULONG Length = 0; 7841 NTSTATUS Status = STATUS_SUCCESS; 7842 7843 /* Get the fixed user attributes */ 7844 Length = sizeof(SAM_USER_FIXED_DATA); 7845 Status = SampGetObjectAttribute(UserObject, 7846 L"F", 7847 NULL, 7848 (PVOID)&FixedData, 7849 &Length); 7850 if (!NT_SUCCESS(Status)) 7851 goto done; 7852 7853 if ((Buffer->Internal2.Flags & USER_LOGON_SUCCESS) && 7854 ((Buffer->Internal2.Flags & ~USER_LOGON_SUCCESS) == 0)) 7855 { 7856 /* Update the LastLogon time */ 7857 Status = NtQuerySystemTime(&FixedData.LastLogon); 7858 if (!NT_SUCCESS(Status)) 7859 goto done; 7860 7861 FixedData.LogonCount++; 7862 FixedData.BadPasswordCount = 0; 7863 } 7864 7865 if ((Buffer->Internal2.Flags & USER_LOGON_BAD_PASSWORD) && 7866 ((Buffer->Internal2.Flags & ~USER_LOGON_BAD_PASSWORD) == 0)) 7867 { 7868 /* Update the LastBadPasswordTime */ 7869 Status = NtQuerySystemTime(&FixedData.LastBadPasswordTime); 7870 if (!NT_SUCCESS(Status)) 7871 goto done; 7872 7873 FixedData.BadPasswordCount++; 7874 } 7875 7876 /* Set the fixed user attributes */ 7877 Status = SampSetObjectAttribute(UserObject, 7878 L"F", 7879 REG_BINARY, 7880 &FixedData, 7881 Length); 7882 7883 done: 7884 return Status; 7885 } 7886 7887 7888 static NTSTATUS 7889 SampSetUserAll(PSAM_DB_OBJECT UserObject, 7890 PSAMPR_USER_INFO_BUFFER Buffer) 7891 { 7892 SAM_USER_FIXED_DATA FixedData; 7893 ULONG Length = 0; 7894 ULONG WhichFields; 7895 PENCRYPTED_NT_OWF_PASSWORD NtPassword = NULL; 7896 PENCRYPTED_LM_OWF_PASSWORD LmPassword = NULL; 7897 BOOLEAN NtPasswordPresent = FALSE; 7898 BOOLEAN LmPasswordPresent = FALSE; 7899 BOOLEAN WriteFixedData = FALSE; 7900 NTSTATUS Status = STATUS_SUCCESS; 7901 7902 WhichFields = Buffer->All.WhichFields; 7903 7904 /* Get the fixed size attributes */ 7905 Length = sizeof(SAM_USER_FIXED_DATA); 7906 Status = SampGetObjectAttribute(UserObject, 7907 L"F", 7908 NULL, 7909 (PVOID)&FixedData, 7910 &Length); 7911 if (!NT_SUCCESS(Status)) 7912 goto done; 7913 7914 if (WhichFields & USER_ALL_USERNAME) 7915 { 7916 Status = SampSetUserName(UserObject, 7917 &Buffer->All.UserName); 7918 if (!NT_SUCCESS(Status)) 7919 goto done; 7920 } 7921 7922 if (WhichFields & USER_ALL_FULLNAME) 7923 { 7924 Status = SampSetObjectAttributeString(UserObject, 7925 L"FullName", 7926 &Buffer->All.FullName); 7927 if (!NT_SUCCESS(Status)) 7928 goto done; 7929 } 7930 7931 if (WhichFields & USER_ALL_ADMINCOMMENT) 7932 { 7933 Status = SampSetObjectAttributeString(UserObject, 7934 L"AdminComment", 7935 &Buffer->All.AdminComment); 7936 if (!NT_SUCCESS(Status)) 7937 goto done; 7938 } 7939 7940 if (WhichFields & USER_ALL_USERCOMMENT) 7941 { 7942 Status = SampSetObjectAttributeString(UserObject, 7943 L"UserComment", 7944 &Buffer->All.UserComment); 7945 if (!NT_SUCCESS(Status)) 7946 goto done; 7947 } 7948 7949 if (WhichFields & USER_ALL_HOMEDIRECTORY) 7950 { 7951 Status = SampSetObjectAttributeString(UserObject, 7952 L"HomeDirectory", 7953 &Buffer->All.HomeDirectory); 7954 if (!NT_SUCCESS(Status)) 7955 goto done; 7956 } 7957 7958 if (WhichFields & USER_ALL_HOMEDIRECTORYDRIVE) 7959 { 7960 Status = SampSetObjectAttributeString(UserObject, 7961 L"HomeDirectoryDrive", 7962 &Buffer->All.HomeDirectoryDrive); 7963 if (!NT_SUCCESS(Status)) 7964 goto done; 7965 } 7966 7967 if (WhichFields & USER_ALL_SCRIPTPATH) 7968 { 7969 Status = SampSetObjectAttributeString(UserObject, 7970 L"ScriptPath", 7971 &Buffer->All.ScriptPath); 7972 if (!NT_SUCCESS(Status)) 7973 goto done; 7974 } 7975 7976 if (WhichFields & USER_ALL_PROFILEPATH) 7977 { 7978 Status = SampSetObjectAttributeString(UserObject, 7979 L"ProfilePath", 7980 &Buffer->All.ProfilePath); 7981 if (!NT_SUCCESS(Status)) 7982 goto done; 7983 } 7984 7985 if (WhichFields & USER_ALL_WORKSTATIONS) 7986 { 7987 Status = SampSetObjectAttributeString(UserObject, 7988 L"WorkStations", 7989 &Buffer->All.WorkStations); 7990 if (!NT_SUCCESS(Status)) 7991 goto done; 7992 } 7993 7994 if (WhichFields & USER_ALL_PARAMETERS) 7995 { 7996 Status = SampSetObjectAttributeString(UserObject, 7997 L"Parameters", 7998 &Buffer->All.Parameters); 7999 if (!NT_SUCCESS(Status)) 8000 goto done; 8001 } 8002 8003 if (WhichFields & USER_ALL_LOGONHOURS) 8004 { 8005 Status = SampSetLogonHoursAttribute(UserObject, 8006 &Buffer->All.LogonHours); 8007 if (!NT_SUCCESS(Status)) 8008 goto done; 8009 } 8010 8011 if (WhichFields & USER_ALL_PRIMARYGROUPID) 8012 { 8013 FixedData.PrimaryGroupId = Buffer->All.PrimaryGroupId; 8014 WriteFixedData = TRUE; 8015 } 8016 8017 if (WhichFields & USER_ALL_ACCOUNTEXPIRES) 8018 { 8019 FixedData.AccountExpires.LowPart = Buffer->All.AccountExpires.LowPart; 8020 FixedData.AccountExpires.HighPart = Buffer->All.AccountExpires.HighPart; 8021 WriteFixedData = TRUE; 8022 } 8023 8024 if (WhichFields & USER_ALL_USERACCOUNTCONTROL) 8025 { 8026 FixedData.UserAccountControl = Buffer->All.UserAccountControl; 8027 WriteFixedData = TRUE; 8028 } 8029 8030 if (WhichFields & USER_ALL_COUNTRYCODE) 8031 { 8032 FixedData.CountryCode = Buffer->All.CountryCode; 8033 WriteFixedData = TRUE; 8034 } 8035 8036 if (WhichFields & USER_ALL_CODEPAGE) 8037 { 8038 FixedData.CodePage = Buffer->All.CodePage; 8039 WriteFixedData = TRUE; 8040 } 8041 8042 if (WhichFields & (USER_ALL_NTPASSWORDPRESENT | 8043 USER_ALL_LMPASSWORDPRESENT)) 8044 { 8045 if (WhichFields & USER_ALL_NTPASSWORDPRESENT) 8046 { 8047 NtPassword = (PENCRYPTED_NT_OWF_PASSWORD)Buffer->All.NtOwfPassword.Buffer; 8048 NtPasswordPresent = Buffer->All.NtPasswordPresent; 8049 } 8050 8051 if (WhichFields & USER_ALL_LMPASSWORDPRESENT) 8052 { 8053 LmPassword = (PENCRYPTED_LM_OWF_PASSWORD)Buffer->All.LmOwfPassword.Buffer; 8054 LmPasswordPresent = Buffer->All.LmPasswordPresent; 8055 } 8056 8057 Status = SampSetUserPassword(UserObject, 8058 NtPassword, 8059 NtPasswordPresent, 8060 LmPassword, 8061 LmPasswordPresent); 8062 if (!NT_SUCCESS(Status)) 8063 goto done; 8064 8065 /* The password has just been set */ 8066 Status = NtQuerySystemTime(&FixedData.PasswordLastSet); 8067 if (!NT_SUCCESS(Status)) 8068 goto done; 8069 8070 WriteFixedData = TRUE; 8071 } 8072 8073 if (WhichFields & USER_ALL_PRIVATEDATA) 8074 { 8075 Status = SampSetObjectAttributeString(UserObject, 8076 L"PrivateData", 8077 &Buffer->All.PrivateData); 8078 if (!NT_SUCCESS(Status)) 8079 goto done; 8080 } 8081 8082 if (WhichFields & USER_ALL_PASSWORDEXPIRED) 8083 { 8084 if (Buffer->All.PasswordExpired) 8085 { 8086 /* The password was last set ages ago */ 8087 FixedData.PasswordLastSet.LowPart = 0; 8088 FixedData.PasswordLastSet.HighPart = 0; 8089 } 8090 else 8091 { 8092 /* The password was last set right now */ 8093 Status = NtQuerySystemTime(&FixedData.PasswordLastSet); 8094 if (!NT_SUCCESS(Status)) 8095 goto done; 8096 } 8097 8098 WriteFixedData = TRUE; 8099 } 8100 8101 if (WhichFields & USER_ALL_SECURITYDESCRIPTOR) 8102 { 8103 Status = SampSetObjectAttribute(UserObject, 8104 L"SecDesc", 8105 REG_BINARY, 8106 Buffer->All.SecurityDescriptor.SecurityDescriptor, 8107 Buffer->All.SecurityDescriptor.Length); 8108 } 8109 8110 if (WriteFixedData != FALSE) 8111 { 8112 Status = SampSetObjectAttribute(UserObject, 8113 L"F", 8114 REG_BINARY, 8115 &FixedData, 8116 Length); 8117 if (!NT_SUCCESS(Status)) 8118 goto done; 8119 } 8120 8121 done: 8122 return Status; 8123 } 8124 8125 8126 /* Function 37 */ 8127 NTSTATUS 8128 NTAPI 8129 SamrSetInformationUser(IN SAMPR_HANDLE UserHandle, 8130 IN USER_INFORMATION_CLASS UserInformationClass, 8131 IN PSAMPR_USER_INFO_BUFFER Buffer) 8132 { 8133 PSAM_DB_OBJECT UserObject; 8134 ACCESS_MASK DesiredAccess; 8135 NTSTATUS Status; 8136 8137 TRACE("SamrSetInformationUser(%p %lu %p)\n", 8138 UserHandle, UserInformationClass, Buffer); 8139 8140 switch (UserInformationClass) 8141 { 8142 case UserLogonHoursInformation: 8143 case UserNameInformation: 8144 case UserAccountNameInformation: 8145 case UserFullNameInformation: 8146 case UserPrimaryGroupInformation: 8147 case UserHomeInformation: 8148 case UserScriptInformation: 8149 case UserProfileInformation: 8150 case UserAdminCommentInformation: 8151 case UserWorkStationsInformation: 8152 case UserControlInformation: 8153 case UserExpiresInformation: 8154 case UserParametersInformation: 8155 DesiredAccess = USER_WRITE_ACCOUNT; 8156 break; 8157 8158 case UserGeneralInformation: 8159 DesiredAccess = USER_WRITE_ACCOUNT | 8160 USER_WRITE_PREFERENCES; 8161 break; 8162 8163 case UserPreferencesInformation: 8164 DesiredAccess = USER_WRITE_PREFERENCES; 8165 break; 8166 8167 case UserSetPasswordInformation: 8168 case UserInternal1Information: 8169 DesiredAccess = USER_FORCE_PASSWORD_CHANGE; 8170 break; 8171 8172 case UserAllInformation: 8173 case UserInternal2Information: 8174 DesiredAccess = 0; /* FIXME */ 8175 break; 8176 8177 default: 8178 return STATUS_INVALID_INFO_CLASS; 8179 } 8180 8181 RtlAcquireResourceExclusive(&SampResource, 8182 TRUE); 8183 8184 /* Validate the domain handle */ 8185 Status = SampValidateDbObject(UserHandle, 8186 SamDbUserObject, 8187 DesiredAccess, 8188 &UserObject); 8189 if (!NT_SUCCESS(Status)) 8190 { 8191 TRACE("failed with status 0x%08lx\n", Status); 8192 goto done; 8193 } 8194 8195 switch (UserInformationClass) 8196 { 8197 case UserGeneralInformation: 8198 Status = SampSetUserGeneral(UserObject, 8199 Buffer); 8200 break; 8201 8202 case UserPreferencesInformation: 8203 Status = SampSetUserPreferences(UserObject, 8204 Buffer); 8205 break; 8206 8207 case UserLogonHoursInformation: 8208 Status = SampSetLogonHoursAttribute(UserObject, 8209 &Buffer->LogonHours.LogonHours); 8210 break; 8211 8212 case UserNameInformation: 8213 Status = SampSetUserName(UserObject, 8214 &Buffer->Name.UserName); 8215 if (!NT_SUCCESS(Status)) 8216 break; 8217 8218 Status = SampSetObjectAttributeString(UserObject, 8219 L"FullName", 8220 &Buffer->Name.FullName); 8221 break; 8222 8223 case UserAccountNameInformation: 8224 Status = SampSetUserName(UserObject, 8225 &Buffer->AccountName.UserName); 8226 break; 8227 8228 case UserFullNameInformation: 8229 Status = SampSetObjectAttributeString(UserObject, 8230 L"FullName", 8231 &Buffer->FullName.FullName); 8232 break; 8233 8234 case UserPrimaryGroupInformation: 8235 Status = SampSetUserPrimaryGroup(UserObject, 8236 Buffer); 8237 break; 8238 8239 case UserHomeInformation: 8240 Status = SampSetObjectAttributeString(UserObject, 8241 L"HomeDirectory", 8242 &Buffer->Home.HomeDirectory); 8243 if (!NT_SUCCESS(Status)) 8244 break; 8245 8246 Status = SampSetObjectAttributeString(UserObject, 8247 L"HomeDirectoryDrive", 8248 &Buffer->Home.HomeDirectoryDrive); 8249 break; 8250 8251 case UserScriptInformation: 8252 Status = SampSetObjectAttributeString(UserObject, 8253 L"ScriptPath", 8254 &Buffer->Script.ScriptPath); 8255 break; 8256 8257 case UserProfileInformation: 8258 Status = SampSetObjectAttributeString(UserObject, 8259 L"ProfilePath", 8260 &Buffer->Profile.ProfilePath); 8261 break; 8262 8263 case UserAdminCommentInformation: 8264 Status = SampSetObjectAttributeString(UserObject, 8265 L"AdminComment", 8266 &Buffer->AdminComment.AdminComment); 8267 break; 8268 8269 case UserWorkStationsInformation: 8270 Status = SampSetObjectAttributeString(UserObject, 8271 L"WorkStations", 8272 &Buffer->WorkStations.WorkStations); 8273 break; 8274 8275 case UserSetPasswordInformation: 8276 TRACE("Password: %S\n", Buffer->SetPassword.Password.Buffer); 8277 TRACE("PasswordExpired: %d\n", Buffer->SetPassword.PasswordExpired); 8278 8279 Status = SampSetObjectAttributeString(UserObject, 8280 L"Password", 8281 &Buffer->SetPassword.Password); 8282 break; 8283 8284 case UserControlInformation: 8285 Status = SampSetUserControl(UserObject, 8286 Buffer); 8287 break; 8288 8289 case UserExpiresInformation: 8290 Status = SampSetUserExpires(UserObject, 8291 Buffer); 8292 break; 8293 8294 case UserInternal1Information: 8295 Status = SampSetUserInternal1(UserObject, 8296 Buffer); 8297 break; 8298 8299 case UserInternal2Information: 8300 Status = SampSetUserInternal2(UserObject, 8301 Buffer); 8302 break; 8303 8304 case UserParametersInformation: 8305 Status = SampSetObjectAttributeString(UserObject, 8306 L"Parameters", 8307 &Buffer->Parameters.Parameters); 8308 break; 8309 8310 case UserAllInformation: 8311 Status = SampSetUserAll(UserObject, 8312 Buffer); 8313 break; 8314 8315 // case UserInternal4Information: 8316 // case UserInternal5Information: 8317 // case UserInternal4InformationNew: 8318 // case UserInternal5InformationNew: 8319 8320 default: 8321 Status = STATUS_INVALID_INFO_CLASS; 8322 } 8323 8324 done: 8325 RtlReleaseResource(&SampResource); 8326 8327 return Status; 8328 } 8329 8330 8331 /* Function 38 */ 8332 NTSTATUS 8333 NTAPI 8334 SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle, 8335 IN unsigned char LmPresent, 8336 IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm, 8337 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm, 8338 IN unsigned char NtPresent, 8339 IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt, 8340 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt, 8341 IN unsigned char NtCrossEncryptionPresent, 8342 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm, 8343 IN unsigned char LmCrossEncryptionPresent, 8344 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt) 8345 { 8346 ENCRYPTED_LM_OWF_PASSWORD StoredLmPassword; 8347 ENCRYPTED_NT_OWF_PASSWORD StoredNtPassword; 8348 LM_OWF_PASSWORD OldLmPassword; 8349 LM_OWF_PASSWORD NewLmPassword; 8350 NT_OWF_PASSWORD OldNtPassword; 8351 NT_OWF_PASSWORD NewNtPassword; 8352 BOOLEAN StoredLmPresent = FALSE; 8353 BOOLEAN StoredNtPresent = FALSE; 8354 BOOLEAN StoredLmEmpty = TRUE; 8355 BOOLEAN StoredNtEmpty = TRUE; 8356 PSAM_DB_OBJECT UserObject; 8357 ULONG Length; 8358 SAM_USER_FIXED_DATA UserFixedData; 8359 SAM_DOMAIN_FIXED_DATA DomainFixedData; 8360 LARGE_INTEGER SystemTime; 8361 NTSTATUS Status; 8362 8363 DBG_UNREFERENCED_LOCAL_VARIABLE(StoredLmPresent); 8364 DBG_UNREFERENCED_LOCAL_VARIABLE(StoredNtPresent); 8365 DBG_UNREFERENCED_LOCAL_VARIABLE(StoredLmEmpty); 8366 8367 TRACE("SamrChangePasswordUser(%p %u %p %p %u %p %p %u %p %u %p)\n", 8368 UserHandle, LmPresent, OldLmEncryptedWithNewLm, NewLmEncryptedWithOldLm, 8369 NtPresent, OldNtEncryptedWithNewNt, NewNtEncryptedWithOldNt, NtCrossEncryptionPresent, 8370 NewNtEncryptedWithNewLm, LmCrossEncryptionPresent, NewLmEncryptedWithNewNt); 8371 8372 RtlAcquireResourceExclusive(&SampResource, 8373 TRUE); 8374 8375 /* Validate the user handle */ 8376 Status = SampValidateDbObject(UserHandle, 8377 SamDbUserObject, 8378 USER_CHANGE_PASSWORD, 8379 &UserObject); 8380 if (!NT_SUCCESS(Status)) 8381 { 8382 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 8383 goto done; 8384 } 8385 8386 /* Get the current time */ 8387 Status = NtQuerySystemTime(&SystemTime); 8388 if (!NT_SUCCESS(Status)) 8389 { 8390 TRACE("NtQuerySystemTime failed (Status 0x%08lx)\n", Status); 8391 goto done; 8392 } 8393 8394 /* Retrieve the LM password */ 8395 Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD); 8396 Status = SampGetObjectAttribute(UserObject, 8397 L"LMPwd", 8398 NULL, 8399 &StoredLmPassword, 8400 &Length); 8401 if (NT_SUCCESS(Status)) 8402 { 8403 if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD)) 8404 { 8405 StoredLmPresent = TRUE; 8406 if (!RtlEqualMemory(&StoredLmPassword, 8407 &EmptyLmHash, 8408 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 8409 StoredLmEmpty = FALSE; 8410 } 8411 } 8412 8413 /* Retrieve the NT password */ 8414 Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD); 8415 Status = SampGetObjectAttribute(UserObject, 8416 L"NTPwd", 8417 NULL, 8418 &StoredNtPassword, 8419 &Length); 8420 if (NT_SUCCESS(Status)) 8421 { 8422 if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD)) 8423 { 8424 StoredNtPresent = TRUE; 8425 if (!RtlEqualMemory(&StoredNtPassword, 8426 &EmptyNtHash, 8427 sizeof(ENCRYPTED_NT_OWF_PASSWORD))) 8428 StoredNtEmpty = FALSE; 8429 } 8430 } 8431 8432 /* Retrieve the fixed size user data */ 8433 Length = sizeof(SAM_USER_FIXED_DATA); 8434 Status = SampGetObjectAttribute(UserObject, 8435 L"F", 8436 NULL, 8437 &UserFixedData, 8438 &Length); 8439 if (!NT_SUCCESS(Status)) 8440 { 8441 TRACE("SampGetObjectAttribute failed to retrieve the fixed user data (Status 0x%08lx)\n", Status); 8442 goto done; 8443 } 8444 8445 /* Check if we can change the password at this time */ 8446 if ((StoredLmEmpty == FALSE) || (StoredNtEmpty == FALSE)) 8447 { 8448 /* Get fixed domain data */ 8449 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 8450 Status = SampGetObjectAttribute(UserObject->ParentObject, 8451 L"F", 8452 NULL, 8453 &DomainFixedData, 8454 &Length); 8455 if (!NT_SUCCESS(Status)) 8456 { 8457 TRACE("SampGetObjectAttribute failed to retrieve the fixed domain data (Status 0x%08lx)\n", Status); 8458 goto done; 8459 } 8460 8461 if (DomainFixedData.MinPasswordAge.QuadPart > 0) 8462 { 8463 if (SystemTime.QuadPart < (UserFixedData.PasswordLastSet.QuadPart + DomainFixedData.MinPasswordAge.QuadPart)) 8464 { 8465 Status = STATUS_ACCOUNT_RESTRICTION; 8466 goto done; 8467 } 8468 } 8469 } 8470 8471 /* Decrypt the LM passwords, if present */ 8472 if (LmPresent) 8473 { 8474 Status = SystemFunction013((const BYTE *)NewLmEncryptedWithOldLm, 8475 (const BYTE *)&StoredLmPassword, 8476 (LPBYTE)&NewLmPassword); 8477 if (!NT_SUCCESS(Status)) 8478 { 8479 TRACE("SystemFunction013 failed (Status 0x%08lx)\n", Status); 8480 goto done; 8481 } 8482 8483 Status = SystemFunction013((const BYTE *)OldLmEncryptedWithNewLm, 8484 (const BYTE *)&NewLmPassword, 8485 (LPBYTE)&OldLmPassword); 8486 if (!NT_SUCCESS(Status)) 8487 { 8488 TRACE("SystemFunction013 failed (Status 0x%08lx)\n", Status); 8489 goto done; 8490 } 8491 } 8492 8493 /* Decrypt the NT passwords, if present */ 8494 if (NtPresent) 8495 { 8496 Status = SystemFunction013((const BYTE *)NewNtEncryptedWithOldNt, 8497 (const BYTE *)&StoredNtPassword, 8498 (LPBYTE)&NewNtPassword); 8499 if (!NT_SUCCESS(Status)) 8500 { 8501 TRACE("SystemFunction013 failed (Status 0x%08lx)\n", Status); 8502 goto done; 8503 } 8504 8505 Status = SystemFunction013((const BYTE *)OldNtEncryptedWithNewNt, 8506 (const BYTE *)&NewNtPassword, 8507 (LPBYTE)&OldNtPassword); 8508 if (!NT_SUCCESS(Status)) 8509 { 8510 TRACE("SystemFunction013 failed (Status 0x%08lx)\n", Status); 8511 goto done; 8512 } 8513 } 8514 8515 /* Check if the old passwords match the stored ones */ 8516 if (NtPresent) 8517 { 8518 if (LmPresent) 8519 { 8520 if (!RtlEqualMemory(&StoredLmPassword, 8521 &OldLmPassword, 8522 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 8523 { 8524 TRACE("Old LM Password does not match!\n"); 8525 Status = STATUS_WRONG_PASSWORD; 8526 } 8527 else 8528 { 8529 if (!RtlEqualMemory(&StoredNtPassword, 8530 &OldNtPassword, 8531 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 8532 { 8533 TRACE("Old NT Password does not match!\n"); 8534 Status = STATUS_WRONG_PASSWORD; 8535 } 8536 } 8537 } 8538 else 8539 { 8540 if (!RtlEqualMemory(&StoredNtPassword, 8541 &OldNtPassword, 8542 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 8543 { 8544 TRACE("Old NT Password does not match!\n"); 8545 Status = STATUS_WRONG_PASSWORD; 8546 } 8547 } 8548 } 8549 else 8550 { 8551 if (LmPresent) 8552 { 8553 if (!RtlEqualMemory(&StoredLmPassword, 8554 &OldLmPassword, 8555 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 8556 { 8557 TRACE("Old LM Password does not match!\n"); 8558 Status = STATUS_WRONG_PASSWORD; 8559 } 8560 } 8561 else 8562 { 8563 Status = STATUS_INVALID_PARAMETER; 8564 } 8565 } 8566 8567 /* Store the new password hashes */ 8568 if (NT_SUCCESS(Status)) 8569 { 8570 Status = SampSetUserPassword(UserObject, 8571 &NewNtPassword, 8572 NtPresent, 8573 &NewLmPassword, 8574 LmPresent); 8575 if (NT_SUCCESS(Status)) 8576 { 8577 /* Update PasswordLastSet */ 8578 UserFixedData.PasswordLastSet.QuadPart = SystemTime.QuadPart; 8579 8580 /* Set the fixed size user data */ 8581 Length = sizeof(SAM_USER_FIXED_DATA); 8582 Status = SampSetObjectAttribute(UserObject, 8583 L"F", 8584 REG_BINARY, 8585 &UserFixedData, 8586 Length); 8587 } 8588 } 8589 8590 if (Status == STATUS_WRONG_PASSWORD) 8591 { 8592 /* Update BadPasswordCount and LastBadPasswordTime */ 8593 UserFixedData.BadPasswordCount++; 8594 UserFixedData.LastBadPasswordTime.QuadPart = SystemTime.QuadPart; 8595 8596 /* Set the fixed size user data */ 8597 Length = sizeof(SAM_USER_FIXED_DATA); 8598 Status = SampSetObjectAttribute(UserObject, 8599 L"F", 8600 REG_BINARY, 8601 &UserFixedData, 8602 Length); 8603 } 8604 8605 done: 8606 RtlReleaseResource(&SampResource); 8607 8608 return Status; 8609 } 8610 8611 8612 /* Function 39 */ 8613 NTSTATUS 8614 NTAPI 8615 SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle, 8616 OUT PSAMPR_GET_GROUPS_BUFFER *Groups) 8617 { 8618 PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL; 8619 PSAM_DB_OBJECT UserObject; 8620 ULONG Length = 0; 8621 NTSTATUS Status; 8622 8623 TRACE("SamrGetGroupsForUser(%p %p)\n", 8624 UserHandle, Groups); 8625 8626 RtlAcquireResourceShared(&SampResource, 8627 TRUE); 8628 8629 /* Validate the user handle */ 8630 Status = SampValidateDbObject(UserHandle, 8631 SamDbUserObject, 8632 USER_LIST_GROUPS, 8633 &UserObject); 8634 if (!NT_SUCCESS(Status)) 8635 { 8636 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 8637 goto done; 8638 } 8639 8640 /* Allocate the groups buffer */ 8641 GroupsBuffer = midl_user_allocate(sizeof(SAMPR_GET_GROUPS_BUFFER)); 8642 if (GroupsBuffer == NULL) 8643 { 8644 Status = STATUS_INSUFFICIENT_RESOURCES; 8645 goto done; 8646 } 8647 8648 /* 8649 * Get the size of the Groups attribute. 8650 * Do not check the status code because in case of an error 8651 * Length will be 0. And that is all we need. 8652 */ 8653 SampGetObjectAttribute(UserObject, 8654 L"Groups", 8655 NULL, 8656 NULL, 8657 &Length); 8658 8659 /* If there is no Groups attribute, return a groups buffer without an array */ 8660 if (Length == 0) 8661 { 8662 GroupsBuffer->MembershipCount = 0; 8663 GroupsBuffer->Groups = NULL; 8664 8665 *Groups = GroupsBuffer; 8666 8667 Status = STATUS_SUCCESS; 8668 goto done; 8669 } 8670 8671 /* Allocate a buffer for the Groups attribute */ 8672 GroupsBuffer->Groups = midl_user_allocate(Length); 8673 if (GroupsBuffer->Groups == NULL) 8674 { 8675 Status = STATUS_INSUFFICIENT_RESOURCES; 8676 goto done; 8677 } 8678 8679 /* Retrieve the Grous attribute */ 8680 Status = SampGetObjectAttribute(UserObject, 8681 L"Groups", 8682 NULL, 8683 GroupsBuffer->Groups, 8684 &Length); 8685 if (!NT_SUCCESS(Status)) 8686 { 8687 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status); 8688 goto done; 8689 } 8690 8691 /* Calculate the membership count */ 8692 GroupsBuffer->MembershipCount = Length / sizeof(GROUP_MEMBERSHIP); 8693 8694 /* Return the groups buffer to the caller */ 8695 *Groups = GroupsBuffer; 8696 8697 done: 8698 if (!NT_SUCCESS(Status)) 8699 { 8700 if (GroupsBuffer != NULL) 8701 { 8702 if (GroupsBuffer->Groups != NULL) 8703 midl_user_free(GroupsBuffer->Groups); 8704 8705 midl_user_free(GroupsBuffer); 8706 } 8707 } 8708 8709 RtlReleaseResource(&SampResource); 8710 8711 return Status; 8712 } 8713 8714 8715 /* Function 40 */ 8716 NTSTATUS 8717 NTAPI 8718 SamrQueryDisplayInformation(IN SAMPR_HANDLE DomainHandle, 8719 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass, 8720 IN unsigned long Index, 8721 IN unsigned long EntryCount, 8722 IN unsigned long PreferredMaximumLength, 8723 OUT unsigned long *TotalAvailable, 8724 OUT unsigned long *TotalReturned, 8725 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer) 8726 { 8727 UNIMPLEMENTED; 8728 return STATUS_NOT_IMPLEMENTED; 8729 } 8730 8731 /* Function 41 */ 8732 NTSTATUS 8733 NTAPI 8734 SamrGetDisplayEnumerationIndex(IN SAMPR_HANDLE DomainHandle, 8735 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass, 8736 IN PRPC_UNICODE_STRING Prefix, 8737 OUT unsigned long *Index) 8738 { 8739 UNIMPLEMENTED; 8740 return STATUS_NOT_IMPLEMENTED; 8741 } 8742 8743 /* Function 42 */ 8744 NTSTATUS 8745 NTAPI 8746 SamrTestPrivateFunctionsDomain(IN SAMPR_HANDLE DomainHandle) 8747 { 8748 UNIMPLEMENTED; 8749 return STATUS_NOT_IMPLEMENTED; 8750 } 8751 8752 /* Function 43 */ 8753 NTSTATUS 8754 NTAPI 8755 SamrTestPrivateFunctionsUser(IN SAMPR_HANDLE UserHandle) 8756 { 8757 UNIMPLEMENTED; 8758 return STATUS_NOT_IMPLEMENTED; 8759 } 8760 8761 8762 /* Function 44 */ 8763 NTSTATUS 8764 NTAPI 8765 SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle, 8766 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation) 8767 { 8768 SAM_DOMAIN_FIXED_DATA DomainFixedData; 8769 SAM_USER_FIXED_DATA UserFixedData; 8770 PSAM_DB_OBJECT DomainObject; 8771 PSAM_DB_OBJECT UserObject; 8772 ULONG Length = 0; 8773 NTSTATUS Status; 8774 8775 TRACE("SamrGetUserDomainPasswordInformation(%p %p)\n", 8776 UserHandle, PasswordInformation); 8777 8778 RtlAcquireResourceShared(&SampResource, 8779 TRUE); 8780 8781 /* Validate the user handle */ 8782 Status = SampValidateDbObject(UserHandle, 8783 SamDbUserObject, 8784 0, 8785 &UserObject); 8786 if (!NT_SUCCESS(Status)) 8787 { 8788 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 8789 goto done; 8790 } 8791 8792 /* Validate the domain object */ 8793 Status = SampValidateDbObject((SAMPR_HANDLE)UserObject->ParentObject, 8794 SamDbDomainObject, 8795 DOMAIN_READ_PASSWORD_PARAMETERS, 8796 &DomainObject); 8797 if (!NT_SUCCESS(Status)) 8798 { 8799 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 8800 goto done; 8801 } 8802 8803 /* Get fixed user data */ 8804 Length = sizeof(SAM_USER_FIXED_DATA); 8805 Status = SampGetObjectAttribute(UserObject, 8806 L"F", 8807 NULL, 8808 (PVOID)&UserFixedData, 8809 &Length); 8810 if (!NT_SUCCESS(Status)) 8811 { 8812 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status); 8813 goto done; 8814 } 8815 8816 if ((UserObject->RelativeId == DOMAIN_USER_RID_KRBTGT) || 8817 (UserFixedData.UserAccountControl & (USER_INTERDOMAIN_TRUST_ACCOUNT | 8818 USER_WORKSTATION_TRUST_ACCOUNT | 8819 USER_SERVER_TRUST_ACCOUNT))) 8820 { 8821 PasswordInformation->MinPasswordLength = 0; 8822 PasswordInformation->PasswordProperties = 0; 8823 } 8824 else 8825 { 8826 /* Get fixed domain data */ 8827 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 8828 Status = SampGetObjectAttribute(DomainObject, 8829 L"F", 8830 NULL, 8831 (PVOID)&DomainFixedData, 8832 &Length); 8833 if (!NT_SUCCESS(Status)) 8834 { 8835 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status); 8836 goto done; 8837 } 8838 8839 PasswordInformation->MinPasswordLength = DomainFixedData.MinPasswordLength; 8840 PasswordInformation->PasswordProperties = DomainFixedData.PasswordProperties; 8841 } 8842 8843 done: 8844 RtlReleaseResource(&SampResource); 8845 8846 return STATUS_SUCCESS; 8847 } 8848 8849 8850 /* Function 45 */ 8851 NTSTATUS 8852 NTAPI 8853 SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle, 8854 IN PRPC_SID MemberSid) 8855 { 8856 PSAM_DB_OBJECT DomainObject; 8857 ULONG Rid = 0; 8858 NTSTATUS Status; 8859 8860 TRACE("SamrRemoveMemberFromForeignDomain(%p %p)\n", 8861 DomainHandle, MemberSid); 8862 8863 RtlAcquireResourceExclusive(&SampResource, 8864 TRUE); 8865 8866 /* Validate the domain object */ 8867 Status = SampValidateDbObject(DomainHandle, 8868 SamDbDomainObject, 8869 DOMAIN_LOOKUP, 8870 &DomainObject); 8871 if (!NT_SUCCESS(Status)) 8872 { 8873 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 8874 goto done; 8875 } 8876 8877 /* Retrieve the RID from the MemberSID */ 8878 Status = SampGetRidFromSid((PSID)MemberSid, 8879 &Rid); 8880 if (!NT_SUCCESS(Status)) 8881 { 8882 TRACE("SampGetRidFromSid failed with status 0x%08lx\n", Status); 8883 goto done; 8884 } 8885 8886 /* Fail, if the RID represents a special account */ 8887 if (Rid < 1000) 8888 { 8889 TRACE("Cannot remove a special account (RID: %lu)\n", Rid); 8890 Status = STATUS_SPECIAL_ACCOUNT; 8891 goto done; 8892 } 8893 8894 /* Remove the member from all aliases in the domain */ 8895 Status = SampRemoveMemberFromAllAliases(DomainObject, 8896 MemberSid); 8897 if (!NT_SUCCESS(Status)) 8898 { 8899 TRACE("SampRemoveMemberFromAllAliases failed with status 0x%08lx\n", Status); 8900 } 8901 8902 done: 8903 RtlReleaseResource(&SampResource); 8904 8905 return Status; 8906 } 8907 8908 8909 /* Function 46 */ 8910 NTSTATUS 8911 NTAPI 8912 SamrQueryInformationDomain2(IN SAMPR_HANDLE DomainHandle, 8913 IN DOMAIN_INFORMATION_CLASS DomainInformationClass, 8914 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 8915 { 8916 TRACE("SamrQueryInformationDomain2(%p %lu %p)\n", 8917 DomainHandle, DomainInformationClass, Buffer); 8918 8919 return SamrQueryInformationDomain(DomainHandle, 8920 DomainInformationClass, 8921 Buffer); 8922 } 8923 8924 8925 /* Function 47 */ 8926 NTSTATUS 8927 NTAPI 8928 SamrQueryInformationUser2(IN SAMPR_HANDLE UserHandle, 8929 IN USER_INFORMATION_CLASS UserInformationClass, 8930 OUT PSAMPR_USER_INFO_BUFFER *Buffer) 8931 { 8932 TRACE("SamrQueryInformationUser2(%p %lu %p)\n", 8933 UserHandle, UserInformationClass, Buffer); 8934 8935 return SamrQueryInformationUser(UserHandle, 8936 UserInformationClass, 8937 Buffer); 8938 } 8939 8940 8941 /* Function 48 */ 8942 NTSTATUS 8943 NTAPI 8944 SamrQueryDisplayInformation2(IN SAMPR_HANDLE DomainHandle, 8945 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass, 8946 IN unsigned long Index, 8947 IN unsigned long EntryCount, 8948 IN unsigned long PreferredMaximumLength, 8949 OUT unsigned long *TotalAvailable, 8950 OUT unsigned long *TotalReturned, 8951 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer) 8952 { 8953 TRACE("SamrQueryDisplayInformation2(%p %lu %lu %lu %lu %p %p %p)\n", 8954 DomainHandle, DisplayInformationClass, Index, 8955 EntryCount, PreferredMaximumLength, TotalAvailable, 8956 TotalReturned, Buffer); 8957 8958 return SamrQueryDisplayInformation(DomainHandle, 8959 DisplayInformationClass, 8960 Index, 8961 EntryCount, 8962 PreferredMaximumLength, 8963 TotalAvailable, 8964 TotalReturned, 8965 Buffer); 8966 } 8967 8968 8969 /* Function 49 */ 8970 NTSTATUS 8971 NTAPI 8972 SamrGetDisplayEnumerationIndex2(IN SAMPR_HANDLE DomainHandle, 8973 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass, 8974 IN PRPC_UNICODE_STRING Prefix, 8975 OUT unsigned long *Index) 8976 { 8977 TRACE("SamrGetDisplayEnumerationIndex2(%p %lu %p %p)\n", 8978 DomainHandle, DisplayInformationClass, Prefix, Index); 8979 8980 return SamrGetDisplayEnumerationIndex(DomainHandle, 8981 DisplayInformationClass, 8982 Prefix, 8983 Index); 8984 } 8985 8986 8987 /* Function 50 */ 8988 NTSTATUS 8989 NTAPI 8990 SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle, 8991 IN PRPC_UNICODE_STRING Name, 8992 IN unsigned long AccountType, 8993 IN ACCESS_MASK DesiredAccess, 8994 OUT SAMPR_HANDLE *UserHandle, 8995 OUT unsigned long *GrantedAccess, 8996 OUT unsigned long *RelativeId) 8997 { 8998 SAM_DOMAIN_FIXED_DATA FixedDomainData; 8999 SAM_USER_FIXED_DATA FixedUserData; 9000 PSAM_DB_OBJECT DomainObject; 9001 PSAM_DB_OBJECT UserObject; 9002 GROUP_MEMBERSHIP GroupMembership; 9003 UCHAR LogonHours[23]; 9004 ULONG ulSize; 9005 ULONG ulRid; 9006 WCHAR szRid[9]; 9007 PSECURITY_DESCRIPTOR Sd = NULL; 9008 ULONG SdSize = 0; 9009 PSID UserSid = NULL; 9010 NTSTATUS Status; 9011 9012 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n", 9013 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId); 9014 9015 if (Name == NULL || 9016 Name->Length == 0 || 9017 Name->Buffer == NULL || 9018 UserHandle == NULL || 9019 RelativeId == NULL) 9020 return STATUS_INVALID_PARAMETER; 9021 9022 /* Check for valid account type */ 9023 if (AccountType != USER_NORMAL_ACCOUNT && 9024 AccountType != USER_WORKSTATION_TRUST_ACCOUNT && 9025 AccountType != USER_INTERDOMAIN_TRUST_ACCOUNT && 9026 AccountType != USER_SERVER_TRUST_ACCOUNT && 9027 AccountType != USER_TEMP_DUPLICATE_ACCOUNT) 9028 return STATUS_INVALID_PARAMETER; 9029 9030 /* Map generic access rights */ 9031 RtlMapGenericMask(&DesiredAccess, 9032 &UserMapping); 9033 9034 RtlAcquireResourceExclusive(&SampResource, 9035 TRUE); 9036 9037 /* Validate the domain handle */ 9038 Status = SampValidateDbObject(DomainHandle, 9039 SamDbDomainObject, 9040 DOMAIN_CREATE_USER, 9041 &DomainObject); 9042 if (!NT_SUCCESS(Status)) 9043 { 9044 TRACE("failed with status 0x%08lx\n", Status); 9045 goto done; 9046 } 9047 9048 /* Check the user account name */ 9049 Status = SampCheckAccountName(Name, 20); 9050 if (!NT_SUCCESS(Status)) 9051 { 9052 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 9053 goto done; 9054 } 9055 9056 /* Check if the user name already exists in the domain */ 9057 Status = SampCheckAccountNameInDomain(DomainObject, 9058 Name->Buffer); 9059 if (!NT_SUCCESS(Status)) 9060 { 9061 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n", 9062 Name->Buffer, Status); 9063 goto done; 9064 } 9065 9066 /* Get the fixed domain attributes */ 9067 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA); 9068 Status = SampGetObjectAttribute(DomainObject, 9069 L"F", 9070 NULL, 9071 (PVOID)&FixedDomainData, 9072 &ulSize); 9073 if (!NT_SUCCESS(Status)) 9074 { 9075 TRACE("failed with status 0x%08lx\n", Status); 9076 goto done; 9077 } 9078 9079 /* Increment the NextRid attribute */ 9080 ulRid = FixedDomainData.NextRid; 9081 FixedDomainData.NextRid++; 9082 9083 TRACE("RID: %lx\n", ulRid); 9084 9085 /* Create the user SID */ 9086 Status = SampCreateAccountSid(DomainObject, 9087 ulRid, 9088 &UserSid); 9089 if (!NT_SUCCESS(Status)) 9090 { 9091 TRACE("SampCreateAccountSid failed (Status 0x%08lx)\n", Status); 9092 goto done; 9093 } 9094 9095 /* Create the security descriptor */ 9096 Status = SampCreateUserSD(UserSid, 9097 &Sd, 9098 &SdSize); 9099 if (!NT_SUCCESS(Status)) 9100 { 9101 TRACE("SampCreateUserSD failed (Status 0x%08lx)\n", Status); 9102 goto done; 9103 } 9104 9105 /* Store the fixed domain attributes */ 9106 Status = SampSetObjectAttribute(DomainObject, 9107 L"F", 9108 REG_BINARY, 9109 &FixedDomainData, 9110 ulSize); 9111 if (!NT_SUCCESS(Status)) 9112 { 9113 TRACE("failed with status 0x%08lx\n", Status); 9114 goto done; 9115 } 9116 9117 /* Convert the RID into a string (hex) */ 9118 swprintf(szRid, L"%08lX", ulRid); 9119 9120 /* Create the user object */ 9121 Status = SampCreateDbObject(DomainObject, 9122 L"Users", 9123 szRid, 9124 ulRid, 9125 SamDbUserObject, 9126 DesiredAccess, 9127 &UserObject); 9128 if (!NT_SUCCESS(Status)) 9129 { 9130 TRACE("failed with status 0x%08lx\n", Status); 9131 goto done; 9132 } 9133 9134 /* Add the account name for the user object */ 9135 Status = SampSetAccountNameInDomain(DomainObject, 9136 L"Users", 9137 Name->Buffer, 9138 ulRid); 9139 if (!NT_SUCCESS(Status)) 9140 { 9141 TRACE("failed with status 0x%08lx\n", Status); 9142 goto done; 9143 } 9144 9145 /* Initialize fixed user data */ 9146 FixedUserData.Version = 1; 9147 FixedUserData.Reserved = 0; 9148 FixedUserData.LastLogon.QuadPart = 0; 9149 FixedUserData.LastLogoff.QuadPart = 0; 9150 FixedUserData.PasswordLastSet.QuadPart = 0; 9151 FixedUserData.AccountExpires.LowPart = MAXULONG; 9152 FixedUserData.AccountExpires.HighPart = MAXLONG; 9153 FixedUserData.LastBadPasswordTime.QuadPart = 0; 9154 FixedUserData.UserId = ulRid; 9155 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS; 9156 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED | 9157 USER_PASSWORD_NOT_REQUIRED | 9158 AccountType; 9159 FixedUserData.CountryCode = 0; 9160 FixedUserData.CodePage = 0; 9161 FixedUserData.BadPasswordCount = 0; 9162 FixedUserData.LogonCount = 0; 9163 FixedUserData.AdminCount = 0; 9164 FixedUserData.OperatorCount = 0; 9165 9166 /* Set fixed user data attribute */ 9167 Status = SampSetObjectAttribute(UserObject, 9168 L"F", 9169 REG_BINARY, 9170 (LPVOID)&FixedUserData, 9171 sizeof(SAM_USER_FIXED_DATA)); 9172 if (!NT_SUCCESS(Status)) 9173 { 9174 TRACE("failed with status 0x%08lx\n", Status); 9175 goto done; 9176 } 9177 9178 /* Set the Name attribute */ 9179 Status = SampSetObjectAttributeString(UserObject, 9180 L"Name", 9181 Name); 9182 if (!NT_SUCCESS(Status)) 9183 { 9184 TRACE("failed with status 0x%08lx\n", Status); 9185 goto done; 9186 } 9187 9188 /* Set the FullName attribute */ 9189 Status = SampSetObjectAttributeString(UserObject, 9190 L"FullName", 9191 NULL); 9192 if (!NT_SUCCESS(Status)) 9193 { 9194 TRACE("failed with status 0x%08lx\n", Status); 9195 goto done; 9196 } 9197 9198 /* Set the HomeDirectory attribute */ 9199 Status = SampSetObjectAttributeString(UserObject, 9200 L"HomeDirectory", 9201 NULL); 9202 if (!NT_SUCCESS(Status)) 9203 { 9204 TRACE("failed with status 0x%08lx\n", Status); 9205 goto done; 9206 } 9207 9208 /* Set the HomeDirectoryDrive attribute */ 9209 Status = SampSetObjectAttributeString(UserObject, 9210 L"HomeDirectoryDrive", 9211 NULL); 9212 if (!NT_SUCCESS(Status)) 9213 { 9214 TRACE("failed with status 0x%08lx\n", Status); 9215 goto done; 9216 } 9217 9218 /* Set the ScriptPath attribute */ 9219 Status = SampSetObjectAttributeString(UserObject, 9220 L"ScriptPath", 9221 NULL); 9222 if (!NT_SUCCESS(Status)) 9223 { 9224 TRACE("failed with status 0x%08lx\n", Status); 9225 goto done; 9226 } 9227 9228 /* Set the ProfilePath attribute */ 9229 Status = SampSetObjectAttributeString(UserObject, 9230 L"ProfilePath", 9231 NULL); 9232 if (!NT_SUCCESS(Status)) 9233 { 9234 TRACE("failed with status 0x%08lx\n", Status); 9235 goto done; 9236 } 9237 9238 /* Set the AdminComment attribute */ 9239 Status = SampSetObjectAttributeString(UserObject, 9240 L"AdminComment", 9241 NULL); 9242 if (!NT_SUCCESS(Status)) 9243 { 9244 TRACE("failed with status 0x%08lx\n", Status); 9245 goto done; 9246 } 9247 9248 /* Set the UserComment attribute */ 9249 Status = SampSetObjectAttributeString(UserObject, 9250 L"UserComment", 9251 NULL); 9252 if (!NT_SUCCESS(Status)) 9253 { 9254 TRACE("failed with status 0x%08lx\n", Status); 9255 goto done; 9256 } 9257 9258 /* Set the WorkStations attribute */ 9259 Status = SampSetObjectAttributeString(UserObject, 9260 L"WorkStations", 9261 NULL); 9262 if (!NT_SUCCESS(Status)) 9263 { 9264 TRACE("failed with status 0x%08lx\n", Status); 9265 goto done; 9266 } 9267 9268 /* Set the Parameters attribute */ 9269 Status = SampSetObjectAttributeString(UserObject, 9270 L"Parameters", 9271 NULL); 9272 if (!NT_SUCCESS(Status)) 9273 { 9274 TRACE("failed with status 0x%08lx\n", Status); 9275 goto done; 9276 } 9277 9278 /* Set LogonHours attribute*/ 9279 *((PUSHORT)LogonHours) = 168; 9280 memset(&(LogonHours[2]), 0xff, 21); 9281 9282 Status = SampSetObjectAttribute(UserObject, 9283 L"LogonHours", 9284 REG_BINARY, 9285 &LogonHours, 9286 sizeof(LogonHours)); 9287 if (!NT_SUCCESS(Status)) 9288 { 9289 TRACE("failed with status 0x%08lx\n", Status); 9290 goto done; 9291 } 9292 9293 /* Set Groups attribute*/ 9294 GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS; 9295 GroupMembership.Attributes = SE_GROUP_MANDATORY | 9296 SE_GROUP_ENABLED | 9297 SE_GROUP_ENABLED_BY_DEFAULT; 9298 9299 Status = SampSetObjectAttribute(UserObject, 9300 L"Groups", 9301 REG_BINARY, 9302 &GroupMembership, 9303 sizeof(GROUP_MEMBERSHIP)); 9304 if (!NT_SUCCESS(Status)) 9305 { 9306 TRACE("failed with status 0x%08lx\n", Status); 9307 goto done; 9308 } 9309 9310 /* Set LMPwd attribute*/ 9311 Status = SampSetObjectAttribute(UserObject, 9312 L"LMPwd", 9313 REG_BINARY, 9314 NULL, 9315 0); 9316 if (!NT_SUCCESS(Status)) 9317 { 9318 TRACE("failed with status 0x%08lx\n", Status); 9319 goto done; 9320 } 9321 9322 /* Set NTPwd attribute*/ 9323 Status = SampSetObjectAttribute(UserObject, 9324 L"NTPwd", 9325 REG_BINARY, 9326 NULL, 9327 0); 9328 if (!NT_SUCCESS(Status)) 9329 { 9330 TRACE("failed with status 0x%08lx\n", Status); 9331 goto done; 9332 } 9333 9334 /* Set LMPwdHistory attribute*/ 9335 Status = SampSetObjectAttribute(UserObject, 9336 L"LMPwdHistory", 9337 REG_BINARY, 9338 NULL, 9339 0); 9340 if (!NT_SUCCESS(Status)) 9341 { 9342 TRACE("failed with status 0x%08lx\n", Status); 9343 goto done; 9344 } 9345 9346 /* Set NTPwdHistory attribute*/ 9347 Status = SampSetObjectAttribute(UserObject, 9348 L"NTPwdHistory", 9349 REG_BINARY, 9350 NULL, 9351 0); 9352 if (!NT_SUCCESS(Status)) 9353 { 9354 TRACE("failed with status 0x%08lx\n", Status); 9355 goto done; 9356 } 9357 9358 /* Set the PrivateData attribute */ 9359 Status = SampSetObjectAttributeString(UserObject, 9360 L"PrivateData", 9361 NULL); 9362 if (!NT_SUCCESS(Status)) 9363 { 9364 TRACE("failed with status 0x%08lx\n", Status); 9365 goto done; 9366 } 9367 9368 /* Set the SecDesc attribute*/ 9369 Status = SampSetObjectAttribute(UserObject, 9370 L"SecDesc", 9371 REG_BINARY, 9372 Sd, 9373 SdSize); 9374 if (!NT_SUCCESS(Status)) 9375 { 9376 TRACE("failed with status 0x%08lx\n", Status); 9377 goto done; 9378 } 9379 9380 if (NT_SUCCESS(Status)) 9381 { 9382 *UserHandle = (SAMPR_HANDLE)UserObject; 9383 *RelativeId = ulRid; 9384 *GrantedAccess = UserObject->Access; 9385 } 9386 9387 done: 9388 if (Sd != NULL) 9389 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd); 9390 9391 if (UserSid != NULL) 9392 RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid); 9393 9394 RtlReleaseResource(&SampResource); 9395 9396 TRACE("returns with status 0x%08lx\n", Status); 9397 9398 return Status; 9399 } 9400 9401 9402 /* Function 51 */ 9403 NTSTATUS 9404 NTAPI 9405 SamrQueryDisplayInformation3(IN SAMPR_HANDLE DomainHandle, 9406 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass, 9407 IN unsigned long Index, 9408 IN unsigned long EntryCount, 9409 IN unsigned long PreferredMaximumLength, 9410 OUT unsigned long *TotalAvailable, 9411 OUT unsigned long *TotalReturned, 9412 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer) 9413 { 9414 TRACE("SamrQueryDisplayInformation3(%p %lu %lu %lu %lu %p %p %p)\n", 9415 DomainHandle, DisplayInformationClass, Index, 9416 EntryCount, PreferredMaximumLength, TotalAvailable, 9417 TotalReturned, Buffer); 9418 9419 return SamrQueryDisplayInformation(DomainHandle, 9420 DisplayInformationClass, 9421 Index, 9422 EntryCount, 9423 PreferredMaximumLength, 9424 TotalAvailable, 9425 TotalReturned, 9426 Buffer); 9427 } 9428 9429 9430 /* Function 52 */ 9431 NTSTATUS 9432 NTAPI 9433 SamrAddMultipleMembersToAlias(IN SAMPR_HANDLE AliasHandle, 9434 IN PSAMPR_PSID_ARRAY MembersBuffer) 9435 { 9436 ULONG i; 9437 NTSTATUS Status = STATUS_SUCCESS; 9438 9439 TRACE("SamrAddMultipleMembersToAlias(%p %p)\n", 9440 AliasHandle, MembersBuffer); 9441 9442 for (i = 0; i < MembersBuffer->Count; i++) 9443 { 9444 Status = SamrAddMemberToAlias(AliasHandle, 9445 ((PSID *)MembersBuffer->Sids)[i]); 9446 9447 if (Status == STATUS_MEMBER_IN_ALIAS) 9448 Status = STATUS_SUCCESS; 9449 9450 if (!NT_SUCCESS(Status)) 9451 break; 9452 } 9453 9454 return Status; 9455 } 9456 9457 9458 /* Function 53 */ 9459 NTSTATUS 9460 NTAPI 9461 SamrRemoveMultipleMembersFromAlias(IN SAMPR_HANDLE AliasHandle, 9462 IN PSAMPR_PSID_ARRAY MembersBuffer) 9463 { 9464 ULONG i; 9465 NTSTATUS Status = STATUS_SUCCESS; 9466 9467 TRACE("SamrRemoveMultipleMembersFromAlias(%p %p)\n", 9468 AliasHandle, MembersBuffer); 9469 9470 for (i = 0; i < MembersBuffer->Count; i++) 9471 { 9472 Status = SamrRemoveMemberFromAlias(AliasHandle, 9473 ((PSID *)MembersBuffer->Sids)[i]); 9474 9475 if (Status == STATUS_MEMBER_IN_ALIAS) 9476 Status = STATUS_SUCCESS; 9477 9478 if (!NT_SUCCESS(Status)) 9479 break; 9480 } 9481 9482 return Status; 9483 } 9484 9485 9486 /* Function 54 */ 9487 NTSTATUS 9488 NTAPI 9489 SamrOemChangePasswordUser2(IN handle_t BindingHandle, 9490 IN PRPC_STRING ServerName, 9491 IN PRPC_STRING UserName, 9492 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm, 9493 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewLm) 9494 { 9495 UNIMPLEMENTED; 9496 return STATUS_NOT_IMPLEMENTED; 9497 } 9498 9499 /* Function 55 */ 9500 NTSTATUS 9501 NTAPI 9502 SamrUnicodeChangePasswordUser2(IN handle_t BindingHandle, 9503 IN PRPC_UNICODE_STRING ServerName, 9504 IN PRPC_UNICODE_STRING UserName, 9505 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldNt, 9506 IN PENCRYPTED_NT_OWF_PASSWORD OldNtOwfPasswordEncryptedWithNewNt, 9507 IN unsigned char LmPresent, 9508 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm, 9509 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewNt) 9510 { 9511 UNIMPLEMENTED; 9512 return STATUS_NOT_IMPLEMENTED; 9513 } 9514 9515 9516 /* Function 56 */ 9517 NTSTATUS 9518 NTAPI 9519 SamrGetDomainPasswordInformation(IN handle_t BindingHandle, 9520 IN PRPC_UNICODE_STRING Unused, 9521 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation) 9522 { 9523 SAMPR_HANDLE ServerHandle = NULL; 9524 PSAM_DB_OBJECT DomainObject = NULL; 9525 SAM_DOMAIN_FIXED_DATA FixedData; 9526 ULONG Length; 9527 NTSTATUS Status; 9528 9529 TRACE("SamrGetDomainPasswordInformation(%p %p %p)\n", 9530 BindingHandle, Unused, PasswordInformation); 9531 9532 Status = SamrConnect(NULL, 9533 &ServerHandle, 9534 SAM_SERVER_LOOKUP_DOMAIN); 9535 if (!NT_SUCCESS(Status)) 9536 { 9537 TRACE("SamrConnect() failed (Status 0x%08lx)\n", Status); 9538 goto done; 9539 } 9540 9541 Status = SampOpenDbObject((PSAM_DB_OBJECT)ServerHandle, 9542 L"Domains", 9543 L"Account", 9544 0, 9545 SamDbDomainObject, 9546 DOMAIN_READ_PASSWORD_PARAMETERS, 9547 &DomainObject); 9548 if (!NT_SUCCESS(Status)) 9549 { 9550 TRACE("SampOpenDbObject() failed (Status 0x%08lx)\n", Status); 9551 goto done; 9552 } 9553 9554 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 9555 Status = SampGetObjectAttribute(DomainObject, 9556 L"F", 9557 NULL, 9558 &FixedData, 9559 &Length); 9560 if (!NT_SUCCESS(Status)) 9561 { 9562 TRACE("SampGetObjectAttribute() failed (Status 0x%08lx)\n", Status); 9563 goto done; 9564 } 9565 9566 PasswordInformation->MinPasswordLength = FixedData.MinPasswordLength; 9567 PasswordInformation->PasswordProperties = FixedData.PasswordProperties; 9568 9569 done: 9570 if (DomainObject != NULL) 9571 SampCloseDbObject(DomainObject); 9572 9573 if (ServerHandle != NULL) 9574 SamrCloseHandle(ServerHandle); 9575 9576 return Status; 9577 } 9578 9579 9580 /* Function 57 */ 9581 NTSTATUS 9582 NTAPI 9583 SamrConnect2(IN PSAMPR_SERVER_NAME ServerName, 9584 OUT SAMPR_HANDLE *ServerHandle, 9585 IN ACCESS_MASK DesiredAccess) 9586 { 9587 SAMPR_REVISION_INFO InRevisionInfo, OutRevisionInfo; 9588 ULONG OutVersion; 9589 9590 TRACE("SamrConnect2(%p %p %lx)\n", 9591 ServerName, ServerHandle, DesiredAccess); 9592 9593 InRevisionInfo.V1.Revision = 1; 9594 InRevisionInfo.V1.SupportedFeatures = 0; 9595 9596 return SamrConnect5(ServerName, 9597 DesiredAccess, 9598 1, 9599 &InRevisionInfo, 9600 &OutVersion, 9601 &OutRevisionInfo, 9602 ServerHandle); 9603 } 9604 9605 9606 /* Function 58 */ 9607 NTSTATUS 9608 NTAPI 9609 SamrSetInformationUser2(IN SAMPR_HANDLE UserHandle, 9610 IN USER_INFORMATION_CLASS UserInformationClass, 9611 IN PSAMPR_USER_INFO_BUFFER Buffer) 9612 { 9613 TRACE("SamrSetInformationUser2(%p %lu %p)\n", 9614 UserHandle, UserInformationClass, Buffer); 9615 9616 return SamrSetInformationUser(UserHandle, 9617 UserInformationClass, 9618 Buffer); 9619 } 9620 9621 9622 /* Function 59 */ 9623 NTSTATUS 9624 NTAPI 9625 SamrSetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */ 9626 { 9627 UNIMPLEMENTED; 9628 return STATUS_NOT_IMPLEMENTED; 9629 } 9630 9631 /* Function 60 */ 9632 NTSTATUS 9633 NTAPI 9634 SamrGetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */ 9635 { 9636 UNIMPLEMENTED; 9637 return STATUS_NOT_IMPLEMENTED; 9638 } 9639 9640 /* Function 61 */ 9641 NTSTATUS 9642 NTAPI 9643 SamrConnect3(IN handle_t BindingHandle) /* FIXME */ 9644 { 9645 UNIMPLEMENTED; 9646 return STATUS_NOT_IMPLEMENTED; 9647 } 9648 9649 9650 /* Function 62 */ 9651 NTSTATUS 9652 NTAPI 9653 SamrConnect4(IN PSAMPR_SERVER_NAME ServerName, 9654 OUT SAMPR_HANDLE *ServerHandle, 9655 IN unsigned long ClientRevision, 9656 IN ACCESS_MASK DesiredAccess) 9657 { 9658 SAMPR_REVISION_INFO InRevisionInfo, OutRevisionInfo; 9659 ULONG OutVersion; 9660 9661 TRACE("SamrConnect4(%p %p %lu 0x%lx)\n", 9662 ServerName, ServerHandle, ClientRevision, DesiredAccess); 9663 9664 InRevisionInfo.V1.Revision = 2; 9665 InRevisionInfo.V1.SupportedFeatures = 0; 9666 9667 return SamrConnect5(ServerName, 9668 DesiredAccess, 9669 1, 9670 &InRevisionInfo, 9671 &OutVersion, 9672 &OutRevisionInfo, 9673 ServerHandle); 9674 } 9675 9676 9677 /* Function 63 */ 9678 NTSTATUS 9679 NTAPI 9680 SamrUnicodeChangePasswordUser3(IN handle_t BindingHandle) /* FIXME */ 9681 { 9682 UNIMPLEMENTED; 9683 return STATUS_NOT_IMPLEMENTED; 9684 } 9685 9686 9687 /* Function 64 */ 9688 NTSTATUS 9689 NTAPI 9690 SamrConnect5(IN PSAMPR_SERVER_NAME ServerName, 9691 IN ACCESS_MASK DesiredAccess, 9692 IN unsigned long InVersion, 9693 IN SAMPR_REVISION_INFO *InRevisionInfo, 9694 OUT unsigned long *OutVersion, 9695 OUT SAMPR_REVISION_INFO *OutRevisionInfo, 9696 OUT SAMPR_HANDLE *ServerHandle) 9697 { 9698 PSAM_DB_OBJECT ServerObject; 9699 NTSTATUS Status; 9700 9701 TRACE("SamrConnect5(%p 0x%lx %lu %p %p %p %p)\n", 9702 ServerName, DesiredAccess, InVersion, InRevisionInfo, 9703 OutVersion, OutRevisionInfo, ServerHandle); 9704 9705 if (InVersion != 1) 9706 return STATUS_NOT_SUPPORTED; 9707 9708 RtlAcquireResourceShared(&SampResource, 9709 TRUE); 9710 9711 /* Map generic access rights */ 9712 RtlMapGenericMask(&DesiredAccess, 9713 &ServerMapping); 9714 9715 /* Open the Server Object */ 9716 Status = SampOpenDbObject(NULL, 9717 NULL, 9718 L"SAM", 9719 0, 9720 SamDbServerObject, 9721 DesiredAccess, 9722 &ServerObject); 9723 if (NT_SUCCESS(Status)) 9724 { 9725 *OutVersion = 1; 9726 9727 OutRevisionInfo->V1.Revision = 3; 9728 OutRevisionInfo->V1.SupportedFeatures = 0; 9729 9730 *ServerHandle = (SAMPR_HANDLE)ServerObject; 9731 } 9732 9733 RtlReleaseResource(&SampResource); 9734 9735 TRACE("SamrConnect5 done (Status 0x%08lx)\n", Status); 9736 9737 return Status; 9738 } 9739 9740 9741 /* Function 65 */ 9742 NTSTATUS 9743 NTAPI 9744 SamrRidToSid(IN SAMPR_HANDLE ObjectHandle, 9745 IN unsigned long Rid, 9746 OUT PRPC_SID *Sid) 9747 { 9748 UNIMPLEMENTED; 9749 return STATUS_NOT_IMPLEMENTED; 9750 } 9751 9752 /* Function 66 */ 9753 NTSTATUS 9754 NTAPI 9755 SamrSetDSRMPassword(IN handle_t BindingHandle, 9756 IN PRPC_UNICODE_STRING Unused, 9757 IN unsigned long UserId, 9758 IN PENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword) 9759 { 9760 UNIMPLEMENTED; 9761 return STATUS_NOT_IMPLEMENTED; 9762 } 9763 9764 /* Function 67 */ 9765 NTSTATUS 9766 NTAPI 9767 SamrValidatePassword(IN handle_t Handle, 9768 IN PASSWORD_POLICY_VALIDATION_TYPE ValidationType, 9769 IN PSAM_VALIDATE_INPUT_ARG InputArg, 9770 OUT PSAM_VALIDATE_OUTPUT_ARG *OutputArg) 9771 { 9772 UNIMPLEMENTED; 9773 return STATUS_NOT_IMPLEMENTED; 9774 } 9775 9776 /* EOF */ 9777