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(%wZ) failed (Status %08lx)\n", AliasName, 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 if (parm_err != NULL) 356 *parm_err = PARM_ERROR_NONE; 357 358 /* Initialize the Server name*/ 359 if (servername != NULL) 360 RtlInitUnicodeString(&ServerName, servername); 361 362 /* Initialize the Alias name*/ 363 switch (level) 364 { 365 case 0: 366 aliasname = ((PLOCALGROUP_INFO_0)buf)->lgrpi0_name; 367 aliascomment = NULL; 368 break; 369 370 case 1: 371 aliasname = ((PLOCALGROUP_INFO_1)buf)->lgrpi1_name; 372 aliascomment = ((PLOCALGROUP_INFO_1)buf)->lgrpi1_comment; 373 break; 374 375 default: 376 return ERROR_INVALID_LEVEL; 377 } 378 379 RtlInitUnicodeString(&AliasName, aliasname); 380 381 /* Connect to the SAM Server */ 382 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 383 &ServerHandle, 384 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 385 NULL); 386 if (!NT_SUCCESS(Status)) 387 { 388 ERR("SamConnect failed (Status %08lx)\n", Status); 389 ApiStatus = NetpNtStatusToApiStatus(Status); 390 goto done; 391 } 392 393 /* Open the Builtin Domain */ 394 Status = OpenBuiltinDomain(ServerHandle, 395 DOMAIN_LOOKUP, 396 &DomainHandle); 397 if (!NT_SUCCESS(Status)) 398 { 399 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 400 ApiStatus = NetpNtStatusToApiStatus(Status); 401 goto done; 402 } 403 404 /* Try to open the Alias Account in the Builtin Domain */ 405 ApiStatus = OpenAliasByName(DomainHandle, 406 &AliasName, 407 ALIAS_READ_INFORMATION, 408 &AliasHandle); 409 if (ApiStatus == NERR_Success) 410 { 411 ERR("OpenAliasByName: alias %wZ already exists!\n", &AliasName); 412 413 SamCloseHandle(AliasHandle); 414 ApiStatus = ERROR_ALIAS_EXISTS; 415 goto done; 416 } 417 418 ApiStatus = NERR_Success; 419 420 /* Close the Builtin Domain */ 421 SamCloseHandle(DomainHandle); 422 DomainHandle = NULL; 423 424 /* Open the account domain */ 425 Status = OpenAccountDomain(ServerHandle, 426 (servername != NULL) ? &ServerName : NULL, 427 DOMAIN_CREATE_ALIAS | DOMAIN_LOOKUP, 428 &DomainHandle); 429 if (!NT_SUCCESS(Status)) 430 { 431 ERR("SamOpenDomain failed (Status %08lx)\n", Status); 432 ApiStatus = NetpNtStatusToApiStatus(Status); 433 goto done; 434 } 435 436 /* Create the alias */ 437 Status = SamCreateAliasInDomain(DomainHandle, 438 &AliasName, 439 DELETE | ALIAS_WRITE_ACCOUNT, 440 &AliasHandle, 441 &RelativeId); 442 if (!NT_SUCCESS(Status)) 443 { 444 ERR("SamCreateAliasInDomain failed (Status %08lx)\n", Status); 445 ApiStatus = NetpNtStatusToApiStatus(Status); 446 goto done; 447 } 448 449 TRACE("Created alias \"%wZ\" (RID: %lu)\n", &AliasName, RelativeId); 450 451 /* Set the admin comment */ 452 if (level == 1) 453 { 454 RtlInitUnicodeString(&AdminComment.AdminComment, aliascomment); 455 456 Status = SamSetInformationAlias(AliasHandle, 457 AliasAdminCommentInformation, 458 &AdminComment); 459 if (!NT_SUCCESS(Status)) 460 { 461 ERR("SamSetInformationAlias failed (Status %08lx)\n", Status); 462 ApiStatus = NetpNtStatusToApiStatus(Status); 463 464 /* Delete the Alias if the Comment could not be set */ 465 SamDeleteAlias(AliasHandle); 466 467 goto done; 468 } 469 } 470 471 done: 472 if (AliasHandle != NULL) 473 { 474 if (ApiStatus != NERR_Success) 475 SamDeleteAlias(AliasHandle); 476 else 477 SamCloseHandle(AliasHandle); 478 } 479 480 if (DomainHandle != NULL) 481 SamCloseHandle(DomainHandle); 482 483 if (ServerHandle != NULL) 484 SamCloseHandle(ServerHandle); 485 486 return ApiStatus; 487 } 488 489 490 /************************************************************ 491 * NetLocalGroupAddMember (NETAPI32.@) 492 */ 493 NET_API_STATUS 494 WINAPI 495 NetLocalGroupAddMember( 496 LPCWSTR servername, 497 LPCWSTR groupname, 498 PSID membersid) 499 { 500 LOCALGROUP_MEMBERS_INFO_0 Member; 501 502 TRACE("(%s %s %p)\n", debugstr_w(servername), 503 debugstr_w(groupname), membersid); 504 505 Member.lgrmi0_sid = membersid; 506 507 return NetLocalGroupAddMembers(servername, 508 groupname, 509 0, 510 (LPBYTE)&Member, 511 1); 512 } 513 514 515 /************************************************************ 516 * NetLocalGroupAddMembers (NETAPI32.@) 517 */ 518 NET_API_STATUS 519 WINAPI 520 NetLocalGroupAddMembers( 521 LPCWSTR servername, 522 LPCWSTR groupname, 523 DWORD level, 524 LPBYTE buf, 525 DWORD totalentries) 526 { 527 UNICODE_STRING ServerName; 528 UNICODE_STRING AliasName; 529 SAM_HANDLE ServerHandle = NULL; 530 SAM_HANDLE DomainHandle = NULL; 531 SAM_HANDLE AliasHandle = NULL; 532 PLOCALGROUP_MEMBERS_INFO_0 MemberList = NULL; 533 ULONG i; 534 NET_API_STATUS ApiStatus = NERR_Success; 535 NTSTATUS Status = STATUS_SUCCESS; 536 537 TRACE("(%s %s %d %p %d)\n", debugstr_w(servername), 538 debugstr_w(groupname), level, buf, totalentries); 539 540 if (servername != NULL) 541 RtlInitUnicodeString(&ServerName, servername); 542 543 RtlInitUnicodeString(&AliasName, groupname); 544 545 switch (level) 546 { 547 case 0: 548 MemberList = (PLOCALGROUP_MEMBERS_INFO_0)buf; 549 break; 550 551 case 3: 552 Status = BuildSidListFromDomainAndName((servername != NULL) ? &ServerName : NULL, 553 (PLOCALGROUP_MEMBERS_INFO_3)buf, 554 totalentries, 555 &MemberList); 556 if (!NT_SUCCESS(Status)) 557 { 558 ERR("BuildSidListFromDomainAndName failed (Status %08lx)\n", Status); 559 ApiStatus = NetpNtStatusToApiStatus(Status); 560 goto done; 561 } 562 break; 563 564 default: 565 ApiStatus = ERROR_INVALID_LEVEL; 566 goto done; 567 } 568 569 /* Connect to the SAM Server */ 570 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 571 &ServerHandle, 572 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 573 NULL); 574 if (!NT_SUCCESS(Status)) 575 { 576 ERR("SamConnect failed (Status %08lx)\n", Status); 577 ApiStatus = NetpNtStatusToApiStatus(Status); 578 goto done; 579 } 580 581 /* Open the Builtin Domain */ 582 Status = OpenBuiltinDomain(ServerHandle, 583 DOMAIN_LOOKUP, 584 &DomainHandle); 585 if (!NT_SUCCESS(Status)) 586 { 587 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 588 ApiStatus = NetpNtStatusToApiStatus(Status); 589 goto done; 590 } 591 592 /* Open the alias account in the builtin domain */ 593 ApiStatus = OpenAliasByName(DomainHandle, 594 &AliasName, 595 ALIAS_ADD_MEMBER, 596 &AliasHandle); 597 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 598 { 599 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &AliasName, ApiStatus); 600 goto done; 601 } 602 603 if (AliasHandle == NULL) 604 { 605 if (DomainHandle != NULL) 606 SamCloseHandle(DomainHandle); 607 608 /* Open the Acount Domain */ 609 Status = OpenAccountDomain(ServerHandle, 610 (servername != NULL) ? &ServerName : NULL, 611 DOMAIN_LOOKUP, 612 &DomainHandle); 613 if (!NT_SUCCESS(Status)) 614 { 615 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 616 ApiStatus = NetpNtStatusToApiStatus(Status); 617 goto done; 618 } 619 620 /* Open the alias account in the account domain */ 621 ApiStatus = OpenAliasByName(DomainHandle, 622 &AliasName, 623 ALIAS_ADD_MEMBER, 624 &AliasHandle); 625 if (ApiStatus != NERR_Success) 626 { 627 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &AliasName, ApiStatus); 628 if (ApiStatus == ERROR_NONE_MAPPED) 629 ApiStatus = NERR_GroupNotFound; 630 goto done; 631 } 632 } 633 634 /* Add new members to the alias */ 635 for (i = 0; i < totalentries; i++) 636 { 637 Status = SamAddMemberToAlias(AliasHandle, 638 MemberList[i].lgrmi0_sid); 639 if (!NT_SUCCESS(Status)) 640 { 641 ERR("SamAddMemberToAlias failed (Status %lu)\n", Status); 642 ApiStatus = NetpNtStatusToApiStatus(Status); 643 goto done; 644 } 645 } 646 647 done: 648 if (level == 3 && MemberList != NULL) 649 { 650 for (i = 0; i < totalentries; i++) 651 { 652 if (MemberList[i].lgrmi0_sid != NULL) 653 NetApiBufferFree(MemberList[i].lgrmi0_sid); 654 } 655 656 NetApiBufferFree(MemberList); 657 } 658 659 if (AliasHandle != NULL) 660 SamCloseHandle(AliasHandle); 661 662 if (DomainHandle != NULL) 663 SamCloseHandle(DomainHandle); 664 665 if (ServerHandle != NULL) 666 SamCloseHandle(ServerHandle); 667 668 return ApiStatus; 669 } 670 671 672 /************************************************************ 673 * NetLocalGroupDel (NETAPI32.@) 674 */ 675 NET_API_STATUS 676 WINAPI 677 NetLocalGroupDel( 678 LPCWSTR servername, 679 LPCWSTR groupname) 680 { 681 UNICODE_STRING ServerName; 682 UNICODE_STRING GroupName; 683 SAM_HANDLE ServerHandle = NULL; 684 SAM_HANDLE DomainHandle = NULL; 685 SAM_HANDLE AliasHandle = NULL; 686 NET_API_STATUS ApiStatus = NERR_Success; 687 NTSTATUS Status = STATUS_SUCCESS; 688 689 TRACE("(%s %s)\n", debugstr_w(servername), debugstr_w(groupname)); 690 691 if (servername != NULL) 692 RtlInitUnicodeString(&ServerName, servername); 693 694 RtlInitUnicodeString(&GroupName, groupname); 695 696 /* Connect to the SAM Server */ 697 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 698 &ServerHandle, 699 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 700 NULL); 701 if (!NT_SUCCESS(Status)) 702 { 703 ERR("SamConnect failed (Status %08lx)\n", Status); 704 ApiStatus = NetpNtStatusToApiStatus(Status); 705 goto done; 706 } 707 708 /* Open the Builtin Domain */ 709 Status = OpenBuiltinDomain(ServerHandle, 710 DOMAIN_LOOKUP, 711 &DomainHandle); 712 if (!NT_SUCCESS(Status)) 713 { 714 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 715 ApiStatus = NetpNtStatusToApiStatus(Status); 716 goto done; 717 } 718 719 /* Open the alias account in the builtin domain */ 720 ApiStatus = OpenAliasByName(DomainHandle, 721 &GroupName, 722 DELETE, 723 &AliasHandle); 724 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 725 { 726 TRACE("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &GroupName, ApiStatus); 727 goto done; 728 } 729 730 if (AliasHandle == NULL) 731 { 732 if (DomainHandle != NULL) 733 { 734 SamCloseHandle(DomainHandle); 735 DomainHandle = NULL; 736 } 737 738 /* Open the Acount Domain */ 739 Status = OpenAccountDomain(ServerHandle, 740 (servername != NULL) ? &ServerName : NULL, 741 DOMAIN_LOOKUP, 742 &DomainHandle); 743 if (!NT_SUCCESS(Status)) 744 { 745 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 746 ApiStatus = NetpNtStatusToApiStatus(Status); 747 goto done; 748 } 749 750 /* Open the alias account in the account domain */ 751 ApiStatus = OpenAliasByName(DomainHandle, 752 &GroupName, 753 DELETE, 754 &AliasHandle); 755 if (ApiStatus != NERR_Success) 756 { 757 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &GroupName, ApiStatus); 758 if (ApiStatus == ERROR_NONE_MAPPED) 759 ApiStatus = NERR_GroupNotFound; 760 goto done; 761 } 762 } 763 764 /* Delete the alias */ 765 Status = SamDeleteAlias(AliasHandle); 766 if (!NT_SUCCESS(Status)) 767 { 768 ERR("SamDeleteAlias failed (Status %08lx)\n", Status); 769 ApiStatus = NetpNtStatusToApiStatus(Status); 770 goto done; 771 } 772 773 done: 774 if (AliasHandle != NULL) 775 SamCloseHandle(AliasHandle); 776 777 if (DomainHandle != NULL) 778 SamCloseHandle(DomainHandle); 779 780 if (ServerHandle != NULL) 781 SamCloseHandle(ServerHandle); 782 783 return ApiStatus; 784 } 785 786 787 /************************************************************ 788 * NetLocalGroupDelMember (NETAPI32.@) 789 */ 790 NET_API_STATUS 791 WINAPI 792 NetLocalGroupDelMember( 793 LPCWSTR servername, 794 LPCWSTR groupname, 795 PSID membersid) 796 { 797 LOCALGROUP_MEMBERS_INFO_0 Member; 798 799 TRACE("(%s %s %p)\n", debugstr_w(servername), 800 debugstr_w(groupname), membersid); 801 802 Member.lgrmi0_sid = membersid; 803 804 return NetLocalGroupDelMembers(servername, 805 groupname, 806 0, 807 (LPBYTE)&Member, 808 1); 809 } 810 811 812 /************************************************************ 813 * NetLocalGroupDelMembers (NETAPI32.@) 814 */ 815 NET_API_STATUS 816 WINAPI 817 NetLocalGroupDelMembers( 818 LPCWSTR servername, 819 LPCWSTR groupname, 820 DWORD level, 821 LPBYTE buf, 822 DWORD totalentries) 823 { 824 UNICODE_STRING ServerName; 825 UNICODE_STRING AliasName; 826 SAM_HANDLE ServerHandle = NULL; 827 SAM_HANDLE DomainHandle = NULL; 828 SAM_HANDLE AliasHandle = NULL; 829 PLOCALGROUP_MEMBERS_INFO_0 MemberList = NULL; 830 ULONG i; 831 NET_API_STATUS ApiStatus = NERR_Success; 832 NTSTATUS Status = STATUS_SUCCESS; 833 834 TRACE("(%s %s %d %p %d)\n", debugstr_w(servername), 835 debugstr_w(groupname), level, buf, totalentries); 836 837 if (servername != NULL) 838 RtlInitUnicodeString(&ServerName, servername); 839 840 RtlInitUnicodeString(&AliasName, groupname); 841 842 switch (level) 843 { 844 case 0: 845 MemberList = (PLOCALGROUP_MEMBERS_INFO_0)buf; 846 break; 847 848 case 3: 849 Status = BuildSidListFromDomainAndName((servername != NULL) ? &ServerName : NULL, 850 (PLOCALGROUP_MEMBERS_INFO_3)buf, 851 totalentries, 852 &MemberList); 853 if (!NT_SUCCESS(Status)) 854 { 855 ERR("BuildSidListFromDomainAndName failed (Status %08lx)\n", Status); 856 ApiStatus = NetpNtStatusToApiStatus(Status); 857 goto done; 858 } 859 break; 860 861 default: 862 ApiStatus = ERROR_INVALID_LEVEL; 863 goto done; 864 } 865 866 /* Connect to the SAM Server */ 867 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 868 &ServerHandle, 869 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 870 NULL); 871 if (!NT_SUCCESS(Status)) 872 { 873 ERR("SamConnect failed (Status %08lx)\n", Status); 874 ApiStatus = NetpNtStatusToApiStatus(Status); 875 goto done; 876 } 877 878 /* Open the Builtin Domain */ 879 Status = OpenBuiltinDomain(ServerHandle, 880 DOMAIN_LOOKUP, 881 &DomainHandle); 882 if (!NT_SUCCESS(Status)) 883 { 884 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 885 ApiStatus = NetpNtStatusToApiStatus(Status); 886 goto done; 887 } 888 889 /* Open the alias account in the builtin domain */ 890 ApiStatus = OpenAliasByName(DomainHandle, 891 &AliasName, 892 ALIAS_REMOVE_MEMBER, 893 &AliasHandle); 894 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 895 { 896 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &AliasName, ApiStatus); 897 goto done; 898 } 899 900 if (AliasHandle == NULL) 901 { 902 if (DomainHandle != NULL) 903 SamCloseHandle(DomainHandle); 904 905 /* Open the Acount Domain */ 906 Status = OpenAccountDomain(ServerHandle, 907 (servername != NULL) ? &ServerName : NULL, 908 DOMAIN_LOOKUP, 909 &DomainHandle); 910 if (!NT_SUCCESS(Status)) 911 { 912 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 913 ApiStatus = NetpNtStatusToApiStatus(Status); 914 goto done; 915 } 916 917 /* Open the alias account in the account domain */ 918 ApiStatus = OpenAliasByName(DomainHandle, 919 &AliasName, 920 ALIAS_REMOVE_MEMBER, 921 &AliasHandle); 922 if (ApiStatus != NERR_Success) 923 { 924 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &AliasName, ApiStatus); 925 if (ApiStatus == ERROR_NONE_MAPPED) 926 ApiStatus = NERR_GroupNotFound; 927 goto done; 928 } 929 } 930 931 /* Remove members from the alias */ 932 for (i = 0; i < totalentries; i++) 933 { 934 Status = SamRemoveMemberFromAlias(AliasHandle, 935 MemberList[i].lgrmi0_sid); 936 if (!NT_SUCCESS(Status)) 937 { 938 ERR("SamAddMemberToAlias failed (Status %lu)\n", Status); 939 ApiStatus = NetpNtStatusToApiStatus(Status); 940 goto done; 941 } 942 } 943 944 done: 945 if (level == 3 && MemberList != NULL) 946 { 947 for (i = 0; i < totalentries; i++) 948 { 949 if (MemberList[i].lgrmi0_sid != NULL) 950 NetApiBufferFree(MemberList[i].lgrmi0_sid); 951 } 952 953 NetApiBufferFree(MemberList); 954 } 955 956 if (AliasHandle != NULL) 957 SamCloseHandle(AliasHandle); 958 959 if (DomainHandle != NULL) 960 SamCloseHandle(DomainHandle); 961 962 if (ServerHandle != NULL) 963 SamCloseHandle(ServerHandle); 964 965 return ApiStatus; 966 } 967 968 969 /************************************************************ 970 * NetLocalGroupEnum (NETAPI32.@) 971 */ 972 NET_API_STATUS 973 WINAPI 974 NetLocalGroupEnum( 975 LPCWSTR servername, 976 DWORD level, 977 LPBYTE* bufptr, 978 DWORD prefmaxlen, 979 LPDWORD entriesread, 980 LPDWORD totalentries, 981 PDWORD_PTR resumehandle) 982 { 983 UNICODE_STRING ServerName; 984 PSAM_RID_ENUMERATION CurrentAlias; 985 PENUM_CONTEXT EnumContext = NULL; 986 ULONG i; 987 SAM_HANDLE AliasHandle = NULL; 988 PALIAS_GENERAL_INFORMATION AliasInfo = NULL; 989 LPVOID Buffer = NULL; 990 NET_API_STATUS ApiStatus = NERR_Success; 991 NTSTATUS Status = STATUS_SUCCESS; 992 993 TRACE("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername), 994 level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle); 995 996 *entriesread = 0; 997 *totalentries = 0; 998 *bufptr = NULL; 999 1000 if (servername != NULL) 1001 RtlInitUnicodeString(&ServerName, servername); 1002 1003 if (resumehandle != NULL && *resumehandle != 0) 1004 { 1005 EnumContext = (PENUM_CONTEXT)*resumehandle; 1006 } 1007 else 1008 { 1009 ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext); 1010 if (ApiStatus != NERR_Success) 1011 goto done; 1012 1013 EnumContext->EnumerationContext = 0; 1014 EnumContext->Buffer = NULL; 1015 EnumContext->Returned = 0; 1016 EnumContext->Index = 0; 1017 1018 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 1019 &EnumContext->ServerHandle, 1020 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 1021 NULL); 1022 if (!NT_SUCCESS(Status)) 1023 { 1024 ERR("SamConnect failed (Status %08lx)\n", Status); 1025 ApiStatus = NetpNtStatusToApiStatus(Status); 1026 goto done; 1027 } 1028 1029 Status = OpenAccountDomain(EnumContext->ServerHandle, 1030 (servername != NULL) ? &ServerName : NULL, 1031 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, 1032 &EnumContext->AccountDomainHandle); 1033 if (!NT_SUCCESS(Status)) 1034 { 1035 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 1036 ApiStatus = NetpNtStatusToApiStatus(Status); 1037 goto done; 1038 } 1039 1040 Status = OpenBuiltinDomain(EnumContext->ServerHandle, 1041 DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, 1042 &EnumContext->BuiltinDomainHandle); 1043 if (!NT_SUCCESS(Status)) 1044 { 1045 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 1046 ApiStatus = NetpNtStatusToApiStatus(Status); 1047 goto done; 1048 } 1049 1050 EnumContext->Phase = BuiltinPhase; 1051 EnumContext->DomainHandle = EnumContext->BuiltinDomainHandle; 1052 } 1053 1054 1055 // while (TRUE) 1056 // { 1057 TRACE("EnumContext->Index: %lu\n", EnumContext->Index); 1058 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned); 1059 1060 if (EnumContext->Index >= EnumContext->Returned) 1061 { 1062 TRACE("Calling SamEnumerateAliasesInDomain\n"); 1063 1064 Status = SamEnumerateAliasesInDomain(EnumContext->DomainHandle, 1065 &EnumContext->EnumerationContext, 1066 (PVOID *)&EnumContext->Buffer, 1067 prefmaxlen, 1068 &EnumContext->Returned); 1069 1070 TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status); 1071 if (!NT_SUCCESS(Status)) 1072 { 1073 ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status); 1074 ApiStatus = NetpNtStatusToApiStatus(Status); 1075 goto done; 1076 } 1077 1078 if (Status == STATUS_MORE_ENTRIES) 1079 { 1080 ApiStatus = NERR_BufTooSmall; 1081 goto done; 1082 } 1083 } 1084 1085 TRACE("EnumContext: %lu\n", EnumContext); 1086 TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned); 1087 TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer); 1088 1089 /* Get a pointer to the current alias */ 1090 CurrentAlias = &EnumContext->Buffer[EnumContext->Index]; 1091 1092 TRACE("RID: %lu\n", CurrentAlias->RelativeId); 1093 1094 Status = SamOpenAlias(EnumContext->DomainHandle, 1095 ALIAS_READ_INFORMATION, 1096 CurrentAlias->RelativeId, 1097 &AliasHandle); 1098 if (!NT_SUCCESS(Status)) 1099 { 1100 ERR("SamOpenAlias failed (Status %08lx)\n", Status); 1101 ApiStatus = NetpNtStatusToApiStatus(Status); 1102 goto done; 1103 } 1104 1105 Status = SamQueryInformationAlias(AliasHandle, 1106 AliasGeneralInformation, 1107 (PVOID *)&AliasInfo); 1108 if (!NT_SUCCESS(Status)) 1109 { 1110 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status); 1111 ApiStatus = NetpNtStatusToApiStatus(Status); 1112 goto done; 1113 } 1114 1115 SamCloseHandle(AliasHandle); 1116 AliasHandle = NULL; 1117 1118 TRACE("Name: %S\n", AliasInfo->Name.Buffer); 1119 TRACE("Comment: %S\n", AliasInfo->AdminComment.Buffer); 1120 1121 ApiStatus = BuildAliasInfoBuffer(AliasInfo, 1122 level, 1123 &Buffer); 1124 if (ApiStatus != NERR_Success) 1125 goto done; 1126 1127 if (AliasInfo != NULL) 1128 { 1129 FreeAliasInfo(AliasInfo); 1130 AliasInfo = NULL; 1131 } 1132 1133 EnumContext->Index++; 1134 1135 (*entriesread)++; 1136 1137 if (EnumContext->Index == EnumContext->Returned) 1138 { 1139 switch (EnumContext->Phase) 1140 { 1141 case BuiltinPhase: 1142 EnumContext->Phase = AccountPhase; 1143 EnumContext->DomainHandle = EnumContext->AccountDomainHandle; 1144 EnumContext->EnumerationContext = 0; 1145 EnumContext->Index = 0; 1146 EnumContext->Returned = 0; 1147 1148 if (EnumContext->Buffer != NULL) 1149 { 1150 for (i = 0; i < EnumContext->Returned; i++) 1151 { 1152 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer); 1153 } 1154 1155 SamFreeMemory(EnumContext->Buffer); 1156 EnumContext->Buffer = NULL; 1157 } 1158 break; 1159 1160 case AccountPhase: 1161 case DonePhase: 1162 EnumContext->Phase = DonePhase; 1163 break; 1164 } 1165 } 1166 // } 1167 1168 done: 1169 if (ApiStatus == NERR_Success && EnumContext != NULL && EnumContext->Phase != DonePhase) 1170 ApiStatus = ERROR_MORE_DATA; 1171 1172 if (EnumContext != NULL) 1173 *totalentries = EnumContext->Returned; 1174 1175 if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA) 1176 { 1177 if (EnumContext != NULL) 1178 { 1179 if (EnumContext->BuiltinDomainHandle != NULL) 1180 SamCloseHandle(EnumContext->BuiltinDomainHandle); 1181 1182 if (EnumContext->AccountDomainHandle != NULL) 1183 SamCloseHandle(EnumContext->AccountDomainHandle); 1184 1185 if (EnumContext->ServerHandle != NULL) 1186 SamCloseHandle(EnumContext->ServerHandle); 1187 1188 if (EnumContext->Buffer != NULL) 1189 { 1190 for (i = 0; i < EnumContext->Returned; i++) 1191 { 1192 SamFreeMemory(EnumContext->Buffer[i].Name.Buffer); 1193 } 1194 1195 SamFreeMemory(EnumContext->Buffer); 1196 } 1197 1198 NetApiBufferFree(EnumContext); 1199 EnumContext = NULL; 1200 } 1201 } 1202 1203 if (AliasHandle != NULL) 1204 SamCloseHandle(AliasHandle); 1205 1206 if (AliasInfo != NULL) 1207 FreeAliasInfo(AliasInfo); 1208 1209 if (resumehandle != NULL) 1210 *resumehandle = (DWORD_PTR)EnumContext; 1211 1212 *bufptr = (LPBYTE)Buffer; 1213 1214 TRACE ("return %lu\n", ApiStatus); 1215 1216 return ApiStatus; 1217 } 1218 1219 1220 /************************************************************ 1221 * NetLocalGroupGetInfo (NETAPI32.@) 1222 */ 1223 NET_API_STATUS 1224 WINAPI 1225 NetLocalGroupGetInfo( 1226 LPCWSTR servername, 1227 LPCWSTR groupname, 1228 DWORD level, 1229 LPBYTE* bufptr) 1230 { 1231 UNICODE_STRING ServerName; 1232 UNICODE_STRING GroupName; 1233 SAM_HANDLE ServerHandle = NULL; 1234 SAM_HANDLE DomainHandle = NULL; 1235 SAM_HANDLE AliasHandle = NULL; 1236 PALIAS_GENERAL_INFORMATION AliasInfo = NULL; 1237 LPVOID Buffer = NULL; 1238 NET_API_STATUS ApiStatus = NERR_Success; 1239 NTSTATUS Status = STATUS_SUCCESS; 1240 1241 TRACE("(%s %s %d %p) stub!\n", debugstr_w(servername), 1242 debugstr_w(groupname), level, bufptr); 1243 1244 if (servername != NULL) 1245 RtlInitUnicodeString(&ServerName, servername); 1246 1247 RtlInitUnicodeString(&GroupName, groupname); 1248 1249 /* Connect to the SAM Server */ 1250 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 1251 &ServerHandle, 1252 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 1253 NULL); 1254 if (!NT_SUCCESS(Status)) 1255 { 1256 ERR("SamConnect failed (Status %08lx)\n", Status); 1257 ApiStatus = NetpNtStatusToApiStatus(Status); 1258 goto done; 1259 } 1260 1261 /* Open the Builtin Domain */ 1262 Status = OpenBuiltinDomain(ServerHandle, 1263 DOMAIN_LOOKUP, 1264 &DomainHandle); 1265 if (!NT_SUCCESS(Status)) 1266 { 1267 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 1268 ApiStatus = NetpNtStatusToApiStatus(Status); 1269 goto done; 1270 } 1271 1272 /* Open the alias account in the builtin domain */ 1273 ApiStatus = OpenAliasByName(DomainHandle, 1274 &GroupName, 1275 ALIAS_READ_INFORMATION, 1276 &AliasHandle); 1277 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 1278 { 1279 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &GroupName, ApiStatus); 1280 goto done; 1281 } 1282 1283 if (AliasHandle == NULL) 1284 { 1285 if (DomainHandle != NULL) 1286 SamCloseHandle(DomainHandle); 1287 1288 /* Open the Acount Domain */ 1289 Status = OpenAccountDomain(ServerHandle, 1290 (servername != NULL) ? &ServerName : NULL, 1291 DOMAIN_LOOKUP, 1292 &DomainHandle); 1293 if (!NT_SUCCESS(Status)) 1294 { 1295 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 1296 ApiStatus = NetpNtStatusToApiStatus(Status); 1297 goto done; 1298 } 1299 1300 /* Open the alias account in the account domain */ 1301 ApiStatus = OpenAliasByName(DomainHandle, 1302 &GroupName, 1303 ALIAS_READ_INFORMATION, 1304 &AliasHandle); 1305 if (ApiStatus != NERR_Success) 1306 { 1307 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &GroupName, ApiStatus); 1308 if (ApiStatus == ERROR_NONE_MAPPED) 1309 ApiStatus = NERR_GroupNotFound; 1310 goto done; 1311 } 1312 } 1313 1314 Status = SamQueryInformationAlias(AliasHandle, 1315 AliasGeneralInformation, 1316 (PVOID *)&AliasInfo); 1317 if (!NT_SUCCESS(Status)) 1318 { 1319 ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status); 1320 ApiStatus = NetpNtStatusToApiStatus(Status); 1321 goto done; 1322 } 1323 1324 ApiStatus = BuildAliasInfoBuffer(AliasInfo, 1325 level, 1326 &Buffer); 1327 if (ApiStatus != NERR_Success) 1328 goto done; 1329 1330 done: 1331 if (AliasInfo != NULL) 1332 FreeAliasInfo(AliasInfo); 1333 1334 if (AliasHandle != NULL) 1335 SamCloseHandle(AliasHandle); 1336 1337 if (DomainHandle != NULL) 1338 SamCloseHandle(DomainHandle); 1339 1340 if (ServerHandle != NULL) 1341 SamCloseHandle(ServerHandle); 1342 1343 *bufptr = (LPBYTE)Buffer; 1344 1345 return ApiStatus; 1346 } 1347 1348 1349 /************************************************************ 1350 * NetLocalGroupGetMembers (NETAPI32.@) 1351 */ 1352 NET_API_STATUS 1353 WINAPI 1354 NetLocalGroupGetMembers( 1355 LPCWSTR servername, 1356 LPCWSTR localgroupname, 1357 DWORD level, 1358 LPBYTE* bufptr, 1359 DWORD prefmaxlen, 1360 LPDWORD entriesread, 1361 LPDWORD totalentries, 1362 PDWORD_PTR resumehandle) 1363 { 1364 OBJECT_ATTRIBUTES ObjectAttributes; 1365 UNICODE_STRING ServerName; 1366 UNICODE_STRING AliasName; 1367 PMEMBER_ENUM_CONTEXT EnumContext = NULL; 1368 LPVOID Buffer = NULL; 1369 PLOCALGROUP_MEMBERS_INFO_0 MembersInfo0; 1370 PLOCALGROUP_MEMBERS_INFO_1 MembersInfo1; 1371 PLOCALGROUP_MEMBERS_INFO_2 MembersInfo2; 1372 PLOCALGROUP_MEMBERS_INFO_3 MembersInfo3; 1373 LPWSTR Ptr; 1374 ULONG Size = 0; 1375 ULONG SidLength; 1376 ULONG i; 1377 NET_API_STATUS ApiStatus = NERR_Success; 1378 NTSTATUS Status = STATUS_SUCCESS; 1379 1380 TRACE("(%s %s %d %p %d %p %p %p)\n", debugstr_w(servername), 1381 debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread, 1382 totalentries, resumehandle); 1383 1384 *entriesread = 0; 1385 *totalentries = 0; 1386 *bufptr = NULL; 1387 1388 if (servername != NULL) 1389 RtlInitUnicodeString(&ServerName, servername); 1390 1391 RtlInitUnicodeString(&AliasName, localgroupname); 1392 1393 if (resumehandle != NULL && *resumehandle != 0) 1394 { 1395 EnumContext = (PMEMBER_ENUM_CONTEXT)*resumehandle; 1396 } 1397 else 1398 { 1399 /* Allocate the enumeration context */ 1400 ApiStatus = NetApiBufferAllocate(sizeof(MEMBER_ENUM_CONTEXT), (PVOID*)&EnumContext); 1401 if (ApiStatus != NERR_Success) 1402 goto done; 1403 1404 /* Connect to the SAM Server */ 1405 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 1406 &EnumContext->ServerHandle, 1407 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 1408 NULL); 1409 if (!NT_SUCCESS(Status)) 1410 { 1411 ERR("SamConnect failed (Status %08lx)\n", Status); 1412 ApiStatus = NetpNtStatusToApiStatus(Status); 1413 goto done; 1414 } 1415 1416 /* Open the Builtin Domain */ 1417 Status = OpenBuiltinDomain(EnumContext->ServerHandle, 1418 DOMAIN_LOOKUP, 1419 &EnumContext->DomainHandle); 1420 if (!NT_SUCCESS(Status)) 1421 { 1422 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 1423 ApiStatus = NetpNtStatusToApiStatus(Status); 1424 goto done; 1425 } 1426 1427 /* Open the alias account in the builtin domain */ 1428 ApiStatus = OpenAliasByName(EnumContext->DomainHandle, 1429 &AliasName, 1430 ALIAS_LIST_MEMBERS, 1431 &EnumContext->AliasHandle); 1432 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 1433 { 1434 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &AliasName, ApiStatus); 1435 goto done; 1436 } 1437 1438 if (EnumContext->AliasHandle == NULL) 1439 { 1440 if (EnumContext->DomainHandle != NULL) 1441 SamCloseHandle(EnumContext->DomainHandle); 1442 1443 /* Open the Acount Domain */ 1444 Status = OpenAccountDomain(EnumContext->ServerHandle, 1445 (servername != NULL) ? &ServerName : NULL, 1446 DOMAIN_LOOKUP, 1447 &EnumContext->DomainHandle); 1448 if (!NT_SUCCESS(Status)) 1449 { 1450 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 1451 ApiStatus = NetpNtStatusToApiStatus(Status); 1452 goto done; 1453 } 1454 1455 /* Open the alias account in the account domain */ 1456 ApiStatus = OpenAliasByName(EnumContext->DomainHandle, 1457 &AliasName, 1458 ALIAS_LIST_MEMBERS, 1459 &EnumContext->AliasHandle); 1460 if (ApiStatus != NERR_Success) 1461 { 1462 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &AliasName, ApiStatus); 1463 if (ApiStatus == ERROR_NONE_MAPPED) 1464 ApiStatus = NERR_GroupNotFound; 1465 goto done; 1466 } 1467 } 1468 1469 /* Get the member list */ 1470 Status = SamGetMembersInAlias(EnumContext->AliasHandle, 1471 &EnumContext->Sids, 1472 &EnumContext->Count); 1473 if (!NT_SUCCESS(Status)) 1474 { 1475 ERR("SamGetMemberInAlias failed (Status %08lx)\n", Status); 1476 ApiStatus = NetpNtStatusToApiStatus(Status); 1477 goto done; 1478 } 1479 1480 if (EnumContext->Count == 0) 1481 { 1482 TRACE("No member found. We're done.\n"); 1483 ApiStatus = NERR_Success; 1484 goto done; 1485 } 1486 1487 /* Get name and domain information for all members */ 1488 if (level != 0) 1489 { 1490 InitializeObjectAttributes(&ObjectAttributes, 1491 NULL, 1492 0, 1493 0, 1494 NULL); 1495 1496 Status = LsaOpenPolicy((servername != NULL) ? &ServerName : NULL, 1497 (PLSA_OBJECT_ATTRIBUTES)&ObjectAttributes, 1498 POLICY_EXECUTE, 1499 &EnumContext->LsaHandle); 1500 if (!NT_SUCCESS(Status)) 1501 { 1502 ApiStatus = NetpNtStatusToApiStatus(Status); 1503 goto done; 1504 } 1505 1506 Status = LsaLookupSids(EnumContext->LsaHandle, 1507 EnumContext->Count, 1508 EnumContext->Sids, 1509 &EnumContext->Domains, 1510 &EnumContext->Names); 1511 if (!NT_SUCCESS(Status)) 1512 { 1513 ApiStatus = NetpNtStatusToApiStatus(Status); 1514 goto done; 1515 } 1516 } 1517 } 1518 1519 /* Calculate the required buffer size */ 1520 for (i = 0; i < EnumContext->Count; i++) 1521 { 1522 switch (level) 1523 { 1524 case 0: 1525 Size += sizeof(LOCALGROUP_MEMBERS_INFO_0) + 1526 RtlLengthSid(EnumContext->Sids[i]); 1527 break; 1528 1529 case 1: 1530 Size += sizeof(LOCALGROUP_MEMBERS_INFO_1) + 1531 RtlLengthSid(EnumContext->Sids[i]) + 1532 EnumContext->Names[i].Name.Length + sizeof(WCHAR); 1533 break; 1534 1535 case 2: 1536 Size += sizeof(LOCALGROUP_MEMBERS_INFO_2) + 1537 RtlLengthSid(EnumContext->Sids[i]) + 1538 EnumContext->Names[i].Name.Length + sizeof(WCHAR); 1539 if (EnumContext->Names[i].DomainIndex >= 0) 1540 Size += EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length + sizeof(WCHAR); 1541 break; 1542 1543 case 3: 1544 Size += sizeof(LOCALGROUP_MEMBERS_INFO_3) + 1545 EnumContext->Names[i].Name.Length + sizeof(WCHAR); 1546 if (EnumContext->Names[i].DomainIndex >= 0) 1547 Size += EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length + sizeof(WCHAR); 1548 break; 1549 1550 default: 1551 ApiStatus = ERROR_INVALID_LEVEL; 1552 goto done; 1553 } 1554 } 1555 1556 /* Allocate the member buffer */ 1557 ApiStatus = NetApiBufferAllocate(Size, &Buffer); 1558 if (ApiStatus != NERR_Success) 1559 goto done; 1560 1561 ZeroMemory(Buffer, Size); 1562 1563 /* Fill the member buffer */ 1564 switch (level) 1565 { 1566 case 0: 1567 MembersInfo0 = (PLOCALGROUP_MEMBERS_INFO_0)Buffer; 1568 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_0) * EnumContext->Count); 1569 break; 1570 1571 case 1: 1572 MembersInfo1 = (PLOCALGROUP_MEMBERS_INFO_1)Buffer; 1573 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_1) * EnumContext->Count); 1574 break; 1575 1576 case 2: 1577 MembersInfo2 = (PLOCALGROUP_MEMBERS_INFO_2)Buffer; 1578 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_2) * EnumContext->Count); 1579 break; 1580 1581 case 3: 1582 MembersInfo3 = (PLOCALGROUP_MEMBERS_INFO_3)Buffer; 1583 Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_3) * EnumContext->Count); 1584 break; 1585 } 1586 1587 for (i = 0; i < EnumContext->Count; i++) 1588 { 1589 switch (level) 1590 { 1591 case 0: 1592 MembersInfo0->lgrmi0_sid = (PSID)Ptr; 1593 1594 SidLength = RtlLengthSid(EnumContext->Sids[i]); 1595 memcpy(MembersInfo0->lgrmi0_sid, 1596 EnumContext->Sids[i], 1597 SidLength); 1598 Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength); 1599 MembersInfo0++; 1600 break; 1601 1602 case 1: 1603 MembersInfo1->lgrmi1_sid = (PSID)Ptr; 1604 1605 SidLength = RtlLengthSid(EnumContext->Sids[i]); 1606 memcpy(MembersInfo1->lgrmi1_sid, 1607 EnumContext->Sids[i], 1608 SidLength); 1609 1610 Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength); 1611 1612 MembersInfo1->lgrmi1_sidusage = EnumContext->Names[i].Use; 1613 1614 TRACE("Name: %S\n", EnumContext->Names[i].Name.Buffer); 1615 1616 MembersInfo1->lgrmi1_name = Ptr; 1617 1618 memcpy(MembersInfo1->lgrmi1_name, 1619 EnumContext->Names[i].Name.Buffer, 1620 EnumContext->Names[i].Name.Length); 1621 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR)); 1622 MembersInfo1++; 1623 break; 1624 1625 case 2: 1626 MembersInfo2->lgrmi2_sid = (PSID)Ptr; 1627 1628 SidLength = RtlLengthSid(EnumContext->Sids[i]); 1629 memcpy(MembersInfo2->lgrmi2_sid, 1630 EnumContext->Sids[i], 1631 SidLength); 1632 1633 Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength); 1634 1635 MembersInfo2->lgrmi2_sidusage = EnumContext->Names[i].Use; 1636 1637 MembersInfo2->lgrmi2_domainandname = Ptr; 1638 1639 if (EnumContext->Names[i].DomainIndex >= 0) 1640 { 1641 memcpy(MembersInfo2->lgrmi2_domainandname, 1642 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Buffer, 1643 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length); 1644 1645 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length); 1646 1647 *((LPWSTR)Ptr) = L'\\'; 1648 1649 Ptr = (PVOID)((ULONG_PTR)Ptr + sizeof(WCHAR)); 1650 } 1651 1652 memcpy(Ptr, 1653 EnumContext->Names[i].Name.Buffer, 1654 EnumContext->Names[i].Name.Length); 1655 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR)); 1656 MembersInfo2++; 1657 break; 1658 1659 case 3: 1660 MembersInfo3->lgrmi3_domainandname = Ptr; 1661 1662 if (EnumContext->Names[i].DomainIndex >= 0) 1663 { 1664 memcpy(MembersInfo3->lgrmi3_domainandname, 1665 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Buffer, 1666 EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length); 1667 1668 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length); 1669 1670 *((LPWSTR)Ptr) = L'\\'; 1671 1672 Ptr = (PVOID)((ULONG_PTR)Ptr + sizeof(WCHAR)); 1673 } 1674 1675 memcpy(Ptr, 1676 EnumContext->Names[i].Name.Buffer, 1677 EnumContext->Names[i].Name.Length); 1678 Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR)); 1679 MembersInfo3++; 1680 break; 1681 } 1682 } 1683 1684 *entriesread = EnumContext->Count; 1685 1686 *bufptr = (LPBYTE)Buffer; 1687 1688 done: 1689 if (EnumContext != NULL) 1690 *totalentries = EnumContext->Count; 1691 1692 if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA) 1693 { 1694 /* Release the enumeration context */ 1695 if (EnumContext != NULL) 1696 { 1697 if (EnumContext->LsaHandle != NULL) 1698 LsaClose(EnumContext->LsaHandle); 1699 1700 if (EnumContext->AliasHandle != NULL) 1701 SamCloseHandle(EnumContext->AliasHandle); 1702 1703 if (EnumContext->DomainHandle != NULL) 1704 SamCloseHandle(EnumContext->DomainHandle); 1705 1706 if (EnumContext->ServerHandle != NULL) 1707 SamCloseHandle(EnumContext->ServerHandle); 1708 1709 if (EnumContext->Sids != NULL) 1710 SamFreeMemory(EnumContext->Sids); 1711 1712 if (EnumContext->Domains != NULL) 1713 LsaFreeMemory(EnumContext->Domains); 1714 1715 if (EnumContext->Names != NULL) 1716 LsaFreeMemory(EnumContext->Names); 1717 1718 NetApiBufferFree(EnumContext); 1719 EnumContext = NULL; 1720 } 1721 } 1722 1723 return ApiStatus; 1724 } 1725 1726 1727 /************************************************************ 1728 * NetLocalGroupSetInfo (NETAPI32.@) 1729 */ 1730 NET_API_STATUS 1731 WINAPI 1732 NetLocalGroupSetInfo( 1733 LPCWSTR servername, 1734 LPCWSTR groupname, 1735 DWORD level, 1736 LPBYTE buf, 1737 LPDWORD parm_err) 1738 { 1739 UNICODE_STRING ServerName; 1740 UNICODE_STRING AliasName; 1741 SAM_HANDLE ServerHandle = NULL; 1742 SAM_HANDLE DomainHandle = NULL; 1743 SAM_HANDLE AliasHandle = NULL; 1744 ALIAS_NAME_INFORMATION AliasNameInfo; 1745 ALIAS_ADM_COMMENT_INFORMATION AdminCommentInfo; 1746 NET_API_STATUS ApiStatus = NERR_Success; 1747 NTSTATUS Status = STATUS_SUCCESS; 1748 1749 TRACE("(%s %s %d %p %p)\n", debugstr_w(servername), 1750 debugstr_w(groupname), level, buf, parm_err); 1751 1752 if (parm_err != NULL) 1753 *parm_err = PARM_ERROR_NONE; 1754 1755 if (servername != NULL) 1756 RtlInitUnicodeString(&ServerName, servername); 1757 1758 RtlInitUnicodeString(&AliasName, groupname); 1759 1760 /* Connect to the SAM Server */ 1761 Status = SamConnect((servername != NULL) ? &ServerName : NULL, 1762 &ServerHandle, 1763 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, 1764 NULL); 1765 if (!NT_SUCCESS(Status)) 1766 { 1767 ERR("SamConnect failed (Status %08lx)\n", Status); 1768 ApiStatus = NetpNtStatusToApiStatus(Status); 1769 goto done; 1770 } 1771 1772 /* Open the Builtin Domain */ 1773 Status = OpenBuiltinDomain(ServerHandle, 1774 DOMAIN_LOOKUP, 1775 &DomainHandle); 1776 if (!NT_SUCCESS(Status)) 1777 { 1778 ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status); 1779 ApiStatus = NetpNtStatusToApiStatus(Status); 1780 goto done; 1781 } 1782 1783 /* Open the alias account in the builtin domain */ 1784 ApiStatus = OpenAliasByName(DomainHandle, 1785 &AliasName, 1786 ALIAS_WRITE_ACCOUNT, 1787 &AliasHandle); 1788 if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED) 1789 { 1790 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &AliasName, ApiStatus); 1791 goto done; 1792 } 1793 1794 if (AliasHandle == NULL) 1795 { 1796 if (DomainHandle != NULL) 1797 SamCloseHandle(DomainHandle); 1798 1799 /* Open the Acount Domain */ 1800 Status = OpenAccountDomain(ServerHandle, 1801 (servername != NULL) ? &ServerName : NULL, 1802 DOMAIN_LOOKUP, 1803 &DomainHandle); 1804 if (!NT_SUCCESS(Status)) 1805 { 1806 ERR("OpenAccountDomain failed (Status %08lx)\n", Status); 1807 ApiStatus = NetpNtStatusToApiStatus(Status); 1808 goto done; 1809 } 1810 1811 /* Open the alias account in the account domain */ 1812 ApiStatus = OpenAliasByName(DomainHandle, 1813 &AliasName, 1814 ALIAS_WRITE_ACCOUNT, 1815 &AliasHandle); 1816 if (ApiStatus != NERR_Success) 1817 { 1818 ERR("OpenAliasByName(%wZ) failed (ApiStatus %lu)\n", &AliasName, ApiStatus); 1819 if (ApiStatus == ERROR_NONE_MAPPED) 1820 ApiStatus = NERR_GroupNotFound; 1821 goto done; 1822 } 1823 } 1824 1825 switch (level) 1826 { 1827 case 0: 1828 /* Set the alias name */ 1829 RtlInitUnicodeString(&AliasNameInfo.Name, 1830 ((PLOCALGROUP_INFO_0)buf)->lgrpi0_name); 1831 1832 Status = SamSetInformationAlias(AliasHandle, 1833 AliasNameInformation, 1834 &AliasNameInfo); 1835 if (!NT_SUCCESS(Status)) 1836 { 1837 TRACE("SamSetInformationAlias failed (ApiStatus %lu)\n", ApiStatus); 1838 ApiStatus = NetpNtStatusToApiStatus(Status); 1839 goto done; 1840 } 1841 break; 1842 1843 case 1: 1844 case 1002: 1845 /* Set the alias admin comment */ 1846 if (level == 1) 1847 RtlInitUnicodeString(&AdminCommentInfo.AdminComment, 1848 ((PLOCALGROUP_INFO_1)buf)->lgrpi1_comment); 1849 else 1850 RtlInitUnicodeString(&AdminCommentInfo.AdminComment, 1851 ((PLOCALGROUP_INFO_1002)buf)->lgrpi1002_comment); 1852 1853 Status = SamSetInformationAlias(AliasHandle, 1854 AliasAdminCommentInformation, 1855 &AdminCommentInfo); 1856 if (!NT_SUCCESS(Status)) 1857 { 1858 TRACE("SamSetInformationAlias failed (ApiStatus %lu)\n", ApiStatus); 1859 ApiStatus = NetpNtStatusToApiStatus(Status); 1860 goto done; 1861 } 1862 break; 1863 1864 default: 1865 ApiStatus = ERROR_INVALID_LEVEL; 1866 goto done; 1867 } 1868 1869 done: 1870 if (AliasHandle != NULL) 1871 SamCloseHandle(AliasHandle); 1872 1873 if (DomainHandle != NULL) 1874 SamCloseHandle(DomainHandle); 1875 1876 if (ServerHandle != NULL) 1877 SamCloseHandle(ServerHandle); 1878 1879 return ApiStatus; 1880 } 1881 1882 1883 /************************************************************ 1884 * NetLocalGroupSetMember (NETAPI32.@) 1885 */ 1886 NET_API_STATUS 1887 WINAPI 1888 NetLocalGroupSetMembers( 1889 LPCWSTR servername, 1890 LPCWSTR groupname, 1891 DWORD level, 1892 LPBYTE buf, 1893 DWORD totalentries) 1894 { 1895 FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername), 1896 debugstr_w(groupname), level, buf, totalentries); 1897 return NERR_Success; 1898 } 1899 1900 /* EOF */ 1901