From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- source3/rpc_client/cli_spoolss.c | 1006 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 1006 insertions(+) create mode 100644 source3/rpc_client/cli_spoolss.c (limited to 'source3/rpc_client/cli_spoolss.c') diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c new file mode 100644 index 0000000..094381c --- /dev/null +++ b/source3/rpc_client/cli_spoolss.c @@ -0,0 +1,1006 @@ +/* + Unix SMB/CIFS implementation. + RPC pipe client + + Copyright (C) Gerald Carter 2001-2005, + Copyright (C) Tim Potter 2000-2002, + Copyright (C) Andrew Tridgell 1994-2000, + Copyright (C) Jean-Francois Micouleau 1999-2000. + Copyright (C) Jeremy Allison 2005. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "rpc_client/rpc_client.h" +#include "../librpc/gen_ndr/ndr_spoolss_c.h" +#include "rpc_client/cli_spoolss.h" +#include "auth/gensec/gensec.h" +#include "auth/credentials/credentials.h" +#include "rpc_client/init_spoolss.h" + +/********************************************************************** + convenience wrapper around rpccli_spoolss_OpenPrinterEx +**********************************************************************/ + +WERROR rpccli_spoolss_openprinter_ex(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *printername, + uint32_t access_desired, + struct policy_handle *handle) +{ + NTSTATUS status; + WERROR werror; + struct spoolss_DevmodeContainer devmode_ctr; + struct spoolss_UserLevelCtr userlevel_ctr; + struct spoolss_UserLevel1 level1; + struct dcerpc_binding_handle *b = cli->binding_handle; + struct cli_credentials *creds = gensec_get_credentials(cli->auth->auth_ctx); + + ZERO_STRUCT(devmode_ctr); + + werror = spoolss_init_spoolss_UserLevel1(mem_ctx, + cli_credentials_get_username(creds), + &level1); + if (!W_ERROR_IS_OK(werror)) { + return werror; + } + + userlevel_ctr.level = 1; + userlevel_ctr.user_info.level1 = &level1; + + status = dcerpc_spoolss_OpenPrinterEx(b, mem_ctx, + printername, + NULL, + devmode_ctr, + access_desired, + userlevel_ctr, + handle, + &werror); + + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (!W_ERROR_IS_OK(werror)) { + return werror; + } + + return WERR_OK; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_GetPrinterDriver +**********************************************************************/ + +WERROR rpccli_spoolss_getprinterdriver(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + const char *architecture, + uint32_t level, + uint32_t offered, + union spoolss_DriverInfo *info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_GetPrinterDriver(b, mem_ctx, + handle, + architecture, + level, + (offered > 0) ? &buffer : NULL, + offered, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_GetPrinterDriver(b, mem_ctx, + handle, + architecture, + level, + &buffer, + offered, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_GetPrinterDriver2 +**********************************************************************/ + +WERROR rpccli_spoolss_getprinterdriver2(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + const char *architecture, + uint32_t level, + uint32_t offered, + uint32_t client_major_version, + uint32_t client_minor_version, + union spoolss_DriverInfo *info, + uint32_t *server_major_version, + uint32_t *server_minor_version) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_GetPrinterDriver2(b, mem_ctx, + handle, + architecture, + level, + (offered > 0) ? &buffer : NULL, + offered, + client_major_version, + client_minor_version, + info, + &needed, + server_major_version, + server_minor_version, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_GetPrinterDriver2(b, mem_ctx, + handle, + architecture, + level, + &buffer, + offered, + client_major_version, + client_minor_version, + info, + &needed, + server_major_version, + server_minor_version, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_AddPrinterEx +**********************************************************************/ + +WERROR rpccli_spoolss_addprinterex(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + struct spoolss_SetPrinterInfoCtr *info_ctr) +{ + WERROR result; + NTSTATUS status; + struct spoolss_DevmodeContainer devmode_ctr; + struct sec_desc_buf secdesc_ctr; + struct spoolss_UserLevelCtr userlevel_ctr; + struct spoolss_UserLevel1 level1; + struct policy_handle handle; + struct dcerpc_binding_handle *b = cli->binding_handle; + struct cli_credentials *creds = gensec_get_credentials(cli->auth->auth_ctx); + + ZERO_STRUCT(devmode_ctr); + ZERO_STRUCT(secdesc_ctr); + + result = spoolss_init_spoolss_UserLevel1(mem_ctx, + cli_credentials_get_username(creds), + &level1); + if (!W_ERROR_IS_OK(result)) { + return result; + } + + userlevel_ctr.level = 1; + userlevel_ctr.user_info.level1 = &level1; + + status = dcerpc_spoolss_AddPrinterEx(b, mem_ctx, + cli->srv_name_slash, + info_ctr, + &devmode_ctr, + &secdesc_ctr, + &userlevel_ctr, + &handle, + &result); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return result; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_GetPrinter +**********************************************************************/ + +WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + uint32_t level, + uint32_t offered, + union spoolss_PrinterInfo *info) +{ + NTSTATUS status; + WERROR werror; + DATA_BLOB buffer; + uint32_t needed; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_GetPrinter(b, mem_ctx, + handle, + level, + (offered > 0) ? &buffer : NULL, + offered, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_GetPrinter(b, mem_ctx, + handle, + level, + &buffer, + offered, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_GetJob +**********************************************************************/ + +WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + uint32_t job_id, + uint32_t level, + uint32_t offered, + union spoolss_JobInfo *info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_GetJob(b, mem_ctx, + handle, + job_id, + level, + (offered > 0) ? &buffer : NULL, + offered, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_GetJob(b, mem_ctx, + handle, + job_id, + level, + &buffer, + offered, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_EnumForms +**********************************************************************/ + +WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + uint32_t level, + uint32_t offered, + uint32_t *count, + union spoolss_FormInfo **info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_EnumForms(b, mem_ctx, + handle, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_EnumForms(b, mem_ctx, + handle, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_EnumPrintProcessors +**********************************************************************/ + +WERROR rpccli_spoolss_enumprintprocessors(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *servername, + const char *environment, + uint32_t level, + uint32_t offered, + uint32_t *count, + union spoolss_PrintProcessorInfo **info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_EnumPrintProcessors(b, mem_ctx, + servername, + environment, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_EnumPrintProcessors(b, mem_ctx, + servername, + environment, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_EnumPrintProcessorDataTypes +**********************************************************************/ + +WERROR rpccli_spoolss_enumprintprocessordatatypes(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *servername, + const char *print_processor_name, + uint32_t level, + uint32_t offered, + uint32_t *count, + union spoolss_PrintProcDataTypesInfo **info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_EnumPrintProcessorDataTypes(b, mem_ctx, + servername, + print_processor_name, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_EnumPrintProcessorDataTypes(b, mem_ctx, + servername, + print_processor_name, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_EnumPorts +**********************************************************************/ + +WERROR rpccli_spoolss_enumports(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *servername, + uint32_t level, + uint32_t offered, + uint32_t *count, + union spoolss_PortInfo **info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_EnumPorts(b, mem_ctx, + servername, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_EnumPorts(b, mem_ctx, + servername, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_EnumMonitors +**********************************************************************/ + +WERROR rpccli_spoolss_enummonitors(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *servername, + uint32_t level, + uint32_t offered, + uint32_t *count, + union spoolss_MonitorInfo **info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_EnumMonitors(b, mem_ctx, + servername, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_EnumMonitors(b, mem_ctx, + servername, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_EnumJobs +**********************************************************************/ + +WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + uint32_t firstjob, + uint32_t numjobs, + uint32_t level, + uint32_t offered, + uint32_t *count, + union spoolss_JobInfo **info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_EnumJobs(b, mem_ctx, + handle, + firstjob, + numjobs, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_EnumJobs(b, mem_ctx, + handle, + firstjob, + numjobs, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_EnumPrinterDrivers +**********************************************************************/ + +WERROR rpccli_spoolss_enumprinterdrivers(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *server, + const char *environment, + uint32_t level, + uint32_t offered, + uint32_t *count, + union spoolss_DriverInfo **info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_EnumPrinterDrivers(b, mem_ctx, + server, + environment, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_EnumPrinterDrivers(b, mem_ctx, + server, + environment, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_EnumPrinters +**********************************************************************/ + +WERROR rpccli_spoolss_enumprinters(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32_t flags, + const char *server, + uint32_t level, + uint32_t offered, + uint32_t *count, + union spoolss_PrinterInfo **info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + DATA_BLOB buffer; + struct dcerpc_binding_handle *b = cli->binding_handle; + + if (offered > 0) { + buffer = data_blob_talloc_zero(mem_ctx, offered); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + } + + status = dcerpc_spoolss_EnumPrinters(b, mem_ctx, + flags, + server, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) { + offered = needed; + buffer = data_blob_talloc_zero(mem_ctx, needed); + W_ERROR_HAVE_NO_MEMORY(buffer.data); + + status = dcerpc_spoolss_EnumPrinters(b, mem_ctx, + flags, + server, + level, + (offered > 0) ? &buffer : NULL, + offered, + count, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_GetPrinterData +**********************************************************************/ + +WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + const char *value_name, + uint32_t offered, + enum winreg_Type *type, + uint32_t *needed_p, + uint8_t **data_p) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + uint8_t *data; + struct dcerpc_binding_handle *b = cli->binding_handle; + + data = talloc_zero_array(mem_ctx, uint8_t, offered); + W_ERROR_HAVE_NO_MEMORY(data); + + status = dcerpc_spoolss_GetPrinterData(b, mem_ctx, + handle, + value_name, + type, + data, + offered, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) { + offered = needed; + data = talloc_zero_array(mem_ctx, uint8_t, offered); + W_ERROR_HAVE_NO_MEMORY(data); + + status = dcerpc_spoolss_GetPrinterData(b, mem_ctx, + handle, + value_name, + type, + data, + offered, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + *data_p = data; + *needed_p = needed; + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_EnumPrinterKey +**********************************************************************/ + +WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + const char *key_name, + const char ***key_buffer, + uint32_t offered) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + union spoolss_KeyNames _key_buffer; + uint32_t _ndr_size; + struct dcerpc_binding_handle *b = cli->binding_handle; + + status = dcerpc_spoolss_EnumPrinterKey(b, mem_ctx, + handle, + key_name, + &_ndr_size, + &_key_buffer, + offered, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) { + offered = needed; + status = dcerpc_spoolss_EnumPrinterKey(b, mem_ctx, + handle, + key_name, + &_ndr_size, + &_key_buffer, + offered, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + *key_buffer = _key_buffer.string_array; + + return werror; +} + +/********************************************************************** + convenience wrapper around rpccli_spoolss_EnumPrinterDataEx +**********************************************************************/ + +WERROR rpccli_spoolss_enumprinterdataex(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + struct policy_handle *handle, + const char *key_name, + uint32_t offered, + uint32_t *count, + struct spoolss_PrinterEnumValues **info) +{ + NTSTATUS status; + WERROR werror; + uint32_t needed; + struct dcerpc_binding_handle *b = cli->binding_handle; + + status = dcerpc_spoolss_EnumPrinterDataEx(b, mem_ctx, + handle, + key_name, + offered, + count, + info, + &needed, + &werror); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) { + offered = needed; + + status = dcerpc_spoolss_EnumPrinterDataEx(b, mem_ctx, + handle, + key_name, + offered, + count, + info, + &needed, + &werror); + } + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + return werror; +} -- cgit v1.2.3