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 goto done; 2294 2295 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION)); 2296 if (EnumBuffer->Buffer == NULL) 2297 { 2298 Status = STATUS_INSUFFICIENT_RESOURCES; 2299 goto done; 2300 } 2301 2302 TRACE("Part 2\n"); 2303 2304 EnumIndex = *EnumerationContext; 2305 for (i = 0; i < EnumCount; i++, EnumIndex++) 2306 { 2307 NameLength = 64 * sizeof(WCHAR); 2308 DataLength = sizeof(ULONG); 2309 Status = SampRegEnumerateValue(NamesKeyHandle, 2310 EnumIndex, 2311 GroupName, 2312 &NameLength, 2313 NULL, 2314 &Rid, 2315 &DataLength); 2316 if (!NT_SUCCESS(Status)) 2317 { 2318 if (Status == STATUS_NO_MORE_ENTRIES) 2319 Status = STATUS_SUCCESS; 2320 break; 2321 } 2322 2323 TRACE("EnumIndex: %lu\n", EnumIndex); 2324 TRACE("Group name: %S\n", GroupName); 2325 TRACE("Name length: %lu\n", NameLength); 2326 TRACE("RID: %lu\n", Rid); 2327 2328 EnumBuffer->Buffer[i].RelativeId = Rid; 2329 2330 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength; 2331 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(NameLength + sizeof(UNICODE_NULL)); 2332 2333 /* FIXME: Disabled because of bugs in widl and rpcrt4 */ 2334 #if 0 2335 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength); 2336 if (EnumBuffer->Buffer[i].Name.Buffer == NULL) 2337 { 2338 Status = STATUS_INSUFFICIENT_RESOURCES; 2339 goto done; 2340 } 2341 2342 memcpy(EnumBuffer->Buffer[i].Name.Buffer, 2343 GroupName, 2344 EnumBuffer->Buffer[i].Name.Length); 2345 #endif 2346 } 2347 2348 done: 2349 if (NT_SUCCESS(Status)) 2350 { 2351 *EnumerationContext += EnumCount; 2352 *Buffer = EnumBuffer; 2353 *CountReturned = EnumCount; 2354 } 2355 else 2356 { 2357 *EnumerationContext = 0; 2358 *Buffer = NULL; 2359 *CountReturned = 0; 2360 2361 if (EnumBuffer != NULL) 2362 { 2363 if (EnumBuffer->Buffer != NULL) 2364 { 2365 if (EnumBuffer->EntriesRead != 0) 2366 { 2367 for (i = 0; i < EnumBuffer->EntriesRead; i++) 2368 { 2369 if (EnumBuffer->Buffer[i].Name.Buffer != NULL) 2370 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer); 2371 } 2372 } 2373 2374 midl_user_free(EnumBuffer->Buffer); 2375 } 2376 2377 midl_user_free(EnumBuffer); 2378 } 2379 } 2380 2381 SampRegCloseKey(&NamesKeyHandle); 2382 SampRegCloseKey(&GroupsKeyHandle); 2383 2384 if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE)) 2385 Status = STATUS_MORE_ENTRIES; 2386 2387 RtlReleaseResource(&SampResource); 2388 2389 return Status; 2390 } 2391 2392 2393 /* Function 12 */ 2394 NTSTATUS 2395 NTAPI 2396 SamrCreateUserInDomain(IN SAMPR_HANDLE DomainHandle, 2397 IN PRPC_UNICODE_STRING Name, 2398 IN ACCESS_MASK DesiredAccess, 2399 OUT SAMPR_HANDLE *UserHandle, 2400 OUT unsigned long *RelativeId) 2401 { 2402 SAM_DOMAIN_FIXED_DATA FixedDomainData; 2403 SAM_USER_FIXED_DATA FixedUserData; 2404 PSAM_DB_OBJECT DomainObject; 2405 PSAM_DB_OBJECT UserObject; 2406 GROUP_MEMBERSHIP GroupMembership; 2407 UCHAR LogonHours[23]; 2408 ULONG ulSize; 2409 ULONG ulRid; 2410 WCHAR szRid[9]; 2411 PSECURITY_DESCRIPTOR Sd = NULL; 2412 ULONG SdSize = 0; 2413 PSID UserSid = NULL; 2414 NTSTATUS Status; 2415 2416 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n", 2417 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId); 2418 2419 if (Name == NULL || 2420 Name->Length == 0 || 2421 Name->Buffer == NULL || 2422 UserHandle == NULL || 2423 RelativeId == NULL) 2424 return STATUS_INVALID_PARAMETER; 2425 2426 /* Map generic access rights */ 2427 RtlMapGenericMask(&DesiredAccess, 2428 &UserMapping); 2429 2430 RtlAcquireResourceExclusive(&SampResource, 2431 TRUE); 2432 2433 /* Validate the domain handle */ 2434 Status = SampValidateDbObject(DomainHandle, 2435 SamDbDomainObject, 2436 DOMAIN_CREATE_USER, 2437 &DomainObject); 2438 if (!NT_SUCCESS(Status)) 2439 { 2440 TRACE("failed with status 0x%08lx\n", Status); 2441 goto done; 2442 } 2443 2444 /* Check the user account name */ 2445 Status = SampCheckAccountName(Name, 20); 2446 if (!NT_SUCCESS(Status)) 2447 { 2448 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 2449 goto done; 2450 } 2451 2452 /* Check if the user name already exists in the domain */ 2453 Status = SampCheckAccountNameInDomain(DomainObject, 2454 Name->Buffer); 2455 if (!NT_SUCCESS(Status)) 2456 { 2457 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n", 2458 Name->Buffer, Status); 2459 goto done; 2460 } 2461 2462 /* Get the fixed domain attributes */ 2463 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA); 2464 Status = SampGetObjectAttribute(DomainObject, 2465 L"F", 2466 NULL, 2467 (PVOID)&FixedDomainData, 2468 &ulSize); 2469 if (!NT_SUCCESS(Status)) 2470 { 2471 TRACE("failed with status 0x%08lx\n", Status); 2472 goto done; 2473 } 2474 2475 /* Increment the NextRid attribute */ 2476 ulRid = FixedDomainData.NextRid; 2477 FixedDomainData.NextRid++; 2478 2479 TRACE("RID: %lx\n", ulRid); 2480 2481 /* Create the user SID */ 2482 Status = SampCreateAccountSid(DomainObject, 2483 ulRid, 2484 &UserSid); 2485 if (!NT_SUCCESS(Status)) 2486 { 2487 TRACE("SampCreateAccountSid failed (Status 0x%08lx)\n", Status); 2488 goto done; 2489 } 2490 2491 /* Create the security descriptor */ 2492 Status = SampCreateUserSD(UserSid, 2493 &Sd, 2494 &SdSize); 2495 if (!NT_SUCCESS(Status)) 2496 { 2497 TRACE("SampCreateUserSD failed (Status 0x%08lx)\n", Status); 2498 goto done; 2499 } 2500 2501 /* Store the fixed domain attributes */ 2502 Status = SampSetObjectAttribute(DomainObject, 2503 L"F", 2504 REG_BINARY, 2505 &FixedDomainData, 2506 ulSize); 2507 if (!NT_SUCCESS(Status)) 2508 { 2509 TRACE("failed with status 0x%08lx\n", Status); 2510 goto done; 2511 } 2512 2513 /* Convert the RID into a string (hex) */ 2514 swprintf(szRid, L"%08lX", ulRid); 2515 2516 /* Create the user object */ 2517 Status = SampCreateDbObject(DomainObject, 2518 L"Users", 2519 szRid, 2520 ulRid, 2521 SamDbUserObject, 2522 DesiredAccess, 2523 &UserObject); 2524 if (!NT_SUCCESS(Status)) 2525 { 2526 TRACE("failed with status 0x%08lx\n", Status); 2527 goto done; 2528 } 2529 2530 /* Add the account name for the user object */ 2531 Status = SampSetAccountNameInDomain(DomainObject, 2532 L"Users", 2533 Name->Buffer, 2534 ulRid); 2535 if (!NT_SUCCESS(Status)) 2536 { 2537 TRACE("failed with status 0x%08lx\n", Status); 2538 goto done; 2539 } 2540 2541 /* Initialize fixed user data */ 2542 memset(&FixedUserData, 0, sizeof(SAM_USER_FIXED_DATA)); 2543 FixedUserData.Version = 1; 2544 FixedUserData.Reserved = 0; 2545 FixedUserData.LastLogon.QuadPart = 0; 2546 FixedUserData.LastLogoff.QuadPart = 0; 2547 FixedUserData.PasswordLastSet.QuadPart = 0; 2548 FixedUserData.AccountExpires.QuadPart = MAXLONGLONG; 2549 FixedUserData.LastBadPasswordTime.QuadPart = 0; 2550 FixedUserData.UserId = ulRid; 2551 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS; 2552 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED | 2553 USER_PASSWORD_NOT_REQUIRED | 2554 USER_NORMAL_ACCOUNT; 2555 FixedUserData.CountryCode = 0; 2556 FixedUserData.CodePage = 0; 2557 FixedUserData.BadPasswordCount = 0; 2558 FixedUserData.LogonCount = 0; 2559 FixedUserData.AdminCount = 0; 2560 FixedUserData.OperatorCount = 0; 2561 2562 /* Set fixed user data attribute */ 2563 Status = SampSetObjectAttribute(UserObject, 2564 L"F", 2565 REG_BINARY, 2566 (LPVOID)&FixedUserData, 2567 sizeof(SAM_USER_FIXED_DATA)); 2568 if (!NT_SUCCESS(Status)) 2569 { 2570 TRACE("failed with status 0x%08lx\n", Status); 2571 goto done; 2572 } 2573 2574 /* Set the Name attribute */ 2575 Status = SampSetObjectAttributeString(UserObject, 2576 L"Name", 2577 Name); 2578 if (!NT_SUCCESS(Status)) 2579 { 2580 TRACE("failed with status 0x%08lx\n", Status); 2581 goto done; 2582 } 2583 2584 /* Set the FullName attribute */ 2585 Status = SampSetObjectAttributeString(UserObject, 2586 L"FullName", 2587 NULL); 2588 if (!NT_SUCCESS(Status)) 2589 { 2590 TRACE("failed with status 0x%08lx\n", Status); 2591 goto done; 2592 } 2593 2594 /* Set the HomeDirectory attribute */ 2595 Status = SampSetObjectAttributeString(UserObject, 2596 L"HomeDirectory", 2597 NULL); 2598 if (!NT_SUCCESS(Status)) 2599 { 2600 TRACE("failed with status 0x%08lx\n", Status); 2601 goto done; 2602 } 2603 2604 /* Set the HomeDirectoryDrive attribute */ 2605 Status = SampSetObjectAttributeString(UserObject, 2606 L"HomeDirectoryDrive", 2607 NULL); 2608 if (!NT_SUCCESS(Status)) 2609 { 2610 TRACE("failed with status 0x%08lx\n", Status); 2611 goto done; 2612 } 2613 2614 /* Set the ScriptPath attribute */ 2615 Status = SampSetObjectAttributeString(UserObject, 2616 L"ScriptPath", 2617 NULL); 2618 if (!NT_SUCCESS(Status)) 2619 { 2620 TRACE("failed with status 0x%08lx\n", Status); 2621 goto done; 2622 } 2623 2624 /* Set the ProfilePath attribute */ 2625 Status = SampSetObjectAttributeString(UserObject, 2626 L"ProfilePath", 2627 NULL); 2628 if (!NT_SUCCESS(Status)) 2629 { 2630 TRACE("failed with status 0x%08lx\n", Status); 2631 goto done; 2632 } 2633 2634 /* Set the AdminComment attribute */ 2635 Status = SampSetObjectAttributeString(UserObject, 2636 L"AdminComment", 2637 NULL); 2638 if (!NT_SUCCESS(Status)) 2639 { 2640 TRACE("failed with status 0x%08lx\n", Status); 2641 goto done; 2642 } 2643 2644 /* Set the UserComment attribute */ 2645 Status = SampSetObjectAttributeString(UserObject, 2646 L"UserComment", 2647 NULL); 2648 if (!NT_SUCCESS(Status)) 2649 { 2650 TRACE("failed with status 0x%08lx\n", Status); 2651 goto done; 2652 } 2653 2654 /* Set the WorkStations attribute */ 2655 Status = SampSetObjectAttributeString(UserObject, 2656 L"WorkStations", 2657 NULL); 2658 if (!NT_SUCCESS(Status)) 2659 { 2660 TRACE("failed with status 0x%08lx\n", Status); 2661 goto done; 2662 } 2663 2664 /* Set the Parameters attribute */ 2665 Status = SampSetObjectAttributeString(UserObject, 2666 L"Parameters", 2667 NULL); 2668 if (!NT_SUCCESS(Status)) 2669 { 2670 TRACE("failed with status 0x%08lx\n", Status); 2671 goto done; 2672 } 2673 2674 /* Set LogonHours attribute*/ 2675 *((PUSHORT)LogonHours) = 168; 2676 memset(&(LogonHours[2]), 0xff, 21); 2677 2678 Status = SampSetObjectAttribute(UserObject, 2679 L"LogonHours", 2680 REG_BINARY, 2681 &LogonHours, 2682 sizeof(LogonHours)); 2683 if (!NT_SUCCESS(Status)) 2684 { 2685 TRACE("failed with status 0x%08lx\n", Status); 2686 goto done; 2687 } 2688 2689 /* Set Groups attribute*/ 2690 GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS; 2691 GroupMembership.Attributes = SE_GROUP_MANDATORY | 2692 SE_GROUP_ENABLED | 2693 SE_GROUP_ENABLED_BY_DEFAULT; 2694 2695 Status = SampSetObjectAttribute(UserObject, 2696 L"Groups", 2697 REG_BINARY, 2698 &GroupMembership, 2699 sizeof(GROUP_MEMBERSHIP)); 2700 if (!NT_SUCCESS(Status)) 2701 { 2702 TRACE("failed with status 0x%08lx\n", Status); 2703 goto done; 2704 } 2705 2706 /* Set LMPwd attribute*/ 2707 Status = SampSetObjectAttribute(UserObject, 2708 L"LMPwd", 2709 REG_BINARY, 2710 &EmptyLmHash, 2711 sizeof(ENCRYPTED_LM_OWF_PASSWORD)); 2712 if (!NT_SUCCESS(Status)) 2713 { 2714 TRACE("failed with status 0x%08lx\n", Status); 2715 goto done; 2716 } 2717 2718 /* Set NTPwd attribute*/ 2719 Status = SampSetObjectAttribute(UserObject, 2720 L"NTPwd", 2721 REG_BINARY, 2722 &EmptyNtHash, 2723 sizeof(ENCRYPTED_NT_OWF_PASSWORD)); 2724 if (!NT_SUCCESS(Status)) 2725 { 2726 TRACE("failed with status 0x%08lx\n", Status); 2727 goto done; 2728 } 2729 2730 /* Set LMPwdHistory attribute*/ 2731 Status = SampSetObjectAttribute(UserObject, 2732 L"LMPwdHistory", 2733 REG_BINARY, 2734 NULL, 2735 0); 2736 if (!NT_SUCCESS(Status)) 2737 { 2738 TRACE("failed with status 0x%08lx\n", Status); 2739 goto done; 2740 } 2741 2742 /* Set NTPwdHistory attribute*/ 2743 Status = SampSetObjectAttribute(UserObject, 2744 L"NTPwdHistory", 2745 REG_BINARY, 2746 NULL, 2747 0); 2748 if (!NT_SUCCESS(Status)) 2749 { 2750 TRACE("failed with status 0x%08lx\n", Status); 2751 goto done; 2752 } 2753 2754 /* Set the PrivateData attribute */ 2755 Status = SampSetObjectAttributeString(UserObject, 2756 L"PrivateData", 2757 NULL); 2758 if (!NT_SUCCESS(Status)) 2759 { 2760 TRACE("failed with status 0x%08lx\n", Status); 2761 goto done; 2762 } 2763 2764 /* Set the SecDesc attribute*/ 2765 Status = SampSetObjectAttribute(UserObject, 2766 L"SecDesc", 2767 REG_BINARY, 2768 Sd, 2769 SdSize); 2770 if (!NT_SUCCESS(Status)) 2771 { 2772 TRACE("failed with status 0x%08lx\n", Status); 2773 goto done; 2774 } 2775 2776 if (NT_SUCCESS(Status)) 2777 { 2778 *UserHandle = (SAMPR_HANDLE)UserObject; 2779 *RelativeId = ulRid; 2780 } 2781 2782 done: 2783 if (Sd != NULL) 2784 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd); 2785 2786 if (UserSid != NULL) 2787 RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid); 2788 2789 RtlReleaseResource(&SampResource); 2790 2791 TRACE("returns with status 0x%08lx\n", Status); 2792 2793 return Status; 2794 } 2795 2796 2797 /* Function 13 */ 2798 NTSTATUS 2799 NTAPI 2800 SamrEnumerateUsersInDomain(IN SAMPR_HANDLE DomainHandle, 2801 IN OUT unsigned long *EnumerationContext, 2802 IN unsigned long UserAccountControl, 2803 OUT PSAMPR_ENUMERATION_BUFFER *Buffer, 2804 IN unsigned long PreferedMaximumLength, 2805 OUT unsigned long *CountReturned) 2806 { 2807 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL; 2808 PSAM_DB_OBJECT DomainObject; 2809 HANDLE UsersKeyHandle = NULL; 2810 HANDLE NamesKeyHandle = NULL; 2811 WCHAR UserName[64]; 2812 ULONG EnumIndex; 2813 ULONG EnumCount = 0; 2814 ULONG RequiredLength = 0; 2815 ULONG NameLength; 2816 ULONG DataLength; 2817 ULONG Rid; 2818 ULONG i; 2819 BOOLEAN MoreEntries = FALSE; 2820 NTSTATUS Status; 2821 2822 TRACE("SamrEnumerateUsersInDomain(%p %p %lx %p %lu %p)\n", 2823 DomainHandle, EnumerationContext, UserAccountControl, Buffer, 2824 PreferedMaximumLength, CountReturned); 2825 2826 RtlAcquireResourceShared(&SampResource, 2827 TRUE); 2828 2829 /* Validate the domain handle */ 2830 Status = SampValidateDbObject(DomainHandle, 2831 SamDbDomainObject, 2832 DOMAIN_LIST_ACCOUNTS, 2833 &DomainObject); 2834 if (!NT_SUCCESS(Status)) 2835 goto done; 2836 2837 Status = SampRegOpenKey(DomainObject->KeyHandle, 2838 L"Users", 2839 KEY_READ, 2840 &UsersKeyHandle); 2841 if (!NT_SUCCESS(Status)) 2842 goto done; 2843 2844 Status = SampRegOpenKey(UsersKeyHandle, 2845 L"Names", 2846 KEY_READ, 2847 &NamesKeyHandle); 2848 if (!NT_SUCCESS(Status)) 2849 goto done; 2850 2851 TRACE("Part 1\n"); 2852 2853 EnumIndex = *EnumerationContext; 2854 2855 while (TRUE) 2856 { 2857 NameLength = 64 * sizeof(WCHAR); 2858 Status = SampRegEnumerateValue(NamesKeyHandle, 2859 EnumIndex, 2860 UserName, 2861 &NameLength, 2862 NULL, 2863 NULL, 2864 NULL); 2865 if (!NT_SUCCESS(Status)) 2866 { 2867 if (Status == STATUS_NO_MORE_ENTRIES) 2868 Status = STATUS_SUCCESS; 2869 break; 2870 } 2871 2872 TRACE("EnumIndex: %lu\n", EnumIndex); 2873 TRACE("User name: %S\n", UserName); 2874 TRACE("Name length: %lu\n", NameLength); 2875 2876 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength) 2877 { 2878 MoreEntries = TRUE; 2879 break; 2880 } 2881 2882 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)); 2883 EnumCount++; 2884 2885 EnumIndex++; 2886 } 2887 2888 TRACE("EnumCount: %lu\n", EnumCount); 2889 TRACE("RequiredLength: %lu\n", RequiredLength); 2890 2891 if (!NT_SUCCESS(Status)) 2892 goto done; 2893 2894 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER)); 2895 if (EnumBuffer == NULL) 2896 { 2897 Status = STATUS_INSUFFICIENT_RESOURCES; 2898 goto done; 2899 } 2900 2901 EnumBuffer->EntriesRead = EnumCount; 2902 if (EnumCount == 0) 2903 goto done; 2904 2905 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION)); 2906 if (EnumBuffer->Buffer == NULL) 2907 { 2908 Status = STATUS_INSUFFICIENT_RESOURCES; 2909 goto done; 2910 } 2911 2912 TRACE("Part 2\n"); 2913 2914 EnumIndex = *EnumerationContext; 2915 for (i = 0; i < EnumCount; i++, EnumIndex++) 2916 { 2917 NameLength = 64 * sizeof(WCHAR); 2918 DataLength = sizeof(ULONG); 2919 Status = SampRegEnumerateValue(NamesKeyHandle, 2920 EnumIndex, 2921 UserName, 2922 &NameLength, 2923 NULL, 2924 &Rid, 2925 &DataLength); 2926 if (!NT_SUCCESS(Status)) 2927 { 2928 if (Status == STATUS_NO_MORE_ENTRIES) 2929 Status = STATUS_SUCCESS; 2930 break; 2931 } 2932 2933 TRACE("EnumIndex: %lu\n", EnumIndex); 2934 TRACE("User name: %S\n", UserName); 2935 TRACE("Name length: %lu\n", NameLength); 2936 TRACE("RID: %lu\n", Rid); 2937 2938 EnumBuffer->Buffer[i].RelativeId = Rid; 2939 2940 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength; 2941 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(NameLength + sizeof(UNICODE_NULL)); 2942 2943 /* FIXME: Disabled because of bugs in widl and rpcrt4 */ 2944 #if 0 2945 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength); 2946 if (EnumBuffer->Buffer[i].Name.Buffer == NULL) 2947 { 2948 Status = STATUS_INSUFFICIENT_RESOURCES; 2949 goto done; 2950 } 2951 2952 memcpy(EnumBuffer->Buffer[i].Name.Buffer, 2953 UserName, 2954 EnumBuffer->Buffer[i].Name.Length); 2955 #endif 2956 } 2957 2958 done: 2959 if (NT_SUCCESS(Status)) 2960 { 2961 *EnumerationContext += EnumCount; 2962 *Buffer = EnumBuffer; 2963 *CountReturned = EnumCount; 2964 } 2965 else 2966 { 2967 *EnumerationContext = 0; 2968 *Buffer = NULL; 2969 *CountReturned = 0; 2970 2971 if (EnumBuffer != NULL) 2972 { 2973 if (EnumBuffer->Buffer != NULL) 2974 { 2975 if (EnumBuffer->EntriesRead != 0) 2976 { 2977 for (i = 0; i < EnumBuffer->EntriesRead; i++) 2978 { 2979 if (EnumBuffer->Buffer[i].Name.Buffer != NULL) 2980 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer); 2981 } 2982 } 2983 2984 midl_user_free(EnumBuffer->Buffer); 2985 } 2986 2987 midl_user_free(EnumBuffer); 2988 } 2989 } 2990 2991 SampRegCloseKey(&NamesKeyHandle); 2992 SampRegCloseKey(&UsersKeyHandle); 2993 2994 if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE)) 2995 Status = STATUS_MORE_ENTRIES; 2996 2997 RtlReleaseResource(&SampResource); 2998 2999 return Status; 3000 } 3001 3002 3003 /* Function 14 */ 3004 NTSTATUS 3005 NTAPI 3006 SamrCreateAliasInDomain(IN SAMPR_HANDLE DomainHandle, 3007 IN PRPC_UNICODE_STRING AccountName, 3008 IN ACCESS_MASK DesiredAccess, 3009 OUT SAMPR_HANDLE *AliasHandle, 3010 OUT unsigned long *RelativeId) 3011 { 3012 SAM_DOMAIN_FIXED_DATA FixedDomainData; 3013 PSAM_DB_OBJECT DomainObject; 3014 PSAM_DB_OBJECT AliasObject; 3015 PSECURITY_DESCRIPTOR Sd = NULL; 3016 ULONG SdSize = 0; 3017 ULONG ulSize; 3018 ULONG ulRid; 3019 WCHAR szRid[9]; 3020 NTSTATUS Status; 3021 3022 TRACE("SamrCreateAliasInDomain(%p %p %lx %p %p)\n", 3023 DomainHandle, AccountName, DesiredAccess, AliasHandle, RelativeId); 3024 3025 /* Map generic access rights */ 3026 RtlMapGenericMask(&DesiredAccess, 3027 &AliasMapping); 3028 3029 RtlAcquireResourceExclusive(&SampResource, 3030 TRUE); 3031 3032 /* Validate the domain handle */ 3033 Status = SampValidateDbObject(DomainHandle, 3034 SamDbDomainObject, 3035 DOMAIN_CREATE_ALIAS, 3036 &DomainObject); 3037 if (!NT_SUCCESS(Status)) 3038 { 3039 TRACE("failed with status 0x%08lx\n", Status); 3040 goto done; 3041 } 3042 3043 /* Check the alias account name */ 3044 Status = SampCheckAccountName(AccountName, 256); 3045 if (!NT_SUCCESS(Status)) 3046 { 3047 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 3048 goto done; 3049 } 3050 3051 /* Check if the alias name already exists in the domain */ 3052 Status = SampCheckAccountNameInDomain(DomainObject, 3053 AccountName->Buffer); 3054 if (!NT_SUCCESS(Status)) 3055 { 3056 TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n", 3057 AccountName->Buffer, Status); 3058 goto done; 3059 } 3060 3061 /* Create the security descriptor */ 3062 Status = SampCreateAliasSD(&Sd, 3063 &SdSize); 3064 if (!NT_SUCCESS(Status)) 3065 { 3066 TRACE("SampCreateAliasSD failed (Status 0x%08lx)\n", Status); 3067 goto done; 3068 } 3069 3070 /* Get the fixed domain attributes */ 3071 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA); 3072 Status = SampGetObjectAttribute(DomainObject, 3073 L"F", 3074 NULL, 3075 (PVOID)&FixedDomainData, 3076 &ulSize); 3077 if (!NT_SUCCESS(Status)) 3078 { 3079 TRACE("failed with status 0x%08lx\n", Status); 3080 goto done; 3081 } 3082 3083 /* Increment the NextRid attribute */ 3084 ulRid = FixedDomainData.NextRid; 3085 FixedDomainData.NextRid++; 3086 3087 /* Store the fixed domain attributes */ 3088 Status = SampSetObjectAttribute(DomainObject, 3089 L"F", 3090 REG_BINARY, 3091 &FixedDomainData, 3092 ulSize); 3093 if (!NT_SUCCESS(Status)) 3094 { 3095 TRACE("failed with status 0x%08lx\n", Status); 3096 goto done; 3097 } 3098 3099 TRACE("RID: %lx\n", ulRid); 3100 3101 /* Convert the RID into a string (hex) */ 3102 swprintf(szRid, L"%08lX", ulRid); 3103 3104 /* Create the alias object */ 3105 Status = SampCreateDbObject(DomainObject, 3106 L"Aliases", 3107 szRid, 3108 ulRid, 3109 SamDbAliasObject, 3110 DesiredAccess, 3111 &AliasObject); 3112 if (!NT_SUCCESS(Status)) 3113 { 3114 TRACE("failed with status 0x%08lx\n", Status); 3115 goto done; 3116 } 3117 3118 /* Add the account name for the alias object */ 3119 Status = SampSetAccountNameInDomain(DomainObject, 3120 L"Aliases", 3121 AccountName->Buffer, 3122 ulRid); 3123 if (!NT_SUCCESS(Status)) 3124 { 3125 TRACE("failed with status 0x%08lx\n", Status); 3126 goto done; 3127 } 3128 3129 /* Set the Name attribute */ 3130 Status = SampSetObjectAttributeString(AliasObject, 3131 L"Name", 3132 AccountName); 3133 if (!NT_SUCCESS(Status)) 3134 { 3135 TRACE("failed with status 0x%08lx\n", Status); 3136 goto done; 3137 } 3138 3139 /* Set the Description attribute */ 3140 Status = SampSetObjectAttributeString(AliasObject, 3141 L"Description", 3142 NULL); 3143 if (!NT_SUCCESS(Status)) 3144 { 3145 TRACE("failed with status 0x%08lx\n", Status); 3146 goto done; 3147 } 3148 3149 /* Set the SecDesc attribute*/ 3150 Status = SampSetObjectAttribute(AliasObject, 3151 L"SecDesc", 3152 REG_BINARY, 3153 Sd, 3154 SdSize); 3155 if (!NT_SUCCESS(Status)) 3156 { 3157 TRACE("failed with status 0x%08lx\n", Status); 3158 goto done; 3159 } 3160 3161 if (NT_SUCCESS(Status)) 3162 { 3163 *AliasHandle = (SAMPR_HANDLE)AliasObject; 3164 *RelativeId = ulRid; 3165 } 3166 3167 done: 3168 if (Sd != NULL) 3169 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd); 3170 3171 RtlReleaseResource(&SampResource); 3172 3173 TRACE("returns with status 0x%08lx\n", Status); 3174 3175 return Status; 3176 } 3177 3178 3179 /* Function 15 */ 3180 NTSTATUS 3181 NTAPI 3182 SamrEnumerateAliasesInDomain(IN SAMPR_HANDLE DomainHandle, 3183 IN OUT unsigned long *EnumerationContext, 3184 OUT PSAMPR_ENUMERATION_BUFFER *Buffer, 3185 IN unsigned long PreferedMaximumLength, 3186 OUT unsigned long *CountReturned) 3187 { 3188 PSAMPR_ENUMERATION_BUFFER EnumBuffer = NULL; 3189 PSAM_DB_OBJECT DomainObject; 3190 HANDLE AliasesKeyHandle = NULL; 3191 HANDLE NamesKeyHandle = NULL; 3192 WCHAR AliasName[64]; 3193 ULONG EnumIndex; 3194 ULONG EnumCount = 0; 3195 ULONG RequiredLength = 0; 3196 ULONG NameLength; 3197 ULONG DataLength; 3198 ULONG Rid; 3199 ULONG i; 3200 BOOLEAN MoreEntries = FALSE; 3201 NTSTATUS Status; 3202 3203 TRACE("SamrEnumerateAliasesInDomain(%p %p %p %lu %p)\n", 3204 DomainHandle, EnumerationContext, Buffer, 3205 PreferedMaximumLength, CountReturned); 3206 3207 RtlAcquireResourceShared(&SampResource, 3208 TRUE); 3209 3210 /* Validate the domain handle */ 3211 Status = SampValidateDbObject(DomainHandle, 3212 SamDbDomainObject, 3213 DOMAIN_LIST_ACCOUNTS, 3214 &DomainObject); 3215 if (!NT_SUCCESS(Status)) 3216 goto done; 3217 3218 Status = SampRegOpenKey(DomainObject->KeyHandle, 3219 L"Aliases", 3220 KEY_READ, 3221 &AliasesKeyHandle); 3222 if (!NT_SUCCESS(Status)) 3223 goto done; 3224 3225 Status = SampRegOpenKey(AliasesKeyHandle, 3226 L"Names", 3227 KEY_READ, 3228 &NamesKeyHandle); 3229 if (!NT_SUCCESS(Status)) 3230 goto done; 3231 3232 TRACE("Part 1\n"); 3233 3234 EnumIndex = *EnumerationContext; 3235 3236 while (TRUE) 3237 { 3238 NameLength = 64 * sizeof(WCHAR); 3239 Status = SampRegEnumerateValue(NamesKeyHandle, 3240 EnumIndex, 3241 AliasName, 3242 &NameLength, 3243 NULL, 3244 NULL, 3245 NULL); 3246 if (!NT_SUCCESS(Status)) 3247 { 3248 if (Status == STATUS_NO_MORE_ENTRIES) 3249 Status = STATUS_SUCCESS; 3250 break; 3251 } 3252 3253 TRACE("EnumIndex: %lu\n", EnumIndex); 3254 TRACE("Alias name: %S\n", AliasName); 3255 TRACE("Name length: %lu\n", NameLength); 3256 3257 if ((RequiredLength + NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)) > PreferedMaximumLength) 3258 { 3259 MoreEntries = TRUE; 3260 break; 3261 } 3262 3263 RequiredLength += (NameLength + sizeof(UNICODE_NULL) + sizeof(SAMPR_RID_ENUMERATION)); 3264 EnumCount++; 3265 3266 EnumIndex++; 3267 } 3268 3269 TRACE("EnumCount: %lu\n", EnumCount); 3270 TRACE("RequiredLength: %lu\n", RequiredLength); 3271 3272 if (!NT_SUCCESS(Status)) 3273 goto done; 3274 3275 EnumBuffer = midl_user_allocate(sizeof(SAMPR_ENUMERATION_BUFFER)); 3276 if (EnumBuffer == NULL) 3277 { 3278 Status = STATUS_INSUFFICIENT_RESOURCES; 3279 goto done; 3280 } 3281 3282 EnumBuffer->EntriesRead = EnumCount; 3283 if (EnumCount == 0) 3284 goto done; 3285 3286 EnumBuffer->Buffer = midl_user_allocate(EnumCount * sizeof(SAMPR_RID_ENUMERATION)); 3287 if (EnumBuffer->Buffer == NULL) 3288 { 3289 Status = STATUS_INSUFFICIENT_RESOURCES; 3290 goto done; 3291 } 3292 3293 TRACE("Part 2\n"); 3294 3295 EnumIndex = *EnumerationContext; 3296 for (i = 0; i < EnumCount; i++, EnumIndex++) 3297 { 3298 NameLength = 64 * sizeof(WCHAR); 3299 DataLength = sizeof(ULONG); 3300 Status = SampRegEnumerateValue(NamesKeyHandle, 3301 EnumIndex, 3302 AliasName, 3303 &NameLength, 3304 NULL, 3305 &Rid, 3306 &DataLength); 3307 if (!NT_SUCCESS(Status)) 3308 { 3309 if (Status == STATUS_NO_MORE_ENTRIES) 3310 Status = STATUS_SUCCESS; 3311 break; 3312 } 3313 3314 TRACE("EnumIndex: %lu\n", EnumIndex); 3315 TRACE("Alias name: %S\n", AliasName); 3316 TRACE("Name length: %lu\n", NameLength); 3317 TRACE("RID: %lu\n", Rid); 3318 3319 EnumBuffer->Buffer[i].RelativeId = Rid; 3320 3321 EnumBuffer->Buffer[i].Name.Length = (USHORT)NameLength; 3322 EnumBuffer->Buffer[i].Name.MaximumLength = (USHORT)(NameLength + sizeof(UNICODE_NULL)); 3323 3324 /* FIXME: Disabled because of bugs in widl and rpcrt4 */ 3325 #if 0 3326 EnumBuffer->Buffer[i].Name.Buffer = midl_user_allocate(EnumBuffer->Buffer[i].Name.MaximumLength); 3327 if (EnumBuffer->Buffer[i].Name.Buffer == NULL) 3328 { 3329 Status = STATUS_INSUFFICIENT_RESOURCES; 3330 goto done; 3331 } 3332 3333 memcpy(EnumBuffer->Buffer[i].Name.Buffer, 3334 AliasName, 3335 EnumBuffer->Buffer[i].Name.Length); 3336 #endif 3337 } 3338 3339 done: 3340 if (NT_SUCCESS(Status)) 3341 { 3342 *EnumerationContext += EnumCount; 3343 *Buffer = EnumBuffer; 3344 *CountReturned = EnumCount; 3345 } 3346 else 3347 { 3348 *EnumerationContext = 0; 3349 *Buffer = NULL; 3350 *CountReturned = 0; 3351 3352 if (EnumBuffer != NULL) 3353 { 3354 if (EnumBuffer->Buffer != NULL) 3355 { 3356 if (EnumBuffer->EntriesRead != 0) 3357 { 3358 for (i = 0; i < EnumBuffer->EntriesRead; i++) 3359 { 3360 if (EnumBuffer->Buffer[i].Name.Buffer != NULL) 3361 midl_user_free(EnumBuffer->Buffer[i].Name.Buffer); 3362 } 3363 } 3364 3365 midl_user_free(EnumBuffer->Buffer); 3366 } 3367 3368 midl_user_free(EnumBuffer); 3369 } 3370 } 3371 3372 SampRegCloseKey(&NamesKeyHandle); 3373 SampRegCloseKey(&AliasesKeyHandle); 3374 3375 if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE)) 3376 Status = STATUS_MORE_ENTRIES; 3377 3378 RtlReleaseResource(&SampResource); 3379 3380 return Status; 3381 } 3382 3383 3384 /* Function 16 */ 3385 NTSTATUS 3386 NTAPI 3387 SamrGetAliasMembership(IN SAMPR_HANDLE DomainHandle, 3388 IN PSAMPR_PSID_ARRAY SidArray, 3389 OUT PSAMPR_ULONG_ARRAY Membership) 3390 { 3391 PSAM_DB_OBJECT DomainObject; 3392 HANDLE AliasesKeyHandle = NULL; 3393 HANDLE MembersKeyHandle = NULL; 3394 HANDLE MemberKeyHandle = NULL; 3395 LPWSTR MemberSidString = NULL; 3396 PULONG RidArray = NULL; 3397 ULONG MaxSidCount = 0; 3398 ULONG ValueCount; 3399 ULONG DataLength; 3400 ULONG i, j; 3401 ULONG RidIndex; 3402 NTSTATUS Status; 3403 WCHAR NameBuffer[9]; 3404 3405 TRACE("SamrGetAliasMembership(%p %p %p)\n", 3406 DomainHandle, SidArray, Membership); 3407 3408 RtlAcquireResourceShared(&SampResource, 3409 TRUE); 3410 3411 /* Validate the domain handle */ 3412 Status = SampValidateDbObject(DomainHandle, 3413 SamDbDomainObject, 3414 DOMAIN_GET_ALIAS_MEMBERSHIP, 3415 &DomainObject); 3416 if (!NT_SUCCESS(Status)) 3417 goto done; 3418 3419 Status = SampRegOpenKey(DomainObject->KeyHandle, 3420 L"Aliases", 3421 KEY_READ, 3422 &AliasesKeyHandle); 3423 TRACE("SampRegOpenKey returned %08lX\n", Status); 3424 if (!NT_SUCCESS(Status)) 3425 goto done; 3426 3427 Status = SampRegOpenKey(AliasesKeyHandle, 3428 L"Members", 3429 KEY_READ, 3430 &MembersKeyHandle); 3431 TRACE("SampRegOpenKey returned %08lX\n", Status); 3432 3433 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 3434 { 3435 Status = STATUS_SUCCESS; 3436 goto done; 3437 } 3438 3439 if (!NT_SUCCESS(Status)) 3440 goto done; 3441 3442 for (i = 0; i < SidArray->Count; i++) 3443 { 3444 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString); 3445 TRACE("Open %S\n", MemberSidString); 3446 3447 Status = SampRegOpenKey(MembersKeyHandle, 3448 MemberSidString, 3449 KEY_READ, 3450 &MemberKeyHandle); 3451 TRACE("SampRegOpenKey returned %08lX\n", Status); 3452 if (NT_SUCCESS(Status)) 3453 { 3454 Status = SampRegQueryKeyInfo(MemberKeyHandle, 3455 NULL, 3456 &ValueCount); 3457 if (NT_SUCCESS(Status)) 3458 { 3459 TRACE("Found %lu values\n", ValueCount); 3460 MaxSidCount += ValueCount; 3461 } 3462 3463 SampRegCloseKey(&MemberKeyHandle); 3464 } 3465 3466 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 3467 Status = STATUS_SUCCESS; 3468 3469 LocalFree(MemberSidString); 3470 } 3471 3472 if (MaxSidCount == 0) 3473 { 3474 Status = STATUS_SUCCESS; 3475 goto done; 3476 } 3477 3478 TRACE("Maximum sid count: %lu\n", MaxSidCount); 3479 RidArray = midl_user_allocate(MaxSidCount * sizeof(ULONG)); 3480 if (RidArray == NULL) 3481 { 3482 Status = STATUS_INSUFFICIENT_RESOURCES; 3483 goto done; 3484 } 3485 3486 RidIndex = 0; 3487 for (i = 0; i < SidArray->Count; i++) 3488 { 3489 ConvertSidToStringSid(SidArray->Sids[i].SidPointer, &MemberSidString); 3490 TRACE("Open %S\n", MemberSidString); 3491 3492 Status = SampRegOpenKey(MembersKeyHandle, 3493 MemberSidString, 3494 KEY_READ, 3495 &MemberKeyHandle); 3496 TRACE("SampRegOpenKey returned %08lX\n", Status); 3497 if (NT_SUCCESS(Status)) 3498 { 3499 Status = SampRegQueryKeyInfo(MemberKeyHandle, 3500 NULL, 3501 &ValueCount); 3502 if (NT_SUCCESS(Status)) 3503 { 3504 TRACE("Found %lu values\n", ValueCount); 3505 3506 for (j = 0; j < ValueCount; j++) 3507 { 3508 DataLength = 9 * sizeof(WCHAR); 3509 Status = SampRegEnumerateValue(MemberKeyHandle, 3510 j, 3511 NameBuffer, 3512 &DataLength, 3513 NULL, 3514 NULL, 3515 NULL); 3516 if (NT_SUCCESS(Status)) 3517 { 3518 /* FIXME: Do not return each RID more than once. */ 3519 RidArray[RidIndex] = wcstoul(NameBuffer, NULL, 16); 3520 RidIndex++; 3521 } 3522 } 3523 } 3524 3525 SampRegCloseKey(&MemberKeyHandle); 3526 } 3527 3528 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 3529 Status = STATUS_SUCCESS; 3530 3531 LocalFree(MemberSidString); 3532 } 3533 3534 done: 3535 SampRegCloseKey(&MembersKeyHandle); 3536 SampRegCloseKey(&AliasesKeyHandle); 3537 3538 if (NT_SUCCESS(Status)) 3539 { 3540 Membership->Count = MaxSidCount; 3541 Membership->Element = RidArray; 3542 } 3543 else 3544 { 3545 if (RidArray != NULL) 3546 midl_user_free(RidArray); 3547 } 3548 3549 RtlReleaseResource(&SampResource); 3550 3551 return Status; 3552 } 3553 3554 3555 /* Function 17 */ 3556 NTSTATUS 3557 NTAPI 3558 SamrLookupNamesInDomain(IN SAMPR_HANDLE DomainHandle, 3559 IN ULONG Count, 3560 IN RPC_UNICODE_STRING Names[], 3561 OUT PSAMPR_ULONG_ARRAY RelativeIds, 3562 OUT PSAMPR_ULONG_ARRAY Use) 3563 { 3564 PSAM_DB_OBJECT DomainObject; 3565 HANDLE AccountsKeyHandle = NULL; 3566 HANDLE NamesKeyHandle = NULL; 3567 ULONG MappedCount = 0; 3568 ULONG DataLength; 3569 ULONG i; 3570 ULONG RelativeId; 3571 NTSTATUS Status; 3572 3573 TRACE("SamrLookupNamesInDomain(%p %lu %p %p %p)\n", 3574 DomainHandle, Count, Names, RelativeIds, Use); 3575 3576 RtlAcquireResourceShared(&SampResource, 3577 TRUE); 3578 3579 /* Validate the domain handle */ 3580 Status = SampValidateDbObject(DomainHandle, 3581 SamDbDomainObject, 3582 DOMAIN_LOOKUP, 3583 &DomainObject); 3584 if (!NT_SUCCESS(Status)) 3585 { 3586 TRACE("failed with status 0x%08lx\n", Status); 3587 goto done; 3588 } 3589 3590 RelativeIds->Count = 0; 3591 Use->Count = 0; 3592 3593 if (Count == 0) 3594 { 3595 Status = STATUS_SUCCESS; 3596 goto done; 3597 } 3598 3599 /* Allocate the relative IDs array */ 3600 RelativeIds->Element = midl_user_allocate(Count * sizeof(ULONG)); 3601 if (RelativeIds->Element == NULL) 3602 { 3603 Status = STATUS_INSUFFICIENT_RESOURCES; 3604 goto done; 3605 } 3606 3607 /* Allocate the use array */ 3608 Use->Element = midl_user_allocate(Count * sizeof(ULONG)); 3609 if (Use->Element == NULL) 3610 { 3611 Status = STATUS_INSUFFICIENT_RESOURCES; 3612 goto done; 3613 } 3614 3615 RelativeIds->Count = Count; 3616 Use->Count = Count; 3617 3618 for (i = 0; i < Count; i++) 3619 { 3620 TRACE("Name: %S\n", Names[i].Buffer); 3621 3622 RelativeId = 0; 3623 3624 /* Lookup aliases */ 3625 Status = SampRegOpenKey(DomainObject->KeyHandle, 3626 L"Aliases", 3627 KEY_READ, 3628 &AccountsKeyHandle); 3629 if (NT_SUCCESS(Status)) 3630 { 3631 Status = SampRegOpenKey(AccountsKeyHandle, 3632 L"Names", 3633 KEY_READ, 3634 &NamesKeyHandle); 3635 if (NT_SUCCESS(Status)) 3636 { 3637 DataLength = sizeof(ULONG); 3638 Status = SampRegQueryValue(NamesKeyHandle, 3639 Names[i].Buffer, 3640 NULL, 3641 &RelativeId, 3642 &DataLength); 3643 3644 SampRegCloseKey(&NamesKeyHandle); 3645 } 3646 3647 SampRegCloseKey(&AccountsKeyHandle); 3648 } 3649 3650 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 3651 break; 3652 3653 /* Return alias account */ 3654 if (NT_SUCCESS(Status) && RelativeId != 0) 3655 { 3656 TRACE("Rid: %lu\n", RelativeId); 3657 RelativeIds->Element[i] = RelativeId; 3658 Use->Element[i] = SidTypeAlias; 3659 MappedCount++; 3660 continue; 3661 } 3662 3663 /* Lookup groups */ 3664 Status = SampRegOpenKey(DomainObject->KeyHandle, 3665 L"Groups", 3666 KEY_READ, 3667 &AccountsKeyHandle); 3668 if (NT_SUCCESS(Status)) 3669 { 3670 Status = SampRegOpenKey(AccountsKeyHandle, 3671 L"Names", 3672 KEY_READ, 3673 &NamesKeyHandle); 3674 if (NT_SUCCESS(Status)) 3675 { 3676 DataLength = sizeof(ULONG); 3677 Status = SampRegQueryValue(NamesKeyHandle, 3678 Names[i].Buffer, 3679 NULL, 3680 &RelativeId, 3681 &DataLength); 3682 3683 SampRegCloseKey(&NamesKeyHandle); 3684 } 3685 3686 SampRegCloseKey(&AccountsKeyHandle); 3687 } 3688 3689 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 3690 break; 3691 3692 /* Return group account */ 3693 if (NT_SUCCESS(Status) && RelativeId != 0) 3694 { 3695 TRACE("Rid: %lu\n", RelativeId); 3696 RelativeIds->Element[i] = RelativeId; 3697 Use->Element[i] = SidTypeGroup; 3698 MappedCount++; 3699 continue; 3700 } 3701 3702 /* Lookup users */ 3703 Status = SampRegOpenKey(DomainObject->KeyHandle, 3704 L"Users", 3705 KEY_READ, 3706 &AccountsKeyHandle); 3707 if (NT_SUCCESS(Status)) 3708 { 3709 Status = SampRegOpenKey(AccountsKeyHandle, 3710 L"Names", 3711 KEY_READ, 3712 &NamesKeyHandle); 3713 if (NT_SUCCESS(Status)) 3714 { 3715 DataLength = sizeof(ULONG); 3716 Status = SampRegQueryValue(NamesKeyHandle, 3717 Names[i].Buffer, 3718 NULL, 3719 &RelativeId, 3720 &DataLength); 3721 3722 SampRegCloseKey(&NamesKeyHandle); 3723 } 3724 3725 SampRegCloseKey(&AccountsKeyHandle); 3726 } 3727 3728 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 3729 break; 3730 3731 /* Return user account */ 3732 if (NT_SUCCESS(Status) && RelativeId != 0) 3733 { 3734 TRACE("Rid: %lu\n", RelativeId); 3735 RelativeIds->Element[i] = RelativeId; 3736 Use->Element[i] = SidTypeUser; 3737 MappedCount++; 3738 continue; 3739 } 3740 3741 /* Return unknown account */ 3742 RelativeIds->Element[i] = 0; 3743 Use->Element[i] = SidTypeUnknown; 3744 } 3745 3746 done: 3747 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 3748 Status = STATUS_SUCCESS; 3749 3750 if (NT_SUCCESS(Status)) 3751 { 3752 if (MappedCount == 0) 3753 Status = STATUS_NONE_MAPPED; 3754 else if (MappedCount < Count) 3755 Status = STATUS_SOME_NOT_MAPPED; 3756 } 3757 else 3758 { 3759 if (RelativeIds->Element != NULL) 3760 { 3761 midl_user_free(RelativeIds->Element); 3762 RelativeIds->Element = NULL; 3763 } 3764 3765 RelativeIds->Count = 0; 3766 3767 if (Use->Element != NULL) 3768 { 3769 midl_user_free(Use->Element); 3770 Use->Element = NULL; 3771 } 3772 3773 Use->Count = 0; 3774 } 3775 3776 RtlReleaseResource(&SampResource); 3777 3778 TRACE("Returned Status %lx\n", Status); 3779 3780 return Status; 3781 } 3782 3783 3784 /* Function 18 */ 3785 NTSTATUS 3786 NTAPI 3787 SamrLookupIdsInDomain(IN SAMPR_HANDLE DomainHandle, 3788 IN ULONG Count, 3789 IN ULONG *RelativeIds, 3790 OUT PSAMPR_RETURNED_USTRING_ARRAY Names, 3791 OUT PSAMPR_ULONG_ARRAY Use) 3792 { 3793 PSAM_DB_OBJECT DomainObject; 3794 WCHAR RidString[9]; 3795 HANDLE AccountsKeyHandle = NULL; 3796 HANDLE AccountKeyHandle = NULL; 3797 ULONG MappedCount = 0; 3798 ULONG DataLength; 3799 ULONG i; 3800 NTSTATUS Status; 3801 3802 TRACE("SamrLookupIdsInDomain(%p %lu %p %p %p)\n", 3803 DomainHandle, Count, RelativeIds, Names, Use); 3804 3805 RtlAcquireResourceShared(&SampResource, 3806 TRUE); 3807 3808 /* Validate the domain handle */ 3809 Status = SampValidateDbObject(DomainHandle, 3810 SamDbDomainObject, 3811 DOMAIN_LOOKUP, 3812 &DomainObject); 3813 if (!NT_SUCCESS(Status)) 3814 { 3815 TRACE("failed with status 0x%08lx\n", Status); 3816 goto done; 3817 } 3818 3819 Names->Count = 0; 3820 Use->Count = 0; 3821 3822 if (Count == 0) 3823 { 3824 Status = STATUS_SUCCESS; 3825 goto done; 3826 } 3827 3828 /* Allocate the names array */ 3829 Names->Element = midl_user_allocate(Count * sizeof(*Names->Element)); 3830 if (Names->Element == NULL) 3831 { 3832 Status = STATUS_INSUFFICIENT_RESOURCES; 3833 goto done; 3834 } 3835 3836 /* Allocate the use array */ 3837 Use->Element = midl_user_allocate(Count * sizeof(*Use->Element)); 3838 if (Use->Element == NULL) 3839 { 3840 Status = STATUS_INSUFFICIENT_RESOURCES; 3841 goto done; 3842 } 3843 3844 Names->Count = Count; 3845 Use->Count = Count; 3846 3847 for (i = 0; i < Count; i++) 3848 { 3849 TRACE("RID: %lu\n", RelativeIds[i]); 3850 3851 swprintf(RidString, L"%08lx", RelativeIds[i]); 3852 3853 /* Lookup aliases */ 3854 Status = SampRegOpenKey(DomainObject->KeyHandle, 3855 L"Aliases", 3856 KEY_READ, 3857 &AccountsKeyHandle); 3858 if (NT_SUCCESS(Status)) 3859 { 3860 Status = SampRegOpenKey(AccountsKeyHandle, 3861 RidString, 3862 KEY_READ, 3863 &AccountKeyHandle); 3864 if (NT_SUCCESS(Status)) 3865 { 3866 DataLength = 0; 3867 Status = SampRegQueryValue(AccountKeyHandle, 3868 L"Name", 3869 NULL, 3870 NULL, 3871 &DataLength); 3872 if (NT_SUCCESS(Status)) 3873 { 3874 Names->Element[i].Buffer = midl_user_allocate(DataLength); 3875 if (Names->Element[i].Buffer == NULL) 3876 Status = STATUS_INSUFFICIENT_RESOURCES; 3877 3878 if (NT_SUCCESS(Status)) 3879 { 3880 Names->Element[i].MaximumLength = (USHORT)DataLength; 3881 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR)); 3882 3883 Status = SampRegQueryValue(AccountKeyHandle, 3884 L"Name", 3885 NULL, 3886 Names->Element[i].Buffer, 3887 &DataLength); 3888 } 3889 } 3890 3891 SampRegCloseKey(&AccountKeyHandle); 3892 } 3893 3894 SampRegCloseKey(&AccountsKeyHandle); 3895 } 3896 3897 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 3898 break; 3899 3900 /* Return alias account */ 3901 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL) 3902 { 3903 TRACE("Name: %S\n", Names->Element[i].Buffer); 3904 Use->Element[i] = SidTypeAlias; 3905 MappedCount++; 3906 continue; 3907 } 3908 3909 /* Lookup groups */ 3910 Status = SampRegOpenKey(DomainObject->KeyHandle, 3911 L"Groups", 3912 KEY_READ, 3913 &AccountsKeyHandle); 3914 if (NT_SUCCESS(Status)) 3915 { 3916 Status = SampRegOpenKey(AccountsKeyHandle, 3917 RidString, 3918 KEY_READ, 3919 &AccountKeyHandle); 3920 if (NT_SUCCESS(Status)) 3921 { 3922 DataLength = 0; 3923 Status = SampRegQueryValue(AccountKeyHandle, 3924 L"Name", 3925 NULL, 3926 NULL, 3927 &DataLength); 3928 if (NT_SUCCESS(Status)) 3929 { 3930 Names->Element[i].Buffer = midl_user_allocate(DataLength); 3931 if (Names->Element[i].Buffer == NULL) 3932 Status = STATUS_INSUFFICIENT_RESOURCES; 3933 3934 if (NT_SUCCESS(Status)) 3935 { 3936 Names->Element[i].MaximumLength = (USHORT)DataLength; 3937 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR)); 3938 3939 Status = SampRegQueryValue(AccountKeyHandle, 3940 L"Name", 3941 NULL, 3942 Names->Element[i].Buffer, 3943 &DataLength); 3944 } 3945 } 3946 3947 SampRegCloseKey(&AccountKeyHandle); 3948 } 3949 3950 SampRegCloseKey(&AccountsKeyHandle); 3951 } 3952 3953 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 3954 break; 3955 3956 /* Return group account */ 3957 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL) 3958 { 3959 TRACE("Name: %S\n", Names->Element[i].Buffer); 3960 Use->Element[i] = SidTypeGroup; 3961 MappedCount++; 3962 continue; 3963 } 3964 3965 /* Lookup users */ 3966 Status = SampRegOpenKey(DomainObject->KeyHandle, 3967 L"Users", 3968 KEY_READ, 3969 &AccountsKeyHandle); 3970 if (NT_SUCCESS(Status)) 3971 { 3972 Status = SampRegOpenKey(AccountsKeyHandle, 3973 RidString, 3974 KEY_READ, 3975 &AccountKeyHandle); 3976 if (NT_SUCCESS(Status)) 3977 { 3978 DataLength = 0; 3979 Status = SampRegQueryValue(AccountKeyHandle, 3980 L"Name", 3981 NULL, 3982 NULL, 3983 &DataLength); 3984 if (NT_SUCCESS(Status)) 3985 { 3986 TRACE("DataLength: %lu\n", DataLength); 3987 3988 Names->Element[i].Buffer = midl_user_allocate(DataLength); 3989 if (Names->Element[i].Buffer == NULL) 3990 Status = STATUS_INSUFFICIENT_RESOURCES; 3991 3992 if (NT_SUCCESS(Status)) 3993 { 3994 Names->Element[i].MaximumLength = (USHORT)DataLength; 3995 Names->Element[i].Length = (USHORT)(DataLength - sizeof(WCHAR)); 3996 3997 Status = SampRegQueryValue(AccountKeyHandle, 3998 L"Name", 3999 NULL, 4000 Names->Element[i].Buffer, 4001 &DataLength); 4002 } 4003 } 4004 4005 SampRegCloseKey(&AccountKeyHandle); 4006 } 4007 4008 SampRegCloseKey(&AccountsKeyHandle); 4009 } 4010 4011 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 4012 break; 4013 4014 /* Return user account */ 4015 if (NT_SUCCESS(Status) && Names->Element[i].Buffer != NULL) 4016 { 4017 TRACE("Name: %S\n", Names->Element[i].Buffer); 4018 Use->Element[i] = SidTypeUser; 4019 MappedCount++; 4020 continue; 4021 } 4022 4023 /* Return unknown account */ 4024 Use->Element[i] = SidTypeUnknown; 4025 } 4026 4027 done: 4028 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 4029 Status = STATUS_SUCCESS; 4030 4031 if (NT_SUCCESS(Status)) 4032 { 4033 if (MappedCount == 0) 4034 Status = STATUS_NONE_MAPPED; 4035 else if (MappedCount < Count) 4036 Status = STATUS_SOME_NOT_MAPPED; 4037 } 4038 else 4039 { 4040 if (Names->Element != NULL) 4041 { 4042 for (i = 0; i < Count; i++) 4043 { 4044 if (Names->Element[i].Buffer != NULL) 4045 midl_user_free(Names->Element[i].Buffer); 4046 } 4047 4048 midl_user_free(Names->Element); 4049 Names->Element = NULL; 4050 } 4051 4052 Names->Count = 0; 4053 4054 if (Use->Element != NULL) 4055 { 4056 midl_user_free(Use->Element); 4057 Use->Element = NULL; 4058 } 4059 4060 Use->Count = 0; 4061 } 4062 4063 RtlReleaseResource(&SampResource); 4064 4065 return Status; 4066 } 4067 4068 4069 /* Function 19 */ 4070 NTSTATUS 4071 NTAPI 4072 SamrOpenGroup(IN SAMPR_HANDLE DomainHandle, 4073 IN ACCESS_MASK DesiredAccess, 4074 IN unsigned long GroupId, 4075 OUT SAMPR_HANDLE *GroupHandle) 4076 { 4077 PSAM_DB_OBJECT DomainObject; 4078 PSAM_DB_OBJECT GroupObject; 4079 WCHAR szRid[9]; 4080 NTSTATUS Status; 4081 4082 TRACE("SamrOpenGroup(%p %lx %lx %p)\n", 4083 DomainHandle, DesiredAccess, GroupId, GroupHandle); 4084 4085 /* Map generic access rights */ 4086 RtlMapGenericMask(&DesiredAccess, 4087 &GroupMapping); 4088 4089 RtlAcquireResourceShared(&SampResource, 4090 TRUE); 4091 4092 /* Validate the domain handle */ 4093 Status = SampValidateDbObject(DomainHandle, 4094 SamDbDomainObject, 4095 DOMAIN_LOOKUP, 4096 &DomainObject); 4097 if (!NT_SUCCESS(Status)) 4098 { 4099 TRACE("failed with status 0x%08lx\n", Status); 4100 goto done; 4101 } 4102 4103 /* Convert the RID into a string (hex) */ 4104 swprintf(szRid, L"%08lX", GroupId); 4105 4106 /* Create the group object */ 4107 Status = SampOpenDbObject(DomainObject, 4108 L"Groups", 4109 szRid, 4110 GroupId, 4111 SamDbGroupObject, 4112 DesiredAccess, 4113 &GroupObject); 4114 if (!NT_SUCCESS(Status)) 4115 { 4116 TRACE("failed with status 0x%08lx\n", Status); 4117 goto done; 4118 } 4119 4120 *GroupHandle = (SAMPR_HANDLE)GroupObject; 4121 4122 done: 4123 RtlReleaseResource(&SampResource); 4124 4125 return Status; 4126 } 4127 4128 4129 static NTSTATUS 4130 SampQueryGroupGeneral(PSAM_DB_OBJECT GroupObject, 4131 PSAMPR_GROUP_INFO_BUFFER *Buffer) 4132 { 4133 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL; 4134 SAM_GROUP_FIXED_DATA FixedData; 4135 ULONG MembersLength = 0; 4136 ULONG Length = 0; 4137 NTSTATUS Status; 4138 4139 *Buffer = NULL; 4140 4141 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER)); 4142 if (InfoBuffer == NULL) 4143 return STATUS_INSUFFICIENT_RESOURCES; 4144 4145 Status = SampGetObjectAttributeString(GroupObject, 4146 L"Name", 4147 &InfoBuffer->General.Name); 4148 if (!NT_SUCCESS(Status)) 4149 { 4150 TRACE("Status 0x%08lx\n", Status); 4151 goto done; 4152 } 4153 4154 Status = SampGetObjectAttributeString(GroupObject, 4155 L"AdminComment", 4156 &InfoBuffer->General.AdminComment); 4157 if (!NT_SUCCESS(Status)) 4158 { 4159 TRACE("Status 0x%08lx\n", Status); 4160 goto done; 4161 } 4162 4163 Length = sizeof(SAM_GROUP_FIXED_DATA); 4164 Status = SampGetObjectAttribute(GroupObject, 4165 L"F", 4166 NULL, 4167 (PVOID)&FixedData, 4168 &Length); 4169 if (!NT_SUCCESS(Status)) 4170 { 4171 TRACE("Status 0x%08lx\n", Status); 4172 goto done; 4173 } 4174 4175 InfoBuffer->General.Attributes = FixedData.Attributes; 4176 4177 Status = SampGetObjectAttribute(GroupObject, 4178 L"Members", 4179 NULL, 4180 NULL, 4181 &MembersLength); 4182 if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND) 4183 { 4184 TRACE("Status 0x%08lx\n", Status); 4185 goto done; 4186 } 4187 4188 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 4189 { 4190 InfoBuffer->General.MemberCount = 0; 4191 Status = STATUS_SUCCESS; 4192 } 4193 else 4194 { 4195 InfoBuffer->General.MemberCount = MembersLength / sizeof(ULONG); 4196 } 4197 4198 *Buffer = InfoBuffer; 4199 4200 done: 4201 if (!NT_SUCCESS(Status)) 4202 { 4203 if (InfoBuffer != NULL) 4204 { 4205 if (InfoBuffer->General.Name.Buffer != NULL) 4206 midl_user_free(InfoBuffer->General.Name.Buffer); 4207 4208 if (InfoBuffer->General.AdminComment.Buffer != NULL) 4209 midl_user_free(InfoBuffer->General.AdminComment.Buffer); 4210 4211 midl_user_free(InfoBuffer); 4212 } 4213 } 4214 4215 return Status; 4216 } 4217 4218 4219 static NTSTATUS 4220 SampQueryGroupName(PSAM_DB_OBJECT GroupObject, 4221 PSAMPR_GROUP_INFO_BUFFER *Buffer) 4222 { 4223 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL; 4224 NTSTATUS Status; 4225 4226 *Buffer = NULL; 4227 4228 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER)); 4229 if (InfoBuffer == NULL) 4230 return STATUS_INSUFFICIENT_RESOURCES; 4231 4232 Status = SampGetObjectAttributeString(GroupObject, 4233 L"Name", 4234 &InfoBuffer->Name.Name); 4235 if (!NT_SUCCESS(Status)) 4236 { 4237 TRACE("Status 0x%08lx\n", Status); 4238 goto done; 4239 } 4240 4241 *Buffer = InfoBuffer; 4242 4243 done: 4244 if (!NT_SUCCESS(Status)) 4245 { 4246 if (InfoBuffer != NULL) 4247 { 4248 if (InfoBuffer->Name.Name.Buffer != NULL) 4249 midl_user_free(InfoBuffer->Name.Name.Buffer); 4250 4251 midl_user_free(InfoBuffer); 4252 } 4253 } 4254 4255 return Status; 4256 } 4257 4258 4259 static NTSTATUS 4260 SampQueryGroupAttribute(PSAM_DB_OBJECT GroupObject, 4261 PSAMPR_GROUP_INFO_BUFFER *Buffer) 4262 { 4263 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL; 4264 SAM_GROUP_FIXED_DATA FixedData; 4265 ULONG Length = 0; 4266 NTSTATUS Status; 4267 4268 *Buffer = NULL; 4269 4270 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER)); 4271 if (InfoBuffer == NULL) 4272 return STATUS_INSUFFICIENT_RESOURCES; 4273 4274 Length = sizeof(SAM_GROUP_FIXED_DATA); 4275 Status = SampGetObjectAttribute(GroupObject, 4276 L"F", 4277 NULL, 4278 (PVOID)&FixedData, 4279 &Length); 4280 if (!NT_SUCCESS(Status)) 4281 { 4282 TRACE("Status 0x%08lx\n", Status); 4283 goto done; 4284 } 4285 4286 InfoBuffer->Attribute.Attributes = FixedData.Attributes; 4287 4288 *Buffer = InfoBuffer; 4289 4290 done: 4291 if (!NT_SUCCESS(Status)) 4292 { 4293 if (InfoBuffer != NULL) 4294 { 4295 midl_user_free(InfoBuffer); 4296 } 4297 } 4298 4299 return Status; 4300 } 4301 4302 4303 static NTSTATUS 4304 SampQueryGroupAdminComment(PSAM_DB_OBJECT GroupObject, 4305 PSAMPR_GROUP_INFO_BUFFER *Buffer) 4306 { 4307 PSAMPR_GROUP_INFO_BUFFER InfoBuffer = NULL; 4308 NTSTATUS Status; 4309 4310 *Buffer = NULL; 4311 4312 InfoBuffer = midl_user_allocate(sizeof(SAMPR_GROUP_INFO_BUFFER)); 4313 if (InfoBuffer == NULL) 4314 return STATUS_INSUFFICIENT_RESOURCES; 4315 4316 Status = SampGetObjectAttributeString(GroupObject, 4317 L"AdminComment", 4318 &InfoBuffer->AdminComment.AdminComment); 4319 if (!NT_SUCCESS(Status)) 4320 { 4321 TRACE("Status 0x%08lx\n", Status); 4322 goto done; 4323 } 4324 4325 *Buffer = InfoBuffer; 4326 4327 done: 4328 if (!NT_SUCCESS(Status)) 4329 { 4330 if (InfoBuffer != NULL) 4331 { 4332 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL) 4333 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer); 4334 4335 midl_user_free(InfoBuffer); 4336 } 4337 } 4338 4339 return Status; 4340 } 4341 4342 4343 /* Function 20 */ 4344 NTSTATUS 4345 NTAPI 4346 SamrQueryInformationGroup(IN SAMPR_HANDLE GroupHandle, 4347 IN GROUP_INFORMATION_CLASS GroupInformationClass, 4348 OUT PSAMPR_GROUP_INFO_BUFFER *Buffer) 4349 { 4350 PSAM_DB_OBJECT GroupObject; 4351 NTSTATUS Status; 4352 4353 TRACE("SamrQueryInformationGroup(%p %lu %p)\n", 4354 GroupHandle, GroupInformationClass, Buffer); 4355 4356 RtlAcquireResourceShared(&SampResource, 4357 TRUE); 4358 4359 /* Validate the group handle */ 4360 Status = SampValidateDbObject(GroupHandle, 4361 SamDbGroupObject, 4362 GROUP_READ_INFORMATION, 4363 &GroupObject); 4364 if (!NT_SUCCESS(Status)) 4365 goto done; 4366 4367 switch (GroupInformationClass) 4368 { 4369 case GroupGeneralInformation: 4370 Status = SampQueryGroupGeneral(GroupObject, 4371 Buffer); 4372 break; 4373 4374 case GroupNameInformation: 4375 Status = SampQueryGroupName(GroupObject, 4376 Buffer); 4377 break; 4378 4379 case GroupAttributeInformation: 4380 Status = SampQueryGroupAttribute(GroupObject, 4381 Buffer); 4382 break; 4383 4384 case GroupAdminCommentInformation: 4385 Status = SampQueryGroupAdminComment(GroupObject, 4386 Buffer); 4387 break; 4388 4389 default: 4390 Status = STATUS_INVALID_INFO_CLASS; 4391 break; 4392 } 4393 4394 done: 4395 RtlReleaseResource(&SampResource); 4396 4397 return Status; 4398 } 4399 4400 4401 static NTSTATUS 4402 SampSetGroupName(PSAM_DB_OBJECT GroupObject, 4403 PSAMPR_GROUP_INFO_BUFFER Buffer) 4404 { 4405 UNICODE_STRING OldGroupName = {0, 0, NULL}; 4406 UNICODE_STRING NewGroupName; 4407 NTSTATUS Status; 4408 4409 Status = SampGetObjectAttributeString(GroupObject, 4410 L"Name", 4411 (PRPC_UNICODE_STRING)&OldGroupName); 4412 if (!NT_SUCCESS(Status)) 4413 { 4414 TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status); 4415 goto done; 4416 } 4417 4418 /* Check the new account name */ 4419 Status = SampCheckAccountName(&Buffer->Name.Name, 256); 4420 if (!NT_SUCCESS(Status)) 4421 { 4422 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 4423 return Status; 4424 } 4425 4426 NewGroupName.Length = Buffer->Name.Name.Length; 4427 NewGroupName.MaximumLength = Buffer->Name.Name.MaximumLength; 4428 NewGroupName.Buffer = Buffer->Name.Name.Buffer; 4429 4430 if (!RtlEqualUnicodeString(&OldGroupName, &NewGroupName, TRUE)) 4431 { 4432 Status = SampCheckAccountNameInDomain(GroupObject->ParentObject, 4433 NewGroupName.Buffer); 4434 if (!NT_SUCCESS(Status)) 4435 { 4436 TRACE("Group name \'%S\' already exists in domain (Status 0x%08lx)\n", 4437 NewGroupName.Buffer, Status); 4438 goto done; 4439 } 4440 } 4441 4442 Status = SampSetAccountNameInDomain(GroupObject->ParentObject, 4443 L"Groups", 4444 NewGroupName.Buffer, 4445 GroupObject->RelativeId); 4446 if (!NT_SUCCESS(Status)) 4447 { 4448 TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status); 4449 goto done; 4450 } 4451 4452 Status = SampRemoveAccountNameFromDomain(GroupObject->ParentObject, 4453 L"Groups", 4454 OldGroupName.Buffer); 4455 if (!NT_SUCCESS(Status)) 4456 { 4457 TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status); 4458 goto done; 4459 } 4460 4461 Status = SampSetObjectAttributeString(GroupObject, 4462 L"Name", 4463 (PRPC_UNICODE_STRING)&NewGroupName); 4464 if (!NT_SUCCESS(Status)) 4465 { 4466 TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status); 4467 } 4468 4469 done: 4470 if (OldGroupName.Buffer != NULL) 4471 midl_user_free(OldGroupName.Buffer); 4472 4473 return Status; 4474 } 4475 4476 4477 static NTSTATUS 4478 SampSetGroupAttribute(PSAM_DB_OBJECT GroupObject, 4479 PSAMPR_GROUP_INFO_BUFFER Buffer) 4480 { 4481 SAM_GROUP_FIXED_DATA FixedData; 4482 ULONG Length = 0; 4483 NTSTATUS Status; 4484 4485 Length = sizeof(SAM_GROUP_FIXED_DATA); 4486 Status = SampGetObjectAttribute(GroupObject, 4487 L"F", 4488 NULL, 4489 (PVOID)&FixedData, 4490 &Length); 4491 if (!NT_SUCCESS(Status)) 4492 goto done; 4493 4494 FixedData.Attributes = Buffer->Attribute.Attributes; 4495 4496 Status = SampSetObjectAttribute(GroupObject, 4497 L"F", 4498 REG_BINARY, 4499 &FixedData, 4500 Length); 4501 4502 done: 4503 return Status; 4504 } 4505 4506 4507 /* Function 21 */ 4508 NTSTATUS 4509 NTAPI 4510 SamrSetInformationGroup(IN SAMPR_HANDLE GroupHandle, 4511 IN GROUP_INFORMATION_CLASS GroupInformationClass, 4512 IN PSAMPR_GROUP_INFO_BUFFER Buffer) 4513 { 4514 PSAM_DB_OBJECT GroupObject; 4515 NTSTATUS Status; 4516 4517 TRACE("SamrSetInformationGroup(%p %lu %p)\n", 4518 GroupHandle, GroupInformationClass, Buffer); 4519 4520 RtlAcquireResourceExclusive(&SampResource, 4521 TRUE); 4522 4523 /* Validate the group handle */ 4524 Status = SampValidateDbObject(GroupHandle, 4525 SamDbGroupObject, 4526 GROUP_WRITE_ACCOUNT, 4527 &GroupObject); 4528 if (!NT_SUCCESS(Status)) 4529 goto done; 4530 4531 switch (GroupInformationClass) 4532 { 4533 case GroupNameInformation: 4534 Status = SampSetGroupName(GroupObject, 4535 Buffer); 4536 break; 4537 4538 case GroupAttributeInformation: 4539 Status = SampSetGroupAttribute(GroupObject, 4540 Buffer); 4541 break; 4542 4543 case GroupAdminCommentInformation: 4544 Status = SampSetObjectAttributeString(GroupObject, 4545 L"AdminComment", 4546 &Buffer->AdminComment.AdminComment); 4547 break; 4548 4549 default: 4550 Status = STATUS_INVALID_INFO_CLASS; 4551 break; 4552 } 4553 4554 done: 4555 RtlReleaseResource(&SampResource); 4556 4557 return Status; 4558 } 4559 4560 4561 /* Function 22 */ 4562 NTSTATUS 4563 NTAPI 4564 SamrAddMemberToGroup(IN SAMPR_HANDLE GroupHandle, 4565 IN unsigned long MemberId, 4566 IN unsigned long Attributes) 4567 { 4568 PSAM_DB_OBJECT GroupObject; 4569 PSAM_DB_OBJECT UserObject = NULL; 4570 NTSTATUS Status; 4571 4572 TRACE("SamrAddMemberToGroup(%p %lu %lx)\n", 4573 GroupHandle, MemberId, Attributes); 4574 4575 RtlAcquireResourceExclusive(&SampResource, 4576 TRUE); 4577 4578 /* Validate the group handle */ 4579 Status = SampValidateDbObject(GroupHandle, 4580 SamDbGroupObject, 4581 GROUP_ADD_MEMBER, 4582 &GroupObject); 4583 if (!NT_SUCCESS(Status)) 4584 goto done; 4585 4586 /* Open the user object in the same domain */ 4587 Status = SampOpenUserObject(GroupObject->ParentObject, 4588 MemberId, 4589 0, 4590 &UserObject); 4591 if (!NT_SUCCESS(Status)) 4592 { 4593 TRACE("SampOpenUserObject() failed (Status 0x%08lx)\n", Status); 4594 goto done; 4595 } 4596 4597 /* Add group membership to the user object */ 4598 Status = SampAddGroupMembershipToUser(UserObject, 4599 GroupObject->RelativeId, 4600 Attributes); 4601 if (!NT_SUCCESS(Status)) 4602 { 4603 TRACE("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status); 4604 goto done; 4605 } 4606 4607 /* Add the member to the group object */ 4608 Status = SampAddMemberToGroup(GroupObject, 4609 MemberId); 4610 if (!NT_SUCCESS(Status)) 4611 { 4612 TRACE("SampAddMemberToGroup() failed (Status 0x%08lx)\n", Status); 4613 } 4614 4615 done: 4616 if (UserObject) 4617 SampCloseDbObject(UserObject); 4618 4619 RtlReleaseResource(&SampResource); 4620 4621 return Status; 4622 } 4623 4624 4625 /* Function 23 */ 4626 NTSTATUS 4627 NTAPI 4628 SamrDeleteGroup(IN OUT SAMPR_HANDLE *GroupHandle) 4629 { 4630 PSAM_DB_OBJECT GroupObject; 4631 ULONG Length = 0; 4632 NTSTATUS Status; 4633 4634 TRACE("SamrDeleteGroup(%p)\n", GroupHandle); 4635 4636 RtlAcquireResourceExclusive(&SampResource, 4637 TRUE); 4638 4639 /* Validate the group handle */ 4640 Status = SampValidateDbObject(*GroupHandle, 4641 SamDbGroupObject, 4642 DELETE, 4643 &GroupObject); 4644 if (!NT_SUCCESS(Status)) 4645 { 4646 TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status); 4647 goto done; 4648 } 4649 4650 /* Fail, if the group is built-in */ 4651 if (GroupObject->RelativeId < 1000) 4652 { 4653 TRACE("You can not delete a special account!\n"); 4654 Status = STATUS_SPECIAL_ACCOUNT; 4655 goto done; 4656 } 4657 4658 /* Get the length of the Members attribute */ 4659 SampGetObjectAttribute(GroupObject, 4660 L"Members", 4661 NULL, 4662 NULL, 4663 &Length); 4664 4665 /* Fail, if the group has members */ 4666 if (Length != 0) 4667 { 4668 TRACE("There are still members in the group!\n"); 4669 Status = STATUS_MEMBER_IN_GROUP; 4670 goto done; 4671 } 4672 4673 /* FIXME: Remove the group from all aliases */ 4674 4675 /* Delete the group from the database */ 4676 Status = SampDeleteAccountDbObject(GroupObject); 4677 if (!NT_SUCCESS(Status)) 4678 { 4679 TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status); 4680 goto done; 4681 } 4682 4683 /* Invalidate the handle */ 4684 *GroupHandle = NULL; 4685 4686 done: 4687 RtlReleaseResource(&SampResource); 4688 4689 return Status; 4690 } 4691 4692 4693 /* Function 24 */ 4694 NTSTATUS 4695 NTAPI 4696 SamrRemoveMemberFromGroup(IN SAMPR_HANDLE GroupHandle, 4697 IN unsigned long MemberId) 4698 { 4699 PSAM_DB_OBJECT GroupObject; 4700 PSAM_DB_OBJECT UserObject = NULL; 4701 NTSTATUS Status; 4702 4703 TRACE("SamrRemoveMemberFromGroup(%p %lu)\n", 4704 GroupHandle, MemberId); 4705 4706 RtlAcquireResourceExclusive(&SampResource, 4707 TRUE); 4708 4709 /* Validate the group handle */ 4710 Status = SampValidateDbObject(GroupHandle, 4711 SamDbGroupObject, 4712 GROUP_REMOVE_MEMBER, 4713 &GroupObject); 4714 if (!NT_SUCCESS(Status)) 4715 goto done; 4716 4717 /* Open the user object in the same domain */ 4718 Status = SampOpenUserObject(GroupObject->ParentObject, 4719 MemberId, 4720 0, 4721 &UserObject); 4722 if (!NT_SUCCESS(Status)) 4723 { 4724 ERR("SampOpenUserObject() failed (Status 0x%08lx)\n", Status); 4725 goto done; 4726 } 4727 4728 /* Remove group membership from the user object */ 4729 Status = SampRemoveGroupMembershipFromUser(UserObject, 4730 GroupObject->RelativeId); 4731 if (!NT_SUCCESS(Status)) 4732 { 4733 ERR("SampAddGroupMembershipToUser() failed (Status 0x%08lx)\n", Status); 4734 goto done; 4735 } 4736 4737 /* Remove the member from the group object */ 4738 Status = SampRemoveMemberFromGroup(GroupObject, 4739 MemberId); 4740 if (!NT_SUCCESS(Status)) 4741 { 4742 ERR("SampRemoveMemberFromGroup() failed (Status 0x%08lx)\n", Status); 4743 } 4744 4745 done: 4746 if (UserObject) 4747 SampCloseDbObject(UserObject); 4748 4749 RtlReleaseResource(&SampResource); 4750 4751 return Status; 4752 } 4753 4754 4755 /* Function 25 */ 4756 NTSTATUS 4757 NTAPI 4758 SamrGetMembersInGroup(IN SAMPR_HANDLE GroupHandle, 4759 OUT PSAMPR_GET_MEMBERS_BUFFER *Members) 4760 { 4761 PSAMPR_GET_MEMBERS_BUFFER MembersBuffer = NULL; 4762 PSAM_DB_OBJECT GroupObject; 4763 ULONG Length = 0; 4764 ULONG i; 4765 NTSTATUS Status; 4766 4767 TRACE("SamrGetMembersInGroup(%p %p)\n", 4768 GroupHandle, Members); 4769 4770 RtlAcquireResourceShared(&SampResource, 4771 TRUE); 4772 4773 /* Validate the group handle */ 4774 Status = SampValidateDbObject(GroupHandle, 4775 SamDbGroupObject, 4776 GROUP_LIST_MEMBERS, 4777 &GroupObject); 4778 if (!NT_SUCCESS(Status)) 4779 goto done; 4780 4781 MembersBuffer = midl_user_allocate(sizeof(SAMPR_GET_MEMBERS_BUFFER)); 4782 if (MembersBuffer == NULL) 4783 { 4784 Status = STATUS_INSUFFICIENT_RESOURCES; 4785 goto done; 4786 } 4787 4788 SampGetObjectAttribute(GroupObject, 4789 L"Members", 4790 NULL, 4791 NULL, 4792 &Length); 4793 4794 if (Length == 0) 4795 { 4796 MembersBuffer->MemberCount = 0; 4797 MembersBuffer->Members = NULL; 4798 MembersBuffer->Attributes = NULL; 4799 4800 *Members = MembersBuffer; 4801 4802 Status = STATUS_SUCCESS; 4803 goto done; 4804 } 4805 4806 MembersBuffer->Members = midl_user_allocate(Length); 4807 if (MembersBuffer->Members == NULL) 4808 { 4809 Status = STATUS_INSUFFICIENT_RESOURCES; 4810 goto done; 4811 } 4812 4813 MembersBuffer->Attributes = midl_user_allocate(Length); 4814 if (MembersBuffer->Attributes == NULL) 4815 { 4816 Status = STATUS_INSUFFICIENT_RESOURCES; 4817 goto done; 4818 } 4819 4820 Status = SampGetObjectAttribute(GroupObject, 4821 L"Members", 4822 NULL, 4823 MembersBuffer->Members, 4824 &Length); 4825 if (!NT_SUCCESS(Status)) 4826 { 4827 TRACE("SampGetObjectAttributes() failed (Status 0x%08lx)\n", Status); 4828 goto done; 4829 } 4830 4831 MembersBuffer->MemberCount = Length / sizeof(ULONG); 4832 4833 for (i = 0; i < MembersBuffer->MemberCount; i++) 4834 { 4835 Status = SampGetUserGroupAttributes(GroupObject->ParentObject, 4836 MembersBuffer->Members[i], 4837 GroupObject->RelativeId, 4838 &(MembersBuffer->Attributes[i])); 4839 if (!NT_SUCCESS(Status)) 4840 { 4841 TRACE("SampGetUserGroupAttributes() failed (Status 0x%08lx)\n", Status); 4842 goto done; 4843 } 4844 } 4845 4846 *Members = MembersBuffer; 4847 4848 done: 4849 if (!NT_SUCCESS(Status)) 4850 { 4851 if (MembersBuffer != NULL) 4852 { 4853 if (MembersBuffer->Members != NULL) 4854 midl_user_free(MembersBuffer->Members); 4855 4856 if (MembersBuffer->Attributes != NULL) 4857 midl_user_free(MembersBuffer->Attributes); 4858 4859 midl_user_free(MembersBuffer); 4860 } 4861 } 4862 4863 RtlReleaseResource(&SampResource); 4864 4865 return Status; 4866 } 4867 4868 4869 /* Function 26 */ 4870 NTSTATUS 4871 NTAPI 4872 SamrSetMemberAttributesOfGroup(IN SAMPR_HANDLE GroupHandle, 4873 IN unsigned long MemberId, 4874 IN unsigned long Attributes) 4875 { 4876 PSAM_DB_OBJECT GroupObject; 4877 NTSTATUS Status; 4878 4879 TRACE("SamrSetMemberAttributesOfGroup(%p %lu %lx)\n", 4880 GroupHandle, MemberId, Attributes); 4881 4882 RtlAcquireResourceExclusive(&SampResource, 4883 TRUE); 4884 4885 /* Validate the group handle */ 4886 Status = SampValidateDbObject(GroupHandle, 4887 SamDbGroupObject, 4888 GROUP_ADD_MEMBER, 4889 &GroupObject); 4890 if (!NT_SUCCESS(Status)) 4891 { 4892 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 4893 goto done; 4894 } 4895 4896 Status = SampSetUserGroupAttributes(GroupObject->ParentObject, 4897 MemberId, 4898 GroupObject->RelativeId, 4899 Attributes); 4900 if (!NT_SUCCESS(Status)) 4901 { 4902 TRACE("SampSetUserGroupAttributes failed with status 0x%08lx\n", Status); 4903 } 4904 4905 done: 4906 RtlReleaseResource(&SampResource); 4907 4908 return Status; 4909 } 4910 4911 4912 /* Function 27 */ 4913 NTSTATUS 4914 NTAPI 4915 SamrOpenAlias(IN SAMPR_HANDLE DomainHandle, 4916 IN ACCESS_MASK DesiredAccess, 4917 IN ULONG AliasId, 4918 OUT SAMPR_HANDLE *AliasHandle) 4919 { 4920 PSAM_DB_OBJECT DomainObject; 4921 PSAM_DB_OBJECT AliasObject; 4922 WCHAR szRid[9]; 4923 NTSTATUS Status; 4924 4925 TRACE("SamrOpenAlias(%p %lx %lx %p)\n", 4926 DomainHandle, DesiredAccess, AliasId, AliasHandle); 4927 4928 /* Map generic access rights */ 4929 RtlMapGenericMask(&DesiredAccess, 4930 &AliasMapping); 4931 4932 RtlAcquireResourceShared(&SampResource, 4933 TRUE); 4934 4935 /* Validate the domain handle */ 4936 Status = SampValidateDbObject(DomainHandle, 4937 SamDbDomainObject, 4938 DOMAIN_LOOKUP, 4939 &DomainObject); 4940 if (!NT_SUCCESS(Status)) 4941 { 4942 TRACE("failed with status 0x%08lx\n", Status); 4943 goto done; 4944 } 4945 4946 /* Convert the RID into a string (hex) */ 4947 swprintf(szRid, L"%08lX", AliasId); 4948 4949 /* Create the alias object */ 4950 Status = SampOpenDbObject(DomainObject, 4951 L"Aliases", 4952 szRid, 4953 AliasId, 4954 SamDbAliasObject, 4955 DesiredAccess, 4956 &AliasObject); 4957 if (!NT_SUCCESS(Status)) 4958 { 4959 TRACE("failed with status 0x%08lx\n", Status); 4960 goto done; 4961 } 4962 4963 *AliasHandle = (SAMPR_HANDLE)AliasObject; 4964 4965 done: 4966 RtlReleaseResource(&SampResource); 4967 4968 return Status; 4969 } 4970 4971 4972 static NTSTATUS 4973 SampQueryAliasGeneral(PSAM_DB_OBJECT AliasObject, 4974 PSAMPR_ALIAS_INFO_BUFFER *Buffer) 4975 { 4976 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL; 4977 HANDLE MembersKeyHandle = NULL; 4978 NTSTATUS Status; 4979 4980 *Buffer = NULL; 4981 4982 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER)); 4983 if (InfoBuffer == NULL) 4984 return STATUS_INSUFFICIENT_RESOURCES; 4985 4986 Status = SampGetObjectAttributeString(AliasObject, 4987 L"Name", 4988 &InfoBuffer->General.Name); 4989 if (!NT_SUCCESS(Status)) 4990 { 4991 TRACE("Status 0x%08lx\n", Status); 4992 goto done; 4993 } 4994 4995 Status = SampGetObjectAttributeString(AliasObject, 4996 L"Description", 4997 &InfoBuffer->General.AdminComment); 4998 if (!NT_SUCCESS(Status)) 4999 { 5000 TRACE("Status 0x%08lx\n", Status); 5001 goto done; 5002 } 5003 5004 /* Open the Members subkey */ 5005 Status = SampRegOpenKey(AliasObject->KeyHandle, 5006 L"Members", 5007 KEY_READ, 5008 &MembersKeyHandle); 5009 if (NT_SUCCESS(Status)) 5010 { 5011 /* Retrieve the number of members of the alias */ 5012 Status = SampRegQueryKeyInfo(MembersKeyHandle, 5013 NULL, 5014 &InfoBuffer->General.MemberCount); 5015 if (!NT_SUCCESS(Status)) 5016 { 5017 TRACE("Status 0x%08lx\n", Status); 5018 goto done; 5019 } 5020 } 5021 else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 5022 { 5023 InfoBuffer->General.MemberCount = 0; 5024 Status = STATUS_SUCCESS; 5025 } 5026 else 5027 { 5028 TRACE("Status 0x%08lx\n", Status); 5029 goto done; 5030 } 5031 5032 *Buffer = InfoBuffer; 5033 5034 done: 5035 SampRegCloseKey(&MembersKeyHandle); 5036 5037 if (!NT_SUCCESS(Status)) 5038 { 5039 if (InfoBuffer != NULL) 5040 { 5041 if (InfoBuffer->General.Name.Buffer != NULL) 5042 midl_user_free(InfoBuffer->General.Name.Buffer); 5043 5044 if (InfoBuffer->General.AdminComment.Buffer != NULL) 5045 midl_user_free(InfoBuffer->General.AdminComment.Buffer); 5046 5047 midl_user_free(InfoBuffer); 5048 } 5049 } 5050 5051 return Status; 5052 } 5053 5054 5055 static NTSTATUS 5056 SampQueryAliasName(PSAM_DB_OBJECT AliasObject, 5057 PSAMPR_ALIAS_INFO_BUFFER *Buffer) 5058 { 5059 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL; 5060 NTSTATUS Status; 5061 5062 *Buffer = NULL; 5063 5064 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER)); 5065 if (InfoBuffer == NULL) 5066 return STATUS_INSUFFICIENT_RESOURCES; 5067 5068 Status = SampGetObjectAttributeString(AliasObject, 5069 L"Name", 5070 &InfoBuffer->Name.Name); 5071 if (!NT_SUCCESS(Status)) 5072 { 5073 TRACE("Status 0x%08lx\n", Status); 5074 goto done; 5075 } 5076 5077 *Buffer = InfoBuffer; 5078 5079 done: 5080 if (!NT_SUCCESS(Status)) 5081 { 5082 if (InfoBuffer != NULL) 5083 { 5084 if (InfoBuffer->Name.Name.Buffer != NULL) 5085 midl_user_free(InfoBuffer->Name.Name.Buffer); 5086 5087 midl_user_free(InfoBuffer); 5088 } 5089 } 5090 5091 return Status; 5092 } 5093 5094 5095 static NTSTATUS 5096 SampQueryAliasAdminComment(PSAM_DB_OBJECT AliasObject, 5097 PSAMPR_ALIAS_INFO_BUFFER *Buffer) 5098 { 5099 PSAMPR_ALIAS_INFO_BUFFER InfoBuffer = NULL; 5100 NTSTATUS Status; 5101 5102 *Buffer = NULL; 5103 5104 InfoBuffer = midl_user_allocate(sizeof(SAMPR_ALIAS_INFO_BUFFER)); 5105 if (InfoBuffer == NULL) 5106 return STATUS_INSUFFICIENT_RESOURCES; 5107 5108 Status = SampGetObjectAttributeString(AliasObject, 5109 L"Description", 5110 &InfoBuffer->AdminComment.AdminComment); 5111 if (!NT_SUCCESS(Status)) 5112 { 5113 TRACE("Status 0x%08lx\n", Status); 5114 goto done; 5115 } 5116 5117 *Buffer = InfoBuffer; 5118 5119 done: 5120 if (!NT_SUCCESS(Status)) 5121 { 5122 if (InfoBuffer != NULL) 5123 { 5124 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL) 5125 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer); 5126 5127 midl_user_free(InfoBuffer); 5128 } 5129 } 5130 5131 return Status; 5132 } 5133 5134 5135 /* Function 28 */ 5136 NTSTATUS 5137 NTAPI 5138 SamrQueryInformationAlias(IN SAMPR_HANDLE AliasHandle, 5139 IN ALIAS_INFORMATION_CLASS AliasInformationClass, 5140 OUT PSAMPR_ALIAS_INFO_BUFFER *Buffer) 5141 { 5142 PSAM_DB_OBJECT AliasObject; 5143 NTSTATUS Status; 5144 5145 TRACE("SamrQueryInformationAlias(%p %lu %p)\n", 5146 AliasHandle, AliasInformationClass, Buffer); 5147 5148 RtlAcquireResourceShared(&SampResource, 5149 TRUE); 5150 5151 /* Validate the alias handle */ 5152 Status = SampValidateDbObject(AliasHandle, 5153 SamDbAliasObject, 5154 ALIAS_READ_INFORMATION, 5155 &AliasObject); 5156 if (!NT_SUCCESS(Status)) 5157 goto done; 5158 5159 switch (AliasInformationClass) 5160 { 5161 case AliasGeneralInformation: 5162 Status = SampQueryAliasGeneral(AliasObject, 5163 Buffer); 5164 break; 5165 5166 case AliasNameInformation: 5167 Status = SampQueryAliasName(AliasObject, 5168 Buffer); 5169 break; 5170 5171 case AliasAdminCommentInformation: 5172 Status = SampQueryAliasAdminComment(AliasObject, 5173 Buffer); 5174 break; 5175 5176 default: 5177 Status = STATUS_INVALID_INFO_CLASS; 5178 break; 5179 } 5180 5181 done: 5182 RtlReleaseResource(&SampResource); 5183 5184 return Status; 5185 } 5186 5187 5188 static NTSTATUS 5189 SampSetAliasName(PSAM_DB_OBJECT AliasObject, 5190 PSAMPR_ALIAS_INFO_BUFFER Buffer) 5191 { 5192 UNICODE_STRING OldAliasName = {0, 0, NULL}; 5193 UNICODE_STRING NewAliasName; 5194 NTSTATUS Status; 5195 5196 Status = SampGetObjectAttributeString(AliasObject, 5197 L"Name", 5198 (PRPC_UNICODE_STRING)&OldAliasName); 5199 if (!NT_SUCCESS(Status)) 5200 { 5201 TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status); 5202 goto done; 5203 } 5204 5205 /* Check the new account name */ 5206 Status = SampCheckAccountName(&Buffer->Name.Name, 256); 5207 if (!NT_SUCCESS(Status)) 5208 { 5209 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 5210 return Status; 5211 } 5212 5213 NewAliasName.Length = Buffer->Name.Name.Length; 5214 NewAliasName.MaximumLength = Buffer->Name.Name.MaximumLength; 5215 NewAliasName.Buffer = Buffer->Name.Name.Buffer; 5216 5217 if (!RtlEqualUnicodeString(&OldAliasName, &NewAliasName, TRUE)) 5218 { 5219 Status = SampCheckAccountNameInDomain(AliasObject->ParentObject, 5220 NewAliasName.Buffer); 5221 if (!NT_SUCCESS(Status)) 5222 { 5223 TRACE("Alias name \'%S\' already exists in domain (Status 0x%08lx)\n", 5224 NewAliasName.Buffer, Status); 5225 goto done; 5226 } 5227 } 5228 5229 Status = SampSetAccountNameInDomain(AliasObject->ParentObject, 5230 L"Aliases", 5231 NewAliasName.Buffer, 5232 AliasObject->RelativeId); 5233 if (!NT_SUCCESS(Status)) 5234 { 5235 TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status); 5236 goto done; 5237 } 5238 5239 Status = SampRemoveAccountNameFromDomain(AliasObject->ParentObject, 5240 L"Aliases", 5241 OldAliasName.Buffer); 5242 if (!NT_SUCCESS(Status)) 5243 { 5244 TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status); 5245 goto done; 5246 } 5247 5248 Status = SampSetObjectAttributeString(AliasObject, 5249 L"Name", 5250 (PRPC_UNICODE_STRING)&NewAliasName); 5251 if (!NT_SUCCESS(Status)) 5252 { 5253 TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status); 5254 } 5255 5256 done: 5257 if (OldAliasName.Buffer != NULL) 5258 midl_user_free(OldAliasName.Buffer); 5259 5260 return Status; 5261 } 5262 5263 5264 /* Function 29 */ 5265 NTSTATUS 5266 NTAPI 5267 SamrSetInformationAlias(IN SAMPR_HANDLE AliasHandle, 5268 IN ALIAS_INFORMATION_CLASS AliasInformationClass, 5269 IN PSAMPR_ALIAS_INFO_BUFFER Buffer) 5270 { 5271 PSAM_DB_OBJECT AliasObject; 5272 NTSTATUS Status; 5273 5274 TRACE("SamrSetInformationAlias(%p %lu %p)\n", 5275 AliasHandle, AliasInformationClass, Buffer); 5276 5277 RtlAcquireResourceExclusive(&SampResource, 5278 TRUE); 5279 5280 /* Validate the alias handle */ 5281 Status = SampValidateDbObject(AliasHandle, 5282 SamDbAliasObject, 5283 ALIAS_WRITE_ACCOUNT, 5284 &AliasObject); 5285 if (!NT_SUCCESS(Status)) 5286 goto done; 5287 5288 switch (AliasInformationClass) 5289 { 5290 case AliasNameInformation: 5291 Status = SampSetAliasName(AliasObject, 5292 Buffer); 5293 break; 5294 5295 case AliasAdminCommentInformation: 5296 Status = SampSetObjectAttributeString(AliasObject, 5297 L"Description", 5298 &Buffer->AdminComment.AdminComment); 5299 break; 5300 5301 default: 5302 Status = STATUS_INVALID_INFO_CLASS; 5303 break; 5304 } 5305 5306 done: 5307 RtlReleaseResource(&SampResource); 5308 5309 return Status; 5310 } 5311 5312 5313 /* Function 30 */ 5314 NTSTATUS 5315 NTAPI 5316 SamrDeleteAlias(IN OUT SAMPR_HANDLE *AliasHandle) 5317 { 5318 PSAM_DB_OBJECT AliasObject; 5319 NTSTATUS Status; 5320 5321 TRACE("SamrDeleteAlias(%p)\n", AliasHandle); 5322 5323 RtlAcquireResourceExclusive(&SampResource, 5324 TRUE); 5325 5326 /* Validate the alias handle */ 5327 Status = SampValidateDbObject(*AliasHandle, 5328 SamDbAliasObject, 5329 DELETE, 5330 &AliasObject); 5331 if (!NT_SUCCESS(Status)) 5332 { 5333 TRACE("SampValidateDbObject failed (Status 0x%08lx)\n", Status); 5334 goto done; 5335 } 5336 5337 /* Fail, if the alias is built-in */ 5338 if (AliasObject->RelativeId < 1000) 5339 { 5340 TRACE("You can not delete a special account!\n"); 5341 Status = STATUS_SPECIAL_ACCOUNT; 5342 goto done; 5343 } 5344 5345 /* Remove all members from the alias */ 5346 Status = SampRemoveAllMembersFromAlias(AliasObject); 5347 if (!NT_SUCCESS(Status)) 5348 { 5349 TRACE("SampRemoveAllMembersFromAlias() failed (Status 0x%08lx)\n", Status); 5350 goto done; 5351 } 5352 5353 /* Delete the alias from the database */ 5354 Status = SampDeleteAccountDbObject(AliasObject); 5355 if (!NT_SUCCESS(Status)) 5356 { 5357 TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status); 5358 goto done; 5359 } 5360 5361 /* Invalidate the handle */ 5362 *AliasHandle = NULL; 5363 5364 done: 5365 RtlReleaseResource(&SampResource); 5366 5367 return Status; 5368 } 5369 5370 5371 /* Function 31 */ 5372 NTSTATUS 5373 NTAPI 5374 SamrAddMemberToAlias(IN SAMPR_HANDLE AliasHandle, 5375 IN PRPC_SID MemberId) 5376 { 5377 PSAM_DB_OBJECT AliasObject; 5378 NTSTATUS Status; 5379 5380 TRACE("SamrAddMemberToAlias(%p %p)\n", 5381 AliasHandle, MemberId); 5382 5383 RtlAcquireResourceExclusive(&SampResource, 5384 TRUE); 5385 5386 /* Validate the alias handle */ 5387 Status = SampValidateDbObject(AliasHandle, 5388 SamDbAliasObject, 5389 ALIAS_ADD_MEMBER, 5390 &AliasObject); 5391 if (!NT_SUCCESS(Status)) 5392 { 5393 TRACE("failed with status 0x%08lx\n", Status); 5394 goto done; 5395 } 5396 5397 Status = SampAddMemberToAlias(AliasObject, 5398 MemberId); 5399 if (!NT_SUCCESS(Status)) 5400 { 5401 TRACE("failed with status 0x%08lx\n", Status); 5402 } 5403 5404 done: 5405 RtlReleaseResource(&SampResource); 5406 5407 return Status; 5408 } 5409 5410 5411 /* Function 32 */ 5412 NTSTATUS 5413 NTAPI 5414 SamrRemoveMemberFromAlias(IN SAMPR_HANDLE AliasHandle, 5415 IN PRPC_SID MemberId) 5416 { 5417 PSAM_DB_OBJECT AliasObject; 5418 NTSTATUS Status; 5419 5420 TRACE("SamrRemoveMemberFromAlias(%p %p)\n", 5421 AliasHandle, MemberId); 5422 5423 RtlAcquireResourceExclusive(&SampResource, 5424 TRUE); 5425 5426 /* Validate the alias handle */ 5427 Status = SampValidateDbObject(AliasHandle, 5428 SamDbAliasObject, 5429 ALIAS_REMOVE_MEMBER, 5430 &AliasObject); 5431 if (!NT_SUCCESS(Status)) 5432 { 5433 TRACE("failed with status 0x%08lx\n", Status); 5434 goto done; 5435 } 5436 5437 Status = SampRemoveMemberFromAlias(AliasObject, 5438 MemberId); 5439 if (!NT_SUCCESS(Status)) 5440 { 5441 TRACE("failed with status 0x%08lx\n", Status); 5442 } 5443 5444 done: 5445 RtlReleaseResource(&SampResource); 5446 5447 return Status; 5448 } 5449 5450 5451 /* Function 33 */ 5452 NTSTATUS 5453 NTAPI 5454 SamrGetMembersInAlias(IN SAMPR_HANDLE AliasHandle, 5455 OUT PSAMPR_PSID_ARRAY_OUT Members) 5456 { 5457 PSAM_DB_OBJECT AliasObject; 5458 PSAMPR_SID_INFORMATION MemberArray = NULL; 5459 ULONG MemberCount = 0; 5460 ULONG Index; 5461 NTSTATUS Status; 5462 5463 TRACE("SamrGetMembersInAlias(%p %p %p)\n", 5464 AliasHandle, Members); 5465 5466 RtlAcquireResourceShared(&SampResource, 5467 TRUE); 5468 5469 /* Validate the alias handle */ 5470 Status = SampValidateDbObject(AliasHandle, 5471 SamDbAliasObject, 5472 ALIAS_LIST_MEMBERS, 5473 &AliasObject); 5474 if (!NT_SUCCESS(Status)) 5475 { 5476 ERR("failed with status 0x%08lx\n", Status); 5477 goto done; 5478 } 5479 5480 Status = SampGetMembersInAlias(AliasObject, 5481 &MemberCount, 5482 &MemberArray); 5483 5484 /* Return the number of members and the member array */ 5485 if (NT_SUCCESS(Status)) 5486 { 5487 Members->Count = MemberCount; 5488 Members->Sids = MemberArray; 5489 } 5490 5491 done: 5492 /* Clean up the members array and the SID buffers if something failed */ 5493 if (!NT_SUCCESS(Status)) 5494 { 5495 if (MemberArray != NULL) 5496 { 5497 for (Index = 0; Index < MemberCount; Index++) 5498 { 5499 if (MemberArray[Index].SidPointer != NULL) 5500 midl_user_free(MemberArray[Index].SidPointer); 5501 } 5502 5503 midl_user_free(MemberArray); 5504 } 5505 } 5506 5507 RtlReleaseResource(&SampResource); 5508 5509 return Status; 5510 } 5511 5512 5513 /* Function 34 */ 5514 NTSTATUS 5515 NTAPI 5516 SamrOpenUser(IN SAMPR_HANDLE DomainHandle, 5517 IN ACCESS_MASK DesiredAccess, 5518 IN unsigned long UserId, 5519 OUT SAMPR_HANDLE *UserHandle) 5520 { 5521 PSAM_DB_OBJECT DomainObject; 5522 PSAM_DB_OBJECT UserObject; 5523 WCHAR szRid[9]; 5524 NTSTATUS Status; 5525 5526 TRACE("SamrOpenUser(%p %lx %lx %p)\n", 5527 DomainHandle, DesiredAccess, UserId, UserHandle); 5528 5529 /* Map generic access rights */ 5530 RtlMapGenericMask(&DesiredAccess, 5531 &UserMapping); 5532 5533 RtlAcquireResourceShared(&SampResource, 5534 TRUE); 5535 5536 /* Validate the domain handle */ 5537 Status = SampValidateDbObject(DomainHandle, 5538 SamDbDomainObject, 5539 DOMAIN_LOOKUP, 5540 &DomainObject); 5541 if (!NT_SUCCESS(Status)) 5542 { 5543 TRACE("failed with status 0x%08lx\n", Status); 5544 goto done; 5545 } 5546 5547 /* Convert the RID into a string (hex) */ 5548 swprintf(szRid, L"%08lX", UserId); 5549 5550 /* Create the user object */ 5551 Status = SampOpenDbObject(DomainObject, 5552 L"Users", 5553 szRid, 5554 UserId, 5555 SamDbUserObject, 5556 DesiredAccess, 5557 &UserObject); 5558 if (!NT_SUCCESS(Status)) 5559 { 5560 TRACE("failed with status 0x%08lx\n", Status); 5561 goto done; 5562 } 5563 5564 *UserHandle = (SAMPR_HANDLE)UserObject; 5565 5566 done: 5567 RtlReleaseResource(&SampResource); 5568 5569 return Status; 5570 } 5571 5572 5573 /* Function 35 */ 5574 NTSTATUS 5575 NTAPI 5576 SamrDeleteUser(IN OUT SAMPR_HANDLE *UserHandle) 5577 { 5578 PSAM_DB_OBJECT UserObject; 5579 NTSTATUS Status; 5580 5581 TRACE("SamrDeleteUser(%p)\n", UserHandle); 5582 5583 RtlAcquireResourceExclusive(&SampResource, 5584 TRUE); 5585 5586 /* Validate the user handle */ 5587 Status = SampValidateDbObject(*UserHandle, 5588 SamDbUserObject, 5589 DELETE, 5590 &UserObject); 5591 if (!NT_SUCCESS(Status)) 5592 { 5593 TRACE("SampValidateDbObject() failed (Status 0x%08lx)\n", Status); 5594 goto done; 5595 } 5596 5597 /* Fail, if the user is built-in */ 5598 if (UserObject->RelativeId < 1000) 5599 { 5600 TRACE("You can not delete a special account!\n"); 5601 Status = STATUS_SPECIAL_ACCOUNT; 5602 goto done; 5603 } 5604 5605 /* Remove the user from all groups */ 5606 Status = SampRemoveUserFromAllGroups(UserObject); 5607 if (!NT_SUCCESS(Status)) 5608 { 5609 TRACE("SampRemoveUserFromAllGroups() failed (Status 0x%08lx)\n", Status); 5610 goto done; 5611 } 5612 5613 /* Remove the user from all aliases */ 5614 Status = SampRemoveUserFromAllAliases(UserObject); 5615 if (!NT_SUCCESS(Status)) 5616 { 5617 TRACE("SampRemoveUserFromAllAliases() failed (Status 0x%08lx)\n", Status); 5618 goto done; 5619 } 5620 5621 /* Delete the user from the database */ 5622 Status = SampDeleteAccountDbObject(UserObject); 5623 if (!NT_SUCCESS(Status)) 5624 { 5625 TRACE("SampDeleteAccountDbObject() failed (Status 0x%08lx)\n", Status); 5626 goto done; 5627 } 5628 5629 /* Invalidate the handle */ 5630 *UserHandle = NULL; 5631 5632 done: 5633 RtlReleaseResource(&SampResource); 5634 5635 return Status; 5636 } 5637 5638 5639 static 5640 NTSTATUS 5641 SampQueryUserGeneral(PSAM_DB_OBJECT UserObject, 5642 PSAMPR_USER_INFO_BUFFER *Buffer) 5643 { 5644 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 5645 SAM_USER_FIXED_DATA FixedData; 5646 ULONG Length = 0; 5647 NTSTATUS Status; 5648 5649 *Buffer = NULL; 5650 5651 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 5652 if (InfoBuffer == NULL) 5653 return STATUS_INSUFFICIENT_RESOURCES; 5654 5655 Length = sizeof(SAM_USER_FIXED_DATA); 5656 Status = SampGetObjectAttribute(UserObject, 5657 L"F", 5658 NULL, 5659 (PVOID)&FixedData, 5660 &Length); 5661 if (!NT_SUCCESS(Status)) 5662 goto done; 5663 5664 InfoBuffer->General.PrimaryGroupId = FixedData.PrimaryGroupId; 5665 5666 /* Get the Name string */ 5667 Status = SampGetObjectAttributeString(UserObject, 5668 L"Name", 5669 &InfoBuffer->General.UserName); 5670 if (!NT_SUCCESS(Status)) 5671 { 5672 TRACE("Status 0x%08lx\n", Status); 5673 goto done; 5674 } 5675 5676 /* Get the FullName string */ 5677 Status = SampGetObjectAttributeString(UserObject, 5678 L"FullName", 5679 &InfoBuffer->General.FullName); 5680 if (!NT_SUCCESS(Status)) 5681 { 5682 TRACE("Status 0x%08lx\n", Status); 5683 goto done; 5684 } 5685 5686 /* Get the AdminComment string */ 5687 Status = SampGetObjectAttributeString(UserObject, 5688 L"AdminComment", 5689 &InfoBuffer->General.AdminComment); 5690 if (!NT_SUCCESS(Status)) 5691 { 5692 TRACE("Status 0x%08lx\n", Status); 5693 goto done; 5694 } 5695 5696 /* Get the UserComment string */ 5697 Status = SampGetObjectAttributeString(UserObject, 5698 L"UserComment", 5699 &InfoBuffer->General.UserComment); 5700 if (!NT_SUCCESS(Status)) 5701 { 5702 TRACE("Status 0x%08lx\n", Status); 5703 goto done; 5704 } 5705 5706 *Buffer = InfoBuffer; 5707 5708 done: 5709 if (!NT_SUCCESS(Status)) 5710 { 5711 if (InfoBuffer != NULL) 5712 { 5713 if (InfoBuffer->General.UserName.Buffer != NULL) 5714 midl_user_free(InfoBuffer->General.UserName.Buffer); 5715 5716 if (InfoBuffer->General.FullName.Buffer != NULL) 5717 midl_user_free(InfoBuffer->General.FullName.Buffer); 5718 5719 if (InfoBuffer->General.AdminComment.Buffer != NULL) 5720 midl_user_free(InfoBuffer->General.AdminComment.Buffer); 5721 5722 if (InfoBuffer->General.UserComment.Buffer != NULL) 5723 midl_user_free(InfoBuffer->General.UserComment.Buffer); 5724 5725 midl_user_free(InfoBuffer); 5726 } 5727 } 5728 5729 return Status; 5730 } 5731 5732 5733 static 5734 NTSTATUS 5735 SampQueryUserPreferences(PSAM_DB_OBJECT UserObject, 5736 PSAMPR_USER_INFO_BUFFER *Buffer) 5737 { 5738 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 5739 SAM_USER_FIXED_DATA FixedData; 5740 ULONG Length = 0; 5741 NTSTATUS Status; 5742 5743 *Buffer = NULL; 5744 5745 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 5746 if (InfoBuffer == NULL) 5747 return STATUS_INSUFFICIENT_RESOURCES; 5748 5749 Length = sizeof(SAM_USER_FIXED_DATA); 5750 Status = SampGetObjectAttribute(UserObject, 5751 L"F", 5752 NULL, 5753 (PVOID)&FixedData, 5754 &Length); 5755 if (!NT_SUCCESS(Status)) 5756 goto done; 5757 5758 InfoBuffer->Preferences.CountryCode = FixedData.CountryCode; 5759 InfoBuffer->Preferences.CodePage = FixedData.CodePage; 5760 5761 /* Get the UserComment string */ 5762 Status = SampGetObjectAttributeString(UserObject, 5763 L"UserComment", 5764 &InfoBuffer->Preferences.UserComment); 5765 if (!NT_SUCCESS(Status)) 5766 { 5767 TRACE("Status 0x%08lx\n", Status); 5768 goto done; 5769 } 5770 5771 *Buffer = InfoBuffer; 5772 5773 done: 5774 if (!NT_SUCCESS(Status)) 5775 { 5776 if (InfoBuffer != NULL) 5777 { 5778 if (InfoBuffer->Preferences.UserComment.Buffer != NULL) 5779 midl_user_free(InfoBuffer->Preferences.UserComment.Buffer); 5780 5781 midl_user_free(InfoBuffer); 5782 } 5783 } 5784 5785 return Status; 5786 } 5787 5788 5789 static 5790 NTSTATUS 5791 SampQueryUserLogon(PSAM_DB_OBJECT UserObject, 5792 PSAMPR_USER_INFO_BUFFER *Buffer) 5793 { 5794 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 5795 SAM_DOMAIN_FIXED_DATA DomainFixedData; 5796 SAM_USER_FIXED_DATA FixedData; 5797 LARGE_INTEGER PasswordCanChange; 5798 LARGE_INTEGER PasswordMustChange; 5799 ULONG Length = 0; 5800 NTSTATUS Status; 5801 5802 *Buffer = NULL; 5803 5804 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 5805 if (InfoBuffer == NULL) 5806 return STATUS_INSUFFICIENT_RESOURCES; 5807 5808 /* Get the fixed size domain data */ 5809 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 5810 Status = SampGetObjectAttribute(UserObject->ParentObject, 5811 L"F", 5812 NULL, 5813 (PVOID)&DomainFixedData, 5814 &Length); 5815 if (!NT_SUCCESS(Status)) 5816 goto done; 5817 5818 /* Get the fixed size user data */ 5819 Length = sizeof(SAM_USER_FIXED_DATA); 5820 Status = SampGetObjectAttribute(UserObject, 5821 L"F", 5822 NULL, 5823 (PVOID)&FixedData, 5824 &Length); 5825 if (!NT_SUCCESS(Status)) 5826 goto done; 5827 5828 InfoBuffer->Logon.UserId = FixedData.UserId; 5829 InfoBuffer->Logon.PrimaryGroupId = FixedData.PrimaryGroupId; 5830 InfoBuffer->Logon.LastLogon.LowPart = FixedData.LastLogon.LowPart; 5831 InfoBuffer->Logon.LastLogon.HighPart = FixedData.LastLogon.HighPart; 5832 InfoBuffer->Logon.LastLogoff.LowPart = FixedData.LastLogoff.LowPart; 5833 InfoBuffer->Logon.LastLogoff.HighPart = FixedData.LastLogoff.HighPart; 5834 InfoBuffer->Logon.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart; 5835 InfoBuffer->Logon.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart; 5836 InfoBuffer->Logon.BadPasswordCount = FixedData.BadPasswordCount; 5837 InfoBuffer->Logon.LogonCount = FixedData.LogonCount; 5838 InfoBuffer->Logon.UserAccountControl = FixedData.UserAccountControl; 5839 5840 PasswordCanChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet, 5841 DomainFixedData.MinPasswordAge); 5842 InfoBuffer->Logon.PasswordCanChange.LowPart = PasswordCanChange.LowPart; 5843 InfoBuffer->Logon.PasswordCanChange.HighPart = PasswordCanChange.HighPart; 5844 5845 PasswordMustChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet, 5846 DomainFixedData.MaxPasswordAge); 5847 InfoBuffer->Logon.PasswordMustChange.LowPart = PasswordMustChange.LowPart; 5848 InfoBuffer->Logon.PasswordMustChange.HighPart = PasswordMustChange.HighPart; 5849 5850 /* Get the Name string */ 5851 Status = SampGetObjectAttributeString(UserObject, 5852 L"Name", 5853 &InfoBuffer->Logon.UserName); 5854 if (!NT_SUCCESS(Status)) 5855 { 5856 TRACE("Status 0x%08lx\n", Status); 5857 goto done; 5858 } 5859 5860 /* Get the FullName string */ 5861 Status = SampGetObjectAttributeString(UserObject, 5862 L"FullName", 5863 &InfoBuffer->Logon.FullName); 5864 if (!NT_SUCCESS(Status)) 5865 { 5866 TRACE("Status 0x%08lx\n", Status); 5867 goto done; 5868 } 5869 5870 /* Get the HomeDirectory string */ 5871 Status = SampGetObjectAttributeString(UserObject, 5872 L"HomeDirectory", 5873 &InfoBuffer->Logon.HomeDirectory); 5874 if (!NT_SUCCESS(Status)) 5875 { 5876 TRACE("Status 0x%08lx\n", Status); 5877 goto done; 5878 } 5879 5880 /* Get the HomeDirectoryDrive string */ 5881 Status = SampGetObjectAttributeString(UserObject, 5882 L"HomeDirectoryDrive", 5883 &InfoBuffer->Logon.HomeDirectoryDrive); 5884 if (!NT_SUCCESS(Status)) 5885 { 5886 TRACE("Status 0x%08lx\n", Status); 5887 goto done; 5888 } 5889 5890 /* Get the ScriptPath string */ 5891 Status = SampGetObjectAttributeString(UserObject, 5892 L"ScriptPath", 5893 &InfoBuffer->Logon.ScriptPath); 5894 if (!NT_SUCCESS(Status)) 5895 { 5896 TRACE("Status 0x%08lx\n", Status); 5897 goto done; 5898 } 5899 5900 /* Get the ProfilePath string */ 5901 Status = SampGetObjectAttributeString(UserObject, 5902 L"ProfilePath", 5903 &InfoBuffer->Logon.ProfilePath); 5904 if (!NT_SUCCESS(Status)) 5905 { 5906 TRACE("Status 0x%08lx\n", Status); 5907 goto done; 5908 } 5909 5910 /* Get the WorkStations string */ 5911 Status = SampGetObjectAttributeString(UserObject, 5912 L"WorkStations", 5913 &InfoBuffer->Logon.WorkStations); 5914 if (!NT_SUCCESS(Status)) 5915 { 5916 TRACE("Status 0x%08lx\n", Status); 5917 goto done; 5918 } 5919 5920 /* Get the LogonHours attribute */ 5921 Status = SampGetLogonHoursAttribute(UserObject, 5922 &InfoBuffer->Logon.LogonHours); 5923 if (!NT_SUCCESS(Status)) 5924 { 5925 TRACE("Status 0x%08lx\n", Status); 5926 goto done; 5927 } 5928 5929 *Buffer = InfoBuffer; 5930 5931 done: 5932 if (!NT_SUCCESS(Status)) 5933 { 5934 if (InfoBuffer != NULL) 5935 { 5936 if (InfoBuffer->Logon.UserName.Buffer != NULL) 5937 midl_user_free(InfoBuffer->Logon.UserName.Buffer); 5938 5939 if (InfoBuffer->Logon.FullName.Buffer != NULL) 5940 midl_user_free(InfoBuffer->Logon.FullName.Buffer); 5941 5942 if (InfoBuffer->Logon.HomeDirectory.Buffer != NULL) 5943 midl_user_free(InfoBuffer->Logon.HomeDirectory.Buffer); 5944 5945 if (InfoBuffer->Logon.HomeDirectoryDrive.Buffer != NULL) 5946 midl_user_free(InfoBuffer->Logon.HomeDirectoryDrive.Buffer); 5947 5948 if (InfoBuffer->Logon.ScriptPath.Buffer != NULL) 5949 midl_user_free(InfoBuffer->Logon.ScriptPath.Buffer); 5950 5951 if (InfoBuffer->Logon.ProfilePath.Buffer != NULL) 5952 midl_user_free(InfoBuffer->Logon.ProfilePath.Buffer); 5953 5954 if (InfoBuffer->Logon.WorkStations.Buffer != NULL) 5955 midl_user_free(InfoBuffer->Logon.WorkStations.Buffer); 5956 5957 if (InfoBuffer->Logon.LogonHours.LogonHours != NULL) 5958 midl_user_free(InfoBuffer->Logon.LogonHours.LogonHours); 5959 5960 midl_user_free(InfoBuffer); 5961 } 5962 } 5963 5964 return Status; 5965 } 5966 5967 5968 static 5969 NTSTATUS 5970 SampQueryUserAccount(PSAM_DB_OBJECT UserObject, 5971 PSAMPR_USER_INFO_BUFFER *Buffer) 5972 { 5973 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 5974 SAM_USER_FIXED_DATA FixedData; 5975 ULONG Length = 0; 5976 NTSTATUS Status; 5977 5978 *Buffer = NULL; 5979 5980 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 5981 if (InfoBuffer == NULL) 5982 return STATUS_INSUFFICIENT_RESOURCES; 5983 5984 Length = sizeof(SAM_USER_FIXED_DATA); 5985 Status = SampGetObjectAttribute(UserObject, 5986 L"F", 5987 NULL, 5988 (PVOID)&FixedData, 5989 &Length); 5990 if (!NT_SUCCESS(Status)) 5991 goto done; 5992 5993 InfoBuffer->Account.UserId = FixedData.UserId; 5994 InfoBuffer->Account.PrimaryGroupId = FixedData.PrimaryGroupId; 5995 InfoBuffer->Account.LastLogon.LowPart = FixedData.LastLogon.LowPart; 5996 InfoBuffer->Account.LastLogon.HighPart = FixedData.LastLogon.HighPart; 5997 InfoBuffer->Account.LastLogoff.LowPart = FixedData.LastLogoff.LowPart; 5998 InfoBuffer->Account.LastLogoff.HighPart = FixedData.LastLogoff.HighPart; 5999 InfoBuffer->Account.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart; 6000 InfoBuffer->Account.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart; 6001 InfoBuffer->Account.AccountExpires.LowPart = FixedData.AccountExpires.LowPart; 6002 InfoBuffer->Account.AccountExpires.HighPart = FixedData.AccountExpires.HighPart; 6003 InfoBuffer->Account.BadPasswordCount = FixedData.BadPasswordCount; 6004 InfoBuffer->Account.LogonCount = FixedData.LogonCount; 6005 InfoBuffer->Account.UserAccountControl = FixedData.UserAccountControl; 6006 6007 /* Get the Name string */ 6008 Status = SampGetObjectAttributeString(UserObject, 6009 L"Name", 6010 &InfoBuffer->Account.UserName); 6011 if (!NT_SUCCESS(Status)) 6012 { 6013 TRACE("Status 0x%08lx\n", Status); 6014 goto done; 6015 } 6016 6017 /* Get the FullName string */ 6018 Status = SampGetObjectAttributeString(UserObject, 6019 L"FullName", 6020 &InfoBuffer->Account.FullName); 6021 if (!NT_SUCCESS(Status)) 6022 { 6023 TRACE("Status 0x%08lx\n", Status); 6024 goto done; 6025 } 6026 6027 /* Get the HomeDirectory string */ 6028 Status = SampGetObjectAttributeString(UserObject, 6029 L"HomeDirectory", 6030 &InfoBuffer->Account.HomeDirectory); 6031 if (!NT_SUCCESS(Status)) 6032 { 6033 TRACE("Status 0x%08lx\n", Status); 6034 goto done; 6035 } 6036 6037 /* Get the HomeDirectoryDrive string */ 6038 Status = SampGetObjectAttributeString(UserObject, 6039 L"HomeDirectoryDrive", 6040 &InfoBuffer->Account.HomeDirectoryDrive); 6041 if (!NT_SUCCESS(Status)) 6042 { 6043 TRACE("Status 0x%08lx\n", Status); 6044 goto done; 6045 } 6046 6047 /* Get the ScriptPath string */ 6048 Status = SampGetObjectAttributeString(UserObject, 6049 L"ScriptPath", 6050 &InfoBuffer->Account.ScriptPath); 6051 if (!NT_SUCCESS(Status)) 6052 { 6053 TRACE("Status 0x%08lx\n", Status); 6054 goto done; 6055 } 6056 6057 /* Get the ProfilePath string */ 6058 Status = SampGetObjectAttributeString(UserObject, 6059 L"ProfilePath", 6060 &InfoBuffer->Account.ProfilePath); 6061 if (!NT_SUCCESS(Status)) 6062 { 6063 TRACE("Status 0x%08lx\n", Status); 6064 goto done; 6065 } 6066 6067 /* Get the AdminComment string */ 6068 Status = SampGetObjectAttributeString(UserObject, 6069 L"AdminComment", 6070 &InfoBuffer->Account.AdminComment); 6071 if (!NT_SUCCESS(Status)) 6072 { 6073 TRACE("Status 0x%08lx\n", Status); 6074 goto done; 6075 } 6076 6077 /* Get the WorkStations string */ 6078 Status = SampGetObjectAttributeString(UserObject, 6079 L"WorkStations", 6080 &InfoBuffer->Account.WorkStations); 6081 if (!NT_SUCCESS(Status)) 6082 { 6083 TRACE("Status 0x%08lx\n", Status); 6084 goto done; 6085 } 6086 6087 /* Get the LogonHours attribute */ 6088 Status = SampGetLogonHoursAttribute(UserObject, 6089 &InfoBuffer->Account.LogonHours); 6090 if (!NT_SUCCESS(Status)) 6091 { 6092 TRACE("Status 0x%08lx\n", Status); 6093 goto done; 6094 } 6095 6096 *Buffer = InfoBuffer; 6097 6098 done: 6099 if (!NT_SUCCESS(Status)) 6100 { 6101 if (InfoBuffer != NULL) 6102 { 6103 if (InfoBuffer->Account.UserName.Buffer != NULL) 6104 midl_user_free(InfoBuffer->Account.UserName.Buffer); 6105 6106 if (InfoBuffer->Account.FullName.Buffer != NULL) 6107 midl_user_free(InfoBuffer->Account.FullName.Buffer); 6108 6109 if (InfoBuffer->Account.HomeDirectory.Buffer != NULL) 6110 midl_user_free(InfoBuffer->Account.HomeDirectory.Buffer); 6111 6112 if (InfoBuffer->Account.HomeDirectoryDrive.Buffer != NULL) 6113 midl_user_free(InfoBuffer->Account.HomeDirectoryDrive.Buffer); 6114 6115 if (InfoBuffer->Account.ScriptPath.Buffer != NULL) 6116 midl_user_free(InfoBuffer->Account.ScriptPath.Buffer); 6117 6118 if (InfoBuffer->Account.ProfilePath.Buffer != NULL) 6119 midl_user_free(InfoBuffer->Account.ProfilePath.Buffer); 6120 6121 if (InfoBuffer->Account.AdminComment.Buffer != NULL) 6122 midl_user_free(InfoBuffer->Account.AdminComment.Buffer); 6123 6124 if (InfoBuffer->Account.WorkStations.Buffer != NULL) 6125 midl_user_free(InfoBuffer->Account.WorkStations.Buffer); 6126 6127 if (InfoBuffer->Account.LogonHours.LogonHours != NULL) 6128 midl_user_free(InfoBuffer->Account.LogonHours.LogonHours); 6129 6130 midl_user_free(InfoBuffer); 6131 } 6132 } 6133 6134 return Status; 6135 } 6136 6137 6138 static 6139 NTSTATUS 6140 SampQueryUserLogonHours(PSAM_DB_OBJECT UserObject, 6141 PSAMPR_USER_INFO_BUFFER *Buffer) 6142 { 6143 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6144 NTSTATUS Status; 6145 6146 TRACE("(%p %p)\n", UserObject, Buffer); 6147 6148 *Buffer = NULL; 6149 6150 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6151 if (InfoBuffer == NULL) 6152 { 6153 TRACE("Failed to allocate InfoBuffer!\n"); 6154 return STATUS_INSUFFICIENT_RESOURCES; 6155 } 6156 6157 Status = SampGetLogonHoursAttribute(UserObject, 6158 &InfoBuffer->LogonHours.LogonHours); 6159 if (!NT_SUCCESS(Status)) 6160 { 6161 TRACE("SampGetLogonHoursAttribute failed (Status 0x%08lx)\n", Status); 6162 goto done; 6163 } 6164 6165 *Buffer = InfoBuffer; 6166 6167 done: 6168 if (!NT_SUCCESS(Status)) 6169 { 6170 if (InfoBuffer != NULL) 6171 { 6172 if (InfoBuffer->LogonHours.LogonHours.LogonHours != NULL) 6173 midl_user_free(InfoBuffer->LogonHours.LogonHours.LogonHours); 6174 6175 midl_user_free(InfoBuffer); 6176 } 6177 } 6178 6179 return Status; 6180 } 6181 6182 6183 static 6184 NTSTATUS 6185 SampQueryUserName(PSAM_DB_OBJECT UserObject, 6186 PSAMPR_USER_INFO_BUFFER *Buffer) 6187 { 6188 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6189 NTSTATUS Status; 6190 6191 *Buffer = NULL; 6192 6193 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6194 if (InfoBuffer == NULL) 6195 return STATUS_INSUFFICIENT_RESOURCES; 6196 6197 /* Get the Name string */ 6198 Status = SampGetObjectAttributeString(UserObject, 6199 L"Name", 6200 &InfoBuffer->Name.UserName); 6201 if (!NT_SUCCESS(Status)) 6202 { 6203 TRACE("Status 0x%08lx\n", Status); 6204 goto done; 6205 } 6206 6207 /* Get the FullName string */ 6208 Status = SampGetObjectAttributeString(UserObject, 6209 L"FullName", 6210 &InfoBuffer->Name.FullName); 6211 if (!NT_SUCCESS(Status)) 6212 { 6213 TRACE("Status 0x%08lx\n", Status); 6214 goto done; 6215 } 6216 6217 *Buffer = InfoBuffer; 6218 6219 done: 6220 if (!NT_SUCCESS(Status)) 6221 { 6222 if (InfoBuffer != NULL) 6223 { 6224 if (InfoBuffer->Name.UserName.Buffer != NULL) 6225 midl_user_free(InfoBuffer->Name.UserName.Buffer); 6226 6227 if (InfoBuffer->Name.FullName.Buffer != NULL) 6228 midl_user_free(InfoBuffer->Name.FullName.Buffer); 6229 6230 midl_user_free(InfoBuffer); 6231 } 6232 } 6233 6234 return Status; 6235 } 6236 6237 6238 static NTSTATUS 6239 SampQueryUserAccountName(PSAM_DB_OBJECT UserObject, 6240 PSAMPR_USER_INFO_BUFFER *Buffer) 6241 { 6242 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6243 NTSTATUS Status; 6244 6245 *Buffer = NULL; 6246 6247 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6248 if (InfoBuffer == NULL) 6249 return STATUS_INSUFFICIENT_RESOURCES; 6250 6251 /* Get the Name string */ 6252 Status = SampGetObjectAttributeString(UserObject, 6253 L"Name", 6254 &InfoBuffer->AccountName.UserName); 6255 if (!NT_SUCCESS(Status)) 6256 { 6257 TRACE("Status 0x%08lx\n", Status); 6258 goto done; 6259 } 6260 6261 *Buffer = InfoBuffer; 6262 6263 done: 6264 if (!NT_SUCCESS(Status)) 6265 { 6266 if (InfoBuffer != NULL) 6267 { 6268 if (InfoBuffer->AccountName.UserName.Buffer != NULL) 6269 midl_user_free(InfoBuffer->AccountName.UserName.Buffer); 6270 6271 midl_user_free(InfoBuffer); 6272 } 6273 } 6274 6275 return Status; 6276 } 6277 6278 6279 static NTSTATUS 6280 SampQueryUserFullName(PSAM_DB_OBJECT UserObject, 6281 PSAMPR_USER_INFO_BUFFER *Buffer) 6282 { 6283 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6284 NTSTATUS Status; 6285 6286 *Buffer = NULL; 6287 6288 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6289 if (InfoBuffer == NULL) 6290 return STATUS_INSUFFICIENT_RESOURCES; 6291 6292 /* Get the FullName string */ 6293 Status = SampGetObjectAttributeString(UserObject, 6294 L"FullName", 6295 &InfoBuffer->FullName.FullName); 6296 if (!NT_SUCCESS(Status)) 6297 { 6298 TRACE("Status 0x%08lx\n", Status); 6299 goto done; 6300 } 6301 6302 *Buffer = InfoBuffer; 6303 6304 done: 6305 if (!NT_SUCCESS(Status)) 6306 { 6307 if (InfoBuffer != NULL) 6308 { 6309 if (InfoBuffer->FullName.FullName.Buffer != NULL) 6310 midl_user_free(InfoBuffer->FullName.FullName.Buffer); 6311 6312 midl_user_free(InfoBuffer); 6313 } 6314 } 6315 6316 return Status; 6317 } 6318 6319 6320 static 6321 NTSTATUS 6322 SampQueryUserPrimaryGroup(PSAM_DB_OBJECT UserObject, 6323 PSAMPR_USER_INFO_BUFFER *Buffer) 6324 { 6325 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6326 SAM_USER_FIXED_DATA FixedData; 6327 ULONG Length = 0; 6328 NTSTATUS Status; 6329 6330 *Buffer = NULL; 6331 6332 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6333 if (InfoBuffer == NULL) 6334 return STATUS_INSUFFICIENT_RESOURCES; 6335 6336 Length = sizeof(SAM_USER_FIXED_DATA); 6337 Status = SampGetObjectAttribute(UserObject, 6338 L"F", 6339 NULL, 6340 (PVOID)&FixedData, 6341 &Length); 6342 if (!NT_SUCCESS(Status)) 6343 goto done; 6344 6345 InfoBuffer->PrimaryGroup.PrimaryGroupId = FixedData.PrimaryGroupId; 6346 6347 *Buffer = InfoBuffer; 6348 6349 done: 6350 if (!NT_SUCCESS(Status)) 6351 { 6352 if (InfoBuffer != NULL) 6353 { 6354 midl_user_free(InfoBuffer); 6355 } 6356 } 6357 6358 return Status; 6359 } 6360 6361 6362 static NTSTATUS 6363 SampQueryUserHome(PSAM_DB_OBJECT UserObject, 6364 PSAMPR_USER_INFO_BUFFER *Buffer) 6365 { 6366 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6367 NTSTATUS Status; 6368 6369 *Buffer = NULL; 6370 6371 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6372 if (InfoBuffer == NULL) 6373 return STATUS_INSUFFICIENT_RESOURCES; 6374 6375 /* Get the HomeDirectory string */ 6376 Status = SampGetObjectAttributeString(UserObject, 6377 L"HomeDirectory", 6378 &InfoBuffer->Home.HomeDirectory); 6379 if (!NT_SUCCESS(Status)) 6380 { 6381 TRACE("Status 0x%08lx\n", Status); 6382 goto done; 6383 } 6384 6385 /* Get the HomeDirectoryDrive string */ 6386 Status = SampGetObjectAttributeString(UserObject, 6387 L"HomeDirectoryDrive", 6388 &InfoBuffer->Home.HomeDirectoryDrive); 6389 if (!NT_SUCCESS(Status)) 6390 { 6391 TRACE("Status 0x%08lx\n", Status); 6392 goto done; 6393 } 6394 6395 *Buffer = InfoBuffer; 6396 6397 done: 6398 if (!NT_SUCCESS(Status)) 6399 { 6400 if (InfoBuffer != NULL) 6401 { 6402 if (InfoBuffer->Home.HomeDirectory.Buffer != NULL) 6403 midl_user_free(InfoBuffer->Home.HomeDirectory.Buffer); 6404 6405 if (InfoBuffer->Home.HomeDirectoryDrive.Buffer != NULL) 6406 midl_user_free(InfoBuffer->Home.HomeDirectoryDrive.Buffer); 6407 6408 midl_user_free(InfoBuffer); 6409 } 6410 } 6411 6412 return Status; 6413 } 6414 6415 6416 static NTSTATUS 6417 SampQueryUserScript(PSAM_DB_OBJECT UserObject, 6418 PSAMPR_USER_INFO_BUFFER *Buffer) 6419 { 6420 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6421 NTSTATUS Status; 6422 6423 *Buffer = NULL; 6424 6425 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6426 if (InfoBuffer == NULL) 6427 return STATUS_INSUFFICIENT_RESOURCES; 6428 6429 /* Get the ScriptPath string */ 6430 Status = SampGetObjectAttributeString(UserObject, 6431 L"ScriptPath", 6432 &InfoBuffer->Script.ScriptPath); 6433 if (!NT_SUCCESS(Status)) 6434 { 6435 TRACE("Status 0x%08lx\n", Status); 6436 goto done; 6437 } 6438 6439 *Buffer = InfoBuffer; 6440 6441 done: 6442 if (!NT_SUCCESS(Status)) 6443 { 6444 if (InfoBuffer != NULL) 6445 { 6446 if (InfoBuffer->Script.ScriptPath.Buffer != NULL) 6447 midl_user_free(InfoBuffer->Script.ScriptPath.Buffer); 6448 6449 midl_user_free(InfoBuffer); 6450 } 6451 } 6452 6453 return Status; 6454 } 6455 6456 6457 static NTSTATUS 6458 SampQueryUserProfile(PSAM_DB_OBJECT UserObject, 6459 PSAMPR_USER_INFO_BUFFER *Buffer) 6460 { 6461 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6462 NTSTATUS Status; 6463 6464 *Buffer = NULL; 6465 6466 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6467 if (InfoBuffer == NULL) 6468 return STATUS_INSUFFICIENT_RESOURCES; 6469 6470 /* Get the ProfilePath string */ 6471 Status = SampGetObjectAttributeString(UserObject, 6472 L"ProfilePath", 6473 &InfoBuffer->Profile.ProfilePath); 6474 if (!NT_SUCCESS(Status)) 6475 { 6476 TRACE("Status 0x%08lx\n", Status); 6477 goto done; 6478 } 6479 6480 *Buffer = InfoBuffer; 6481 6482 done: 6483 if (!NT_SUCCESS(Status)) 6484 { 6485 if (InfoBuffer != NULL) 6486 { 6487 if (InfoBuffer->Profile.ProfilePath.Buffer != NULL) 6488 midl_user_free(InfoBuffer->Profile.ProfilePath.Buffer); 6489 6490 midl_user_free(InfoBuffer); 6491 } 6492 } 6493 6494 return Status; 6495 } 6496 6497 6498 static NTSTATUS 6499 SampQueryUserAdminComment(PSAM_DB_OBJECT UserObject, 6500 PSAMPR_USER_INFO_BUFFER *Buffer) 6501 { 6502 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6503 NTSTATUS Status; 6504 6505 *Buffer = NULL; 6506 6507 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6508 if (InfoBuffer == NULL) 6509 return STATUS_INSUFFICIENT_RESOURCES; 6510 6511 /* Get the AdminComment string */ 6512 Status = SampGetObjectAttributeString(UserObject, 6513 L"AdminComment", 6514 &InfoBuffer->AdminComment.AdminComment); 6515 if (!NT_SUCCESS(Status)) 6516 { 6517 TRACE("Status 0x%08lx\n", Status); 6518 goto done; 6519 } 6520 6521 *Buffer = InfoBuffer; 6522 6523 done: 6524 if (!NT_SUCCESS(Status)) 6525 { 6526 if (InfoBuffer != NULL) 6527 { 6528 if (InfoBuffer->AdminComment.AdminComment.Buffer != NULL) 6529 midl_user_free(InfoBuffer->AdminComment.AdminComment.Buffer); 6530 6531 midl_user_free(InfoBuffer); 6532 } 6533 } 6534 6535 return Status; 6536 } 6537 6538 6539 static NTSTATUS 6540 SampQueryUserWorkStations(PSAM_DB_OBJECT UserObject, 6541 PSAMPR_USER_INFO_BUFFER *Buffer) 6542 { 6543 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6544 NTSTATUS Status; 6545 6546 *Buffer = NULL; 6547 6548 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6549 if (InfoBuffer == NULL) 6550 return STATUS_INSUFFICIENT_RESOURCES; 6551 6552 /* Get the WorkStations string */ 6553 Status = SampGetObjectAttributeString(UserObject, 6554 L"WorkStations", 6555 &InfoBuffer->WorkStations.WorkStations); 6556 if (!NT_SUCCESS(Status)) 6557 { 6558 TRACE("Status 0x%08lx\n", Status); 6559 goto done; 6560 } 6561 6562 *Buffer = InfoBuffer; 6563 6564 done: 6565 if (!NT_SUCCESS(Status)) 6566 { 6567 if (InfoBuffer != NULL) 6568 { 6569 if (InfoBuffer->WorkStations.WorkStations.Buffer != NULL) 6570 midl_user_free(InfoBuffer->WorkStations.WorkStations.Buffer); 6571 6572 midl_user_free(InfoBuffer); 6573 } 6574 } 6575 6576 return Status; 6577 } 6578 6579 6580 static 6581 NTSTATUS 6582 SampQueryUserControl(PSAM_DB_OBJECT UserObject, 6583 PSAMPR_USER_INFO_BUFFER *Buffer) 6584 { 6585 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6586 SAM_USER_FIXED_DATA FixedData; 6587 ULONG Length = 0; 6588 NTSTATUS Status; 6589 6590 *Buffer = NULL; 6591 6592 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6593 if (InfoBuffer == NULL) 6594 return STATUS_INSUFFICIENT_RESOURCES; 6595 6596 Length = sizeof(SAM_USER_FIXED_DATA); 6597 Status = SampGetObjectAttribute(UserObject, 6598 L"F", 6599 NULL, 6600 (PVOID)&FixedData, 6601 &Length); 6602 if (!NT_SUCCESS(Status)) 6603 goto done; 6604 6605 InfoBuffer->Control.UserAccountControl = FixedData.UserAccountControl; 6606 6607 *Buffer = InfoBuffer; 6608 6609 done: 6610 if (!NT_SUCCESS(Status)) 6611 { 6612 if (InfoBuffer != NULL) 6613 { 6614 midl_user_free(InfoBuffer); 6615 } 6616 } 6617 6618 return Status; 6619 } 6620 6621 6622 static 6623 NTSTATUS 6624 SampQueryUserExpires(PSAM_DB_OBJECT UserObject, 6625 PSAMPR_USER_INFO_BUFFER *Buffer) 6626 { 6627 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6628 SAM_USER_FIXED_DATA FixedData; 6629 ULONG Length = 0; 6630 NTSTATUS Status; 6631 6632 *Buffer = NULL; 6633 6634 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6635 if (InfoBuffer == NULL) 6636 return STATUS_INSUFFICIENT_RESOURCES; 6637 6638 Length = sizeof(SAM_USER_FIXED_DATA); 6639 Status = SampGetObjectAttribute(UserObject, 6640 L"F", 6641 NULL, 6642 (PVOID)&FixedData, 6643 &Length); 6644 if (!NT_SUCCESS(Status)) 6645 goto done; 6646 6647 InfoBuffer->Expires.AccountExpires.LowPart = FixedData.AccountExpires.LowPart; 6648 InfoBuffer->Expires.AccountExpires.HighPart = FixedData.AccountExpires.HighPart; 6649 6650 *Buffer = InfoBuffer; 6651 6652 done: 6653 if (!NT_SUCCESS(Status)) 6654 { 6655 if (InfoBuffer != NULL) 6656 { 6657 midl_user_free(InfoBuffer); 6658 } 6659 } 6660 6661 return Status; 6662 } 6663 6664 6665 static 6666 NTSTATUS 6667 SampQueryUserInternal1(PSAM_DB_OBJECT UserObject, 6668 PSAMPR_USER_INFO_BUFFER *Buffer) 6669 { 6670 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6671 ULONG Length = 0; 6672 NTSTATUS Status = STATUS_SUCCESS; 6673 6674 /* Fail, if the caller is not a trusted caller */ 6675 if (UserObject->Trusted == FALSE) 6676 return STATUS_INVALID_INFO_CLASS; 6677 6678 *Buffer = NULL; 6679 6680 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6681 if (InfoBuffer == NULL) 6682 return STATUS_INSUFFICIENT_RESOURCES; 6683 6684 InfoBuffer->Internal1.LmPasswordPresent = FALSE; 6685 InfoBuffer->Internal1.NtPasswordPresent = FALSE; 6686 6687 /* Get the NT password */ 6688 Length = 0; 6689 SampGetObjectAttribute(UserObject, 6690 L"NTPwd", 6691 NULL, 6692 NULL, 6693 &Length); 6694 6695 if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD)) 6696 { 6697 Status = SampGetObjectAttribute(UserObject, 6698 L"NTPwd", 6699 NULL, 6700 (PVOID)&InfoBuffer->Internal1.EncryptedNtOwfPassword, 6701 &Length); 6702 if (!NT_SUCCESS(Status)) 6703 goto done; 6704 6705 if (memcmp(&InfoBuffer->Internal1.EncryptedNtOwfPassword, 6706 &EmptyNtHash, 6707 sizeof(ENCRYPTED_NT_OWF_PASSWORD))) 6708 InfoBuffer->Internal1.NtPasswordPresent = TRUE; 6709 } 6710 6711 6712 /* Get the LM password */ 6713 Length = 0; 6714 SampGetObjectAttribute(UserObject, 6715 L"LMPwd", 6716 NULL, 6717 NULL, 6718 &Length); 6719 6720 if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD)) 6721 { 6722 Status = SampGetObjectAttribute(UserObject, 6723 L"LMPwd", 6724 NULL, 6725 (PVOID)&InfoBuffer->Internal1.EncryptedLmOwfPassword, 6726 &Length); 6727 if (!NT_SUCCESS(Status)) 6728 goto done; 6729 6730 if (memcmp(&InfoBuffer->Internal1.EncryptedLmOwfPassword, 6731 &EmptyLmHash, 6732 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 6733 InfoBuffer->Internal1.LmPasswordPresent = TRUE; 6734 } 6735 6736 InfoBuffer->Internal1.PasswordExpired = FALSE; 6737 6738 *Buffer = InfoBuffer; 6739 6740 done: 6741 if (!NT_SUCCESS(Status)) 6742 { 6743 if (InfoBuffer != NULL) 6744 { 6745 midl_user_free(InfoBuffer); 6746 } 6747 } 6748 6749 return Status; 6750 } 6751 6752 6753 static 6754 NTSTATUS 6755 SampQueryUserInternal2(PSAM_DB_OBJECT UserObject, 6756 PSAMPR_USER_INFO_BUFFER *Buffer) 6757 { 6758 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6759 SAM_USER_FIXED_DATA FixedData; 6760 ULONG Length = 0; 6761 NTSTATUS Status; 6762 6763 *Buffer = NULL; 6764 6765 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6766 if (InfoBuffer == NULL) 6767 return STATUS_INSUFFICIENT_RESOURCES; 6768 6769 Length = sizeof(SAM_USER_FIXED_DATA); 6770 Status = SampGetObjectAttribute(UserObject, 6771 L"F", 6772 NULL, 6773 (PVOID)&FixedData, 6774 &Length); 6775 if (!NT_SUCCESS(Status)) 6776 goto done; 6777 6778 InfoBuffer->Internal2.Flags = 0; 6779 InfoBuffer->Internal2.LastLogon.LowPart = FixedData.LastLogon.LowPart; 6780 InfoBuffer->Internal2.LastLogon.HighPart = FixedData.LastLogon.HighPart; 6781 InfoBuffer->Internal2.LastLogoff.LowPart = FixedData.LastLogoff.LowPart; 6782 InfoBuffer->Internal2.LastLogoff.HighPart = FixedData.LastLogoff.HighPart; 6783 InfoBuffer->Internal2.BadPasswordCount = FixedData.BadPasswordCount; 6784 InfoBuffer->Internal2.LogonCount = FixedData.LogonCount; 6785 6786 *Buffer = InfoBuffer; 6787 6788 done: 6789 if (!NT_SUCCESS(Status)) 6790 { 6791 if (InfoBuffer != NULL) 6792 { 6793 midl_user_free(InfoBuffer); 6794 } 6795 } 6796 6797 return Status; 6798 } 6799 6800 6801 static NTSTATUS 6802 SampQueryUserParameters(PSAM_DB_OBJECT UserObject, 6803 PSAMPR_USER_INFO_BUFFER *Buffer) 6804 { 6805 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6806 NTSTATUS Status; 6807 6808 *Buffer = NULL; 6809 6810 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6811 if (InfoBuffer == NULL) 6812 return STATUS_INSUFFICIENT_RESOURCES; 6813 6814 /* Get the Parameters string */ 6815 Status = SampGetObjectAttributeString(UserObject, 6816 L"Parameters", 6817 &InfoBuffer->Parameters.Parameters); 6818 if (!NT_SUCCESS(Status)) 6819 { 6820 TRACE("Status 0x%08lx\n", Status); 6821 goto done; 6822 } 6823 6824 *Buffer = InfoBuffer; 6825 6826 done: 6827 if (!NT_SUCCESS(Status)) 6828 { 6829 if (InfoBuffer != NULL) 6830 { 6831 if (InfoBuffer->Parameters.Parameters.Buffer != NULL) 6832 midl_user_free(InfoBuffer->Parameters.Parameters.Buffer); 6833 6834 midl_user_free(InfoBuffer); 6835 } 6836 } 6837 6838 return Status; 6839 } 6840 6841 6842 static NTSTATUS 6843 SampQueryUserAll(PSAM_DB_OBJECT UserObject, 6844 PSAMPR_USER_INFO_BUFFER *Buffer) 6845 { 6846 PSAMPR_USER_INFO_BUFFER InfoBuffer = NULL; 6847 SAM_DOMAIN_FIXED_DATA DomainFixedData; 6848 SAM_USER_FIXED_DATA FixedData; 6849 LARGE_INTEGER PasswordCanChange; 6850 LARGE_INTEGER PasswordMustChange; 6851 ULONG Length = 0; 6852 NTSTATUS Status; 6853 6854 *Buffer = NULL; 6855 6856 InfoBuffer = midl_user_allocate(sizeof(SAMPR_USER_INFO_BUFFER)); 6857 if (InfoBuffer == NULL) 6858 return STATUS_INSUFFICIENT_RESOURCES; 6859 6860 /* Get the fixed size domain data */ 6861 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 6862 Status = SampGetObjectAttribute(UserObject->ParentObject, 6863 L"F", 6864 NULL, 6865 (PVOID)&DomainFixedData, 6866 &Length); 6867 if (!NT_SUCCESS(Status)) 6868 goto done; 6869 6870 /* Get the fixed size user data */ 6871 Length = sizeof(SAM_USER_FIXED_DATA); 6872 Status = SampGetObjectAttribute(UserObject, 6873 L"F", 6874 NULL, 6875 (PVOID)&FixedData, 6876 &Length); 6877 if (!NT_SUCCESS(Status)) 6878 goto done; 6879 6880 /* Set the fields to be returned */ 6881 if (UserObject->Trusted) 6882 { 6883 InfoBuffer->All.WhichFields = USER_ALL_READ_GENERAL_MASK | 6884 USER_ALL_READ_LOGON_MASK | 6885 USER_ALL_READ_ACCOUNT_MASK | 6886 USER_ALL_READ_PREFERENCES_MASK | 6887 USER_ALL_READ_TRUSTED_MASK; 6888 } 6889 else 6890 { 6891 InfoBuffer->All.WhichFields = 0; 6892 6893 if (UserObject->Access & USER_READ_GENERAL) 6894 InfoBuffer->All.WhichFields |= USER_ALL_READ_GENERAL_MASK; 6895 6896 if (UserObject->Access & USER_READ_LOGON) 6897 InfoBuffer->All.WhichFields |= USER_ALL_READ_LOGON_MASK; 6898 6899 if (UserObject->Access & USER_READ_ACCOUNT) 6900 InfoBuffer->All.WhichFields |= USER_ALL_READ_ACCOUNT_MASK; 6901 6902 if (UserObject->Access & USER_READ_PREFERENCES) 6903 InfoBuffer->All.WhichFields |= USER_ALL_READ_PREFERENCES_MASK; 6904 } 6905 6906 /* Fail, if no fields are to be returned */ 6907 if (InfoBuffer->All.WhichFields == 0) 6908 { 6909 Status = STATUS_ACCESS_DENIED; 6910 goto done; 6911 } 6912 6913 /* Get the UserName attribute */ 6914 if (InfoBuffer->All.WhichFields & USER_ALL_USERNAME) 6915 { 6916 Status = SampGetObjectAttributeString(UserObject, 6917 L"Name", 6918 &InfoBuffer->All.UserName); 6919 if (!NT_SUCCESS(Status)) 6920 { 6921 TRACE("Status 0x%08lx\n", Status); 6922 goto done; 6923 } 6924 } 6925 6926 /* Get the FullName attribute */ 6927 if (InfoBuffer->All.WhichFields & USER_ALL_FULLNAME) 6928 { 6929 Status = SampGetObjectAttributeString(UserObject, 6930 L"FullName", 6931 &InfoBuffer->All.FullName); 6932 if (!NT_SUCCESS(Status)) 6933 { 6934 TRACE("Status 0x%08lx\n", Status); 6935 goto done; 6936 } 6937 } 6938 6939 /* Get the UserId attribute */ 6940 if (InfoBuffer->All.WhichFields & USER_ALL_USERID) 6941 { 6942 InfoBuffer->All.UserId = FixedData.UserId; 6943 } 6944 6945 /* Get the PrimaryGroupId attribute */ 6946 if (InfoBuffer->All.WhichFields & USER_ALL_PRIMARYGROUPID) 6947 { 6948 InfoBuffer->All.PrimaryGroupId = FixedData.PrimaryGroupId; 6949 } 6950 6951 /* Get the AdminComment attribute */ 6952 if (InfoBuffer->All.WhichFields & USER_ALL_ADMINCOMMENT) 6953 { 6954 Status = SampGetObjectAttributeString(UserObject, 6955 L"AdminComment", 6956 &InfoBuffer->All.AdminComment); 6957 if (!NT_SUCCESS(Status)) 6958 { 6959 TRACE("Status 0x%08lx\n", Status); 6960 goto done; 6961 } 6962 } 6963 6964 /* Get the UserComment attribute */ 6965 if (InfoBuffer->All.WhichFields & USER_ALL_USERCOMMENT) 6966 { 6967 Status = SampGetObjectAttributeString(UserObject, 6968 L"UserComment", 6969 &InfoBuffer->All.UserComment); 6970 if (!NT_SUCCESS(Status)) 6971 { 6972 TRACE("Status 0x%08lx\n", Status); 6973 goto done; 6974 } 6975 } 6976 6977 /* Get the HomeDirectory attribute */ 6978 if (InfoBuffer->All.WhichFields & USER_ALL_HOMEDIRECTORY) 6979 { 6980 Status = SampGetObjectAttributeString(UserObject, 6981 L"HomeDirectory", 6982 &InfoBuffer->All.HomeDirectory); 6983 if (!NT_SUCCESS(Status)) 6984 { 6985 TRACE("Status 0x%08lx\n", Status); 6986 goto done; 6987 } 6988 } 6989 6990 /* Get the HomeDirectoryDrive attribute */ 6991 if (InfoBuffer->All.WhichFields & USER_ALL_HOMEDIRECTORYDRIVE) 6992 { 6993 Status = SampGetObjectAttributeString(UserObject, 6994 L"HomeDirectoryDrive", 6995 &InfoBuffer->Home.HomeDirectoryDrive); 6996 if (!NT_SUCCESS(Status)) 6997 { 6998 TRACE("Status 0x%08lx\n", Status); 6999 goto done; 7000 } 7001 } 7002 7003 /* Get the ScriptPath attribute */ 7004 if (InfoBuffer->All.WhichFields & USER_ALL_SCRIPTPATH) 7005 { 7006 Status = SampGetObjectAttributeString(UserObject, 7007 L"ScriptPath", 7008 &InfoBuffer->All.ScriptPath); 7009 if (!NT_SUCCESS(Status)) 7010 { 7011 TRACE("Status 0x%08lx\n", Status); 7012 goto done; 7013 } 7014 } 7015 7016 /* Get the ProfilePath attribute */ 7017 if (InfoBuffer->All.WhichFields & USER_ALL_PROFILEPATH) 7018 { 7019 Status = SampGetObjectAttributeString(UserObject, 7020 L"ProfilePath", 7021 &InfoBuffer->All.ProfilePath); 7022 if (!NT_SUCCESS(Status)) 7023 { 7024 TRACE("Status 0x%08lx\n", Status); 7025 goto done; 7026 } 7027 } 7028 7029 /* Get the WorkStations attribute */ 7030 if (InfoBuffer->All.WhichFields & USER_ALL_WORKSTATIONS) 7031 { 7032 Status = SampGetObjectAttributeString(UserObject, 7033 L"WorkStations", 7034 &InfoBuffer->All.WorkStations); 7035 if (!NT_SUCCESS(Status)) 7036 { 7037 TRACE("Status 0x%08lx\n", Status); 7038 goto done; 7039 } 7040 } 7041 7042 /* Get the LastLogon attribute */ 7043 if (InfoBuffer->All.WhichFields & USER_ALL_LASTLOGON) 7044 { 7045 InfoBuffer->All.LastLogon.LowPart = FixedData.LastLogon.LowPart; 7046 InfoBuffer->All.LastLogon.HighPart = FixedData.LastLogon.HighPart; 7047 } 7048 7049 /* Get the LastLogoff attribute */ 7050 if (InfoBuffer->All.WhichFields & USER_ALL_LASTLOGOFF) 7051 { 7052 InfoBuffer->All.LastLogoff.LowPart = FixedData.LastLogoff.LowPart; 7053 InfoBuffer->All.LastLogoff.HighPart = FixedData.LastLogoff.HighPart; 7054 } 7055 7056 /* Get the LogonHours attribute */ 7057 if (InfoBuffer->All.WhichFields & USER_ALL_LOGONHOURS) 7058 { 7059 Status = SampGetLogonHoursAttribute(UserObject, 7060 &InfoBuffer->All.LogonHours); 7061 if (!NT_SUCCESS(Status)) 7062 { 7063 TRACE("Status 0x%08lx\n", Status); 7064 goto done; 7065 } 7066 } 7067 7068 /* Get the BadPasswordCount attribute */ 7069 if (InfoBuffer->All.WhichFields & USER_ALL_BADPASSWORDCOUNT) 7070 { 7071 InfoBuffer->All.BadPasswordCount = FixedData.BadPasswordCount; 7072 } 7073 7074 /* Get the LogonCount attribute */ 7075 if (InfoBuffer->All.WhichFields & USER_ALL_LOGONCOUNT) 7076 { 7077 InfoBuffer->All.LogonCount = FixedData.LogonCount; 7078 } 7079 7080 /* Get the PasswordCanChange attribute */ 7081 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDCANCHANGE) 7082 { 7083 PasswordCanChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet, 7084 DomainFixedData.MinPasswordAge); 7085 InfoBuffer->All.PasswordCanChange.LowPart = PasswordCanChange.LowPart; 7086 InfoBuffer->All.PasswordCanChange.HighPart = PasswordCanChange.HighPart; 7087 } 7088 7089 /* Get the PasswordMustChange attribute */ 7090 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDMUSTCHANGE) 7091 { 7092 PasswordMustChange = SampAddRelativeTimeToTime(FixedData.PasswordLastSet, 7093 DomainFixedData.MaxPasswordAge); 7094 InfoBuffer->All.PasswordMustChange.LowPart = PasswordMustChange.LowPart; 7095 InfoBuffer->All.PasswordMustChange.HighPart = PasswordMustChange.HighPart; 7096 } 7097 7098 /* Get the PasswordLastSet attribute */ 7099 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDLASTSET) 7100 { 7101 InfoBuffer->All.PasswordLastSet.LowPart = FixedData.PasswordLastSet.LowPart; 7102 InfoBuffer->All.PasswordLastSet.HighPart = FixedData.PasswordLastSet.HighPart; 7103 } 7104 7105 /* Get the AccountExpires attribute */ 7106 if (InfoBuffer->All.WhichFields & USER_ALL_ACCOUNTEXPIRES) 7107 { 7108 InfoBuffer->All.AccountExpires.LowPart = FixedData.AccountExpires.LowPart; 7109 InfoBuffer->All.AccountExpires.HighPart = FixedData.AccountExpires.HighPart; 7110 } 7111 7112 /* Get the UserAccountControl attribute */ 7113 if (InfoBuffer->All.WhichFields & USER_ALL_USERACCOUNTCONTROL) 7114 { 7115 InfoBuffer->All.UserAccountControl = FixedData.UserAccountControl; 7116 } 7117 7118 /* Get the Parameters attribute */ 7119 if (InfoBuffer->All.WhichFields & USER_ALL_PARAMETERS) 7120 { 7121 Status = SampGetObjectAttributeString(UserObject, 7122 L"Parameters", 7123 &InfoBuffer->All.Parameters); 7124 if (!NT_SUCCESS(Status)) 7125 { 7126 TRACE("Status 0x%08lx\n", Status); 7127 goto done; 7128 } 7129 } 7130 7131 /* Get the CountryCode attribute */ 7132 if (InfoBuffer->All.WhichFields & USER_ALL_COUNTRYCODE) 7133 { 7134 InfoBuffer->All.CountryCode = FixedData.CountryCode; 7135 } 7136 7137 /* Get the CodePage attribute */ 7138 if (InfoBuffer->All.WhichFields & USER_ALL_CODEPAGE) 7139 { 7140 InfoBuffer->All.CodePage = FixedData.CodePage; 7141 } 7142 7143 /* Get the LmPassword and NtPassword attributes */ 7144 if (InfoBuffer->All.WhichFields & (USER_ALL_NTPASSWORDPRESENT | USER_ALL_LMPASSWORDPRESENT)) 7145 { 7146 InfoBuffer->All.LmPasswordPresent = FALSE; 7147 InfoBuffer->All.NtPasswordPresent = FALSE; 7148 7149 /* Get the NT password */ 7150 Length = 0; 7151 SampGetObjectAttribute(UserObject, 7152 L"NTPwd", 7153 NULL, 7154 NULL, 7155 &Length); 7156 7157 if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD)) 7158 { 7159 InfoBuffer->All.NtOwfPassword.Buffer = midl_user_allocate(sizeof(ENCRYPTED_NT_OWF_PASSWORD)); 7160 if (InfoBuffer->All.NtOwfPassword.Buffer == NULL) 7161 { 7162 Status = STATUS_INSUFFICIENT_RESOURCES; 7163 goto done; 7164 } 7165 7166 InfoBuffer->All.NtOwfPassword.Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD); 7167 InfoBuffer->All.NtOwfPassword.MaximumLength = sizeof(ENCRYPTED_NT_OWF_PASSWORD); 7168 7169 Status = SampGetObjectAttribute(UserObject, 7170 L"NTPwd", 7171 NULL, 7172 (PVOID)InfoBuffer->All.NtOwfPassword.Buffer, 7173 &Length); 7174 if (!NT_SUCCESS(Status)) 7175 goto done; 7176 7177 if (memcmp(InfoBuffer->All.NtOwfPassword.Buffer, 7178 &EmptyNtHash, 7179 sizeof(ENCRYPTED_NT_OWF_PASSWORD))) 7180 InfoBuffer->All.NtPasswordPresent = TRUE; 7181 } 7182 7183 /* Get the LM password */ 7184 Length = 0; 7185 SampGetObjectAttribute(UserObject, 7186 L"LMPwd", 7187 NULL, 7188 NULL, 7189 &Length); 7190 7191 if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD)) 7192 { 7193 InfoBuffer->All.LmOwfPassword.Buffer = midl_user_allocate(sizeof(ENCRYPTED_LM_OWF_PASSWORD)); 7194 if (InfoBuffer->All.LmOwfPassword.Buffer == NULL) 7195 { 7196 Status = STATUS_INSUFFICIENT_RESOURCES; 7197 goto done; 7198 } 7199 7200 InfoBuffer->All.LmOwfPassword.Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD); 7201 InfoBuffer->All.LmOwfPassword.MaximumLength = sizeof(ENCRYPTED_LM_OWF_PASSWORD); 7202 7203 Status = SampGetObjectAttribute(UserObject, 7204 L"LMPwd", 7205 NULL, 7206 (PVOID)InfoBuffer->All.LmOwfPassword.Buffer, 7207 &Length); 7208 if (!NT_SUCCESS(Status)) 7209 goto done; 7210 7211 if (memcmp(InfoBuffer->All.LmOwfPassword.Buffer, 7212 &EmptyLmHash, 7213 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 7214 InfoBuffer->All.LmPasswordPresent = TRUE; 7215 } 7216 } 7217 7218 if (InfoBuffer->All.WhichFields & USER_ALL_PRIVATEDATA) 7219 { 7220 Status = SampGetObjectAttributeString(UserObject, 7221 L"PrivateData", 7222 &InfoBuffer->All.PrivateData); 7223 if (!NT_SUCCESS(Status)) 7224 { 7225 TRACE("Status 0x%08lx\n", Status); 7226 goto done; 7227 } 7228 } 7229 7230 if (InfoBuffer->All.WhichFields & USER_ALL_PASSWORDEXPIRED) 7231 { 7232 /* FIXME */ 7233 } 7234 7235 if (InfoBuffer->All.WhichFields & USER_ALL_SECURITYDESCRIPTOR) 7236 { 7237 Length = 0; 7238 SampGetObjectAttribute(UserObject, 7239 L"SecDesc", 7240 NULL, 7241 NULL, 7242 &Length); 7243 7244 if (Length > 0) 7245 { 7246 InfoBuffer->All.SecurityDescriptor.SecurityDescriptor = midl_user_allocate(Length); 7247 if (InfoBuffer->All.SecurityDescriptor.SecurityDescriptor == NULL) 7248 { 7249 Status = STATUS_INSUFFICIENT_RESOURCES; 7250 goto done; 7251 } 7252 7253 InfoBuffer->All.SecurityDescriptor.Length = Length; 7254 7255 Status = SampGetObjectAttribute(UserObject, 7256 L"SecDesc", 7257 NULL, 7258 (PVOID)InfoBuffer->All.SecurityDescriptor.SecurityDescriptor, 7259 &Length); 7260 if (!NT_SUCCESS(Status)) 7261 goto done; 7262 } 7263 } 7264 7265 *Buffer = InfoBuffer; 7266 7267 done: 7268 if (!NT_SUCCESS(Status)) 7269 { 7270 if (InfoBuffer != NULL) 7271 { 7272 if (InfoBuffer->All.UserName.Buffer != NULL) 7273 midl_user_free(InfoBuffer->All.UserName.Buffer); 7274 7275 if (InfoBuffer->All.FullName.Buffer != NULL) 7276 midl_user_free(InfoBuffer->All.FullName.Buffer); 7277 7278 if (InfoBuffer->All.AdminComment.Buffer != NULL) 7279 midl_user_free(InfoBuffer->All.AdminComment.Buffer); 7280 7281 if (InfoBuffer->All.UserComment.Buffer != NULL) 7282 midl_user_free(InfoBuffer->All.UserComment.Buffer); 7283 7284 if (InfoBuffer->All.HomeDirectory.Buffer != NULL) 7285 midl_user_free(InfoBuffer->All.HomeDirectory.Buffer); 7286 7287 if (InfoBuffer->All.HomeDirectoryDrive.Buffer != NULL) 7288 midl_user_free(InfoBuffer->All.HomeDirectoryDrive.Buffer); 7289 7290 if (InfoBuffer->All.ScriptPath.Buffer != NULL) 7291 midl_user_free(InfoBuffer->All.ScriptPath.Buffer); 7292 7293 if (InfoBuffer->All.ProfilePath.Buffer != NULL) 7294 midl_user_free(InfoBuffer->All.ProfilePath.Buffer); 7295 7296 if (InfoBuffer->All.WorkStations.Buffer != NULL) 7297 midl_user_free(InfoBuffer->All.WorkStations.Buffer); 7298 7299 if (InfoBuffer->All.LogonHours.LogonHours != NULL) 7300 midl_user_free(InfoBuffer->All.LogonHours.LogonHours); 7301 7302 if (InfoBuffer->All.Parameters.Buffer != NULL) 7303 midl_user_free(InfoBuffer->All.Parameters.Buffer); 7304 7305 if (InfoBuffer->All.LmOwfPassword.Buffer != NULL) 7306 midl_user_free(InfoBuffer->All.LmOwfPassword.Buffer); 7307 7308 if (InfoBuffer->All.NtOwfPassword.Buffer != NULL) 7309 midl_user_free(InfoBuffer->All.NtOwfPassword.Buffer); 7310 7311 if (InfoBuffer->All.PrivateData.Buffer != NULL) 7312 midl_user_free(InfoBuffer->All.PrivateData.Buffer); 7313 7314 if (InfoBuffer->All.SecurityDescriptor.SecurityDescriptor != NULL) 7315 midl_user_free(InfoBuffer->All.SecurityDescriptor.SecurityDescriptor); 7316 7317 midl_user_free(InfoBuffer); 7318 } 7319 } 7320 7321 return Status; 7322 } 7323 7324 7325 /* Function 36 */ 7326 NTSTATUS 7327 NTAPI 7328 SamrQueryInformationUser(IN SAMPR_HANDLE UserHandle, 7329 IN USER_INFORMATION_CLASS UserInformationClass, 7330 OUT PSAMPR_USER_INFO_BUFFER *Buffer) 7331 { 7332 PSAM_DB_OBJECT UserObject; 7333 ACCESS_MASK DesiredAccess; 7334 NTSTATUS Status; 7335 7336 TRACE("SamrQueryInformationUser(%p %lu %p)\n", 7337 UserHandle, UserInformationClass, Buffer); 7338 7339 switch (UserInformationClass) 7340 { 7341 case UserGeneralInformation: 7342 case UserNameInformation: 7343 case UserAccountNameInformation: 7344 case UserFullNameInformation: 7345 case UserPrimaryGroupInformation: 7346 case UserAdminCommentInformation: 7347 DesiredAccess = USER_READ_GENERAL; 7348 break; 7349 7350 case UserLogonHoursInformation: 7351 case UserHomeInformation: 7352 case UserScriptInformation: 7353 case UserProfileInformation: 7354 case UserWorkStationsInformation: 7355 DesiredAccess = USER_READ_LOGON; 7356 break; 7357 7358 case UserControlInformation: 7359 case UserExpiresInformation: 7360 case UserParametersInformation: 7361 DesiredAccess = USER_READ_ACCOUNT; 7362 break; 7363 7364 case UserPreferencesInformation: 7365 DesiredAccess = USER_READ_GENERAL | 7366 USER_READ_PREFERENCES; 7367 break; 7368 7369 case UserLogonInformation: 7370 case UserAccountInformation: 7371 DesiredAccess = USER_READ_GENERAL | 7372 USER_READ_PREFERENCES | 7373 USER_READ_LOGON | 7374 USER_READ_ACCOUNT; 7375 break; 7376 7377 case UserInternal1Information: 7378 case UserInternal2Information: 7379 case UserAllInformation: 7380 DesiredAccess = 0; 7381 break; 7382 7383 default: 7384 return STATUS_INVALID_INFO_CLASS; 7385 } 7386 7387 RtlAcquireResourceShared(&SampResource, 7388 TRUE); 7389 7390 /* Validate the domain handle */ 7391 Status = SampValidateDbObject(UserHandle, 7392 SamDbUserObject, 7393 DesiredAccess, 7394 &UserObject); 7395 if (!NT_SUCCESS(Status)) 7396 { 7397 TRACE("failed with status 0x%08lx\n", Status); 7398 goto done; 7399 } 7400 7401 switch (UserInformationClass) 7402 { 7403 case UserGeneralInformation: 7404 Status = SampQueryUserGeneral(UserObject, 7405 Buffer); 7406 break; 7407 7408 case UserPreferencesInformation: 7409 Status = SampQueryUserPreferences(UserObject, 7410 Buffer); 7411 break; 7412 7413 case UserLogonInformation: 7414 Status = SampQueryUserLogon(UserObject, 7415 Buffer); 7416 break; 7417 7418 case UserLogonHoursInformation: 7419 Status = SampQueryUserLogonHours(UserObject, 7420 Buffer); 7421 break; 7422 7423 case UserAccountInformation: 7424 Status = SampQueryUserAccount(UserObject, 7425 Buffer); 7426 break; 7427 7428 case UserNameInformation: 7429 Status = SampQueryUserName(UserObject, 7430 Buffer); 7431 break; 7432 7433 case UserAccountNameInformation: 7434 Status = SampQueryUserAccountName(UserObject, 7435 Buffer); 7436 break; 7437 7438 case UserFullNameInformation: 7439 Status = SampQueryUserFullName(UserObject, 7440 Buffer); 7441 break; 7442 7443 case UserPrimaryGroupInformation: 7444 Status = SampQueryUserPrimaryGroup(UserObject, 7445 Buffer); 7446 break; 7447 7448 case UserHomeInformation: 7449 Status = SampQueryUserHome(UserObject, 7450 Buffer); 7451 7452 case UserScriptInformation: 7453 Status = SampQueryUserScript(UserObject, 7454 Buffer); 7455 break; 7456 7457 case UserProfileInformation: 7458 Status = SampQueryUserProfile(UserObject, 7459 Buffer); 7460 break; 7461 7462 case UserAdminCommentInformation: 7463 Status = SampQueryUserAdminComment(UserObject, 7464 Buffer); 7465 break; 7466 7467 case UserWorkStationsInformation: 7468 Status = SampQueryUserWorkStations(UserObject, 7469 Buffer); 7470 break; 7471 7472 case UserControlInformation: 7473 Status = SampQueryUserControl(UserObject, 7474 Buffer); 7475 break; 7476 7477 case UserExpiresInformation: 7478 Status = SampQueryUserExpires(UserObject, 7479 Buffer); 7480 break; 7481 7482 case UserInternal1Information: 7483 Status = SampQueryUserInternal1(UserObject, 7484 Buffer); 7485 break; 7486 7487 case UserInternal2Information: 7488 Status = SampQueryUserInternal2(UserObject, 7489 Buffer); 7490 break; 7491 7492 case UserParametersInformation: 7493 Status = SampQueryUserParameters(UserObject, 7494 Buffer); 7495 break; 7496 7497 case UserAllInformation: 7498 Status = SampQueryUserAll(UserObject, 7499 Buffer); 7500 break; 7501 7502 // case UserInternal4Information: 7503 // case UserInternal5Information: 7504 // case UserInternal4InformationNew: 7505 // case UserInternal5InformationNew: 7506 7507 default: 7508 Status = STATUS_INVALID_INFO_CLASS; 7509 } 7510 7511 done: 7512 RtlReleaseResource(&SampResource); 7513 7514 return Status; 7515 } 7516 7517 7518 static NTSTATUS 7519 SampSetUserName(PSAM_DB_OBJECT UserObject, 7520 PRPC_UNICODE_STRING NewUserName) 7521 { 7522 UNICODE_STRING OldUserName = {0, 0, NULL}; 7523 NTSTATUS Status; 7524 7525 /* Check the account name */ 7526 Status = SampCheckAccountName(NewUserName, 20); 7527 if (!NT_SUCCESS(Status)) 7528 { 7529 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 7530 return Status; 7531 } 7532 7533 Status = SampGetObjectAttributeString(UserObject, 7534 L"Name", 7535 (PRPC_UNICODE_STRING)&OldUserName); 7536 if (!NT_SUCCESS(Status)) 7537 { 7538 TRACE("SampGetObjectAttributeString failed (Status 0x%08lx)\n", Status); 7539 goto done; 7540 } 7541 7542 if (!RtlEqualUnicodeString(&OldUserName, (PCUNICODE_STRING)NewUserName, TRUE)) 7543 { 7544 Status = SampCheckAccountNameInDomain(UserObject->ParentObject, 7545 NewUserName->Buffer); 7546 if (!NT_SUCCESS(Status)) 7547 { 7548 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n", 7549 NewUserName->Buffer, Status); 7550 goto done; 7551 } 7552 } 7553 7554 Status = SampSetAccountNameInDomain(UserObject->ParentObject, 7555 L"Users", 7556 NewUserName->Buffer, 7557 UserObject->RelativeId); 7558 if (!NT_SUCCESS(Status)) 7559 { 7560 TRACE("SampSetAccountNameInDomain failed (Status 0x%08lx)\n", Status); 7561 goto done; 7562 } 7563 7564 Status = SampRemoveAccountNameFromDomain(UserObject->ParentObject, 7565 L"Users", 7566 OldUserName.Buffer); 7567 if (!NT_SUCCESS(Status)) 7568 { 7569 TRACE("SampRemoveAccountNameFromDomain failed (Status 0x%08lx)\n", Status); 7570 goto done; 7571 } 7572 7573 Status = SampSetObjectAttributeString(UserObject, 7574 L"Name", 7575 NewUserName); 7576 if (!NT_SUCCESS(Status)) 7577 { 7578 TRACE("SampSetObjectAttribute failed (Status 0x%08lx)\n", Status); 7579 } 7580 7581 done: 7582 if (OldUserName.Buffer != NULL) 7583 midl_user_free(OldUserName.Buffer); 7584 7585 return Status; 7586 } 7587 7588 7589 static NTSTATUS 7590 SampSetUserGeneral(PSAM_DB_OBJECT UserObject, 7591 PSAMPR_USER_INFO_BUFFER Buffer) 7592 { 7593 SAM_USER_FIXED_DATA FixedData; 7594 ULONG Length = 0; 7595 NTSTATUS Status; 7596 7597 Length = sizeof(SAM_USER_FIXED_DATA); 7598 Status = SampGetObjectAttribute(UserObject, 7599 L"F", 7600 NULL, 7601 (PVOID)&FixedData, 7602 &Length); 7603 if (!NT_SUCCESS(Status)) 7604 goto done; 7605 7606 FixedData.PrimaryGroupId = Buffer->General.PrimaryGroupId; 7607 7608 Status = SampSetObjectAttribute(UserObject, 7609 L"F", 7610 REG_BINARY, 7611 &FixedData, 7612 Length); 7613 if (!NT_SUCCESS(Status)) 7614 goto done; 7615 7616 Status = SampSetUserName(UserObject, 7617 &Buffer->General.UserName); 7618 if (!NT_SUCCESS(Status)) 7619 goto done; 7620 7621 Status = SampSetObjectAttributeString(UserObject, 7622 L"FullName", 7623 &Buffer->General.FullName); 7624 if (!NT_SUCCESS(Status)) 7625 goto done; 7626 7627 Status = SampSetObjectAttributeString(UserObject, 7628 L"AdminComment", 7629 &Buffer->General.AdminComment); 7630 if (!NT_SUCCESS(Status)) 7631 goto done; 7632 7633 Status = SampSetObjectAttributeString(UserObject, 7634 L"UserComment", 7635 &Buffer->General.UserComment); 7636 7637 done: 7638 return Status; 7639 } 7640 7641 7642 static NTSTATUS 7643 SampSetUserPreferences(PSAM_DB_OBJECT UserObject, 7644 PSAMPR_USER_INFO_BUFFER Buffer) 7645 { 7646 SAM_USER_FIXED_DATA FixedData; 7647 ULONG Length = 0; 7648 NTSTATUS Status; 7649 7650 Length = sizeof(SAM_USER_FIXED_DATA); 7651 Status = SampGetObjectAttribute(UserObject, 7652 L"F", 7653 NULL, 7654 (PVOID)&FixedData, 7655 &Length); 7656 if (!NT_SUCCESS(Status)) 7657 goto done; 7658 7659 FixedData.CountryCode = Buffer->Preferences.CountryCode; 7660 FixedData.CodePage = Buffer->Preferences.CodePage; 7661 7662 Status = SampSetObjectAttribute(UserObject, 7663 L"F", 7664 REG_BINARY, 7665 &FixedData, 7666 Length); 7667 if (!NT_SUCCESS(Status)) 7668 goto done; 7669 7670 Status = SampSetObjectAttributeString(UserObject, 7671 L"UserComment", 7672 &Buffer->Preferences.UserComment); 7673 7674 done: 7675 return Status; 7676 } 7677 7678 7679 static NTSTATUS 7680 SampSetUserPrimaryGroup(PSAM_DB_OBJECT UserObject, 7681 PSAMPR_USER_INFO_BUFFER Buffer) 7682 { 7683 SAM_USER_FIXED_DATA FixedData; 7684 ULONG Length = 0; 7685 NTSTATUS Status; 7686 7687 Length = sizeof(SAM_USER_FIXED_DATA); 7688 Status = SampGetObjectAttribute(UserObject, 7689 L"F", 7690 NULL, 7691 (PVOID)&FixedData, 7692 &Length); 7693 if (!NT_SUCCESS(Status)) 7694 goto done; 7695 7696 FixedData.PrimaryGroupId = Buffer->PrimaryGroup.PrimaryGroupId; 7697 7698 Status = SampSetObjectAttribute(UserObject, 7699 L"F", 7700 REG_BINARY, 7701 &FixedData, 7702 Length); 7703 7704 done: 7705 return Status; 7706 } 7707 7708 7709 static NTSTATUS 7710 SampSetUserControl(PSAM_DB_OBJECT UserObject, 7711 PSAMPR_USER_INFO_BUFFER Buffer) 7712 { 7713 SAM_USER_FIXED_DATA FixedData; 7714 ULONG Length = 0; 7715 NTSTATUS Status; 7716 7717 Length = sizeof(SAM_USER_FIXED_DATA); 7718 Status = SampGetObjectAttribute(UserObject, 7719 L"F", 7720 NULL, 7721 (PVOID)&FixedData, 7722 &Length); 7723 if (!NT_SUCCESS(Status)) 7724 goto done; 7725 7726 FixedData.UserAccountControl = Buffer->Control.UserAccountControl; 7727 7728 Status = SampSetObjectAttribute(UserObject, 7729 L"F", 7730 REG_BINARY, 7731 &FixedData, 7732 Length); 7733 7734 done: 7735 return Status; 7736 } 7737 7738 7739 static NTSTATUS 7740 SampSetUserExpires(PSAM_DB_OBJECT UserObject, 7741 PSAMPR_USER_INFO_BUFFER Buffer) 7742 { 7743 SAM_USER_FIXED_DATA FixedData; 7744 ULONG Length = 0; 7745 NTSTATUS Status; 7746 7747 Length = sizeof(SAM_USER_FIXED_DATA); 7748 Status = SampGetObjectAttribute(UserObject, 7749 L"F", 7750 NULL, 7751 (PVOID)&FixedData, 7752 &Length); 7753 if (!NT_SUCCESS(Status)) 7754 goto done; 7755 7756 FixedData.AccountExpires.LowPart = Buffer->Expires.AccountExpires.LowPart; 7757 FixedData.AccountExpires.HighPart = Buffer->Expires.AccountExpires.HighPart; 7758 7759 Status = SampSetObjectAttribute(UserObject, 7760 L"F", 7761 REG_BINARY, 7762 &FixedData, 7763 Length); 7764 7765 done: 7766 return Status; 7767 } 7768 7769 7770 static NTSTATUS 7771 SampSetUserInternal1(PSAM_DB_OBJECT UserObject, 7772 PSAMPR_USER_INFO_BUFFER Buffer) 7773 { 7774 SAM_USER_FIXED_DATA FixedData; 7775 ULONG Length = 0; 7776 NTSTATUS Status = STATUS_SUCCESS; 7777 7778 /* FIXME: Decrypt NT password */ 7779 /* FIXME: Decrypt LM password */ 7780 7781 Status = SampSetUserPassword(UserObject, 7782 &Buffer->Internal1.EncryptedNtOwfPassword, 7783 Buffer->Internal1.NtPasswordPresent, 7784 &Buffer->Internal1.EncryptedLmOwfPassword, 7785 Buffer->Internal1.LmPasswordPresent); 7786 if (!NT_SUCCESS(Status)) 7787 goto done; 7788 7789 /* Get the fixed user attributes */ 7790 Length = sizeof(SAM_USER_FIXED_DATA); 7791 Status = SampGetObjectAttribute(UserObject, 7792 L"F", 7793 NULL, 7794 (PVOID)&FixedData, 7795 &Length); 7796 if (!NT_SUCCESS(Status)) 7797 goto done; 7798 7799 if (Buffer->Internal1.PasswordExpired) 7800 { 7801 /* The password was last set ages ago */ 7802 FixedData.PasswordLastSet.LowPart = 0; 7803 FixedData.PasswordLastSet.HighPart = 0; 7804 } 7805 else 7806 { 7807 /* The password was last set right now */ 7808 Status = NtQuerySystemTime(&FixedData.PasswordLastSet); 7809 if (!NT_SUCCESS(Status)) 7810 goto done; 7811 } 7812 7813 /* Set the fixed user attributes */ 7814 Status = SampSetObjectAttribute(UserObject, 7815 L"F", 7816 REG_BINARY, 7817 &FixedData, 7818 Length); 7819 7820 done: 7821 return Status; 7822 } 7823 7824 7825 static NTSTATUS 7826 SampSetUserInternal2(PSAM_DB_OBJECT UserObject, 7827 PSAMPR_USER_INFO_BUFFER Buffer) 7828 { 7829 SAM_USER_FIXED_DATA FixedData; 7830 ULONG Length = 0; 7831 NTSTATUS Status = STATUS_SUCCESS; 7832 7833 /* Get the fixed user attributes */ 7834 Length = sizeof(SAM_USER_FIXED_DATA); 7835 Status = SampGetObjectAttribute(UserObject, 7836 L"F", 7837 NULL, 7838 (PVOID)&FixedData, 7839 &Length); 7840 if (!NT_SUCCESS(Status)) 7841 goto done; 7842 7843 if ((Buffer->Internal2.Flags & USER_LOGON_SUCCESS) && 7844 ((Buffer->Internal2.Flags & ~USER_LOGON_SUCCESS) == 0)) 7845 { 7846 /* Update the LastLogon time */ 7847 Status = NtQuerySystemTime(&FixedData.LastLogon); 7848 if (!NT_SUCCESS(Status)) 7849 goto done; 7850 7851 FixedData.LogonCount++; 7852 FixedData.BadPasswordCount = 0; 7853 } 7854 7855 if ((Buffer->Internal2.Flags & USER_LOGON_BAD_PASSWORD) && 7856 ((Buffer->Internal2.Flags & ~USER_LOGON_BAD_PASSWORD) == 0)) 7857 { 7858 /* Update the LastBadPasswordTime */ 7859 Status = NtQuerySystemTime(&FixedData.LastBadPasswordTime); 7860 if (!NT_SUCCESS(Status)) 7861 goto done; 7862 7863 FixedData.BadPasswordCount++; 7864 } 7865 7866 /* Set the fixed user attributes */ 7867 Status = SampSetObjectAttribute(UserObject, 7868 L"F", 7869 REG_BINARY, 7870 &FixedData, 7871 Length); 7872 7873 done: 7874 return Status; 7875 } 7876 7877 7878 static NTSTATUS 7879 SampSetUserAll(PSAM_DB_OBJECT UserObject, 7880 PSAMPR_USER_INFO_BUFFER Buffer) 7881 { 7882 SAM_USER_FIXED_DATA FixedData; 7883 ULONG Length = 0; 7884 ULONG WhichFields; 7885 PENCRYPTED_NT_OWF_PASSWORD NtPassword = NULL; 7886 PENCRYPTED_LM_OWF_PASSWORD LmPassword = NULL; 7887 BOOLEAN NtPasswordPresent = FALSE; 7888 BOOLEAN LmPasswordPresent = FALSE; 7889 BOOLEAN WriteFixedData = FALSE; 7890 NTSTATUS Status = STATUS_SUCCESS; 7891 7892 WhichFields = Buffer->All.WhichFields; 7893 7894 /* Get the fixed size attributes */ 7895 Length = sizeof(SAM_USER_FIXED_DATA); 7896 Status = SampGetObjectAttribute(UserObject, 7897 L"F", 7898 NULL, 7899 (PVOID)&FixedData, 7900 &Length); 7901 if (!NT_SUCCESS(Status)) 7902 goto done; 7903 7904 if (WhichFields & USER_ALL_USERNAME) 7905 { 7906 Status = SampSetUserName(UserObject, 7907 &Buffer->All.UserName); 7908 if (!NT_SUCCESS(Status)) 7909 goto done; 7910 } 7911 7912 if (WhichFields & USER_ALL_FULLNAME) 7913 { 7914 Status = SampSetObjectAttributeString(UserObject, 7915 L"FullName", 7916 &Buffer->All.FullName); 7917 if (!NT_SUCCESS(Status)) 7918 goto done; 7919 } 7920 7921 if (WhichFields & USER_ALL_ADMINCOMMENT) 7922 { 7923 Status = SampSetObjectAttributeString(UserObject, 7924 L"AdminComment", 7925 &Buffer->All.AdminComment); 7926 if (!NT_SUCCESS(Status)) 7927 goto done; 7928 } 7929 7930 if (WhichFields & USER_ALL_USERCOMMENT) 7931 { 7932 Status = SampSetObjectAttributeString(UserObject, 7933 L"UserComment", 7934 &Buffer->All.UserComment); 7935 if (!NT_SUCCESS(Status)) 7936 goto done; 7937 } 7938 7939 if (WhichFields & USER_ALL_HOMEDIRECTORY) 7940 { 7941 Status = SampSetObjectAttributeString(UserObject, 7942 L"HomeDirectory", 7943 &Buffer->All.HomeDirectory); 7944 if (!NT_SUCCESS(Status)) 7945 goto done; 7946 } 7947 7948 if (WhichFields & USER_ALL_HOMEDIRECTORYDRIVE) 7949 { 7950 Status = SampSetObjectAttributeString(UserObject, 7951 L"HomeDirectoryDrive", 7952 &Buffer->All.HomeDirectoryDrive); 7953 if (!NT_SUCCESS(Status)) 7954 goto done; 7955 } 7956 7957 if (WhichFields & USER_ALL_SCRIPTPATH) 7958 { 7959 Status = SampSetObjectAttributeString(UserObject, 7960 L"ScriptPath", 7961 &Buffer->All.ScriptPath); 7962 if (!NT_SUCCESS(Status)) 7963 goto done; 7964 } 7965 7966 if (WhichFields & USER_ALL_PROFILEPATH) 7967 { 7968 Status = SampSetObjectAttributeString(UserObject, 7969 L"ProfilePath", 7970 &Buffer->All.ProfilePath); 7971 if (!NT_SUCCESS(Status)) 7972 goto done; 7973 } 7974 7975 if (WhichFields & USER_ALL_WORKSTATIONS) 7976 { 7977 Status = SampSetObjectAttributeString(UserObject, 7978 L"WorkStations", 7979 &Buffer->All.WorkStations); 7980 if (!NT_SUCCESS(Status)) 7981 goto done; 7982 } 7983 7984 if (WhichFields & USER_ALL_PARAMETERS) 7985 { 7986 Status = SampSetObjectAttributeString(UserObject, 7987 L"Parameters", 7988 &Buffer->All.Parameters); 7989 if (!NT_SUCCESS(Status)) 7990 goto done; 7991 } 7992 7993 if (WhichFields & USER_ALL_LOGONHOURS) 7994 { 7995 Status = SampSetLogonHoursAttribute(UserObject, 7996 &Buffer->All.LogonHours); 7997 if (!NT_SUCCESS(Status)) 7998 goto done; 7999 } 8000 8001 if (WhichFields & USER_ALL_PRIMARYGROUPID) 8002 { 8003 FixedData.PrimaryGroupId = Buffer->All.PrimaryGroupId; 8004 WriteFixedData = TRUE; 8005 } 8006 8007 if (WhichFields & USER_ALL_ACCOUNTEXPIRES) 8008 { 8009 FixedData.AccountExpires.LowPart = Buffer->All.AccountExpires.LowPart; 8010 FixedData.AccountExpires.HighPart = Buffer->All.AccountExpires.HighPart; 8011 WriteFixedData = TRUE; 8012 } 8013 8014 if (WhichFields & USER_ALL_USERACCOUNTCONTROL) 8015 { 8016 FixedData.UserAccountControl = Buffer->All.UserAccountControl; 8017 WriteFixedData = TRUE; 8018 } 8019 8020 if (WhichFields & USER_ALL_COUNTRYCODE) 8021 { 8022 FixedData.CountryCode = Buffer->All.CountryCode; 8023 WriteFixedData = TRUE; 8024 } 8025 8026 if (WhichFields & USER_ALL_CODEPAGE) 8027 { 8028 FixedData.CodePage = Buffer->All.CodePage; 8029 WriteFixedData = TRUE; 8030 } 8031 8032 if (WhichFields & (USER_ALL_NTPASSWORDPRESENT | 8033 USER_ALL_LMPASSWORDPRESENT)) 8034 { 8035 if (WhichFields & USER_ALL_NTPASSWORDPRESENT) 8036 { 8037 NtPassword = (PENCRYPTED_NT_OWF_PASSWORD)Buffer->All.NtOwfPassword.Buffer; 8038 NtPasswordPresent = Buffer->All.NtPasswordPresent; 8039 } 8040 8041 if (WhichFields & USER_ALL_LMPASSWORDPRESENT) 8042 { 8043 LmPassword = (PENCRYPTED_LM_OWF_PASSWORD)Buffer->All.LmOwfPassword.Buffer; 8044 LmPasswordPresent = Buffer->All.LmPasswordPresent; 8045 } 8046 8047 Status = SampSetUserPassword(UserObject, 8048 NtPassword, 8049 NtPasswordPresent, 8050 LmPassword, 8051 LmPasswordPresent); 8052 if (!NT_SUCCESS(Status)) 8053 goto done; 8054 8055 /* The password has just been set */ 8056 Status = NtQuerySystemTime(&FixedData.PasswordLastSet); 8057 if (!NT_SUCCESS(Status)) 8058 goto done; 8059 8060 WriteFixedData = TRUE; 8061 } 8062 8063 if (WhichFields & USER_ALL_PRIVATEDATA) 8064 { 8065 Status = SampSetObjectAttributeString(UserObject, 8066 L"PrivateData", 8067 &Buffer->All.PrivateData); 8068 if (!NT_SUCCESS(Status)) 8069 goto done; 8070 } 8071 8072 if (WhichFields & USER_ALL_PASSWORDEXPIRED) 8073 { 8074 if (Buffer->All.PasswordExpired) 8075 { 8076 /* The password was last set ages ago */ 8077 FixedData.PasswordLastSet.LowPart = 0; 8078 FixedData.PasswordLastSet.HighPart = 0; 8079 } 8080 else 8081 { 8082 /* The password was last set right now */ 8083 Status = NtQuerySystemTime(&FixedData.PasswordLastSet); 8084 if (!NT_SUCCESS(Status)) 8085 goto done; 8086 } 8087 8088 WriteFixedData = TRUE; 8089 } 8090 8091 if (WhichFields & USER_ALL_SECURITYDESCRIPTOR) 8092 { 8093 Status = SampSetObjectAttribute(UserObject, 8094 L"SecDesc", 8095 REG_BINARY, 8096 Buffer->All.SecurityDescriptor.SecurityDescriptor, 8097 Buffer->All.SecurityDescriptor.Length); 8098 } 8099 8100 if (WriteFixedData != FALSE) 8101 { 8102 Status = SampSetObjectAttribute(UserObject, 8103 L"F", 8104 REG_BINARY, 8105 &FixedData, 8106 Length); 8107 if (!NT_SUCCESS(Status)) 8108 goto done; 8109 } 8110 8111 done: 8112 return Status; 8113 } 8114 8115 8116 /* Function 37 */ 8117 NTSTATUS 8118 NTAPI 8119 SamrSetInformationUser(IN SAMPR_HANDLE UserHandle, 8120 IN USER_INFORMATION_CLASS UserInformationClass, 8121 IN PSAMPR_USER_INFO_BUFFER Buffer) 8122 { 8123 PSAM_DB_OBJECT UserObject; 8124 ACCESS_MASK DesiredAccess; 8125 NTSTATUS Status; 8126 8127 TRACE("SamrSetInformationUser(%p %lu %p)\n", 8128 UserHandle, UserInformationClass, Buffer); 8129 8130 switch (UserInformationClass) 8131 { 8132 case UserLogonHoursInformation: 8133 case UserNameInformation: 8134 case UserAccountNameInformation: 8135 case UserFullNameInformation: 8136 case UserPrimaryGroupInformation: 8137 case UserHomeInformation: 8138 case UserScriptInformation: 8139 case UserProfileInformation: 8140 case UserAdminCommentInformation: 8141 case UserWorkStationsInformation: 8142 case UserControlInformation: 8143 case UserExpiresInformation: 8144 case UserParametersInformation: 8145 DesiredAccess = USER_WRITE_ACCOUNT; 8146 break; 8147 8148 case UserGeneralInformation: 8149 DesiredAccess = USER_WRITE_ACCOUNT | 8150 USER_WRITE_PREFERENCES; 8151 break; 8152 8153 case UserPreferencesInformation: 8154 DesiredAccess = USER_WRITE_PREFERENCES; 8155 break; 8156 8157 case UserSetPasswordInformation: 8158 case UserInternal1Information: 8159 DesiredAccess = USER_FORCE_PASSWORD_CHANGE; 8160 break; 8161 8162 case UserAllInformation: 8163 case UserInternal2Information: 8164 DesiredAccess = 0; /* FIXME */ 8165 break; 8166 8167 default: 8168 return STATUS_INVALID_INFO_CLASS; 8169 } 8170 8171 RtlAcquireResourceExclusive(&SampResource, 8172 TRUE); 8173 8174 /* Validate the domain handle */ 8175 Status = SampValidateDbObject(UserHandle, 8176 SamDbUserObject, 8177 DesiredAccess, 8178 &UserObject); 8179 if (!NT_SUCCESS(Status)) 8180 { 8181 TRACE("failed with status 0x%08lx\n", Status); 8182 goto done; 8183 } 8184 8185 switch (UserInformationClass) 8186 { 8187 case UserGeneralInformation: 8188 Status = SampSetUserGeneral(UserObject, 8189 Buffer); 8190 break; 8191 8192 case UserPreferencesInformation: 8193 Status = SampSetUserPreferences(UserObject, 8194 Buffer); 8195 break; 8196 8197 case UserLogonHoursInformation: 8198 Status = SampSetLogonHoursAttribute(UserObject, 8199 &Buffer->LogonHours.LogonHours); 8200 break; 8201 8202 case UserNameInformation: 8203 Status = SampSetUserName(UserObject, 8204 &Buffer->Name.UserName); 8205 if (!NT_SUCCESS(Status)) 8206 break; 8207 8208 Status = SampSetObjectAttributeString(UserObject, 8209 L"FullName", 8210 &Buffer->Name.FullName); 8211 break; 8212 8213 case UserAccountNameInformation: 8214 Status = SampSetUserName(UserObject, 8215 &Buffer->AccountName.UserName); 8216 break; 8217 8218 case UserFullNameInformation: 8219 Status = SampSetObjectAttributeString(UserObject, 8220 L"FullName", 8221 &Buffer->FullName.FullName); 8222 break; 8223 8224 case UserPrimaryGroupInformation: 8225 Status = SampSetUserPrimaryGroup(UserObject, 8226 Buffer); 8227 break; 8228 8229 case UserHomeInformation: 8230 Status = SampSetObjectAttributeString(UserObject, 8231 L"HomeDirectory", 8232 &Buffer->Home.HomeDirectory); 8233 if (!NT_SUCCESS(Status)) 8234 break; 8235 8236 Status = SampSetObjectAttributeString(UserObject, 8237 L"HomeDirectoryDrive", 8238 &Buffer->Home.HomeDirectoryDrive); 8239 break; 8240 8241 case UserScriptInformation: 8242 Status = SampSetObjectAttributeString(UserObject, 8243 L"ScriptPath", 8244 &Buffer->Script.ScriptPath); 8245 break; 8246 8247 case UserProfileInformation: 8248 Status = SampSetObjectAttributeString(UserObject, 8249 L"ProfilePath", 8250 &Buffer->Profile.ProfilePath); 8251 break; 8252 8253 case UserAdminCommentInformation: 8254 Status = SampSetObjectAttributeString(UserObject, 8255 L"AdminComment", 8256 &Buffer->AdminComment.AdminComment); 8257 break; 8258 8259 case UserWorkStationsInformation: 8260 Status = SampSetObjectAttributeString(UserObject, 8261 L"WorkStations", 8262 &Buffer->WorkStations.WorkStations); 8263 break; 8264 8265 case UserSetPasswordInformation: 8266 TRACE("Password: %S\n", Buffer->SetPassword.Password.Buffer); 8267 TRACE("PasswordExpired: %d\n", Buffer->SetPassword.PasswordExpired); 8268 8269 Status = SampSetObjectAttributeString(UserObject, 8270 L"Password", 8271 &Buffer->SetPassword.Password); 8272 break; 8273 8274 case UserControlInformation: 8275 Status = SampSetUserControl(UserObject, 8276 Buffer); 8277 break; 8278 8279 case UserExpiresInformation: 8280 Status = SampSetUserExpires(UserObject, 8281 Buffer); 8282 break; 8283 8284 case UserInternal1Information: 8285 Status = SampSetUserInternal1(UserObject, 8286 Buffer); 8287 break; 8288 8289 case UserInternal2Information: 8290 Status = SampSetUserInternal2(UserObject, 8291 Buffer); 8292 break; 8293 8294 case UserParametersInformation: 8295 Status = SampSetObjectAttributeString(UserObject, 8296 L"Parameters", 8297 &Buffer->Parameters.Parameters); 8298 break; 8299 8300 case UserAllInformation: 8301 Status = SampSetUserAll(UserObject, 8302 Buffer); 8303 break; 8304 8305 // case UserInternal4Information: 8306 // case UserInternal5Information: 8307 // case UserInternal4InformationNew: 8308 // case UserInternal5InformationNew: 8309 8310 default: 8311 Status = STATUS_INVALID_INFO_CLASS; 8312 } 8313 8314 done: 8315 RtlReleaseResource(&SampResource); 8316 8317 return Status; 8318 } 8319 8320 8321 /* Function 38 */ 8322 NTSTATUS 8323 NTAPI 8324 SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle, 8325 IN unsigned char LmPresent, 8326 IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm, 8327 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm, 8328 IN unsigned char NtPresent, 8329 IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt, 8330 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt, 8331 IN unsigned char NtCrossEncryptionPresent, 8332 IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm, 8333 IN unsigned char LmCrossEncryptionPresent, 8334 IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt) 8335 { 8336 ENCRYPTED_LM_OWF_PASSWORD StoredLmPassword; 8337 ENCRYPTED_NT_OWF_PASSWORD StoredNtPassword; 8338 LM_OWF_PASSWORD OldLmPassword; 8339 LM_OWF_PASSWORD NewLmPassword; 8340 NT_OWF_PASSWORD OldNtPassword; 8341 NT_OWF_PASSWORD NewNtPassword; 8342 BOOLEAN StoredLmPresent = FALSE; 8343 BOOLEAN StoredNtPresent = FALSE; 8344 BOOLEAN StoredLmEmpty = TRUE; 8345 BOOLEAN StoredNtEmpty = TRUE; 8346 PSAM_DB_OBJECT UserObject; 8347 ULONG Length; 8348 SAM_USER_FIXED_DATA UserFixedData; 8349 SAM_DOMAIN_FIXED_DATA DomainFixedData; 8350 LARGE_INTEGER SystemTime; 8351 NTSTATUS Status; 8352 8353 DBG_UNREFERENCED_LOCAL_VARIABLE(StoredLmPresent); 8354 DBG_UNREFERENCED_LOCAL_VARIABLE(StoredNtPresent); 8355 DBG_UNREFERENCED_LOCAL_VARIABLE(StoredLmEmpty); 8356 8357 TRACE("SamrChangePasswordUser(%p %u %p %p %u %p %p %u %p %u %p)\n", 8358 UserHandle, LmPresent, OldLmEncryptedWithNewLm, NewLmEncryptedWithOldLm, 8359 NtPresent, OldNtEncryptedWithNewNt, NewNtEncryptedWithOldNt, NtCrossEncryptionPresent, 8360 NewNtEncryptedWithNewLm, LmCrossEncryptionPresent, NewLmEncryptedWithNewNt); 8361 8362 RtlAcquireResourceExclusive(&SampResource, 8363 TRUE); 8364 8365 /* Validate the user handle */ 8366 Status = SampValidateDbObject(UserHandle, 8367 SamDbUserObject, 8368 USER_CHANGE_PASSWORD, 8369 &UserObject); 8370 if (!NT_SUCCESS(Status)) 8371 { 8372 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 8373 goto done; 8374 } 8375 8376 /* Get the current time */ 8377 Status = NtQuerySystemTime(&SystemTime); 8378 if (!NT_SUCCESS(Status)) 8379 { 8380 TRACE("NtQuerySystemTime failed (Status 0x%08lx)\n", Status); 8381 goto done; 8382 } 8383 8384 /* Retrieve the LM password */ 8385 Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD); 8386 Status = SampGetObjectAttribute(UserObject, 8387 L"LMPwd", 8388 NULL, 8389 &StoredLmPassword, 8390 &Length); 8391 if (NT_SUCCESS(Status)) 8392 { 8393 if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD)) 8394 { 8395 StoredLmPresent = TRUE; 8396 if (!RtlEqualMemory(&StoredLmPassword, 8397 &EmptyLmHash, 8398 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 8399 StoredLmEmpty = FALSE; 8400 } 8401 } 8402 8403 /* Retrieve the NT password */ 8404 Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD); 8405 Status = SampGetObjectAttribute(UserObject, 8406 L"NTPwd", 8407 NULL, 8408 &StoredNtPassword, 8409 &Length); 8410 if (NT_SUCCESS(Status)) 8411 { 8412 if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD)) 8413 { 8414 StoredNtPresent = TRUE; 8415 if (!RtlEqualMemory(&StoredNtPassword, 8416 &EmptyNtHash, 8417 sizeof(ENCRYPTED_NT_OWF_PASSWORD))) 8418 StoredNtEmpty = FALSE; 8419 } 8420 } 8421 8422 /* Retrieve the fixed size user data */ 8423 Length = sizeof(SAM_USER_FIXED_DATA); 8424 Status = SampGetObjectAttribute(UserObject, 8425 L"F", 8426 NULL, 8427 &UserFixedData, 8428 &Length); 8429 if (!NT_SUCCESS(Status)) 8430 { 8431 TRACE("SampGetObjectAttribute failed to retrieve the fixed user data (Status 0x%08lx)\n", Status); 8432 goto done; 8433 } 8434 8435 /* Check if we can change the password at this time */ 8436 if ((StoredLmEmpty == FALSE) || (StoredNtEmpty == FALSE)) 8437 { 8438 /* Get fixed domain data */ 8439 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 8440 Status = SampGetObjectAttribute(UserObject->ParentObject, 8441 L"F", 8442 NULL, 8443 &DomainFixedData, 8444 &Length); 8445 if (!NT_SUCCESS(Status)) 8446 { 8447 TRACE("SampGetObjectAttribute failed to retrieve the fixed domain data (Status 0x%08lx)\n", Status); 8448 goto done; 8449 } 8450 8451 if (DomainFixedData.MinPasswordAge.QuadPart > 0) 8452 { 8453 if (SystemTime.QuadPart < (UserFixedData.PasswordLastSet.QuadPart + DomainFixedData.MinPasswordAge.QuadPart)) 8454 { 8455 Status = STATUS_ACCOUNT_RESTRICTION; 8456 goto done; 8457 } 8458 } 8459 } 8460 8461 /* Decrypt the LM passwords, if present */ 8462 if (LmPresent) 8463 { 8464 Status = SystemFunction013((const BYTE *)NewLmEncryptedWithOldLm, 8465 (const BYTE *)&StoredLmPassword, 8466 (LPBYTE)&NewLmPassword); 8467 if (!NT_SUCCESS(Status)) 8468 { 8469 TRACE("SystemFunction013 failed (Status 0x%08lx)\n", Status); 8470 goto done; 8471 } 8472 8473 Status = SystemFunction013((const BYTE *)OldLmEncryptedWithNewLm, 8474 (const BYTE *)&NewLmPassword, 8475 (LPBYTE)&OldLmPassword); 8476 if (!NT_SUCCESS(Status)) 8477 { 8478 TRACE("SystemFunction013 failed (Status 0x%08lx)\n", Status); 8479 goto done; 8480 } 8481 } 8482 8483 /* Decrypt the NT passwords, if present */ 8484 if (NtPresent) 8485 { 8486 Status = SystemFunction013((const BYTE *)NewNtEncryptedWithOldNt, 8487 (const BYTE *)&StoredNtPassword, 8488 (LPBYTE)&NewNtPassword); 8489 if (!NT_SUCCESS(Status)) 8490 { 8491 TRACE("SystemFunction013 failed (Status 0x%08lx)\n", Status); 8492 goto done; 8493 } 8494 8495 Status = SystemFunction013((const BYTE *)OldNtEncryptedWithNewNt, 8496 (const BYTE *)&NewNtPassword, 8497 (LPBYTE)&OldNtPassword); 8498 if (!NT_SUCCESS(Status)) 8499 { 8500 TRACE("SystemFunction013 failed (Status 0x%08lx)\n", Status); 8501 goto done; 8502 } 8503 } 8504 8505 /* Check if the old passwords match the stored ones */ 8506 if (NtPresent) 8507 { 8508 if (LmPresent) 8509 { 8510 if (!RtlEqualMemory(&StoredLmPassword, 8511 &OldLmPassword, 8512 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 8513 { 8514 TRACE("Old LM Password does not match!\n"); 8515 Status = STATUS_WRONG_PASSWORD; 8516 } 8517 else 8518 { 8519 if (!RtlEqualMemory(&StoredNtPassword, 8520 &OldNtPassword, 8521 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 8522 { 8523 TRACE("Old NT Password does not match!\n"); 8524 Status = STATUS_WRONG_PASSWORD; 8525 } 8526 } 8527 } 8528 else 8529 { 8530 if (!RtlEqualMemory(&StoredNtPassword, 8531 &OldNtPassword, 8532 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 8533 { 8534 TRACE("Old NT Password does not match!\n"); 8535 Status = STATUS_WRONG_PASSWORD; 8536 } 8537 } 8538 } 8539 else 8540 { 8541 if (LmPresent) 8542 { 8543 if (!RtlEqualMemory(&StoredLmPassword, 8544 &OldLmPassword, 8545 sizeof(ENCRYPTED_LM_OWF_PASSWORD))) 8546 { 8547 TRACE("Old LM Password does not match!\n"); 8548 Status = STATUS_WRONG_PASSWORD; 8549 } 8550 } 8551 else 8552 { 8553 Status = STATUS_INVALID_PARAMETER; 8554 } 8555 } 8556 8557 /* Store the new password hashes */ 8558 if (NT_SUCCESS(Status)) 8559 { 8560 Status = SampSetUserPassword(UserObject, 8561 &NewNtPassword, 8562 NtPresent, 8563 &NewLmPassword, 8564 LmPresent); 8565 if (NT_SUCCESS(Status)) 8566 { 8567 /* Update PasswordLastSet */ 8568 UserFixedData.PasswordLastSet.QuadPart = SystemTime.QuadPart; 8569 8570 /* Set the fixed size user data */ 8571 Length = sizeof(SAM_USER_FIXED_DATA); 8572 Status = SampSetObjectAttribute(UserObject, 8573 L"F", 8574 REG_BINARY, 8575 &UserFixedData, 8576 Length); 8577 } 8578 } 8579 8580 if (Status == STATUS_WRONG_PASSWORD) 8581 { 8582 /* Update BadPasswordCount and LastBadPasswordTime */ 8583 UserFixedData.BadPasswordCount++; 8584 UserFixedData.LastBadPasswordTime.QuadPart = SystemTime.QuadPart; 8585 8586 /* Set the fixed size user data */ 8587 Length = sizeof(SAM_USER_FIXED_DATA); 8588 Status = SampSetObjectAttribute(UserObject, 8589 L"F", 8590 REG_BINARY, 8591 &UserFixedData, 8592 Length); 8593 } 8594 8595 done: 8596 RtlReleaseResource(&SampResource); 8597 8598 return Status; 8599 } 8600 8601 8602 /* Function 39 */ 8603 NTSTATUS 8604 NTAPI 8605 SamrGetGroupsForUser(IN SAMPR_HANDLE UserHandle, 8606 OUT PSAMPR_GET_GROUPS_BUFFER *Groups) 8607 { 8608 PSAMPR_GET_GROUPS_BUFFER GroupsBuffer = NULL; 8609 PSAM_DB_OBJECT UserObject; 8610 ULONG Length = 0; 8611 NTSTATUS Status; 8612 8613 TRACE("SamrGetGroupsForUser(%p %p)\n", 8614 UserHandle, Groups); 8615 8616 RtlAcquireResourceShared(&SampResource, 8617 TRUE); 8618 8619 /* Validate the user handle */ 8620 Status = SampValidateDbObject(UserHandle, 8621 SamDbUserObject, 8622 USER_LIST_GROUPS, 8623 &UserObject); 8624 if (!NT_SUCCESS(Status)) 8625 { 8626 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 8627 goto done; 8628 } 8629 8630 /* Allocate the groups buffer */ 8631 GroupsBuffer = midl_user_allocate(sizeof(SAMPR_GET_GROUPS_BUFFER)); 8632 if (GroupsBuffer == NULL) 8633 { 8634 Status = STATUS_INSUFFICIENT_RESOURCES; 8635 goto done; 8636 } 8637 8638 /* 8639 * Get the size of the Groups attribute. 8640 * Do not check the status code because in case of an error 8641 * Length will be 0. And that is all we need. 8642 */ 8643 SampGetObjectAttribute(UserObject, 8644 L"Groups", 8645 NULL, 8646 NULL, 8647 &Length); 8648 8649 /* If there is no Groups attribute, return a groups buffer without an array */ 8650 if (Length == 0) 8651 { 8652 GroupsBuffer->MembershipCount = 0; 8653 GroupsBuffer->Groups = NULL; 8654 8655 *Groups = GroupsBuffer; 8656 8657 Status = STATUS_SUCCESS; 8658 goto done; 8659 } 8660 8661 /* Allocate a buffer for the Groups attribute */ 8662 GroupsBuffer->Groups = midl_user_allocate(Length); 8663 if (GroupsBuffer->Groups == NULL) 8664 { 8665 Status = STATUS_INSUFFICIENT_RESOURCES; 8666 goto done; 8667 } 8668 8669 /* Retrieve the Grous attribute */ 8670 Status = SampGetObjectAttribute(UserObject, 8671 L"Groups", 8672 NULL, 8673 GroupsBuffer->Groups, 8674 &Length); 8675 if (!NT_SUCCESS(Status)) 8676 { 8677 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status); 8678 goto done; 8679 } 8680 8681 /* Calculate the membership count */ 8682 GroupsBuffer->MembershipCount = Length / sizeof(GROUP_MEMBERSHIP); 8683 8684 /* Return the groups buffer to the caller */ 8685 *Groups = GroupsBuffer; 8686 8687 done: 8688 if (!NT_SUCCESS(Status)) 8689 { 8690 if (GroupsBuffer != NULL) 8691 { 8692 if (GroupsBuffer->Groups != NULL) 8693 midl_user_free(GroupsBuffer->Groups); 8694 8695 midl_user_free(GroupsBuffer); 8696 } 8697 } 8698 8699 RtlReleaseResource(&SampResource); 8700 8701 return Status; 8702 } 8703 8704 8705 /* Function 40 */ 8706 NTSTATUS 8707 NTAPI 8708 SamrQueryDisplayInformation(IN SAMPR_HANDLE DomainHandle, 8709 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass, 8710 IN unsigned long Index, 8711 IN unsigned long EntryCount, 8712 IN unsigned long PreferredMaximumLength, 8713 OUT unsigned long *TotalAvailable, 8714 OUT unsigned long *TotalReturned, 8715 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer) 8716 { 8717 UNIMPLEMENTED; 8718 return STATUS_NOT_IMPLEMENTED; 8719 } 8720 8721 /* Function 41 */ 8722 NTSTATUS 8723 NTAPI 8724 SamrGetDisplayEnumerationIndex(IN SAMPR_HANDLE DomainHandle, 8725 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass, 8726 IN PRPC_UNICODE_STRING Prefix, 8727 OUT unsigned long *Index) 8728 { 8729 UNIMPLEMENTED; 8730 return STATUS_NOT_IMPLEMENTED; 8731 } 8732 8733 /* Function 42 */ 8734 NTSTATUS 8735 NTAPI 8736 SamrTestPrivateFunctionsDomain(IN SAMPR_HANDLE DomainHandle) 8737 { 8738 UNIMPLEMENTED; 8739 return STATUS_NOT_IMPLEMENTED; 8740 } 8741 8742 /* Function 43 */ 8743 NTSTATUS 8744 NTAPI 8745 SamrTestPrivateFunctionsUser(IN SAMPR_HANDLE UserHandle) 8746 { 8747 UNIMPLEMENTED; 8748 return STATUS_NOT_IMPLEMENTED; 8749 } 8750 8751 8752 /* Function 44 */ 8753 NTSTATUS 8754 NTAPI 8755 SamrGetUserDomainPasswordInformation(IN SAMPR_HANDLE UserHandle, 8756 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation) 8757 { 8758 SAM_DOMAIN_FIXED_DATA DomainFixedData; 8759 SAM_USER_FIXED_DATA UserFixedData; 8760 PSAM_DB_OBJECT DomainObject; 8761 PSAM_DB_OBJECT UserObject; 8762 ULONG Length = 0; 8763 NTSTATUS Status; 8764 8765 TRACE("SamrGetUserDomainPasswordInformation(%p %p)\n", 8766 UserHandle, PasswordInformation); 8767 8768 RtlAcquireResourceShared(&SampResource, 8769 TRUE); 8770 8771 /* Validate the user handle */ 8772 Status = SampValidateDbObject(UserHandle, 8773 SamDbUserObject, 8774 0, 8775 &UserObject); 8776 if (!NT_SUCCESS(Status)) 8777 { 8778 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 8779 goto done; 8780 } 8781 8782 /* Validate the domain object */ 8783 Status = SampValidateDbObject((SAMPR_HANDLE)UserObject->ParentObject, 8784 SamDbDomainObject, 8785 DOMAIN_READ_PASSWORD_PARAMETERS, 8786 &DomainObject); 8787 if (!NT_SUCCESS(Status)) 8788 { 8789 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 8790 goto done; 8791 } 8792 8793 /* Get fixed user data */ 8794 Length = sizeof(SAM_USER_FIXED_DATA); 8795 Status = SampGetObjectAttribute(UserObject, 8796 L"F", 8797 NULL, 8798 (PVOID)&UserFixedData, 8799 &Length); 8800 if (!NT_SUCCESS(Status)) 8801 { 8802 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status); 8803 goto done; 8804 } 8805 8806 if ((UserObject->RelativeId == DOMAIN_USER_RID_KRBTGT) || 8807 (UserFixedData.UserAccountControl & (USER_INTERDOMAIN_TRUST_ACCOUNT | 8808 USER_WORKSTATION_TRUST_ACCOUNT | 8809 USER_SERVER_TRUST_ACCOUNT))) 8810 { 8811 PasswordInformation->MinPasswordLength = 0; 8812 PasswordInformation->PasswordProperties = 0; 8813 } 8814 else 8815 { 8816 /* Get fixed domain data */ 8817 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 8818 Status = SampGetObjectAttribute(DomainObject, 8819 L"F", 8820 NULL, 8821 (PVOID)&DomainFixedData, 8822 &Length); 8823 if (!NT_SUCCESS(Status)) 8824 { 8825 TRACE("SampGetObjectAttribute failed with status 0x%08lx\n", Status); 8826 goto done; 8827 } 8828 8829 PasswordInformation->MinPasswordLength = DomainFixedData.MinPasswordLength; 8830 PasswordInformation->PasswordProperties = DomainFixedData.PasswordProperties; 8831 } 8832 8833 done: 8834 RtlReleaseResource(&SampResource); 8835 8836 return STATUS_SUCCESS; 8837 } 8838 8839 8840 /* Function 45 */ 8841 NTSTATUS 8842 NTAPI 8843 SamrRemoveMemberFromForeignDomain(IN SAMPR_HANDLE DomainHandle, 8844 IN PRPC_SID MemberSid) 8845 { 8846 PSAM_DB_OBJECT DomainObject; 8847 ULONG Rid = 0; 8848 NTSTATUS Status; 8849 8850 TRACE("SamrRemoveMemberFromForeignDomain(%p %p)\n", 8851 DomainHandle, MemberSid); 8852 8853 RtlAcquireResourceExclusive(&SampResource, 8854 TRUE); 8855 8856 /* Validate the domain object */ 8857 Status = SampValidateDbObject(DomainHandle, 8858 SamDbDomainObject, 8859 DOMAIN_LOOKUP, 8860 &DomainObject); 8861 if (!NT_SUCCESS(Status)) 8862 { 8863 TRACE("SampValidateDbObject failed with status 0x%08lx\n", Status); 8864 goto done; 8865 } 8866 8867 /* Retrieve the RID from the MemberSID */ 8868 Status = SampGetRidFromSid((PSID)MemberSid, 8869 &Rid); 8870 if (!NT_SUCCESS(Status)) 8871 { 8872 TRACE("SampGetRidFromSid failed with status 0x%08lx\n", Status); 8873 goto done; 8874 } 8875 8876 /* Fail, if the RID represents a special account */ 8877 if (Rid < 1000) 8878 { 8879 TRACE("Cannot remove a special account (RID: %lu)\n", Rid); 8880 Status = STATUS_SPECIAL_ACCOUNT; 8881 goto done; 8882 } 8883 8884 /* Remove the member from all aliases in the domain */ 8885 Status = SampRemoveMemberFromAllAliases(DomainObject, 8886 MemberSid); 8887 if (!NT_SUCCESS(Status)) 8888 { 8889 TRACE("SampRemoveMemberFromAllAliases failed with status 0x%08lx\n", Status); 8890 } 8891 8892 done: 8893 RtlReleaseResource(&SampResource); 8894 8895 return Status; 8896 } 8897 8898 8899 /* Function 46 */ 8900 NTSTATUS 8901 NTAPI 8902 SamrQueryInformationDomain2(IN SAMPR_HANDLE DomainHandle, 8903 IN DOMAIN_INFORMATION_CLASS DomainInformationClass, 8904 OUT PSAMPR_DOMAIN_INFO_BUFFER *Buffer) 8905 { 8906 TRACE("SamrQueryInformationDomain2(%p %lu %p)\n", 8907 DomainHandle, DomainInformationClass, Buffer); 8908 8909 return SamrQueryInformationDomain(DomainHandle, 8910 DomainInformationClass, 8911 Buffer); 8912 } 8913 8914 8915 /* Function 47 */ 8916 NTSTATUS 8917 NTAPI 8918 SamrQueryInformationUser2(IN SAMPR_HANDLE UserHandle, 8919 IN USER_INFORMATION_CLASS UserInformationClass, 8920 OUT PSAMPR_USER_INFO_BUFFER *Buffer) 8921 { 8922 TRACE("SamrQueryInformationUser2(%p %lu %p)\n", 8923 UserHandle, UserInformationClass, Buffer); 8924 8925 return SamrQueryInformationUser(UserHandle, 8926 UserInformationClass, 8927 Buffer); 8928 } 8929 8930 8931 /* Function 48 */ 8932 NTSTATUS 8933 NTAPI 8934 SamrQueryDisplayInformation2(IN SAMPR_HANDLE DomainHandle, 8935 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass, 8936 IN unsigned long Index, 8937 IN unsigned long EntryCount, 8938 IN unsigned long PreferredMaximumLength, 8939 OUT unsigned long *TotalAvailable, 8940 OUT unsigned long *TotalReturned, 8941 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer) 8942 { 8943 TRACE("SamrQueryDisplayInformation2(%p %lu %lu %lu %lu %p %p %p)\n", 8944 DomainHandle, DisplayInformationClass, Index, 8945 EntryCount, PreferredMaximumLength, TotalAvailable, 8946 TotalReturned, Buffer); 8947 8948 return SamrQueryDisplayInformation(DomainHandle, 8949 DisplayInformationClass, 8950 Index, 8951 EntryCount, 8952 PreferredMaximumLength, 8953 TotalAvailable, 8954 TotalReturned, 8955 Buffer); 8956 } 8957 8958 8959 /* Function 49 */ 8960 NTSTATUS 8961 NTAPI 8962 SamrGetDisplayEnumerationIndex2(IN SAMPR_HANDLE DomainHandle, 8963 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass, 8964 IN PRPC_UNICODE_STRING Prefix, 8965 OUT unsigned long *Index) 8966 { 8967 TRACE("SamrGetDisplayEnumerationIndex2(%p %lu %p %p)\n", 8968 DomainHandle, DisplayInformationClass, Prefix, Index); 8969 8970 return SamrGetDisplayEnumerationIndex(DomainHandle, 8971 DisplayInformationClass, 8972 Prefix, 8973 Index); 8974 } 8975 8976 8977 /* Function 50 */ 8978 NTSTATUS 8979 NTAPI 8980 SamrCreateUser2InDomain(IN SAMPR_HANDLE DomainHandle, 8981 IN PRPC_UNICODE_STRING Name, 8982 IN unsigned long AccountType, 8983 IN ACCESS_MASK DesiredAccess, 8984 OUT SAMPR_HANDLE *UserHandle, 8985 OUT unsigned long *GrantedAccess, 8986 OUT unsigned long *RelativeId) 8987 { 8988 SAM_DOMAIN_FIXED_DATA FixedDomainData; 8989 SAM_USER_FIXED_DATA FixedUserData; 8990 PSAM_DB_OBJECT DomainObject; 8991 PSAM_DB_OBJECT UserObject; 8992 GROUP_MEMBERSHIP GroupMembership; 8993 UCHAR LogonHours[23]; 8994 ULONG ulSize; 8995 ULONG ulRid; 8996 WCHAR szRid[9]; 8997 PSECURITY_DESCRIPTOR Sd = NULL; 8998 ULONG SdSize = 0; 8999 PSID UserSid = NULL; 9000 NTSTATUS Status; 9001 9002 TRACE("SamrCreateUserInDomain(%p %p %lx %p %p)\n", 9003 DomainHandle, Name, DesiredAccess, UserHandle, RelativeId); 9004 9005 if (Name == NULL || 9006 Name->Length == 0 || 9007 Name->Buffer == NULL || 9008 UserHandle == NULL || 9009 RelativeId == NULL) 9010 return STATUS_INVALID_PARAMETER; 9011 9012 /* Check for valid account type */ 9013 if (AccountType != USER_NORMAL_ACCOUNT && 9014 AccountType != USER_WORKSTATION_TRUST_ACCOUNT && 9015 AccountType != USER_INTERDOMAIN_TRUST_ACCOUNT && 9016 AccountType != USER_SERVER_TRUST_ACCOUNT && 9017 AccountType != USER_TEMP_DUPLICATE_ACCOUNT) 9018 return STATUS_INVALID_PARAMETER; 9019 9020 /* Map generic access rights */ 9021 RtlMapGenericMask(&DesiredAccess, 9022 &UserMapping); 9023 9024 RtlAcquireResourceExclusive(&SampResource, 9025 TRUE); 9026 9027 /* Validate the domain handle */ 9028 Status = SampValidateDbObject(DomainHandle, 9029 SamDbDomainObject, 9030 DOMAIN_CREATE_USER, 9031 &DomainObject); 9032 if (!NT_SUCCESS(Status)) 9033 { 9034 TRACE("failed with status 0x%08lx\n", Status); 9035 goto done; 9036 } 9037 9038 /* Check the user account name */ 9039 Status = SampCheckAccountName(Name, 20); 9040 if (!NT_SUCCESS(Status)) 9041 { 9042 TRACE("SampCheckAccountName failed (Status 0x%08lx)\n", Status); 9043 goto done; 9044 } 9045 9046 /* Check if the user name already exists in the domain */ 9047 Status = SampCheckAccountNameInDomain(DomainObject, 9048 Name->Buffer); 9049 if (!NT_SUCCESS(Status)) 9050 { 9051 TRACE("User name \'%S\' already exists in domain (Status 0x%08lx)\n", 9052 Name->Buffer, Status); 9053 goto done; 9054 } 9055 9056 /* Get the fixed domain attributes */ 9057 ulSize = sizeof(SAM_DOMAIN_FIXED_DATA); 9058 Status = SampGetObjectAttribute(DomainObject, 9059 L"F", 9060 NULL, 9061 (PVOID)&FixedDomainData, 9062 &ulSize); 9063 if (!NT_SUCCESS(Status)) 9064 { 9065 TRACE("failed with status 0x%08lx\n", Status); 9066 goto done; 9067 } 9068 9069 /* Increment the NextRid attribute */ 9070 ulRid = FixedDomainData.NextRid; 9071 FixedDomainData.NextRid++; 9072 9073 TRACE("RID: %lx\n", ulRid); 9074 9075 /* Create the user SID */ 9076 Status = SampCreateAccountSid(DomainObject, 9077 ulRid, 9078 &UserSid); 9079 if (!NT_SUCCESS(Status)) 9080 { 9081 TRACE("SampCreateAccountSid failed (Status 0x%08lx)\n", Status); 9082 goto done; 9083 } 9084 9085 /* Create the security descriptor */ 9086 Status = SampCreateUserSD(UserSid, 9087 &Sd, 9088 &SdSize); 9089 if (!NT_SUCCESS(Status)) 9090 { 9091 TRACE("SampCreateUserSD failed (Status 0x%08lx)\n", Status); 9092 goto done; 9093 } 9094 9095 /* Store the fixed domain attributes */ 9096 Status = SampSetObjectAttribute(DomainObject, 9097 L"F", 9098 REG_BINARY, 9099 &FixedDomainData, 9100 ulSize); 9101 if (!NT_SUCCESS(Status)) 9102 { 9103 TRACE("failed with status 0x%08lx\n", Status); 9104 goto done; 9105 } 9106 9107 /* Convert the RID into a string (hex) */ 9108 swprintf(szRid, L"%08lX", ulRid); 9109 9110 /* Create the user object */ 9111 Status = SampCreateDbObject(DomainObject, 9112 L"Users", 9113 szRid, 9114 ulRid, 9115 SamDbUserObject, 9116 DesiredAccess, 9117 &UserObject); 9118 if (!NT_SUCCESS(Status)) 9119 { 9120 TRACE("failed with status 0x%08lx\n", Status); 9121 goto done; 9122 } 9123 9124 /* Add the account name for the user object */ 9125 Status = SampSetAccountNameInDomain(DomainObject, 9126 L"Users", 9127 Name->Buffer, 9128 ulRid); 9129 if (!NT_SUCCESS(Status)) 9130 { 9131 TRACE("failed with status 0x%08lx\n", Status); 9132 goto done; 9133 } 9134 9135 /* Initialize fixed user data */ 9136 FixedUserData.Version = 1; 9137 FixedUserData.Reserved = 0; 9138 FixedUserData.LastLogon.QuadPart = 0; 9139 FixedUserData.LastLogoff.QuadPart = 0; 9140 FixedUserData.PasswordLastSet.QuadPart = 0; 9141 FixedUserData.AccountExpires.LowPart = MAXULONG; 9142 FixedUserData.AccountExpires.HighPart = MAXLONG; 9143 FixedUserData.LastBadPasswordTime.QuadPart = 0; 9144 FixedUserData.UserId = ulRid; 9145 FixedUserData.PrimaryGroupId = DOMAIN_GROUP_RID_USERS; 9146 FixedUserData.UserAccountControl = USER_ACCOUNT_DISABLED | 9147 USER_PASSWORD_NOT_REQUIRED | 9148 AccountType; 9149 FixedUserData.CountryCode = 0; 9150 FixedUserData.CodePage = 0; 9151 FixedUserData.BadPasswordCount = 0; 9152 FixedUserData.LogonCount = 0; 9153 FixedUserData.AdminCount = 0; 9154 FixedUserData.OperatorCount = 0; 9155 9156 /* Set fixed user data attribute */ 9157 Status = SampSetObjectAttribute(UserObject, 9158 L"F", 9159 REG_BINARY, 9160 (LPVOID)&FixedUserData, 9161 sizeof(SAM_USER_FIXED_DATA)); 9162 if (!NT_SUCCESS(Status)) 9163 { 9164 TRACE("failed with status 0x%08lx\n", Status); 9165 goto done; 9166 } 9167 9168 /* Set the Name attribute */ 9169 Status = SampSetObjectAttributeString(UserObject, 9170 L"Name", 9171 Name); 9172 if (!NT_SUCCESS(Status)) 9173 { 9174 TRACE("failed with status 0x%08lx\n", Status); 9175 goto done; 9176 } 9177 9178 /* Set the FullName attribute */ 9179 Status = SampSetObjectAttributeString(UserObject, 9180 L"FullName", 9181 NULL); 9182 if (!NT_SUCCESS(Status)) 9183 { 9184 TRACE("failed with status 0x%08lx\n", Status); 9185 goto done; 9186 } 9187 9188 /* Set the HomeDirectory attribute */ 9189 Status = SampSetObjectAttributeString(UserObject, 9190 L"HomeDirectory", 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 HomeDirectoryDrive attribute */ 9199 Status = SampSetObjectAttributeString(UserObject, 9200 L"HomeDirectoryDrive", 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 ScriptPath attribute */ 9209 Status = SampSetObjectAttributeString(UserObject, 9210 L"ScriptPath", 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 ProfilePath attribute */ 9219 Status = SampSetObjectAttributeString(UserObject, 9220 L"ProfilePath", 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 AdminComment attribute */ 9229 Status = SampSetObjectAttributeString(UserObject, 9230 L"AdminComment", 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 UserComment attribute */ 9239 Status = SampSetObjectAttributeString(UserObject, 9240 L"UserComment", 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 WorkStations attribute */ 9249 Status = SampSetObjectAttributeString(UserObject, 9250 L"WorkStations", 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 Parameters attribute */ 9259 Status = SampSetObjectAttributeString(UserObject, 9260 L"Parameters", 9261 NULL); 9262 if (!NT_SUCCESS(Status)) 9263 { 9264 TRACE("failed with status 0x%08lx\n", Status); 9265 goto done; 9266 } 9267 9268 /* Set LogonHours attribute*/ 9269 *((PUSHORT)LogonHours) = 168; 9270 memset(&(LogonHours[2]), 0xff, 21); 9271 9272 Status = SampSetObjectAttribute(UserObject, 9273 L"LogonHours", 9274 REG_BINARY, 9275 &LogonHours, 9276 sizeof(LogonHours)); 9277 if (!NT_SUCCESS(Status)) 9278 { 9279 TRACE("failed with status 0x%08lx\n", Status); 9280 goto done; 9281 } 9282 9283 /* Set Groups attribute*/ 9284 GroupMembership.RelativeId = DOMAIN_GROUP_RID_USERS; 9285 GroupMembership.Attributes = SE_GROUP_MANDATORY | 9286 SE_GROUP_ENABLED | 9287 SE_GROUP_ENABLED_BY_DEFAULT; 9288 9289 Status = SampSetObjectAttribute(UserObject, 9290 L"Groups", 9291 REG_BINARY, 9292 &GroupMembership, 9293 sizeof(GROUP_MEMBERSHIP)); 9294 if (!NT_SUCCESS(Status)) 9295 { 9296 TRACE("failed with status 0x%08lx\n", Status); 9297 goto done; 9298 } 9299 9300 /* Set LMPwd attribute*/ 9301 Status = SampSetObjectAttribute(UserObject, 9302 L"LMPwd", 9303 REG_BINARY, 9304 NULL, 9305 0); 9306 if (!NT_SUCCESS(Status)) 9307 { 9308 TRACE("failed with status 0x%08lx\n", Status); 9309 goto done; 9310 } 9311 9312 /* Set NTPwd attribute*/ 9313 Status = SampSetObjectAttribute(UserObject, 9314 L"NTPwd", 9315 REG_BINARY, 9316 NULL, 9317 0); 9318 if (!NT_SUCCESS(Status)) 9319 { 9320 TRACE("failed with status 0x%08lx\n", Status); 9321 goto done; 9322 } 9323 9324 /* Set LMPwdHistory attribute*/ 9325 Status = SampSetObjectAttribute(UserObject, 9326 L"LMPwdHistory", 9327 REG_BINARY, 9328 NULL, 9329 0); 9330 if (!NT_SUCCESS(Status)) 9331 { 9332 TRACE("failed with status 0x%08lx\n", Status); 9333 goto done; 9334 } 9335 9336 /* Set NTPwdHistory attribute*/ 9337 Status = SampSetObjectAttribute(UserObject, 9338 L"NTPwdHistory", 9339 REG_BINARY, 9340 NULL, 9341 0); 9342 if (!NT_SUCCESS(Status)) 9343 { 9344 TRACE("failed with status 0x%08lx\n", Status); 9345 goto done; 9346 } 9347 9348 /* Set the PrivateData attribute */ 9349 Status = SampSetObjectAttributeString(UserObject, 9350 L"PrivateData", 9351 NULL); 9352 if (!NT_SUCCESS(Status)) 9353 { 9354 TRACE("failed with status 0x%08lx\n", Status); 9355 goto done; 9356 } 9357 9358 /* Set the SecDesc attribute*/ 9359 Status = SampSetObjectAttribute(UserObject, 9360 L"SecDesc", 9361 REG_BINARY, 9362 Sd, 9363 SdSize); 9364 if (!NT_SUCCESS(Status)) 9365 { 9366 TRACE("failed with status 0x%08lx\n", Status); 9367 goto done; 9368 } 9369 9370 if (NT_SUCCESS(Status)) 9371 { 9372 *UserHandle = (SAMPR_HANDLE)UserObject; 9373 *RelativeId = ulRid; 9374 *GrantedAccess = UserObject->Access; 9375 } 9376 9377 done: 9378 if (Sd != NULL) 9379 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd); 9380 9381 if (UserSid != NULL) 9382 RtlFreeHeap(RtlGetProcessHeap(), 0, UserSid); 9383 9384 RtlReleaseResource(&SampResource); 9385 9386 TRACE("returns with status 0x%08lx\n", Status); 9387 9388 return Status; 9389 } 9390 9391 9392 /* Function 51 */ 9393 NTSTATUS 9394 NTAPI 9395 SamrQueryDisplayInformation3(IN SAMPR_HANDLE DomainHandle, 9396 IN DOMAIN_DISPLAY_INFORMATION DisplayInformationClass, 9397 IN unsigned long Index, 9398 IN unsigned long EntryCount, 9399 IN unsigned long PreferredMaximumLength, 9400 OUT unsigned long *TotalAvailable, 9401 OUT unsigned long *TotalReturned, 9402 OUT PSAMPR_DISPLAY_INFO_BUFFER Buffer) 9403 { 9404 TRACE("SamrQueryDisplayInformation3(%p %lu %lu %lu %lu %p %p %p)\n", 9405 DomainHandle, DisplayInformationClass, Index, 9406 EntryCount, PreferredMaximumLength, TotalAvailable, 9407 TotalReturned, Buffer); 9408 9409 return SamrQueryDisplayInformation(DomainHandle, 9410 DisplayInformationClass, 9411 Index, 9412 EntryCount, 9413 PreferredMaximumLength, 9414 TotalAvailable, 9415 TotalReturned, 9416 Buffer); 9417 } 9418 9419 9420 /* Function 52 */ 9421 NTSTATUS 9422 NTAPI 9423 SamrAddMultipleMembersToAlias(IN SAMPR_HANDLE AliasHandle, 9424 IN PSAMPR_PSID_ARRAY MembersBuffer) 9425 { 9426 ULONG i; 9427 NTSTATUS Status = STATUS_SUCCESS; 9428 9429 TRACE("SamrAddMultipleMembersToAlias(%p %p)\n", 9430 AliasHandle, MembersBuffer); 9431 9432 for (i = 0; i < MembersBuffer->Count; i++) 9433 { 9434 Status = SamrAddMemberToAlias(AliasHandle, 9435 ((PSID *)MembersBuffer->Sids)[i]); 9436 9437 if (Status == STATUS_MEMBER_IN_ALIAS) 9438 Status = STATUS_SUCCESS; 9439 9440 if (!NT_SUCCESS(Status)) 9441 break; 9442 } 9443 9444 return Status; 9445 } 9446 9447 9448 /* Function 53 */ 9449 NTSTATUS 9450 NTAPI 9451 SamrRemoveMultipleMembersFromAlias(IN SAMPR_HANDLE AliasHandle, 9452 IN PSAMPR_PSID_ARRAY MembersBuffer) 9453 { 9454 ULONG i; 9455 NTSTATUS Status = STATUS_SUCCESS; 9456 9457 TRACE("SamrRemoveMultipleMembersFromAlias(%p %p)\n", 9458 AliasHandle, MembersBuffer); 9459 9460 for (i = 0; i < MembersBuffer->Count; i++) 9461 { 9462 Status = SamrRemoveMemberFromAlias(AliasHandle, 9463 ((PSID *)MembersBuffer->Sids)[i]); 9464 9465 if (Status == STATUS_MEMBER_IN_ALIAS) 9466 Status = STATUS_SUCCESS; 9467 9468 if (!NT_SUCCESS(Status)) 9469 break; 9470 } 9471 9472 return Status; 9473 } 9474 9475 9476 /* Function 54 */ 9477 NTSTATUS 9478 NTAPI 9479 SamrOemChangePasswordUser2(IN handle_t BindingHandle, 9480 IN PRPC_STRING ServerName, 9481 IN PRPC_STRING UserName, 9482 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm, 9483 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewLm) 9484 { 9485 UNIMPLEMENTED; 9486 return STATUS_NOT_IMPLEMENTED; 9487 } 9488 9489 /* Function 55 */ 9490 NTSTATUS 9491 NTAPI 9492 SamrUnicodeChangePasswordUser2(IN handle_t BindingHandle, 9493 IN PRPC_UNICODE_STRING ServerName, 9494 IN PRPC_UNICODE_STRING UserName, 9495 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldNt, 9496 IN PENCRYPTED_NT_OWF_PASSWORD OldNtOwfPasswordEncryptedWithNewNt, 9497 IN unsigned char LmPresent, 9498 IN PSAMPR_ENCRYPTED_USER_PASSWORD NewPasswordEncryptedWithOldLm, 9499 IN PENCRYPTED_LM_OWF_PASSWORD OldLmOwfPasswordEncryptedWithNewNt) 9500 { 9501 UNIMPLEMENTED; 9502 return STATUS_NOT_IMPLEMENTED; 9503 } 9504 9505 9506 /* Function 56 */ 9507 NTSTATUS 9508 NTAPI 9509 SamrGetDomainPasswordInformation(IN handle_t BindingHandle, 9510 IN PRPC_UNICODE_STRING Unused, 9511 OUT PUSER_DOMAIN_PASSWORD_INFORMATION PasswordInformation) 9512 { 9513 SAMPR_HANDLE ServerHandle = NULL; 9514 PSAM_DB_OBJECT DomainObject = NULL; 9515 SAM_DOMAIN_FIXED_DATA FixedData; 9516 ULONG Length; 9517 NTSTATUS Status; 9518 9519 TRACE("SamrGetDomainPasswordInformation(%p %p %p)\n", 9520 BindingHandle, Unused, PasswordInformation); 9521 9522 Status = SamrConnect(NULL, 9523 &ServerHandle, 9524 SAM_SERVER_LOOKUP_DOMAIN); 9525 if (!NT_SUCCESS(Status)) 9526 { 9527 TRACE("SamrConnect() failed (Status 0x%08lx)\n", Status); 9528 goto done; 9529 } 9530 9531 Status = SampOpenDbObject((PSAM_DB_OBJECT)ServerHandle, 9532 L"Domains", 9533 L"Account", 9534 0, 9535 SamDbDomainObject, 9536 DOMAIN_READ_PASSWORD_PARAMETERS, 9537 &DomainObject); 9538 if (!NT_SUCCESS(Status)) 9539 { 9540 TRACE("SampOpenDbObject() failed (Status 0x%08lx)\n", Status); 9541 goto done; 9542 } 9543 9544 Length = sizeof(SAM_DOMAIN_FIXED_DATA); 9545 Status = SampGetObjectAttribute(DomainObject, 9546 L"F", 9547 NULL, 9548 &FixedData, 9549 &Length); 9550 if (!NT_SUCCESS(Status)) 9551 { 9552 TRACE("SampGetObjectAttribute() failed (Status 0x%08lx)\n", Status); 9553 goto done; 9554 } 9555 9556 PasswordInformation->MinPasswordLength = FixedData.MinPasswordLength; 9557 PasswordInformation->PasswordProperties = FixedData.PasswordProperties; 9558 9559 done: 9560 if (DomainObject != NULL) 9561 SampCloseDbObject(DomainObject); 9562 9563 if (ServerHandle != NULL) 9564 SamrCloseHandle(ServerHandle); 9565 9566 return Status; 9567 } 9568 9569 9570 /* Function 57 */ 9571 NTSTATUS 9572 NTAPI 9573 SamrConnect2(IN PSAMPR_SERVER_NAME ServerName, 9574 OUT SAMPR_HANDLE *ServerHandle, 9575 IN ACCESS_MASK DesiredAccess) 9576 { 9577 SAMPR_REVISION_INFO InRevisionInfo, OutRevisionInfo; 9578 ULONG OutVersion; 9579 9580 TRACE("SamrConnect2(%p %p %lx)\n", 9581 ServerName, ServerHandle, DesiredAccess); 9582 9583 InRevisionInfo.V1.Revision = 1; 9584 InRevisionInfo.V1.SupportedFeatures = 0; 9585 9586 return SamrConnect5(ServerName, 9587 DesiredAccess, 9588 1, 9589 &InRevisionInfo, 9590 &OutVersion, 9591 &OutRevisionInfo, 9592 ServerHandle); 9593 } 9594 9595 9596 /* Function 58 */ 9597 NTSTATUS 9598 NTAPI 9599 SamrSetInformationUser2(IN SAMPR_HANDLE UserHandle, 9600 IN USER_INFORMATION_CLASS UserInformationClass, 9601 IN PSAMPR_USER_INFO_BUFFER Buffer) 9602 { 9603 TRACE("SamrSetInformationUser2(%p %lu %p)\n", 9604 UserHandle, UserInformationClass, Buffer); 9605 9606 return SamrSetInformationUser(UserHandle, 9607 UserInformationClass, 9608 Buffer); 9609 } 9610 9611 9612 /* Function 59 */ 9613 NTSTATUS 9614 NTAPI 9615 SamrSetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */ 9616 { 9617 UNIMPLEMENTED; 9618 return STATUS_NOT_IMPLEMENTED; 9619 } 9620 9621 /* Function 60 */ 9622 NTSTATUS 9623 NTAPI 9624 SamrGetBootKeyInformation(IN handle_t BindingHandle) /* FIXME */ 9625 { 9626 UNIMPLEMENTED; 9627 return STATUS_NOT_IMPLEMENTED; 9628 } 9629 9630 /* Function 61 */ 9631 NTSTATUS 9632 NTAPI 9633 SamrConnect3(IN handle_t BindingHandle) /* FIXME */ 9634 { 9635 UNIMPLEMENTED; 9636 return STATUS_NOT_IMPLEMENTED; 9637 } 9638 9639 9640 /* Function 62 */ 9641 NTSTATUS 9642 NTAPI 9643 SamrConnect4(IN PSAMPR_SERVER_NAME ServerName, 9644 OUT SAMPR_HANDLE *ServerHandle, 9645 IN unsigned long ClientRevision, 9646 IN ACCESS_MASK DesiredAccess) 9647 { 9648 SAMPR_REVISION_INFO InRevisionInfo, OutRevisionInfo; 9649 ULONG OutVersion; 9650 9651 TRACE("SamrConnect4(%p %p %lu 0x%lx)\n", 9652 ServerName, ServerHandle, ClientRevision, DesiredAccess); 9653 9654 InRevisionInfo.V1.Revision = 2; 9655 InRevisionInfo.V1.SupportedFeatures = 0; 9656 9657 return SamrConnect5(ServerName, 9658 DesiredAccess, 9659 1, 9660 &InRevisionInfo, 9661 &OutVersion, 9662 &OutRevisionInfo, 9663 ServerHandle); 9664 } 9665 9666 9667 /* Function 63 */ 9668 NTSTATUS 9669 NTAPI 9670 SamrUnicodeChangePasswordUser3(IN handle_t BindingHandle) /* FIXME */ 9671 { 9672 UNIMPLEMENTED; 9673 return STATUS_NOT_IMPLEMENTED; 9674 } 9675 9676 9677 /* Function 64 */ 9678 NTSTATUS 9679 NTAPI 9680 SamrConnect5(IN PSAMPR_SERVER_NAME ServerName, 9681 IN ACCESS_MASK DesiredAccess, 9682 IN unsigned long InVersion, 9683 IN SAMPR_REVISION_INFO *InRevisionInfo, 9684 OUT unsigned long *OutVersion, 9685 OUT SAMPR_REVISION_INFO *OutRevisionInfo, 9686 OUT SAMPR_HANDLE *ServerHandle) 9687 { 9688 PSAM_DB_OBJECT ServerObject; 9689 NTSTATUS Status; 9690 9691 TRACE("SamrConnect5(%p 0x%lx %lu %p %p %p %p)\n", 9692 ServerName, DesiredAccess, InVersion, InRevisionInfo, 9693 OutVersion, OutRevisionInfo, ServerHandle); 9694 9695 if (InVersion != 1) 9696 return STATUS_NOT_SUPPORTED; 9697 9698 RtlAcquireResourceShared(&SampResource, 9699 TRUE); 9700 9701 /* Map generic access rights */ 9702 RtlMapGenericMask(&DesiredAccess, 9703 &ServerMapping); 9704 9705 /* Open the Server Object */ 9706 Status = SampOpenDbObject(NULL, 9707 NULL, 9708 L"SAM", 9709 0, 9710 SamDbServerObject, 9711 DesiredAccess, 9712 &ServerObject); 9713 if (NT_SUCCESS(Status)) 9714 { 9715 *OutVersion = 1; 9716 9717 OutRevisionInfo->V1.Revision = 3; 9718 OutRevisionInfo->V1.SupportedFeatures = 0; 9719 9720 *ServerHandle = (SAMPR_HANDLE)ServerObject; 9721 } 9722 9723 RtlReleaseResource(&SampResource); 9724 9725 TRACE("SamrConnect5 done (Status 0x%08lx)\n", Status); 9726 9727 return Status; 9728 } 9729 9730 9731 /* Function 65 */ 9732 NTSTATUS 9733 NTAPI 9734 SamrRidToSid(IN SAMPR_HANDLE ObjectHandle, 9735 IN unsigned long Rid, 9736 OUT PRPC_SID *Sid) 9737 { 9738 UNIMPLEMENTED; 9739 return STATUS_NOT_IMPLEMENTED; 9740 } 9741 9742 /* Function 66 */ 9743 NTSTATUS 9744 NTAPI 9745 SamrSetDSRMPassword(IN handle_t BindingHandle, 9746 IN PRPC_UNICODE_STRING Unused, 9747 IN unsigned long UserId, 9748 IN PENCRYPTED_NT_OWF_PASSWORD EncryptedNtOwfPassword) 9749 { 9750 UNIMPLEMENTED; 9751 return STATUS_NOT_IMPLEMENTED; 9752 } 9753 9754 /* Function 67 */ 9755 NTSTATUS 9756 NTAPI 9757 SamrValidatePassword(IN handle_t Handle, 9758 IN PASSWORD_POLICY_VALIDATION_TYPE ValidationType, 9759 IN PSAM_VALIDATE_INPUT_ARG InputArg, 9760 OUT PSAM_VALIDATE_OUTPUT_ARG *OutputArg) 9761 { 9762 UNIMPLEMENTED; 9763 return STATUS_NOT_IMPLEMENTED; 9764 } 9765 9766 /* EOF */ 9767