s3-talloc Change TALLOC_ZERO_P() to talloc_zero()
[nivanova/samba-autobuild/.git] / source3 / lib / netapi / localgroup.c
index c15a17efb102efd0e9b9efe07f7651bd9cc2fa4f..54ec14eb84dec970152180c342557b1ed811140c 100644 (file)
 #include "lib/netapi/netapi.h"
 #include "lib/netapi/netapi_private.h"
 #include "lib/netapi/libnetapi.h"
-
-static WERROR libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
-                                                  struct rpc_pipe_client *pipe_cli,
-                                                  struct policy_handle *domain_handle,
-                                                  const char *group_name,
-                                                  uint32_t access_rights,
-                                                  struct policy_handle *alias_handle)
+#include "rpc_client/rpc_client.h"
+#include "../librpc/gen_ndr/ndr_samr_c.h"
+#include "../librpc/gen_ndr/ndr_lsa_c.h"
+#include "rpc_client/cli_lsarpc.h"
+#include "rpc_client/init_lsa.h"
+#include "../libcli/security/security.h"
+
+static NTSTATUS libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
+                                                    struct rpc_pipe_client *pipe_cli,
+                                                    struct policy_handle *domain_handle,
+                                                    const char *group_name,
+                                                    uint32_t access_rights,
+                                                    struct policy_handle *alias_handle)
 {
-       NTSTATUS status;
-       WERROR werr;
+       NTSTATUS status, result;
 
        struct lsa_String lsa_account_name;
        struct samr_Ids user_rids, name_types;
+       struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
 
        init_lsa_String(&lsa_account_name, group_name);
 
-       status = rpccli_samr_LookupNames(pipe_cli, mem_ctx,
+       status = dcerpc_samr_LookupNames(b, mem_ctx,
                                         domain_handle,
                                         1,
                                         &lsa_account_name,
                                         &user_rids,
-                                        &name_types);
+                                        &name_types,
+                                        &result);
        if (!NT_STATUS_IS_OK(status)) {
-               werr = ntstatus_to_werror(status);
-               goto done;
+               return status;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
        }
 
        switch (name_types.ids[0]) {
@@ -55,23 +64,20 @@ static WERROR libnetapi_samr_lookup_and_open_alias(TALLOC_CTX *mem_ctx,
                case SID_NAME_WKN_GRP:
                        break;
                default:
-                       return WERR_INVALID_DATATYPE;
+                       return NT_STATUS_INVALID_SID;
        }
 
-       status = rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
+       status = dcerpc_samr_OpenAlias(b, mem_ctx,
                                       domain_handle,
                                       access_rights,
                                       user_rids.ids[0],
-                                      alias_handle);
-       if (NT_STATUS_IS_OK(status)) {
-               werr = ntstatus_to_werror(status);
-               goto done;
+                                      alias_handle,
+                                      &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       werr = WERR_OK;
-
- done:
-       return werr;
+       return result;
 }
 
 /****************************************************************
@@ -85,34 +91,45 @@ static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
                                                    enum samr_AliasInfoEnum level,
                                                    union samr_AliasInfo **alias_info)
 {
-       NTSTATUS status;
+       NTSTATUS status, result;
        struct policy_handle alias_handle;
        union samr_AliasInfo *_alias_info = NULL;
+       struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
 
        ZERO_STRUCT(alias_handle);
 
-       status = rpccli_samr_OpenAlias(pipe_cli, mem_ctx,
+       status = dcerpc_samr_OpenAlias(b, mem_ctx,
                                       handle,
                                       access_rights,
                                       rid,
-                                      &alias_handle);
+                                      &alias_handle,
+                                      &result);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto done;
+       }
 
-       status = rpccli_samr_QueryAliasInfo(pipe_cli, mem_ctx,
+       status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
                                            &alias_handle,
                                            level,
-                                           &_alias_info);
+                                           &_alias_info,
+                                           &result);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               status = result;
+               goto done;
+       }
 
        *alias_info = _alias_info;
 
  done:
        if (is_valid_policy_hnd(&alias_handle)) {
-               rpccli_samr_Close(pipe_cli, mem_ctx, &alias_handle);
+               dcerpc_samr_Close(b, mem_ctx, &alias_handle, &result);
        }
 
        return status;
@@ -124,14 +141,14 @@ static NTSTATUS libnetapi_samr_open_alias_queryinfo(TALLOC_CTX *mem_ctx,
 WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
                          struct NetLocalGroupAdd *r)
 {
-       struct cli_state *cli = NULL;
        struct rpc_pipe_client *pipe_cli = NULL;
-       NTSTATUS status;
+       NTSTATUS status, result;
        WERROR werr;
        struct lsa_String lsa_account_name;
        struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
        struct dom_sid2 *domain_sid = NULL;
        uint32_t rid;
+       struct dcerpc_binding_handle *b = NULL;
 
        struct LOCALGROUP_INFO_0 *info0 = NULL;
        struct LOCALGROUP_INFO_1 *info1 = NULL;
@@ -161,19 +178,17 @@ WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
        ZERO_STRUCT(domain_handle);
        ZERO_STRUCT(alias_handle);
 
-       werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
-       if (!W_ERROR_IS_OK(werr)) {
-               goto done;
-       }
-
-       werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
+       werr = libnetapi_open_pipe(ctx, r->in.server_name,
+                                  &ndr_table_samr.syntax_id,
                                   &pipe_cli);
        if (!W_ERROR_IS_OK(werr)) {
                goto done;
        }
 
+       b = pipe_cli->binding_handle;
+
        werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
-                                                 SAMR_ACCESS_OPEN_DOMAIN |
+                                                 SAMR_ACCESS_LOOKUP_DOMAIN |
                                                  SAMR_ACCESS_ENUM_DOMAINS,
                                                  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
                                                  &connect_handle,
@@ -182,24 +197,23 @@ WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
                goto done;
        }
 
-       werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
-                                                   &builtin_handle,
-                                                   alias_name,
-                                                   SAMR_ALIAS_ACCESS_LOOKUP_INFO,
-                                                   &alias_handle);
-
+       status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+                                                     &builtin_handle,
+                                                     alias_name,
+                                                     SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+                                                     &alias_handle);
        if (ctx->disable_policy_handle_cache) {
                libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
        }
 
-       if (W_ERROR_IS_OK(werr)) {
+       if (NT_STATUS_IS_OK(status)) {
                werr = WERR_ALIAS_EXISTS;
                goto done;
        }
 
        werr = libnetapi_samr_open_domain(ctx, pipe_cli,
                                          SAMR_ACCESS_ENUM_DOMAINS |
-                                         SAMR_ACCESS_OPEN_DOMAIN,
+                                         SAMR_ACCESS_LOOKUP_DOMAIN,
                                          SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
                                          SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
                                          &connect_handle,
@@ -211,17 +225,23 @@ WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
 
        init_lsa_String(&lsa_account_name, alias_name);
 
-       status = rpccli_samr_CreateDomAlias(pipe_cli, ctx,
+       status = dcerpc_samr_CreateDomAlias(b, talloc_tos(),
                                            &domain_handle,
                                            &lsa_account_name,
                                            SEC_STD_DELETE |
                                            SAMR_ALIAS_ACCESS_SET_INFO,
                                            &alias_handle,
-                                           &rid);
+                                           &rid,
+                                           &result);
        if (!NT_STATUS_IS_OK(status)) {
                werr = ntstatus_to_werror(status);
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               werr = ntstatus_to_werror(result);
+               goto done;
+       }
+
 
        if (r->in.level == 1 && info1->lgrpi1_comment) {
 
@@ -229,25 +249,26 @@ WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
 
                init_lsa_String(&alias_info.description, info1->lgrpi1_comment);
 
-               status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
+               status = dcerpc_samr_SetAliasInfo(b, talloc_tos(),
                                                  &alias_handle,
                                                  ALIASINFODESCRIPTION,
-                                                 &alias_info);
+                                                 &alias_info,
+                                                 &result);
                if (!NT_STATUS_IS_OK(status)) {
                        werr = ntstatus_to_werror(status);
                        goto done;
                }
+               if (!NT_STATUS_IS_OK(result)) {
+                       werr = ntstatus_to_werror(result);
+                       goto done;
+               }
        }
 
        werr = WERR_OK;
 
  done:
-       if (!cli) {
-               return werr;
-       }
-
        if (is_valid_policy_hnd(&alias_handle)) {
-               rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
+               dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
        }
 
        if (ctx->disable_policy_handle_cache) {
@@ -265,7 +286,7 @@ WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx,
 WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
                          struct NetLocalGroupAdd *r)
 {
-       return NetLocalGroupAdd_r(ctx, r);
+       LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAdd);
 }
 
 /****************************************************************
@@ -275,12 +296,12 @@ WERROR NetLocalGroupAdd_l(struct libnetapi_ctx *ctx,
 WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
                          struct NetLocalGroupDel *r)
 {
-       struct cli_state *cli = NULL;
        struct rpc_pipe_client *pipe_cli = NULL;
-       NTSTATUS status;
+       NTSTATUS status, result;
        WERROR werr;
        struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
        struct dom_sid2 *domain_sid = NULL;
+       struct dcerpc_binding_handle *b = NULL;
 
        if (!r->in.group_name) {
                return WERR_INVALID_PARAM;
@@ -291,19 +312,17 @@ WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
        ZERO_STRUCT(domain_handle);
        ZERO_STRUCT(alias_handle);
 
-       werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
-       if (!W_ERROR_IS_OK(werr)) {
-               goto done;
-       }
-
-       werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
+       werr = libnetapi_open_pipe(ctx, r->in.server_name,
+                                  &ndr_table_samr.syntax_id,
                                   &pipe_cli);
        if (!W_ERROR_IS_OK(werr)) {
                goto done;
        }
 
+       b = pipe_cli->binding_handle;
+
        werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
-                                                 SAMR_ACCESS_OPEN_DOMAIN |
+                                                 SAMR_ACCESS_LOOKUP_DOMAIN |
                                                  SAMR_ACCESS_ENUM_DOMAINS,
                                                  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
                                                  &connect_handle,
@@ -312,23 +331,23 @@ WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
                goto done;
        }
 
-       werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
-                                                   &builtin_handle,
-                                                   r->in.group_name,
-                                                   SEC_STD_DELETE,
-                                                   &alias_handle);
+       status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+                                                     &builtin_handle,
+                                                     r->in.group_name,
+                                                     SEC_STD_DELETE,
+                                                     &alias_handle);
 
        if (ctx->disable_policy_handle_cache) {
                libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
        }
 
-       if (W_ERROR_IS_OK(werr)) {
+       if (NT_STATUS_IS_OK(status)) {
                goto delete_alias;
        }
 
        werr = libnetapi_samr_open_domain(ctx, pipe_cli,
                                          SAMR_ACCESS_ENUM_DOMAINS |
-                                         SAMR_ACCESS_OPEN_DOMAIN,
+                                         SAMR_ACCESS_LOOKUP_DOMAIN,
                                          SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
                                          SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
                                          &connect_handle,
@@ -338,40 +357,42 @@ WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
                goto done;
        }
 
-       werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
-                                                   &domain_handle,
-                                                   r->in.group_name,
-                                                   SEC_STD_DELETE,
-                                                   &alias_handle);
+       status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+                                                     &domain_handle,
+                                                     r->in.group_name,
+                                                     SEC_STD_DELETE,
+                                                     &alias_handle);
 
        if (ctx->disable_policy_handle_cache) {
                libnetapi_samr_close_domain_handle(ctx, &domain_handle);
        }
 
-       if (!W_ERROR_IS_OK(werr)) {
+       if (!NT_STATUS_IS_OK(status)) {
+               werr = ntstatus_to_werror(status);
                goto done;
        }
 
 
  delete_alias:
-       status = rpccli_samr_DeleteDomAlias(pipe_cli, ctx,
-                                           &alias_handle);
+       status = dcerpc_samr_DeleteDomAlias(b, talloc_tos(),
+                                           &alias_handle,
+                                           &result);
        if (!NT_STATUS_IS_OK(status)) {
                werr = ntstatus_to_werror(status);
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               werr = ntstatus_to_werror(result);
+               goto done;
+       }
 
        ZERO_STRUCT(alias_handle);
 
        werr = WERR_OK;
 
  done:
-       if (!cli) {
-               return werr;
-       }
-
        if (is_valid_policy_hnd(&alias_handle)) {
-               rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
+               dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
        }
 
        if (ctx->disable_policy_handle_cache) {
@@ -389,7 +410,7 @@ WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx,
 WERROR NetLocalGroupDel_l(struct libnetapi_ctx *ctx,
                          struct NetLocalGroupDel *r)
 {
-       return NetLocalGroupDel_r(ctx, r);
+       LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDel);
 }
 
 /****************************************************************
@@ -444,14 +465,14 @@ static WERROR map_alias_info_to_buffer(TALLOC_CTX *mem_ctx,
 WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
                              struct NetLocalGroupGetInfo *r)
 {
-       struct cli_state *cli = NULL;
        struct rpc_pipe_client *pipe_cli = NULL;
-       NTSTATUS status;
+       NTSTATUS status, result;
        WERROR werr;
        struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
        struct dom_sid2 *domain_sid = NULL;
        union samr_AliasInfo *alias_info = NULL;
        uint32_t entries_read = 0;
+       struct dcerpc_binding_handle *b = NULL;
 
        if (!r->in.group_name) {
                return WERR_INVALID_PARAM;
@@ -471,19 +492,17 @@ WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
        ZERO_STRUCT(domain_handle);
        ZERO_STRUCT(alias_handle);
 
-       werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
-       if (!W_ERROR_IS_OK(werr)) {
-               goto done;
-       }
-
-       werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
+       werr = libnetapi_open_pipe(ctx, r->in.server_name,
+                                  &ndr_table_samr.syntax_id,
                                   &pipe_cli);
        if (!W_ERROR_IS_OK(werr)) {
                goto done;
        }
 
+       b = pipe_cli->binding_handle;
+
        werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
-                                                 SAMR_ACCESS_OPEN_DOMAIN |
+                                                 SAMR_ACCESS_LOOKUP_DOMAIN |
                                                  SAMR_ACCESS_ENUM_DOMAINS,
                                                  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
                                                  &connect_handle,
@@ -492,23 +511,23 @@ WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
                goto done;
        }
 
-       werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
-                                                   &builtin_handle,
-                                                   r->in.group_name,
-                                                   SAMR_ALIAS_ACCESS_LOOKUP_INFO,
-                                                   &alias_handle);
+       status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+                                                     &builtin_handle,
+                                                     r->in.group_name,
+                                                     SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+                                                     &alias_handle);
 
        if (ctx->disable_policy_handle_cache) {
                libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
        }
 
-       if (W_ERROR_IS_OK(werr)) {
+       if (NT_STATUS_IS_OK(status)) {
                goto query_alias;
        }
 
        werr = libnetapi_samr_open_domain(ctx, pipe_cli,
                                          SAMR_ACCESS_ENUM_DOMAINS |
-                                         SAMR_ACCESS_OPEN_DOMAIN,
+                                         SAMR_ACCESS_LOOKUP_DOMAIN,
                                          SAMR_DOMAIN_ACCESS_CREATE_ALIAS |
                                          SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
                                          &connect_handle,
@@ -518,29 +537,35 @@ WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
                goto done;
        }
 
-       werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
-                                                   &domain_handle,
-                                                   r->in.group_name,
-                                                   SAMR_ALIAS_ACCESS_LOOKUP_INFO,
-                                                   &alias_handle);
+       status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+                                                     &domain_handle,
+                                                     r->in.group_name,
+                                                     SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+                                                     &alias_handle);
 
        if (ctx->disable_policy_handle_cache) {
                libnetapi_samr_close_domain_handle(ctx, &domain_handle);
        }
 
-       if (!W_ERROR_IS_OK(werr)) {
+       if (!NT_STATUS_IS_OK(status)) {
+               werr = ntstatus_to_werror(status);
                goto done;
        }
 
  query_alias:
-       status = rpccli_samr_QueryAliasInfo(pipe_cli, ctx,
+       status = dcerpc_samr_QueryAliasInfo(b, talloc_tos(),
                                            &alias_handle,
                                            ALIASINFOALL,
-                                           &alias_info);
+                                           &alias_info,
+                                           &result);
        if (!NT_STATUS_IS_OK(status)) {
                werr = ntstatus_to_werror(status);
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               werr = ntstatus_to_werror(result);
+               goto done;
+       }
 
        werr = map_alias_info_to_buffer(ctx,
                                        r->in.group_name,
@@ -549,12 +574,8 @@ WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
                                        r->out.buffer);
 
  done:
-       if (!cli) {
-               return werr;
-       }
-
        if (is_valid_policy_hnd(&alias_handle)) {
-               rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
+               dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
        }
 
        if (ctx->disable_policy_handle_cache) {
@@ -572,7 +593,7 @@ WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx,
 WERROR NetLocalGroupGetInfo_l(struct libnetapi_ctx *ctx,
                              struct NetLocalGroupGetInfo *r)
 {
-       return NetLocalGroupGetInfo_r(ctx, r);
+       LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetInfo);
 }
 
 /****************************************************************
@@ -589,7 +610,7 @@ static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
        struct LOCALGROUP_INFO_1002 *info1002;
        union samr_AliasInfo *info = NULL;
 
-       info = TALLOC_ZERO_P(mem_ctx, union samr_AliasInfo);
+       info = talloc_zero(mem_ctx, union samr_AliasInfo);
        W_ERROR_HAVE_NO_MEMORY(info);
 
        switch (level) {
@@ -622,15 +643,15 @@ static WERROR map_buffer_to_alias_info(TALLOC_CTX *mem_ctx,
 WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
                              struct NetLocalGroupSetInfo *r)
 {
-       struct cli_state *cli = NULL;
        struct rpc_pipe_client *pipe_cli = NULL;
-       NTSTATUS status;
+       NTSTATUS status, result;
        WERROR werr;
        struct lsa_String lsa_account_name;
        struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
        struct dom_sid2 *domain_sid = NULL;
        enum samr_AliasInfoEnum alias_level = 0;
        union samr_AliasInfo *alias_info = NULL;
+       struct dcerpc_binding_handle *b = NULL;
 
        if (!r->in.group_name) {
                return WERR_INVALID_PARAM;
@@ -650,19 +671,17 @@ WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
        ZERO_STRUCT(domain_handle);
        ZERO_STRUCT(alias_handle);
 
-       werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
-       if (!W_ERROR_IS_OK(werr)) {
-               goto done;
-       }
-
-       werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
+       werr = libnetapi_open_pipe(ctx, r->in.server_name,
+                                  &ndr_table_samr.syntax_id,
                                   &pipe_cli);
        if (!W_ERROR_IS_OK(werr)) {
                goto done;
        }
 
+       b = pipe_cli->binding_handle;
+
        werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
-                                                 SAMR_ACCESS_OPEN_DOMAIN |
+                                                 SAMR_ACCESS_LOOKUP_DOMAIN |
                                                  SAMR_ACCESS_ENUM_DOMAINS,
                                                  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
                                                  &connect_handle,
@@ -673,23 +692,23 @@ WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
 
        init_lsa_String(&lsa_account_name, r->in.group_name);
 
-       werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
-                                                   &builtin_handle,
-                                                   r->in.group_name,
-                                                   SAMR_ALIAS_ACCESS_SET_INFO,
-                                                   &alias_handle);
+       status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+                                                     &builtin_handle,
+                                                     r->in.group_name,
+                                                     SAMR_ALIAS_ACCESS_SET_INFO,
+                                                     &alias_handle);
 
        if (ctx->disable_policy_handle_cache) {
                libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
        }
 
-       if (W_ERROR_IS_OK(werr)) {
+       if (NT_STATUS_IS_OK(status)) {
                goto set_alias;
        }
 
        werr = libnetapi_samr_open_domain(ctx, pipe_cli,
                                          SAMR_ACCESS_ENUM_DOMAINS |
-                                         SAMR_ACCESS_OPEN_DOMAIN,
+                                         SAMR_ACCESS_LOOKUP_DOMAIN,
                                          SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
                                          &connect_handle,
                                          &domain_handle,
@@ -698,12 +717,13 @@ WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
                goto done;
        }
 
-       werr = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
-                                                   &domain_handle,
-                                                   r->in.group_name,
-                                                   SAMR_ALIAS_ACCESS_SET_INFO,
-                                                   &alias_handle);
-       if (!W_ERROR_IS_OK(werr)) {
+       status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+                                                     &domain_handle,
+                                                     r->in.group_name,
+                                                     SAMR_ALIAS_ACCESS_SET_INFO,
+                                                     &alias_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               werr = ntstatus_to_werror(status);
                goto done;
        }
 
@@ -719,24 +739,25 @@ WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
                goto done;
        }
 
-       status = rpccli_samr_SetAliasInfo(pipe_cli, ctx,
+       status = dcerpc_samr_SetAliasInfo(b, talloc_tos(),
                                          &alias_handle,
                                          alias_level,
-                                         alias_info);
+                                         alias_info,
+                                         &result);
        if (!NT_STATUS_IS_OK(status)) {
                werr = ntstatus_to_werror(status);
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               werr = ntstatus_to_werror(result);
+               goto done;
+       }
 
        werr = WERR_OK;
 
  done:
-       if (!cli) {
-               return werr;
-       }
-
        if (is_valid_policy_hnd(&alias_handle)) {
-               rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
+               dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
        }
 
        if (ctx->disable_policy_handle_cache) {
@@ -754,7 +775,7 @@ WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx,
 WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
                              struct NetLocalGroupSetInfo *r)
 {
-       return NetLocalGroupSetInfo_r(ctx, r);
+       LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetInfo);
 }
 
 /****************************************************************
@@ -763,9 +784,8 @@ WERROR NetLocalGroupSetInfo_l(struct libnetapi_ctx *ctx,
 WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
                           struct NetLocalGroupEnum *r)
 {
-       struct cli_state *cli = NULL;
        struct rpc_pipe_client *pipe_cli = NULL;
-       NTSTATUS status;
+       NTSTATUS status, result;
        WERROR werr;
        struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
        struct dom_sid2 *domain_sid = NULL;
@@ -775,6 +795,7 @@ WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
        struct samr_SamArray *domain_sam_array = NULL;
        struct samr_SamArray *builtin_sam_array = NULL;
        int i;
+       struct dcerpc_binding_handle *b = NULL;
 
        if (!r->out.buffer) {
                return WERR_INVALID_PARAM;
@@ -800,19 +821,17 @@ WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
        ZERO_STRUCT(domain_handle);
        ZERO_STRUCT(alias_handle);
 
-       werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
-       if (!W_ERROR_IS_OK(werr)) {
-               goto done;
-       }
-
-       werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
+       werr = libnetapi_open_pipe(ctx, r->in.server_name,
+                                  &ndr_table_samr.syntax_id,
                                   &pipe_cli);
        if (!W_ERROR_IS_OK(werr)) {
                goto done;
        }
 
+       b = pipe_cli->binding_handle;
+
        werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
-                                                 SAMR_ACCESS_OPEN_DOMAIN |
+                                                 SAMR_ACCESS_LOOKUP_DOMAIN |
                                                  SAMR_ACCESS_ENUM_DOMAINS,
                                                  SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
                                                  SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
@@ -824,7 +843,7 @@ WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
        }
 
        werr = libnetapi_samr_open_domain(ctx, pipe_cli,
-                                         SAMR_ACCESS_OPEN_DOMAIN |
+                                         SAMR_ACCESS_LOOKUP_DOMAIN |
                                          SAMR_ACCESS_ENUM_DOMAINS,
                                          SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
                                          SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
@@ -836,42 +855,57 @@ WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
                goto done;
        }
 
-       status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
+       status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
                                             &builtin_handle,
                                             2,
-                                            &builtin_info);
+                                            &builtin_info,
+                                            &result);
        if (!NT_STATUS_IS_OK(status)) {
                werr = ntstatus_to_werror(status);
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               werr = ntstatus_to_werror(result);
+               goto done;
+       }
 
        if (r->out.total_entries) {
-               *r->out.total_entries += builtin_info->info2.num_aliases;
+               *r->out.total_entries += builtin_info->general.num_aliases;
        }
 
-       status = rpccli_samr_QueryDomainInfo(pipe_cli, ctx,
+       status = dcerpc_samr_QueryDomainInfo(b, talloc_tos(),
                                             &domain_handle,
                                             2,
-                                            &domain_info);
+                                            &domain_info,
+                                            &result);
        if (!NT_STATUS_IS_OK(status)) {
                werr = ntstatus_to_werror(status);
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               werr = ntstatus_to_werror(result);
+               goto done;
+       }
 
        if (r->out.total_entries) {
-               *r->out.total_entries += domain_info->info2.num_aliases;
+               *r->out.total_entries += domain_info->general.num_aliases;
        }
 
-       status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
+       status = dcerpc_samr_EnumDomainAliases(b, talloc_tos(),
                                               &builtin_handle,
                                               r->in.resume_handle,
                                               &builtin_sam_array,
                                               r->in.prefmaxlen,
-                                              &entries_read);
+                                              &entries_read,
+                                              &result);
        if (!NT_STATUS_IS_OK(status)) {
                werr = ntstatus_to_werror(status);
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               werr = ntstatus_to_werror(result);
+               goto done;
+       }
 
        for (i=0; i<builtin_sam_array->count; i++) {
                union samr_AliasInfo *alias_info = NULL;
@@ -898,16 +932,21 @@ WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
                                                r->out.buffer);
        }
 
-       status = rpccli_samr_EnumDomainAliases(pipe_cli, ctx,
+       status = dcerpc_samr_EnumDomainAliases(b, talloc_tos(),
                                               &domain_handle,
                                               r->in.resume_handle,
                                               &domain_sam_array,
                                               r->in.prefmaxlen,
-                                              &entries_read);
+                                              &entries_read,
+                                              &result);
        if (!NT_STATUS_IS_OK(status)) {
                werr = ntstatus_to_werror(status);
                goto done;
        }
+       if (!NT_STATUS_IS_OK(result)) {
+               werr = ntstatus_to_werror(result);
+               goto done;
+       }
 
        for (i=0; i<domain_sam_array->count; i++) {
 
@@ -935,10 +974,6 @@ WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
        }
 
  done:
-       if (!cli) {
-               return werr;
-       }
-
        if (ctx->disable_policy_handle_cache) {
                libnetapi_samr_close_domain_handle(ctx, &domain_handle);
                libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
@@ -953,6 +988,443 @@ WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx,
 
 WERROR NetLocalGroupEnum_l(struct libnetapi_ctx *ctx,
                           struct NetLocalGroupEnum *r)
+{
+       LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupEnum);
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS libnetapi_lsa_lookup_names3(TALLOC_CTX *mem_ctx,
+                                           struct rpc_pipe_client *lsa_pipe,
+                                           const char *name,
+                                           struct dom_sid *sid)
+{
+       NTSTATUS status, result;
+       struct policy_handle lsa_handle;
+       struct dcerpc_binding_handle *b = lsa_pipe->binding_handle;
+
+       struct lsa_RefDomainList *domains = NULL;
+       struct lsa_TransSidArray3 sids;
+       uint32_t count = 0;
+
+       struct lsa_String names;
+       uint32_t num_names = 1;
+
+       if (!sid || !name) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       ZERO_STRUCT(sids);
+
+       init_lsa_String(&names, name);
+
+       status = rpccli_lsa_open_policy2(lsa_pipe, mem_ctx,
+                                        false,
+                                        SEC_STD_READ_CONTROL |
+                                        LSA_POLICY_VIEW_LOCAL_INFORMATION |
+                                        LSA_POLICY_LOOKUP_NAMES,
+                                        &lsa_handle);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       status = dcerpc_lsa_LookupNames3(b, mem_ctx,
+                                        &lsa_handle,
+                                        num_names,
+                                        &names,
+                                        &domains,
+                                        &sids,
+                                        LSA_LOOKUP_NAMES_ALL, /* sure ? */
+                                        &count,
+                                        0, 0,
+                                        &result);
+       NT_STATUS_NOT_OK_RETURN(status);
+       NT_STATUS_NOT_OK_RETURN(result);
+
+       if (count != 1 || sids.count != 1) {
+               return NT_STATUS_NONE_MAPPED;
+       }
+
+       sid_copy(sid, sids.sids[0].sid);
+
+       return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
+                                          struct NetLocalGroupAddMembers *add,
+                                          struct NetLocalGroupDelMembers *del,
+                                          struct NetLocalGroupSetMembers *set)
+{
+       struct NetLocalGroupAddMembers *r = NULL;
+
+       struct rpc_pipe_client *pipe_cli = NULL;
+       struct rpc_pipe_client *lsa_pipe = NULL;
+       NTSTATUS status, result;
+       WERROR werr;
+       struct lsa_String lsa_account_name;
+       struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
+       struct dom_sid2 *domain_sid = NULL;
+       struct dom_sid *member_sids = NULL;
+       int i = 0, k = 0;
+
+       struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
+       struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;
+
+       struct dom_sid *add_sids = NULL;
+       struct dom_sid *del_sids = NULL;
+       uint32_t num_add_sids = 0;
+       uint32_t num_del_sids = 0;
+       struct dcerpc_binding_handle *b = NULL;
+
+       if ((!add && !del && !set) || (add && del && set)) {
+               return WERR_INVALID_PARAM;
+       }
+
+       if (add) {
+               r = add;
+       }
+
+       if (del) {
+               r = (struct NetLocalGroupAddMembers *)del;
+       }
+
+       if (set) {
+               r = (struct NetLocalGroupAddMembers *)set;
+       }
+
+       if (!r->in.group_name) {
+               return WERR_INVALID_PARAM;
+       }
+
+       switch (r->in.level) {
+               case 0:
+               case 3:
+                       break;
+               default:
+                       return WERR_UNKNOWN_LEVEL;
+       }
+
+       if (r->in.total_entries == 0 || !r->in.buffer) {
+               return WERR_INVALID_PARAM;
+       }
+
+       ZERO_STRUCT(connect_handle);
+       ZERO_STRUCT(builtin_handle);
+       ZERO_STRUCT(domain_handle);
+       ZERO_STRUCT(alias_handle);
+
+       member_sids = TALLOC_ZERO_ARRAY(ctx, struct dom_sid,
+                                       r->in.total_entries);
+       W_ERROR_HAVE_NO_MEMORY(member_sids);
+
+       switch (r->in.level) {
+               case 0:
+                       info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
+                       for (i=0; i < r->in.total_entries; i++) {
+                               sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
+                       }
+                       break;
+               case 3:
+                       info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
+                       break;
+               default:
+                       break;
+       }
+
+       if (r->in.level == 3) {
+               werr = libnetapi_open_pipe(ctx, r->in.server_name,
+                                          &ndr_table_lsarpc.syntax_id,
+                                          &lsa_pipe);
+               if (!W_ERROR_IS_OK(werr)) {
+                       goto done;
+               }
+
+               for (i=0; i < r->in.total_entries; i++) {
+                       status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
+                                                            info3[i].lgrmi3_domainandname,
+                                                            &member_sids[i]);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               werr = ntstatus_to_werror(status);
+                               goto done;
+                       }
+               }
+               TALLOC_FREE(lsa_pipe);
+       }
+
+       werr = libnetapi_open_pipe(ctx, r->in.server_name,
+                                  &ndr_table_samr.syntax_id,
+                                  &pipe_cli);
+       if (!W_ERROR_IS_OK(werr)) {
+               goto done;
+       }
+
+       b = pipe_cli->binding_handle;
+
+       werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
+                                                 SAMR_ACCESS_LOOKUP_DOMAIN |
+                                                 SAMR_ACCESS_ENUM_DOMAINS,
+                                                 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+                                                 &connect_handle,
+                                                 &builtin_handle);
+       if (!W_ERROR_IS_OK(werr)) {
+               goto done;
+       }
+
+       init_lsa_String(&lsa_account_name, r->in.group_name);
+
+       status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+                                                     &builtin_handle,
+                                                     r->in.group_name,
+                                                     SAMR_ALIAS_ACCESS_ADD_MEMBER |
+                                                     SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
+                                                     SAMR_ALIAS_ACCESS_GET_MEMBERS |
+                                                     SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+                                                     &alias_handle);
+
+       if (ctx->disable_policy_handle_cache) {
+               libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+       }
+
+       if (NT_STATUS_IS_OK(status)) {
+               goto modify_membership;
+       }
+
+       werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+                                         SAMR_ACCESS_ENUM_DOMAINS |
+                                         SAMR_ACCESS_LOOKUP_DOMAIN,
+                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+                                         &connect_handle,
+                                         &domain_handle,
+                                         &domain_sid);
+       if (!W_ERROR_IS_OK(werr)) {
+               goto done;
+       }
+
+       status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
+                                                     &domain_handle,
+                                                     r->in.group_name,
+                                                     SAMR_ALIAS_ACCESS_ADD_MEMBER |
+                                                     SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
+                                                     SAMR_ALIAS_ACCESS_GET_MEMBERS |
+                                                     SAMR_ALIAS_ACCESS_LOOKUP_INFO,
+                                                     &alias_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               werr = ntstatus_to_werror(status);
+               goto done;
+       }
+
+       if (ctx->disable_policy_handle_cache) {
+               libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+       }
+
+ modify_membership:
+
+       if (add) {
+               for (i=0; i < r->in.total_entries; i++) {
+                       status = add_sid_to_array_unique(ctx, &member_sids[i],
+                                                        &add_sids,
+                                                        &num_add_sids);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               werr = ntstatus_to_werror(status);
+                               goto done;
+                       }
+               }
+       }
+
+       if (del) {
+               for (i=0; i < r->in.total_entries; i++) {
+                       status = add_sid_to_array_unique(ctx, &member_sids[i],
+                                                        &del_sids,
+                                                        &num_del_sids);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               werr = ntstatus_to_werror(status);
+                               goto done;
+                       }
+               }
+       }
+
+       if (set) {
+
+               struct lsa_SidArray current_sids;
+
+               status = dcerpc_samr_GetMembersInAlias(b, talloc_tos(),
+                                                      &alias_handle,
+                                                      &current_sids,
+                                                      &result);
+               if (!NT_STATUS_IS_OK(status)) {
+                       werr = ntstatus_to_werror(status);
+                       goto done;
+               }
+               if (!NT_STATUS_IS_OK(result)) {
+                       werr = ntstatus_to_werror(result);
+                       goto done;
+               }
+
+               /* add list */
+
+               for (i=0; i < r->in.total_entries; i++) {
+                       bool already_member = false;
+                       for (k=0; k < current_sids.num_sids; k++) {
+                               if (dom_sid_equal(&member_sids[i],
+                                             current_sids.sids[k].sid)) {
+                                       already_member = true;
+                                       break;
+                               }
+                       }
+                       if (!already_member) {
+                               status = add_sid_to_array_unique(ctx,
+                                       &member_sids[i],
+                                       &add_sids, &num_add_sids);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       werr = ntstatus_to_werror(status);
+                                       goto done;
+                               }
+                       }
+               }
+
+               /* del list */
+
+               for (k=0; k < current_sids.num_sids; k++) {
+                       bool keep_member = false;
+                       for (i=0; i < r->in.total_entries; i++) {
+                               if (dom_sid_equal(&member_sids[i],
+                                             current_sids.sids[k].sid)) {
+                                       keep_member = true;
+                                       break;
+                               }
+                       }
+                       if (!keep_member) {
+                               status = add_sid_to_array_unique(ctx,
+                                               current_sids.sids[k].sid,
+                                               &del_sids, &num_del_sids);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       werr = ntstatus_to_werror(status);
+                                       goto done;
+                               }
+                       }
+               }
+       }
+
+       /* add list */
+
+       for (i=0; i < num_add_sids; i++) {
+               status = dcerpc_samr_AddAliasMember(b, talloc_tos(),
+                                                   &alias_handle,
+                                                   &add_sids[i],
+                                                   &result);
+               if (!NT_STATUS_IS_OK(status)) {
+                       werr = ntstatus_to_werror(status);
+                       goto done;
+               }
+               if (!NT_STATUS_IS_OK(result)) {
+                       werr = ntstatus_to_werror(result);
+                       goto done;
+               }
+       }
+
+       /* del list */
+
+       for (i=0; i < num_del_sids; i++) {
+               status = dcerpc_samr_DeleteAliasMember(b, talloc_tos(),
+                                                      &alias_handle,
+                                                      &del_sids[i],
+                                                      &result);
+               if (!NT_STATUS_IS_OK(status)) {
+                       werr = ntstatus_to_werror(status);
+                       goto done;
+               }
+               if (!NT_STATUS_IS_OK(result)) {
+                       werr = ntstatus_to_werror(result);
+                       goto done;
+               }
+       }
+
+       werr = WERR_OK;
+
+ done:
+       if (b && is_valid_policy_hnd(&alias_handle)) {
+               dcerpc_samr_Close(b, talloc_tos(), &alias_handle, &result);
+       }
+
+       if (ctx->disable_policy_handle_cache) {
+               libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+               libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
+               libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+       }
+
+       return werr;
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupAddMembers_r(struct libnetapi_ctx *ctx,
+                                struct NetLocalGroupAddMembers *r)
+{
+       return NetLocalGroupModifyMembers_r(ctx, r, NULL, NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupAddMembers_l(struct libnetapi_ctx *ctx,
+                                struct NetLocalGroupAddMembers *r)
+{
+       LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupAddMembers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupDelMembers_r(struct libnetapi_ctx *ctx,
+                                struct NetLocalGroupDelMembers *r)
+{
+       return NetLocalGroupModifyMembers_r(ctx, NULL, r, NULL);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupDelMembers_l(struct libnetapi_ctx *ctx,
+                                struct NetLocalGroupDelMembers *r)
+{
+       LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupDelMembers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupGetMembers_r(struct libnetapi_ctx *ctx,
+                                struct NetLocalGroupGetMembers *r)
 {
        return WERR_NOT_SUPPORTED;
 }
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupGetMembers_l(struct libnetapi_ctx *ctx,
+                                struct NetLocalGroupGetMembers *r)
+{
+       LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupGetMembers);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupSetMembers_r(struct libnetapi_ctx *ctx,
+                                struct NetLocalGroupSetMembers *r)
+{
+       return NetLocalGroupModifyMembers_r(ctx, NULL, NULL, r);
+}
+
+/****************************************************************
+****************************************************************/
+
+WERROR NetLocalGroupSetMembers_l(struct libnetapi_ctx *ctx,
+                                struct NetLocalGroupSetMembers *r)
+{
+       LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetLocalGroupSetMembers);
+}