1 /* 2 * Copyright 2006 Robert Reif 3 * 4 * netapi32 local group functions 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "netapi32.h" 22 23 WINE_DEFAULT_DEBUG_CHANNEL(netapi32); 24 25 typedef enum _ENUM_PHASE 26 { 27 BuiltinPhase, 28 AccountPhase, 29 DonePhase 30 } ENUM_PHASE; 31 32 typedef struct _ENUM_CONTEXT 33 { 34 SAM_HANDLE ServerHandle; 35 SAM_HANDLE DomainHandle; 36 SAM_HANDLE BuiltinDomainHandle; 37 SAM_HANDLE AccountDomainHandle; 38 39 SAM_ENUMERATE_HANDLE EnumerationContext; 40 PSAM_RID_ENUMERATION Buffer; 41 ULONG Returned; 42 ULONG Index; 43 ENUM_PHASE Phase; 44 45 } ENUM_CONTEXT, *PENUM_CONTEXT; 46 47 typedef struct _MEMBER_ENUM_CONTEXT 48 { 49 SAM_HANDLE ServerHandle; 50 SAM_HANDLE DomainHandle; 51 SAM_HANDLE AliasHandle; 52 LSA_HANDLE LsaHandle; 53 54 PSID *Sids; 55 ULONG Count; 56 PLSA_REFERENCED_DOMAIN_LIST Domains; 57 PLSA_TRANSLATED_NAME Names; 58 59 } MEMBER_ENUM_CONTEXT, *PMEMBER_ENUM_CONTEXT; 60 61 62 static 63 NET_API_STATUS 64 BuildAliasInfoBuffer(PALIAS_GENERAL_INFORMATION AliasInfo, 65 DWORD level, 66 LPVOID *Buffer) 67 { 68 LPVOID LocalBuffer = NULL; 69 PLOCALGROUP_INFO_0 LocalInfo0; 70 PLOCALGROUP_INFO_1 LocalInfo1; 71 LPWSTR Ptr; 72 ULONG Size = 0; 73 NET_API_STATUS ApiStatus = NERR_Success; 74 75 *Buffer = NULL; 76 77 switch (level) 78 { 79 case 0: 80 Size = sizeof(LOCALGROUP_INFO_0) + 81 AliasInfo->Name.Length + sizeof(WCHAR); 82 break; 83 84 case 1: 85 Size = sizeof(LOCALGROUP_INFO_1) + 86 AliasInfo->Name.Length + sizeof(WCHAR) + 87 AliasInfo->AdminComment.Length + sizeof(WCHAR); 88 break; 89 90 default: 91 ApiStatus = ERROR_INVALID_LEVEL; 92 goto done; 93 } 94 95 ApiStatus = NetApiBufferAllocate(Size, &LocalBuffer); 96 if (ApiStatus != NERR_Success) 97 goto done; 98 99 ZeroMemory(LocalBuffer, Size); 100 101 switch (level) 102 { 103 case 0: 104 LocalInfo0 = (PLOCALGROUP_INFO_0)LocalBuffer; 105 106 Ptr = (LPWSTR)((ULONG_PTR)LocalInfo0 + sizeof(LOCALGROUP_INFO_0)); 107 LocalInfo0->lgrpi0_name = Ptr; 108 109 memcpy(LocalInfo0->lgrpi0_name, 110 AliasInfo->Name.Buffer, 111 AliasInfo->Name.Length); 112 LocalInfo0->lgrpi0_name[AliasInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL; 113 break; 114 115 case 1: 116 LocalInfo1 = (PLOCALGROUP_INFO_1)LocalBuffer; 117 118 Ptr = (LPWSTR)((ULONG_PTR)LocalInfo1 + sizeof(LOCALGROUP_INFO_1)); 119 LocalInfo1->lgrpi1_name = Ptr; 120 121 memcpy(LocalInfo1->lgrpi1_name, 122 AliasInfo->Name.Buffer, 123 AliasInfo->Name.Length); 124 LocalInfo1->lgrpi1_name[AliasInfo->Name.Length / sizeof(WCHAR)] = UNICODE_NULL; 125 126 Ptr = (LPWSTR)((ULONG_PTR)Ptr + AliasInfo->Name.Length + sizeof(WCHAR)); 127 LocalInfo1->lgrpi1_comment = Ptr; 128 129 memcpy(LocalInfo1->lgrpi1_comment, 130 AliasInfo->AdminComment.Buffer, 131 AliasInfo->AdminComment.Length); 132 LocalInfo1->lgrpi1_comment[AliasInfo->AdminComment.Length / sizeof(WCHAR)] = UNICODE_NULL; 133 break; 134 } 135 136 done: 137 if (ApiStatus == NERR_Success) 138 { 139 *Buffer = LocalBuffer; 140 } 141 else 142 { 143 if (LocalBuffer != NULL) 144 NetApiBufferFree(LocalBuffer); 145 } 146 147 return ApiStatus; 148 } 149 150 151 static 152 VOID 153 FreeAliasInfo(PALIAS_GENERAL_INFORMATION AliasInfo) 154 { 155 if (AliasInfo->Name.Buffer != NULL) 156 SamFreeMemory(AliasInfo->Name.Buffer); 157 158 if (AliasInfo->AdminComment.Buffer != NULL) 159 SamFreeMemory(AliasInfo->AdminComment.Buffer); 160 161 SamFreeMemory(AliasInfo); 162 } 163 164 165 static 166 NET_API_STATUS 167 OpenAliasByName(SAM_HANDLE DomainHandle, 168 PUNICODE_STRING AliasName, 169 ULONG DesiredAccess, 170 PSAM_HANDLE AliasHandle) 171 { 172 PULONG RelativeIds = NULL; 173 PSID_NAME_USE Use = NULL; 174 NET_API_STATUS ApiStatus = NERR_Success; 175 NTSTATUS Status = STATUS_SUCCESS; 176 177 /* Get the RID for the given user name */ 178 Status = SamLookupNamesInDomain(DomainHandle, 179 1, 180 AliasName, 181 &RelativeIds, 182 &Use); 183 if (!NT_SUCCESS(Status)) 184 { 185 ERR("SamLookupNamesInDomain failed (Status %08lx)\n", Status); 186 return NetpNtStatusToApiStatus(Status); 187 } 188 189 /* Fail, if it is not an alias account */ 190 if (Use[0] != SidTypeAlias) 191 { 192 ERR("Object is not an Alias!\n"); 193 ApiStatus = NERR_GroupNotFound; 194 goto done; 195 } 196 197 /* Open the alias account */ 198 Status = SamOpenAlias(DomainHandle, 199 DesiredAccess, 200 RelativeIds[0], 201 AliasHandle); 202 if (!NT_SUCCESS(Status)) 203 { 204 ERR("SamOpenDomain failed (Status %08lx)\n", Status); 205 ApiStatus = NetpNtStatusToApiStatus(Status); 206 goto done; 207 } 208 209 done: 210 if (RelativeIds != NULL) 211 SamFreeMemory(RelativeIds); 212 213 if (Use != NULL) 214 SamFreeMemory(Use); 215 216 return ApiStatus; 217 } 218 219 220 static 221 NET_API_STATUS 222 BuildSidListFromDomainAndName(IN PUNICODE_STRING ServerName, 223 IN PLOCALGROUP_MEMBERS_INFO_3 buf, 224 IN ULONG EntryCount, 225 OUT PLOCALGROUP_MEMBERS_INFO_0 *MemberList) 226 { 227 OBJECT_ATTRIBUTES ObjectAttributes; 228 LSA_HANDLE LsaHandle = NULL; 229 PUNICODE_STRING NamesArray = NULL; 230 ULONG i; 231 PLSA_REFERENCED_DOMAIN_LIST Domains = NULL; 232 PLSA_TRANSLATED_SID Sids = NULL; 233 PLOCALGROUP_MEMBERS_INFO_0 MemberBuffer = NULL; 234 NET_API_STATUS ApiStatus = NERR_Success; 235 NTSTATUS Status = STATUS_SUCCESS; 236 237 ApiStatus = NetApiBufferAllocate(sizeof(UNICODE_STRING) * EntryCount, 238 (LPVOID*)&NamesArray); 239 if (ApiStatus != NERR_Success) 240 { 241 goto done; 242 } 243 244 for (i = 0; i < EntryCount; i++) 245 { 246 RtlInitUnicodeString(&NamesArray[i], 247 buf[i].lgrmi3_domainandname); 248 } 249 250 InitializeObjectAttributes(&ObjectAttributes, 251 NULL, 252 0, 253 0, 254 NULL); 255 256 Status = LsaOpenPolicy(ServerName, 257 (PLSA_OBJECT_ATTRIBUTES)&ObjectAttributes, 258 POLICY_EXECUTE, 259 &LsaHandle); 260 if (!NT_SUCCESS(Status)) 261 { 262 ApiStatus = NetpNtStatusToApiStatus(Status); 263 goto done; 264 } 265 266 Status = LsaLookupNames(LsaHandle, 267 EntryCount, 268 NamesArray, 269 &Domains, 270 &Sids); 271 if (!NT_SUCCESS(Status)) 272 { 273 ApiStatus = NetpNtStatusToApiStatus(Status); 274 goto done; 275 } 276 277 ApiStatus = NetApiBufferAllocate(sizeof(LOCALGROUP_MEMBERS_INFO_0) * EntryCount, 278 (LPVOID*)&MemberBuffer); 279 if (ApiStatus != NERR_Success) 280 { 281 goto done; 282 } 283 284 for (i = 0; i < EntryCount; i++) 285 { 286 ApiStatus = BuildSidFromSidAndRid(Domains->Domains[Sids[i].DomainIndex].Sid, 287 Sids[i].RelativeId, 288 &MemberBuffer[i].lgrmi0_sid); 289 if (ApiStatus != NERR_Success) 290 { 291 goto done; 292 } 293 } 294 295 done: 296 if (ApiStatus != NERR_Success) 297 { 298 if (MemberBuffer != NULL) 299 { 300 for (i = 0; i < EntryCount; i++) 301 { 302 if (MemberBuffer[i].lgrmi0_sid != NULL) 303 NetApiBufferFree(MemberBuffer[i].lgrmi0_sid); 304 } 305 306 NetApiBufferFree(MemberBuffer); 307 MemberBuffer = NULL; 308 } 309 } 310 311 if (Sids != NULL) 312 LsaFreeMemory(Sids); 313 314 if (Domains != NULL) 315 LsaFreeMemory(Domains); 316 317 if (LsaHandle != NULL) 318 LsaClose(LsaHandle); 319 320 if (NamesArray != NULL) 321 NetApiBufferFree(NamesArray); 322 323 *MemberList = MemberBuffer; 324 325 return ApiStatus; 326 } 327 328 329 /************************************************************ 330 * NetLocalGroupAdd (NETAPI32.@) 331 */ 332 NET_API_STATUS 333 WINAPI 334 NetLocalGroupAdd( 335 LPCWSTR servername, 336 DWORD level, 337 LPBYTE buf, 338 LPDWORD parm_err) 339 { 340 ALIAS_ADM_COMMENT_INFORMATION AdminComment; 341 UNICODE_STRING ServerName; 342 UNICODE_STRING AliasName; 343 SAM_HANDLE ServerHandle = NULL; 344 SAM_HANDLE DomainHandle = NULL; 345 SAM_HANDLE AliasHandle = NULL; 346 LPWSTR aliasname = NULL; 347 LPWSTR aliascomment = NULL; 348 ULONG RelativeId; 349 NET_API_STATUS ApiStatus = NERR_Success; 350 NTSTATUS Status = STATUS_SUCCESS; 351 352 TRACE("(%s %d %p %p) stub!\n", debugstr_w(servername), level, buf, 353 parm_err); 354 355 /* Initialize the Server name*/ 356 if (servername != NULL) 357 RtlInitUnicodeString(&ServerName, servername); 358 359 /* Initialize the Alias name*/ 360 switch (level) 361 { 362 case 0: 363 aliasname = ((PLOCALGROUP_INFO_0)buf)->lgrpi0_name; 364 aliascomment = NULL; 365 break; 366 367 case 1: 368 aliasname = ((PLOCALGROUP_INFO_1)buf)->lgrpi1_name; 369 aliascomment = ((PLOCALGROUP_INFO_1)buf)->lgrpi1_comment; 370 break; 371 372 default: 373 return ERROR_INVALID_LEVEL; 374 } 375 376 RtlInitUnicodeString(&AliasName, aliasname); 377 378 /* Connect to the SAM Server */ 379 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 380 &ServerHandle, 381 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 382 NULL); 383 if (!NT_SUCCESS(Status)) 384 { 385 ERR("SamConnect failed (Status %08lx)\n", Status); 386 ApiStatus = NetpNtStatusToApiStatus(Status); 387 goto done; 388 } 389 390 /* Open the Builtin Domain */ 391 Status = OpenBuiltinDomain(ServerHandle, 392 DOMAIN_LOOKUP, 393 &DomainHandle); 394 if (!NT_SUCCESS(Status)) 395 { 396 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 397 ApiStatus = NetpNtStatusToApiStatus(Status); 398 goto done; 399 } 400 401 /* Try to open the Alias Account in the Builtin Domain */ 402 ApiStatus = OpenAliasByName(DomainHandle, 403 &AliasName, 404 ALIAS_READ_INFORMATION, 405 &AliasHandle); 406 if (ApiStatus == NERR_Success) 407 { 408 ERR("OpenAliasByName: alias %wZ already exists!\n", &AliasName); 409 410 SamCloseHandle(AliasHandle); 411 ApiStatus = ERROR_ALIAS_EXISTS; 412 goto done; 413 } 414 415 ApiStatus = NERR_Success; 416 417 /* Close the Builtin Domain */ 418 SamCloseHandle(DomainHandle); 419 DomainHandle = NULL; 420 421 /* Open the account domain */ 422 Status = OpenAccountDomain(ServerHandle, 423 (servername != NULL) ? &ServerName : NULL, 424 DOMAIN_CREATE_ALIAS | DOMAIN_LOOKUP, 425 &DomainHandle); 426 if (!NT_SUCCESS(Status)) 427 { 428 ERR("SamOpenDomain failed (Status %08lx)\n", Status); 429 ApiStatus = NetpNtStatusToApiStatus(Status); 430 goto done; 431 } 432 433 /* Create the alias */ 434 Status = SamCreateAliasInDomain(DomainHandle, 435 &AliasName, 436 DELETE | ALIAS_WRITE_ACCOUNT, 437 &AliasHandle, 438 &RelativeId); 439 if (!NT_SUCCESS(Status)) 440 { 441 ERR("SamCreateAliasInDomain failed (Status %08lx)\n", Status); 442 ApiStatus = NetpNtStatusToApiStatus(Status); 443 goto done; 444 } 445 446 TRACE("Created alias \"%wZ\" (RID: %lu)\n", &AliasName, RelativeId); 447 448 /* Set the admin comment */ 449 if (level == 1) 450 { 451 RtlInitUnicodeString(&AdminComment.AdminComment, aliascomment); 452 453 Status = SamSetInformationAlias(AliasHandle, 454 AliasAdminCommentInformation, 455 &AdminComment); 456 if (!NT_SUCCESS(Status)) 457 { 458 ERR("SamSetInformationAlias failed (Status %08lx)\n", Status); 459 ApiStatus = NetpNtStatusToApiStatus(Status); 460 461 /* Delete the Alias if the Comment could not be set */ 462 SamDeleteAlias(AliasHandle); 463 464 goto done; 465 } 466 } 467 468 done: 469 if (AliasHandle != NULL) 470 { 471 if (ApiStatus != NERR_Success) 472 SamDeleteAlias(AliasHandle); 473 else 474 SamCloseHandle(AliasHandle); 475 } 476 477 if (DomainHandle != NULL) 478 SamCloseHandle(DomainHandle); 479 480 if (ServerHandle != NULL) 481 SamCloseHandle(ServerHandle); 482 483 return ApiStatus; 484 } 485 486 487 /************************************************************ 488 * NetLocalGroupAddMember (NETAPI32.@) 489 */ 490 NET_API_STATUS 491 WINAPI 492 NetLocalGroupAddMember( 493 LPCWSTR servername, 494 LPCWSTR groupname, 495 PSID membersid) 496 { 497 LOCALGROUP_MEMBERS_INFO_0 Member; 498 499 TRACE("(%s %s %p)\n", debugstr_w(servername), 500 debugstr_w(groupname), membersid); 501 502 Member.lgrmi0_sid = membersid; 503 504 return NetLocalGroupAddMembers(servername, 505 groupname, 506 0, 507 (LPBYTE)&Member, 508 1); 509 } 510 511 512 /************************************************************ 513 * NetLocalGroupAddMembers (NETAPI32.@) 514 */ 515 NET_API_STATUS 516 WINAPI 517 NetLocalGroupAddMembers( 518 LPCWSTR servername, 519 LPCWSTR groupname, 520 DWORD level, 521 LPBYTE buf, 522 DWORD totalentries) 523 { 524 UNICODE_STRING ServerName; 525 UNICODE_STRING AliasName; 526 SAM_HANDLE ServerHandle = NULL; 527 SAM_HANDLE DomainHandle = NULL; 528 SAM_HANDLE AliasHandle = NULL; 529 PLOCALGROUP_MEMBERS_INFO_0 MemberList = NULL; 530 ULONG i; 531 NET_API_STATUS ApiStatus = NERR_Success; 532 NTSTATUS Status = STATUS_SUCCESS; 533 534 TRACE("(%s %s %d %p %d)\n", debugstr_w(servername), 535 debugstr_w(groupname), level, buf, totalentries); 536 537 if (servername != NULL) 538 RtlInitUnicodeString(&ServerName, servername); 539 540 RtlInitUnicodeString(&AliasName, groupname); 541 542 switch (level) 543 { 544 case 0: 545 MemberList = (PLOCALGROUP_MEMBERS_INFO_0)buf; 546 break; 547 548 case 3: 549 Status = BuildSidListFromDomainAndName((servername != NULL) ? &ServerName : NULL, 550 (PLOCALGROUP_MEMBERS_INFO_3)buf, 551 totalentries, 552 &MemberList); 553 if (!NT_SUCCESS(Status)) 554 { 555 ERR("BuildSidListFromDomainAndName failed (Status %08lx)\n", Status); 556 ApiStatus = NetpNtStatusToApiStatus(Status); 557 goto done; 558 } 559 break; 560 561 default: 562 ApiStatus = ERROR_INVALID_LEVEL; 563 goto done; 564 } 565 566 /* Connect to the SAM Server */ 567 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 568 &ServerHandle, 569 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 570 NULL); 571 if (!NT_SUCCESS(Status)) 572 { 573 ERR("SamConnect failed (Status %08lx)\n", Status); 574 ApiStatus = NetpNtStatusToApiStatus(Status); 575 goto done; 576 } 577 578 /* Open the Builtin Domain */ 579 Status = OpenBuiltinDomain(ServerHandle, 580 DOMAIN_LOOKUP, 581 &DomainHandle); 582 if (!NT_SUCCESS(Status)) 583 { 584 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 585 ApiStatus = NetpNtStatusToApiStatus(Status); 586 goto done; 587 } 588 589 /* Open the alias account in the builtin domain */ 590 ApiStatus = OpenAliasByName(DomainHandle, 591 &AliasName, 592 ALIAS_ADD_MEMBER, 593 &AliasHandle); 594 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 595 { 596 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 597 goto done; 598 } 599 600 if (AliasHandle == NULL) 601 { 602 if (DomainHandle != NULL) 603 SamCloseHandle(DomainHandle); 604 605 /* Open the Acount Domain */ 606 Status = OpenAccountDomain(ServerHandle, 607 (servername != NULL) ? &ServerName : NULL, 608 DOMAIN_LOOKUP, 609 &DomainHandle); 610 if (!NT_SUCCESS(Status)) 611 { 612 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 613 ApiStatus = NetpNtStatusToApiStatus(Status); 614 goto done; 615 } 616 617 /* Open the alias account in the account domain */ 618 ApiStatus = OpenAliasByName(DomainHandle, 619 &AliasName, 620 ALIAS_ADD_MEMBER, 621 &AliasHandle); 622 if (ApiStatus != NERR_Success) 623 { 624 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 625 if (ApiStatus == ERROR_NONE_MAPPED) 626 ApiStatus = NERR_GroupNotFound; 627 goto done; 628 } 629 } 630 631 /* Add new members to the alias */ 632 for (i = 0; i < totalentries; i++) 633 { 634 Status = SamAddMemberToAlias(AliasHandle, 635 MemberList[i].lgrmi0_sid); 636 if (!NT_SUCCESS(Status)) 637 { 638 ERR("SamAddMemberToAlias failed (Status %lu)\n", Status); 639 ApiStatus = NetpNtStatusToApiStatus(Status); 640 goto done; 641 } 642 } 643 644 done: 645 if (level == 3 && MemberList != NULL) 646 { 647 for (i = 0; i < totalentries; i++) 648 { 649 if (MemberList[i].lgrmi0_sid != NULL) 650 NetApiBufferFree(MemberList[i].lgrmi0_sid); 651 } 652 653 NetApiBufferFree(MemberList); 654 } 655 656 if (AliasHandle != NULL) 657 SamCloseHandle(AliasHandle); 658 659 if (DomainHandle != NULL) 660 SamCloseHandle(DomainHandle); 661 662 if (ServerHandle != NULL) 663 SamCloseHandle(ServerHandle); 664 665 return ApiStatus; 666 } 667 668 669 /************************************************************ 670 * NetLocalGroupDel (NETAPI32.@) 671 */ 672 NET_API_STATUS 673 WINAPI 674 NetLocalGroupDel( 675 LPCWSTR servername, 676 LPCWSTR groupname) 677 { 678 UNICODE_STRING ServerName; 679 UNICODE_STRING GroupName; 680 SAM_HANDLE ServerHandle = NULL; 681 SAM_HANDLE DomainHandle = NULL; 682 SAM_HANDLE AliasHandle = NULL; 683 NET_API_STATUS ApiStatus = NERR_Success; 684 NTSTATUS Status = STATUS_SUCCESS; 685 686 TRACE("(%s %s)\n", debugstr_w(servername), debugstr_w(groupname)); 687 688 if (servername != NULL) 689 RtlInitUnicodeString(&ServerName, servername); 690 691 RtlInitUnicodeString(&GroupName, groupname); 692 693 /* Connect to the SAM Server */ 694 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 695 &ServerHandle, 696 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 697 NULL); 698 if (!NT_SUCCESS(Status)) 699 { 700 ERR("SamConnect failed (Status %08lx)\n", Status); 701 ApiStatus = NetpNtStatusToApiStatus(Status); 702 goto done; 703 } 704 705 /* Open the Builtin Domain */ 706 Status = OpenBuiltinDomain(ServerHandle, 707 DOMAIN_LOOKUP, 708 &DomainHandle); 709 if (!NT_SUCCESS(Status)) 710 { 711 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 712 ApiStatus = NetpNtStatusToApiStatus(Status); 713 goto done; 714 } 715 716 /* Open the alias account in the builtin domain */ 717 ApiStatus = OpenAliasByName(DomainHandle, 718 &GroupName, 719 DELETE, 720 &AliasHandle); 721 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 722 { 723 TRACE("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 724 goto done; 725 } 726 727 if (AliasHandle == NULL) 728 { 729 if (DomainHandle != NULL) 730 { 731 SamCloseHandle(DomainHandle); 732 DomainHandle = NULL; 733 } 734 735 /* Open the Acount Domain */ 736 Status = OpenAccountDomain(ServerHandle, 737 (servername != NULL) ? &ServerName : NULL, 738 DOMAIN_LOOKUP, 739 &DomainHandle); 740 if (!NT_SUCCESS(Status)) 741 { 742 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 743 ApiStatus = NetpNtStatusToApiStatus(Status); 744 goto done; 745 } 746 747 /* Open the alias account in the account domain */ 748 ApiStatus = OpenAliasByName(DomainHandle, 749 &GroupName, 750 DELETE, 751 &AliasHandle); 752 if (ApiStatus != NERR_Success) 753 { 754 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 755 if (ApiStatus == ERROR_NONE_MAPPED) 756 ApiStatus = NERR_GroupNotFound; 757 goto done; 758 } 759 } 760 761 /* Delete the alias */ 762 Status = SamDeleteAlias(AliasHandle); 763 if (!NT_SUCCESS(Status)) 764 { 765 ERR("SamDeleteAlias failed (Status %08lx)\n", Status); 766 ApiStatus = NetpNtStatusToApiStatus(Status); 767 goto done; 768 } 769 770 done: 771 if (AliasHandle != NULL) 772 SamCloseHandle(AliasHandle); 773 774 if (DomainHandle != NULL) 775 SamCloseHandle(DomainHandle); 776 777 if (ServerHandle != NULL) 778 SamCloseHandle(ServerHandle); 779 780 return ApiStatus; 781 } 782 783 784 /************************************************************ 785 * NetLocalGroupDelMember (NETAPI32.@) 786 */ 787 NET_API_STATUS 788 WINAPI 789 NetLocalGroupDelMember( 790 LPCWSTR servername, 791 LPCWSTR groupname, 792 PSID membersid) 793 { 794 LOCALGROUP_MEMBERS_INFO_0 Member; 795 796 TRACE("(%s %s %p)\n", debugstr_w(servername), 797 debugstr_w(groupname), membersid); 798 799 Member.lgrmi0_sid = membersid; 800 801 return NetLocalGroupDelMembers(servername, 802 groupname, 803 0, 804 (LPBYTE)&Member, 805 1); 806 } 807 808 809 /************************************************************ 810 * NetLocalGroupDelMembers (NETAPI32.@) 811 */ 812 NET_API_STATUS 813 WINAPI 814 NetLocalGroupDelMembers( 815 LPCWSTR servername, 816 LPCWSTR groupname, 817 DWORD level, 818 LPBYTE buf, 819 DWORD totalentries) 820 { 821 UNICODE_STRING ServerName; 822 UNICODE_STRING AliasName; 823 SAM_HANDLE ServerHandle = NULL; 824 SAM_HANDLE DomainHandle = NULL; 825 SAM_HANDLE AliasHandle = NULL; 826 PLOCALGROUP_MEMBERS_INFO_0 MemberList = NULL; 827 ULONG i; 828 NET_API_STATUS ApiStatus = NERR_Success; 829 NTSTATUS Status = STATUS_SUCCESS; 830 831 TRACE("(%s %s %d %p %d)\n", debugstr_w(servername), 832 debugstr_w(groupname), level, buf, totalentries); 833 834 if (servername != NULL) 835 RtlInitUnicodeString(&ServerName, servername); 836 837 RtlInitUnicodeString(&AliasName, groupname); 838 839 switch (level) 840 { 841 case 0: 842 MemberList = (PLOCALGROUP_MEMBERS_INFO_0)buf; 843 break; 844 845 case 3: 846 Status = BuildSidListFromDomainAndName((servername != NULL) ? &ServerName : NULL, 847 (PLOCALGROUP_MEMBERS_INFO_3)buf, 848 totalentries, 849 &MemberList); 850 if (!NT_SUCCESS(Status)) 851 { 852 ERR("BuildSidListFromDomainAndName failed (Status %08lx)\n", Status); 853 ApiStatus = NetpNtStatusToApiStatus(Status); 854 goto done; 855 } 856 break; 857 858 default: 859 ApiStatus = ERROR_INVALID_LEVEL; 860 goto done; 861 } 862 863 /* Connect to the SAM Server */ 864 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 865 &ServerHandle, 866 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 867 NULL); 868 if (!NT_SUCCESS(Status)) 869 { 870 ERR("SamConnect failed (Status %08lx)\n", Status); 871 ApiStatus = NetpNtStatusToApiStatus(Status); 872 goto done; 873 } 874 875 /* Open the Builtin Domain */ 876 Status = OpenBuiltinDomain(ServerHandle, 877 DOMAIN_LOOKUP, 878 &DomainHandle); 879 if (!NT_SUCCESS(Status)) 880 { 881 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 882 ApiStatus = NetpNtStatusToApiStatus(Status); 883 goto done; 884 } 885 886 /* Open the alias account in the builtin domain */ 887 ApiStatus = OpenAliasByName(DomainHandle, 888 &AliasName, 889 ALIAS_REMOVE_MEMBER, 890 &AliasHandle); 891 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 892 { 893 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 894 goto done; 895 } 896 897 if (AliasHandle == NULL) 898 { 899 if (DomainHandle != NULL) 900 SamCloseHandle(DomainHandle); 901 902 /* Open the Acount Domain */ 903 Status = OpenAccountDomain(ServerHandle, 904 (servername != NULL) ? &ServerName : NULL, 905 DOMAIN_LOOKUP, 906 &DomainHandle); 907 if (!NT_SUCCESS(Status)) 908 { 909 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 910 ApiStatus = NetpNtStatusToApiStatus(Status); 911 goto done; 912 } 913 914 /* Open the alias account in the account domain */ 915 ApiStatus = OpenAliasByName(DomainHandle, 916 &AliasName, 917 ALIAS_REMOVE_MEMBER, 918 &AliasHandle); 919 if (ApiStatus != NERR_Success) 920 { 921 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 922 if (ApiStatus == ERROR_NONE_MAPPED) 923 ApiStatus = NERR_GroupNotFound; 924 goto done; 925 } 926 } 927 928 /* Remove members from the alias */ 929 for (i = 0; i < totalentries; i++) 930 { 931 Status = SamRemoveMemberFromAlias(AliasHandle, 932 MemberList[i].lgrmi0_sid); 933 if (!NT_SUCCESS(Status)) 934 { 935 ERR("SamAddMemberToAlias failed (Status %lu)\n", Status); 936 ApiStatus = NetpNtStatusToApiStatus(Status); 937 goto done; 938 } 939 } 940 941 done: 942 if (level == 3 && MemberList != NULL) 943 { 944 for (i = 0; i < totalentries; i++) 945 { 946 if (MemberList[i].lgrmi0_sid != NULL) 947 NetApiBufferFree(MemberList[i].lgrmi0_sid); 948 } 949 950 NetApiBufferFree(MemberList); 951 } 952 953 if (AliasHandle != NULL) 954 SamCloseHandle(AliasHandle); 955 956 if (DomainHandle != NULL) 957 SamCloseHandle(DomainHandle); 958 959 if (ServerHandle != NULL) 960 SamCloseHandle(ServerHandle); 961 962 return ApiStatus; 963 } 964 965 966 /************************************************************ 967 * NetLocalGroupEnum (NETAPI32.@) 968 */ 969 NET_API_STATUS 970 WINAPI 971 NetLocalGroupEnum( 972 LPCWSTR servername, 973 DWORD level, 974 LPBYTE* bufptr, 975 DWORD prefmaxlen, 976 LPDWORD entriesread, 977 LPDWORD totalentries, 978 PDWORD_PTR resumehandle) 979 { 980 UNICODE_STRING ServerName; 981 PSAM_RID_ENUMERATION CurrentAlias; 982 PENUM_CONTEXT EnumContext = NULL; 983 ULONG i; 984 SAM_HANDLE AliasHandle = NULL; 985 PALIAS_GENERAL_INFORMATION AliasInfo = NULL; 986 LPVOID Buffer = NULL; 987 NET_API_STATUS ApiStatus = NERR_Success; 988 NTSTATUS Status = STATUS_SUCCESS; 989 990 TRACE("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername), 991 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle); 992 993 *entriesread = 0; 994 *totalentries = 0; 995 *bufptr = NULL; 996 997 if (servername != NULL) 998 RtlInitUnicodeString(&ServerName, servername); 999 1000 if (resumehandle != NULL && *resumehandle != 0) 1001 { 1002 EnumContext = (PENUM_CONTEXT)*resumehandle; 1003 } 1004 else 1005 { 1006 ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext); 1007 if (ApiStatus != NERR_Success) 1008 goto done; 1009 1010 EnumContext->EnumerationContext = 0; 1011 EnumContext->Buffer = NULL; 1012 EnumContext->Returned = 0; 1013 EnumContext->Index = 0; 1014 1015 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 1016 &EnumContext->ServerHandle, 1017 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 1018 NULL); 1019 if (!NT_SUCCESS(Status)) 1020 { 1021 ERR("SamConnect failed (Status %08lx)\n", Status); 1022 ApiStatus = NetpNtStatusToApiStatus(Status); 1023 goto done; 1024 } 1025 1026 Status = OpenAccountDomain(EnumContext->ServerHandle, 1027 (servername != NULL) ? &ServerName : NULL, 1028 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, 1029 &EnumContext->AccountDomainHandle); 1030 if (!NT_SUCCESS(Status)) 1031 { 1032 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 1033 ApiStatus = NetpNtStatusToApiStatus(Status); 1034 goto done; 1035 } 1036 1037 Status = OpenBuiltinDomain(EnumContext->ServerHandle, 1038 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, 1039 &EnumContext->BuiltinDomainHandle); 1040 if (!NT_SUCCESS(Status)) 1041 { 1042 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 1043 ApiStatus = NetpNtStatusToApiStatus(Status); 1044 goto done; 1045 } 1046 1047 EnumContext->Phase = BuiltinPhase; 1048 EnumContext->DomainHandle = EnumContext->BuiltinDomainHandle; 1049 } 1050 1051 1052 // while (TRUE) 1053 // { 1054 TRACE("EnumContext->Index: %lu\n", EnumContext->Index); 1055 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned); 1056 1057 if (EnumContext->Index >= EnumContext->Returned) 1058 { 1059 TRACE("Calling SamEnumerateAliasesInDomain\n"); 1060 1061 Status = SamEnumerateAliasesInDomain(EnumContext->DomainHandle, 1062 &EnumContext->EnumerationContext, 1063 (PVOID *)&EnumContext->Buffer, 1064 prefmaxlen, 1065 &EnumContext->Returned); 1066 1067 TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status); 1068 if (!NT_SUCCESS(Status)) 1069 { 1070 ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status); 1071 ApiStatus = NetpNtStatusToApiStatus(Status); 1072 goto done; 1073 } 1074 1075 if (Status == STATUS_MORE_ENTRIES) 1076 { 1077 ApiStatus = NERR_BufTooSmall; 1078 goto done; 1079 } 1080 } 1081 1082 TRACE("EnumContext: %lu\n", EnumContext); 1083 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned); 1084 TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer); 1085 1086 /* Get a pointer to the current alias */ 1087 CurrentAlias = &EnumContext->Buffer[EnumContext->Index]; 1088 1089 TRACE("RID: %lu\n", CurrentAlias->RelativeId); 1090 1091 Status = SamOpenAlias(EnumContext->DomainHandle, 1092 ALIAS_READ_INFORMATION, 1093 CurrentAlias->RelativeId, 1094 &AliasHandle); 1095 if (!NT_SUCCESS(Status)) 1096 { 1097 ERR("SamOpenAlias failed (Status %08lx)\n", Status); 1098 ApiStatus = NetpNtStatusToApiStatus(Status); 1099 goto done; 1100 } 1101 1102 Status = SamQueryInformationAlias(AliasHandle, 1103 AliasGeneralInformation, 1104 (PVOID *)&AliasInfo); 1105 if (!NT_SUCCESS(Status)) 1106 { 1107 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status); 1108 ApiStatus = NetpNtStatusToApiStatus(Status); 1109 goto done; 1110 } 1111 1112 SamCloseHandle(AliasHandle); 1113 AliasHandle = NULL; 1114 1115 TRACE("Name: %S\n", AliasInfo->Name.Buffer); 1116 TRACE("Comment: %S\n", AliasInfo->AdminComment.Buffer); 1117 1118 ApiStatus = BuildAliasInfoBuffer(AliasInfo, 1119 level, 1120 &Buffer); 1121 if (ApiStatus != NERR_Success) 1122 goto done; 1123 1124 if (AliasInfo != NULL) 1125 { 1126 FreeAliasInfo(AliasInfo); 1127 AliasInfo = NULL; 1128 } 1129 1130 EnumContext->Index++; 1131 1132 (*entriesread)++; 1133 1134 if (EnumContext->Index == EnumContext->Returned) 1135 { 1136 switch (EnumContext->Phase) 1137 { 1138 case BuiltinPhase: 1139 EnumContext->Phase = AccountPhase; 1140 EnumContext->DomainHandle = EnumContext->AccountDomainHandle; 1141 EnumContext->EnumerationContext = 0; 1142 EnumContext->Index = 0; 1143 EnumContext->Returned = 0; 1144 1145 if (EnumContext->Buffer != NULL) 1146 { 1147 for (i = 0; i < EnumContext->Returned; i++) 1148 { 1149 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer); 1150 } 1151 1152 SamFreeMemory(EnumContext->Buffer); 1153 EnumContext->Buffer = NULL; 1154 } 1155 break; 1156 1157 case AccountPhase: 1158 case DonePhase: 1159 EnumContext->Phase = DonePhase; 1160 break; 1161 } 1162 } 1163 // } 1164 1165 done: 1166 if (ApiStatus == NERR_Success && EnumContext != NULL && EnumContext->Phase != DonePhase) 1167 ApiStatus = ERROR_MORE_DATA; 1168 1169 if (EnumContext != NULL) 1170 *totalentries = EnumContext->Returned; 1171 1172 if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA) 1173 { 1174 if (EnumContext != NULL) 1175 { 1176 if (EnumContext->BuiltinDomainHandle != NULL) 1177 SamCloseHandle(EnumContext->BuiltinDomainHandle); 1178 1179 if (EnumContext->AccountDomainHandle != NULL) 1180 SamCloseHandle(EnumContext->AccountDomainHandle); 1181 1182 if (EnumContext->ServerHandle != NULL) 1183 SamCloseHandle(EnumContext->ServerHandle); 1184 1185 if (EnumContext->Buffer != NULL) 1186 { 1187 for (i = 0; i < EnumContext->Returned; i++) 1188 { 1189 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer); 1190 } 1191 1192 SamFreeMemory(EnumContext->Buffer); 1193 } 1194 1195 NetApiBufferFree(EnumContext); 1196 EnumContext = NULL; 1197 } 1198 } 1199 1200 if (AliasHandle != NULL) 1201 SamCloseHandle(AliasHandle); 1202 1203 if (AliasInfo != NULL) 1204 FreeAliasInfo(AliasInfo); 1205 1206 if (resumehandle != NULL) 1207 *resumehandle = (DWORD_PTR)EnumContext; 1208 1209 *bufptr = (LPBYTE)Buffer; 1210 1211 TRACE ("return %lu\n", ApiStatus); 1212 1213 return ApiStatus; 1214 } 1215 1216 1217 /************************************************************ 1218 * NetLocalGroupGetInfo (NETAPI32.@) 1219 */ 1220 NET_API_STATUS 1221 WINAPI 1222 NetLocalGroupGetInfo( 1223 LPCWSTR servername, 1224 LPCWSTR groupname, 1225 DWORD level, 1226 LPBYTE* bufptr) 1227 { 1228 UNICODE_STRING ServerName; 1229 UNICODE_STRING GroupName; 1230 SAM_HANDLE ServerHandle = NULL; 1231 SAM_HANDLE DomainHandle = NULL; 1232 SAM_HANDLE AliasHandle = NULL; 1233 PALIAS_GENERAL_INFORMATION AliasInfo = NULL; 1234 LPVOID Buffer = NULL; 1235 NET_API_STATUS ApiStatus = NERR_Success; 1236 NTSTATUS Status = STATUS_SUCCESS; 1237 1238 TRACE("(%s %s %d %p) stub!\n", debugstr_w(servername), 1239 debugstr_w(groupname), level, bufptr); 1240 1241 if (servername != NULL) 1242 RtlInitUnicodeString(&ServerName, servername); 1243 1244 RtlInitUnicodeString(&GroupName, groupname); 1245 1246 /* Connect to the SAM Server */ 1247 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 1248 &ServerHandle, 1249 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 1250 NULL); 1251 if (!NT_SUCCESS(Status)) 1252 { 1253 ERR("SamConnect failed (Status %08lx)\n", Status); 1254 ApiStatus = NetpNtStatusToApiStatus(Status); 1255 goto done; 1256 } 1257 1258 /* Open the Builtin Domain */ 1259 Status = OpenBuiltinDomain(ServerHandle, 1260 DOMAIN_LOOKUP, 1261 &DomainHandle); 1262 if (!NT_SUCCESS(Status)) 1263 { 1264 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 1265 ApiStatus = NetpNtStatusToApiStatus(Status); 1266 goto done; 1267 } 1268 1269 /* Open the alias account in the builtin domain */ 1270 ApiStatus = OpenAliasByName(DomainHandle, 1271 &GroupName, 1272 ALIAS_READ_INFORMATION, 1273 &AliasHandle); 1274 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 1275 { 1276 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 1277 goto done; 1278 } 1279 1280 if (AliasHandle == NULL) 1281 { 1282 if (DomainHandle != NULL) 1283 SamCloseHandle(DomainHandle); 1284 1285 /* Open the Acount Domain */ 1286 Status = OpenAccountDomain(ServerHandle, 1287 (servername != NULL) ? &ServerName : NULL, 1288 DOMAIN_LOOKUP, 1289 &DomainHandle); 1290 if (!NT_SUCCESS(Status)) 1291 { 1292 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 1293 ApiStatus = NetpNtStatusToApiStatus(Status); 1294 goto done; 1295 } 1296 1297 /* Open the alias account in the account domain */ 1298 ApiStatus = OpenAliasByName(DomainHandle, 1299 &GroupName, 1300 ALIAS_READ_INFORMATION, 1301 &AliasHandle); 1302 if (ApiStatus != NERR_Success) 1303 { 1304 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 1305 if (ApiStatus == ERROR_NONE_MAPPED) 1306 ApiStatus = NERR_GroupNotFound; 1307 goto done; 1308 } 1309 } 1310 1311 Status = SamQueryInformationAlias(AliasHandle, 1312 AliasGeneralInformation, 1313 (PVOID *)&AliasInfo); 1314 if (!NT_SUCCESS(Status)) 1315 { 1316 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status); 1317 ApiStatus = NetpNtStatusToApiStatus(Status); 1318 goto done; 1319 } 1320 1321 ApiStatus = BuildAliasInfoBuffer(AliasInfo, 1322 level, 1323 &Buffer); 1324 if (ApiStatus != NERR_Success) 1325 goto done; 1326 1327 done: 1328 if (AliasInfo != NULL) 1329 FreeAliasInfo(AliasInfo); 1330 1331 if (AliasHandle != NULL) 1332 SamCloseHandle(AliasHandle); 1333 1334 if (DomainHandle != NULL) 1335 SamCloseHandle(DomainHandle); 1336 1337 if (ServerHandle != NULL) 1338 SamCloseHandle(ServerHandle); 1339 1340 *bufptr = (LPBYTE)Buffer; 1341 1342 return ApiStatus; 1343 } 1344 1345 1346 /************************************************************ 1347 * NetLocalGroupGetMembers (NETAPI32.@) 1348 */ 1349 NET_API_STATUS 1350 WINAPI 1351 NetLocalGroupGetMembers( 1352 LPCWSTR servername, 1353 LPCWSTR localgroupname, 1354 DWORD level, 1355 LPBYTE* bufptr, 1356 DWORD prefmaxlen, 1357 LPDWORD entriesread, 1358 LPDWORD totalentries, 1359 PDWORD_PTR resumehandle) 1360 { 1361 OBJECT_ATTRIBUTES ObjectAttributes; 1362 UNICODE_STRING ServerName; 1363 UNICODE_STRING AliasName; 1364 PMEMBER_ENUM_CONTEXT EnumContext = NULL; 1365 LPVOID Buffer = NULL; 1366 PLOCALGROUP_MEMBERS_INFO_0 MembersInfo0; 1367 PLOCALGROUP_MEMBERS_INFO_1 MembersInfo1; 1368 PLOCALGROUP_MEMBERS_INFO_2 MembersInfo2; 1369 PLOCALGROUP_MEMBERS_INFO_3 MembersInfo3; 1370 LPWSTR Ptr; 1371 ULONG Size = 0; 1372 ULONG SidLength; 1373 ULONG i; 1374 NET_API_STATUS ApiStatus = NERR_Success; 1375 NTSTATUS Status = STATUS_SUCCESS; 1376 1377 TRACE("(%s %s %d %p %d %p %p %p)\n", debugstr_w(servername), 1378 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread, 1379 totalentries, resumehandle); 1380 1381 *entriesread = 0; 1382 *totalentries = 0; 1383 *bufptr = NULL; 1384 1385 if (servername != NULL) 1386 RtlInitUnicodeString(&ServerName, servername); 1387 1388 RtlInitUnicodeString(&AliasName, localgroupname); 1389 1390 if (resumehandle != NULL && *resumehandle != 0) 1391 { 1392 EnumContext = (PMEMBER_ENUM_CONTEXT)*resumehandle; 1393 } 1394 else 1395 { 1396 /* Allocate the enumeration context */ 1397 ApiStatus = NetApiBufferAllocate(sizeof(MEMBER_ENUM_CONTEXT), (PVOID*)&EnumContext); 1398 if (ApiStatus != NERR_Success) 1399 goto done; 1400 1401 /* Connect to the SAM Server */ 1402 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 1403 &EnumContext->ServerHandle, 1404 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 1405 NULL); 1406 if (!NT_SUCCESS(Status)) 1407 { 1408 ERR("SamConnect failed (Status %08lx)\n", Status); 1409 ApiStatus = NetpNtStatusToApiStatus(Status); 1410 goto done; 1411 } 1412 1413 /* Open the Builtin Domain */ 1414 Status = OpenBuiltinDomain(EnumContext->ServerHandle, 1415 DOMAIN_LOOKUP, 1416 &EnumContext->DomainHandle); 1417 if (!NT_SUCCESS(Status)) 1418 { 1419 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 1420 ApiStatus = NetpNtStatusToApiStatus(Status); 1421 goto done; 1422 } 1423 1424 /* Open the alias account in the builtin domain */ 1425 ApiStatus = OpenAliasByName(EnumContext->DomainHandle, 1426 &AliasName, 1427 ALIAS_LIST_MEMBERS, 1428 &EnumContext->AliasHandle); 1429 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 1430 { 1431 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 1432 goto done; 1433 } 1434 1435 if (EnumContext->AliasHandle == NULL) 1436 { 1437 if (EnumContext->DomainHandle != NULL) 1438 SamCloseHandle(EnumContext->DomainHandle); 1439 1440 /* Open the Acount Domain */ 1441 Status = OpenAccountDomain(EnumContext->ServerHandle, 1442 (servername != NULL) ? &ServerName : NULL, 1443 DOMAIN_LOOKUP, 1444 &EnumContext->DomainHandle); 1445 if (!NT_SUCCESS(Status)) 1446 { 1447 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 1448 ApiStatus = NetpNtStatusToApiStatus(Status); 1449 goto done; 1450 } 1451 1452 /* Open the alias account in the account domain */ 1453 ApiStatus = OpenAliasByName(EnumContext->DomainHandle, 1454 &AliasName, 1455 ALIAS_LIST_MEMBERS, 1456 &EnumContext->AliasHandle); 1457 if (ApiStatus != NERR_Success) 1458 { 1459 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 1460 if (ApiStatus == ERROR_NONE_MAPPED) 1461 ApiStatus = NERR_GroupNotFound; 1462 goto done; 1463 } 1464 } 1465 1466 /* Get the member list */ 1467 Status = SamGetMembersInAlias(EnumContext->AliasHandle, 1468 &EnumContext->Sids, 1469 &EnumContext->Count); 1470 if (!NT_SUCCESS(Status)) 1471 { 1472 ERR("SamGetMemberInAlias failed (Status %08lx)\n", Status); 1473 ApiStatus = NetpNtStatusToApiStatus(Status); 1474 goto done; 1475 } 1476 1477 if (EnumContext->Count == 0) 1478 { 1479 TRACE("No member found. We're done.\n"); 1480 ApiStatus = NERR_Success; 1481 goto done; 1482 } 1483 1484 /* Get name and domain information for all members */ 1485 if (level != 0) 1486 { 1487 InitializeObjectAttributes(&ObjectAttributes, 1488 NULL, 1489 0, 1490 0, 1491 NULL); 1492 1493 Status = LsaOpenPolicy((servername != NULL) ? &ServerName : NULL, 1494 (PLSA_OBJECT_ATTRIBUTES)&ObjectAttributes, 1495 POLICY_EXECUTE, 1496 &EnumContext->LsaHandle); 1497 if (!NT_SUCCESS(Status)) 1498 { 1499 ApiStatus = NetpNtStatusToApiStatus(Status); 1500 goto done; 1501 } 1502 1503 Status = LsaLookupSids(EnumContext->LsaHandle, 1504 EnumContext->Count, 1505 EnumContext->Sids, 1506 &EnumContext->Domains, 1507 &EnumContext->Names); 1508 if (!NT_SUCCESS(Status)) 1509 { 1510 ApiStatus = NetpNtStatusToApiStatus(Status); 1511 goto done; 1512 } 1513 } 1514 } 1515 1516 /* Calculate the required buffer size */ 1517 for (i = 0; i < EnumContext->Count; i++) 1518 { 1519 switch (level) 1520 { 1521 case 0: 1522 Size += sizeof(LOCALGROUP_MEMBERS_INFO_0) + 1523 RtlLengthSid(EnumContext->Sids[i]); 1524 break; 1525 1526 case 1: 1527 Size += sizeof(LOCALGROUP_MEMBERS_INFO_1) + 1528 RtlLengthSid(EnumContext->Sids[i]) + 1529 EnumContext->Names[i].Name.Length + sizeof(WCHAR); 1530 break; 1531 1532 case 2: 1533 Size += sizeof(LOCALGROUP_MEMBERS_INFO_2) + 1534 RtlLengthSid(EnumContext->Sids[i]) + 1535 EnumContext->Names[i].Name.Length + sizeof(WCHAR); 1536 if (EnumContext->Names[i].DomainIndex >= 0) 1537 Size += EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length + sizeof(WCHAR); 1538 break; 1539 1540 case 3: 1541 Size += sizeof(LOCALGROUP_MEMBERS_INFO_3) + 1542 EnumContext->Names[i].Name.Length + sizeof(WCHAR); 1543 if (EnumContext->Names[i].DomainIndex >= 0) 1544 Size += EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length + sizeof(WCHAR); 1545 break; 1546 1547 default: 1548 ApiStatus = ERROR_INVALID_LEVEL; 1549 goto done; 1550 } 1551 } 1552 1553 /* Allocate the member buffer */ 1554 ApiStatus = NetApiBufferAllocate(Size, &Buffer); 1555 if (ApiStatus != NERR_Success) 1556 goto done; 1557 1558 ZeroMemory(Buffer, Size); 1559 1560 /* Fill the member buffer */ 1561 switch (level) 1562 { 1563 case 0: 1564 MembersInfo0 = (PLOCALGROUP_MEMBERS_INFO_0)Buffer; 1565 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_0) * EnumContext->Count); 1566 break; 1567 1568 case 1: 1569 MembersInfo1 = (PLOCALGROUP_MEMBERS_INFO_1)Buffer; 1570 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_1) * EnumContext->Count); 1571 break; 1572 1573 case 2: 1574 MembersInfo2 = (PLOCALGROUP_MEMBERS_INFO_2)Buffer; 1575 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_2) * EnumContext->Count); 1576 break; 1577 1578 case 3: 1579 MembersInfo3 = (PLOCALGROUP_MEMBERS_INFO_3)Buffer; 1580 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_3) * EnumContext->Count); 1581 break; 1582 } 1583 1584 for (i = 0; i < EnumContext->Count; i++) 1585 { 1586 switch (level) 1587 { 1588 case 0: 1589 MembersInfo0->lgrmi0_sid = (PSID)Ptr; 1590 1591 SidLength = RtlLengthSid(EnumContext->Sids[i]); 1592 memcpy(MembersInfo0->lgrmi0_sid, 1593 EnumContext->Sids[i], 1594 SidLength); 1595 Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength); 1596 MembersInfo0++; 1597 break; 1598 1599 case 1: 1600 MembersInfo1->lgrmi1_sid = (PSID)Ptr; 1601 1602 SidLength = RtlLengthSid(EnumContext->Sids[i]); 1603 memcpy(MembersInfo1->lgrmi1_sid, 1604 EnumContext->Sids[i], 1605 SidLength); 1606 1607 Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength); 1608 1609 MembersInfo1->lgrmi1_sidusage = EnumContext->Names[i].Use; 1610 1611 TRACE("Name: %S\n", EnumContext->Names[i].Name.Buffer); 1612 1613 MembersInfo1->lgrmi1_name = Ptr; 1614 1615 memcpy(MembersInfo1->lgrmi1_name, 1616 EnumContext->Names[i].Name.Buffer, 1617 EnumContext->Names[i].Name.Length); 1618 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR)); 1619 MembersInfo1++; 1620 break; 1621 1622 case 2: 1623 MembersInfo2->lgrmi2_sid = (PSID)Ptr; 1624 1625 SidLength = RtlLengthSid(EnumContext->Sids[i]); 1626 memcpy(MembersInfo2->lgrmi2_sid, 1627 EnumContext->Sids[i], 1628 SidLength); 1629 1630 Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength); 1631 1632 MembersInfo2->lgrmi2_sidusage = EnumContext->Names[i].Use; 1633 1634 MembersInfo2->lgrmi2_domainandname = Ptr; 1635 1636 if (EnumContext->Names[i].DomainIndex >= 0) 1637 { 1638 memcpy(MembersInfo2->lgrmi2_domainandname, 1639 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Buffer, 1640 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length); 1641 1642 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length); 1643 1644 *((LPWSTR)Ptr) = L'\\'; 1645 1646 Ptr = (PVOID)((ULONG_PTR)Ptr + sizeof(WCHAR)); 1647 } 1648 1649 memcpy(Ptr, 1650 EnumContext->Names[i].Name.Buffer, 1651 EnumContext->Names[i].Name.Length); 1652 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR)); 1653 MembersInfo2++; 1654 break; 1655 1656 case 3: 1657 MembersInfo3->lgrmi3_domainandname = Ptr; 1658 1659 if (EnumContext->Names[i].DomainIndex >= 0) 1660 { 1661 memcpy(MembersInfo3->lgrmi3_domainandname, 1662 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Buffer, 1663 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length); 1664 1665 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length); 1666 1667 *((LPWSTR)Ptr) = L'\\'; 1668 1669 Ptr = (PVOID)((ULONG_PTR)Ptr + sizeof(WCHAR)); 1670 } 1671 1672 memcpy(Ptr, 1673 EnumContext->Names[i].Name.Buffer, 1674 EnumContext->Names[i].Name.Length); 1675 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR)); 1676 MembersInfo3++; 1677 break; 1678 } 1679 } 1680 1681 *entriesread = EnumContext->Count; 1682 1683 *bufptr = (LPBYTE)Buffer; 1684 1685 done: 1686 if (EnumContext != NULL) 1687 *totalentries = EnumContext->Count; 1688 1689 if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA) 1690 { 1691 /* Release the enumeration context */ 1692 if (EnumContext != NULL) 1693 { 1694 if (EnumContext->LsaHandle != NULL) 1695 LsaClose(EnumContext->LsaHandle); 1696 1697 if (EnumContext->AliasHandle != NULL) 1698 SamCloseHandle(EnumContext->AliasHandle); 1699 1700 if (EnumContext->DomainHandle != NULL) 1701 SamCloseHandle(EnumContext->DomainHandle); 1702 1703 if (EnumContext->ServerHandle != NULL) 1704 SamCloseHandle(EnumContext->ServerHandle); 1705 1706 if (EnumContext->Sids != NULL) 1707 SamFreeMemory(EnumContext->Sids); 1708 1709 if (EnumContext->Domains != NULL) 1710 LsaFreeMemory(EnumContext->Domains); 1711 1712 if (EnumContext->Names != NULL) 1713 LsaFreeMemory(EnumContext->Names); 1714 1715 NetApiBufferFree(EnumContext); 1716 EnumContext = NULL; 1717 } 1718 } 1719 1720 return ApiStatus; 1721 } 1722 1723 1724 /************************************************************ 1725 * NetLocalGroupSetInfo (NETAPI32.@) 1726 */ 1727 NET_API_STATUS 1728 WINAPI 1729 NetLocalGroupSetInfo( 1730 LPCWSTR servername, 1731 LPCWSTR groupname, 1732 DWORD level, 1733 LPBYTE buf, 1734 LPDWORD parm_err) 1735 { 1736 UNICODE_STRING ServerName; 1737 UNICODE_STRING AliasName; 1738 SAM_HANDLE ServerHandle = NULL; 1739 SAM_HANDLE DomainHandle = NULL; 1740 SAM_HANDLE AliasHandle = NULL; 1741 ALIAS_NAME_INFORMATION AliasNameInfo; 1742 ALIAS_ADM_COMMENT_INFORMATION AdminCommentInfo; 1743 NET_API_STATUS ApiStatus = NERR_Success; 1744 NTSTATUS Status = STATUS_SUCCESS; 1745 1746 TRACE("(%s %s %d %p %p)\n", debugstr_w(servername), 1747 debugstr_w(groupname), level, buf, parm_err); 1748 1749 if (parm_err != NULL) 1750 *parm_err = PARM_ERROR_NONE; 1751 1752 if (servername != NULL) 1753 RtlInitUnicodeString(&ServerName, servername); 1754 1755 RtlInitUnicodeString(&AliasName, groupname); 1756 1757 /* Connect to the SAM Server */ 1758 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 1759 &ServerHandle, 1760 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 1761 NULL); 1762 if (!NT_SUCCESS(Status)) 1763 { 1764 ERR("SamConnect failed (Status %08lx)\n", Status); 1765 ApiStatus = NetpNtStatusToApiStatus(Status); 1766 goto done; 1767 } 1768 1769 /* Open the Builtin Domain */ 1770 Status = OpenBuiltinDomain(ServerHandle, 1771 DOMAIN_LOOKUP, 1772 &DomainHandle); 1773 if (!NT_SUCCESS(Status)) 1774 { 1775 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 1776 ApiStatus = NetpNtStatusToApiStatus(Status); 1777 goto done; 1778 } 1779 1780 /* Open the alias account in the builtin domain */ 1781 ApiStatus = OpenAliasByName(DomainHandle, 1782 &AliasName, 1783 ALIAS_WRITE_ACCOUNT, 1784 &AliasHandle); 1785 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 1786 { 1787 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 1788 goto done; 1789 } 1790 1791 if (AliasHandle == NULL) 1792 { 1793 if (DomainHandle != NULL) 1794 SamCloseHandle(DomainHandle); 1795 1796 /* Open the Acount Domain */ 1797 Status = OpenAccountDomain(ServerHandle, 1798 (servername != NULL) ? &ServerName : NULL, 1799 DOMAIN_LOOKUP, 1800 &DomainHandle); 1801 if (!NT_SUCCESS(Status)) 1802 { 1803 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 1804 ApiStatus = NetpNtStatusToApiStatus(Status); 1805 goto done; 1806 } 1807 1808 /* Open the alias account in the account domain */ 1809 ApiStatus = OpenAliasByName(DomainHandle, 1810 &AliasName, 1811 ALIAS_WRITE_ACCOUNT, 1812 &AliasHandle); 1813 if (ApiStatus != NERR_Success) 1814 { 1815 ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus); 1816 if (ApiStatus == ERROR_NONE_MAPPED) 1817 ApiStatus = NERR_GroupNotFound; 1818 goto done; 1819 } 1820 } 1821 1822 switch (level) 1823 { 1824 case 0: 1825 /* Set the alias name */ 1826 RtlInitUnicodeString(&AliasNameInfo.Name, 1827 ((PLOCALGROUP_INFO_0)buf)->lgrpi0_name); 1828 1829 Status = SamSetInformationAlias(AliasHandle, 1830 AliasNameInformation, 1831 &AliasNameInfo); 1832 if (!NT_SUCCESS(Status)) 1833 { 1834 TRACE("SamSetInformationAlias failed (ApiStatus %lu)\n", ApiStatus); 1835 ApiStatus = NetpNtStatusToApiStatus(Status); 1836 goto done; 1837 } 1838 break; 1839 1840 case 1: 1841 case 1002: 1842 /* Set the alias admin comment */ 1843 if (level == 1) 1844 RtlInitUnicodeString(&AdminCommentInfo.AdminComment, 1845 ((PLOCALGROUP_INFO_1)buf)->lgrpi1_comment); 1846 else 1847 RtlInitUnicodeString(&AdminCommentInfo.AdminComment, 1848 ((PLOCALGROUP_INFO_1002)buf)->lgrpi1002_comment); 1849 1850 Status = SamSetInformationAlias(AliasHandle, 1851 AliasAdminCommentInformation, 1852 &AdminCommentInfo); 1853 if (!NT_SUCCESS(Status)) 1854 { 1855 TRACE("SamSetInformationAlias failed (ApiStatus %lu)\n", ApiStatus); 1856 ApiStatus = NetpNtStatusToApiStatus(Status); 1857 goto done; 1858 } 1859 break; 1860 1861 default: 1862 ApiStatus = ERROR_INVALID_LEVEL; 1863 goto done; 1864 } 1865 1866 done: 1867 if (AliasHandle != NULL) 1868 SamCloseHandle(AliasHandle); 1869 1870 if (DomainHandle != NULL) 1871 SamCloseHandle(DomainHandle); 1872 1873 if (ServerHandle != NULL) 1874 SamCloseHandle(ServerHandle); 1875 1876 return ApiStatus; 1877 } 1878 1879 1880 /************************************************************ 1881 * NetLocalGroupSetMember (NETAPI32.@) 1882 */ 1883 NET_API_STATUS 1884 WINAPI 1885 NetLocalGroupSetMembers( 1886 LPCWSTR servername, 1887 LPCWSTR groupname, 1888 DWORD level, 1889 LPBYTE buf, 1890 DWORD totalentries) 1891 { 1892 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername), 1893 debugstr_w(groupname), level, buf, totalentries); 1894 return NERR_Success; 1895 } 1896 1897 /* EOF */ 1898