From 5f60855ba2eb822dcb867378ff09278c42931b89 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 2 Dec 2009 14:25:31 +0100 Subject: samba-spoolss: use spoolss_StringArray2 in spoolss_EnumPrinterKey. This should finally resolve the endian issues we were seeing on sparc and is much cleaner for spoolss clients and servers. Guenther --- librpc/gen_ndr/cli_spoolss.c | 8 ++++---- librpc/gen_ndr/cli_spoolss.h | 4 ++-- librpc/gen_ndr/ndr_spoolss.c | 41 +++++++++---------------------------- librpc/gen_ndr/spoolss.h | 2 +- librpc/gen_ndr/srv_spoolss.c | 4 ++-- librpc/idl/spoolss.idl | 2 +- source3/rpc_client/cli_spoolss.c | 24 ++++------------------ source3/rpc_server/srv_spoolss_nt.c | 2 +- source4/torture/rpc/spoolss.c | 19 +++-------------- source4/torture/rpc/spoolss_win.c | 19 +++-------------- 10 files changed, 31 insertions(+), 94 deletions(-) diff --git a/librpc/gen_ndr/cli_spoolss.c b/librpc/gen_ndr/cli_spoolss.c index aba70f2d2d..0a5c2a6eb7 100644 --- a/librpc/gen_ndr/cli_spoolss.c +++ b/librpc/gen_ndr/cli_spoolss.c @@ -12207,7 +12207,7 @@ struct tevent_req *rpccli_spoolss_EnumPrinterKey_send(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, struct policy_handle *_handle /* [in] [ref] */, const char *_key_name /* [in] [charset(UTF16)] */, - uint16_t *_key_buffer /* [out] [ref,size_is(offered/2)] */, + struct spoolss_StringArray2 *_key_buffer /* [out] [ref] */, uint32_t _offered /* [in] */, uint32_t *_needed /* [out] [ref] */) { @@ -12278,7 +12278,7 @@ static void rpccli_spoolss_EnumPrinterKey_done(struct tevent_req *subreq) } /* Copy out parameters */ - memcpy(state->orig.out.key_buffer, state->tmp.out.key_buffer, (state->tmp.in.offered / 2) * sizeof(*state->orig.out.key_buffer)); + *state->orig.out.key_buffer = *state->tmp.out.key_buffer; *state->orig.out.needed = *state->tmp.out.needed; /* Copy result */ @@ -12317,7 +12317,7 @@ NTSTATUS rpccli_spoolss_EnumPrinterKey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle /* [in] [ref] */, const char *key_name /* [in] [charset(UTF16)] */, - uint16_t *key_buffer /* [out] [ref,size_is(offered/2)] */, + struct spoolss_StringArray2 *key_buffer /* [out] [ref] */, uint32_t offered /* [in] */, uint32_t *needed /* [out] [ref] */, WERROR *werror) @@ -12345,7 +12345,7 @@ NTSTATUS rpccli_spoolss_EnumPrinterKey(struct rpc_pipe_client *cli, } /* Return variables */ - memcpy(key_buffer, r.out.key_buffer, (r.in.offered / 2) * sizeof(*key_buffer)); + *key_buffer = *r.out.key_buffer; *needed = *r.out.needed; /* Return result */ diff --git a/librpc/gen_ndr/cli_spoolss.h b/librpc/gen_ndr/cli_spoolss.h index 943cbce17e..58a45ee672 100644 --- a/librpc/gen_ndr/cli_spoolss.h +++ b/librpc/gen_ndr/cli_spoolss.h @@ -1262,7 +1262,7 @@ struct tevent_req *rpccli_spoolss_EnumPrinterKey_send(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, struct policy_handle *_handle /* [in] [ref] */, const char *_key_name /* [in] [charset(UTF16)] */, - uint16_t *_key_buffer /* [out] [ref,size_is(offered/2)] */, + struct spoolss_StringArray2 *_key_buffer /* [out] [ref] */, uint32_t _offered /* [in] */, uint32_t *_needed /* [out] [ref] */); NTSTATUS rpccli_spoolss_EnumPrinterKey_recv(struct tevent_req *req, @@ -1272,7 +1272,7 @@ NTSTATUS rpccli_spoolss_EnumPrinterKey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle /* [in] [ref] */, const char *key_name /* [in] [charset(UTF16)] */, - uint16_t *key_buffer /* [out] [ref,size_is(offered/2)] */, + struct spoolss_StringArray2 *key_buffer /* [out] [ref] */, uint32_t offered /* [in] */, uint32_t *needed /* [out] [ref] */, WERROR *werror); diff --git a/librpc/gen_ndr/ndr_spoolss.c b/librpc/gen_ndr/ndr_spoolss.c index 44b3188fb8..41d07d1e60 100644 --- a/librpc/gen_ndr/ndr_spoolss.c +++ b/librpc/gen_ndr/ndr_spoolss.c @@ -28127,7 +28127,6 @@ _PUBLIC_ void ndr_print_spoolss_EnumPrinterDataEx(struct ndr_print *ndr, const c _PUBLIC_ enum ndr_err_code ndr_push_spoolss_EnumPrinterKey(struct ndr_push *ndr, int flags, const struct spoolss_EnumPrinterKey *r) { - uint32_t cntr_key_buffer_1; if (flags & NDR_IN) { if (r->in.handle == NULL) { return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer"); @@ -28143,10 +28142,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_spoolss_EnumPrinterKey(struct ndr_push *ndr, if (r->out.key_buffer == NULL) { return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer"); } - NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, r->in.offered / 2)); - for (cntr_key_buffer_1 = 0; cntr_key_buffer_1 < r->in.offered / 2; cntr_key_buffer_1++) { - NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->out.key_buffer[cntr_key_buffer_1])); - } + NDR_CHECK(ndr_push_spoolss_StringArray2(ndr, NDR_SCALARS, r->out.key_buffer)); if (r->out.needed == NULL) { return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer"); } @@ -28158,9 +28154,8 @@ _PUBLIC_ enum ndr_err_code ndr_push_spoolss_EnumPrinterKey(struct ndr_push *ndr, _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_EnumPrinterKey(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrinterKey *r) { - uint32_t cntr_key_buffer_1; TALLOC_CTX *_mem_save_handle_0; - TALLOC_CTX *_mem_save_key_buffer_1; + TALLOC_CTX *_mem_save_key_buffer_0; TALLOC_CTX *_mem_save_needed_0; if (flags & NDR_IN) { ZERO_STRUCT(r->out); @@ -28180,22 +28175,19 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_EnumPrinterKey(struct ndr_pull *ndr, NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->in.key_name), sizeof(uint16_t))); NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->in.key_name, ndr_get_array_length(ndr, &r->in.key_name), sizeof(uint16_t), CH_UTF16)); NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->in.offered)); - NDR_PULL_ALLOC_N(ndr, r->out.key_buffer, r->in.offered / 2); - memset(r->out.key_buffer, 0, (r->in.offered / 2) * sizeof(*r->out.key_buffer)); + NDR_PULL_ALLOC(ndr, r->out.key_buffer); + ZERO_STRUCTP(r->out.key_buffer); NDR_PULL_ALLOC(ndr, r->out.needed); ZERO_STRUCTP(r->out.needed); } if (flags & NDR_OUT) { - NDR_CHECK(ndr_pull_array_size(ndr, &r->out.key_buffer)); if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { - NDR_PULL_ALLOC_N(ndr, r->out.key_buffer, ndr_get_array_size(ndr, &r->out.key_buffer)); - } - _mem_save_key_buffer_1 = NDR_PULL_GET_MEM_CTX(ndr); - NDR_PULL_SET_MEM_CTX(ndr, r->out.key_buffer, 0); - for (cntr_key_buffer_1 = 0; cntr_key_buffer_1 < r->in.offered / 2; cntr_key_buffer_1++) { - NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->out.key_buffer[cntr_key_buffer_1])); + NDR_PULL_ALLOC(ndr, r->out.key_buffer); } - NDR_PULL_SET_MEM_CTX(ndr, _mem_save_key_buffer_1, 0); + _mem_save_key_buffer_0 = NDR_PULL_GET_MEM_CTX(ndr); + NDR_PULL_SET_MEM_CTX(ndr, r->out.key_buffer, LIBNDR_FLAG_REF_ALLOC); + NDR_CHECK(ndr_pull_spoolss_StringArray2(ndr, NDR_SCALARS, r->out.key_buffer)); + NDR_PULL_SET_MEM_CTX(ndr, _mem_save_key_buffer_0, LIBNDR_FLAG_REF_ALLOC); if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_PULL_ALLOC(ndr, r->out.needed); } @@ -28204,16 +28196,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_EnumPrinterKey(struct ndr_pull *ndr, NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, r->out.needed)); NDR_PULL_SET_MEM_CTX(ndr, _mem_save_needed_0, LIBNDR_FLAG_REF_ALLOC); NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &r->out.result)); - if (r->out.key_buffer) { - NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->out.key_buffer, r->in.offered / 2)); - } } return NDR_ERR_SUCCESS; } _PUBLIC_ void ndr_print_spoolss_EnumPrinterKey(struct ndr_print *ndr, const char *name, int flags, const struct spoolss_EnumPrinterKey *r) { - uint32_t cntr_key_buffer_1; ndr_print_struct(ndr, name, "spoolss_EnumPrinterKey"); ndr->depth++; if (flags & NDR_SET_VALUES) { @@ -28235,16 +28223,7 @@ _PUBLIC_ void ndr_print_spoolss_EnumPrinterKey(struct ndr_print *ndr, const char ndr->depth++; ndr_print_ptr(ndr, "key_buffer", r->out.key_buffer); ndr->depth++; - ndr->print(ndr, "%s: ARRAY(%d)", "key_buffer", (int)r->in.offered / 2); - ndr->depth++; - for (cntr_key_buffer_1=0;cntr_key_buffer_1in.offered / 2;cntr_key_buffer_1++) { - char *idx_1=NULL; - if (asprintf(&idx_1, "[%d]", cntr_key_buffer_1) != -1) { - ndr_print_uint16(ndr, "key_buffer", r->out.key_buffer[cntr_key_buffer_1]); - free(idx_1); - } - } - ndr->depth--; + ndr_print_spoolss_StringArray2(ndr, "key_buffer", r->out.key_buffer); ndr->depth--; ndr_print_ptr(ndr, "needed", r->out.needed); ndr->depth++; diff --git a/librpc/gen_ndr/spoolss.h b/librpc/gen_ndr/spoolss.h index 8327f8ff49..8b9a1ee8eb 100644 --- a/librpc/gen_ndr/spoolss.h +++ b/librpc/gen_ndr/spoolss.h @@ -3557,7 +3557,7 @@ struct spoolss_EnumPrinterKey { } in; struct { - uint16_t *key_buffer;/* [ref,size_is(offered/2)] */ + struct spoolss_StringArray2 *key_buffer;/* [ref] */ uint32_t *needed;/* [ref] */ WERROR result; } out; diff --git a/librpc/gen_ndr/srv_spoolss.c b/librpc/gen_ndr/srv_spoolss.c index 6ca334b3d2..3b981f0dbb 100644 --- a/librpc/gen_ndr/srv_spoolss.c +++ b/librpc/gen_ndr/srv_spoolss.c @@ -6325,7 +6325,7 @@ static bool api_spoolss_EnumPrinterKey(pipes_struct *p) } ZERO_STRUCT(r->out); - r->out.key_buffer = talloc_zero_array(r, uint16_t, r->in.offered / 2); + r->out.key_buffer = talloc_zero(r, struct spoolss_StringArray2); if (r->out.key_buffer == NULL) { talloc_free(r); return false; @@ -9504,7 +9504,7 @@ NTSTATUS rpc_spoolss_dispatch(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, case NDR_SPOOLSS_ENUMPRINTERKEY: { struct spoolss_EnumPrinterKey *r = (struct spoolss_EnumPrinterKey *)_r; ZERO_STRUCT(r->out); - r->out.key_buffer = talloc_zero_array(mem_ctx, uint16_t, r->in.offered / 2); + r->out.key_buffer = talloc_zero(mem_ctx, struct spoolss_StringArray2); if (r->out.key_buffer == NULL) { return NT_STATUS_NO_MEMORY; } diff --git a/librpc/idl/spoolss.idl b/librpc/idl/spoolss.idl index 84373aacb9..3ae1685e66 100644 --- a/librpc/idl/spoolss.idl +++ b/librpc/idl/spoolss.idl @@ -2583,7 +2583,7 @@ import "misc.idl", "security.idl", "winreg.idl"; [public] WERROR spoolss_EnumPrinterKey( [in, ref] policy_handle *handle, [in] [string,charset(UTF16)] uint16 key_name[], - [out,ref] [size_is(offered/2)] uint16 *key_buffer, + [out,ref] spoolss_StringArray2 *key_buffer, [in] uint32 offered, [out,ref] uint32 *needed ); diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c index a4622d07cf..047cb709ac 100644 --- a/source3/rpc_client/cli_spoolss.c +++ b/source3/rpc_client/cli_spoolss.c @@ -810,44 +810,28 @@ WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, NTSTATUS status; WERROR werror; uint32_t needed; - uint16_t *buffer = NULL; - - *key_buffer = NULL; - - if (offered) { - buffer = talloc_array(mem_ctx, uint16_t, offered/2); - W_ERROR_HAVE_NO_MEMORY(buffer); - } + struct spoolss_StringArray2 _key_buffer; status = rpccli_spoolss_EnumPrinterKey(cli, mem_ctx, handle, key_name, - buffer, + &_key_buffer, offered, &needed, &werror); if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) { offered = needed; - buffer = talloc_realloc(mem_ctx, buffer, uint16_t, needed/2); - W_ERROR_HAVE_NO_MEMORY(buffer); status = rpccli_spoolss_EnumPrinterKey(cli, mem_ctx, handle, key_name, - buffer, + &_key_buffer, offered, &needed, &werror); } - if (W_ERROR_IS_OK(werror)) { - const char **array; - DATA_BLOB blob = data_blob_const((uint8_t *)buffer, offered); - if (!pull_reg_multi_sz(mem_ctx, &blob, &array)) { - return WERR_NOMEM; - } - *key_buffer = array; - } + *key_buffer = _key_buffer.string; return werror; } diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index d74204800a..4a3f07f849 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -9157,7 +9157,7 @@ WERROR _spoolss_EnumPrinterKey(pipes_struct *p, result = WERR_MORE_DATA; } else { result = WERR_OK; - memcpy(r->out.key_buffer, blob.data, blob.length); + r->out.key_buffer->string = array; } done: diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c index 396ed75d25..e341b71307 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -3043,44 +3043,31 @@ bool test_printer_keys(struct torture_context *tctx, struct dcerpc_pipe *p, struct policy_handle *handle) { - DATA_BLOB blob; const char **key_array = NULL; int i; { struct spoolss_EnumPrinterKey r; uint32_t needed; - uint16_t *key_buffer = talloc_zero_array(tctx, uint16_t, 0); + struct spoolss_StringArray2 key_buffer; r.in.handle = handle; r.in.key_name = ""; r.in.offered = 0; - r.out.key_buffer = key_buffer; + r.out.key_buffer = &key_buffer; r.out.needed = &needed; torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r), "failed to call EnumPrinterKey"); if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) { r.in.offered = needed; - key_buffer = talloc_zero_array(tctx, uint16_t, needed/2); - r.out.key_buffer = key_buffer; torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r), "failed to call EnumPrinterKey"); } torture_assert_werr_ok(tctx, r.out.result, "failed to call EnumPrinterKey"); - blob = data_blob_const(key_buffer, needed); - } - - { - union winreg_Data data; - enum ndr_err_code ndr_err; - ndr_err = ndr_pull_union_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), - &data, REG_MULTI_SZ, - (ndr_pull_flags_fn_t)ndr_pull_winreg_Data); - torture_assert_ndr_success(tctx, ndr_err, "failed to pull REG_MULTI_SZ"); - key_array = data.string_array; + key_array = key_buffer.string; } for (i=0; key_array[i]; i++) { diff --git a/source4/torture/rpc/spoolss_win.c b/source4/torture/rpc/spoolss_win.c index 3a3245df55..d2851cfea1 100644 --- a/source4/torture/rpc/spoolss_win.c +++ b/source4/torture/rpc/spoolss_win.c @@ -384,17 +384,15 @@ static bool test_EnumPrinterKey(struct torture_context *tctx, NTSTATUS status; struct spoolss_EnumPrinterKey epk; uint32_t needed = 0; - uint16_t *key_buffer; + struct spoolss_StringArray2 key_buffer; torture_comment(tctx, "Testing EnumPrinterKey(%s)\n", key); - key_buffer = talloc_zero_array(tctx, uint16_t, 0); - epk.in.handle = handle; epk.in.key_name = talloc_strdup(tctx, key); epk.in.offered = 0; epk.out.needed = &needed; - epk.out.key_buffer = key_buffer; + epk.out.key_buffer = &key_buffer; status = dcerpc_spoolss_EnumPrinterKey(p, tctx, &epk); torture_assert_ntstatus_ok(tctx, status, "EnumPrinterKey failed"); @@ -402,8 +400,6 @@ static bool test_EnumPrinterKey(struct torture_context *tctx, if (W_ERROR_EQUAL(epk.out.result, WERR_MORE_DATA)) { epk.in.offered = needed; - key_buffer = talloc_zero_array(tctx, uint16_t, needed/2); - epk.out.key_buffer = key_buffer; status = dcerpc_spoolss_EnumPrinterKey(p, tctx, &epk); torture_assert_ntstatus_ok(tctx, status, "EnumPrinterKey failed"); @@ -411,16 +407,7 @@ static bool test_EnumPrinterKey(struct torture_context *tctx, torture_assert_werr_ok(tctx, epk.out.result, "EnumPrinterKey failed"); - { - union winreg_Data data; - enum ndr_err_code ndr_err; - DATA_BLOB blob = data_blob_const(key_buffer, needed); - ndr_err = ndr_pull_union_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), - &data, REG_MULTI_SZ, - (ndr_pull_flags_fn_t)ndr_pull_winreg_Data); - torture_assert_ndr_success(tctx, ndr_err, "failed to pull REG_MULTI_SZ"); - ctx->printer_keys = data.string_array; - } + ctx->printer_keys = key_buffer.string; return true; } -- cgit