r10656: BIG merge from trunk. Features not copied over
[ira/wip.git] / source3 / rpc_client / cli_spoolss_notify.c
index 320708736ed2803cb9355df9599e31c09ecffef7..f8098943dbf58b223fa13e7e70beebce2381dde6 100644 (file)
-/*
- *  Unix SMB/CIFS implementation.
- *  RPC Pipe client / server routines
- *  Copyright (C) Andrew Tridgell              1992-2000,
- *  Copyright (C) Jean Francois Micouleau      1998-2000,
- *
- *  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
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+/* 
+   Unix SMB/CIFS implementation.
+   RPC pipe client
+
+   Copyright (C) Gerald Carter                2001-2002,
+   Copyright (C) Tim Potter                   2000-2002,
+   Copyright (C) Andrew Tridgell              1994-2000,
+   Copyright (C) Jean-Francois Micouleau      1999-2000.
+   Copyright (C) Jeremy Allison                    2005.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
 
 #include "includes.h"
-#if 0
-#include "rpc_parse.h"
-#include "nterr.h"
-#endif
-extern pstring global_myname;
-
-struct msg_info_table {
-       uint32 msg;
-       uint32 field;
-       char*  name;
-       void (*construct_fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
-               print_queue_struct *queue,
-               NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
-};
-
-struct msg_info_table msg_table[] = {
-{ PRINTER_MESSAGE_DRIVER,      PRINTER_NOTIFY_DRIVER_NAME,    "PRINTER_MESSAGE_DRIVER",      spoolss_notify_driver_name  },
-{ PRINTER_MESSAGE_ATTRIBUTES,  PRINTER_NOTIFY_ATTRIBUTES,     "PRINTER_MESSAGE_ATTRIBUTES",  spoolss_notify_attributes   },
-{ PRINTER_MESSAGE_COMMENT,     PRINTER_NOTIFY_COMMENT,        "PRINTER_MESSAGE_COMMENT",     spoolss_notify_comment      },
-{ PRINTER_MESSAGE_LOCATION,    PRINTER_NOTIFY_LOCATION,       "PRINTER_MESSAGE_LOCATION",    spoolss_notify_location     },
-{ PRINTER_MESSAGE_PRINTERNAME, PRINTER_NOTIFY_PRINTER_NAME,   "PRINTER_MESSAGE_PRINTERNAME", spoolss_notify_printer_name },
-{ PRINTER_MESSAGE_SHARENAME,   PRINTER_NOTIFY_SHARE_NAME,     "PRINTER_MESSAGE_SHARENAME",   spoolss_notify_share_name   },
-{ PRINTER_MESSAGE_PORT,        PRINTER_NOTIFY_PORT_NAME,      "PRINTER_MESSAGE_PORT",        spoolss_notify_port_name    },
-{ PRINTER_MESSAGE_CJOBS,       PRINTER_NOTIFY_CJOBS,          "PRINTER_MESSAGE_CJOBS",       spoolss_notify_cjobs        },
-{ PRINTER_MESSAGE_SEPFILE,     PRINTER_NOTIFY_SEPFILE,        "PRINTER_MESSAGE_SEPFILE",     spoolss_notify_sepfile      },
-{ PRINTER_MESSAGE_PARAMS,      PRINTER_NOTIFY_PARAMETERS,     "PRINTER_MESSAGE_PARAMETERS",  spoolss_notify_parameters   },
-{ PRINTER_MESSAGE_DATATYPE,    PRINTER_NOTIFY_DATATYPE,       "PRINTER_MESSAGE_DATATYPE",    spoolss_notify_datatype     },
-{ PRINTER_MESSAGE_NULL,        0x0,                           "",                            NULL                        },
-};
-
-/*********************************************************
- Disconnect from the client machine.
-**********************************************************/
-BOOL spoolss_disconnect_from_client( struct cli_state *cli)
-{
-       cli_nt_session_close(cli);
-       cli_ulogoff(cli);
-       cli_shutdown(cli);
-
-       return True;
-}
-
-
-/*********************************************************
- Connect to the client machine.
-**********************************************************/
-
-BOOL spoolss_connect_to_client( struct cli_state *cli, char *remote_machine)
-{
-       ZERO_STRUCTP(cli);
-       if(cli_initialise(cli) == NULL) {
-               DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
-               return False;
-       }
-
-       if(!resolve_name( remote_machine, &cli->dest_ip, 0x20)) {
-               DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
-               cli_shutdown(cli);
-       return False;
-       }
-
-       if (ismyip(cli->dest_ip)) {
-               DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
-               cli_shutdown(cli);
-               return False;
-       }
-
-       if (!cli_connect(cli, remote_machine, &cli->dest_ip)) {
-               DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
-               cli_shutdown(cli);
-               return False;
-       }
-  
-       if (!attempt_netbios_session_request(cli, global_myname, remote_machine, &cli->dest_ip)) {
-               DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n", 
-                       remote_machine));
-               return False;
-       }
-
-       cli->protocol = PROTOCOL_NT1;
-    
-       if (!cli_negprot(cli)) {
-               DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
-               cli_shutdown(cli);
-               return False;
-       }
-
-       if (cli->protocol != PROTOCOL_NT1) {
-               DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
-               cli_shutdown(cli);
-               return False;
-       }
-    
-       /*
-        * Do an anonymous session setup.
-        */
-    
-       if (!cli_session_setup(cli, "", "", 0, "", 0, "")) {
-               DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
-               cli_shutdown(cli);
-               return False;
-       }
-    
-       if (!(cli->sec_mode & 1)) {
-               DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
-               cli_shutdown(cli);
-               return False;
-       }
-    
-       if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
-               DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
-               cli_shutdown(cli);
-               return False;
-       }
-
-       /*
-        * Ok - we have an anonymous connection to the IPC$ share.
-        * Now start the NT Domain stuff :-).
-        */
-
-       if(cli_nt_session_open(cli, PIPE_SPOOLSS) == False) {
-               DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli)));
-               cli_nt_session_close(cli);
-               cli_ulogoff(cli);
-               cli_shutdown(cli);
-               return False;
-       } 
-
-       return True;
-}
 
 /*
  * SPOOLSS Client RPC's used by servers as the notification
- * back channel
+ * back channel.
  */
 
-/***************************************************************************
- do a reply open printer
-****************************************************************************/
+/* Send a ReplyOpenPrinter request.  This rpc is made by the printer
+   server to the printer client in response to a rffpcnex request.
+   The rrfpcnex request names a printer and a handle (the printerlocal
+   value) and this rpc establishes a back-channel over which printer
+   notifications are performed. */
 
-WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                               char *printer, uint32 localprinter, uint32 type, 
-                               POLICY_HND *handle)
+WERROR rpccli_spoolss_reply_open_printer(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
+                                     const char *printer, uint32 printerlocal, uint32 type, 
+                                     POLICY_HND *handle)
 {
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_REPLYOPENPRINTER q;
+       SPOOL_R_REPLYOPENPRINTER r;
        WERROR result = W_ERROR(ERRgeneral);
        
-       prs_struct rbuf;
-       prs_struct buf; 
+       /* Initialise input parameters */
 
-       SPOOL_Q_REPLYOPENPRINTER q_s;
-       SPOOL_R_REPLYOPENPRINTER r_s;
+       make_spoolss_q_replyopenprinter(&q, printer, printerlocal, type);
 
-       prs_init(&buf, 1024, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL );
+       /* Marshall data and send request */
 
-       /* create and send a MSRPC command with api SPOOLSS_REPLYOPENPRINTER */
-       
-       /* store the parameters */
-       make_spoolss_q_replyopenprinter(&q_s, printer, localprinter, type);
-
-       /* turn parameters into data stream */
-       if(!spoolss_io_q_replyopenprinter("", &q_s,  &buf, 0)) {
-               DEBUG(0,("cli_spoolss_reply_open_printer: Error : failed to marshall SPOOL_Q_REPLYOPENPRINTER struct.\n"));
-               goto done;
-       }
-
-       /* send the data on \PIPE\ */
-       if (!rpc_api_pipe_req(cli, SPOOLSS_REPLYOPENPRINTER, &buf, &rbuf)) 
-               goto done;
-
-       /* turn data stream into parameters*/
-       if(!spoolss_io_r_replyopenprinter("", &r_s, &rbuf, 0)) {
-               DEBUG(0,("cli_spoolss_reply_open_printer: Error : failed to unmarshall SPOOL_R_REPLYOPENPRINTER struct.\n"));
-               goto done;
-       }
-       
-       memcpy(handle, &r_s.handle, sizeof(r_s.handle));
-       result = r_s.status;
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_REPLYOPENPRINTER,
+               q, r,
+               qbuf, rbuf,
+               spoolss_io_q_replyopenprinter,
+               spoolss_io_r_replyopenprinter,
+               WERR_GENERAL_FAILURE );
+
+       /* Return result */
 
-done:
-       prs_mem_free(&buf);
-       prs_mem_free(&rbuf);
+       memcpy(handle, &r.handle, sizeof(r.handle));
+       result = r.status;
 
        return result;
 }
 
-/***************************************************************************
- do a reply open printer
-****************************************************************************/
+/* Close a back-channel notification connection */
 
-WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                       POLICY_HND *handle)
+WERROR rpccli_spoolss_reply_close_printer(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
+                                      POLICY_HND *handle)
 {
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_REPLYCLOSEPRINTER q;
+       SPOOL_R_REPLYCLOSEPRINTER r;
        WERROR result = W_ERROR(ERRgeneral);
-       prs_struct rbuf;
-       prs_struct buf; 
 
-       SPOOL_Q_REPLYCLOSEPRINTER q_s;
-       SPOOL_R_REPLYCLOSEPRINTER r_s;
+       /* Initialise input parameters */
+
+       make_spoolss_q_reply_closeprinter(&q, handle);
 
-       prs_init(&buf, 1024, cli->mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL );
+       /* Marshall data and send request */
 
-       /* create and send a MSRPC command with api  */
-       
-       /* store the parameters */
-       make_spoolss_q_reply_closeprinter(&q_s, handle);
-
-       /* turn parameters into data stream */
-       if(!spoolss_io_q_replycloseprinter("", &q_s,  &buf, 0)) {
-               DEBUG(0,("cli_spoolss_reply_close_printer: Error : failed to marshall SPOOL_Q_REPLY_CLOSEPRINTER struct.\n"));
-               goto done;
-       }
-
-       /* send the data on \PIPE\ */
-       if (!rpc_api_pipe_req(cli, SPOOLSS_REPLYCLOSEPRINTER, &buf, &rbuf))
-               goto done;
-
-       /* turn data stream into parameters*/
-       if(!spoolss_io_r_replycloseprinter("", &r_s, &rbuf, 0)) {
-               DEBUG(0,("cli_spoolss_reply_close_printer: Error : failed to marshall SPOOL_R_REPLY_CLOSEPRINTER struct.\n"));
-               goto done;
-       }
-       
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_REPLYCLOSEPRINTER,
+               q, r,
+               qbuf, rbuf,
+               spoolss_io_q_replycloseprinter,
+               spoolss_io_r_replycloseprinter,
+               WERR_GENERAL_FAILURE );
 
-       result = r_s.status;
-       
-done:
-               prs_mem_free(&buf);
-               prs_mem_free(&rbuf);
+       /* Return result */
 
+       result = r.status;
        return result;
 }
 
 /*********************************************************************
  This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change 
  notification event when the registration **did not** use 
@@ -262,186 +102,118 @@ done:
  Also see cli_spolss_reply_rrpcn()
  *********************************************************************/
  
-WERROR cli_spoolss_routerreplyprinter (struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                       POLICY_HND *pol, uint32 condition, uint32 changd_id)
+WERROR rpccli_spoolss_routerreplyprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                                     POLICY_HND *pol, uint32 condition, uint32 change_id)
 {
        prs_struct qbuf, rbuf;
        SPOOL_Q_ROUTERREPLYPRINTER q;
         SPOOL_R_ROUTERREPLYPRINTER 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);
-
-
-       /* write the request */
-       make_spoolss_q_routerreplyprinter(&q, pol, condition, changd_id);
+       make_spoolss_q_routerreplyprinter(&q, pol, condition, change_id);
 
        /* Marshall data and send request */
-       if (!spoolss_io_q_routerreplyprinter ("", &q, &qbuf, 0)) {
-               DEBUG(0,("cli_spoolss_routerreplyprinter: Unable to marshall SPOOL_Q_ROUTERREPLYPRINTER!\n"));
-               goto done;
-       }
-               
-               
-       if (!rpc_api_pipe_req (cli, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf)) 
-               goto done;
-
-       /* Unmarshall response */
-       if (!spoolss_io_r_routerreplyprinter ("", &r, &rbuf, 0)) {
-               DEBUG(0,("cli_spoolss_routerreplyprinter: Unable to unmarshall SPOOL_R_ROUTERREPLYPRINTER!\n"));
-               goto done;
-       }
+
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ROUTERREPLYPRINTER,
+               q, r,
+               qbuf, rbuf,
+               spoolss_io_q_routerreplyprinter,
+               spoolss_io_r_routerreplyprinter,
+               WERR_GENERAL_FAILURE );
 
        /* Return output parameters */
-       result = r.status;
-       
-done:
-       prs_mem_free(&qbuf);
-               prs_mem_free(&rbuf);
 
+       result = r.status;
        return result;  
 }
 
-
-/**********************************************************************************
- Build the SPOOL_NOTIFY_INFO_DATA entries based upon the flags which have been set
- *********************************************************************************/
-
-static int build_notify_data (TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer, uint32 flags, 
-                       SPOOL_NOTIFY_INFO_DATA **notify_data)
-{
-       SPOOL_NOTIFY_INFO_DATA *data;
-       uint32 idx = 0;
-       int i = 0;
-       
-       while ((msg_table[i].msg != PRINTER_MESSAGE_NULL) && flags)
-       {
-               if (flags & msg_table[i].msg) 
-               {
-                       DEBUG(10,("build_notify_data: %s set on [%s][%d]\n", msg_table[i].name,
-                               printer->info_2->printername, idx));
-                       if ((data=Realloc(*notify_data, (idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
-                               DEBUG(0,("build_notify_data: Realloc() failed with size [%d]!\n",
-                                       (idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA)));
-                               return -1;
-       }
-                       *notify_data = data;
-
-                       /* clear memory */
-                       memset(*notify_data+idx, 0x0, sizeof(SPOOL_NOTIFY_INFO_DATA));
-       
-                       /*
-                        * 'id' (last param here) is undefined when type == PRINTER_NOTIFY_TYPE
-                        * See PRINTER_NOTIFY_INFO_DATA entries in MSDN
-                        * --jerry
-                        */
-                       construct_info_data(*notify_data+idx, PRINTER_NOTIFY_TYPE, msg_table[i].field, 0x00);
-
-                       msg_table[i].construct_fn(-1, *notify_data+idx, NULL, printer, ctx);
-                       idx++;
-               }
-
-               i++;
-       }
-       
-       return idx;
-}
-
 /*********************************************************************
- This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change 
+ This SPOOLSS_REPLY_RRPCN function is used to send a change 
  notification event when the registration **did** use 
  SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor
  Also see cli_spoolss_routereplyprinter()
  *********************************************************************/
 
-WERROR cli_spoolss_reply_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                       POLICY_HND *handle, PRINTER_MESSAGE_INFO *info,
-                                       NT_PRINTER_INFO_LEVEL *printer)
+WERROR rpccli_spoolss_rrpcn(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
+                        POLICY_HND *pol, uint32 notify_data_len,
+                        SPOOL_NOTIFY_INFO_DATA *notify_data,
+                        uint32 change_low, uint32 change_high)
 {
-       prs_struct rbuf;
-       prs_struct buf; 
-
-       SPOOL_NOTIFY_INFO       notify_info;
-       SPOOL_NOTIFY_INFO_DATA  *notify_data = NULL;
-       uint32                  data_len;
-
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_REPLY_RRPCN q;
+       SPOOL_R_REPLY_RRPCN r;
        WERROR result = W_ERROR(ERRgeneral);
+       SPOOL_NOTIFY_INFO       notify_info;
 
-       SPOOL_Q_REPLY_RRPCN q_s;
-       SPOOL_R_REPLY_RRPCN r_s;
-
-       if (!info) {
-               DEBUG(5,("cli_spoolss_reply_rrpcn: NULL printer message info pointer!\n"));
-               goto done;
-       }
-               
-       prs_init(&buf, 1024, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0,   mem_ctx, UNMARSHALL );
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
 
        ZERO_STRUCT(notify_info);
 
-/*
-        * See comments in _spoolss_setprinter() about PRINTER_CHANGE_XXX
-        * events.  --jerry
-*/
-       DEBUG(10,("cli_spoolss_reply_rrpcn: PRINTER_MESSAGE flags = 0x%8x\n", info->flags));
-
-       data_len = build_notify_data(mem_ctx, printer, info->flags, &notify_data);
-       if (info->flags && (data_len == -1)) {
-               DEBUG(0,("cli_spoolss_reply_rrpcn: Failed to build SPOOL_NOTIFY_INFO_DATA [flags == 0x%x] for printer [%s]\n",
-                       info->flags, info->printer_name));
-               result = WERR_NOMEM;
-               goto done;
-       }
+       /* Initialise input parameters */
+
        notify_info.version = 0x2;
        notify_info.flags   = 0x00020000;       /* ?? */
-       notify_info.count   = data_len;
+       notify_info.count   = notify_data_len;
        notify_info.data    = notify_data;
 
        /* create and send a MSRPC command with api  */
        /* store the parameters */
 
-       make_spoolss_q_reply_rrpcn(&q_s, handle, info->low, info->high, &notify_info);
+       make_spoolss_q_reply_rrpcn(&q, pol, change_low, change_high, 
+                                  &notify_info);
 
-       /* turn parameters into data stream */
-       if(!spoolss_io_q_reply_rrpcn("", &q_s,  &buf, 0)) {
-               DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to marshall SPOOL_Q_REPLY_RRPCN struct.\n"));
-               goto done;
-       }
-
-       /* send the data on \PIPE\ */
-       if (!rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &buf, &rbuf)) 
-               goto done;
+       /* Marshall data and send request */
 
-       
-       /* turn data stream into parameters*/
-       if(!spoolss_io_r_reply_rrpcn("", &r_s, &rbuf, 0)) {
-               DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to unmarshall SPOOL_R_REPLY_RRPCN struct.\n"));
-               goto done;
-       }
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_RRPCN,
+               q, r,
+               qbuf, rbuf,
+               spoolss_io_q_reply_rrpcn,
+               spoolss_io_r_reply_rrpcn,
+               WERR_GENERAL_FAILURE );
 
-       if (r_s.unknown0 == 0x00080000) {
+       if (r.unknown0 == 0x00080000)
                DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n"));
-       }
+       else if ( r.unknown0 != 0x0 )
+               DEBUG(8,("cli_spoolss_reply_rrpcn: unknown0 is non-zero [0x%x]\n", r.unknown0));
        
-       result = r_s.status;
+       result = r.status;
+       return result;
+}
 
-done:
-       prs_mem_free(&buf);
-       prs_mem_free(&rbuf);
-       /*
-        * The memory allocated in this array is talloc'd so we only need
-        * free the array here. JRA.
-        */
-       SAFE_FREE(notify_data);
+/*********************************************************************
+ *********************************************************************/
+WERROR rpccli_spoolss_rffpcnex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                           POLICY_HND *pol, uint32 flags, uint32 options,
+                           const char *localmachine, uint32 printerlocal,
+                           SPOOL_NOTIFY_OPTION *option)
+{
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_RFFPCNEX q;
+       SPOOL_R_RFFPCNEX r;
+       WERROR result = W_ERROR(ERRgeneral);
 
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise input parameters */
+
+       make_spoolss_q_rffpcnex(
+               &q, pol, flags, options, localmachine, printerlocal,
+               option);
+
+       /* Marshall data and send request */
+
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_RFFPCNEX,
+               q, r,
+               qbuf, rbuf,
+               spoolss_io_q_rffpcnex,
+               spoolss_io_r_rffpcnex,
+               WERR_GENERAL_FAILURE );
+
+       result = r.status;
        return result;
 }
-