s3-spoolss: remove unused decode_printer_info_7.
[ira/wip.git] / source3 / rpc_client / cli_spoolss.c
index 92077f963779ecfd98eacc8fa29d6663f1ed346c..4c1d57e063f85253b10bbfd5587ed396c9df0023 100644 (file)
@@ -2,15 +2,15 @@
    Unix SMB/CIFS implementation.
    RPC pipe client
 
-   Copyright (C) Gerald Carter                2001-2002,
+   Copyright (C) Gerald Carter                2001-2005,
    Copyright (C) Tim Potter                   2000-2002,
    Copyright (C) Andrew Tridgell              1994-2000,
-   Copyright (C) Luke Kenneth Casson Leighton 1996-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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "rpc_client.h"
 
-/** @defgroup spoolss SPOOLSS - NT printing routines
- *  @ingroup rpc_client
- *
- * @{
- **/
+/**********************************************************************
+ 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;
+       union spoolss_UserLevel userlevel;
+       struct spoolss_UserLevel1 level1;
+
+       ZERO_STRUCT(devmode_ctr);
+
+       level1.size     = 28;
+       level1.client   = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
+       W_ERROR_HAVE_NO_MEMORY(level1.client);
+       level1.user     = cli->auth->user_name;
+       level1.build    = 1381;
+       level1.major    = 2;
+       level1.minor    = 0;
+       level1.processor = 0;
+
+       userlevel.level1 = &level1;
+
+       status = rpccli_spoolss_OpenPrinterEx(cli, mem_ctx,
+                                             printername,
+                                             NULL,
+                                             devmode_ctr,
+                                             access_desired,
+                                             1, /* level */
+                                             userlevel,
+                                             handle,
+                                             &werror);
+
+       if (!W_ERROR_IS_OK(werror)) {
+               return werror;
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return ntstatus_to_werror(status);
+       }
+
+       return WERR_OK;
+}
+
+/**********************************************************************
+ 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;
+
+       if (offered > 0) {
+               buffer = data_blob_talloc_zero(mem_ctx, offered);
+               W_ERROR_HAVE_NO_MEMORY(buffer.data);
+       }
+
+       status = rpccli_spoolss_GetPrinterDriver2(cli, 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 (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 = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx,
+                                                         handle,
+                                                         architecture,
+                                                         level,
+                                                         &buffer,
+                                                         offered,
+                                                         client_major_version,
+                                                         client_minor_version,
+                                                         info,
+                                                         &needed,
+                                                         server_major_version,
+                                                         server_minor_version,
+                                                         &werror);
+       }
+
+       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;
+
+       ZERO_STRUCT(devmode_ctr);
+       ZERO_STRUCT(secdesc_ctr);
+
+       level1.size             = 28;
+       level1.build            = 1381;
+       level1.major            = 2;
+       level1.minor            = 0;
+       level1.processor        = 0;
+       level1.client           = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
+       W_ERROR_HAVE_NO_MEMORY(level1.client);
+       level1.user             = cli->auth->user_name;
+
+       userlevel_ctr.level = 1;
+       userlevel_ctr.user_info.level1 = &level1;
+
+       status = rpccli_spoolss_AddPrinterEx(cli, mem_ctx,
+                                            cli->srv_name_slash,
+                                            info_ctr,
+                                            &devmode_ctr,
+                                            &secdesc_ctr,
+                                            &userlevel_ctr,
+                                            &handle,
+                                            &result);
+       return result;
+}
 
 /**********************************************************************
- Initialize a new spoolss buff for use by a client rpc
+ convencience wrapper around rpccli_spoolss_GetPrinter
 **********************************************************************/
-static void init_buffer(NEW_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx)
+
+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)
 {
-       buffer->ptr = (size != 0);
-       buffer->size = size;
-       buffer->string_at_end = size;
-       prs_init(&buffer->prs, size, ctx, MARSHALL);
-       buffer->struct_start = prs_offset(&buffer->prs);
+       NTSTATUS status;
+       WERROR werror;
+       DATA_BLOB buffer;
+       uint32_t needed;
+
+       if (offered > 0) {
+               buffer = data_blob_talloc_zero(mem_ctx, offered);
+               W_ERROR_HAVE_NO_MEMORY(buffer.data);
+       }
+
+       status = rpccli_spoolss_GetPrinter(cli, mem_ctx,
+                                          handle,
+                                          level,
+                                          (offered > 0) ? &buffer : NULL,
+                                          offered,
+                                          info,
+                                          &needed,
+                                          &werror);
+
+       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 = rpccli_spoolss_GetPrinter(cli, mem_ctx,
+                                                  handle,
+                                                  level,
+                                                  &buffer,
+                                                  offered,
+                                                  info,
+                                                  &needed,
+                                                  &werror);
+       }
+
+       return werror;
 }
 
 /*********************************************************************
@@ -49,2317 +234,1043 @@ static void init_buffer(NEW_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx)
 
 /**********************************************************************
 **********************************************************************/
-static void decode_printer_info_0(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
+
+static bool decode_printer_info_0(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
                                uint32 returned, PRINTER_INFO_0 **info)
 {
-        uint32 i;
-        PRINTER_INFO_0  *inf;
+       uint32 i;
+       PRINTER_INFO_0  *inf;
 
-        inf=(PRINTER_INFO_0 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_0));
-       memset(inf, 0, returned*sizeof(PRINTER_INFO_0));
+       if (returned) {
+               inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_0, returned);
+               if (!inf) {
+                       return False;
+               }
+               memset(inf, 0, returned*sizeof(PRINTER_INFO_0));
+       } else {
+               inf = NULL;
+       }
 
-        buffer->prs.data_offset=0;
+       prs_set_offset(&buffer->prs,0);
 
-        for (i=0; i<returned; i++) {
-                smb_io_printer_info_0("", buffer, &inf[i], 0);
-        }
+       for (i=0; i<returned; i++) {
+               if (!smb_io_printer_info_0("", buffer, &inf[i], 0)) {
+                       return False;
+               }
+       }
 
-        *info=inf;
+       *info=inf;
+       return True;
 }
 
 /**********************************************************************
 **********************************************************************/
-static void decode_printer_info_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
+
+static bool decode_printer_info_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
                                uint32 returned, PRINTER_INFO_1 **info)
 {
-        uint32 i;
-        PRINTER_INFO_1  *inf;
+       uint32 i;
+       PRINTER_INFO_1  *inf;
 
-        inf=(PRINTER_INFO_1 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_1));
-       memset(inf, 0, returned*sizeof(PRINTER_INFO_1));
+       if (returned) {
+               inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_1, returned);
+               if (!inf) {
+                       return False;
+               }
+               memset(inf, 0, returned*sizeof(PRINTER_INFO_1));
+       } else {
+               inf = NULL;
+       }
 
-        buffer->prs.data_offset=0;
+       prs_set_offset(&buffer->prs,0);
 
-        for (i=0; i<returned; i++) {
-                smb_io_printer_info_1("", buffer, &inf[i], 0);
-        }
+       for (i=0; i<returned; i++) {
+               if (!smb_io_printer_info_1("", buffer, &inf[i], 0)) {
+                       return False;
+               }
+       }
 
-        *info=inf;
+       *info=inf;
+       return True;
 }
 
 /**********************************************************************
 **********************************************************************/
-static void decode_printer_info_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, 
+
+static bool decode_printer_info_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
                                uint32 returned, PRINTER_INFO_2 **info)
 {
-        uint32 i;
-        PRINTER_INFO_2  *inf;
+       uint32 i;
+       PRINTER_INFO_2  *inf;
 
-        inf=(PRINTER_INFO_2 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_2));
-       memset(inf, 0, returned*sizeof(PRINTER_INFO_2));
+       if (returned) {
+               inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_2, returned);
+               if (!inf) {
+                       return False;
+               }
+               memset(inf, 0, returned*sizeof(PRINTER_INFO_2));
+       } else {
+               inf = NULL;
+       }
 
-        buffer->prs.data_offset=0;
+       prs_set_offset(&buffer->prs,0);
 
-        for (i=0; i<returned; i++) {
+       for (i=0; i<returned; i++) {
                /* a little initialization as we go */
                inf[i].secdesc = NULL;
-                smb_io_printer_info_2("", buffer, &inf[i], 0);
-        }
+               if (!smb_io_printer_info_2("", buffer, &inf[i], 0)) {
+                       return False;
+               }
+       }
 
-        *info=inf;
+       *info=inf;
+       return True;
 }
 
 /**********************************************************************
 **********************************************************************/
-static void decode_printer_info_3(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, 
+
+static bool decode_printer_info_3(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
                                uint32 returned, PRINTER_INFO_3 **info)
 {
-        uint32 i;
-        PRINTER_INFO_3  *inf;
+       uint32 i;
+       PRINTER_INFO_3  *inf;
 
-        inf=(PRINTER_INFO_3 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_3));
-       memset(inf, 0, returned*sizeof(PRINTER_INFO_3));
+       if (returned) {
+               inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_3, returned);
+               if (!inf) {
+                       return False;
+               }
+               memset(inf, 0, returned*sizeof(PRINTER_INFO_3));
+       } else {
+               inf = NULL;
+       }
 
-        buffer->prs.data_offset=0;
+       prs_set_offset(&buffer->prs,0);
 
-        for (i=0; i<returned; i++) {
+       for (i=0; i<returned; i++) {
                inf[i].secdesc = NULL;
-                smb_io_printer_info_3("", buffer, &inf[i], 0);
-        }
+               if (!smb_io_printer_info_3("", buffer, &inf[i], 0)) {
+                       return False;
+               }
+       }
 
-        *info=inf;
+       *info=inf;
+       return True;
 }
 
 /**********************************************************************
 **********************************************************************/
-static void decode_port_info_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, 
+
+static bool decode_port_info_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
                        uint32 returned, PORT_INFO_1 **info)
 {
-        uint32 i;
-        PORT_INFO_1 *inf;
+       uint32 i;
+       PORT_INFO_1 *inf;
 
-        inf=(PORT_INFO_1*)talloc(mem_ctx, returned*sizeof(PORT_INFO_1));
-       memset(inf, 0, returned*sizeof(PORT_INFO_1));
+       if (returned) {
+               inf=TALLOC_ARRAY(mem_ctx, PORT_INFO_1, returned);
+               if (!inf) {
+                       return False;
+               }
+               memset(inf, 0, returned*sizeof(PORT_INFO_1));
+       } else {
+               inf = NULL;
+       }
 
-        prs_set_offset(&buffer->prs, 0);
+       prs_set_offset(&buffer->prs, 0);
 
-        for (i=0; i<returned; i++) {
-                smb_io_port_info_1("", buffer, &(inf[i]), 0);
-        }
+       for (i=0; i<returned; i++) {
+               if (!smb_io_port_info_1("", buffer, &(inf[i]), 0)) {
+                       return False;
+               }
+       }
 
-        *info=inf;
+       *info=inf;
+       return True;
 }
 
 /**********************************************************************
 **********************************************************************/
-static void decode_port_info_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, 
+
+static bool decode_port_info_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
                        uint32 returned, PORT_INFO_2 **info)
 {
-        uint32 i;
-        PORT_INFO_2 *inf;
+       uint32 i;
+       PORT_INFO_2 *inf;
 
-        inf=(PORT_INFO_2*)talloc(mem_ctx, returned*sizeof(PORT_INFO_2));
-       memset(inf, 0, returned*sizeof(PORT_INFO_2));
+       if (returned) {
+               inf=TALLOC_ARRAY(mem_ctx, PORT_INFO_2, returned);
+               if (!inf) {
+                       return False;
+               }
+               memset(inf, 0, returned*sizeof(PORT_INFO_2));
+       } else {
+               inf = NULL;
+       }
 
-        prs_set_offset(&buffer->prs, 0);
+       prs_set_offset(&buffer->prs, 0);
 
-        for (i=0; i<returned; i++) {
-                smb_io_port_info_2("", buffer, &(inf[i]), 0);
-        }
+       for (i=0; i<returned; i++) {
+               if (!smb_io_port_info_2("", buffer, &(inf[i]), 0)) {
+                       return False;
+               }
+       }
 
-        *info=inf;
+       *info=inf;
+       return True;
 }
 
 /**********************************************************************
 **********************************************************************/
-static void decode_printer_driver_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, 
+
+static bool decode_printer_driver_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
                        uint32 returned, DRIVER_INFO_1 **info)
 {
-        uint32 i;
-        DRIVER_INFO_1 *inf;
+       uint32 i;
+       DRIVER_INFO_1 *inf;
 
-        inf=(DRIVER_INFO_1 *)talloc(mem_ctx, returned*sizeof(DRIVER_INFO_1));
-       memset(inf, 0, returned*sizeof(DRIVER_INFO_1));
+       if (returned) {
+               inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_1, returned);
+               if (!inf) {
+                       return False;
+               }
+               memset(inf, 0, returned*sizeof(DRIVER_INFO_1));
+       } else {
+               inf = NULL;
+       }
 
-        buffer->prs.data_offset=0;
+       prs_set_offset(&buffer->prs,0);
 
-        for (i=0; i<returned; i++) {
-                smb_io_printer_driver_info_1("", buffer, &(inf[i]), 0);
-        }
+       for (i=0; i<returned; i++) {
+               if (!smb_io_printer_driver_info_1("", buffer, &(inf[i]), 0)) {
+                       return False;
+               }
+       }
 
-        *info=inf;
+       *info=inf;
+       return True;
 }
 
 /**********************************************************************
 **********************************************************************/
-static void decode_printer_driver_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, 
+
+static bool decode_printer_driver_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
                        uint32 returned, DRIVER_INFO_2 **info)
 {
-        uint32 i;
-        DRIVER_INFO_2 *inf;
+       uint32 i;
+       DRIVER_INFO_2 *inf;
 
-        inf=(DRIVER_INFO_2 *)talloc(mem_ctx, returned*sizeof(DRIVER_INFO_2));
-       memset(inf, 0, returned*sizeof(DRIVER_INFO_2));
+       if (returned) {
+               inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_2, returned);
+               if (!inf) {
+                       return False;
+               }
+               memset(inf, 0, returned*sizeof(DRIVER_INFO_2));
+       } else {
+               inf = NULL;
+       }
 
-        buffer->prs.data_offset=0;
+       prs_set_offset(&buffer->prs,0);
 
-        for (i=0; i<returned; i++) {
-                smb_io_printer_driver_info_2("", buffer, &(inf[i]), 0);
-        }
+       for (i=0; i<returned; i++) {
+               if (!smb_io_printer_driver_info_2("", buffer, &(inf[i]), 0)) {
+                       return False;
+               }
+       }
 
-        *info=inf;
+       *info=inf;
+       return True;
 }
 
 /**********************************************************************
 **********************************************************************/
-static void decode_printer_driver_3(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, 
+
+static bool decode_printer_driver_3(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
                        uint32 returned, DRIVER_INFO_3 **info)
 {
-        uint32 i;
-        DRIVER_INFO_3 *inf;
+       uint32 i;
+       DRIVER_INFO_3 *inf;
 
-        inf=(DRIVER_INFO_3 *)talloc(mem_ctx, returned*sizeof(DRIVER_INFO_3));
-       memset(inf, 0, returned*sizeof(DRIVER_INFO_3));
+       if (returned) {
+               inf=TALLOC_ARRAY(mem_ctx, DRIVER_INFO_3, returned);
+               if (!inf) {
+                       return False;
+               }
+               memset(inf, 0, returned*sizeof(DRIVER_INFO_3));
+       } else {
+               inf = NULL;
+       }
 
-        buffer->prs.data_offset=0;
+       prs_set_offset(&buffer->prs,0);
 
-        for (i=0; i<returned; i++) {
-                smb_io_printer_driver_info_3("", buffer, &(inf[i]), 0);
-        }
+       for (i=0; i<returned; i++) {
+               if (!smb_io_printer_driver_info_3("", buffer, &(inf[i]), 0)) {
+                       return False;
+               }
+       }
 
-        *info=inf;
+       *info=inf;
+       return True;
 }
 
 /**********************************************************************
 **********************************************************************/
-static void decode_printerdriverdir_1 (TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
-                       uint32 returned, DRIVER_DIRECTORY_1 **info
-)
-{
-       DRIVER_DIRECTORY_1 *inf;
-        inf=(DRIVER_DIRECTORY_1 *)talloc(mem_ctx, sizeof(DRIVER_DIRECTORY_1));
-       memset(inf, 0, sizeof(DRIVER_DIRECTORY_1));
 
-        prs_set_offset(&buffer->prs, 0);
-
-        smb_io_driverdir_1("", buffer, inf, 0);
-       *info=inf;
-}
-
-/** Return a handle to the specified printer or print server.
- *
- * @param cli              Pointer to client state structure which is open
- * on the SPOOLSS pipe.
- *
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param printername      The name of the printer or print server to be
- * opened in UNC format.
- *
- * @param datatype         Specifies the default data type for the printer.
- *
- * @param access_required  The access rights requested on the printer or
- * print server.
- *
- * @param station          The UNC name of the requesting workstation.
- *
- * @param username         The name of the user requesting the open.
- *
- * @param pol              Returned policy handle.
- */
-
-/*********************************************************************************
- Win32 API - OpenPrinter()
- ********************************************************************************/
-
-WERROR cli_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                               char *printername, char *datatype, uint32 access_required,
-                               char *station, char *username, POLICY_HND *pol)
+static bool decode_jobs_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
+                         uint32 num_jobs, JOB_INFO_1 **jobs)
 {
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_OPEN_PRINTER_EX q;
-       SPOOL_R_OPEN_PRINTER_EX r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_open_printer_ex(&q, printername, datatype,
-                                       access_required, station, username);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_open_printer_ex("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_OPENPRINTEREX, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_open_printer_ex("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
+       uint32 i;
 
-       if (W_ERROR_IS_OK(result))
-               *pol = r.handle;
+       if (num_jobs) {
+               *jobs = TALLOC_ARRAY(mem_ctx, JOB_INFO_1, num_jobs);
+               if (*jobs == NULL) {
+                       return False;
+               }
+       } else {
+               *jobs = NULL;
+       }
+       prs_set_offset(&buffer->prs,0);
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       for (i = 0; i < num_jobs; i++) {
+               if (!smb_io_job_info_1("", buffer, &((*jobs)[i]), 0)) {
+                       return False;
+               }
+       }
 
-       return result;
+       return True;
 }
 
-/** Close a printer handle
- *
- * @param cli              Pointer to client state structure which is open
- * on the SPOOLSS pipe.
- *
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param pol              Policy handle of printer or print server to close.
- */
-/*********************************************************************************
- Win32 API - ClosePrinter()
- ********************************************************************************/
-
-WERROR cli_spoolss_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                POLICY_HND *pol)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_CLOSEPRINTER q;
-       SPOOL_R_CLOSEPRINTER r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
+/**********************************************************************
+**********************************************************************/
 
-        make_spoolss_q_closeprinter(&q, pol);
+static bool decode_jobs_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
+                         uint32 num_jobs, JOB_INFO_2 **jobs)
+{
+       uint32 i;
 
-       /* Marshall data and send request */
+       if (num_jobs) {
+               *jobs = TALLOC_ARRAY(mem_ctx, JOB_INFO_2, num_jobs);
+               if (*jobs == NULL) {
+                       return False;
+               }
+       } else {
+               *jobs = NULL;
+       }
+       prs_set_offset(&buffer->prs,0);
 
-       if (!spoolss_io_q_closeprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_CLOSEPRINTER, &qbuf, &rbuf))
-               goto done;
+       for (i = 0; i < num_jobs; i++) {
+               if (!smb_io_job_info_2("", buffer, &((*jobs)[i]), 0)) {
+                       return False;
+               }
+       }
 
-       /* Unmarshall response */
+       return True;
+}
 
-       if (!spoolss_io_r_closeprinter("", &r, &rbuf, 0))
-               goto done;
+/**********************************************************************
+**********************************************************************/
 
-       /* Return output parameters */
+static bool decode_forms_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, 
+                          uint32 num_forms, FORM_1 **forms)
+{
+       int i;
 
-       result = r.status;
+       if (num_forms) {
+               *forms = TALLOC_ARRAY(mem_ctx, FORM_1, num_forms);
+               if (*forms == NULL) {
+                       return False;
+               }
+       } else {
+               *forms = NULL;
+       }
 
-       if (W_ERROR_IS_OK(result))
-               *pol = r.handle;
+       prs_set_offset(&buffer->prs,0);
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       for (i = 0; i < num_forms; i++) {
+               if (!smb_io_form_1("", buffer, &((*forms)[i]), 0)) {
+                       return False;
+               }
+       }
 
-       return result;
+       return True;
 }
 
-/** Enumerate printers on a print server.
- *
- * @param cli              Pointer to client state structure which is open
- *                         on the SPOOLSS pipe.
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param offered          Buffer size offered in the request.
- * @param needed           Number of bytes needed to complete the request.
- *                         may be NULL.
- *
- * @param flags            Selected from PRINTER_ENUM_* flags.
- * @param level            Request information level.
- *
- * @param num_printers     Pointer to number of printers returned.  May be
- *                         NULL.
- * @param ctr              Return structure for printer information.  May
- *                         be NULL.
- */
-/*********************************************************************************
- Win32 API - EnumPrinters()
- ********************************************************************************/
-
-WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                uint32 offered, uint32 *needed,
+/**********************************************************************
+**********************************************************************/
+
+WERROR rpccli_spoolss_enum_printers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 char *name, uint32 flags, uint32 level,
                                 uint32 *num_printers, PRINTER_INFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
-       SPOOL_Q_ENUMPRINTERS q;
-        SPOOL_R_ENUMPRINTERS r;
-       NEW_BUFFER buffer;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise input parameters */
-
-       init_buffer(&buffer, offered, mem_ctx);
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       make_spoolss_q_enumprinters(&q, flags, name, level, &buffer, 
-                                   offered);
-
-       /* Marshall data and send request */
-       
-       if (!spoolss_io_q_enumprinters("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_ENUMPRINTERS, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (spoolss_io_r_enumprinters("", &r, &rbuf, 0)) {
-               if (needed)
-                       *needed = r.needed;
+       SPOOL_Q_ENUMPRINTERS in;
+        SPOOL_R_ENUMPRINTERS out;
+       RPC_BUFFER buffer;
+       uint32 offered;
+
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
+
+       offered = 0;
+       if (!rpcbuf_init(&buffer, offered, mem_ctx))
+               return WERR_NOMEM;
+       make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered );
+
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERS,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_enumprinters,
+                   spoolss_io_r_enumprinters, 
+                   WERR_GENERAL_FAILURE );
+                   
+       if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
+               offered = out.needed;
+               
+               ZERO_STRUCT(in);
+               ZERO_STRUCT(out);
+
+               if (!rpcbuf_init(&buffer, offered, mem_ctx))
+                       return WERR_NOMEM;
+               make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered );
+
+               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERS,
+                           in, out, 
+                           qbuf, rbuf,
+                           spoolss_io_q_enumprinters,
+                           spoolss_io_r_enumprinters, 
+                           WERR_GENERAL_FAILURE );
        }
-       
-       result = r.status;
-
-       /* Return output parameters */
-
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;
 
-       if (num_printers)
-               *num_printers = r.returned;
-
-       if (!ctr)
-               goto done;
+       if ( !W_ERROR_IS_OK(out.status) )
+               return out.status;
 
        switch (level) {
        case 0:
-               decode_printer_info_0(mem_ctx, r.buffer, r.returned, 
-                                     &ctr->printers_0);
+               if (!decode_printer_info_0(mem_ctx, out.buffer, out.returned, &ctr->printers_0)) {
+                       return WERR_GENERAL_FAILURE;
+               }
                break;
        case 1:
-               decode_printer_info_1(mem_ctx, r.buffer, r.returned, 
-                                     &ctr->printers_1);
+               if (!decode_printer_info_1(mem_ctx, out.buffer, out.returned, &ctr->printers_1)) {
+                       return WERR_GENERAL_FAILURE;
+               }
                break;
        case 2:
-               decode_printer_info_2(mem_ctx, r.buffer, r.returned, 
-                                     &ctr->printers_2);
+               if (!decode_printer_info_2(mem_ctx, out.buffer, out.returned, &ctr->printers_2)) {
+                       return WERR_GENERAL_FAILURE;
+               }
                break;
        case 3:
-               decode_printer_info_3(mem_ctx, r.buffer, r.returned, 
-                                     &ctr->printers_3);
+               if (!decode_printer_info_3(mem_ctx, out.buffer, out.returned, &ctr->printers_3)) {
+                       return WERR_GENERAL_FAILURE;
+               }
                break;
+       default:
+               return WERR_UNKNOWN_LEVEL;
        }                       
-       
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
-       return result;  
+       *num_printers = out.returned;
+
+       return out.status;
 }
 
-/*********************************************************************************
- Win32 API - EnumPorts()
- ********************************************************************************/
-/** Enumerate printer ports on a print server.
- *
- * @param cli              Pointer to client state structure which is open
- *                         on the SPOOLSS pipe.
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param offered          Buffer size offered in the request.
- * @param needed           Number of bytes needed to complete the request.
- *                         May be NULL.
- *
- * @param level            Requested information level.
- *
- * @param num_ports        Pointer to number of ports returned.  May be NULL.
- * @param ctr              Pointer to structure holding port information.
- *                         May be NULL.
- */
-
-WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                             uint32 offered, uint32 *needed,
+/**********************************************************************
+**********************************************************************/
+
+WERROR rpccli_spoolss_enum_ports(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              uint32 level, uint32 *num_ports, PORT_INFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
-       SPOOL_Q_ENUMPORTS q;
-        SPOOL_R_ENUMPORTS r;
-       NEW_BUFFER buffer;
-       WERROR result = W_ERROR(ERRgeneral);
+       SPOOL_Q_ENUMPORTS in;
+        SPOOL_R_ENUMPORTS out;
+       RPC_BUFFER buffer;
        fstring server;
+       uint32 offered;
 
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
 
-        slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-        strupper (server);
+        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+        strupper_m(server);
 
-       /* Initialise input parameters */
+       offered = 0;
+       if (!rpcbuf_init(&buffer, offered, mem_ctx))
+               return WERR_NOMEM;
+       make_spoolss_q_enumports( &in, server, level, &buffer, offered );
        
-       init_buffer(&buffer, offered, mem_ctx);
-       
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-       
-       make_spoolss_q_enumports(&q, server, level, &buffer, offered);
-       
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_enumports("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_ENUMPORTS, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (spoolss_io_r_enumports("", &r, &rbuf, 0)) {
-               if (needed)
-                       *needed = r.needed;
-       }
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPORTS,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_enumports,
+                   spoolss_io_r_enumports, 
+                   WERR_GENERAL_FAILURE );
+                       
+       if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
+               offered = out.needed;
                
-       result = r.status;
-
-       /* Return output parameters */
-
-       if (!W_ERROR_IS_OK(result))
-               goto done;
-
-       if (num_ports)
-               *num_ports = r.returned;
-
-       if (!ctr)
-               goto done;
+               ZERO_STRUCT(in);
+               ZERO_STRUCT(out);
+               
+               if (!rpcbuf_init(&buffer, offered, mem_ctx))
+                       return WERR_NOMEM;
+               make_spoolss_q_enumports( &in, server, level, &buffer, offered );
+
+               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPORTS,
+                           in, out, 
+                           qbuf, rbuf,
+                           spoolss_io_q_enumports,
+                           spoolss_io_r_enumports, 
+                           WERR_GENERAL_FAILURE );
+       }
+       
+       if ( !W_ERROR_IS_OK(out.status) )
+               return out.status;
        
        switch (level) {
        case 1:
-               decode_port_info_1(mem_ctx, r.buffer, r.returned, 
-                                  &ctr->port.info_1);
+               if (!decode_port_info_1(mem_ctx, out.buffer, out.returned, &ctr->port.info_1)) {
+                       return WERR_GENERAL_FAILURE;
+               }
                break;
        case 2:
-               decode_port_info_2(mem_ctx, r.buffer, r.returned, 
-                                  &ctr->port.info_2);
+               if (!decode_port_info_2(mem_ctx, out.buffer, out.returned, &ctr->port.info_2)) {
+                       return WERR_GENERAL_FAILURE;
+               }
                break;
-       }                       
+       default:
+               return WERR_UNKNOWN_LEVEL;
+       }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-       
-       return result;  
+       *num_ports = out.returned;
+
+       return out.status;
 }
 
-/*********************************************************************************
- Win32 API - GetPrinter()
- ********************************************************************************/
+/**********************************************************************
+**********************************************************************/
 
-WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                             uint32 offered, uint32 *needed,
-                             POLICY_HND *pol, uint32 level, 
-                             PRINTER_INFO_CTR *ctr)
+WERROR rpccli_spoolss_enumprinterdrivers (struct rpc_pipe_client *cli, 
+                                      TALLOC_CTX *mem_ctx,
+                                      uint32 level, const char *env,
+                                      uint32 *num_drivers,
+                                      PRINTER_DRIVER_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
-       SPOOL_Q_GETPRINTER q;
-       SPOOL_R_GETPRINTER r;
-       NEW_BUFFER buffer;
-       WERROR result = W_ERROR(ERRgeneral);
+       SPOOL_Q_ENUMPRINTERDRIVERS in;
+        SPOOL_R_ENUMPRINTERDRIVERS out;
+       RPC_BUFFER buffer;
+       fstring server;
+       uint32 offered;
 
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
 
-       /* Initialise input parameters */
+        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+        strupper_m(server);
 
-       init_buffer(&buffer, offered, mem_ctx);
+       offered = 0;
+       if (!rpcbuf_init(&buffer, offered, mem_ctx))
+               return WERR_NOMEM;
+       make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
+               &buffer, offered);
        
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       make_spoolss_q_getprinter(mem_ctx, &q, pol, level, &buffer, offered);
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDRIVERS,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_enumprinterdrivers,
+                   spoolss_io_r_enumprinterdrivers, 
+                   WERR_GENERAL_FAILURE );
+
+       if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
+               offered = out.needed;
+               
+               ZERO_STRUCT(in);
+               ZERO_STRUCT(out);
+               
+               if (!rpcbuf_init(&buffer, offered, mem_ctx))
+                       return WERR_NOMEM;
+               make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
+                       &buffer, offered);
        
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_getprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTER, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_getprinter("", &r, &rbuf, 0))
-               goto done;
-
-       if (needed)
-               *needed = r.needed;
+               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDRIVERS,
+                           in, out, 
+                           qbuf, rbuf,
+                           spoolss_io_q_enumprinterdrivers,
+                           spoolss_io_r_enumprinterdrivers, 
+                           WERR_GENERAL_FAILURE );
+       }
        
-       /* Return output parameters */
+       *num_drivers = out.returned;
 
-       result = r.status;
+       if ( !W_ERROR_IS_OK(out.status) )
+               return out.status;
+               
+       if ( out.returned ) {
 
-       if (W_ERROR_IS_OK(result)) {
                switch (level) {
-               case 0:
-                       decode_printer_info_0(mem_ctx, r.buffer, 1, &ctr->printers_0);
-                       break;
                case 1:
-                       decode_printer_info_1(mem_ctx, r.buffer, 1, &ctr->printers_1);
+                       if (!decode_printer_driver_1(mem_ctx, out.buffer, out.returned, &ctr->info1)) {
+                               return WERR_GENERAL_FAILURE;
+                       }
                        break;
                case 2:
-                       decode_printer_info_2(mem_ctx, r.buffer, 1, &ctr->printers_2);
+                       if (!decode_printer_driver_2(mem_ctx, out.buffer, out.returned, &ctr->info2)) {
+                               return WERR_GENERAL_FAILURE;
+                       }
                        break;
                case 3:
-                       decode_printer_info_3(mem_ctx, r.buffer, 1, &ctr->printers_3);
+                       if (!decode_printer_driver_3(mem_ctx, out.buffer, out.returned, &ctr->info3)) {
+                               return WERR_GENERAL_FAILURE;
+                       }
                        break;
-               }                       
+               default:
+                       return WERR_UNKNOWN_LEVEL;
+               }
        }
-       
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
-       return result;  
+       return out.status;
 }
 
-/*********************************************************************************
- Win32 API - SetPrinter()
- ********************************************************************************/
-/** Set printer info 
- *
- * @param cli              Pointer to client state structure which is open
- *                         on the SPOOLSS pipe.
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param pol              Policy handle on printer to set info.
- * @param level            Information level to set.
- * @param ctr              Pointer to structure holding printer information.
- * @param command          Specifies the action performed.  See
- * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/prntspol_13ua.asp 
- * for details.
- *
- */
-
-WERROR cli_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                             POLICY_HND *pol, uint32 level, 
-                             PRINTER_INFO_CTR *ctr, uint32 command)
+/**********************************************************************
+**********************************************************************/
+
+WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                            POLICY_HND *handle, int level, uint32 *num_forms,
+                            FORM_1 **forms)
 {
        prs_struct qbuf, rbuf;
-       SPOOL_Q_SETPRINTER q;
-       SPOOL_R_SETPRINTER r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise input parameters */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+       SPOOL_Q_ENUMFORMS in;
+       SPOOL_R_ENUMFORMS out;
+       RPC_BUFFER buffer;
+       uint32 offered;
+
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
+
+       offered = 0;
+       if (!rpcbuf_init(&buffer, offered, mem_ctx))
+               return WERR_NOMEM;
+       make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
+
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMFORMS,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_enumforms,
+                   spoolss_io_r_enumforms, 
+                   WERR_GENERAL_FAILURE );
+
+       if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
+               offered = out.needed;
                
-       if (!make_spoolss_q_setprinter(mem_ctx, &q, pol, level, ctr, command))
-               goto done;
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_setprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_SETPRINTER, &qbuf, &rbuf))
-               goto done;
+               ZERO_STRUCT(in);
+               ZERO_STRUCT(out);
+
+               if (!rpcbuf_init(&buffer, offered, mem_ctx))
+                       return WERR_NOMEM;
+               make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
+
+               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMFORMS,
+                           in, out, 
+                           qbuf, rbuf,
+                           spoolss_io_q_enumforms,
+                           spoolss_io_r_enumforms, 
+                           WERR_GENERAL_FAILURE );
+       }
 
-       /* Unmarshall response */
+       if (!W_ERROR_IS_OK(out.status))
+               return out.status;
 
-       if (!spoolss_io_r_setprinter("", &r, &rbuf, 0))
-               goto done;
+       *num_forms = out.numofforms;
        
-       result = r.status;
-
-done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       if (!decode_forms_1(mem_ctx, out.buffer, *num_forms, forms)) {
+               return WERR_GENERAL_FAILURE;
+       }
 
-       return result;  
+       return out.status;
 }
 
-/*********************************************************************************
- Win32 API - GetPrinterDriver()
- ********************************************************************************/
-/** Get installed printer drivers for a given printer
- *
- * @param cli              Pointer to client state structure which is open
- * on the SPOOLSS pipe.
- *
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param offered          Buffer size offered in the request.
- * @param needed           Number of bytes needed to complete the request.
- *                         may be NULL.
- *
- * @param pol              Pointer to an open policy handle for the printer
- *                         opened with cli_spoolss_open_printer_ex().
- * @param level            Requested information level.
- * @param env              The print environment or archictecture.  This is
- *                         "Windows NT x86" for NT4.
- * @param ctr              Returned printer driver information.
- */
-
-WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, 
-                                   TALLOC_CTX *mem_ctx, 
-                                   uint32 offered, uint32 *needed,
-                                   POLICY_HND *pol, uint32 level, 
-                                   char *env, PRINTER_DRIVER_CTR *ctr)
+/**********************************************************************
+**********************************************************************/
+
+WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                           POLICY_HND *hnd, uint32 level, uint32 firstjob, 
+                           uint32 num_jobs, uint32 *returned, JOB_INFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
-       SPOOL_Q_GETPRINTERDRIVER2 q;
-        SPOOL_R_GETPRINTERDRIVER2 r;
-       NEW_BUFFER buffer;
-       WERROR result = W_ERROR(ERRgeneral);
-       fstring server;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
+       SPOOL_Q_ENUMJOBS in;
+       SPOOL_R_ENUMJOBS out;
+       RPC_BUFFER buffer;
+       uint32 offered;
+
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
+
+       offered = 0;
+       if (!rpcbuf_init(&buffer, offered, mem_ctx))
+               return WERR_NOMEM;
+       make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
+               &buffer, offered );
+
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMJOBS,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_enumjobs,
+                   spoolss_io_r_enumjobs, 
+                   WERR_GENERAL_FAILURE );
+
+       if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
+               offered = out.needed;
+               
+               ZERO_STRUCT(in);
+               ZERO_STRUCT(out);
+
+               if (!rpcbuf_init(&buffer, offered, mem_ctx))
+                       return WERR_NOMEM;
+               make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
+                       &buffer, offered );
+
+               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMJOBS,
+                           in, out, 
+                           qbuf, rbuf,
+                           spoolss_io_q_enumjobs,
+                           spoolss_io_r_enumjobs, 
+                           WERR_GENERAL_FAILURE );
+       }
 
-       fstrcpy (server, cli->desthost);
-       strupper (server);
+       if (!W_ERROR_IS_OK(out.status))
+               return out.status;
+               
+       switch(level) {
+       case 1:
+               if (!decode_jobs_1(mem_ctx, out.buffer, out.returned, &ctr->job.job_info_1)) {
+                       return WERR_GENERAL_FAILURE;
+               }
+               break;
+       case 2:
+               if (!decode_jobs_2(mem_ctx, out.buffer, out.returned, &ctr->job.job_info_2)) {
+                       return WERR_GENERAL_FAILURE;
+               }
+               break;
+       default:
+               DEBUG(3, ("unsupported info level %d", level));
+               return WERR_UNKNOWN_LEVEL;
+       }
+       
+       *returned = out.returned;
 
-       /* Initialise input parameters */
+       return out.status;
+}
 
-       init_buffer(&buffer, offered, mem_ctx);
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       make_spoolss_q_getprinterdriver2(&q, pol, env, level, 2, 2,
-                                        &buffer, offered);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_getprinterdriver2 ("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVER2, &qbuf, &rbuf)) 
-               goto done;
-
-       /* Unmarshall response */
-
-       if (spoolss_io_r_getprinterdriver2 ("", &r, &rbuf, 0)) {
-               if (needed)
-                       *needed = r.needed;
-       }
-
-       result = r.status;
-
-       /* Return output parameters */
-
-       if (!W_ERROR_IS_OK(result))
-               goto done;
-
-       if (!ctr)
-               goto done;
-
-       switch (level) {
-       case 1:
-               decode_printer_driver_1(mem_ctx, r.buffer, 1, &ctr->info1);
-               break;
-       case 2:
-               decode_printer_driver_2(mem_ctx, r.buffer, 1, &ctr->info2);
-               break;
-       case 3:
-               decode_printer_driver_3(mem_ctx, r.buffer, 1, &ctr->info3);
-               break;
-       default:
-               DEBUG(10, ("cli_spoolss_getprinterdriver: unknown info level %d", level));
-               return WERR_UNKNOWN_LEVEL;
-       }
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-               
-       return result;  
-}
-
-/*********************************************************************************
- Win32 API - EnumPrinterDrivers()
- ********************************************************************************/
-/**********************************************************************
- * Get installed printer drivers for a given printer
- */
-WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, 
-                                      TALLOC_CTX *mem_ctx,
-                                      uint32 offered, uint32 *needed,
-                                      uint32 level, char *env,
-                                      uint32 *num_drivers,
-                                      PRINTER_DRIVER_CTR *ctr)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_ENUMPRINTERDRIVERS q;
-        SPOOL_R_ENUMPRINTERDRIVERS r;
-       NEW_BUFFER buffer;
-       WERROR result = W_ERROR(ERRgeneral);
-       fstring server;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-        slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-        strupper (server);
-
-       /* Initialise input parameters */
-
-       init_buffer(&buffer, offered, mem_ctx);
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Write the request */
-
-       make_spoolss_q_enumprinterdrivers(&q, server, env, level, &buffer, 
-                                         offered);
-       
-       /* Marshall data and send request */
-       
-       if (!spoolss_io_q_enumprinterdrivers ("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req (cli, SPOOLSS_ENUMPRINTERDRIVERS, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_enumprinterdrivers ("", &r, &rbuf, 0))
-               goto done;
-
-       if (needed)
-               *needed = r.needed;
-
-       if (num_drivers)
-               *num_drivers = r.returned;
-
-       result = r.status;
-
-       /* Return output parameters */
-
-       if (W_ERROR_IS_OK(result) && (r.returned != 0)) {
-               *num_drivers = r.returned;
-
-               switch (level) {
-               case 1:
-                       decode_printer_driver_1(mem_ctx, r.buffer, r.returned, &ctr->info1);
-                       break;
-               case 2:
-                       decode_printer_driver_2(mem_ctx, r.buffer, r.returned, &ctr->info2);
-                       break;
-               case 3:
-                       decode_printer_driver_3(mem_ctx, r.buffer, r.returned, &ctr->info3);
-                       break;
-               default:
-                       DEBUG(10, ("cli_spoolss_enumprinterdrivers: unknown info level %d\n",
-                                  level));
-                       return WERR_UNKNOWN_LEVEL;
-               }
-       }
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-               
-       return result;
-}
-
-
-/*********************************************************************************
- Win32 API - GetPrinterDriverDirectory()
- ********************************************************************************/
-/**********************************************************************
- * Get installed printer drivers for a given printer
- */
-WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, 
-                                       TALLOC_CTX *mem_ctx,
-                                       uint32 offered, uint32 *needed,
-                                       uint32 level, char *env,
-                                       DRIVER_DIRECTORY_CTR *ctr)
-{
-       prs_struct                      qbuf, rbuf;
-       SPOOL_Q_GETPRINTERDRIVERDIR     q;
-        SPOOL_R_GETPRINTERDRIVERDIR    r;
-       NEW_BUFFER                      buffer;
-       WERROR result = W_ERROR(ERRgeneral);
-       fstring                         server;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-        slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-        strupper (server);
-
-       /* Initialise input parameters */
-
-       init_buffer(&buffer, offered, mem_ctx);
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Write the request */
-
-       make_spoolss_q_getprinterdriverdir(&q, server, env, level, &buffer, 
-                                          offered);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_getprinterdriverdir ("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVERDIRECTORY,
-                              &qbuf, &rbuf)) 
-               goto done;
-
-       /* Unmarshall response */
-
-       if (spoolss_io_r_getprinterdriverdir ("", &r, &rbuf, 0)) {
-               if (needed)
-                       *needed = r.needed;
-       }
-               
-       /* Return output parameters */
-
-       result = r.status;
-
-       if (W_ERROR_IS_OK(result)) {
-               switch (level) {
-               case 1:
-                       decode_printerdriverdir_1(mem_ctx, r.buffer, 1, 
-                                                 &ctr->info1);
-                       break;
-               }                       
-       }
-               
-       done:
-               prs_mem_free(&qbuf);
-               prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/*********************************************************************************
- Win32 API - AddPrinterDriver()
- ********************************************************************************/
-/**********************************************************************
- * Install a printer driver
- */
-WERROR cli_spoolss_addprinterdriver (struct cli_state *cli, 
-                                    TALLOC_CTX *mem_ctx, uint32 level,
-                                    PRINTER_DRIVER_CTR *ctr)
-{
-       prs_struct                      qbuf, rbuf;
-       SPOOL_Q_ADDPRINTERDRIVER        q;
-        SPOOL_R_ADDPRINTERDRIVER       r;
-       WERROR result = W_ERROR(ERRgeneral);
-       fstring                         server;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-       
-        slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-        strupper (server);
-
-       /* Initialise input parameters */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Write the request */
-
-       make_spoolss_q_addprinterdriver (mem_ctx, &q, server, level, ctr);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_addprinterdriver ("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req (cli, SPOOLSS_ADDPRINTERDRIVER, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_addprinterdriver ("", &r, &rbuf, 0))
-               goto done;
-               
-       /* Return output parameters */
-
-       result = r.status;
-
-done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-       
-       return result;  
-}
-
-/*********************************************************************************
- Win32 API - AddPrinter()
- ********************************************************************************/
-/**********************************************************************
- * Install a printer
- */
-WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                uint32 level, PRINTER_INFO_CTR*ctr)
-{
-       prs_struct                      qbuf, rbuf;
-       SPOOL_Q_ADDPRINTEREX            q;
-        SPOOL_R_ADDPRINTEREX           r;
-       WERROR result = W_ERROR(ERRgeneral);
-       fstring                         server,
-                                       client,
-                                       user;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-        slprintf (client, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-        strupper (client);
-        slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-        strupper (server);
-       fstrcpy  (user, cli->user_name);
-
-       /* Initialise input parameters */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Write the request */
-
-       make_spoolss_q_addprinterex (mem_ctx, &q, server, client, user,
-                                    level, ctr);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_addprinterex ("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req (cli, SPOOLSS_ADDPRINTEREX, &qbuf, &rbuf)) 
-               goto done;
-               
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_addprinterex ("", &r, &rbuf, 0))
-               goto done;
-               
-       /* Return output parameters */
-
-       result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;  
-}
-
-/*********************************************************************************
- Win32 API - DeltePrinterDriver()
- ********************************************************************************/
-/**********************************************************************
- * Delete a Printer Driver from the server (does not remove 
- * the driver files
- */
-WERROR cli_spoolss_deleteprinterdriver (struct cli_state *cli, 
-                                       TALLOC_CTX *mem_ctx, char *arch,
-                                       char *driver)
-{
-       prs_struct                      qbuf, rbuf;
-       SPOOL_Q_DELETEPRINTERDRIVER     q;
-        SPOOL_R_DELETEPRINTERDRIVER    r;
-       WERROR result = W_ERROR(ERRgeneral);
-       fstring                         server;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-
-       /* Initialise input parameters */
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-        slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-        strupper (server);
-
-       /* Write the request */
-
-       make_spoolss_q_deleteprinterdriver(mem_ctx, &q, server, arch, driver);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_deleteprinterdriver ("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req (cli,SPOOLSS_DELETEPRINTERDRIVER , &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_deleteprinterdriver ("", &r, &rbuf, 0))
-               goto done;
-               
-       /* Return output parameters */
-
-       result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;  
-}
-
-/*********************************************************************************
- Win32 API - GetPrinterProcessorDirectory()
- ********************************************************************************/
-
-WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli,
-                                             TALLOC_CTX *mem_ctx,
-                                             uint32 offered, uint32 *needed,
-                                             char *name, char *environment,
-                                             fstring procdir)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_GETPRINTPROCESSORDIRECTORY q;
-       SPOOL_R_GETPRINTPROCESSORDIRECTORY r;
-       int level = 1;
-       WERROR result = W_ERROR(ERRgeneral);
-       NEW_BUFFER buffer;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-       init_buffer(&buffer, offered, mem_ctx);
-
-       make_spoolss_q_getprintprocessordirectory(
-               &q, name, environment, level, &buffer, offered);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_getprintprocessordirectory("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTPROCESSORDIRECTORY,
-                             &qbuf, &rbuf))
-               goto done;
-               
-       /* Unmarshall response */
-               
-       if (!spoolss_io_r_getprintprocessordirectory("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-               
-       result = r.status;
-
-       if (needed)
-               *needed = r.needed;
-
-       if (W_ERROR_IS_OK(result))
-               fstrcpy(procdir, "Not implemented!");
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/** Add a form to a printer.
- *
- * @param cli              Pointer to client state structure which is open
- *                         on the SPOOLSS pipe.
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param handle           Policy handle opened with cli_spoolss_open_printer_ex
- *                         or cli_spoolss_addprinterex.
- * @param level            Form info level to add - should always be 1.
- * @param form             A pointer to the form to be added.
- *
- */
-
-WERROR cli_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                          POLICY_HND *handle, uint32 level, FORM *form)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_ADDFORM q;
-       SPOOL_R_ADDFORM r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_addform(&q, handle, level, form);
-       
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_addform("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_ADDFORM, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_addform("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/** Set a form on a printer.
- *
- * @param cli              Pointer to client state structure which is open
- *                         on the SPOOLSS pipe.
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param handle           Policy handle opened with cli_spoolss_open_printer_ex 
- *                         or cli_spoolss_addprinterex.
- * @param level            Form info level to set - should always be 1.
- * @param form             A pointer to the form to be set.
- *
- */
-
-WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                          POLICY_HND *handle, uint32 level, char *form_name,
-                          FORM *form)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_SETFORM q;
-       SPOOL_R_SETFORM r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_setform(&q, handle, level, form_name, form);
-       
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_setform("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_SETFORM, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_setform("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-
-       if (!W_ERROR_IS_OK(result))
-               goto done;
-
-
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/** Get a form on a printer.
- *
- * @param cli              Pointer to client state structure which is open
- *                         on the SPOOLSS pipe.
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param handle           Policy handle opened with cli_spoolss_open_printer_ex 
- *                         or cli_spoolss_addprinterex.
- * @param formname         Name of the form to get
- * @param level            Form info level to get - should always be 1.
- *
- */
-
-WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                          uint32 offered, uint32 *needed,
-                          POLICY_HND *handle, char *formname, uint32 level, 
-                          FORM_1 *form)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_GETFORM q;
-       SPOOL_R_GETFORM r;
-       WERROR result = W_ERROR(ERRgeneral);
-       NEW_BUFFER buffer;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       init_buffer(&buffer, offered, mem_ctx);
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_getform(&q, handle, formname, level, &buffer, offered);
-       
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_getform("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_GETFORM, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_getform("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-
-       if (needed)
-               *needed = r.needed;
-
-       if (W_ERROR_IS_OK(result)) {
-               switch(level) {
-               case 1:
-                       smb_io_form_1("", r.buffer, form, 0);
-                       break;
-               default:
-                       DEBUG(10, ("cli_spoolss_getform: unknown info level %d", level));
-                       return WERR_UNKNOWN_LEVEL;
-               }
-       }
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/** Delete a form on a printer.
- *
- * @param cli              Pointer to client state structure which is open
- *                         on the SPOOLSS pipe.
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param handle           Policy handle opened with cli_spoolss_open_printer_ex 
- *                         or cli_spoolss_addprinterex.
- * @param form             The name of the form to delete.
- *
- */
-
-WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                             POLICY_HND *handle, char *form_name)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_DELETEFORM q;
-       SPOOL_R_DELETEFORM r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_deleteform(&q, handle, form_name);
-       
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_deleteform("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_DELETEFORM, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_deleteform("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-static void decode_forms_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, 
-                          uint32 num_forms, FORM_1 **forms)
-{
-       int i;
-
-       *forms = (FORM_1 *)talloc(mem_ctx, num_forms * sizeof(FORM_1));
-       buffer->prs.data_offset = 0;
-
-       for (i = 0; i < num_forms; i++)
-               smb_io_form_1("", buffer, &((*forms)[i]), 0);
-}
-
-/** Enumerate forms
- *
- * @param cli              Pointer to client state structure which is open
- *                         on the SPOOLSS pipe.
- * @param mem_ctx          Pointer to an initialised talloc context.
- *
- * @param offered          Buffer size offered in the request.
- * @param needed           Number of bytes needed to complete the request.
- *                         may be NULL.
- *                         or cli_spoolss_addprinterex.
- * @param level            Form info level to get - should always be 1.
- * @param handle           Open policy handle
- *
- */
-
-WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                            uint32 offered, uint32 *needed,
-                            POLICY_HND *handle, int level, uint32 *num_forms,
-                            FORM_1 **forms)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_ENUMFORMS q;
-       SPOOL_R_ENUMFORMS r;
-       WERROR result = W_ERROR(ERRgeneral);
-       NEW_BUFFER buffer;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       init_buffer(&buffer, offered, mem_ctx);
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_enumforms(&q, handle, level, &buffer, offered);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_enumforms("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_ENUMFORMS, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_enumforms("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-
-       if (needed)
-               *needed = r.needed;
-
-       if (num_forms)
-               *num_forms = r.numofforms;
-
-       decode_forms_1(mem_ctx, r.buffer, *num_forms, forms);
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-static void decode_jobs_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, 
-                         uint32 num_jobs, JOB_INFO_1 **jobs)
-{
-       uint32 i;
-
-       *jobs = (JOB_INFO_1 *)talloc(mem_ctx, num_jobs * sizeof(JOB_INFO_1));
-       buffer->prs.data_offset = 0;
-
-       for (i = 0; i < num_jobs; i++) 
-               smb_io_job_info_1("", buffer, &((*jobs)[i]), 0);
-}
-
-static void decode_jobs_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, 
-                         uint32 num_jobs, JOB_INFO_2 **jobs)
-{
-       uint32 i;
-
-       *jobs = (JOB_INFO_2 *)talloc(mem_ctx, num_jobs * sizeof(JOB_INFO_2));
-       buffer->prs.data_offset = 0;
-
-       for (i = 0; i < num_jobs; i++) 
-               smb_io_job_info_2("", buffer, &((*jobs)[i]), 0);
-}
-
-/* Enumerate jobs */
-
-WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                           uint32 offered, uint32 *needed,
-                           POLICY_HND *hnd, uint32 level, uint32 firstjob, 
-                           uint32 num_jobs, uint32 *returned, JOB_INFO_CTR *ctr)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_ENUMJOBS q;
-       SPOOL_R_ENUMJOBS r;
-       WERROR result = W_ERROR(ERRgeneral);
-       NEW_BUFFER buffer;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       init_buffer(&buffer, offered, mem_ctx);
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_enumjobs(&q, hnd, firstjob, num_jobs, level, &buffer, 
-                               offered);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_enumjobs("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_ENUMJOBS, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_enumjobs("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-
-       if (needed)
-               *needed = r.needed;
-
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;
-
-       *returned = r.returned;
-
-       switch(level) {
-       case 1:
-               decode_jobs_1(mem_ctx, r.buffer, r.returned,
-                             &ctr->job.job_info_1);
-               break;
-       case 2:
-               decode_jobs_2(mem_ctx, r.buffer, r.returned,
-                             &ctr->job.job_info_2);
-               break;
-       default:
-               DEBUG(3, ("unsupported info level %d", level));
-               break;
-       }
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/* Set job */
-
-WERROR cli_spoolss_setjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                         POLICY_HND *hnd, uint32 jobid, uint32 level, 
-                         uint32 command)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_SETJOB q;
-       SPOOL_R_SETJOB r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_setjob(&q, hnd, jobid, level, command);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_setjob("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_SETJOB, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_setjob("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/* Get job */
-
-WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                         uint32 offered, uint32 *needed,
-                         POLICY_HND *hnd, uint32 jobid, uint32 level,
-                         JOB_INFO_CTR *ctr)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_GETJOB q;
-       SPOOL_R_GETJOB r;
-       WERROR result = W_ERROR(ERRgeneral);
-       NEW_BUFFER buffer;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       init_buffer(&buffer, offered, mem_ctx);
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_getjob(&q, hnd, jobid, level, &buffer, offered);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_getjob("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_GETJOB, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_getjob("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
+/**********************************************************************
+**********************************************************************/
 
-       if (needed)
-               *needed = r.needed;
+WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                         POLICY_HND *hnd, uint32 jobid, uint32 level,
+                         JOB_INFO_CTR *ctr)
+{
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_GETJOB in;
+       SPOOL_R_GETJOB out;
+       RPC_BUFFER buffer;
+       uint32 offered;
+
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
+
+       offered = 0;
+       if (!rpcbuf_init(&buffer, offered, mem_ctx))
+               return WERR_NOMEM;
+       make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
+
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETJOB,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_getjob,
+                   spoolss_io_r_getjob, 
+                   WERR_GENERAL_FAILURE );
+
+       if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
+               offered = out.needed;
+               
+               ZERO_STRUCT(in);
+               ZERO_STRUCT(out);
+               
+               if (!rpcbuf_init(&buffer, offered, mem_ctx))
+                       return WERR_NOMEM;
+               make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
+
+               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETJOB,
+                           in, out, 
+                           qbuf, rbuf,
+                           spoolss_io_q_getjob,
+                           spoolss_io_r_getjob, 
+                           WERR_GENERAL_FAILURE );
+       }
 
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;
+       if (!W_ERROR_IS_OK(out.status))
+               return out.status;
 
        switch(level) {
        case 1:
-               decode_jobs_1(mem_ctx, r.buffer, 1, &ctr->job.job_info_1);
+               if (!decode_jobs_1(mem_ctx, out.buffer, 1, &ctr->job.job_info_1)) {
+                       return WERR_GENERAL_FAILURE;
+               }
                break;
        case 2:
-               decode_jobs_2(mem_ctx, r.buffer, 1, &ctr->job.job_info_2);
+               if (!decode_jobs_2(mem_ctx, out.buffer, 1, &ctr->job.job_info_2)) {
+                       return WERR_GENERAL_FAILURE;
+               }
                break;
        default:
-               DEBUG(3, ("unsupported info level %d", level));
-               break;
+               return WERR_UNKNOWN_LEVEL;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/* Startpageprinter.  Sent to notify the spooler when a page is about to be
-   sent to a printer. */ 
-
-WERROR cli_spoolss_startpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                   POLICY_HND *hnd)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_STARTPAGEPRINTER q;
-       SPOOL_R_STARTPAGEPRINTER r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_startpageprinter(&q, hnd);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_startpageprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_STARTPAGEPRINTER, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_startpageprinter("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/* Endpageprinter.  Sent to notify the spooler when a page has finished
-   being sent to a printer. */
-
-WERROR cli_spoolss_endpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                 POLICY_HND *hnd)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_ENDPAGEPRINTER q;
-       SPOOL_R_ENDPAGEPRINTER r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_endpageprinter(&q, hnd);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_endpageprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_ENDPAGEPRINTER, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_endpageprinter("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/* Startdocprinter.  Sent to notify the spooler that a document is about
-   to be spooled for printing. */
-
-WERROR cli_spoolss_startdocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                  POLICY_HND *hnd, char *docname, 
-                                  char *outputfile, char *datatype, 
-                                  uint32 *jobid)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_STARTDOCPRINTER q;
-       SPOOL_R_STARTDOCPRINTER r;
-       WERROR result = W_ERROR(ERRgeneral);
-       uint32 level = 1;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_startdocprinter(&q, hnd, level, docname, outputfile, 
-                                      datatype);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_startdocprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_STARTDOCPRINTER, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_startdocprinter("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-       
-       if (W_ERROR_IS_OK(result))
-               *jobid = r.jobid;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/* Enddocprinter.  Sent to notify the spooler that a document has finished
-   being spooled. */
-
-WERROR cli_spoolss_enddocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                 POLICY_HND *hnd)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_ENDDOCPRINTER q;
-       SPOOL_R_ENDDOCPRINTER r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_enddocprinter(&q, hnd);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_enddocprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_ENDDOCPRINTER, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_enddocprinter("", &r, &rbuf, 0))
-               goto done;
-
-       /* Return output parameters */
-
-       result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
+       return out.status;
 }
 
-/* Get printer data */
+/**********************************************************************
+**********************************************************************/
 
-WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                 uint32 offered, uint32 *needed,
-                                 POLICY_HND *hnd, char *valuename, 
+WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                                 POLICY_HND *hnd, const char *valuename, 
                                  REGISTRY_VALUE *value)
 {
        prs_struct qbuf, rbuf;
-       SPOOL_Q_GETPRINTERDATA q;
-       SPOOL_R_GETPRINTERDATA r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_getprinterdata(&q, hnd, valuename, offered);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_getprinterdata("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTERDATA, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_getprinterdata("", &r, &rbuf, 0))
-               goto done;
-       
-       result = r.status;
-
-       if (needed)
-               *needed = r.needed;
-
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;      
-
-       /* Return output parameters */
-
-       value->data_p = talloc_memdup(mem_ctx, r.data, r.needed);
-       value->type = r.type;
-       value->size = r.size;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-WERROR cli_spoolss_getprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                   uint32 offered, uint32 *needed,
-                                   POLICY_HND *hnd, char *keyname, 
-                                   char *valuename, REGISTRY_VALUE *value)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_GETPRINTERDATAEX q;
-       SPOOL_R_GETPRINTERDATAEX r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+       SPOOL_Q_GETPRINTERDATA in;
+       SPOOL_R_GETPRINTERDATA out;
+       uint32 offered;
 
-       /* Initialise input parameters */
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
 
-        make_spoolss_q_getprinterdataex(&q, hnd, keyname, valuename, offered);
+       offered = 0;
+       make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
 
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_getprinterdataex("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTERDATAEX, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_getprinterdataex("", &r, &rbuf, 0))
-               goto done;
-       
-       result = r.status;
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDATA,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_getprinterdata,
+                   spoolss_io_r_getprinterdata, 
+                   WERR_GENERAL_FAILURE );
 
-       if (needed)
-               *needed = r.needed;
+       if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
+               offered = out.needed;
+               
+               ZERO_STRUCT(in);
+               ZERO_STRUCT(out);
+               
+               make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
+
+               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDATA,
+                           in, out, 
+                           qbuf, rbuf,
+                           spoolss_io_q_getprinterdata,
+                           spoolss_io_r_getprinterdata, 
+                           WERR_GENERAL_FAILURE );
+       }
 
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;      
+       if (!W_ERROR_IS_OK(out.status))
+               return out.status;      
 
        /* Return output parameters */
 
-       value->data_p = talloc_memdup(mem_ctx, r.data, r.needed);
-       value->type = r.type;
-       value->size = r.needed;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       if (out.needed) {
+               value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data, out.needed);
+       } else {
+               value->data_p = NULL;
+       }
+       value->type = out.type;
+       value->size = out.size;
 
-       return result;
+       return out.status;
 }
 
-/* Set printer data */
+/**********************************************************************
+**********************************************************************/
 
-WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_setprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *hnd, REGISTRY_VALUE *value)
 {
        prs_struct qbuf, rbuf;
-       SPOOL_Q_SETPRINTERDATA q;
-       SPOOL_R_SETPRINTERDATA r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_setprinterdata(
-               &q, hnd, value->valuename, value->type, value->data_p, value->size);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_setprinterdata("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_SETPRINTERDATA, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_setprinterdata("", &r, &rbuf, 0))
-               goto done;
-       
-       result = r.status;
-
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;      
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-WERROR cli_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                   POLICY_HND *hnd, char *keyname, 
-                                   REGISTRY_VALUE *value)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_SETPRINTERDATAEX q;
-       SPOOL_R_SETPRINTERDATAEX r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_setprinterdataex(
-               &q, hnd, keyname, value->valuename, value->type, value->data_p, 
-               value->size);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_setprinterdataex("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_SETPRINTERDATAEX, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_setprinterdataex("", &r, &rbuf, 0))
-               goto done;
-       
-       result = r.status;
-
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;      
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
+       SPOOL_Q_SETPRINTERDATA in;
+       SPOOL_R_SETPRINTERDATA out;
+
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
+
+        make_spoolss_q_setprinterdata( &in, hnd, value->valuename, 
+               value->type, (char *)value->data_p, value->size);
+
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_SETPRINTERDATA,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_setprinterdata,
+                   spoolss_io_r_setprinterdata, 
+                   WERR_GENERAL_FAILURE );
+                   
+       return out.status;
 }
 
-/* Enum printer data */
+/**********************************************************************
+**********************************************************************/
 
-WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_enumprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                   POLICY_HND *hnd, uint32 ndx,
                                   uint32 value_offered, uint32 data_offered,
                                   uint32 *value_needed, uint32 *data_needed,
                                   REGISTRY_VALUE *value)
 {
        prs_struct qbuf, rbuf;
-       SPOOL_Q_ENUMPRINTERDATA q;
-       SPOOL_R_ENUMPRINTERDATA r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_enumprinterdata(&q, hnd, ndx, value_offered, data_offered);
-
-       /* Marshall data and send request */
+       SPOOL_Q_ENUMPRINTERDATA in;
+       SPOOL_R_ENUMPRINTERDATA out;
 
-       if (!spoolss_io_q_enumprinterdata("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_ENUMPRINTERDATA, &qbuf, &rbuf))
-               goto done;
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
 
-       /* Unmarshall response */
+        make_spoolss_q_enumprinterdata( &in, hnd, ndx, value_offered, data_offered );
 
-       if (!spoolss_io_r_enumprinterdata("", &r, &rbuf, 0))
-               goto done;
-       
-       result = r.status;
-
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;
-
-       /* Return data */
-       
-       if (value_needed)
-               *value_needed = r.realvaluesize;
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATA,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_enumprinterdata,
+                   spoolss_io_r_enumprinterdata, 
+                   WERR_GENERAL_FAILURE );
 
-       if (data_needed)
-               *data_needed = r.realdatasize;
+       if ( value_needed )
+               *value_needed = out.realvaluesize;
+       if ( data_needed )
+               *data_needed = out.realdatasize;
+               
+       if (!W_ERROR_IS_OK(out.status))
+               return out.status;
 
        if (value) {
-               rpcstr_pull(value->valuename, r.value, sizeof(value->valuename), -1,
+               rpcstr_pull(value->valuename, out.value, sizeof(value->valuename), -1,
                            STR_TERMINATE);
-               value->data_p = talloc_memdup(mem_ctx, r.data, r.realdatasize);
-               value->type = r.type;
-               value->size = r.realdatasize;
+               if (out.realdatasize) {
+                       value->data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, out.data,
+                                                      out.realdatasize);
+               } else {
+                       value->data_p = NULL;
+               }
+               value->type = out.type;
+               value->size = out.realdatasize;
        }
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
+       
+       return out.status;
 }
 
-WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                    uint32 offered, uint32 *needed,
-                                    POLICY_HND *hnd, char *keyname, 
+/**********************************************************************
+**********************************************************************/
+
+WERROR rpccli_spoolss_enumprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                                    POLICY_HND *hnd, const char *keyname, 
                                     REGVAL_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
-       SPOOL_Q_ENUMPRINTERDATAEX q;
-       SPOOL_R_ENUMPRINTERDATAEX r;
-       WERROR result = W_ERROR(ERRgeneral);
+       SPOOL_Q_ENUMPRINTERDATAEX in;
+       SPOOL_R_ENUMPRINTERDATAEX out;
        int i;
+       uint32 offered;
 
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
 
-        make_spoolss_q_enumprinterdataex(&q, hnd, keyname, offered);
+       offered = 0;
+       make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
 
-       /* Marshall data and send request */
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATAEX,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_enumprinterdataex,
+                   spoolss_io_r_enumprinterdataex, 
+                   WERR_GENERAL_FAILURE );
 
-       if (!spoolss_io_q_enumprinterdataex("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_ENUMPRINTERDATAEX, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_enumprinterdataex("", &r, &rbuf, 0))
-               goto done;
-       
-       result = r.status;
-       
-       if (needed)
-               *needed = r.needed;
+       if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
+               offered = out.needed;
+               
+               ZERO_STRUCT(in);
+               ZERO_STRUCT(out);
+               
+               make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
+
+               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERDATAEX,
+                           in, out, 
+                           qbuf, rbuf,
+                           spoolss_io_q_enumprinterdataex,
+                           spoolss_io_r_enumprinterdataex, 
+                           WERR_GENERAL_FAILURE );
+       }
        
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;
-
-       /* Return data */
+       if (!W_ERROR_IS_OK(out.status))
+               return out.status;
 
-       ZERO_STRUCTP(ctr);
-       regval_ctr_init(ctr);
-
-       for (i = 0; i < r.returned; i++) {
-               PRINTER_ENUM_VALUES *v = &r.ctr.values[i];
+       for (i = 0; i < out.returned; i++) {
+               PRINTER_ENUM_VALUES *v = &out.ctr.values[i];
                fstring name;
 
                rpcstr_pull(name, v->valuename.buffer, sizeof(name), -1, 
                            STR_TERMINATE);
-               regval_ctr_addvalue(ctr, name, v->type, v->data, v->data_len);
+               regval_ctr_addvalue(ctr, name, v->type, (const char *)v->data, v->data_len);
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
-
-/* Write data to printer */
-
-WERROR cli_spoolss_writeprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                               POLICY_HND *hnd, uint32 data_size, char *data,
-                               uint32 *num_written)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_WRITEPRINTER q;
-       SPOOL_R_WRITEPRINTER r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_writeprinter(&q, hnd, data_size, data);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_writeprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_WRITEPRINTER, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_writeprinter("", &r, &rbuf, 0))
-               goto done;
-       
-       result = r.status;
-
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;      
-
-       if (num_written)
-               *num_written = r.buffer_written;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
+       return out.status;
 }
 
-/* Delete printer data */
-
-WERROR cli_spoolss_deleteprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                    POLICY_HND *hnd, char *valuename)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_DELETEPRINTERDATA q;
-       SPOOL_R_DELETEPRINTERDATA r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
-        make_spoolss_q_deleteprinterdata(&q, hnd, valuename);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_deleteprinterdata("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_DELETEPRINTERDATA, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!spoolss_io_r_deleteprinterdata("", &r, &rbuf, 0))
-               goto done;
-       
-       result = r.status;
-
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;      
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
-       return result;
-}
+/**********************************************************************
+**********************************************************************/
 
-WERROR cli_spoolss_deleteprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                      POLICY_HND *hnd, char *keyname, 
-                                      char *valuename)
+WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                                 POLICY_HND *hnd, const char *keyname,
+                                 uint16 **keylist, uint32 *len)
 {
        prs_struct qbuf, rbuf;
-       SPOOL_Q_DELETEPRINTERDATAEX q;
-       SPOOL_R_DELETEPRINTERDATAEX r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
+       SPOOL_Q_ENUMPRINTERKEY in;
+       SPOOL_R_ENUMPRINTERKEY out;
+       uint32 offered = 0;
 
-       /* Initialise parse structures */
+       ZERO_STRUCT(in);
+       ZERO_STRUCT(out);
 
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+       make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
 
-       /* Initialise input parameters */
+       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERKEY,
+                   in, out, 
+                   qbuf, rbuf,
+                   spoolss_io_q_enumprinterkey,
+                   spoolss_io_r_enumprinterkey, 
+                   WERR_GENERAL_FAILURE );
 
-        make_spoolss_q_deleteprinterdataex(&q, hnd, keyname, valuename);
-
-       /* Marshall data and send request */
-
-       if (!spoolss_io_q_deleteprinterdataex("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, SPOOLSS_DELETEPRINTERDATAEX, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
+       if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
+               offered = out.needed;
+               
+               ZERO_STRUCT(in);
+               ZERO_STRUCT(out);
+               
+               make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
+
+               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ENUMPRINTERKEY,
+                           in, out, 
+                           qbuf, rbuf,
+                           spoolss_io_q_enumprinterkey,
+                           spoolss_io_r_enumprinterkey, 
+                           WERR_GENERAL_FAILURE );
+       }
 
-       if (!spoolss_io_r_deleteprinterdataex("", &r, &rbuf, 0))
-               goto done;
+       if ( !W_ERROR_IS_OK(out.status) )
+               return out.status;      
        
-       result = r.status;
-
-       if (!W_ERROR_IS_OK(r.status))
-               goto done;      
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       if (keylist) {
+               *keylist = SMB_MALLOC_ARRAY(uint16, out.keys.buf_len);
+               if (!*keylist) {
+                       return WERR_NOMEM;
+               }
+               memcpy(*keylist, out.keys.buffer, out.keys.buf_len * 2);
+               if (len)
+                       *len = out.keys.buf_len * 2;
+       }
 
-       return result;
+       return out.status;
 }
-
 /** @} **/