summaryrefslogtreecommitdiffstats
path: root/source3/rpc_client/cli_spoolss.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:47:29 +0000
commit4f5791ebd03eaec1c7da0865a383175b05102712 (patch)
tree8ce7b00f7a76baa386372422adebbe64510812d4 /source3/rpc_client/cli_spoolss.c
parentInitial commit. (diff)
downloadsamba-4f5791ebd03eaec1c7da0865a383175b05102712.tar.xz
samba-4f5791ebd03eaec1c7da0865a383175b05102712.zip
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/rpc_client/cli_spoolss.c')
-rw-r--r--source3/rpc_client/cli_spoolss.c1006
1 files changed, 1006 insertions, 0 deletions
diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c
new file mode 100644
index 0000000..36ca806
--- /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 <http://www.gnu.org/licenses/>.
+*/
+
+#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"
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}
+
+/**********************************************************************
+ convencience 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;
+}