WINE_DEFAULT_DEBUG_CHANNEL(netapi32);
+typedef enum _ENUM_PHASE
+{
+ BuiltinPhase,
+ AccountPhase,
+ DonePhase
+} ENUM_PHASE;
+
typedef struct _ENUM_CONTEXT
{
SAM_HANDLE ServerHandle;
+ SAM_HANDLE DomainHandle;
SAM_HANDLE BuiltinDomainHandle;
SAM_HANDLE AccountDomainHandle;
PSAM_RID_ENUMERATION Buffer;
ULONG Returned;
ULONG Index;
- BOOLEAN BuiltinDone;
+ ENUM_PHASE Phase;
} ENUM_CONTEXT, *PENUM_CONTEXT;
+typedef struct _MEMBER_ENUM_CONTEXT
+{
+ SAM_HANDLE ServerHandle;
+ SAM_HANDLE DomainHandle;
+ SAM_HANDLE AliasHandle;
+ LSA_HANDLE LsaHandle;
+
+ PSID *Sids;
+ ULONG Count;
+ PLSA_REFERENCED_DOMAIN_LIST Domains;
+ PLSA_TRANSLATED_NAME Names;
+
+} MEMBER_ENUM_CONTEXT, *PMEMBER_ENUM_CONTEXT;
+
static
NET_API_STATUS
}
+static
+NET_API_STATUS
+BuildSidListFromDomainAndName(IN PUNICODE_STRING ServerName,
+ IN PLOCALGROUP_MEMBERS_INFO_3 buf,
+ IN ULONG EntryCount,
+ OUT PLOCALGROUP_MEMBERS_INFO_0 *MemberList)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ LSA_HANDLE LsaHandle = NULL;
+ PUNICODE_STRING NamesArray = NULL;
+ ULONG i;
+ PLSA_REFERENCED_DOMAIN_LIST Domains = NULL;
+ PLSA_TRANSLATED_SID Sids = NULL;
+ PLOCALGROUP_MEMBERS_INFO_0 MemberBuffer = NULL;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ ApiStatus = NetApiBufferAllocate(sizeof(UNICODE_STRING) * EntryCount,
+ (LPVOID*)&NamesArray);
+ if (ApiStatus != NERR_Success)
+ {
+ goto done;
+ }
+
+ for (i = 0; i < EntryCount; i++)
+ {
+ RtlInitUnicodeString(&NamesArray[i],
+ buf[i].lgrmi3_domainandname);
+ }
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ 0,
+ 0,
+ NULL);
+
+ Status = LsaOpenPolicy(ServerName,
+ (PLSA_OBJECT_ATTRIBUTES)&ObjectAttributes,
+ POLICY_EXECUTE,
+ &LsaHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ Status = LsaLookupNames(LsaHandle,
+ EntryCount,
+ NamesArray,
+ &Domains,
+ &Sids);
+ if (!NT_SUCCESS(Status))
+ {
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ ApiStatus = NetApiBufferAllocate(sizeof(LOCALGROUP_MEMBERS_INFO_0) * EntryCount,
+ (LPVOID*)&MemberBuffer);
+ if (ApiStatus != NERR_Success)
+ {
+ goto done;
+ }
+
+ for (i = 0; i < EntryCount; i++)
+ {
+ ApiStatus = BuildSidFromSidAndRid(Domains->Domains[Sids[i].DomainIndex].Sid,
+ Sids[i].RelativeId,
+ &MemberBuffer[i].lgrmi0_sid);
+ if (ApiStatus != NERR_Success)
+ {
+ goto done;
+ }
+ }
+
+done:
+ if (ApiStatus != NERR_Success)
+ {
+ if (MemberBuffer != NULL)
+ {
+ for (i = 0; i < EntryCount; i++)
+ {
+ if (MemberBuffer[i].lgrmi0_sid != NULL)
+ NetApiBufferFree(MemberBuffer[i].lgrmi0_sid);
+ }
+
+ NetApiBufferFree(MemberBuffer);
+ MemberBuffer = NULL;
+ }
+ }
+
+ if (Sids != NULL)
+ LsaFreeMemory(Sids);
+
+ if (Domains != NULL)
+ LsaFreeMemory(Domains);
+
+ if (LsaHandle != NULL)
+ LsaClose(LsaHandle);
+
+ if (NamesArray != NULL)
+ NetApiBufferFree(NamesArray);
+
+ *MemberList = MemberBuffer;
+
+ return ApiStatus;
+}
+
+
/************************************************************
* NetLocalGroupAdd (NETAPI32.@)
*/
/************************************************************
* NetLocalGroupAddMember (NETAPI32.@)
*/
-NET_API_STATUS WINAPI NetLocalGroupAddMember(
+NET_API_STATUS
+WINAPI
+NetLocalGroupAddMember(
LPCWSTR servername,
LPCWSTR groupname,
PSID membersid)
{
- FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
+ LOCALGROUP_MEMBERS_INFO_0 Member;
+
+ TRACE("(%s %s %p)\n", debugstr_w(servername),
debugstr_w(groupname), membersid);
- return NERR_Success;
-}
-/************************************************************
- * NetLocalGroupAddMembers (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetLocalGroupAddMembers(
- LPCWSTR servername,
- LPCWSTR groupname,
- DWORD level,
- LPBYTE buf,
- DWORD totalentries)
-{
- FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
- debugstr_w(groupname), level, buf, totalentries);
- return NERR_Success;
-}
+ Member.lgrmi0_sid = membersid;
-/************************************************************
- * NetLocalGroupDel (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetLocalGroupDel(
- LPCWSTR servername,
- LPCWSTR groupname)
-{
- FIXME("(%s %s) stub!\n", debugstr_w(servername), debugstr_w(groupname));
- return NERR_Success;
+ return NetLocalGroupAddMembers(servername,
+ groupname,
+ 0,
+ (LPBYTE)&Member,
+ 1);
}
-/************************************************************
- * NetLocalGroupDelMember (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetLocalGroupDelMember(
- LPCWSTR servername,
- LPCWSTR groupname,
- PSID membersid)
-{
- FIXME("(%s %s %p) stub!\n", debugstr_w(servername),
- debugstr_w(groupname), membersid);
- return NERR_Success;
-}
/************************************************************
- * NetLocalGroupDelMembers (NETAPI32.@)
+ * NetLocalGroupAddMembers (NETAPI32.@)
*/
-NET_API_STATUS WINAPI NetLocalGroupDelMembers(
+NET_API_STATUS
+WINAPI
+NetLocalGroupAddMembers(
LPCWSTR servername,
LPCWSTR groupname,
DWORD level,
LPBYTE buf,
DWORD totalentries)
-{
- FIXME("(%s %s %d %p %d) stub!\n", debugstr_w(servername),
- debugstr_w(groupname), level, buf, totalentries);
- return NERR_Success;
-}
-
-/************************************************************
- * NetLocalGroupEnum (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetLocalGroupEnum(
- LPCWSTR servername,
- DWORD level,
- LPBYTE* bufptr,
- DWORD prefmaxlen,
- LPDWORD entriesread,
- LPDWORD totalentries,
- PDWORD_PTR resumehandle)
{
UNICODE_STRING ServerName;
- PSAM_RID_ENUMERATION CurrentAlias;
- PENUM_CONTEXT EnumContext = NULL;
- ULONG i;
+ UNICODE_STRING AliasName;
+ SAM_HANDLE ServerHandle = NULL;
+ SAM_HANDLE DomainHandle = NULL;
SAM_HANDLE AliasHandle = NULL;
- PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
- LPVOID Buffer = NULL;
+ PLOCALGROUP_MEMBERS_INFO_0 MemberList = NULL;
+ ULONG i;
NET_API_STATUS ApiStatus = NERR_Success;
NTSTATUS Status = STATUS_SUCCESS;
- TRACE("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
- level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
-
- *entriesread = 0;
- *totalentries = 0;
- *bufptr = NULL;
+ TRACE("(%s %s %d %p %d)\n", debugstr_w(servername),
+ debugstr_w(groupname), level, buf, totalentries);
if (servername != NULL)
RtlInitUnicodeString(&ServerName, servername);
- if (resumehandle != NULL && *resumehandle != 0)
+ RtlInitUnicodeString(&AliasName, groupname);
+
+ switch (level)
{
- EnumContext = (PENUM_CONTEXT)*resumehandle;
+ case 0:
+ MemberList = (PLOCALGROUP_MEMBERS_INFO_0)buf;
+ break;
+
+ case 3:
+ Status = BuildSidListFromDomainAndName((servername != NULL) ? &ServerName : NULL,
+ (PLOCALGROUP_MEMBERS_INFO_3)buf,
+ totalentries,
+ &MemberList);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("BuildSidListFromDomainAndName failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ break;
+
+ default:
+ ApiStatus = ERROR_INVALID_LEVEL;
+ goto done;
}
- else
+
+ /* Connect to the SAM Server */
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &ServerHandle,
+ SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
+ NULL);
+ if (!NT_SUCCESS(Status))
{
- ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
- if (ApiStatus != NERR_Success)
- goto done;
+ ERR("SamConnect failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
- EnumContext->EnumerationContext = 0;
- EnumContext->Buffer = NULL;
- EnumContext->Returned = 0;
- EnumContext->Index = 0;
- EnumContext->BuiltinDone = FALSE;
+ /* Open the Builtin Domain */
+ Status = OpenBuiltinDomain(ServerHandle,
+ DOMAIN_LOOKUP,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
- Status = SamConnect((servername != NULL) ? &ServerName : NULL,
- &EnumContext->ServerHandle,
- SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
- NULL);
+ /* Open the alias account in the builtin domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &AliasName,
+ ALIAS_ADD_MEMBER,
+ &AliasHandle);
+ if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
+ {
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ goto done;
+ }
+
+ if (AliasHandle == NULL)
+ {
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
+
+ /* Open the Acount Domain */
+ Status = OpenAccountDomain(ServerHandle,
+ (servername != NULL) ? &ServerName : NULL,
+ DOMAIN_LOOKUP,
+ &DomainHandle);
if (!NT_SUCCESS(Status))
{
- ERR("SamConnect failed (Status %08lx)\n", Status);
+ ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
ApiStatus = NetpNtStatusToApiStatus(Status);
goto done;
}
- Status = OpenAccountDomain(EnumContext->ServerHandle,
- (servername != NULL) ? &ServerName : NULL,
- DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
- &EnumContext->AccountDomainHandle);
- if (!NT_SUCCESS(Status))
+ /* Open the alias account in the account domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &AliasName,
+ ALIAS_ADD_MEMBER,
+ &AliasHandle);
+ if (ApiStatus != NERR_Success)
{
- ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
- ApiStatus = NetpNtStatusToApiStatus(Status);
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ if (ApiStatus == ERROR_NONE_MAPPED)
+ ApiStatus = NERR_GroupNotFound;
goto done;
}
+ }
- Status = OpenBuiltinDomain(EnumContext->ServerHandle,
- DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
- &EnumContext->BuiltinDomainHandle);
+ /* Add new members to the alias */
+ for (i = 0; i < totalentries; i++)
+ {
+ Status = SamAddMemberToAlias(AliasHandle,
+ MemberList[i].lgrmi0_sid);
if (!NT_SUCCESS(Status))
{
- ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
+ ERR("SamAddMemberToAlias failed (Status %lu)\n", Status);
ApiStatus = NetpNtStatusToApiStatus(Status);
goto done;
}
}
-
-// while (TRUE)
-// {
- TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
- TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
-
- if (EnumContext->Index >= EnumContext->Returned)
+done:
+ if (level == 3 && MemberList != NULL)
+ {
+ for (i = 0; i < totalentries; i++)
{
-// if (EnumContext->BuiltinDone == TRUE)
-// {
-// ApiStatus = NERR_Success;
-// goto done;
-// }
+ if (MemberList[i].lgrmi0_sid != NULL)
+ NetApiBufferFree(MemberList[i].lgrmi0_sid);
+ }
- TRACE("Calling SamEnumerateAliasesInDomain\n");
+ NetApiBufferFree(MemberList);
+ }
- Status = SamEnumerateAliasesInDomain(EnumContext->BuiltinDomainHandle,
- &EnumContext->EnumerationContext,
- (PVOID *)&EnumContext->Buffer,
- prefmaxlen,
- &EnumContext->Returned);
+ if (AliasHandle != NULL)
+ SamCloseHandle(AliasHandle);
- TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status);
- if (!NT_SUCCESS(Status))
- {
- ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status);
- ApiStatus = NetpNtStatusToApiStatus(Status);
- goto done;
- }
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
- if (Status == STATUS_MORE_ENTRIES)
- {
+ if (ServerHandle != NULL)
+ SamCloseHandle(ServerHandle);
+
+ return ApiStatus;
+}
+
+
+/************************************************************
+ * NetLocalGroupDel (NETAPI32.@)
+ */
+NET_API_STATUS
+WINAPI
+NetLocalGroupDel(
+ LPCWSTR servername,
+ LPCWSTR groupname)
+{
+ UNICODE_STRING ServerName;
+ UNICODE_STRING GroupName;
+ SAM_HANDLE ServerHandle = NULL;
+ SAM_HANDLE DomainHandle = NULL;
+ SAM_HANDLE AliasHandle = NULL;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("(%s %s)\n", debugstr_w(servername), debugstr_w(groupname));
+
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
+ RtlInitUnicodeString(&GroupName, groupname);
+
+ /* Connect to the SAM Server */
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &ServerHandle,
+ SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamConnect failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the Builtin Domain */
+ Status = OpenBuiltinDomain(ServerHandle,
+ DOMAIN_LOOKUP,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the alias account in the builtin domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &GroupName,
+ DELETE,
+ &AliasHandle);
+ if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
+ {
+ TRACE("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ goto done;
+ }
+
+ if (AliasHandle == NULL)
+ {
+ if (DomainHandle != NULL)
+ {
+ SamCloseHandle(DomainHandle);
+ DomainHandle = NULL;
+ }
+
+ /* Open the Acount Domain */
+ Status = OpenAccountDomain(ServerHandle,
+ (servername != NULL) ? &ServerName : NULL,
+ DOMAIN_LOOKUP,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the alias account in the account domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &GroupName,
+ DELETE,
+ &AliasHandle);
+ if (ApiStatus != NERR_Success)
+ {
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ if (ApiStatus == ERROR_NONE_MAPPED)
+ ApiStatus = NERR_GroupNotFound;
+ goto done;
+ }
+ }
+
+ /* Delete the alias */
+ Status = SamDeleteAlias(AliasHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamDeleteAlias failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+done:
+ if (AliasHandle != NULL)
+ SamCloseHandle(AliasHandle);
+
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
+
+ if (ServerHandle != NULL)
+ SamCloseHandle(ServerHandle);
+
+ return ApiStatus;
+}
+
+
+/************************************************************
+ * NetLocalGroupDelMember (NETAPI32.@)
+ */
+NET_API_STATUS
+WINAPI
+NetLocalGroupDelMember(
+ LPCWSTR servername,
+ LPCWSTR groupname,
+ PSID membersid)
+{
+ LOCALGROUP_MEMBERS_INFO_0 Member;
+
+ TRACE("(%s %s %p)\n", debugstr_w(servername),
+ debugstr_w(groupname), membersid);
+
+ Member.lgrmi0_sid = membersid;
+
+ return NetLocalGroupDelMembers(servername,
+ groupname,
+ 0,
+ (LPBYTE)&Member,
+ 1);
+}
+
+
+/************************************************************
+ * NetLocalGroupDelMembers (NETAPI32.@)
+ */
+NET_API_STATUS
+WINAPI
+NetLocalGroupDelMembers(
+ LPCWSTR servername,
+ LPCWSTR groupname,
+ DWORD level,
+ LPBYTE buf,
+ DWORD totalentries)
+{
+ UNICODE_STRING ServerName;
+ UNICODE_STRING AliasName;
+ SAM_HANDLE ServerHandle = NULL;
+ SAM_HANDLE DomainHandle = NULL;
+ SAM_HANDLE AliasHandle = NULL;
+ PLOCALGROUP_MEMBERS_INFO_0 MemberList = NULL;
+ ULONG i;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("(%s %s %d %p %d)\n", debugstr_w(servername),
+ debugstr_w(groupname), level, buf, totalentries);
+
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
+ RtlInitUnicodeString(&AliasName, groupname);
+
+ switch (level)
+ {
+ case 0:
+ MemberList = (PLOCALGROUP_MEMBERS_INFO_0)buf;
+ break;
+
+ case 3:
+ Status = BuildSidListFromDomainAndName((servername != NULL) ? &ServerName : NULL,
+ (PLOCALGROUP_MEMBERS_INFO_3)buf,
+ totalentries,
+ &MemberList);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("BuildSidListFromDomainAndName failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ break;
+
+ default:
+ ApiStatus = ERROR_INVALID_LEVEL;
+ goto done;
+ }
+
+ /* Connect to the SAM Server */
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &ServerHandle,
+ SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamConnect failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the Builtin Domain */
+ Status = OpenBuiltinDomain(ServerHandle,
+ DOMAIN_LOOKUP,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the alias account in the builtin domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &AliasName,
+ ALIAS_REMOVE_MEMBER,
+ &AliasHandle);
+ if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
+ {
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ goto done;
+ }
+
+ if (AliasHandle == NULL)
+ {
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
+
+ /* Open the Acount Domain */
+ Status = OpenAccountDomain(ServerHandle,
+ (servername != NULL) ? &ServerName : NULL,
+ DOMAIN_LOOKUP,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the alias account in the account domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &AliasName,
+ ALIAS_REMOVE_MEMBER,
+ &AliasHandle);
+ if (ApiStatus != NERR_Success)
+ {
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ if (ApiStatus == ERROR_NONE_MAPPED)
+ ApiStatus = NERR_GroupNotFound;
+ goto done;
+ }
+ }
+
+ /* Remove members from the alias */
+ for (i = 0; i < totalentries; i++)
+ {
+ Status = SamRemoveMemberFromAlias(AliasHandle,
+ MemberList[i].lgrmi0_sid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamAddMemberToAlias failed (Status %lu)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ }
+
+done:
+ if (level == 3 && MemberList != NULL)
+ {
+ for (i = 0; i < totalentries; i++)
+ {
+ if (MemberList[i].lgrmi0_sid != NULL)
+ NetApiBufferFree(MemberList[i].lgrmi0_sid);
+ }
+
+ NetApiBufferFree(MemberList);
+ }
+
+ if (AliasHandle != NULL)
+ SamCloseHandle(AliasHandle);
+
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
+
+ if (ServerHandle != NULL)
+ SamCloseHandle(ServerHandle);
+
+ return ApiStatus;
+}
+
+
+/************************************************************
+ * NetLocalGroupEnum (NETAPI32.@)
+ */
+NET_API_STATUS
+WINAPI
+NetLocalGroupEnum(
+ LPCWSTR servername,
+ DWORD level,
+ LPBYTE* bufptr,
+ DWORD prefmaxlen,
+ LPDWORD entriesread,
+ LPDWORD totalentries,
+ PDWORD_PTR resumehandle)
+{
+ UNICODE_STRING ServerName;
+ PSAM_RID_ENUMERATION CurrentAlias;
+ PENUM_CONTEXT EnumContext = NULL;
+ ULONG i;
+ SAM_HANDLE AliasHandle = NULL;
+ PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
+ LPVOID Buffer = NULL;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("(%s %d %p %d %p %p %p) stub!\n", debugstr_w(servername),
+ level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle);
+
+ *entriesread = 0;
+ *totalentries = 0;
+ *bufptr = NULL;
+
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
+ if (resumehandle != NULL && *resumehandle != 0)
+ {
+ EnumContext = (PENUM_CONTEXT)*resumehandle;
+ }
+ else
+ {
+ ApiStatus = NetApiBufferAllocate(sizeof(ENUM_CONTEXT), (PVOID*)&EnumContext);
+ if (ApiStatus != NERR_Success)
+ goto done;
+
+ EnumContext->EnumerationContext = 0;
+ EnumContext->Buffer = NULL;
+ EnumContext->Returned = 0;
+ EnumContext->Index = 0;
+
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &EnumContext->ServerHandle,
+ SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamConnect failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ Status = OpenAccountDomain(EnumContext->ServerHandle,
+ (servername != NULL) ? &ServerName : NULL,
+ DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
+ &EnumContext->AccountDomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ Status = OpenBuiltinDomain(EnumContext->ServerHandle,
+ DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP,
+ &EnumContext->BuiltinDomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ EnumContext->Phase = BuiltinPhase;
+ EnumContext->DomainHandle = EnumContext->BuiltinDomainHandle;
+ }
+
+
+// while (TRUE)
+// {
+ TRACE("EnumContext->Index: %lu\n", EnumContext->Index);
+ TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
+
+ if (EnumContext->Index >= EnumContext->Returned)
+ {
+ TRACE("Calling SamEnumerateAliasesInDomain\n");
+
+ Status = SamEnumerateAliasesInDomain(EnumContext->DomainHandle,
+ &EnumContext->EnumerationContext,
+ (PVOID *)&EnumContext->Buffer,
+ prefmaxlen,
+ &EnumContext->Returned);
+
+ TRACE("SamEnumerateAliasesInDomain returned (Status %08lx)\n", Status);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamEnumerateAliasesInDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ if (Status == STATUS_MORE_ENTRIES)
+ {
ApiStatus = NERR_BufTooSmall;
goto done;
}
- else
+ }
+
+ TRACE("EnumContext: %lu\n", EnumContext);
+ TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
+ TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
+
+ /* Get a pointer to the current alias */
+ CurrentAlias = &EnumContext->Buffer[EnumContext->Index];
+
+ TRACE("RID: %lu\n", CurrentAlias->RelativeId);
+
+ Status = SamOpenAlias(EnumContext->DomainHandle,
+ ALIAS_READ_INFORMATION,
+ CurrentAlias->RelativeId,
+ &AliasHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamOpenAlias failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ Status = SamQueryInformationAlias(AliasHandle,
+ AliasGeneralInformation,
+ (PVOID *)&AliasInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ SamCloseHandle(AliasHandle);
+ AliasHandle = NULL;
+
+ TRACE("Name: %S\n", AliasInfo->Name.Buffer);
+ TRACE("Comment: %S\n", AliasInfo->AdminComment.Buffer);
+
+ ApiStatus = BuildAliasInfoBuffer(AliasInfo,
+ level,
+ &Buffer);
+ if (ApiStatus != NERR_Success)
+ goto done;
+
+ if (AliasInfo != NULL)
+ {
+ FreeAliasInfo(AliasInfo);
+ AliasInfo = NULL;
+ }
+
+ EnumContext->Index++;
+
+ (*entriesread)++;
+
+ if (EnumContext->Index == EnumContext->Returned)
+ {
+ switch (EnumContext->Phase)
+ {
+ case BuiltinPhase:
+ EnumContext->Phase = AccountPhase;
+ EnumContext->DomainHandle = EnumContext->AccountDomainHandle;
+ EnumContext->EnumerationContext = 0;
+ EnumContext->Index = 0;
+ EnumContext->Returned = 0;
+
+ if (EnumContext->Buffer != NULL)
+ {
+ for (i = 0; i < EnumContext->Returned; i++)
+ {
+ SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
+ }
+
+ SamFreeMemory(EnumContext->Buffer);
+ EnumContext->Buffer = NULL;
+ }
+ break;
+
+ case AccountPhase:
+ case DonePhase:
+ EnumContext->Phase = DonePhase;
+ break;
+ }
+ }
+// }
+
+done:
+ if (ApiStatus == NERR_Success && EnumContext->Phase != DonePhase)
+ ApiStatus = ERROR_MORE_DATA;
+
+ if (EnumContext != NULL)
+ *totalentries = EnumContext->Returned;
+
+ if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA)
+ {
+ if (EnumContext != NULL)
+ {
+ if (EnumContext->BuiltinDomainHandle != NULL)
+ SamCloseHandle(EnumContext->BuiltinDomainHandle);
+
+ if (EnumContext->AccountDomainHandle != NULL)
+ SamCloseHandle(EnumContext->AccountDomainHandle);
+
+ if (EnumContext->ServerHandle != NULL)
+ SamCloseHandle(EnumContext->ServerHandle);
+
+ if (EnumContext->Buffer != NULL)
+ {
+ for (i = 0; i < EnumContext->Returned; i++)
+ {
+ SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
+ }
+
+ SamFreeMemory(EnumContext->Buffer);
+ }
+
+ NetApiBufferFree(EnumContext);
+ EnumContext = NULL;
+ }
+ }
+
+ if (AliasHandle != NULL)
+ SamCloseHandle(AliasHandle);
+
+ if (AliasInfo != NULL)
+ FreeAliasInfo(AliasInfo);
+
+ if (resumehandle != NULL)
+ *resumehandle = (DWORD_PTR)EnumContext;
+
+ *bufptr = (LPBYTE)Buffer;
+
+ TRACE ("return %lu\n", ApiStatus);
+
+ return ApiStatus;
+}
+
+
+/************************************************************
+ * NetLocalGroupGetInfo (NETAPI32.@)
+ */
+NET_API_STATUS
+WINAPI
+NetLocalGroupGetInfo(
+ LPCWSTR servername,
+ LPCWSTR groupname,
+ DWORD level,
+ LPBYTE* bufptr)
+{
+ UNICODE_STRING ServerName;
+ UNICODE_STRING GroupName;
+ SAM_HANDLE ServerHandle = NULL;
+ SAM_HANDLE DomainHandle = NULL;
+ SAM_HANDLE AliasHandle = NULL;
+ PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
+ LPVOID Buffer = NULL;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("(%s %s %d %p) stub!\n", debugstr_w(servername),
+ debugstr_w(groupname), level, bufptr);
+
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
+ RtlInitUnicodeString(&GroupName, groupname);
+
+ /* Connect to the SAM Server */
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &ServerHandle,
+ SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamConnect failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the Builtin Domain */
+ Status = OpenBuiltinDomain(ServerHandle,
+ DOMAIN_LOOKUP,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the alias account in the builtin domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &GroupName,
+ ALIAS_READ_INFORMATION,
+ &AliasHandle);
+ if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
+ {
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ goto done;
+ }
+
+ if (AliasHandle == NULL)
+ {
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
+
+ /* Open the Acount Domain */
+ Status = OpenAccountDomain(ServerHandle,
+ (servername != NULL) ? &ServerName : NULL,
+ DOMAIN_LOOKUP,
+ &DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the alias account in the account domain */
+ ApiStatus = OpenAliasByName(DomainHandle,
+ &GroupName,
+ ALIAS_READ_INFORMATION,
+ &AliasHandle);
+ if (ApiStatus != NERR_Success)
+ {
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ if (ApiStatus == ERROR_NONE_MAPPED)
+ ApiStatus = NERR_GroupNotFound;
+ goto done;
+ }
+ }
+
+ Status = SamQueryInformationAlias(AliasHandle,
+ AliasGeneralInformation,
+ (PVOID *)&AliasInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ ApiStatus = BuildAliasInfoBuffer(AliasInfo,
+ level,
+ &Buffer);
+ if (ApiStatus != NERR_Success)
+ goto done;
+
+done:
+ if (AliasInfo != NULL)
+ FreeAliasInfo(AliasInfo);
+
+ if (AliasHandle != NULL)
+ SamCloseHandle(AliasHandle);
+
+ if (DomainHandle != NULL)
+ SamCloseHandle(DomainHandle);
+
+ if (ServerHandle != NULL)
+ SamCloseHandle(ServerHandle);
+
+ *bufptr = (LPBYTE)Buffer;
+
+ return ApiStatus;
+}
+
+
+/************************************************************
+ * NetLocalGroupGetMembers (NETAPI32.@)
+ */
+NET_API_STATUS
+WINAPI
+NetLocalGroupGetMembers(
+ LPCWSTR servername,
+ LPCWSTR localgroupname,
+ DWORD level,
+ LPBYTE* bufptr,
+ DWORD prefmaxlen,
+ LPDWORD entriesread,
+ LPDWORD totalentries,
+ PDWORD_PTR resumehandle)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING ServerName;
+ UNICODE_STRING AliasName;
+ PMEMBER_ENUM_CONTEXT EnumContext = NULL;
+ LPVOID Buffer = NULL;
+ PLOCALGROUP_MEMBERS_INFO_0 MembersInfo0;
+ PLOCALGROUP_MEMBERS_INFO_1 MembersInfo1;
+ PLOCALGROUP_MEMBERS_INFO_2 MembersInfo2;
+ PLOCALGROUP_MEMBERS_INFO_3 MembersInfo3;
+ LPWSTR Ptr;
+ ULONG Size = 0;
+ ULONG SidLength;
+ ULONG i;
+ NET_API_STATUS ApiStatus = NERR_Success;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ TRACE("(%s %s %d %p %d, %p %p %p)\n", debugstr_w(servername),
+ debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
+ totalentries, resumehandle);
+
+ *entriesread = 0;
+ *totalentries = 0;
+ *bufptr = NULL;
+
+ if (servername != NULL)
+ RtlInitUnicodeString(&ServerName, servername);
+
+ RtlInitUnicodeString(&AliasName, localgroupname);
+
+ if (resumehandle != NULL && *resumehandle != 0)
+ {
+ EnumContext = (PMEMBER_ENUM_CONTEXT)*resumehandle;
+ }
+ else
+ {
+ /* Allocate the enumeration context */
+ ApiStatus = NetApiBufferAllocate(sizeof(MEMBER_ENUM_CONTEXT), (PVOID*)&EnumContext);
+ if (ApiStatus != NERR_Success)
+ goto done;
+
+ /* Connect to the SAM Server */
+ Status = SamConnect((servername != NULL) ? &ServerName : NULL,
+ &EnumContext->ServerHandle,
+ SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("SamConnect failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the Builtin Domain */
+ Status = OpenBuiltinDomain(EnumContext->ServerHandle,
+ DOMAIN_LOOKUP,
+ &EnumContext->DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenBuiltinDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the alias account in the builtin domain */
+ ApiStatus = OpenAliasByName(EnumContext->DomainHandle,
+ &AliasName,
+ ALIAS_LIST_MEMBERS,
+ &EnumContext->AliasHandle);
+ if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
+ {
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ goto done;
+ }
+
+ if (EnumContext->AliasHandle == NULL)
+ {
+ if (EnumContext->DomainHandle != NULL)
+ SamCloseHandle(EnumContext->DomainHandle);
+
+ /* Open the Acount Domain */
+ Status = OpenAccountDomain(EnumContext->ServerHandle,
+ (servername != NULL) ? &ServerName : NULL,
+ DOMAIN_LOOKUP,
+ &EnumContext->DomainHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("OpenAccountDomain failed (Status %08lx)\n", Status);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+
+ /* Open the alias account in the account domain */
+ ApiStatus = OpenAliasByName(EnumContext->DomainHandle,
+ &AliasName,
+ ALIAS_LIST_MEMBERS,
+ &EnumContext->AliasHandle);
+ if (ApiStatus != NERR_Success)
{
- EnumContext->BuiltinDone = TRUE;
+ ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ if (ApiStatus == ERROR_NONE_MAPPED)
+ ApiStatus = NERR_GroupNotFound;
+ goto done;
}
}
- TRACE("EnumContext: %lu\n", EnumContext);
- TRACE("EnumContext->Returned: %lu\n", EnumContext->Returned);
- TRACE("EnumContext->Buffer: %p\n", EnumContext->Buffer);
-
- /* Get a pointer to the current alias */
- CurrentAlias = &EnumContext->Buffer[EnumContext->Index];
-
- TRACE("RID: %lu\n", CurrentAlias->RelativeId);
-
- Status = SamOpenAlias(EnumContext->BuiltinDomainHandle,
- ALIAS_READ_INFORMATION,
- CurrentAlias->RelativeId,
- &AliasHandle);
+ /* Get the member list */
+ Status = SamGetMembersInAlias(EnumContext->AliasHandle,
+ &EnumContext->Sids,
+ &EnumContext->Count);
if (!NT_SUCCESS(Status))
{
- ERR("SamOpenAlias failed (Status %08lx)\n", Status);
+ ERR("SamGetMemberInAlias failed (Status %08lx)\n", Status);
ApiStatus = NetpNtStatusToApiStatus(Status);
goto done;
}
- Status = SamQueryInformationAlias(AliasHandle,
- AliasGeneralInformation,
- (PVOID *)&AliasInfo);
- if (!NT_SUCCESS(Status))
+ if (EnumContext->Count == 0)
{
- ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
- ApiStatus = NetpNtStatusToApiStatus(Status);
+ TRACE("No member found. We're done.\n");
+ ApiStatus = NERR_Success;
goto done;
}
- SamCloseHandle(AliasHandle);
- AliasHandle = NULL;
-
- TRACE("Name: %S\n", AliasInfo->Name.Buffer);
- TRACE("Comment: %S\n", AliasInfo->AdminComment.Buffer);
+ /* Get name and domain information for all members */
+ if (level != 0)
+ {
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ 0,
+ 0,
+ NULL);
+
+ Status = LsaOpenPolicy((servername != NULL) ? &ServerName : NULL,
+ (PLSA_OBJECT_ATTRIBUTES)&ObjectAttributes,
+ POLICY_EXECUTE,
+ &EnumContext->LsaHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
- ApiStatus = BuildAliasInfoBuffer(AliasInfo,
- level,
- &Buffer);
- if (ApiStatus != NERR_Success)
- goto done;
+ Status = LsaLookupSids(EnumContext->LsaHandle,
+ EnumContext->Count,
+ EnumContext->Sids,
+ &EnumContext->Domains,
+ &EnumContext->Names);
+ if (!NT_SUCCESS(Status))
+ {
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ }
+ }
- if (AliasInfo != NULL)
+ /* Calculate the required buffer size */
+ for (i = 0; i < EnumContext->Count; i++)
+ {
+ switch (level)
{
- FreeAliasInfo(AliasInfo);
- AliasInfo = NULL;
+ case 0:
+ Size += sizeof(LOCALGROUP_MEMBERS_INFO_0) +
+ RtlLengthSid(EnumContext->Sids[i]);
+ break;
+
+ case 1:
+ Size += sizeof(LOCALGROUP_MEMBERS_INFO_1) +
+ RtlLengthSid(EnumContext->Sids[i]) +
+ EnumContext->Names[i].Name.Length + sizeof(WCHAR);
+ break;
+
+ case 2:
+ Size += sizeof(LOCALGROUP_MEMBERS_INFO_2) +
+ RtlLengthSid(EnumContext->Sids[i]) +
+ EnumContext->Names[i].Name.Length + sizeof(WCHAR);
+ if (EnumContext->Names[i].DomainIndex >= 0)
+ Size += EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length + sizeof(WCHAR);
+ break;
+
+ case 3:
+ Size += sizeof(LOCALGROUP_MEMBERS_INFO_3) +
+ EnumContext->Names[i].Name.Length + sizeof(WCHAR);
+ if (EnumContext->Names[i].DomainIndex >= 0)
+ Size += EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length + sizeof(WCHAR);
+ break;
+
+ default:
+ ApiStatus = ERROR_INVALID_LEVEL;
+ goto done;
}
+ }
- EnumContext->Index++;
+ /* Allocate the member buffer */
+ ApiStatus = NetApiBufferAllocate(Size, &Buffer);
+ if (ApiStatus != NERR_Success)
+ goto done;
- (*entriesread)++;
+ ZeroMemory(Buffer, Size);
-// }
+ /* Fill the member buffer */
+ switch (level)
+ {
+ case 0:
+ MembersInfo0 = (PLOCALGROUP_MEMBERS_INFO_0)Buffer;
+ Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_0) * EnumContext->Count);
+ break;
-done:
- if (ApiStatus == NERR_Success && EnumContext->Index < EnumContext->Returned)
- ApiStatus = ERROR_MORE_DATA;
+ case 1:
+ MembersInfo1 = (PLOCALGROUP_MEMBERS_INFO_1)Buffer;
+ Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_1) * EnumContext->Count);
+ break;
- if (EnumContext != NULL)
- *totalentries = EnumContext->Returned;
+ case 2:
+ MembersInfo2 = (PLOCALGROUP_MEMBERS_INFO_2)Buffer;
+ Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_2) * EnumContext->Count);
+ break;
- if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA)
+ case 3:
+ MembersInfo3 = (PLOCALGROUP_MEMBERS_INFO_3)Buffer;
+ Ptr = (PVOID)((ULONG_PTR)Buffer + sizeof(LOCALGROUP_MEMBERS_INFO_3) * EnumContext->Count);
+ break;
+ }
+
+ for (i = 0; i < EnumContext->Count; i++)
{
- if (EnumContext != NULL)
+ switch (level)
{
- if (EnumContext->BuiltinDomainHandle != NULL)
- SamCloseHandle(EnumContext->BuiltinDomainHandle);
+ case 0:
+ MembersInfo0->lgrmi0_sid = (PSID)Ptr;
- if (EnumContext->AccountDomainHandle != NULL)
- SamCloseHandle(EnumContext->AccountDomainHandle);
+ SidLength = RtlLengthSid(EnumContext->Sids[i]);
+ memcpy(MembersInfo0->lgrmi0_sid,
+ EnumContext->Sids[i],
+ SidLength);
+ Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength);
+ MembersInfo0++;
+ break;
- if (EnumContext->ServerHandle != NULL)
- SamCloseHandle(EnumContext->ServerHandle);
+ case 1:
+ MembersInfo1->lgrmi1_sid = (PSID)Ptr;
- if (EnumContext->Buffer != NULL)
- {
- for (i = 0; i < EnumContext->Returned; i++)
+ SidLength = RtlLengthSid(EnumContext->Sids[i]);
+ memcpy(MembersInfo1->lgrmi1_sid,
+ EnumContext->Sids[i],
+ SidLength);
+
+ Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength);
+
+ MembersInfo1->lgrmi1_sidusage = EnumContext->Names[i].Use;
+
+ TRACE("Name: %S\n", EnumContext->Names[i].Name.Buffer);
+
+ MembersInfo1->lgrmi1_name = (LPWSTR)Ptr;
+
+ memcpy(MembersInfo1->lgrmi1_name,
+ EnumContext->Names[i].Name.Buffer,
+ EnumContext->Names[i].Name.Length);
+ Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR));
+ MembersInfo1++;
+ break;
+
+ case 2:
+ MembersInfo2->lgrmi2_sid = (PSID)Ptr;
+
+ SidLength = RtlLengthSid(EnumContext->Sids[i]);
+ memcpy(MembersInfo2->lgrmi2_sid,
+ EnumContext->Sids[i],
+ SidLength);
+
+ Ptr = (PVOID)((ULONG_PTR)Ptr + SidLength);
+
+ MembersInfo2->lgrmi2_sidusage = EnumContext->Names[i].Use;
+
+ MembersInfo2->lgrmi2_domainandname = (LPWSTR)Ptr;
+
+ if (EnumContext->Names[i].DomainIndex >= 0)
{
- SamFreeMemory(EnumContext->Buffer[i].Name.Buffer);
+ memcpy(MembersInfo2->lgrmi2_domainandname,
+ EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Buffer,
+ EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length);
+
+ Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length);
+
+ *((LPWSTR)Ptr) = L'\\';
+
+ Ptr = (PVOID)((ULONG_PTR)Ptr + sizeof(WCHAR));
}
- SamFreeMemory(EnumContext->Buffer);
- }
+ memcpy(Ptr,
+ EnumContext->Names[i].Name.Buffer,
+ EnumContext->Names[i].Name.Length);
+ Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR));
+ MembersInfo2++;
+ break;
- NetApiBufferFree(EnumContext);
- EnumContext = NULL;
+ case 3:
+ MembersInfo3->lgrmi3_domainandname = (PSID)Ptr;
+
+ if (EnumContext->Names[i].DomainIndex >= 0)
+ {
+ memcpy(MembersInfo2->lgrmi2_domainandname,
+ EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Buffer,
+ EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length);
+
+ Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Domains->Domains[EnumContext->Names[i].DomainIndex].Name.Length);
+
+ *((LPWSTR)Ptr) = L'\\';
+
+ Ptr = (PVOID)((ULONG_PTR)Ptr + sizeof(WCHAR));
+ }
+
+ memcpy(Ptr,
+ EnumContext->Names[i].Name.Buffer,
+ EnumContext->Names[i].Name.Length);
+ Ptr = (PVOID)((ULONG_PTR)Ptr + EnumContext->Names[i].Name.Length + sizeof(WCHAR));
+ MembersInfo3++;
+ break;
}
}
- if (AliasHandle != NULL)
- SamCloseHandle(AliasHandle);
+ *entriesread = EnumContext->Count;
- if (AliasInfo != NULL)
- FreeAliasInfo(AliasInfo);
+ *bufptr = (LPBYTE)Buffer;
- if (resumehandle != NULL)
- *resumehandle = (DWORD_PTR)EnumContext;
+done:
+ if (EnumContext != NULL)
+ *totalentries = EnumContext->Count;
- *bufptr = (LPBYTE)Buffer;
+ if (resumehandle == NULL || ApiStatus != ERROR_MORE_DATA)
+ {
+ /* Release the enumeration context */
+ if (EnumContext != NULL)
+ {
+ if (EnumContext->LsaHandle != NULL)
+ LsaClose(EnumContext->LsaHandle);
- TRACE ("return %lu\n", ApiStatus);
+ if (EnumContext->AliasHandle != NULL)
+ SamCloseHandle(EnumContext->AliasHandle);
+
+ if (EnumContext->DomainHandle != NULL)
+ SamCloseHandle(EnumContext->DomainHandle);
+
+ if (EnumContext->ServerHandle != NULL)
+ SamCloseHandle(EnumContext->ServerHandle);
+
+ if (EnumContext->Sids != NULL)
+ SamFreeMemory(EnumContext->Sids);
+
+ if (EnumContext->Domains != NULL)
+ LsaFreeMemory(EnumContext->Domains);
+
+ if (EnumContext->Names != NULL)
+ LsaFreeMemory(EnumContext->Names);
+
+ NetApiBufferFree(EnumContext);
+ EnumContext = NULL;
+ }
+ }
return ApiStatus;
}
/************************************************************
- * NetLocalGroupGetInfo (NETAPI32.@)
+ * NetLocalGroupSetInfo (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
-NetLocalGroupGetInfo(
+NetLocalGroupSetInfo(
LPCWSTR servername,
LPCWSTR groupname,
DWORD level,
- LPBYTE* bufptr)
+ LPBYTE buf,
+ LPDWORD parm_err)
{
UNICODE_STRING ServerName;
- UNICODE_STRING GroupName;
+ UNICODE_STRING AliasName;
SAM_HANDLE ServerHandle = NULL;
SAM_HANDLE DomainHandle = NULL;
SAM_HANDLE AliasHandle = NULL;
- PALIAS_GENERAL_INFORMATION AliasInfo = NULL;
- LPVOID Buffer = NULL;
+ ALIAS_NAME_INFORMATION AliasNameInfo;
+ ALIAS_ADM_COMMENT_INFORMATION AdminCommentInfo;
NET_API_STATUS ApiStatus = NERR_Success;
NTSTATUS Status = STATUS_SUCCESS;
- TRACE("(%s %s %d %p) stub!\n", debugstr_w(servername),
- debugstr_w(groupname), level, bufptr);
+ TRACE("(%s %s %d %p %p)\n", debugstr_w(servername),
+ debugstr_w(groupname), level, buf, parm_err);
+
+ if (parm_err != NULL)
+ *parm_err = PARM_ERROR_NONE;
if (servername != NULL)
RtlInitUnicodeString(&ServerName, servername);
- RtlInitUnicodeString(&GroupName, groupname);
+ RtlInitUnicodeString(&AliasName, groupname);
/* Connect to the SAM Server */
Status = SamConnect((servername != NULL) ? &ServerName : NULL,
/* Open the alias account in the builtin domain */
ApiStatus = OpenAliasByName(DomainHandle,
- &GroupName,
- ALIAS_READ_INFORMATION,
+ &AliasName,
+ ALIAS_WRITE_ACCOUNT,
&AliasHandle);
- if (ApiStatus != NERR_Success)
+ if (ApiStatus != NERR_Success && ApiStatus != ERROR_NONE_MAPPED)
{
ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
goto done;
/* Open the alias account in the account domain */
ApiStatus = OpenAliasByName(DomainHandle,
- &GroupName,
- ALIAS_READ_INFORMATION,
+ &AliasName,
+ ALIAS_WRITE_ACCOUNT,
&AliasHandle);
if (ApiStatus != NERR_Success)
{
ERR("OpenAliasByName failed (ApiStatus %lu)\n", ApiStatus);
+ if (ApiStatus == ERROR_NONE_MAPPED)
+ ApiStatus = NERR_GroupNotFound;
goto done;
}
}
- Status = SamQueryInformationAlias(AliasHandle,
- AliasGeneralInformation,
- (PVOID *)&AliasInfo);
- if (!NT_SUCCESS(Status))
+ switch (level)
{
- ERR("SamQueryInformationAlias failed (Status %08lx)\n", Status);
- ApiStatus = NetpNtStatusToApiStatus(Status);
- goto done;
- }
+ case 0:
+ /* Set the alias name */
+ RtlInitUnicodeString(&AliasNameInfo.Name,
+ ((PLOCALGROUP_INFO_0)buf)->lgrpi0_name);
- ApiStatus = BuildAliasInfoBuffer(AliasInfo,
- level,
- &Buffer);
- if (ApiStatus != NERR_Success)
- goto done;
+ Status = SamSetInformationAlias(AliasHandle,
+ AliasNameInformation,
+ &AliasNameInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SamSetInformationAlias failed (ApiStatus %lu)\n", ApiStatus);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ break;
-done:
- if (AliasInfo != NULL)
- FreeAliasInfo(AliasInfo);
+ case 1:
+ case 1002:
+ /* Set the alias admin comment */
+ if (level == 1)
+ RtlInitUnicodeString(&AdminCommentInfo.AdminComment,
+ ((PLOCALGROUP_INFO_1)buf)->lgrpi1_comment);
+ else
+ RtlInitUnicodeString(&AdminCommentInfo.AdminComment,
+ ((PLOCALGROUP_INFO_1002)buf)->lgrpi1002_comment);
+
+ Status = SamSetInformationAlias(AliasHandle,
+ AliasAdminCommentInformation,
+ &AdminCommentInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SamSetInformationAlias failed (ApiStatus %lu)\n", ApiStatus);
+ ApiStatus = NetpNtStatusToApiStatus(Status);
+ goto done;
+ }
+ break;
+
+ default:
+ ApiStatus = ERROR_INVALID_LEVEL;
+ goto done;
+ }
+done:
if (AliasHandle != NULL)
SamCloseHandle(AliasHandle);
if (ServerHandle != NULL)
SamCloseHandle(ServerHandle);
- *bufptr = (LPBYTE)Buffer;
-
return ApiStatus;
}
-/************************************************************
- * NetLocalGroupGetMembers (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetLocalGroupGetMembers(
- LPCWSTR servername,
- LPCWSTR localgroupname,
- DWORD level,
- LPBYTE* bufptr,
- DWORD prefmaxlen,
- LPDWORD entriesread,
- LPDWORD totalentries,
- PDWORD_PTR resumehandle)
-{
- FIXME("(%s %s %d %p %d, %p %p %p) stub!\n", debugstr_w(servername),
- debugstr_w(localgroupname), level, bufptr, prefmaxlen, entriesread,
- totalentries, resumehandle);
-
- if (level == 3)
- {
- WCHAR userName[MAX_COMPUTERNAME_LENGTH + 1];
- DWORD userNameLen;
- DWORD len,needlen;
- PLOCALGROUP_MEMBERS_INFO_3 ptr;
-
- /* still a stub, current user is belonging to all groups */
-
- *totalentries = 1;
- *entriesread = 0;
-
- userNameLen = MAX_COMPUTERNAME_LENGTH + 1;
- GetUserNameW(userName,&userNameLen);
- needlen = sizeof(LOCALGROUP_MEMBERS_INFO_3) +
- (userNameLen+2) * sizeof(WCHAR);
- if (prefmaxlen != MAX_PREFERRED_LENGTH)
- len = min(prefmaxlen,needlen);
- else
- len = needlen;
-
- NetApiBufferAllocate(len, (LPVOID *) bufptr);
- if (len < needlen)
- return ERROR_MORE_DATA;
-
- ptr = (PLOCALGROUP_MEMBERS_INFO_3)*bufptr;
- ptr->lgrmi3_domainandname = (LPWSTR)(*bufptr+sizeof(LOCALGROUP_MEMBERS_INFO_3));
- lstrcpyW(ptr->lgrmi3_domainandname,userName);
-
- *entriesread = 1;
- }
-
- return NERR_Success;
-}
-
-/************************************************************
- * NetLocalGroupSetInfo (NETAPI32.@)
- */
-NET_API_STATUS WINAPI NetLocalGroupSetInfo(
- LPCWSTR servername,
- LPCWSTR groupname,
- DWORD level,
- LPBYTE buf,
- LPDWORD parm_err)
-{
- FIXME("(%s %s %d %p %p) stub!\n", debugstr_w(servername),
- debugstr_w(groupname), level, buf, parm_err);
- return NERR_Success;
-}
-
/************************************************************
* NetLocalGroupSetMember (NETAPI32.@)
*/
debugstr_w(groupname), level, buf, totalentries);
return NERR_Success;
}
+
+/* EOF */