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