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