LCOV - code coverage report
Current view: top level - source3/rpc_server/spoolss - srv_spoolss_nt.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 2237 4421 50.6 %
Date: 2021-09-23 10:06:22 Functions: 129 291 44.3 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  RPC Pipe client / server routines
       4             :  *  Copyright (C) Andrew Tridgell              1992-2000,
       5             :  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
       6             :  *  Copyright (C) Jean François Micouleau      1998-2000,
       7             :  *  Copyright (C) Jeremy Allison               2001-2002,
       8             :  *  Copyright (C) Gerald Carter                2000-2004,
       9             :  *  Copyright (C) Tim Potter                   2001-2002.
      10             :  *  Copyright (C) Guenther Deschner            2009-2010.
      11             :  *  Copyright (C) Andreas Schneider            2010.
      12             :  *
      13             :  *  This program is free software; you can redistribute it and/or modify
      14             :  *  it under the terms of the GNU General Public License as published by
      15             :  *  the Free Software Foundation; either version 3 of the License, or
      16             :  *  (at your option) any later version.
      17             :  *
      18             :  *  This program is distributed in the hope that it will be useful,
      19             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      20             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      21             :  *  GNU General Public License for more details.
      22             :  *
      23             :  *  You should have received a copy of the GNU General Public License
      24             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      25             :  */
      26             : 
      27             : /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
      28             :    up, all the errors returned are DOS errors, not NT status codes. */
      29             : 
      30             : #include "includes.h"
      31             : #include "libsmb/namequery.h"
      32             : #include "ntdomain.h"
      33             : #include "nt_printing.h"
      34             : #include "srv_spoolss_util.h"
      35             : #include "librpc/gen_ndr/ndr_spoolss.h"
      36             : #include "librpc/gen_ndr/ndr_spoolss_scompat.h"
      37             : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
      38             : #include "rpc_client/init_spoolss.h"
      39             : #include "rpc_client/cli_pipe.h"
      40             : #include "../libcli/security/security.h"
      41             : #include "librpc/gen_ndr/ndr_security.h"
      42             : #include "registry.h"
      43             : #include "include/printing.h"
      44             : #include "secrets.h"
      45             : #include "../librpc/gen_ndr/netlogon.h"
      46             : #include "rpc_misc.h"
      47             : #include "printing/notify.h"
      48             : #include "serverid.h"
      49             : #include "../libcli/registry/util_reg.h"
      50             : #include "smbd/smbd.h"
      51             : #include "smbd/globals.h"
      52             : #include "auth.h"
      53             : #include "messages.h"
      54             : #include "rpc_server/spoolss/srv_spoolss_nt.h"
      55             : #include "util_tdb.h"
      56             : #include "libsmb/libsmb.h"
      57             : #include "printing/printer_list.h"
      58             : #include "../lib/tsocket/tsocket.h"
      59             : #include "rpc_client/cli_winreg_spoolss.h"
      60             : #include "../libcli/smb/smbXcli_base.h"
      61             : #include "rpc_server/spoolss/srv_spoolss_handle.h"
      62             : #include "lib/gencache.h"
      63             : #include "rpc_server/rpc_server.h"
      64             : #include "librpc/rpc/dcesrv_core.h"
      65             : #include "printing/nt_printing_migrate_internal.h"
      66             : #include "lib/util/string_wrappers.h"
      67             : #include "lib/global_contexts.h"
      68             : 
      69             : /* macros stolen from s4 spoolss server */
      70             : #define SPOOLSS_BUFFER_UNION(fn,info,level) \
      71             :         ((info)?ndr_size_##fn(info, level, 0):0)
      72             : 
      73             : #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
      74             :         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
      75             : 
      76             : #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
      77             :         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
      78             : 
      79             : #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
      80             : 
      81             : #undef DBGC_CLASS
      82             : #define DBGC_CLASS DBGC_RPC_SRV
      83             : 
      84             : #ifndef MAX_OPEN_PRINTER_EXS
      85             : #define MAX_OPEN_PRINTER_EXS 50
      86             : #endif
      87             : 
      88             : #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
      89             : #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
      90             : #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
      91             : #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
      92             : 
      93             : static struct printer_handle *printers_list;
      94             : 
      95             : struct printer_session_counter {
      96             :         struct printer_session_counter *next;
      97             :         struct printer_session_counter *prev;
      98             : 
      99             :         int snum;
     100             :         uint32_t counter;
     101             : };
     102             : 
     103             : static struct printer_session_counter *counter_list;
     104             : 
     105             : struct notify_back_channel {
     106             :         struct notify_back_channel *prev, *next;
     107             : 
     108             :         /* associated client */
     109             :         struct sockaddr_storage client_address;
     110             : 
     111             :         /* print notify back-channel pipe handle*/
     112             :         struct rpc_pipe_client *cli_pipe;
     113             :         struct cli_state *cli;
     114             :         uint32_t active_connections;
     115             : };
     116             : 
     117             : static struct notify_back_channel *back_channels;
     118             : 
     119             : /* Map generic permissions to printer object specific permissions */
     120             : 
     121             : const struct standard_mapping printer_std_mapping = {
     122             :         PRINTER_READ,
     123             :         PRINTER_WRITE,
     124             :         PRINTER_EXECUTE,
     125             :         PRINTER_ALL_ACCESS
     126             : };
     127             : 
     128             : /* Map generic permissions to print server object specific permissions */
     129             : 
     130             : const struct standard_mapping printserver_std_mapping = {
     131             :         SERVER_READ,
     132             :         SERVER_WRITE,
     133             :         SERVER_EXECUTE,
     134             :         SERVER_ALL_ACCESS
     135             : };
     136             : 
     137             : /* API table for Xcv Monitor functions */
     138             : 
     139             : struct xcv_api_table {
     140             :         const char *name;
     141             :         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
     142             : };
     143             : 
     144             : static void prune_printername_cache(void);
     145             : 
     146             : /********************************************************************
     147             :  * Canonicalize servername.
     148             :  ********************************************************************/
     149             : 
     150         426 : static const char *canon_servername(const char *servername)
     151             : {
     152         426 :         const char *pservername = servername;
     153             : 
     154         426 :         if (servername == NULL) {
     155           0 :                 return "";
     156             :         }
     157             : 
     158        1583 :         while (*pservername == '\\') {
     159         860 :                 pservername++;
     160             :         }
     161         426 :         return pservername;
     162             : }
     163             : 
     164             : /* translate between internal status numbers and NT status numbers */
     165         384 : static int nt_printj_status(int v)
     166             : {
     167         384 :         switch (v) {
     168         384 :         case LPQ_QUEUED:
     169         384 :                 return 0;
     170           0 :         case LPQ_PAUSED:
     171           0 :                 return JOB_STATUS_PAUSED;
     172           0 :         case LPQ_SPOOLING:
     173           0 :                 return JOB_STATUS_SPOOLING;
     174           0 :         case LPQ_PRINTING:
     175           0 :                 return JOB_STATUS_PRINTING;
     176           0 :         case LPQ_ERROR:
     177           0 :                 return JOB_STATUS_ERROR;
     178           0 :         case LPQ_DELETING:
     179           0 :                 return JOB_STATUS_DELETING;
     180           0 :         case LPQ_OFFLINE:
     181           0 :                 return JOB_STATUS_OFFLINE;
     182           0 :         case LPQ_PAPEROUT:
     183           0 :                 return JOB_STATUS_PAPEROUT;
     184           0 :         case LPQ_PRINTED:
     185           0 :                 return JOB_STATUS_PRINTED;
     186           0 :         case LPQ_DELETED:
     187           0 :                 return JOB_STATUS_DELETED;
     188           0 :         case LPQ_BLOCKED:
     189           0 :                 return JOB_STATUS_BLOCKED_DEVQ;
     190           0 :         case LPQ_USER_INTERVENTION:
     191           0 :                 return JOB_STATUS_USER_INTERVENTION;
     192             :         }
     193           0 :         return 0;
     194             : }
     195             : 
     196        1604 : static int nt_printq_status(int v)
     197             : {
     198        1604 :         switch (v) {
     199         216 :         case LPQ_PAUSED:
     200         216 :                 return PRINTER_STATUS_PAUSED;
     201        1388 :         case LPQ_QUEUED:
     202             :         case LPQ_SPOOLING:
     203             :         case LPQ_PRINTING:
     204        1388 :                 return 0;
     205             :         }
     206           0 :         return 0;
     207             : }
     208             : 
     209             : /***************************************************************************
     210             :  Disconnect from the client
     211             : ****************************************************************************/
     212             : 
     213           2 : static void srv_spoolss_replycloseprinter(int snum,
     214             :                                           struct printer_handle *prn_hnd)
     215             : {
     216             :         WERROR result;
     217             :         NTSTATUS status;
     218             : 
     219             :         /*
     220             :          * Tell the specific printing tdb we no longer want messages for this printer
     221             :          * by deregistering our PID.
     222             :          */
     223             : 
     224           2 :         if (!print_notify_deregister_pid(snum)) {
     225           0 :                 DEBUG(0, ("Failed to register our pid for printer %s\n",
     226             :                           lp_const_servicename(snum)));
     227             :         }
     228             : 
     229             :         /* weird if the test succeeds !!! */
     230           3 :         if (prn_hnd->notify.cli_chan == NULL ||
     231           3 :             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
     232           3 :             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
     233           2 :             prn_hnd->notify.cli_chan->active_connections == 0) {
     234           0 :                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
     235           0 :                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
     236           0 :                 TALLOC_FREE(prn_hnd->notify.cli_chan);
     237           0 :                 return;
     238             :         }
     239             : 
     240           3 :         status = dcerpc_spoolss_ReplyClosePrinter(
     241           2 :                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
     242             :                                         talloc_tos(),
     243             :                                         &prn_hnd->notify.cli_hnd,
     244             :                                         &result);
     245           2 :         if (!NT_STATUS_IS_OK(status)) {
     246           0 :                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
     247             :                           nt_errstr(status)));
     248           0 :                 result = ntstatus_to_werror(status);
     249           2 :         } else if (!W_ERROR_IS_OK(result)) {
     250           0 :                 DEBUG(0, ("reply_close_printer failed [%s].\n",
     251             :                           win_errstr(result)));
     252             :         }
     253             : 
     254             :         /* if it's the last connection, deconnect the IPC$ share */
     255           2 :         if (prn_hnd->notify.cli_chan->active_connections == 1) {
     256             : 
     257           2 :                 cli_shutdown(prn_hnd->notify.cli_chan->cli);
     258           2 :                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
     259           2 :                 TALLOC_FREE(prn_hnd->notify.cli_chan);
     260             : 
     261           2 :                 if (prn_hnd->notify.msg_ctx != NULL) {
     262           2 :                         messaging_deregister(prn_hnd->notify.msg_ctx,
     263             :                                              MSG_PRINTER_NOTIFY2, NULL);
     264             :                 }
     265             :         }
     266             : 
     267           2 :         if (prn_hnd->notify.cli_chan) {
     268           0 :                 prn_hnd->notify.cli_chan->active_connections--;
     269           0 :                 prn_hnd->notify.cli_chan = NULL;
     270             :         }
     271             : }
     272             : 
     273             : /****************************************************************************
     274             :  Functions to free a printer entry datastruct.
     275             : ****************************************************************************/
     276             : 
     277         922 : static int printer_entry_destructor(struct printer_handle *Printer)
     278             : {
     279         923 :         if (Printer->notify.cli_chan != NULL &&
     280           2 :             Printer->notify.cli_chan->active_connections > 0) {
     281           2 :                 int snum = -1;
     282             : 
     283           2 :                 switch(Printer->printer_type) {
     284           2 :                 case SPLHND_SERVER:
     285           2 :                         srv_spoolss_replycloseprinter(snum, Printer);
     286           2 :                         break;
     287             : 
     288           0 :                 case SPLHND_PRINTER:
     289           0 :                         snum = print_queue_snum(Printer->sharename);
     290           0 :                         if (snum != -1) {
     291           0 :                                 srv_spoolss_replycloseprinter(snum, Printer);
     292             :                         }
     293           0 :                         break;
     294           0 :                 default:
     295           0 :                         break;
     296             :                 }
     297         675 :         }
     298             : 
     299         922 :         Printer->notify.flags=0;
     300         922 :         Printer->notify.options=0;
     301         922 :         Printer->notify.localmachine[0]='\0';
     302         922 :         Printer->notify.printerlocal=0;
     303         922 :         TALLOC_FREE(Printer->notify.option);
     304         922 :         TALLOC_FREE(Printer->devmode);
     305             : 
     306             :         /* Remove from the internal list. */
     307         922 :         DLIST_REMOVE(printers_list, Printer);
     308         922 :         return 0;
     309             : }
     310             : 
     311             : /****************************************************************************
     312             :   find printer index by handle
     313             : ****************************************************************************/
     314             : 
     315       51922 : static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
     316             :                                                         struct policy_handle *hnd)
     317             : {
     318       51922 :         struct printer_handle *find_printer = NULL;
     319             :         NTSTATUS status;
     320             : 
     321       51922 :         find_printer = find_policy_by_hnd(p,
     322             :                                           hnd,
     323             :                                           DCESRV_HANDLE_ANY,
     324             :                                           struct printer_handle,
     325             :                                           &status);
     326       51922 :         if (!NT_STATUS_IS_OK(status)) {
     327           0 :                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
     328           0 :                 return NULL;
     329             :         }
     330             : 
     331       51922 :         return find_printer;
     332             : }
     333             : 
     334             : /****************************************************************************
     335             :  Close printer index by handle.
     336             : ****************************************************************************/
     337             : 
     338         914 : static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
     339             : {
     340         914 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     341             : 
     342         914 :         if (!Printer) {
     343           0 :                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
     344             :                         OUR_HANDLE(hnd)));
     345           0 :                 return false;
     346             :         }
     347             : 
     348         914 :         close_policy_hnd(p, hnd);
     349             : 
     350         914 :         return true;
     351             : }
     352             : 
     353             : /****************************************************************************
     354             :  Delete a printer given a handle.
     355             : ****************************************************************************/
     356             : 
     357          16 : static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
     358             :                                   const char *sharename,
     359             :                                   struct messaging_context *msg_ctx)
     360             : {
     361          12 :         const struct loadparm_substitution *lp_sub =
     362           4 :                 loadparm_s3_global_substitution();
     363          16 :         char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
     364          16 :         char *command = NULL;
     365             :         int ret;
     366          16 :         bool is_print_op = false;
     367             : 
     368             :         /* can't fail if we don't try */
     369             : 
     370          16 :         if ( !*cmd )
     371           0 :                 return WERR_OK;
     372             : 
     373          16 :         command = talloc_asprintf(ctx,
     374             :                         "%s \"%s\"",
     375             :                         cmd, sharename);
     376          16 :         if (!command) {
     377           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     378             :         }
     379          16 :         if ( token )
     380          16 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
     381             : 
     382          16 :         DEBUG(10,("Running [%s]\n", command));
     383             : 
     384             :         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
     385             : 
     386          16 :         if ( is_print_op )
     387           0 :                 become_root();
     388             : 
     389          16 :         ret = smbrun(command, NULL, NULL);
     390          12 :         if (ret == 0) {
     391             :                 /* Tell everyone we updated smb.conf. */
     392          12 :                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
     393             :         }
     394             : 
     395          12 :         if ( is_print_op )
     396           0 :                 unbecome_root();
     397             : 
     398             :         /********** END SePrintOperatorPrivlege BLOCK **********/
     399             : 
     400          12 :         DEBUGADD(10,("returned [%d]\n", ret));
     401             : 
     402          12 :         TALLOC_FREE(command);
     403             : 
     404          12 :         if (ret != 0)
     405           0 :                 return WERR_INVALID_HANDLE; /* What to return here? */
     406             : 
     407          12 :         return WERR_OK;
     408             : }
     409             : 
     410             : /****************************************************************************
     411             :  Delete a printer given a handle.
     412             : ****************************************************************************/
     413             : 
     414          16 : static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
     415             : {
     416          16 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     417             :         WERROR result;
     418             : 
     419          16 :         if (!Printer) {
     420           0 :                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
     421             :                         OUR_HANDLE(hnd)));
     422           0 :                 return WERR_INVALID_HANDLE;
     423             :         }
     424             : 
     425             :         /*
     426             :          * It turns out that Windows allows delete printer on a handle
     427             :          * opened by an admin user, then used on a pipe handle created
     428             :          * by an anonymous user..... but they're working on security.... riiight !
     429             :          * JRA.
     430             :          */
     431             : 
     432          16 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
     433           0 :                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
     434           0 :                 return WERR_ACCESS_DENIED;
     435             :         }
     436             : 
     437             :         /* this does not need a become root since the access check has been
     438             :            done on the handle already */
     439             : 
     440          16 :         result = winreg_delete_printer_key_internal(p->mem_ctx,
     441             :                                            get_session_info_system(),
     442             :                                            p->msg_ctx,
     443          16 :                                            Printer->sharename,
     444             :                                            "");
     445          16 :         if (!W_ERROR_IS_OK(result)) {
     446           0 :                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
     447           0 :                 return WERR_INVALID_HANDLE;
     448             :         }
     449             : 
     450          28 :         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
     451          16 :                                      Printer->sharename, p->msg_ctx);
     452          12 :         if (!W_ERROR_IS_OK(result)) {
     453           0 :                 return result;
     454             :         }
     455          12 :         prune_printername_cache();
     456          12 :         return WERR_OK;
     457             : }
     458             : 
     459             : /****************************************************************************
     460             :  Return the snum of a printer corresponding to an handle.
     461             : ****************************************************************************/
     462             : 
     463       24670 : static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
     464             :                              int *number, struct share_params **params)
     465             : {
     466       24670 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     467             : 
     468       24670 :         if (!Printer) {
     469           0 :                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
     470             :                         OUR_HANDLE(hnd)));
     471           0 :                 return false;
     472             :         }
     473             : 
     474       24670 :         switch (Printer->printer_type) {
     475       24670 :                 case SPLHND_PRINTER:
     476       24670 :                         DEBUG(4,("short name:%s\n", Printer->sharename));
     477       24670 :                         *number = print_queue_snum(Printer->sharename);
     478       24670 :                         return (*number != -1);
     479           0 :                 case SPLHND_SERVER:
     480           0 :                         return false;
     481           0 :                 default:
     482           0 :                         return false;
     483             :         }
     484             : }
     485             : 
     486             : /****************************************************************************
     487             :  Set printer handle type.
     488             :  Check if it's \\server or \\server\printer
     489             : ****************************************************************************/
     490             : 
     491         934 : static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
     492             : {
     493         934 :         DEBUG(3,("Setting printer type=%s\n", handlename));
     494             : 
     495             :         /* it's a print server */
     496         934 :         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
     497          92 :                 DEBUGADD(4,("Printer is a print server\n"));
     498          92 :                 Printer->printer_type = SPLHND_SERVER;
     499             :         }
     500             :         /* it's a printer (set_printer_hnd_name() will handle port monitors */
     501             :         else {
     502         842 :                 DEBUGADD(4,("Printer is a printer\n"));
     503         842 :                 Printer->printer_type = SPLHND_PRINTER;
     504             :         }
     505             : 
     506         934 :         return true;
     507             : }
     508             : 
     509         366 : static void prune_printername_cache_fn(const char *key, const char *value,
     510             :                                        time_t timeout, void *private_data)
     511             : {
     512         366 :         gencache_del(key);
     513         366 : }
     514             : 
     515         128 : static void prune_printername_cache(void)
     516             : {
     517         128 :         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
     518         128 : }
     519             : 
     520             : /****************************************************************************
     521             :  Set printer handle name..  Accept names like \\server, \\server\printer,
     522             :  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
     523             :  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
     524             :  XcvDataPort() interface.
     525             : ****************************************************************************/
     526             : 
     527         934 : static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
     528             :                                    const struct auth_session_info *session_info,
     529             :                                    struct messaging_context *msg_ctx,
     530             :                                    struct printer_handle *Printer,
     531             :                                    const char *handlename)
     532             : {
     533             :         int snum;
     534         934 :         int n_services=lp_numservices();
     535             :         char *aprinter;
     536             :         const char *printername;
     537         934 :         const char *servername = NULL;
     538             :         fstring sname;
     539         934 :         bool found = false;
     540         934 :         struct spoolss_PrinterInfo2 *info2 = NULL;
     541             :         WERROR result;
     542             :         char *p;
     543             : 
     544             :         /*
     545             :          * Hopefully nobody names his printers like this. Maybe \ or ,
     546             :          * are illegal in printer names even?
     547             :          */
     548         934 :         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
     549             :         char *cache_key;
     550             :         char *tmp;
     551             : 
     552         934 :         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
     553             :                 (unsigned long)strlen(handlename)));
     554             : 
     555         934 :         aprinter = discard_const_p(char, handlename);
     556         934 :         if ( *handlename == '\\' ) {
     557         214 :                 servername = canon_servername(handlename);
     558         214 :                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
     559         114 :                         *aprinter = '\0';
     560         114 :                         aprinter++;
     561             :                 }
     562         214 :                 if (!is_myname_or_ipaddr(servername)) {
     563          12 :                         return WERR_INVALID_PRINTER_NAME;
     564             :                 }
     565         202 :                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
     566         202 :                 if (Printer->servername == NULL) {
     567           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     568             :                 }
     569             :         }
     570             : 
     571         922 :         if (Printer->printer_type == SPLHND_SERVER) {
     572          88 :                 return WERR_OK;
     573             :         }
     574             : 
     575         834 :         if (Printer->printer_type != SPLHND_PRINTER) {
     576           0 :                 return WERR_INVALID_HANDLE;
     577             :         }
     578             : 
     579         834 :         DEBUGADD(5, ("searching for [%s]\n", aprinter));
     580             : 
     581         834 :         p = strchr(aprinter, ',');
     582         834 :         if (p != NULL) {
     583         504 :                 char *p2 = p;
     584         504 :                 p++;
     585         504 :                 if (*p == ' ') {
     586         308 :                         p++;
     587             :                 }
     588         504 :                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
     589         140 :                         *p2 = '\0';
     590         364 :                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
     591         140 :                         *p2 = '\0';
     592             :                 }
     593             :         }
     594             : 
     595         834 :         if (p) {
     596         504 :                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
     597             :         }
     598             : 
     599             :         /* check for the Port Monitor Interface */
     600         834 :         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
     601           0 :                 Printer->printer_type = SPLHND_PORTMON_TCP;
     602           0 :                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
     603           0 :                 found = true;
     604             :         }
     605         834 :         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
     606           0 :                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
     607           0 :                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
     608           0 :                 found = true;
     609             :         }
     610             : 
     611         834 :         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
     612         834 :         if (cache_key == NULL) {
     613           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     614             :         }
     615             : 
     616             :         /*
     617             :          * With hundreds of printers, the "for" loop iterating all
     618             :          * shares can be quite expensive, as it is done on every
     619             :          * OpenPrinter. The loop maps "aprinter" to "sname", the
     620             :          * result of which we cache in gencache.
     621             :          */
     622         834 :         if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
     623         458 :                 found = (strcmp(tmp, printer_not_found) != 0);
     624         458 :                 if (!found) {
     625          32 :                         DEBUG(4, ("Printer %s not found\n", aprinter));
     626          32 :                         TALLOC_FREE(tmp);
     627          32 :                         return WERR_INVALID_PRINTER_NAME;
     628             :                 }
     629         426 :                 fstrcpy(sname, tmp);
     630         426 :                 TALLOC_FREE(tmp);
     631             :         }
     632             : 
     633             :         /* Search all sharenames first as this is easier than pulling
     634             :            the printer_info_2 off of disk. Don't use find_service() since
     635             :            that calls out to map_username() */
     636             : 
     637             :         /* do another loop to look for printernames */
     638       20488 :         for (snum = 0; !found && snum < n_services; snum++) {
     639       19774 :                 const char *printer = lp_const_servicename(snum);
     640             : 
     641             :                 /* no point going on if this is not a printer */
     642       19774 :                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
     643       17906 :                         continue;
     644             :                 }
     645             : 
     646             :                 /* ignore [printers] share */
     647        1868 :                 if (strequal(printer, "printers")) {
     648           0 :                         continue;
     649             :                 }
     650             : 
     651        1868 :                 fstrcpy(sname, printer);
     652        1868 :                 if (strequal(aprinter, printer)) {
     653          80 :                         found = true;
     654          80 :                         break;
     655             :                 }
     656             : 
     657             :                 /* no point looking up the printer object if
     658             :                    we aren't allowing printername != sharename */
     659        1788 :                 if (lp_force_printername(snum)) {
     660           0 :                         continue;
     661             :                 }
     662             : 
     663        1788 :                 result = winreg_get_printer_internal(mem_ctx,
     664             :                                             session_info,
     665             :                                             msg_ctx,
     666             :                                             sname,
     667             :                                             &info2);
     668        1788 :                 if ( !W_ERROR_IS_OK(result) ) {
     669          48 :                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
     670             :                                  sname, win_errstr(result)));
     671          48 :                         continue;
     672             :                 }
     673             : 
     674        1740 :                 printername = strrchr(info2->printername, '\\');
     675        1740 :                 if (printername == NULL) {
     676        1740 :                         printername = info2->printername;
     677             :                 } else {
     678           0 :                         printername++;
     679             :                 }
     680             : 
     681        1740 :                 if (strequal(printername, aprinter)) {
     682           8 :                         found = true;
     683           8 :                         break;
     684             :                 }
     685             : 
     686        1732 :                 DEBUGADD(10, ("printername: %s\n", printername));
     687             : 
     688        1732 :                 TALLOC_FREE(info2);
     689             :         }
     690             : 
     691         802 :         if (!found) {
     692         288 :                 gencache_set(cache_key, printer_not_found,
     693         288 :                              time(NULL) + 300);
     694         288 :                 TALLOC_FREE(cache_key);
     695         288 :                 DEBUGADD(4,("Printer not found\n"));
     696         288 :                 return WERR_INVALID_PRINTER_NAME;
     697             :         }
     698             : 
     699         514 :         gencache_set(cache_key, sname, time(NULL) + 300);
     700         514 :         TALLOC_FREE(cache_key);
     701             : 
     702         514 :         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
     703             : 
     704         514 :         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
     705             : 
     706         514 :         return WERR_OK;
     707             : }
     708             : 
     709             : /****************************************************************************
     710             :  Find first available printer slot. creates a printer handle for you.
     711             :  ****************************************************************************/
     712             : 
     713         934 : static WERROR open_printer_hnd(struct pipes_struct *p,
     714             :                                struct policy_handle *hnd,
     715             :                                const char *name,
     716             :                                uint32_t access_granted)
     717             : {
     718             :         struct printer_handle *new_printer;
     719             :         WERROR result;
     720             : 
     721         934 :         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
     722             : 
     723         934 :         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
     724         934 :         if (new_printer == NULL) {
     725           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     726             :         }
     727         934 :         talloc_set_destructor(new_printer, printer_entry_destructor);
     728             : 
     729             :         /* This also steals the printer_handle on the policy_handle */
     730         934 :         if (!create_policy_hnd(p, hnd, 0, new_printer)) {
     731           0 :                 TALLOC_FREE(new_printer);
     732           0 :                 return WERR_INVALID_HANDLE;
     733             :         }
     734             : 
     735             :         /* Add to the internal list. */
     736         934 :         DLIST_ADD(printers_list, new_printer);
     737             : 
     738         934 :         new_printer->notify.option=NULL;
     739             : 
     740         934 :         if (!set_printer_hnd_printertype(new_printer, name)) {
     741           0 :                 close_printer_handle(p, hnd);
     742           0 :                 return WERR_INVALID_HANDLE;
     743             :         }
     744             : 
     745         934 :         result = set_printer_hnd_name(p->mem_ctx,
     746             :                                       get_session_info_system(),
     747             :                                       p->msg_ctx,
     748             :                                       new_printer, name);
     749         934 :         if (!W_ERROR_IS_OK(result)) {
     750         332 :                 close_printer_handle(p, hnd);
     751         332 :                 return result;
     752             :         }
     753             : 
     754         602 :         new_printer->access_granted = access_granted;
     755             : 
     756         602 :         DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
     757             : 
     758         602 :         return WERR_OK;
     759             : }
     760             : 
     761             : /***************************************************************************
     762             :  check to see if the client motify handle is monitoring the notification
     763             :  given by (notify_type, notify_field).
     764             :  **************************************************************************/
     765             : 
     766           0 : static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
     767             :                                       uint16_t notify_field)
     768             : {
     769           0 :         return true;
     770             : }
     771             : 
     772           0 : static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
     773             :                                 uint16_t notify_field)
     774             : {
     775           0 :         struct spoolss_NotifyOption *option = p->notify.option;
     776             :         uint32_t i, j;
     777             : 
     778             :         /*
     779             :          * Flags should always be zero when the change notify
     780             :          * is registered by the client's spooler.  A user Win32 app
     781             :          * might use the flags though instead of the NOTIFY_OPTION_INFO
     782             :          * --jerry
     783             :          */
     784             : 
     785           0 :         if (!option) {
     786           0 :                 return false;
     787             :         }
     788             : 
     789           0 :         if (p->notify.flags)
     790           0 :                 return is_monitoring_event_flags(
     791             :                         p->notify.flags, notify_type, notify_field);
     792             : 
     793           0 :         for (i = 0; i < option->count; i++) {
     794             : 
     795             :                 /* Check match for notify_type */
     796             : 
     797           0 :                 if (option->types[i].type != notify_type)
     798           0 :                         continue;
     799             : 
     800             :                 /* Check match for field */
     801             : 
     802           0 :                 for (j = 0; j < option->types[i].count; j++) {
     803           0 :                         if (option->types[i].fields[j].field == notify_field) {
     804           0 :                                 return true;
     805             :                         }
     806             :                 }
     807             :         }
     808             : 
     809           0 :         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
     810             :                    p->servername, p->sharename, notify_type, notify_field));
     811             : 
     812           0 :         return false;
     813             : }
     814             : 
     815             : #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
     816             :         _data->data.integer[0] = _integer; \
     817             :         _data->data.integer[1] = 0;
     818             : 
     819             : 
     820             : #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
     821             :         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
     822             :         if (!_data->data.string.string) {\
     823             :                 _data->data.string.size = 0; \
     824             :         } \
     825             :         _data->data.string.size = strlen_m_term(_p) * 2;
     826             : 
     827             : #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
     828             :         _data->data.devmode.devmode = _devmode;
     829             : 
     830           0 : static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
     831             :                                    struct tm *t,
     832             :                                    const char **pp,
     833             :                                    uint32_t *plen)
     834             : {
     835             :         struct spoolss_Time st;
     836           0 :         uint32_t len = 16;
     837             :         char *p;
     838             : 
     839           0 :         if (!init_systemtime(&st, t)) {
     840           0 :                 return;
     841             :         }
     842             : 
     843           0 :         p = talloc_array(mem_ctx, char, len);
     844           0 :         if (!p) {
     845           0 :                 return;
     846             :         }
     847             : 
     848             :         /*
     849             :          * Systemtime must be linearized as a set of UINT16's.
     850             :          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
     851             :          */
     852             : 
     853           0 :         SSVAL(p, 0, st.year);
     854           0 :         SSVAL(p, 2, st.month);
     855           0 :         SSVAL(p, 4, st.day_of_week);
     856           0 :         SSVAL(p, 6, st.day);
     857           0 :         SSVAL(p, 8, st.hour);
     858           0 :         SSVAL(p, 10, st.minute);
     859           0 :         SSVAL(p, 12, st.second);
     860           0 :         SSVAL(p, 14, st.millisecond);
     861             : 
     862           0 :         *pp = p;
     863           0 :         *plen = len;
     864             : }
     865             : 
     866             : /* Convert a notification message to a struct spoolss_Notify */
     867             : 
     868           0 : static void notify_one_value(struct spoolss_notify_msg *msg,
     869             :                              struct spoolss_Notify *data,
     870             :                              TALLOC_CTX *mem_ctx)
     871             : {
     872           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
     873           0 : }
     874             : 
     875           0 : static void notify_string(struct spoolss_notify_msg *msg,
     876             :                           struct spoolss_Notify *data,
     877             :                           TALLOC_CTX *mem_ctx)
     878             : {
     879             :         /* The length of the message includes the trailing \0 */
     880             : 
     881           0 :         data->data.string.size = msg->len * 2;
     882           0 :         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
     883           0 :         if (!data->data.string.string) {
     884           0 :                 data->data.string.size = 0;
     885           0 :                 return;
     886             :         }
     887             : }
     888             : 
     889           0 : static void notify_system_time(struct spoolss_notify_msg *msg,
     890             :                                struct spoolss_Notify *data,
     891             :                                TALLOC_CTX *mem_ctx)
     892             : {
     893           0 :         data->data.string.string = NULL;
     894           0 :         data->data.string.size = 0;
     895             : 
     896           0 :         if (msg->len != sizeof(time_t)) {
     897           0 :                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
     898             :                           msg->len));
     899           0 :                 return;
     900             :         }
     901             : 
     902           0 :         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
     903             :                                &data->data.string.string,
     904             :                                &data->data.string.size);
     905             : }
     906             : 
     907             : struct notify2_message_table {
     908             :         const char *name;
     909             :         void (*fn)(struct spoolss_notify_msg *msg,
     910             :                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
     911             : };
     912             : 
     913             : static struct notify2_message_table printer_notify_table[] = {
     914             :         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
     915             :         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
     916             :         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
     917             :         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
     918             :         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
     919             :         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
     920             :         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
     921             :         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
     922             :         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
     923             :         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
     924             :         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
     925             :         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
     926             :         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
     927             :         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
     928             :         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
     929             :         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
     930             :         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
     931             :         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
     932             :         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
     933             : };
     934             : 
     935             : static struct notify2_message_table job_notify_table[] = {
     936             :         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
     937             :         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
     938             :         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
     939             :         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
     940             :         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
     941             :         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
     942             :         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
     943             :         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
     944             :         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
     945             :         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
     946             :         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
     947             :         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
     948             :         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
     949             :         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
     950             :         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
     951             :         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
     952             :         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
     953             :         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
     954             :         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
     955             :         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
     956             :         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
     957             :         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
     958             :         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
     959             :         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
     960             : };
     961             : 
     962             : 
     963             : /***********************************************************************
     964             :  Allocate talloc context for container object
     965             :  **********************************************************************/
     966             : 
     967           0 : static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     968             : {
     969           0 :         if ( !ctr )
     970           0 :                 return;
     971             : 
     972           0 :         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
     973             : 
     974           0 :         return;
     975             : }
     976             : 
     977             : /***********************************************************************
     978             :  release all allocated memory and zero out structure
     979             :  **********************************************************************/
     980             : 
     981           0 : static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     982             : {
     983           0 :         if ( !ctr )
     984           0 :                 return;
     985             : 
     986           0 :         if ( ctr->ctx )
     987           0 :                 talloc_destroy(ctr->ctx);
     988             : 
     989           0 :         ZERO_STRUCTP(ctr);
     990             : 
     991           0 :         return;
     992             : }
     993             : 
     994             : /***********************************************************************
     995             :  **********************************************************************/
     996             : 
     997           0 : static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     998             : {
     999           0 :         if ( !ctr )
    1000           0 :                 return NULL;
    1001             : 
    1002           0 :         return ctr->ctx;
    1003             : }
    1004             : 
    1005             : /***********************************************************************
    1006             :  **********************************************************************/
    1007             : 
    1008           0 : static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
    1009             : {
    1010           0 :         if ( !ctr || !ctr->msg_groups )
    1011           0 :                 return NULL;
    1012             : 
    1013           0 :         if ( idx >= ctr->num_groups )
    1014           0 :                 return NULL;
    1015             : 
    1016           0 :         return &ctr->msg_groups[idx];
    1017             : 
    1018             : }
    1019             : 
    1020             : /***********************************************************************
    1021             :  How many groups of change messages do we have ?
    1022             :  **********************************************************************/
    1023             : 
    1024           0 : static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
    1025             : {
    1026           0 :         if ( !ctr )
    1027           0 :                 return 0;
    1028             : 
    1029           0 :         return ctr->num_groups;
    1030             : }
    1031             : 
    1032             : /***********************************************************************
    1033             :  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
    1034             :  **********************************************************************/
    1035             : 
    1036           0 : static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
    1037             : {
    1038           0 :         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
    1039           0 :         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
    1040           0 :         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
    1041             :         uint32_t                        i, new_slot;
    1042             : 
    1043           0 :         if ( !ctr || !msg )
    1044           0 :                 return 0;
    1045             : 
    1046             :         /* loop over all groups looking for a matching printer name */
    1047             : 
    1048           0 :         for ( i=0; i<ctr->num_groups; i++ ) {
    1049           0 :                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
    1050           0 :                         break;
    1051             :         }
    1052             : 
    1053             :         /* add a new group? */
    1054             : 
    1055           0 :         if ( i == ctr->num_groups ) {
    1056           0 :                 ctr->num_groups++;
    1057             : 
    1058           0 :                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
    1059           0 :                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
    1060           0 :                         return 0;
    1061             :                 }
    1062           0 :                 ctr->msg_groups = groups;
    1063             : 
    1064             :                 /* clear the new entry and set the printer name */
    1065             : 
    1066           0 :                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
    1067           0 :                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
    1068             :         }
    1069             : 
    1070             :         /* add the change messages; 'i' is the correct index now regardless */
    1071             : 
    1072           0 :         msg_grp = &ctr->msg_groups[i];
    1073             : 
    1074           0 :         msg_grp->num_msgs++;
    1075             : 
    1076           0 :         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
    1077           0 :                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
    1078           0 :                 return 0;
    1079             :         }
    1080           0 :         msg_grp->msgs = msg_list;
    1081             : 
    1082           0 :         new_slot = msg_grp->num_msgs-1;
    1083           0 :         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
    1084             : 
    1085             :         /* need to allocate own copy of data */
    1086             : 
    1087           0 :         if ( msg->len != 0 )
    1088           0 :                 msg_grp->msgs[new_slot].notify.data = (char *)
    1089           0 :                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
    1090             : 
    1091           0 :         return ctr->num_groups;
    1092             : }
    1093             : 
    1094             : static void construct_info_data(struct spoolss_Notify *info_data,
    1095             :                                 enum spoolss_NotifyType type,
    1096             :                                 uint16_t field, int id);
    1097             : 
    1098             : /***********************************************************************
    1099             :  Send a change notifation message on all handles which have a call
    1100             :  back registered
    1101             :  **********************************************************************/
    1102             : 
    1103           0 : static int build_notify2_messages(TALLOC_CTX *mem_ctx,
    1104             :                                   struct printer_handle *prn_hnd,
    1105             :                                   SPOOLSS_NOTIFY_MSG *messages,
    1106             :                                   uint32_t num_msgs,
    1107             :                                   struct spoolss_Notify **_notifies,
    1108             :                                   size_t *_count)
    1109             : {
    1110             :         struct spoolss_Notify *notifies;
    1111             :         SPOOLSS_NOTIFY_MSG *msg;
    1112           0 :         size_t count = 0;
    1113             :         uint32_t id;
    1114             :         uint32_t i;
    1115             : 
    1116           0 :         notifies = talloc_zero_array(mem_ctx,
    1117             :                                      struct spoolss_Notify, num_msgs);
    1118           0 :         if (!notifies) {
    1119           0 :                 return ENOMEM;
    1120             :         }
    1121             : 
    1122           0 :         for (i = 0; i < num_msgs; i++) {
    1123             : 
    1124           0 :                 msg = &messages[i];
    1125             : 
    1126             :                 /* Are we monitoring this event? */
    1127             : 
    1128           0 :                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
    1129           0 :                         continue;
    1130             :                 }
    1131             : 
    1132           0 :                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
    1133             :                            "for printer [%s]\n",
    1134             :                            msg->type, msg->field, prn_hnd->sharename));
    1135             : 
    1136             :                 /*
    1137             :                  * if the is a printer notification handle and not a job
    1138             :                  * notification type, then set the id to 0.
    1139             :                  * Otherwise just use what was specified in the message.
    1140             :                  *
    1141             :                  * When registering change notification on a print server
    1142             :                  * handle we always need to send back the id (snum) matching
    1143             :                  * the printer for which the change took place.
    1144             :                  * For change notify registered on a printer handle,
    1145             :                  * this does not matter and the id should be 0.
    1146             :                  *
    1147             :                  * --jerry
    1148             :                  */
    1149             : 
    1150           0 :                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
    1151           0 :                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
    1152           0 :                         id = 0;
    1153             :                 } else {
    1154           0 :                         id = msg->id;
    1155             :                 }
    1156             : 
    1157             :                 /* Convert unix jobid to smb jobid */
    1158             : 
    1159           0 :                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
    1160           0 :                         id = sysjob_to_jobid(msg->id);
    1161             : 
    1162           0 :                         if (id == -1) {
    1163           0 :                                 DEBUG(3, ("no such unix jobid %d\n",
    1164             :                                           msg->id));
    1165           0 :                                 continue;
    1166             :                         }
    1167             :                 }
    1168             : 
    1169           0 :                 construct_info_data(&notifies[count],
    1170           0 :                                     msg->type, msg->field, id);
    1171             : 
    1172           0 :                 switch(msg->type) {
    1173           0 :                 case PRINTER_NOTIFY_TYPE:
    1174           0 :                         if (printer_notify_table[msg->field].fn) {
    1175           0 :                                 printer_notify_table[msg->field].fn(msg,
    1176           0 :                                                 &notifies[count], mem_ctx);
    1177             :                         }
    1178           0 :                         break;
    1179             : 
    1180           0 :                 case JOB_NOTIFY_TYPE:
    1181           0 :                         if (job_notify_table[msg->field].fn) {
    1182           0 :                                 job_notify_table[msg->field].fn(msg,
    1183           0 :                                                 &notifies[count], mem_ctx);
    1184             :                         }
    1185           0 :                         break;
    1186             : 
    1187           0 :                 default:
    1188           0 :                         DEBUG(5, ("Unknown notification type %d\n",
    1189             :                                   msg->type));
    1190           0 :                         continue;
    1191             :                 }
    1192             : 
    1193           0 :                 count++;
    1194             :         }
    1195             : 
    1196           0 :         *_notifies = notifies;
    1197           0 :         *_count = count;
    1198             : 
    1199           0 :         return 0;
    1200             : }
    1201             : 
    1202           0 : static int send_notify2_printer(TALLOC_CTX *mem_ctx,
    1203             :                                 struct printer_handle *prn_hnd,
    1204             :                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
    1205             : {
    1206             :         struct spoolss_Notify *notifies;
    1207           0 :         size_t count = 0;
    1208             :         union spoolss_ReplyPrinterInfo info;
    1209             :         struct spoolss_NotifyInfo info0;
    1210             :         uint32_t reply_result;
    1211             :         NTSTATUS status;
    1212             :         WERROR werr;
    1213             :         int ret;
    1214             : 
    1215             :         /* Is there notification on this handle? */
    1216           0 :         if (prn_hnd->notify.cli_chan == NULL ||
    1217           0 :             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
    1218           0 :             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
    1219           0 :             prn_hnd->notify.cli_chan->active_connections == 0) {
    1220           0 :                 return 0;
    1221             :         }
    1222             : 
    1223           0 :         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
    1224             :                    prn_hnd->servername, prn_hnd->sharename));
    1225             : 
    1226             :         /* For this printer? Print servers always receive notifications. */
    1227           0 :         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
    1228           0 :             (!strequal(msg_group->printername, prn_hnd->sharename))) {
    1229           0 :                 return 0;
    1230             :         }
    1231             : 
    1232           0 :         DEBUG(10,("Our printer\n"));
    1233             : 
    1234             :         /* build the array of change notifications */
    1235           0 :         ret = build_notify2_messages(mem_ctx, prn_hnd,
    1236             :                                      msg_group->msgs,
    1237             :                                      msg_group->num_msgs,
    1238             :                                      &notifies, &count);
    1239           0 :         if (ret) {
    1240           0 :                 return ret;
    1241             :         }
    1242             : 
    1243           0 :         info0.version   = 0x2;
    1244           0 :         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
    1245           0 :         info0.count     = count;
    1246           0 :         info0.notifies  = notifies;
    1247             : 
    1248           0 :         info.info0 = &info0;
    1249             : 
    1250           0 :         status = dcerpc_spoolss_RouterReplyPrinterEx(
    1251           0 :                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
    1252             :                                 mem_ctx,
    1253             :                                 &prn_hnd->notify.cli_hnd,
    1254             :                                 prn_hnd->notify.change, /* color */
    1255             :                                 prn_hnd->notify.flags,
    1256             :                                 &reply_result,
    1257             :                                 0, /* reply_type, must be 0 */
    1258             :                                 info, &werr);
    1259           0 :         if (!NT_STATUS_IS_OK(status)) {
    1260           0 :                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
    1261             :                           "failed: %s\n",
    1262             :                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
    1263             :                           nt_errstr(status)));
    1264           0 :                 werr = ntstatus_to_werror(status);
    1265           0 :         } else if (!W_ERROR_IS_OK(werr)) {
    1266           0 :                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
    1267             :                           "failed: %s\n",
    1268             :                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
    1269             :                           win_errstr(werr)));
    1270             :         }
    1271           0 :         switch (reply_result) {
    1272           0 :         case 0:
    1273           0 :                 break;
    1274           0 :         case PRINTER_NOTIFY_INFO_DISCARDED:
    1275             :         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
    1276             :         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
    1277           0 :                 break;
    1278           0 :         default:
    1279           0 :                 break;
    1280             :         }
    1281             : 
    1282           0 :         return 0;
    1283             : }
    1284             : 
    1285           0 : static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
    1286             : {
    1287             :         struct printer_handle    *p;
    1288           0 :         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
    1289           0 :         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
    1290             :         int ret;
    1291             : 
    1292           0 :         if ( !msg_group ) {
    1293           0 :                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
    1294           0 :                 return;
    1295             :         }
    1296             : 
    1297           0 :         if (!msg_group->msgs) {
    1298           0 :                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
    1299           0 :                 return;
    1300             :         }
    1301             : 
    1302           0 :         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
    1303             : 
    1304             :         /* loop over all printers */
    1305             : 
    1306           0 :         for (p = printers_list; p; p = p->next) {
    1307           0 :                 ret = send_notify2_printer(mem_ctx, p, msg_group);
    1308           0 :                 if (ret) {
    1309           0 :                         goto done;
    1310             :                 }
    1311             :         }
    1312             : 
    1313           0 : done:
    1314           0 :         DEBUG(8,("send_notify2_changes: Exit...\n"));
    1315           0 :         return;
    1316             : }
    1317             : 
    1318             : /***********************************************************************
    1319             :  **********************************************************************/
    1320             : 
    1321           0 : static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
    1322             : {
    1323             : 
    1324             :         uint32_t tv_sec, tv_usec;
    1325           0 :         size_t offset = 0;
    1326             : 
    1327             :         /* Unpack message */
    1328             : 
    1329           0 :         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
    1330           0 :                              msg->printer);
    1331             : 
    1332           0 :         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
    1333             :                                 &tv_sec, &tv_usec,
    1334             :                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
    1335             : 
    1336           0 :         if (msg->len == 0)
    1337           0 :                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
    1338             :                            &msg->notify.value[0], &msg->notify.value[1]);
    1339             :         else
    1340           0 :                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
    1341             :                            &msg->len, &msg->notify.data);
    1342             : 
    1343           0 :         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
    1344             :                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
    1345             : 
    1346           0 :         tv->tv_sec = tv_sec;
    1347           0 :         tv->tv_usec = tv_usec;
    1348             : 
    1349           0 :         if (msg->len == 0)
    1350           0 :                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
    1351             :                           msg->notify.value[1]));
    1352             :         else
    1353           0 :                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
    1354             : 
    1355           0 :         return true;
    1356             : }
    1357             : 
    1358             : /********************************************************************
    1359             :  Receive a notify2 message list
    1360             :  ********************************************************************/
    1361             : 
    1362           0 : static void receive_notify2_message_list(struct messaging_context *msg,
    1363             :                                          void *private_data,
    1364             :                                          uint32_t msg_type,
    1365             :                                          struct server_id server_id,
    1366             :                                          DATA_BLOB *data)
    1367             : {
    1368             :         size_t                  msg_count, i, num_groups;
    1369           0 :         char                    *buf = (char *)data->data;
    1370             :         char                    *msg_ptr;
    1371             :         size_t                  msg_len;
    1372             :         SPOOLSS_NOTIFY_MSG      notify;
    1373             :         SPOOLSS_NOTIFY_MSG_CTR  messages;
    1374             : 
    1375           0 :         if (data->length < 4) {
    1376           0 :                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
    1377           0 :                 return;
    1378             :         }
    1379             : 
    1380           0 :         msg_count = IVAL(buf, 0);
    1381           0 :         msg_ptr = buf + 4;
    1382             : 
    1383           0 :         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
    1384             : 
    1385           0 :         if (msg_count == 0) {
    1386           0 :                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
    1387           0 :                 return;
    1388             :         }
    1389             : 
    1390             :         /* initialize the container */
    1391             : 
    1392           0 :         ZERO_STRUCT( messages );
    1393           0 :         notify_msg_ctr_init( &messages );
    1394             : 
    1395             :         /*
    1396             :          * build message groups for each printer identified
    1397             :          * in a change_notify msg.  Remember that a PCN message
    1398             :          * includes the handle returned for the srv_spoolss_replyopenprinter()
    1399             :          * call.  Therefore messages are grouped according to printer handle.
    1400             :          */
    1401             : 
    1402           0 :         for ( i=0; i<msg_count; i++ ) {
    1403             :                 struct timeval msg_tv;
    1404             : 
    1405           0 :                 if (msg_ptr + 4 - buf > data->length) {
    1406           0 :                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
    1407           0 :                         return;
    1408             :                 }
    1409             : 
    1410           0 :                 msg_len = IVAL(msg_ptr,0);
    1411           0 :                 msg_ptr += 4;
    1412             : 
    1413           0 :                 if (msg_ptr + msg_len - buf > data->length) {
    1414           0 :                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
    1415           0 :                         return;
    1416             :                 }
    1417             : 
    1418             :                 /* unpack messages */
    1419             : 
    1420           0 :                 ZERO_STRUCT( notify );
    1421           0 :                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
    1422           0 :                 msg_ptr += msg_len;
    1423             : 
    1424             :                 /* add to correct list in container */
    1425             : 
    1426           0 :                 notify_msg_ctr_addmsg( &messages, &notify );
    1427             : 
    1428             :                 /* free memory that might have been allocated by notify2_unpack_msg() */
    1429             : 
    1430           0 :                 if ( notify.len != 0 )
    1431           0 :                         SAFE_FREE( notify.notify.data );
    1432             :         }
    1433             : 
    1434             :         /* process each group of messages */
    1435             : 
    1436           0 :         num_groups = notify_msg_ctr_numgroups( &messages );
    1437           0 :         for ( i=0; i<num_groups; i++ )
    1438           0 :                 send_notify2_changes( &messages, i );
    1439             : 
    1440             : 
    1441             :         /* cleanup */
    1442             : 
    1443           0 :         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
    1444             :                 (uint32_t)msg_count ));
    1445             : 
    1446           0 :         notify_msg_ctr_destroy( &messages );
    1447             : 
    1448           0 :         return;
    1449             : }
    1450             : 
    1451             : /********************************************************************
    1452             :  Send a message to ourself about new driver being installed
    1453             :  so we can upgrade the information for each printer bound to this
    1454             :  driver
    1455             :  ********************************************************************/
    1456             : 
    1457           0 : static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
    1458             :                                             struct messaging_context *msg_ctx)
    1459             : {
    1460           0 :         int len = strlen(drivername);
    1461             : 
    1462           0 :         if (!len)
    1463           0 :                 return false;
    1464             : 
    1465           0 :         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
    1466             :                 drivername));
    1467             : 
    1468           0 :         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
    1469             :                            MSG_PRINTER_DRVUPGRADE,
    1470           0 :                            (const uint8_t *)drivername, len+1);
    1471             : 
    1472           0 :         return true;
    1473             : }
    1474             : 
    1475           1 : void srv_spoolss_cleanup(void)
    1476             : {
    1477             :         struct printer_session_counter *session_counter;
    1478             : 
    1479           2 :         for (session_counter = counter_list;
    1480           0 :              session_counter != NULL;
    1481           0 :              session_counter = counter_list) {
    1482           0 :                 DLIST_REMOVE(counter_list, session_counter);
    1483           0 :                 TALLOC_FREE(session_counter);
    1484             :         }
    1485           1 : }
    1486             : 
    1487             : /**********************************************************************
    1488             :  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
    1489             :  over all printers, upgrading ones as necessary
    1490             :  This is now *ONLY* called inside the background lpq updater. JRA.
    1491             :  **********************************************************************/
    1492             : 
    1493           0 : void do_drv_upgrade_printer(struct messaging_context *msg,
    1494             :                             void *private_data,
    1495             :                             uint32_t msg_type,
    1496             :                             struct server_id server_id,
    1497             :                             DATA_BLOB *data)
    1498             : {
    1499             :         TALLOC_CTX *tmp_ctx;
    1500           0 :         const struct auth_session_info *session_info = get_session_info_system();
    1501             :         struct spoolss_PrinterInfo2 *pinfo2;
    1502             :         WERROR result;
    1503             :         const char *drivername;
    1504             :         int snum;
    1505           0 :         int n_services = lp_numservices();
    1506           0 :         struct dcerpc_binding_handle *b = NULL;
    1507             : 
    1508           0 :         tmp_ctx = talloc_new(NULL);
    1509           0 :         if (!tmp_ctx) return;
    1510             : 
    1511           0 :         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
    1512           0 :         if (!drivername) {
    1513           0 :                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
    1514           0 :                 goto done;
    1515             :         }
    1516             : 
    1517           0 :         DEBUG(10, ("do_drv_upgrade_printer: "
    1518             :                    "Got message for new driver [%s]\n", drivername));
    1519             : 
    1520             :         /* Iterate the printer list */
    1521             : 
    1522           0 :         for (snum = 0; snum < n_services; snum++) {
    1523           0 :                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
    1524           0 :                         continue;
    1525             :                 }
    1526             : 
    1527             :                 /* ignore [printers] share */
    1528           0 :                 if (strequal(lp_const_servicename(snum), "printers")) {
    1529           0 :                         continue;
    1530             :                 }
    1531             : 
    1532           0 :                 if (b == NULL) {
    1533           0 :                         result = winreg_printer_binding_handle(tmp_ctx,
    1534             :                                                                session_info,
    1535             :                                                                msg,
    1536             :                                                                &b);
    1537           0 :                         if (!W_ERROR_IS_OK(result)) {
    1538           0 :                                 break;
    1539             :                         }
    1540             :                 }
    1541             : 
    1542           0 :                 result = winreg_get_printer(tmp_ctx, b,
    1543             :                                             lp_const_servicename(snum),
    1544             :                                             &pinfo2);
    1545             : 
    1546           0 :                 if (!W_ERROR_IS_OK(result)) {
    1547           0 :                         continue;
    1548             :                 }
    1549             : 
    1550           0 :                 if (!pinfo2->drivername) {
    1551           0 :                         continue;
    1552             :                 }
    1553             : 
    1554           0 :                 if (strcmp(drivername, pinfo2->drivername) != 0) {
    1555           0 :                         continue;
    1556             :                 }
    1557             : 
    1558           0 :                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
    1559             : 
    1560             :                 /* all we care about currently is the change_id */
    1561           0 :                 result = winreg_printer_update_changeid(tmp_ctx, b,
    1562           0 :                                                         pinfo2->printername);
    1563             : 
    1564           0 :                 if (!W_ERROR_IS_OK(result)) {
    1565           0 :                         DEBUG(3, ("do_drv_upgrade_printer: "
    1566             :                                   "Failed to update changeid [%s]\n",
    1567             :                                   win_errstr(result)));
    1568             :                 }
    1569             :         }
    1570             : 
    1571             :         /* all done */
    1572           0 : done:
    1573           0 :         talloc_free(tmp_ctx);
    1574             : }
    1575             : 
    1576             : /********************************************************************
    1577             :  Update the cache for all printq's with a registered client
    1578             :  connection
    1579             :  ********************************************************************/
    1580             : 
    1581        1054 : void update_monitored_printq_cache(struct messaging_context *msg_ctx)
    1582             : {
    1583        1054 :         struct printer_handle *printer = printers_list;
    1584             :         int snum;
    1585             : 
    1586             :         /* loop through all printers and update the cache where
    1587             :            a client is connected */
    1588        1793 :         while (printer) {
    1589           9 :                 if ((printer->printer_type == SPLHND_PRINTER) &&
    1590           4 :                     ((printer->notify.cli_chan != NULL) &&
    1591           0 :                      (printer->notify.cli_chan->active_connections > 0))) {
    1592           0 :                         snum = print_queue_snum(printer->sharename);
    1593           0 :                         print_queue_status(msg_ctx, snum, NULL, NULL);
    1594             :                 }
    1595             : 
    1596           5 :                 printer = printer->next;
    1597             :         }
    1598             : 
    1599        1054 :         return;
    1600             : }
    1601             : 
    1602             : /****************************************************************
    1603             :  _spoolss_OpenPrinter
    1604             : ****************************************************************/
    1605             : 
    1606         166 : WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
    1607             :                             struct spoolss_OpenPrinter *r)
    1608             : {
    1609             :         struct spoolss_OpenPrinterEx e;
    1610             :         struct spoolss_UserLevel1 level1;
    1611             :         WERROR werr;
    1612             : 
    1613         166 :         ZERO_STRUCT(level1);
    1614             : 
    1615         166 :         e.in.printername        = r->in.printername;
    1616         166 :         e.in.datatype           = r->in.datatype;
    1617         166 :         e.in.devmode_ctr        = r->in.devmode_ctr;
    1618         166 :         e.in.access_mask        = r->in.access_mask;
    1619         166 :         e.in.userlevel_ctr.level                = 1;
    1620         166 :         e.in.userlevel_ctr.user_info.level1     = &level1;
    1621             : 
    1622         166 :         e.out.handle            = r->out.handle;
    1623             : 
    1624         166 :         werr = _spoolss_OpenPrinterEx(p, &e);
    1625             : 
    1626         166 :         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
    1627             :                 /* OpenPrinterEx returns this for a bad
    1628             :                  * printer name. We must return WERR_INVALID_PRINTER_NAME
    1629             :                  * instead.
    1630             :                  */
    1631           4 :                 werr = WERR_INVALID_PRINTER_NAME;
    1632             :         }
    1633             : 
    1634         166 :         return werr;
    1635             : }
    1636             : 
    1637        2830 : static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
    1638             :                               struct spoolss_DeviceMode *orig,
    1639             :                               struct spoolss_DeviceMode **dest)
    1640             : {
    1641             :         struct spoolss_DeviceMode *dm;
    1642             : 
    1643        2830 :         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
    1644        2830 :         if (!dm) {
    1645           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1646             :         }
    1647             : 
    1648             :         /* copy all values, then duplicate strings and structs */
    1649        2830 :         *dm = *orig;
    1650             : 
    1651        2830 :         dm->devicename = talloc_strdup(dm, orig->devicename);
    1652        2830 :         if (!dm->devicename) {
    1653           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1654             :         }
    1655        2830 :         dm->formname = talloc_strdup(dm, orig->formname);
    1656        2830 :         if (!dm->formname) {
    1657           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1658             :         }
    1659        2830 :         if (orig->driverextra_data.data) {
    1660        1768 :                 dm->driverextra_data.data =
    1661        1768 :                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
    1662             :                                         orig->driverextra_data.length);
    1663        1768 :                 if (!dm->driverextra_data.data) {
    1664           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1665             :                 }
    1666             :         }
    1667             : 
    1668        2830 :         *dest = dm;
    1669        2830 :         return WERR_OK;
    1670             : }
    1671             : 
    1672             : /****************************************************************
    1673             :  _spoolss_OpenPrinterEx
    1674             : ****************************************************************/
    1675             : 
    1676         950 : WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
    1677             :                               struct spoolss_OpenPrinterEx *r)
    1678             : {
    1679             :         int snum;
    1680             :         char *raddr;
    1681             :         char *rhost;
    1682         950 :         struct printer_handle *Printer=NULL;
    1683             :         WERROR result;
    1684             :         int rc;
    1685             : 
    1686         950 :         if (!r->in.printername) {
    1687           0 :                 return WERR_INVALID_PARAMETER;
    1688             :         }
    1689             : 
    1690         950 :         if (!*r->in.printername) {
    1691           8 :                 return WERR_INVALID_PARAMETER;
    1692             :         }
    1693             : 
    1694         942 :         if (r->in.userlevel_ctr.level > 3) {
    1695           0 :                 return WERR_INVALID_PARAMETER;
    1696             :         }
    1697        1618 :         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
    1698        1594 :             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
    1699         918 :             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
    1700          24 :                 return WERR_INVALID_PARAMETER;
    1701             :         }
    1702             : 
    1703             :         /*
    1704             :          * The printcap printer share inventory is updated on client
    1705             :          * enumeration. For clients that do not perform enumeration prior to
    1706             :          * access, such as cupssmbadd, we reinitialise the printer share
    1707             :          * inventory on open as well.
    1708             :          */
    1709         918 :         become_root();
    1710         918 :         delete_and_reload_printers();
    1711         918 :         unbecome_root();
    1712             : 
    1713             :         /* some sanity check because you can open a printer or a print server */
    1714             :         /* aka: \\server\printer or \\server */
    1715             : 
    1716         918 :         DEBUGADD(3,("checking name: %s\n", r->in.printername));
    1717             : 
    1718         918 :         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
    1719         918 :         if (!W_ERROR_IS_OK(result)) {
    1720         332 :                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
    1721             :                         "for printer %s\n", r->in.printername));
    1722         332 :                 ZERO_STRUCTP(r->out.handle);
    1723         332 :                 return result;
    1724             :         }
    1725             : 
    1726         586 :         Printer = find_printer_index_by_hnd(p, r->out.handle);
    1727         586 :         if ( !Printer ) {
    1728           0 :                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
    1729             :                         "handle we created for printer %s\n", r->in.printername));
    1730           0 :                 close_printer_handle(p, r->out.handle);
    1731           0 :                 ZERO_STRUCTP(r->out.handle);
    1732           0 :                 return WERR_INVALID_PARAMETER;
    1733             :         }
    1734             : 
    1735             :         /*
    1736             :          * First case: the user is opening the print server:
    1737             :          *
    1738             :          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
    1739             :          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
    1740             :          *
    1741             :          * Then both Win2k and WinNT clients try an OpenPrinterEx with
    1742             :          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
    1743             :          * or if the user is listed in the smb.conf printer admin parameter.
    1744             :          *
    1745             :          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
    1746             :          * client view printer folder, but does not show the MSAPW.
    1747             :          *
    1748             :          * Note: this test needs code to check access rights here too. Jeremy
    1749             :          * could you look at this?
    1750             :          *
    1751             :          * Second case: the user is opening a printer:
    1752             :          * NT doesn't let us connect to a printer if the connecting user
    1753             :          * doesn't have print permission.
    1754             :          *
    1755             :          * Third case: user is opening a Port Monitor
    1756             :          * access checks same as opening a handle to the print server.
    1757             :          */
    1758             : 
    1759         586 :         switch (Printer->printer_type )
    1760             :         {
    1761          88 :         case SPLHND_SERVER:
    1762             :         case SPLHND_PORTMON_TCP:
    1763             :         case SPLHND_PORTMON_LOCAL:
    1764             :                 /* Printserver handles use global struct... */
    1765             : 
    1766          88 :                 snum = -1;
    1767             : 
    1768          88 :                 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
    1769          62 :                         r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
    1770          62 :                         r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
    1771             :                 }
    1772             : 
    1773             :                 /* Map standard access rights to object specific access rights */
    1774             : 
    1775          88 :                 se_map_standard(&r->in.access_mask,
    1776             :                                 &printserver_std_mapping);
    1777             : 
    1778             :                 /* Deny any object specific bits that don't apply to print
    1779             :                    servers (i.e printer and job specific bits) */
    1780             : 
    1781          88 :                 r->in.access_mask &= SEC_MASK_SPECIFIC;
    1782             : 
    1783          88 :                 if (r->in.access_mask &
    1784             :                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
    1785           0 :                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
    1786           0 :                         close_printer_handle(p, r->out.handle);
    1787           0 :                         ZERO_STRUCTP(r->out.handle);
    1788           0 :                         return WERR_ACCESS_DENIED;
    1789             :                 }
    1790             : 
    1791             :                 /* Allow admin access */
    1792             : 
    1793          88 :                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
    1794             :                 {
    1795          66 :                         if (!lp_show_add_printer_wizard()) {
    1796           0 :                                 close_printer_handle(p, r->out.handle);
    1797           0 :                                 ZERO_STRUCTP(r->out.handle);
    1798           0 :                                 return WERR_ACCESS_DENIED;
    1799             :                         }
    1800             : 
    1801             :                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    1802             :                            and not a printer admin, then fail */
    1803             : 
    1804          67 :                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
    1805           2 :                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
    1806           0 :                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
    1807           0 :                                                 p->session_info->security_token)) {
    1808           0 :                                 close_printer_handle(p, r->out.handle);
    1809           0 :                                 ZERO_STRUCTP(r->out.handle);
    1810           0 :                                 DEBUG(3,("access DENIED as user is not root, "
    1811             :                                         "has no printoperator privilege and is "
    1812             :                                         "not a member of the printoperator builtin group\n"));
    1813           0 :                                 return WERR_ACCESS_DENIED;
    1814             :                         }
    1815             : 
    1816          66 :                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
    1817             :                 }
    1818             :                 else
    1819             :                 {
    1820          22 :                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
    1821             :                 }
    1822             : 
    1823          88 :                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
    1824             :                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
    1825             : 
    1826          88 :                 break;
    1827             : 
    1828         498 :         case SPLHND_PRINTER:
    1829             :                 /* NT doesn't let us connect to a printer if the connecting user
    1830             :                    doesn't have print permission.  */
    1831             : 
    1832         498 :                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
    1833           0 :                         close_printer_handle(p, r->out.handle);
    1834           0 :                         ZERO_STRUCTP(r->out.handle);
    1835           0 :                         return WERR_INVALID_HANDLE;
    1836             :                 }
    1837             : 
    1838         498 :                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
    1839         164 :                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
    1840             :                 }
    1841             : 
    1842         498 :                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
    1843             : 
    1844             :                 /* map an empty access mask to the minimum access mask */
    1845         498 :                 if (r->in.access_mask == 0x0)
    1846         294 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1847             : 
    1848             :                 /*
    1849             :                  * If we are not serving the printer driver for this printer,
    1850             :                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
    1851             :                  * will keep NT clients happy  --jerry
    1852             :                  */
    1853             : 
    1854         498 :                 if (lp_use_client_driver(snum)
    1855           0 :                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
    1856             :                 {
    1857           0 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1858             :                 }
    1859             : 
    1860             :                 /* check smb.conf parameters and the the sec_desc */
    1861         498 :                 raddr = tsocket_address_inet_addr_string(p->remote_address,
    1862             :                                                          p->mem_ctx);
    1863         498 :                 if (raddr == NULL) {
    1864           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1865             :                 }
    1866             : 
    1867         498 :                 rc = get_remote_hostname(p->remote_address,
    1868             :                                          &rhost,
    1869             :                                          p->mem_ctx);
    1870         498 :                 if (rc < 0) {
    1871           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1872             :                 }
    1873         498 :                 if (strequal(rhost, "UNKNOWN")) {
    1874           0 :                         rhost = raddr;
    1875             :                 }
    1876             : 
    1877         498 :                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
    1878             :                                   rhost, raddr)) {
    1879           0 :                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
    1880           0 :                         ZERO_STRUCTP(r->out.handle);
    1881           0 :                         return WERR_ACCESS_DENIED;
    1882             :                 }
    1883             : 
    1884         867 :                 if (!user_ok_token(p->session_info->unix_info->unix_name,
    1885         498 :                                    p->session_info->info->domain_name,
    1886         867 :                                    p->session_info->security_token, snum) ||
    1887         498 :                     !W_ERROR_IS_OK(print_access_check(p->session_info,
    1888             :                                                       p->msg_ctx,
    1889             :                                                       snum,
    1890             :                                                       r->in.access_mask))) {
    1891           0 :                         DEBUG(3, ("access DENIED for printer open\n"));
    1892           0 :                         close_printer_handle(p, r->out.handle);
    1893           0 :                         ZERO_STRUCTP(r->out.handle);
    1894           0 :                         return WERR_ACCESS_DENIED;
    1895             :                 }
    1896             : 
    1897         498 :                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
    1898           4 :                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
    1899           4 :                         close_printer_handle(p, r->out.handle);
    1900           4 :                         ZERO_STRUCTP(r->out.handle);
    1901           4 :                         return WERR_ACCESS_DENIED;
    1902             :                 }
    1903             : 
    1904         494 :                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
    1905         164 :                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
    1906             :                 else
    1907         330 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1908             : 
    1909         494 :                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
    1910             :                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
    1911             : 
    1912         494 :                 winreg_create_printer_internal(p->mem_ctx,
    1913             :                                       get_session_info_system(),
    1914             :                                       p->msg_ctx,
    1915             :                                       lp_const_servicename(snum));
    1916             : 
    1917         494 :                 break;
    1918             : 
    1919           0 :         default:
    1920             :                 /* sanity check to prevent programmer error */
    1921           0 :                 ZERO_STRUCTP(r->out.handle);
    1922           0 :                 return WERR_INVALID_HANDLE;
    1923             :         }
    1924             : 
    1925         582 :         Printer->access_granted = r->in.access_mask;
    1926             : 
    1927             :         /*
    1928             :          * If the client sent a devmode in the OpenPrinter() call, then
    1929             :          * save it here in case we get a job submission on this handle
    1930             :          */
    1931             : 
    1932         582 :          if ((Printer->printer_type != SPLHND_SERVER)
    1933         494 :           && (r->in.devmode_ctr.devmode != NULL)) {
    1934           8 :                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
    1935             :                                 &Printer->devmode);
    1936             :          }
    1937             : 
    1938         582 :         return WERR_OK;
    1939             : }
    1940             : 
    1941             : /****************************************************************
    1942             :  _spoolss_ClosePrinter
    1943             : ****************************************************************/
    1944             : 
    1945         582 : WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
    1946             :                              struct spoolss_ClosePrinter *r)
    1947             : {
    1948         582 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    1949             : 
    1950         582 :         if (Printer && Printer->document_started) {
    1951             :                 struct spoolss_EndDocPrinter e;
    1952             : 
    1953          28 :                 e.in.handle = r->in.handle;
    1954             : 
    1955          28 :                 _spoolss_EndDocPrinter(p, &e);
    1956             :         }
    1957             : 
    1958         578 :         if (!close_printer_handle(p, r->in.handle))
    1959           0 :                 return WERR_INVALID_HANDLE;
    1960             : 
    1961             :         /* clear the returned printer handle.  Observed behavior
    1962             :            from Win2k server.  Don't think this really matters.
    1963             :            Previous code just copied the value of the closed
    1964             :            handle.    --jerry */
    1965             : 
    1966         578 :         ZERO_STRUCTP(r->out.handle);
    1967             : 
    1968         578 :         return WERR_OK;
    1969             : }
    1970             : 
    1971             : /****************************************************************
    1972             :  _spoolss_DeletePrinter
    1973             : ****************************************************************/
    1974             : 
    1975          16 : WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
    1976             :                               struct spoolss_DeletePrinter *r)
    1977             : {
    1978          16 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    1979             :         WERROR result;
    1980             :         int snum;
    1981             : 
    1982          16 :         if (Printer && Printer->document_started) {
    1983             :                 struct spoolss_EndDocPrinter e;
    1984             : 
    1985           0 :                 e.in.handle = r->in.handle;
    1986             : 
    1987           0 :                 _spoolss_EndDocPrinter(p, &e);
    1988             :         }
    1989             : 
    1990          16 :         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
    1991          16 :                 winreg_delete_printer_key_internal(p->mem_ctx,
    1992             :                                           get_session_info_system(),
    1993             :                                           p->msg_ctx,
    1994             :                                           lp_const_servicename(snum),
    1995             :                                           "");
    1996             :         }
    1997             : 
    1998          16 :         result = delete_printer_handle(p, r->in.handle);
    1999             : 
    2000          12 :         return result;
    2001             : }
    2002             : 
    2003             : /*******************************************************************
    2004             :  * static function to lookup the version id corresponding to an
    2005             :  * long architecture string
    2006             :  ******************************************************************/
    2007             : 
    2008             : static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
    2009             :                                    SPOOLSS_DRIVER_VERSION_NT35,
    2010             :                                    SPOOLSS_DRIVER_VERSION_NT4,
    2011             :                                    SPOOLSS_DRIVER_VERSION_200X,
    2012             :                                    -1};
    2013             : 
    2014           0 : static int get_version_id(const char *arch)
    2015             : {
    2016             :         int i;
    2017             : 
    2018           0 :         for (i=0; archi_table[i].long_archi != NULL; i++)
    2019             :         {
    2020           0 :                 if (strcmp(arch, archi_table[i].long_archi) == 0)
    2021           0 :                         return (archi_table[i].version);
    2022             :         }
    2023             : 
    2024           0 :         return -1;
    2025             : }
    2026             : 
    2027             : /****************************************************************
    2028             :  _spoolss_DeletePrinterDriver
    2029             : ****************************************************************/
    2030             : 
    2031           0 : WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
    2032             :                                     struct spoolss_DeletePrinterDriver *r)
    2033             : {
    2034             : 
    2035           0 :         struct spoolss_DriverInfo8 *info = NULL;
    2036             :         int                             version;
    2037             :         WERROR                          status;
    2038             :         struct dcerpc_binding_handle *b;
    2039           0 :         TALLOC_CTX *tmp_ctx = NULL;
    2040             :         int i;
    2041             :         bool found;
    2042             : 
    2043             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    2044             :            and not a printer admin, then fail */
    2045             : 
    2046           0 :         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
    2047           0 :             !security_token_has_privilege(p->session_info->security_token,
    2048             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    2049           0 :                 return WERR_ACCESS_DENIED;
    2050             :         }
    2051             : 
    2052           0 :         if (r->in.architecture == NULL || r->in.driver == NULL) {
    2053           0 :                 return WERR_INVALID_ENVIRONMENT;
    2054             :         }
    2055             : 
    2056             :         /* check that we have a valid driver name first */
    2057             : 
    2058           0 :         if ((version = get_version_id(r->in.architecture)) == -1) {
    2059           0 :                 return WERR_INVALID_ENVIRONMENT;
    2060             :         }
    2061             : 
    2062           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    2063           0 :         if (!tmp_ctx) {
    2064           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2065             :         }
    2066             : 
    2067           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    2068             :                                                get_session_info_system(),
    2069             :                                                p->msg_ctx,
    2070             :                                                &b);
    2071           0 :         if (!W_ERROR_IS_OK(status)) {
    2072           0 :                 goto done;
    2073             :         }
    2074             : 
    2075           0 :         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
    2076           0 :                 status = winreg_get_driver(tmp_ctx, b,
    2077             :                                            r->in.architecture, r->in.driver,
    2078           0 :                                            drv_cversion[i], &info);
    2079           0 :                 if (!W_ERROR_IS_OK(status)) {
    2080           0 :                         DEBUG(5, ("skipping del of driver with version %d\n",
    2081             :                                   drv_cversion[i]));
    2082           0 :                         continue;
    2083             :                 }
    2084           0 :                 found = true;
    2085             : 
    2086           0 :                 if (printer_driver_in_use(tmp_ctx, b, info)) {
    2087           0 :                         status = WERR_PRINTER_DRIVER_IN_USE;
    2088           0 :                         goto done;
    2089             :                 }
    2090             : 
    2091           0 :                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
    2092           0 :                 if (!W_ERROR_IS_OK(status)) {
    2093           0 :                         DEBUG(0, ("failed del of driver with version %d\n",
    2094             :                                   drv_cversion[i]));
    2095           0 :                         goto done;
    2096             :                 }
    2097             :         }
    2098           0 :         if (found == false) {
    2099           0 :                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
    2100           0 :                 status = WERR_UNKNOWN_PRINTER_DRIVER;
    2101             :         } else {
    2102           0 :                 status = WERR_OK;
    2103             :         }
    2104             : 
    2105           0 : done:
    2106           0 :         talloc_free(tmp_ctx);
    2107             : 
    2108           0 :         return status;
    2109             : }
    2110             : 
    2111           0 : static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
    2112             :                                   struct pipes_struct *p,
    2113             :                                   struct spoolss_DeletePrinterDriverEx *r,
    2114             :                                   struct dcerpc_binding_handle *b,
    2115             :                                   struct spoolss_DriverInfo8 *info)
    2116             : {
    2117             :         WERROR status;
    2118             :         bool delete_files;
    2119             : 
    2120           0 :         if (printer_driver_in_use(mem_ctx, b, info)) {
    2121           0 :                 status = WERR_PRINTER_DRIVER_IN_USE;
    2122           0 :                 goto done;
    2123             :         }
    2124             : 
    2125             :         /*
    2126             :          * we have a couple of cases to consider.
    2127             :          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
    2128             :          *     then the delete should fail if **any** files overlap with
    2129             :          *     other drivers
    2130             :          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
    2131             :          *     non-overlapping files
    2132             :          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
    2133             :          *     are set, then do not delete any files
    2134             :          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
    2135             :          */
    2136             : 
    2137           0 :         delete_files = r->in.delete_flags
    2138           0 :                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
    2139             : 
    2140             : 
    2141           0 :         if (delete_files) {
    2142           0 :                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
    2143           0 :                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
    2144           0 :                         status = WERR_PRINTER_DRIVER_IN_USE;
    2145           0 :                         goto done;
    2146             :                 }
    2147             :                 /*
    2148             :                  * printer_driver_files_in_use() has trimmed overlapping files
    2149             :                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
    2150             :                  */
    2151             :         }
    2152             : 
    2153             : 
    2154           0 :         status = winreg_del_driver(mem_ctx, b, info, info->version);
    2155           0 :         if (!W_ERROR_IS_OK(status)) {
    2156           0 :                 goto done;
    2157             :         }
    2158             : 
    2159             :         /*
    2160             :          * now delete any associated files if delete_files is
    2161             :          * true. Even if this part failes, we return succes
    2162             :          * because the driver doesn not exist any more
    2163             :          */
    2164           0 :         if (delete_files) {
    2165           0 :                 delete_driver_files(p->session_info, info);
    2166             :         }
    2167             : 
    2168           0 : done:
    2169           0 :         return status;
    2170             : }
    2171             : 
    2172             : /****************************************************************
    2173             :  _spoolss_DeletePrinterDriverEx
    2174             : ****************************************************************/
    2175             : 
    2176           0 : WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
    2177             :                                       struct spoolss_DeletePrinterDriverEx *r)
    2178             : {
    2179           0 :         struct spoolss_DriverInfo8 *info = NULL;
    2180             :         WERROR                          status;
    2181             :         struct dcerpc_binding_handle *b;
    2182           0 :         TALLOC_CTX *tmp_ctx = NULL;
    2183             :         int i;
    2184             :         bool found;
    2185             : 
    2186             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    2187             :            and not a printer admin, then fail */
    2188             : 
    2189           0 :         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
    2190           0 :             !security_token_has_privilege(p->session_info->security_token,
    2191             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    2192           0 :                 return WERR_ACCESS_DENIED;
    2193             :         }
    2194             : 
    2195           0 :         if (r->in.architecture == NULL || r->in.driver == NULL) {
    2196           0 :                 return WERR_INVALID_ENVIRONMENT;
    2197             :         }
    2198             : 
    2199             :         /* check that we have a valid driver name first */
    2200           0 :         if (get_version_id(r->in.architecture) == -1) {
    2201             :                 /* this is what NT returns */
    2202           0 :                 return WERR_INVALID_ENVIRONMENT;
    2203             :         }
    2204             : 
    2205           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    2206           0 :         if (!tmp_ctx) {
    2207           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2208             :         }
    2209             : 
    2210           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    2211             :                                                get_session_info_system(),
    2212             :                                                p->msg_ctx,
    2213             :                                                &b);
    2214           0 :         if (!W_ERROR_IS_OK(status)) {
    2215           0 :                 goto done;
    2216             :         }
    2217             : 
    2218           0 :         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
    2219           0 :                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
    2220           0 :                  && (drv_cversion[i] != r->in.version)) {
    2221           0 :                         continue;
    2222             :                 }
    2223             : 
    2224             :                 /* check if a driver with this version exists before delete */
    2225           0 :                 status = winreg_get_driver(tmp_ctx, b,
    2226             :                                            r->in.architecture, r->in.driver,
    2227           0 :                                            drv_cversion[i], &info);
    2228           0 :                 if (!W_ERROR_IS_OK(status)) {
    2229           0 :                         DEBUG(5, ("skipping del of driver with version %d\n",
    2230             :                                   drv_cversion[i]));
    2231           0 :                         continue;
    2232             :                 }
    2233           0 :                 found = true;
    2234             : 
    2235           0 :                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
    2236           0 :                 if (!W_ERROR_IS_OK(status)) {
    2237           0 :                         DEBUG(0, ("failed to delete driver with version %d\n",
    2238             :                                   drv_cversion[i]));
    2239           0 :                         goto done;
    2240             :                 }
    2241             :         }
    2242           0 :         if (found == false) {
    2243           0 :                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
    2244           0 :                 status = WERR_UNKNOWN_PRINTER_DRIVER;
    2245             :         } else {
    2246           0 :                 status = WERR_OK;
    2247             :         }
    2248             : 
    2249           0 : done:
    2250           0 :         talloc_free(tmp_ctx);
    2251           0 :         return status;
    2252             : }
    2253             : 
    2254             : 
    2255             : /********************************************************************
    2256             :  GetPrinterData on a printer server Handle.
    2257             : ********************************************************************/
    2258             : 
    2259         348 : static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
    2260             :                                             const char *value,
    2261             :                                             enum winreg_Type *type,
    2262             :                                             union spoolss_PrinterData *data)
    2263             : {
    2264         348 :         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
    2265             : 
    2266         348 :         if (!strcasecmp_m(value, "W3SvcInstalled")) {
    2267          28 :                 *type = REG_DWORD;
    2268          28 :                 SIVAL(&data->value, 0, 0x00);
    2269          28 :                 return WERR_OK;
    2270             :         }
    2271             : 
    2272         320 :         if (!strcasecmp_m(value, "BeepEnabled")) {
    2273          24 :                 *type = REG_DWORD;
    2274          24 :                 SIVAL(&data->value, 0, 0x00);
    2275          24 :                 return WERR_OK;
    2276             :         }
    2277             : 
    2278         296 :         if (!strcasecmp_m(value, "EventLog")) {
    2279          24 :                 *type = REG_DWORD;
    2280             :                 /* formally was 0x1b */
    2281          24 :                 SIVAL(&data->value, 0, 0x00);
    2282          24 :                 return WERR_OK;
    2283             :         }
    2284             : 
    2285         272 :         if (!strcasecmp_m(value, "NetPopup")) {
    2286           0 :                 *type = REG_DWORD;
    2287           0 :                 SIVAL(&data->value, 0, 0x00);
    2288           0 :                 return WERR_OK;
    2289             :         }
    2290             : 
    2291         272 :         if (!strcasecmp_m(value, "MajorVersion")) {
    2292          28 :                 *type = REG_DWORD;
    2293             : 
    2294             :                 /* Windows NT 4.0 seems to not allow uploading of drivers
    2295             :                    to a server that reports 0x3 as the MajorVersion.
    2296             :                    need to investigate more how Win2k gets around this .
    2297             :                    -- jerry */
    2298             : 
    2299          28 :                 if (RA_WINNT == get_remote_arch()) {
    2300           0 :                         SIVAL(&data->value, 0, 0x02);
    2301             :                 } else {
    2302          28 :                         SIVAL(&data->value, 0, 0x03);
    2303             :                 }
    2304             : 
    2305          28 :                 return WERR_OK;
    2306             :         }
    2307             : 
    2308         244 :         if (!strcasecmp_m(value, "MinorVersion")) {
    2309          24 :                 *type = REG_DWORD;
    2310          24 :                 SIVAL(&data->value, 0, 0x00);
    2311          24 :                 return WERR_OK;
    2312             :         }
    2313             : 
    2314             :         /* REG_BINARY
    2315             :          *  uint32_t size        = 0x114
    2316             :          *  uint32_t major       = 5
    2317             :          *  uint32_t minor       = [0|1]
    2318             :          *  uint32_t build       = [2195|2600]
    2319             :          *  extra unicode string = e.g. "Service Pack 3"
    2320             :          */
    2321         220 :         if (!strcasecmp_m(value, "OSVersion")) {
    2322             :                 DATA_BLOB blob;
    2323             :                 enum ndr_err_code ndr_err;
    2324             :                 struct spoolss_OSVersion os;
    2325             : 
    2326             :                 /*
    2327             :                  * Set the default OSVersion to:
    2328             :                  *
    2329             :                  *     Windows Server 2003R2 SP2 (5.2.3790)
    2330             :                  *
    2331             :                  * used to be Windows 2000 (5.0.2195)
    2332             :                  */
    2333          40 :                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2334             :                                                       "spoolss", "os_major",
    2335             :                                                       GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
    2336          40 :                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2337             :                                                       "spoolss", "os_minor",
    2338             :                                                       GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
    2339          40 :                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2340             :                                                       "spoolss", "os_build",
    2341             :                                                       GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
    2342          40 :                 os.extra_string         = ""; /* leave extra string empty */
    2343             : 
    2344          40 :                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
    2345             :                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
    2346          40 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    2347           0 :                         return WERR_GEN_FAILURE;
    2348             :                 }
    2349             : 
    2350          40 :                 if (DEBUGLEVEL >= 10) {
    2351           0 :                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
    2352             :                 }
    2353             : 
    2354          40 :                 *type = REG_BINARY;
    2355          40 :                 data->binary = blob;
    2356             : 
    2357          40 :                 return WERR_OK;
    2358             :         }
    2359             : 
    2360             : 
    2361         180 :         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
    2362          24 :                 *type = REG_SZ;
    2363             : 
    2364          24 :                 data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
    2365          24 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2366             : 
    2367          24 :                 return WERR_OK;
    2368             :         }
    2369             : 
    2370         156 :         if (!strcasecmp_m(value, "Architecture")) {
    2371         104 :                 *type = REG_SZ;
    2372         104 :                 data->string = talloc_strdup(mem_ctx,
    2373             :                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
    2374         104 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2375             : 
    2376         104 :                 return WERR_OK;
    2377             :         }
    2378             : 
    2379          52 :         if (!strcasecmp_m(value, "DsPresent")) {
    2380          24 :                 *type = REG_DWORD;
    2381             : 
    2382             :                 /* only show the publish check box if we are a
    2383             :                    member of a AD domain */
    2384             : 
    2385          24 :                 if (lp_security() == SEC_ADS) {
    2386           0 :                         SIVAL(&data->value, 0, 0x01);
    2387             :                 } else {
    2388          24 :                         SIVAL(&data->value, 0, 0x00);
    2389             :                 }
    2390          24 :                 return WERR_OK;
    2391             :         }
    2392             : 
    2393          28 :         if (!strcasecmp_m(value, "DNSMachineName")) {
    2394          24 :                 const char *hostname = get_mydnsfullname();
    2395             : 
    2396          24 :                 if (!hostname) {
    2397           0 :                         return WERR_FILE_NOT_FOUND;
    2398             :                 }
    2399             : 
    2400          24 :                 *type = REG_SZ;
    2401          24 :                 data->string = talloc_strdup(mem_ctx, hostname);
    2402          24 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2403             : 
    2404          24 :                 return WERR_OK;
    2405             :         }
    2406             : 
    2407           4 :         *type = REG_NONE;
    2408             : 
    2409           4 :         return WERR_INVALID_PARAMETER;
    2410             : }
    2411             : 
    2412             : /****************************************************************
    2413             :  _spoolss_GetPrinterData
    2414             : ****************************************************************/
    2415             : 
    2416         424 : WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
    2417             :                                struct spoolss_GetPrinterData *r)
    2418             : {
    2419             :         struct spoolss_GetPrinterDataEx r2;
    2420             : 
    2421         424 :         r2.in.handle            = r->in.handle;
    2422         424 :         r2.in.key_name          = "PrinterDriverData";
    2423         424 :         r2.in.value_name        = r->in.value_name;
    2424         424 :         r2.in.offered           = r->in.offered;
    2425         424 :         r2.out.type             = r->out.type;
    2426         424 :         r2.out.data             = r->out.data;
    2427         424 :         r2.out.needed           = r->out.needed;
    2428             : 
    2429         424 :         return _spoolss_GetPrinterDataEx(p, &r2);
    2430             : }
    2431             : 
    2432             : /*********************************************************
    2433             :  Connect to the client machine.
    2434             : **********************************************************/
    2435             : 
    2436           2 : static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
    2437             :                                       struct sockaddr_storage *client_ss, const char *remote_machine)
    2438             : {
    2439             :         NTSTATUS ret;
    2440             :         struct sockaddr_storage rm_addr;
    2441             :         char addr[INET6_ADDRSTRLEN];
    2442           2 :         struct cli_credentials *anon_creds = NULL;
    2443             : 
    2444           2 :         if ( is_zero_addr(client_ss) ) {
    2445           0 :                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
    2446             :                         remote_machine));
    2447           0 :                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
    2448           0 :                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
    2449           0 :                         return false;
    2450             :                 }
    2451           0 :                 print_sockaddr(addr, sizeof(addr), &rm_addr);
    2452             :         } else {
    2453           2 :                 rm_addr = *client_ss;
    2454           2 :                 print_sockaddr(addr, sizeof(addr), &rm_addr);
    2455           2 :                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
    2456             :                         addr));
    2457             :         }
    2458             : 
    2459           2 :         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
    2460           0 :                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
    2461             :                         addr));
    2462           0 :                 return false;
    2463             :         }
    2464             : 
    2465           2 :         anon_creds = cli_credentials_init_anon(NULL);
    2466           2 :         if (anon_creds == NULL) {
    2467           0 :                 DBG_ERR("cli_credentials_init_anon() failed\n");
    2468           0 :                 return false;
    2469             :         }
    2470             : 
    2471             :         /* setup the connection */
    2472           2 :         ret = cli_full_connection_creds( pp_cli, lp_netbios_name(), remote_machine,
    2473             :                 &rm_addr, 0, "IPC$", "IPC",
    2474             :                 anon_creds,
    2475             :                 CLI_FULL_CONNECTION_IPC);
    2476           2 :         TALLOC_FREE(anon_creds);
    2477           2 :         if ( !NT_STATUS_IS_OK( ret ) ) {
    2478           0 :                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
    2479             :                         remote_machine ));
    2480           0 :                 return false;
    2481             :         }
    2482             : 
    2483           2 :         if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
    2484           0 :                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
    2485           0 :                 cli_shutdown(*pp_cli);
    2486           0 :                 return false;
    2487             :         }
    2488             : 
    2489             :         /*
    2490             :          * Ok - we have an anonymous connection to the IPC$ share.
    2491             :          * Now start the NT Domain stuff :-).
    2492             :          */
    2493             : 
    2494           2 :         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
    2495           2 :         if (!NT_STATUS_IS_OK(ret)) {
    2496           0 :                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
    2497             :                         remote_machine, nt_errstr(ret)));
    2498           0 :                 cli_shutdown(*pp_cli);
    2499           0 :                 return false;
    2500             :         }
    2501             : 
    2502           2 :         return true;
    2503             : }
    2504             : 
    2505             : /***************************************************************************
    2506             :  Connect to the client.
    2507             : ****************************************************************************/
    2508             : 
    2509           2 : static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
    2510             :                                         uint32_t localprinter,
    2511             :                                         enum winreg_Type type,
    2512             :                                         struct policy_handle *handle,
    2513             :                                         struct notify_back_channel **_chan,
    2514             :                                         struct sockaddr_storage *client_ss,
    2515             :                                         struct messaging_context *msg_ctx)
    2516             : {
    2517             :         WERROR result;
    2518             :         NTSTATUS status;
    2519             :         struct notify_back_channel *chan;
    2520             : 
    2521           2 :         for (chan = back_channels; chan; chan = chan->next) {
    2522           0 :                 if (memcmp(&chan->client_address, client_ss,
    2523             :                            sizeof(struct sockaddr_storage)) == 0) {
    2524           0 :                         break;
    2525             :                 }
    2526             :         }
    2527             : 
    2528             :         /*
    2529             :          * If it's the first connection, contact the client
    2530             :          * and connect to the IPC$ share anonymously
    2531             :          */
    2532           2 :         if (!chan) {
    2533             :                 fstring unix_printer;
    2534             : 
    2535             :                 /* the +2 is to strip the leading 2 backslashs */
    2536           2 :                 fstrcpy(unix_printer, printer + 2);
    2537             : 
    2538           2 :                 chan = talloc_zero(NULL, struct notify_back_channel);
    2539           2 :                 if (!chan) {
    2540           0 :                         return false;
    2541             :                 }
    2542           2 :                 chan->client_address = *client_ss;
    2543             : 
    2544           2 :                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
    2545           0 :                         TALLOC_FREE(chan);
    2546           0 :                         return false;
    2547             :                 }
    2548             : 
    2549           2 :                 DLIST_ADD(back_channels, chan);
    2550             : 
    2551           2 :                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
    2552             :                                    receive_notify2_message_list);
    2553             :         }
    2554             : 
    2555           3 :         if (chan->cli_pipe == NULL ||
    2556           2 :             chan->cli_pipe->binding_handle == NULL) {
    2557           0 :                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
    2558             :                         "NULL %s for printer %s\n",
    2559             :                         chan->cli_pipe == NULL ?
    2560             :                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
    2561             :                         printer));
    2562           0 :                 return false;
    2563             :         }
    2564             : 
    2565             :         /*
    2566             :          * Tell the specific printing tdb we want messages for this printer
    2567             :          * by registering our PID.
    2568             :          */
    2569             : 
    2570           2 :         if (!print_notify_register_pid(snum)) {
    2571           0 :                 DEBUG(0, ("Failed to register our pid for printer %s\n",
    2572             :                           printer));
    2573             :         }
    2574             : 
    2575           2 :         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
    2576             :                                                  talloc_tos(),
    2577             :                                                  printer,
    2578             :                                                  localprinter,
    2579             :                                                  type,
    2580             :                                                  0,
    2581             :                                                  NULL,
    2582             :                                                  handle,
    2583             :                                                  &result);
    2584           2 :         if (!NT_STATUS_IS_OK(status)) {
    2585           0 :                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
    2586           0 :                 result = ntstatus_to_werror(status);
    2587           2 :         } else if (!W_ERROR_IS_OK(result)) {
    2588           0 :                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
    2589             :         }
    2590             : 
    2591           2 :         chan->active_connections++;
    2592           2 :         *_chan = chan;
    2593             : 
    2594           2 :         return (W_ERROR_IS_OK(result));
    2595             : }
    2596             : 
    2597             : /****************************************************************
    2598             :  ****************************************************************/
    2599             : 
    2600           2 : static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
    2601             :                                                              const struct spoolss_NotifyOption *r)
    2602             : {
    2603             :         struct spoolss_NotifyOption *option;
    2604             :         uint32_t i,k;
    2605             : 
    2606           2 :         if (!r) {
    2607           0 :                 return NULL;
    2608             :         }
    2609             : 
    2610           2 :         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
    2611           2 :         if (!option) {
    2612           0 :                 return NULL;
    2613             :         }
    2614             : 
    2615           2 :         *option = *r;
    2616             : 
    2617           2 :         if (!option->count) {
    2618           0 :                 return option;
    2619             :         }
    2620             : 
    2621           2 :         option->types = talloc_zero_array(option,
    2622             :                 struct spoolss_NotifyOptionType, option->count);
    2623           2 :         if (!option->types) {
    2624           0 :                 talloc_free(option);
    2625           0 :                 return NULL;
    2626             :         }
    2627             : 
    2628           6 :         for (i=0; i < option->count; i++) {
    2629           4 :                 option->types[i] = r->types[i];
    2630             : 
    2631           4 :                 if (option->types[i].count) {
    2632           4 :                         option->types[i].fields = talloc_zero_array(option,
    2633             :                                 union spoolss_Field, option->types[i].count);
    2634           4 :                         if (!option->types[i].fields) {
    2635           0 :                                 talloc_free(option);
    2636           0 :                                 return NULL;
    2637             :                         }
    2638           8 :                         for (k=0; k<option->types[i].count; k++) {
    2639           4 :                                 option->types[i].fields[k] =
    2640           4 :                                         r->types[i].fields[k];
    2641             :                         }
    2642             :                 }
    2643             :         }
    2644             : 
    2645           2 :         return option;
    2646             : }
    2647             : 
    2648             : /****************************************************************
    2649             :  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
    2650             :  *
    2651             :  * before replying OK: status=0 a rpc call is made to the workstation
    2652             :  * asking ReplyOpenPrinter
    2653             :  *
    2654             :  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
    2655             :  * called from api_spoolss_rffpcnex
    2656             : ****************************************************************/
    2657             : 
    2658           2 : WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
    2659             :                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
    2660             : {
    2661           2 :         int snum = -1;
    2662           2 :         struct spoolss_NotifyOption *option = r->in.notify_options;
    2663             :         struct sockaddr_storage client_ss;
    2664             :         ssize_t client_len;
    2665             : 
    2666             :         /* store the notify value in the printer struct */
    2667             : 
    2668           2 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    2669             : 
    2670           2 :         if (!Printer) {
    2671           0 :                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2672             :                         "Invalid handle (%s:%u:%u).\n",
    2673             :                         OUR_HANDLE(r->in.handle)));
    2674           0 :                 return WERR_INVALID_HANDLE;
    2675             :         }
    2676             : 
    2677           2 :         Printer->notify.flags                = r->in.flags;
    2678           2 :         Printer->notify.options              = r->in.options;
    2679           2 :         Printer->notify.printerlocal = r->in.printer_local;
    2680           2 :         Printer->notify.msg_ctx              = p->msg_ctx;
    2681             : 
    2682           2 :         TALLOC_FREE(Printer->notify.option);
    2683           2 :         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
    2684             : 
    2685           2 :         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
    2686             : 
    2687             :         /* Connect to the client machine and send a ReplyOpenPrinter */
    2688             : 
    2689           2 :         if ( Printer->printer_type == SPLHND_SERVER)
    2690           2 :                 snum = -1;
    2691           0 :         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
    2692           0 :                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
    2693           0 :                 return WERR_INVALID_HANDLE;
    2694             : 
    2695           2 :         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2696             :                   "remote_address is %s\n",
    2697             :                   tsocket_address_string(p->remote_address, p->mem_ctx)));
    2698             : 
    2699           2 :         if (!lp_print_notify_backchannel(snum)) {
    2700           0 :                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2701             :                         "backchannel disabled\n"));
    2702           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
    2703             :         }
    2704             : 
    2705           2 :         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
    2706             :                                                   (struct sockaddr *) &client_ss,
    2707             :                                                   sizeof(struct sockaddr_storage));
    2708           2 :         if (client_len < 0) {
    2709           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2710             :         }
    2711             : 
    2712           2 :         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
    2713             :                                         Printer->notify.printerlocal, REG_SZ,
    2714             :                                         &Printer->notify.cli_hnd,
    2715             :                                         &Printer->notify.cli_chan,
    2716             :                                         &client_ss, p->msg_ctx)) {
    2717           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
    2718             :         }
    2719             : 
    2720           2 :         return WERR_OK;
    2721             : }
    2722             : 
    2723             : /*******************************************************************
    2724             :  * fill a notify_info_data with the servername
    2725             :  ********************************************************************/
    2726             : 
    2727           0 : static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
    2728             :                                        int snum,
    2729             :                                        struct spoolss_Notify *data,
    2730             :                                        print_queue_struct *queue,
    2731             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    2732             :                                        TALLOC_CTX *mem_ctx)
    2733             : {
    2734           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
    2735           0 : }
    2736             : 
    2737             : /*******************************************************************
    2738             :  * fill a notify_info_data with the printername (not including the servername).
    2739             :  ********************************************************************/
    2740             : 
    2741           0 : static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
    2742             :                                         int snum,
    2743             :                                         struct spoolss_Notify *data,
    2744             :                                         print_queue_struct *queue,
    2745             :                                         struct spoolss_PrinterInfo2 *pinfo2,
    2746             :                                         TALLOC_CTX *mem_ctx)
    2747             : {
    2748             :         /* the notify name should not contain the \\server\ part */
    2749           0 :         const char *p = strrchr(pinfo2->printername, '\\');
    2750             : 
    2751           0 :         if (!p) {
    2752           0 :                 p = pinfo2->printername;
    2753             :         } else {
    2754           0 :                 p++;
    2755             :         }
    2756             : 
    2757           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    2758           0 : }
    2759             : 
    2760             : /*******************************************************************
    2761             :  * fill a notify_info_data with the servicename
    2762             :  ********************************************************************/
    2763             : 
    2764           0 : static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
    2765             :                                       int snum,
    2766             :                                       struct spoolss_Notify *data,
    2767             :                                       print_queue_struct *queue,
    2768             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2769             :                                       TALLOC_CTX *mem_ctx)
    2770             : {
    2771           0 :         const struct loadparm_substitution *lp_sub =
    2772           0 :                 loadparm_s3_global_substitution();
    2773             : 
    2774           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
    2775           0 : }
    2776             : 
    2777             : /*******************************************************************
    2778             :  * fill a notify_info_data with the port name
    2779             :  ********************************************************************/
    2780             : 
    2781           0 : static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
    2782             :                                      int snum,
    2783             :                                      struct spoolss_Notify *data,
    2784             :                                      print_queue_struct *queue,
    2785             :                                      struct spoolss_PrinterInfo2 *pinfo2,
    2786             :                                      TALLOC_CTX *mem_ctx)
    2787             : {
    2788           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
    2789           0 : }
    2790             : 
    2791             : /*******************************************************************
    2792             :  * fill a notify_info_data with the printername
    2793             :  * but it doesn't exist, have to see what to do
    2794             :  ********************************************************************/
    2795             : 
    2796           0 : static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
    2797             :                                        int snum,
    2798             :                                        struct spoolss_Notify *data,
    2799             :                                        print_queue_struct *queue,
    2800             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    2801             :                                        TALLOC_CTX *mem_ctx)
    2802             : {
    2803           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
    2804           0 : }
    2805             : 
    2806             : /*******************************************************************
    2807             :  * fill a notify_info_data with the comment
    2808             :  ********************************************************************/
    2809             : 
    2810           0 : static void spoolss_notify_comment(struct messaging_context *msg_ctx,
    2811             :                                    int snum,
    2812             :                                    struct spoolss_Notify *data,
    2813             :                                    print_queue_struct *queue,
    2814             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2815             :                                    TALLOC_CTX *mem_ctx)
    2816             : {
    2817           0 :         const struct loadparm_substitution *lp_sub =
    2818           0 :                 loadparm_s3_global_substitution();
    2819             :         const char *p;
    2820             : 
    2821           0 :         if (*pinfo2->comment == '\0') {
    2822           0 :                 p = lp_comment(talloc_tos(), lp_sub, snum);
    2823             :         } else {
    2824           0 :                 p = pinfo2->comment;
    2825             :         }
    2826             : 
    2827           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    2828           0 : }
    2829             : 
    2830             : /*******************************************************************
    2831             :  * fill a notify_info_data with the comment
    2832             :  * location = "Room 1, floor 2, building 3"
    2833             :  ********************************************************************/
    2834             : 
    2835           0 : static void spoolss_notify_location(struct messaging_context *msg_ctx,
    2836             :                                     int snum,
    2837             :                                     struct spoolss_Notify *data,
    2838             :                                     print_queue_struct *queue,
    2839             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2840             :                                     TALLOC_CTX *mem_ctx)
    2841             : {
    2842           0 :         const char *loc = pinfo2->location;
    2843             :         NTSTATUS status;
    2844             : 
    2845           0 :         status = printer_list_get_printer(mem_ctx,
    2846             :                                           pinfo2->sharename,
    2847             :                                           NULL,
    2848             :                                           &loc,
    2849             :                                           NULL);
    2850           0 :         if (NT_STATUS_IS_OK(status)) {
    2851           0 :                 if (loc == NULL) {
    2852           0 :                         loc = pinfo2->location;
    2853             :                 }
    2854             :         }
    2855             : 
    2856           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
    2857           0 : }
    2858             : 
    2859             : /*******************************************************************
    2860             :  * fill a notify_info_data with the device mode
    2861             :  * jfm:xxxx don't to it for know but that's a real problem !!!
    2862             :  ********************************************************************/
    2863             : 
    2864           0 : static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
    2865             :                                    int snum,
    2866             :                                    struct spoolss_Notify *data,
    2867             :                                    print_queue_struct *queue,
    2868             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2869             :                                    TALLOC_CTX *mem_ctx)
    2870             : {
    2871             :         /* for a dummy implementation we have to zero the fields */
    2872           0 :         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
    2873           0 : }
    2874             : 
    2875             : /*******************************************************************
    2876             :  * fill a notify_info_data with the separator file name
    2877             :  ********************************************************************/
    2878             : 
    2879           0 : static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
    2880             :                                    int snum,
    2881             :                                    struct spoolss_Notify *data,
    2882             :                                    print_queue_struct *queue,
    2883             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2884             :                                    TALLOC_CTX *mem_ctx)
    2885             : {
    2886           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
    2887           0 : }
    2888             : 
    2889             : /*******************************************************************
    2890             :  * fill a notify_info_data with the print processor
    2891             :  * jfm:xxxx return always winprint to indicate we don't do anything to it
    2892             :  ********************************************************************/
    2893             : 
    2894           0 : static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
    2895             :                                            int snum,
    2896             :                                            struct spoolss_Notify *data,
    2897             :                                            print_queue_struct *queue,
    2898             :                                            struct spoolss_PrinterInfo2 *pinfo2,
    2899             :                                            TALLOC_CTX *mem_ctx)
    2900             : {
    2901           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
    2902           0 : }
    2903             : 
    2904             : /*******************************************************************
    2905             :  * fill a notify_info_data with the print processor options
    2906             :  * jfm:xxxx send an empty string
    2907             :  ********************************************************************/
    2908             : 
    2909           0 : static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
    2910             :                                       int snum,
    2911             :                                       struct spoolss_Notify *data,
    2912             :                                       print_queue_struct *queue,
    2913             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2914             :                                       TALLOC_CTX *mem_ctx)
    2915             : {
    2916           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
    2917           0 : }
    2918             : 
    2919             : /*******************************************************************
    2920             :  * fill a notify_info_data with the data type
    2921             :  * jfm:xxxx always send RAW as data type
    2922             :  ********************************************************************/
    2923             : 
    2924           0 : static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
    2925             :                                     int snum,
    2926             :                                     struct spoolss_Notify *data,
    2927             :                                     print_queue_struct *queue,
    2928             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2929             :                                     TALLOC_CTX *mem_ctx)
    2930             : {
    2931           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
    2932           0 : }
    2933             : 
    2934             : /*******************************************************************
    2935             :  * fill a notify_info_data with the security descriptor
    2936             :  * jfm:xxxx send an null pointer to say no security desc
    2937             :  * have to implement security before !
    2938             :  ********************************************************************/
    2939             : 
    2940           0 : static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
    2941             :                                          int snum,
    2942             :                                          struct spoolss_Notify *data,
    2943             :                                          print_queue_struct *queue,
    2944             :                                          struct spoolss_PrinterInfo2 *pinfo2,
    2945             :                                          TALLOC_CTX *mem_ctx)
    2946             : {
    2947           0 :         if (pinfo2->secdesc == NULL) {
    2948           0 :                 data->data.sd.sd = NULL;
    2949             :         } else {
    2950           0 :                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
    2951           0 :                                                             pinfo2->secdesc);
    2952             :         }
    2953           0 :         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
    2954             :                                                              0);
    2955           0 : }
    2956             : 
    2957             : /*******************************************************************
    2958             :  * fill a notify_info_data with the attributes
    2959             :  * jfm:xxxx a samba printer is always shared
    2960             :  ********************************************************************/
    2961             : 
    2962           0 : static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
    2963             :                                       int snum,
    2964             :                                       struct spoolss_Notify *data,
    2965             :                                       print_queue_struct *queue,
    2966             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2967             :                                       TALLOC_CTX *mem_ctx)
    2968             : {
    2969           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
    2970           0 : }
    2971             : 
    2972             : /*******************************************************************
    2973             :  * fill a notify_info_data with the priority
    2974             :  ********************************************************************/
    2975             : 
    2976           0 : static void spoolss_notify_priority(struct messaging_context *msg_ctx,
    2977             :                                     int snum,
    2978             :                                     struct spoolss_Notify *data,
    2979             :                                     print_queue_struct *queue,
    2980             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2981             :                                     TALLOC_CTX *mem_ctx)
    2982             : {
    2983           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
    2984           0 : }
    2985             : 
    2986             : /*******************************************************************
    2987             :  * fill a notify_info_data with the default priority
    2988             :  ********************************************************************/
    2989             : 
    2990           0 : static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
    2991             :                                             int snum,
    2992             :                                             struct spoolss_Notify *data,
    2993             :                                             print_queue_struct *queue,
    2994             :                                             struct spoolss_PrinterInfo2 *pinfo2,
    2995             :                                             TALLOC_CTX *mem_ctx)
    2996             : {
    2997           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
    2998           0 : }
    2999             : 
    3000             : /*******************************************************************
    3001             :  * fill a notify_info_data with the start time
    3002             :  ********************************************************************/
    3003             : 
    3004           0 : static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
    3005             :                                       int snum,
    3006             :                                       struct spoolss_Notify *data,
    3007             :                                       print_queue_struct *queue,
    3008             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3009             :                                       TALLOC_CTX *mem_ctx)
    3010             : {
    3011           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
    3012           0 : }
    3013             : 
    3014             : /*******************************************************************
    3015             :  * fill a notify_info_data with the until time
    3016             :  ********************************************************************/
    3017             : 
    3018           0 : static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
    3019             :                                       int snum,
    3020             :                                       struct spoolss_Notify *data,
    3021             :                                       print_queue_struct *queue,
    3022             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3023             :                                       TALLOC_CTX *mem_ctx)
    3024             : {
    3025           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
    3026           0 : }
    3027             : 
    3028             : /*******************************************************************
    3029             :  * fill a notify_info_data with the status
    3030             :  ********************************************************************/
    3031             : 
    3032           0 : static void spoolss_notify_status(struct messaging_context *msg_ctx,
    3033             :                                   int snum,
    3034             :                                   struct spoolss_Notify *data,
    3035             :                                   print_queue_struct *queue,
    3036             :                                   struct spoolss_PrinterInfo2 *pinfo2,
    3037             :                                   TALLOC_CTX *mem_ctx)
    3038             : {
    3039             :         print_status_struct status;
    3040             : 
    3041           0 :         print_queue_length(msg_ctx, snum, &status);
    3042           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
    3043           0 : }
    3044             : 
    3045             : /*******************************************************************
    3046             :  * fill a notify_info_data with the number of jobs queued
    3047             :  ********************************************************************/
    3048             : 
    3049           0 : static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
    3050             :                                  int snum,
    3051             :                                  struct spoolss_Notify *data,
    3052             :                                  print_queue_struct *queue,
    3053             :                                  struct spoolss_PrinterInfo2 *pinfo2,
    3054             :                                  TALLOC_CTX *mem_ctx)
    3055             : {
    3056           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
    3057             :                 data, print_queue_length(msg_ctx, snum, NULL));
    3058           0 : }
    3059             : 
    3060             : /*******************************************************************
    3061             :  * fill a notify_info_data with the average ppm
    3062             :  ********************************************************************/
    3063             : 
    3064           0 : static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
    3065             :                                        int snum,
    3066             :                                        struct spoolss_Notify *data,
    3067             :                                        print_queue_struct *queue,
    3068             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    3069             :                                        TALLOC_CTX *mem_ctx)
    3070             : {
    3071             :         /* always respond 8 pages per minutes */
    3072             :         /* a little hard ! */
    3073           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
    3074           0 : }
    3075             : 
    3076             : /*******************************************************************
    3077             :  * fill a notify_info_data with username
    3078             :  ********************************************************************/
    3079             : 
    3080           0 : static void spoolss_notify_username(struct messaging_context *msg_ctx,
    3081             :                                     int snum,
    3082             :                                     struct spoolss_Notify *data,
    3083             :                                     print_queue_struct *queue,
    3084             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3085             :                                     TALLOC_CTX *mem_ctx)
    3086             : {
    3087           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
    3088           0 : }
    3089             : 
    3090             : /*******************************************************************
    3091             :  * fill a notify_info_data with job status
    3092             :  ********************************************************************/
    3093             : 
    3094           0 : static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
    3095             :                                       int snum,
    3096             :                                       struct spoolss_Notify *data,
    3097             :                                       print_queue_struct *queue,
    3098             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3099             :                                       TALLOC_CTX *mem_ctx)
    3100             : {
    3101           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
    3102           0 : }
    3103             : 
    3104             : /*******************************************************************
    3105             :  * fill a notify_info_data with job name
    3106             :  ********************************************************************/
    3107             : 
    3108           0 : static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
    3109             :                                     int snum,
    3110             :                                     struct spoolss_Notify *data,
    3111             :                                     print_queue_struct *queue,
    3112             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3113             :                                     TALLOC_CTX *mem_ctx)
    3114             : {
    3115           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
    3116           0 : }
    3117             : 
    3118             : /*******************************************************************
    3119             :  * fill a notify_info_data with job status
    3120             :  ********************************************************************/
    3121             : 
    3122           0 : static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
    3123             :                                              int snum,
    3124             :                                              struct spoolss_Notify *data,
    3125             :                                              print_queue_struct *queue,
    3126             :                                              struct spoolss_PrinterInfo2 *pinfo2,
    3127             :                                              TALLOC_CTX *mem_ctx)
    3128             : {
    3129             :         /*
    3130             :          * Now we're returning job status codes we just return a "" here. JRA.
    3131             :          */
    3132             : 
    3133           0 :         const char *p = "";
    3134             : 
    3135             : #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
    3136             :         p = "unknown";
    3137             : 
    3138             :         switch (queue->status) {
    3139             :         case LPQ_QUEUED:
    3140             :                 p = "Queued";
    3141             :                 break;
    3142             :         case LPQ_PAUSED:
    3143             :                 p = "";    /* NT provides the paused string */
    3144             :                 break;
    3145             :         case LPQ_SPOOLING:
    3146             :                 p = "Spooling";
    3147             :                 break;
    3148             :         case LPQ_PRINTING:
    3149             :                 p = "Printing";
    3150             :                 break;
    3151             :         }
    3152             : #endif /* NO LONGER NEEDED. */
    3153             : 
    3154           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    3155           0 : }
    3156             : 
    3157             : /*******************************************************************
    3158             :  * fill a notify_info_data with job time
    3159             :  ********************************************************************/
    3160             : 
    3161           0 : static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
    3162             :                                     int snum,
    3163             :                                     struct spoolss_Notify *data,
    3164             :                                     print_queue_struct *queue,
    3165             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3166             :                                     TALLOC_CTX *mem_ctx)
    3167             : {
    3168           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
    3169           0 : }
    3170             : 
    3171             : /*******************************************************************
    3172             :  * fill a notify_info_data with job size
    3173             :  ********************************************************************/
    3174             : 
    3175           0 : static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
    3176             :                                     int snum,
    3177             :                                     struct spoolss_Notify *data,
    3178             :                                     print_queue_struct *queue,
    3179             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3180             :                                     TALLOC_CTX *mem_ctx)
    3181             : {
    3182           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
    3183           0 : }
    3184             : 
    3185             : /*******************************************************************
    3186             :  * fill a notify_info_data with page info
    3187             :  ********************************************************************/
    3188           0 : static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
    3189             :                                        int snum,
    3190             :                                 struct spoolss_Notify *data,
    3191             :                                 print_queue_struct *queue,
    3192             :                                 struct spoolss_PrinterInfo2 *pinfo2,
    3193             :                                 TALLOC_CTX *mem_ctx)
    3194             : {
    3195           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
    3196           0 : }
    3197             : 
    3198             : /*******************************************************************
    3199             :  * fill a notify_info_data with pages printed info.
    3200             :  ********************************************************************/
    3201           0 : static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
    3202             :                                          int snum,
    3203             :                                 struct spoolss_Notify *data,
    3204             :                                 print_queue_struct *queue,
    3205             :                                 struct spoolss_PrinterInfo2 *pinfo2,
    3206             :                                 TALLOC_CTX *mem_ctx)
    3207             : {
    3208             :         /* Add code when back-end tracks this */
    3209           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
    3210           0 : }
    3211             : 
    3212             : /*******************************************************************
    3213             :  Fill a notify_info_data with job position.
    3214             :  ********************************************************************/
    3215             : 
    3216           0 : static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
    3217             :                                         int snum,
    3218             :                                         struct spoolss_Notify *data,
    3219             :                                         print_queue_struct *queue,
    3220             :                                         struct spoolss_PrinterInfo2 *pinfo2,
    3221             :                                         TALLOC_CTX *mem_ctx)
    3222             : {
    3223           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
    3224           0 : }
    3225             : 
    3226             : /*******************************************************************
    3227             :  Fill a notify_info_data with submitted time.
    3228             :  ********************************************************************/
    3229             : 
    3230           0 : static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
    3231             :                                           int snum,
    3232             :                                           struct spoolss_Notify *data,
    3233             :                                           print_queue_struct *queue,
    3234             :                                           struct spoolss_PrinterInfo2 *pinfo2,
    3235             :                                           TALLOC_CTX *mem_ctx)
    3236             : {
    3237           0 :         data->data.string.string = NULL;
    3238           0 :         data->data.string.size = 0;
    3239             : 
    3240           0 :         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
    3241             :                                &data->data.string.string,
    3242             :                                &data->data.string.size);
    3243             : 
    3244           0 : }
    3245             : 
    3246             : struct s_notify_info_data_table
    3247             : {
    3248             :         enum spoolss_NotifyType type;
    3249             :         uint16_t field;
    3250             :         const char *name;
    3251             :         enum spoolss_NotifyTable variable_type;
    3252             :         void (*fn) (struct messaging_context *msg_ctx,
    3253             :                     int snum, struct spoolss_Notify *data,
    3254             :                     print_queue_struct *queue,
    3255             :                     struct spoolss_PrinterInfo2 *pinfo2,
    3256             :                     TALLOC_CTX *mem_ctx);
    3257             : };
    3258             : 
    3259             : /* A table describing the various print notification constants and
    3260             :    whether the notification data is a pointer to a variable sized
    3261             :    buffer, a one value uint32_t or a two value uint32_t. */
    3262             : 
    3263             : static const struct s_notify_info_data_table notify_info_data_table[] =
    3264             : {
    3265             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
    3266             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
    3267             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
    3268             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
    3269             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
    3270             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
    3271             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
    3272             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
    3273             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
    3274             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
    3275             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
    3276             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
    3277             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
    3278             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
    3279             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
    3280             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
    3281             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
    3282             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
    3283             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
    3284             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
    3285             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
    3286             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
    3287             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
    3288             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
    3289             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
    3290             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
    3291             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
    3292             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
    3293             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
    3294             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
    3295             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
    3296             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
    3297             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
    3298             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
    3299             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
    3300             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
    3301             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
    3302             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
    3303             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
    3304             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
    3305             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
    3306             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
    3307             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
    3308             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
    3309             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
    3310             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
    3311             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
    3312             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
    3313             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
    3314             : };
    3315             : 
    3316             : /*******************************************************************
    3317             :  Return the variable_type of info_data structure.
    3318             : ********************************************************************/
    3319             : 
    3320           0 : static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
    3321             :                                                                   uint16_t field)
    3322             : {
    3323           0 :         int i=0;
    3324             : 
    3325           0 :         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
    3326           0 :                 if ( (notify_info_data_table[i].type == type) &&
    3327           0 :                      (notify_info_data_table[i].field == field) ) {
    3328           0 :                         return notify_info_data_table[i].variable_type;
    3329             :                 }
    3330             :         }
    3331             : 
    3332           0 :         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
    3333             : 
    3334           0 :         return (enum spoolss_NotifyTable) 0;
    3335             : }
    3336             : 
    3337             : /****************************************************************************
    3338             : ****************************************************************************/
    3339             : 
    3340           0 : static bool search_notify(enum spoolss_NotifyType type,
    3341             :                           uint16_t field,
    3342             :                           int *value)
    3343             : {
    3344             :         int i;
    3345             : 
    3346           0 :         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
    3347           0 :                 if (notify_info_data_table[i].type == type &&
    3348           0 :                     notify_info_data_table[i].field == field &&
    3349           0 :                     notify_info_data_table[i].fn != NULL) {
    3350           0 :                         *value = i;
    3351           0 :                         return true;
    3352             :                 }
    3353             :         }
    3354             : 
    3355           0 :         return false;
    3356             : }
    3357             : 
    3358             : /****************************************************************************
    3359             : ****************************************************************************/
    3360             : 
    3361           0 : static void construct_info_data(struct spoolss_Notify *info_data,
    3362             :                                 enum spoolss_NotifyType type,
    3363             :                                 uint16_t field, int id)
    3364             : {
    3365           0 :         info_data->type                      = type;
    3366           0 :         info_data->field.field               = field;
    3367           0 :         info_data->variable_type     = variable_type_of_notify_info_data(type, field);
    3368           0 :         info_data->job_id            = id;
    3369           0 : }
    3370             : 
    3371             : /*******************************************************************
    3372             :  *
    3373             :  * fill a notify_info struct with info asked
    3374             :  *
    3375             :  ********************************************************************/
    3376             : 
    3377           0 : static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
    3378             :                                           struct printer_handle *print_hnd,
    3379             :                                           struct spoolss_NotifyInfo *info,
    3380             :                                           struct spoolss_PrinterInfo2 *pinfo2,
    3381             :                                           int snum,
    3382             :                                           const struct spoolss_NotifyOptionType *option_type,
    3383             :                                           uint32_t id,
    3384             :                                           TALLOC_CTX *mem_ctx)
    3385             : {
    3386           0 :         const struct loadparm_substitution *lp_sub =
    3387           0 :                 loadparm_s3_global_substitution();
    3388             :         int field_num,j;
    3389             :         enum spoolss_NotifyType type;
    3390             :         uint16_t field;
    3391             : 
    3392             :         struct spoolss_Notify *current_data;
    3393             : 
    3394           0 :         type = option_type->type;
    3395             : 
    3396           0 :         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
    3397             :                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
    3398             :                 option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
    3399             : 
    3400           0 :         for(field_num=0; field_num < option_type->count; field_num++) {
    3401           0 :                 field = option_type->fields[field_num].field;
    3402             : 
    3403           0 :                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
    3404             : 
    3405           0 :                 if (!search_notify(type, field, &j) )
    3406           0 :                         continue;
    3407             : 
    3408           0 :                 info->notifies = talloc_realloc(info, info->notifies,
    3409             :                                                       struct spoolss_Notify,
    3410             :                                                       info->count + 1);
    3411           0 :                 if (info->notifies == NULL) {
    3412           0 :                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
    3413           0 :                         return false;
    3414             :                 }
    3415             : 
    3416           0 :                 current_data = &info->notifies[info->count];
    3417             : 
    3418           0 :                 construct_info_data(current_data, type, field, id);
    3419             : 
    3420           0 :                 DEBUG(10, ("construct_notify_printer_info: "
    3421             :                            "calling [%s]  snum=%d  printername=[%s])\n",
    3422             :                            notify_info_data_table[j].name, snum,
    3423             :                            pinfo2->printername));
    3424             : 
    3425           0 :                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
    3426             :                                              NULL, pinfo2, mem_ctx);
    3427             : 
    3428           0 :                 info->count++;
    3429             :         }
    3430             : 
    3431           0 :         return true;
    3432             : }
    3433             : 
    3434             : /*******************************************************************
    3435             :  *
    3436             :  * fill a notify_info struct with info asked
    3437             :  *
    3438             :  ********************************************************************/
    3439             : 
    3440           0 : static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
    3441             :                                        print_queue_struct *queue,
    3442             :                                        struct spoolss_NotifyInfo *info,
    3443             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    3444             :                                        int snum,
    3445             :                                        const struct spoolss_NotifyOptionType *option_type,
    3446             :                                        uint32_t id,
    3447             :                                        TALLOC_CTX *mem_ctx)
    3448             : {
    3449             :         int field_num,j;
    3450             :         enum spoolss_NotifyType type;
    3451             :         uint16_t field;
    3452             :         struct spoolss_Notify *current_data;
    3453             : 
    3454           0 :         DEBUG(4,("construct_notify_jobs_info\n"));
    3455             : 
    3456           0 :         type = option_type->type;
    3457             : 
    3458           0 :         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
    3459             :                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
    3460             :                 option_type->count));
    3461             : 
    3462           0 :         for(field_num=0; field_num<option_type->count; field_num++) {
    3463           0 :                 field = option_type->fields[field_num].field;
    3464             : 
    3465           0 :                 if (!search_notify(type, field, &j) )
    3466           0 :                         continue;
    3467             : 
    3468           0 :                 info->notifies = talloc_realloc(info, info->notifies,
    3469             :                                                       struct spoolss_Notify,
    3470             :                                                       info->count + 1);
    3471           0 :                 if (info->notifies == NULL) {
    3472           0 :                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
    3473           0 :                         return false;
    3474             :                 }
    3475             : 
    3476           0 :                 current_data=&(info->notifies[info->count]);
    3477             : 
    3478           0 :                 construct_info_data(current_data, type, field, id);
    3479           0 :                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
    3480             :                                              queue, pinfo2, mem_ctx);
    3481           0 :                 info->count++;
    3482             :         }
    3483             : 
    3484           0 :         return true;
    3485             : }
    3486             : 
    3487             : /*
    3488             :  * JFM: The enumeration is not that simple, it's even non obvious.
    3489             :  *
    3490             :  * let's take an example: I want to monitor the PRINTER SERVER for
    3491             :  * the printer's name and the number of jobs currently queued.
    3492             :  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
    3493             :  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
    3494             :  *
    3495             :  * I have 3 printers on the back of my server.
    3496             :  *
    3497             :  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
    3498             :  * structures.
    3499             :  *   Number     Data                    Id
    3500             :  *      1       printer 1 name          1
    3501             :  *      2       printer 1 cjob          1
    3502             :  *      3       printer 2 name          2
    3503             :  *      4       printer 2 cjob          2
    3504             :  *      5       printer 3 name          3
    3505             :  *      6       printer 3 name          3
    3506             :  *
    3507             :  * that's the print server case, the printer case is even worse.
    3508             :  */
    3509             : 
    3510             : /*******************************************************************
    3511             :  *
    3512             :  * enumerate all printers on the printserver
    3513             :  * fill a notify_info struct with info asked
    3514             :  *
    3515             :  ********************************************************************/
    3516             : 
    3517           4 : static WERROR printserver_notify_info(struct pipes_struct *p,
    3518             :                                       struct policy_handle *hnd,
    3519             :                                       struct spoolss_NotifyInfo *info,
    3520             :                                       TALLOC_CTX *mem_ctx)
    3521             : {
    3522           2 :         const struct loadparm_substitution *lp_sub =
    3523           2 :                 loadparm_s3_global_substitution();
    3524             :         int snum;
    3525           4 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
    3526           4 :         int n_services=lp_numservices();
    3527             :         int i;
    3528             :         struct spoolss_NotifyOption *option;
    3529             :         struct spoolss_NotifyOptionType option_type;
    3530           4 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    3531             :         WERROR result;
    3532             : 
    3533           4 :         DEBUG(4,("printserver_notify_info\n"));
    3534             : 
    3535           4 :         if (!Printer)
    3536           0 :                 return WERR_INVALID_HANDLE;
    3537             : 
    3538           4 :         option = Printer->notify.option;
    3539             : 
    3540           4 :         info->version        = 2;
    3541           4 :         info->notifies       = NULL;
    3542           4 :         info->count  = 0;
    3543             : 
    3544             :         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
    3545             :            sending a ffpcn() request first */
    3546             : 
    3547           4 :         if ( !option )
    3548           0 :                 return WERR_INVALID_HANDLE;
    3549             : 
    3550          12 :         for (i=0; i<option->count; i++) {
    3551           8 :                 option_type = option->types[i];
    3552             : 
    3553           8 :                 if (option_type.type != PRINTER_NOTIFY_TYPE)
    3554           4 :                         continue;
    3555             : 
    3556         416 :                 for (snum = 0; snum < n_services; snum++) {
    3557         618 :                         if (!lp_browseable(snum) ||
    3558         618 :                             !lp_snum_ok(snum) ||
    3559         412 :                             !lp_printable(snum)) {
    3560         392 :                                 continue; /* skip */
    3561             :                         }
    3562             : 
    3563             :                         /* Maybe we should use the SYSTEM session_info here... */
    3564          20 :                         result = winreg_get_printer_internal(mem_ctx,
    3565             :                                                     get_session_info_system(),
    3566             :                                                     p->msg_ctx,
    3567          20 :                                                     lp_servicename(talloc_tos(), lp_sub, snum),
    3568             :                                                     &pinfo2);
    3569          20 :                         if (!W_ERROR_IS_OK(result)) {
    3570          20 :                                 DEBUG(4, ("printserver_notify_info: "
    3571             :                                           "Failed to get printer [%s]\n",
    3572             :                                           lp_servicename(talloc_tos(), lp_sub, snum)));
    3573          20 :                                 continue;
    3574             :                         }
    3575             : 
    3576             : 
    3577           0 :                         construct_notify_printer_info(p->msg_ctx,
    3578             :                                                       Printer, info,
    3579             :                                                       pinfo2, snum,
    3580             :                                                       &option_type, snum,
    3581             :                                                       mem_ctx);
    3582             : 
    3583           0 :                         TALLOC_FREE(pinfo2);
    3584             :                 }
    3585             :         }
    3586             : 
    3587             : #if 0
    3588             :         /*
    3589             :          * Debugging information, don't delete.
    3590             :          */
    3591             : 
    3592             :         DEBUG(1,("dumping the NOTIFY_INFO\n"));
    3593             :         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
    3594             :         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
    3595             : 
    3596             :         for (i=0; i<info->count; i++) {
    3597             :                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
    3598             :                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
    3599             :                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
    3600             :         }
    3601             : #endif
    3602             : 
    3603           4 :         return WERR_OK;
    3604             : }
    3605             : 
    3606             : /*******************************************************************
    3607             :  *
    3608             :  * fill a notify_info struct with info asked
    3609             :  *
    3610             :  ********************************************************************/
    3611             : 
    3612           0 : static WERROR printer_notify_info(struct pipes_struct *p,
    3613             :                                   struct policy_handle *hnd,
    3614             :                                   struct spoolss_NotifyInfo *info,
    3615             :                                   TALLOC_CTX *mem_ctx)
    3616             : {
    3617           0 :         const struct loadparm_substitution *lp_sub =
    3618           0 :                 loadparm_s3_global_substitution();
    3619             :         int snum;
    3620           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
    3621             :         int i;
    3622             :         uint32_t id;
    3623             :         struct spoolss_NotifyOption *option;
    3624             :         struct spoolss_NotifyOptionType option_type;
    3625             :         int count,j;
    3626           0 :         print_queue_struct *queue=NULL;
    3627             :         print_status_struct status;
    3628           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    3629             :         WERROR result;
    3630             :         struct tdb_print_db *pdb;
    3631             : 
    3632           0 :         DEBUG(4,("printer_notify_info\n"));
    3633             : 
    3634           0 :         if (!Printer)
    3635           0 :                 return WERR_INVALID_HANDLE;
    3636             : 
    3637           0 :         option = Printer->notify.option;
    3638           0 :         id = 0x0;
    3639             : 
    3640           0 :         info->version        = 2;
    3641           0 :         info->notifies       = NULL;
    3642           0 :         info->count  = 0;
    3643             : 
    3644             :         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
    3645             :            sending a ffpcn() request first */
    3646             : 
    3647           0 :         if ( !option )
    3648           0 :                 return WERR_INVALID_HANDLE;
    3649             : 
    3650           0 :         if (!get_printer_snum(p, hnd, &snum, NULL)) {
    3651           0 :                 return WERR_INVALID_HANDLE;
    3652             :         }
    3653             : 
    3654           0 :         pdb = get_print_db_byname(Printer->sharename);
    3655           0 :         if (pdb == NULL) {
    3656           0 :                 return WERR_INVALID_HANDLE;
    3657             :         }
    3658             : 
    3659             :         /* Maybe we should use the SYSTEM session_info here... */
    3660           0 :         result = winreg_get_printer_internal(mem_ctx,
    3661             :                                     get_session_info_system(),
    3662             :                                     p->msg_ctx,
    3663           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
    3664           0 :         if (!W_ERROR_IS_OK(result)) {
    3665           0 :                 result = WERR_INVALID_HANDLE;
    3666           0 :                 goto err_pdb_drop;
    3667             :         }
    3668             : 
    3669             :         /*
    3670             :          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
    3671             :          * correct servername.
    3672             :          */
    3673           0 :         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
    3674           0 :         if (pinfo2->servername == NULL) {
    3675           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3676           0 :                 goto err_pdb_drop;
    3677             :         }
    3678             : 
    3679           0 :         for (i = 0; i < option->count; i++) {
    3680           0 :                 option_type = option->types[i];
    3681             : 
    3682           0 :                 switch (option_type.type) {
    3683           0 :                 case PRINTER_NOTIFY_TYPE:
    3684           0 :                         if (construct_notify_printer_info(p->msg_ctx,
    3685             :                                                           Printer, info,
    3686             :                                                           pinfo2, snum,
    3687             :                                                           &option_type, id,
    3688             :                                                           mem_ctx)) {
    3689           0 :                                 id--;
    3690             :                         }
    3691           0 :                         break;
    3692             : 
    3693           0 :                 case JOB_NOTIFY_TYPE:
    3694             : 
    3695           0 :                         count = print_queue_status(p->msg_ctx, snum, &queue,
    3696             :                                                    &status);
    3697             : 
    3698           0 :                         for (j = 0; j < count; j++) {
    3699             :                                 uint32_t jobid;
    3700           0 :                                 jobid = sysjob_to_jobid_pdb(pdb,
    3701           0 :                                                             queue[j].sysjob);
    3702           0 :                                 if (jobid == (uint32_t)-1) {
    3703           0 :                                         DEBUG(2, ("ignoring untracked job %d\n",
    3704             :                                                   queue[j].sysjob));
    3705           0 :                                         continue;
    3706             :                                 }
    3707             :                                 /* FIXME check return value */
    3708           0 :                                 construct_notify_jobs_info(p->msg_ctx,
    3709           0 :                                                            &queue[j], info,
    3710             :                                                            pinfo2, snum,
    3711             :                                                            &option_type,
    3712             :                                                            jobid,
    3713             :                                                            mem_ctx);
    3714             :                         }
    3715             : 
    3716           0 :                         SAFE_FREE(queue);
    3717           0 :                         break;
    3718             :                 }
    3719             :         }
    3720             : 
    3721             :         /*
    3722             :          * Debugging information, don't delete.
    3723             :          */
    3724             :         /*
    3725             :         DEBUG(1,("dumping the NOTIFY_INFO\n"));
    3726             :         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
    3727             :         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
    3728             : 
    3729             :         for (i=0; i<info->count; i++) {
    3730             :                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
    3731             :                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
    3732             :                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
    3733             :         }
    3734             :         */
    3735             : 
    3736           0 :         talloc_free(pinfo2);
    3737           0 :         result = WERR_OK;
    3738           0 : err_pdb_drop:
    3739           0 :         release_print_db(pdb);
    3740           0 :         return result;
    3741             : }
    3742             : 
    3743             : /****************************************************************
    3744             :  _spoolss_RouterRefreshPrinterChangeNotify
    3745             : ****************************************************************/
    3746             : 
    3747           4 : WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
    3748             :                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
    3749             : {
    3750             :         struct spoolss_NotifyInfo *info;
    3751             : 
    3752           4 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    3753           4 :         WERROR result = WERR_INVALID_HANDLE;
    3754             : 
    3755             :         /* we always have a spoolss_NotifyInfo struct */
    3756           4 :         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
    3757           4 :         if (!info) {
    3758           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3759           0 :                 goto done;
    3760             :         }
    3761             : 
    3762           4 :         *r->out.info = info;
    3763             : 
    3764           4 :         if (!Printer) {
    3765           0 :                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
    3766             :                         "Invalid handle (%s:%u:%u).\n",
    3767             :                         OUR_HANDLE(r->in.handle)));
    3768           0 :                 goto done;
    3769             :         }
    3770             : 
    3771           4 :         DEBUG(4,("Printer type %x\n",Printer->printer_type));
    3772             : 
    3773             :         /*
    3774             :          *      We are now using the change value, and
    3775             :          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
    3776             :          *      I don't have a global notification system, I'm sending back all the
    3777             :          *      information even when _NOTHING_ has changed.
    3778             :          */
    3779             : 
    3780             :         /* We need to keep track of the change value to send back in
    3781             :            RRPCN replies otherwise our updates are ignored. */
    3782             : 
    3783           4 :         Printer->notify.fnpcn = true;
    3784             : 
    3785           6 :         if (Printer->notify.cli_chan != NULL &&
    3786           4 :             Printer->notify.cli_chan->active_connections > 0) {
    3787           4 :                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
    3788             :                         "Saving change value in request [%x]\n",
    3789             :                         r->in.change_low));
    3790           4 :                 Printer->notify.change = r->in.change_low;
    3791             :         }
    3792             : 
    3793             :         /* just ignore the spoolss_NotifyOption */
    3794             : 
    3795           4 :         switch (Printer->printer_type) {
    3796           4 :                 case SPLHND_SERVER:
    3797           4 :                         result = printserver_notify_info(p, r->in.handle,
    3798             :                                                          info, p->mem_ctx);
    3799           4 :                         break;
    3800             : 
    3801           0 :                 case SPLHND_PRINTER:
    3802           0 :                         result = printer_notify_info(p, r->in.handle,
    3803             :                                                      info, p->mem_ctx);
    3804           0 :                         break;
    3805             :         }
    3806             : 
    3807           4 :         Printer->notify.fnpcn = false;
    3808             : 
    3809           4 : done:
    3810           4 :         return result;
    3811             : }
    3812             : 
    3813             : /********************************************************************
    3814             :  ********************************************************************/
    3815             : 
    3816        3951 : static WERROR create_printername(TALLOC_CTX *mem_ctx,
    3817             :                                  const char *servername,
    3818             :                                  const char *printername,
    3819             :                                  const char **printername_p)
    3820             : {
    3821             :         /* FIXME: add lp_force_printername() */
    3822             : 
    3823        3951 :         if (servername == NULL) {
    3824        1667 :                 *printername_p = talloc_strdup(mem_ctx, printername);
    3825        1667 :                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
    3826        1667 :                 return WERR_OK;
    3827             :         }
    3828             : 
    3829        2284 :         if (servername[0] == '\\' && servername[1] == '\\') {
    3830        2284 :                 servername += 2;
    3831             :         }
    3832             : 
    3833        2284 :         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
    3834        2284 :         W_ERROR_HAVE_NO_MEMORY(*printername_p);
    3835             : 
    3836        2284 :         return WERR_OK;
    3837             : }
    3838             : 
    3839             : /********************************************************************
    3840             :  ********************************************************************/
    3841             : 
    3842        2912 : static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
    3843             :                                           const char *printername)
    3844             : {
    3845        2912 :         if (dm == NULL) {
    3846          90 :                 return;
    3847             :         }
    3848             : 
    3849        2822 :         dm->devicename = talloc_strndup(dm, printername,
    3850        2822 :                                         MIN(strlen(printername), 31));
    3851             : }
    3852             : 
    3853             : /********************************************************************
    3854             :  * construct_printer_info_0
    3855             :  * fill a printer_info_0 struct
    3856             :  ********************************************************************/
    3857             : 
    3858         272 : static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
    3859             :                                       const struct auth_session_info *session_info,
    3860             :                                       struct messaging_context *msg_ctx,
    3861             :                                       struct spoolss_PrinterInfo2 *info2,
    3862             :                                       const char *servername,
    3863             :                                       struct spoolss_PrinterInfo0 *r,
    3864             :                                       int snum)
    3865             : {
    3866             :         int count;
    3867             :         struct printer_session_counter *session_counter;
    3868             :         struct timeval setuptime;
    3869             :         print_status_struct status;
    3870             :         WERROR result;
    3871             :         int os_major, os_minor, os_build;
    3872             :         const char *architecture;
    3873             :         uint32_t processor_architecture, processor_type;
    3874             : 
    3875         272 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    3876         272 :         if (!W_ERROR_IS_OK(result)) {
    3877           0 :                 return result;
    3878             :         }
    3879             : 
    3880         272 :         if (servername) {
    3881         136 :                 r->servername = talloc_strdup(mem_ctx, servername);
    3882         136 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    3883             :         } else {
    3884         136 :                 r->servername = NULL;
    3885             :         }
    3886             : 
    3887         272 :         count = print_queue_length(msg_ctx, snum, &status);
    3888             : 
    3889             :         /* check if we already have a counter for this printer */
    3890         628 :         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
    3891         588 :                 if (session_counter->snum == snum)
    3892         232 :                         break;
    3893             :         }
    3894             : 
    3895             :         /* it's the first time, add it to the list */
    3896         272 :         if (session_counter == NULL) {
    3897          40 :                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
    3898          40 :                 W_ERROR_HAVE_NO_MEMORY(session_counter);
    3899          40 :                 session_counter->snum                = snum;
    3900          40 :                 session_counter->counter     = 0;
    3901          40 :                 DLIST_ADD(counter_list, session_counter);
    3902             :         }
    3903             : 
    3904             :         /* increment it */
    3905         272 :         session_counter->counter++;
    3906             : 
    3907         272 :         r->cjobs                     = count;
    3908         272 :         r->total_jobs                        = 0;
    3909         272 :         r->total_bytes                       = 0;
    3910             : 
    3911         272 :         get_startup_time(&setuptime);
    3912         272 :         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
    3913             : 
    3914             :         /* JFM:
    3915             :          * the global_counter should be stored in a TDB as it's common to all the clients
    3916             :          * and should be zeroed on samba startup
    3917             :          */
    3918         272 :         r->global_counter            = session_counter->counter;
    3919         272 :         r->total_pages                       = 0;
    3920             : 
    3921             :         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
    3922         272 :         os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
    3923             :                                "spoolss", "os_major",
    3924             :                                GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
    3925         272 :         os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
    3926             :                                "spoolss", "os_minor",
    3927             :                                GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
    3928         272 :         os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
    3929             :                                "spoolss", "os_build",
    3930             :                                GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
    3931             : 
    3932         272 :         SCVAL(&r->version, 0, os_major);
    3933         272 :         SCVAL(&r->version, 1, os_minor);
    3934         272 :         SSVAL(&r->version, 2, os_build);
    3935             : 
    3936         272 :         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    3937             :                                             "spoolss",
    3938             :                                             "architecture",
    3939             :                                             GLOBAL_SPOOLSS_ARCHITECTURE);
    3940             : 
    3941         272 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
    3942         272 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_AMD64;
    3943         272 :                 processor_type          = PROCESSOR_AMD_X8664;
    3944           0 :         } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
    3945           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_ARM64;
    3946           0 :                 processor_type          = PROCESSOR_ARM820;
    3947             :         } else {
    3948           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_INTEL;
    3949           0 :                 processor_type          = PROCESSOR_INTEL_PENTIUM;
    3950             :         }
    3951             : 
    3952         272 :         r->free_build                        = SPOOLSS_RELEASE_BUILD;
    3953         272 :         r->spooling                  = 0;
    3954         272 :         r->max_spooling                      = 0;
    3955         272 :         r->session_counter           = session_counter->counter;
    3956         272 :         r->num_error_out_of_paper    = 0x0;
    3957         272 :         r->num_error_not_ready               = 0x0;          /* number of print failure */
    3958         272 :         r->job_error                 = 0x0;
    3959         272 :         r->number_of_processors              = 0x1;
    3960         272 :         r->processor_type            = processor_type;
    3961         272 :         r->high_part_total_bytes     = 0x0;
    3962             : 
    3963             :         /* ChangeID in milliseconds*/
    3964         272 :         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
    3965             :                                     info2->sharename, &r->change_id);
    3966             : 
    3967         272 :         r->last_error                        = WERR_OK;
    3968         272 :         r->status                    = nt_printq_status(status.status);
    3969         272 :         r->enumerate_network_printers        = 0x0;
    3970         272 :         r->c_setprinter                      = 0x0;
    3971         272 :         r->processor_architecture    = processor_architecture;
    3972         272 :         r->processor_level           = 0x6;          /* 6  ???*/
    3973         272 :         r->ref_ic                    = 0;
    3974         272 :         r->reserved2                 = 0;
    3975         272 :         r->reserved3                 = 0;
    3976             : 
    3977         272 :         return WERR_OK;
    3978             : }
    3979             : 
    3980             : 
    3981             : /********************************************************************
    3982             :  * construct_printer_info1
    3983             :  * fill a spoolss_PrinterInfo1 struct
    3984             : ********************************************************************/
    3985             : 
    3986         439 : static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
    3987             :                                       const struct spoolss_PrinterInfo2 *info2,
    3988             :                                       uint32_t flags,
    3989             :                                       const char *servername,
    3990             :                                       struct spoolss_PrinterInfo1 *r,
    3991             :                                       int snum)
    3992             : {
    3993         311 :         const struct loadparm_substitution *lp_sub =
    3994         128 :                 loadparm_s3_global_substitution();
    3995             :         WERROR result;
    3996             : 
    3997         439 :         r->flags             = flags;
    3998             : 
    3999         439 :         if (info2->comment == NULL || info2->comment[0] == '\0') {
    4000         339 :                 r->comment   = lp_comment(mem_ctx, lp_sub, snum);
    4001             :         } else {
    4002         100 :                 r->comment   = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
    4003             :         }
    4004         439 :         W_ERROR_HAVE_NO_MEMORY(r->comment);
    4005             : 
    4006         439 :         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
    4007         439 :         if (!W_ERROR_IS_OK(result)) {
    4008           0 :                 return result;
    4009             :         }
    4010             : 
    4011         567 :         r->description               = talloc_asprintf(mem_ctx, "%s,%s,%s",
    4012             :                                                   r->name,
    4013         128 :                                                   info2->drivername,
    4014             :                                                   r->comment);
    4015         439 :         W_ERROR_HAVE_NO_MEMORY(r->description);
    4016             : 
    4017         439 :         return WERR_OK;
    4018             : }
    4019             : 
    4020             : /********************************************************************
    4021             :  * construct_printer_info2
    4022             :  * fill a spoolss_PrinterInfo2 struct
    4023             : ********************************************************************/
    4024             : 
    4025        1248 : static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
    4026             :                                       struct messaging_context *msg_ctx,
    4027             :                                       const struct spoolss_PrinterInfo2 *info2,
    4028             :                                       const char *servername,
    4029             :                                       struct spoolss_PrinterInfo2 *r,
    4030             :                                       int snum)
    4031             : {
    4032         930 :         const struct loadparm_substitution *lp_sub =
    4033         318 :                 loadparm_s3_global_substitution();
    4034             :         int count;
    4035             :         print_status_struct status;
    4036             :         WERROR result;
    4037             : 
    4038        1248 :         count = print_queue_length(msg_ctx, snum, &status);
    4039             : 
    4040        1248 :         if (servername) {
    4041         548 :                 r->servername                = talloc_strdup(mem_ctx, servername);
    4042         548 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    4043             :         } else {
    4044         700 :                 r->servername                = NULL;
    4045             :         }
    4046             : 
    4047        1248 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4048        1248 :         if (!W_ERROR_IS_OK(result)) {
    4049           0 :                 return result;
    4050             :         }
    4051             : 
    4052        1248 :         r->sharename         = lp_servicename(mem_ctx, lp_sub, snum);
    4053        1248 :         W_ERROR_HAVE_NO_MEMORY(r->sharename);
    4054        1248 :         r->portname          = talloc_strdup(mem_ctx, info2->portname);
    4055        1248 :         W_ERROR_HAVE_NO_MEMORY(r->portname);
    4056        1248 :         r->drivername                = talloc_strdup(mem_ctx, info2->drivername);
    4057        1248 :         W_ERROR_HAVE_NO_MEMORY(r->drivername);
    4058             : 
    4059        1248 :         if (info2->comment[0] == '\0') {
    4060         852 :                 r->comment   = lp_comment(mem_ctx, lp_sub, snum);
    4061             :         } else {
    4062         396 :                 r->comment   = talloc_strdup(mem_ctx, info2->comment);
    4063             :         }
    4064        1248 :         W_ERROR_HAVE_NO_MEMORY(r->comment);
    4065             : 
    4066        1248 :         r->location  = talloc_strdup(mem_ctx, info2->location);
    4067        1248 :         if (info2->location[0] == '\0') {
    4068        1168 :                 const char *loc = NULL;
    4069             :                 NTSTATUS nt_status;
    4070             : 
    4071        1168 :                 nt_status = printer_list_get_printer(mem_ctx,
    4072         298 :                                                      info2->sharename,
    4073             :                                                      NULL,
    4074             :                                                      &loc,
    4075             :                                                      NULL);
    4076        1168 :                 if (NT_STATUS_IS_OK(nt_status)) {
    4077           0 :                         if (loc != NULL) {
    4078           0 :                                 r->location = talloc_strdup(mem_ctx, loc);
    4079             :                         }
    4080             :                 }
    4081             :         }
    4082        1248 :         W_ERROR_HAVE_NO_MEMORY(r->location);
    4083             : 
    4084        1248 :         r->sepfile           = talloc_strdup(mem_ctx, info2->sepfile);
    4085        1248 :         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
    4086        1248 :         r->printprocessor    = talloc_strdup(mem_ctx, info2->printprocessor);
    4087        1248 :         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
    4088        1248 :         r->datatype          = talloc_strdup(mem_ctx, info2->datatype);
    4089        1248 :         W_ERROR_HAVE_NO_MEMORY(r->datatype);
    4090        1248 :         r->parameters                = talloc_strdup(mem_ctx, info2->parameters);
    4091        1248 :         W_ERROR_HAVE_NO_MEMORY(r->parameters);
    4092             : 
    4093        1248 :         r->attributes                = info2->attributes;
    4094             : 
    4095        1248 :         r->priority          = info2->priority;
    4096        1248 :         r->defaultpriority   = info2->defaultpriority;
    4097        1248 :         r->starttime         = info2->starttime;
    4098        1248 :         r->untiltime         = info2->untiltime;
    4099        1248 :         r->status            = nt_printq_status(status.status);
    4100        1248 :         r->cjobs             = count;
    4101        1248 :         r->averageppm                = info2->averageppm;
    4102             : 
    4103        1248 :         if (info2->devmode != NULL) {
    4104        1166 :                 result = copy_devicemode(mem_ctx,
    4105         318 :                                          info2->devmode,
    4106             :                                          &r->devmode);
    4107        1166 :                 if (!W_ERROR_IS_OK(result)) {
    4108           0 :                         return result;
    4109             :                 }
    4110          82 :         } else if (lp_default_devmode(snum)) {
    4111           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    4112           0 :                                                         info2->printername,
    4113             :                                                         &r->devmode);
    4114           0 :                 if (!W_ERROR_IS_OK(result)) {
    4115           0 :                         return result;
    4116             :                 }
    4117             :         } else {
    4118          82 :                 r->devmode = NULL;
    4119          82 :                 DEBUG(8,("Returning NULL Devicemode!\n"));
    4120             :         }
    4121             : 
    4122        1248 :         compose_devicemode_devicename(r->devmode, r->printername);
    4123             : 
    4124        1248 :         r->secdesc = NULL;
    4125             : 
    4126        1248 :         if (info2->secdesc != NULL) {
    4127             :                 /* don't use talloc_steal() here unless you do a deep steal of all
    4128             :                    the SEC_DESC members */
    4129             : 
    4130        1248 :                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
    4131        1248 :                 if (r->secdesc == NULL) {
    4132           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    4133             :                 }
    4134             :         }
    4135             : 
    4136        1248 :         return WERR_OK;
    4137             : }
    4138             : 
    4139             : /********************************************************************
    4140             :  * construct_printer_info3
    4141             :  * fill a spoolss_PrinterInfo3 struct
    4142             :  ********************************************************************/
    4143             : 
    4144         140 : static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
    4145             :                                       const struct spoolss_PrinterInfo2 *info2,
    4146             :                                       const char *servername,
    4147             :                                       struct spoolss_PrinterInfo3 *r,
    4148             :                                       int snum)
    4149             : {
    4150             :         /* These are the components of the SD we are returning. */
    4151             : 
    4152         140 :         if (info2->secdesc != NULL) {
    4153             :                 /* don't use talloc_steal() here unless you do a deep steal of all
    4154             :                    the SEC_DESC members */
    4155             : 
    4156         140 :                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
    4157         140 :                 if (r->secdesc == NULL) {
    4158           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    4159             :                 }
    4160             :         }
    4161             : 
    4162         140 :         return WERR_OK;
    4163             : }
    4164             : 
    4165             : /********************************************************************
    4166             :  * construct_printer_info4
    4167             :  * fill a spoolss_PrinterInfo4 struct
    4168             :  ********************************************************************/
    4169             : 
    4170         164 : static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
    4171             :                                       const struct spoolss_PrinterInfo2 *info2,
    4172             :                                       const char *servername,
    4173             :                                       struct spoolss_PrinterInfo4 *r,
    4174             :                                       int snum)
    4175             : {
    4176             :         WERROR result;
    4177             : 
    4178         164 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4179         164 :         if (!W_ERROR_IS_OK(result)) {
    4180           0 :                 return result;
    4181             :         }
    4182             : 
    4183         164 :         if (servername) {
    4184           4 :                 r->servername        = talloc_strdup(mem_ctx, servername);
    4185           4 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    4186             :         } else {
    4187         160 :                 r->servername = NULL;
    4188             :         }
    4189             : 
    4190         164 :         r->attributes        = info2->attributes;
    4191             : 
    4192         164 :         return WERR_OK;
    4193             : }
    4194             : 
    4195             : /********************************************************************
    4196             :  * construct_printer_info5
    4197             :  * fill a spoolss_PrinterInfo5 struct
    4198             :  ********************************************************************/
    4199             : 
    4200         164 : static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
    4201             :                                       const struct spoolss_PrinterInfo2 *info2,
    4202             :                                       const char *servername,
    4203             :                                       struct spoolss_PrinterInfo5 *r,
    4204             :                                       int snum)
    4205             : {
    4206             :         WERROR result;
    4207             : 
    4208         164 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4209         164 :         if (!W_ERROR_IS_OK(result)) {
    4210           0 :                 return result;
    4211             :         }
    4212             : 
    4213         164 :         r->portname  = talloc_strdup(mem_ctx, info2->portname);
    4214         164 :         W_ERROR_HAVE_NO_MEMORY(r->portname);
    4215             : 
    4216         164 :         r->attributes        = info2->attributes;
    4217             : 
    4218             :         /*
    4219             :          * These two are not used by NT+ according to MSDN. However the values
    4220             :          * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
    4221             :          */
    4222         164 :         r->device_not_selected_timeout               = 0xafc8; /* 45 sec */
    4223         164 :         r->transmission_retry_timeout                = 0xafc8; /* 45 sec */
    4224             : 
    4225         164 :         return WERR_OK;
    4226             : }
    4227             : 
    4228             : /********************************************************************
    4229             :  * construct_printer_info_6
    4230             :  * fill a spoolss_PrinterInfo6 struct
    4231             :  ********************************************************************/
    4232             : 
    4233          84 : static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
    4234             :                                       struct messaging_context *msg_ctx,
    4235             :                                       const struct spoolss_PrinterInfo2 *info2,
    4236             :                                       const char *servername,
    4237             :                                       struct spoolss_PrinterInfo6 *r,
    4238             :                                       int snum)
    4239             : {
    4240             :         print_status_struct status;
    4241             : 
    4242          84 :         print_queue_length(msg_ctx, snum, &status);
    4243             : 
    4244          84 :         r->status = nt_printq_status(status.status);
    4245             : 
    4246          84 :         return WERR_OK;
    4247             : }
    4248             : 
    4249             : /********************************************************************
    4250             :  * construct_printer_info7
    4251             :  * fill a spoolss_PrinterInfo7 struct
    4252             :  ********************************************************************/
    4253             : 
    4254         108 : static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
    4255             :                                       struct messaging_context *msg_ctx,
    4256             :                                       const char *servername,
    4257             :                                       struct spoolss_PrinterInfo7 *r,
    4258             :                                       int snum)
    4259             : {
    4260          80 :         const struct loadparm_substitution *lp_sub =
    4261          28 :                 loadparm_s3_global_substitution();
    4262             :         const struct auth_session_info *session_info;
    4263         108 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    4264             :         char *printer;
    4265             :         WERROR werr;
    4266         108 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    4267         108 :         if (tmp_ctx == NULL) {
    4268           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4269             :         }
    4270             : 
    4271         108 :         session_info = get_session_info_system();
    4272         108 :         SMB_ASSERT(session_info != NULL);
    4273             : 
    4274         108 :         printer = lp_servicename(tmp_ctx, lp_sub, snum);
    4275         108 :         if (printer == NULL) {
    4276           0 :                 DEBUG(0, ("invalid printer snum %d\n", snum));
    4277           0 :                 werr = WERR_INVALID_PARAMETER;
    4278           0 :                 goto out_tmp_free;
    4279             :         }
    4280             : 
    4281         108 :         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
    4282             :                                  servername, printer, &pinfo2)) {
    4283             :                 struct GUID guid;
    4284             :                 char *guidstr;
    4285           0 :                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
    4286             :                                            printer, &guid);
    4287           0 :                 if (!W_ERROR_IS_OK(werr)) {
    4288             :                         /*
    4289             :                          * If we do not have a GUID entry in the registry, then
    4290             :                          * try to retrieve it from AD and store it now.
    4291             :                          */
    4292           0 :                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
    4293             :                                                         &guid);
    4294           0 :                         if (!W_ERROR_IS_OK(werr)) {
    4295           0 :                                 DBG_NOTICE("Failed to retrieve GUID for "
    4296             :                                            "printer [%s] from AD - %s\n",
    4297             :                                            printer,
    4298             :                                            win_errstr(werr));
    4299           0 :                                 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
    4300             :                                         /*
    4301             :                                          * If we did not find it in AD, then it
    4302             :                                          * is unpublished and we should reflect
    4303             :                                          * this in the registry and return
    4304             :                                          * success.
    4305             :                                          */
    4306           0 :                                         DBG_WARNING("Unpublish printer [%s]\n",
    4307             :                                                     pinfo2->sharename);
    4308           0 :                                         nt_printer_publish(tmp_ctx,
    4309             :                                                            session_info,
    4310             :                                                            msg_ctx,
    4311             :                                                            pinfo2,
    4312             :                                                            DSPRINT_UNPUBLISH);
    4313           0 :                                         r->guid = talloc_strdup(mem_ctx, "");
    4314           0 :                                         r->action = DSPRINT_UNPUBLISH;
    4315             : 
    4316           0 :                                         if (r->guid == NULL) {
    4317           0 :                                                 werr = WERR_NOT_ENOUGH_MEMORY;
    4318             :                                         } else {
    4319           0 :                                                 werr = WERR_OK;
    4320             :                                         }
    4321             :                                 }
    4322           0 :                                 goto out_tmp_free;
    4323             :                         }
    4324             : 
    4325           0 :                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
    4326           0 :                         if (!W_ERROR_IS_OK(werr)) {
    4327           0 :                                 DEBUG(3, ("failed to store printer %s guid\n",
    4328             :                                           printer));
    4329             :                         }
    4330             :                 }
    4331             : 
    4332             :                 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
    4333           0 :                 guidstr = GUID_string2(mem_ctx, &guid);
    4334           0 :                 if (guidstr == NULL) {
    4335           0 :                         werr = WERR_NOT_ENOUGH_MEMORY;
    4336           0 :                         goto out_tmp_free;
    4337             :                 }
    4338             :                 /* Convert GUID string to uppercase otherwise printers
    4339             :                  * are pruned */
    4340           0 :                 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
    4341           0 :                 r->action = DSPRINT_PUBLISH;
    4342             : 
    4343           0 :                 TALLOC_FREE(guidstr);
    4344             :         } else {
    4345         108 :                 r->guid = talloc_strdup(mem_ctx, "");
    4346         108 :                 r->action = DSPRINT_UNPUBLISH;
    4347             :         }
    4348         108 :         if (r->guid == NULL) {
    4349           0 :                 werr = WERR_NOT_ENOUGH_MEMORY;
    4350           0 :                 goto out_tmp_free;
    4351             :         }
    4352             : 
    4353         108 :         werr = WERR_OK;
    4354         108 : out_tmp_free:
    4355         108 :         talloc_free(tmp_ctx);
    4356         108 :         return werr;
    4357             : }
    4358             : 
    4359             : /********************************************************************
    4360             :  * construct_printer_info8
    4361             :  * fill a spoolss_PrinterInfo8 struct
    4362             :  ********************************************************************/
    4363             : 
    4364        1664 : static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
    4365             :                                       const struct spoolss_PrinterInfo2 *info2,
    4366             :                                       const char *servername,
    4367             :                                       struct spoolss_DeviceModeInfo *r,
    4368             :                                       int snum)
    4369             : {
    4370             :         WERROR result;
    4371             :         const char *printername;
    4372             : 
    4373        1664 :         result = create_printername(mem_ctx, servername, info2->printername, &printername);
    4374        1664 :         if (!W_ERROR_IS_OK(result)) {
    4375           0 :                 return result;
    4376             :         }
    4377             : 
    4378        1664 :         if (info2->devmode != NULL) {
    4379        1656 :                 result = copy_devicemode(mem_ctx,
    4380         416 :                                          info2->devmode,
    4381             :                                          &r->devmode);
    4382        1656 :                 if (!W_ERROR_IS_OK(result)) {
    4383           0 :                         return result;
    4384             :                 }
    4385           8 :         } else if (lp_default_devmode(snum)) {
    4386           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    4387           0 :                                                         info2->printername,
    4388             :                                                         &r->devmode);
    4389           0 :                 if (!W_ERROR_IS_OK(result)) {
    4390           0 :                         return result;
    4391             :                 }
    4392             :         } else {
    4393           8 :                 r->devmode = NULL;
    4394           8 :                 DEBUG(8,("Returning NULL Devicemode!\n"));
    4395             :         }
    4396             : 
    4397        1664 :         compose_devicemode_devicename(r->devmode, printername);
    4398             : 
    4399        1664 :         return WERR_OK;
    4400             : }
    4401             : 
    4402             : /********************************************************************
    4403             :  Spoolss_enumprinters.
    4404             : ********************************************************************/
    4405             : 
    4406         164 : static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
    4407             :                                            const struct auth_session_info *session_info,
    4408             :                                            struct messaging_context *msg_ctx,
    4409             :                                            const char *servername,
    4410             :                                            uint32_t level,
    4411             :                                            uint32_t flags,
    4412             :                                            union spoolss_PrinterInfo **info_p,
    4413             :                                            uint32_t *count_p)
    4414             : {
    4415             :         int snum;
    4416             :         int n_services;
    4417         164 :         union spoolss_PrinterInfo *info = NULL;
    4418         164 :         uint32_t count = 0;
    4419         164 :         WERROR result = WERR_OK;
    4420         164 :         struct dcerpc_binding_handle *b = NULL;
    4421         164 :         TALLOC_CTX *tmp_ctx = NULL;
    4422             : 
    4423         164 :         tmp_ctx = talloc_new(mem_ctx);
    4424         164 :         if (!tmp_ctx) {
    4425           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4426             :         }
    4427             : 
    4428             :         /*
    4429             :          * printer shares are updated on client enumeration. The background
    4430             :          * printer process updates printer_list.tdb at regular intervals.
    4431             :          */
    4432         164 :         become_root();
    4433         164 :         delete_and_reload_printers();
    4434         164 :         unbecome_root();
    4435             : 
    4436         164 :         n_services = lp_numservices();
    4437         164 :         *count_p = 0;
    4438         164 :         *info_p = NULL;
    4439             : 
    4440        9126 :         for (snum = 0; snum < n_services; snum++) {
    4441             : 
    4442             :                 const char *printer;
    4443             :                 struct spoolss_PrinterInfo2 *info2;
    4444             : 
    4445        8962 :                 if (!snum_is_shared_printer(snum)) {
    4446        8087 :                         continue;
    4447             :                 }
    4448             : 
    4449         875 :                 printer = lp_const_servicename(snum);
    4450             : 
    4451         875 :                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
    4452             :                         printer, snum));
    4453             : 
    4454         875 :                 if (b == NULL) {
    4455         164 :                         result = winreg_printer_binding_handle(tmp_ctx,
    4456             :                                                                session_info,
    4457             :                                                                msg_ctx,
    4458             :                                                                &b);
    4459         164 :                         if (!W_ERROR_IS_OK(result)) {
    4460           0 :                                 goto out;
    4461             :                         }
    4462             :                 }
    4463             : 
    4464         875 :                 result = winreg_create_printer(tmp_ctx, b,
    4465             :                                                printer);
    4466         875 :                 if (!W_ERROR_IS_OK(result)) {
    4467           0 :                         goto out;
    4468             :                 }
    4469             : 
    4470         875 :                 info = talloc_realloc(tmp_ctx, info,
    4471             :                                             union spoolss_PrinterInfo,
    4472             :                                             count + 1);
    4473         875 :                 if (!info) {
    4474           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    4475           0 :                         goto out;
    4476             :                 }
    4477             : 
    4478         875 :                 result = winreg_get_printer(tmp_ctx, b,
    4479             :                                             printer, &info2);
    4480         875 :                 if (!W_ERROR_IS_OK(result)) {
    4481           0 :                         goto out;
    4482             :                 }
    4483             : 
    4484         875 :                 switch (level) {
    4485          40 :                 case 0:
    4486          40 :                         result = construct_printer_info0(info, session_info,
    4487             :                                                          msg_ctx, info2,
    4488             :                                                          servername,
    4489          40 :                                                          &info[count].info0, snum);
    4490          40 :                         break;
    4491         355 :                 case 1:
    4492         355 :                         result = construct_printer_info1(info, info2, flags,
    4493             :                                                          servername,
    4494         355 :                                                          &info[count].info1, snum);
    4495         355 :                         break;
    4496         320 :                 case 2:
    4497         320 :                         result = construct_printer_info2(info, msg_ctx, info2,
    4498             :                                                          servername,
    4499         320 :                                                          &info[count].info2, snum);
    4500         320 :                         break;
    4501          80 :                 case 4:
    4502          80 :                         result = construct_printer_info4(info, info2,
    4503             :                                                          servername,
    4504          80 :                                                          &info[count].info4, snum);
    4505          80 :                         break;
    4506          80 :                 case 5:
    4507          80 :                         result = construct_printer_info5(info, info2,
    4508             :                                                          servername,
    4509          80 :                                                          &info[count].info5, snum);
    4510          80 :                         break;
    4511             : 
    4512           0 :                 default:
    4513           0 :                         result = WERR_INVALID_LEVEL;
    4514           0 :                         goto out;
    4515             :                 }
    4516             : 
    4517         875 :                 if (!W_ERROR_IS_OK(result)) {
    4518           0 :                         goto out;
    4519             :                 }
    4520             : 
    4521         875 :                 count++;
    4522             :         }
    4523             : 
    4524         164 : out:
    4525         164 :         if (W_ERROR_IS_OK(result)) {
    4526         164 :                 *info_p = talloc_move(mem_ctx, &info);
    4527         164 :                 *count_p = count;
    4528             :         }
    4529             : 
    4530         164 :         talloc_free(tmp_ctx);
    4531             : 
    4532         164 :         return result;
    4533             : }
    4534             : 
    4535             : /********************************************************************
    4536             :  * handle enumeration of printers at level 0
    4537             :  ********************************************************************/
    4538             : 
    4539           8 : static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
    4540             :                                   const struct auth_session_info *session_info,
    4541             :                                   struct messaging_context *msg_ctx,
    4542             :                                   uint32_t flags,
    4543             :                                   const char *servername,
    4544             :                                   union spoolss_PrinterInfo **info,
    4545             :                                   uint32_t *count)
    4546             : {
    4547           8 :         DEBUG(4,("enum_all_printers_info_0\n"));
    4548             : 
    4549           8 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4550             :                                             servername, 0, flags, info, count);
    4551             : }
    4552             : 
    4553             : 
    4554             : /********************************************************************
    4555             : ********************************************************************/
    4556             : 
    4557          60 : static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
    4558             :                                        const struct auth_session_info *session_info,
    4559             :                                        struct messaging_context *msg_ctx,
    4560             :                                        const char *servername,
    4561             :                                        uint32_t flags,
    4562             :                                        union spoolss_PrinterInfo **info,
    4563             :                                        uint32_t *count)
    4564             : {
    4565          60 :         DEBUG(4,("enum_all_printers_info_1\n"));
    4566             : 
    4567          60 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4568             :                                             servername, 1, flags, info, count);
    4569             : }
    4570             : 
    4571             : /********************************************************************
    4572             :  enum_all_printers_info_1_local.
    4573             : *********************************************************************/
    4574             : 
    4575          60 : static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
    4576             :                                              const struct auth_session_info *session_info,
    4577             :                                              struct messaging_context *msg_ctx,
    4578             :                                              const char *servername,
    4579             :                                              union spoolss_PrinterInfo **info,
    4580             :                                              uint32_t *count)
    4581             : {
    4582          60 :         DEBUG(4,("enum_all_printers_info_1_local\n"));
    4583             : 
    4584          60 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4585             :                                         servername, PRINTER_ENUM_ICON8, info, count);
    4586             : }
    4587             : 
    4588             : /********************************************************************
    4589             :  enum_all_printers_info_1_name.
    4590             : *********************************************************************/
    4591             : 
    4592           0 : static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
    4593             :                                             const struct auth_session_info *session_info,
    4594             :                                             struct messaging_context *msg_ctx,
    4595             :                                             const char *servername,
    4596             :                                             union spoolss_PrinterInfo **info,
    4597             :                                             uint32_t *count)
    4598             : {
    4599           0 :         const char *s = servername;
    4600             : 
    4601           0 :         DEBUG(4,("enum_all_printers_info_1_name\n"));
    4602             : 
    4603           0 :         if (servername != NULL &&
    4604           0 :             (servername[0] == '\\') && (servername[1] == '\\')) {
    4605           0 :                 s = servername + 2;
    4606             :         }
    4607             : 
    4608           0 :         if (!is_myname_or_ipaddr(s)) {
    4609           0 :                 return WERR_INVALID_NAME;
    4610             :         }
    4611             : 
    4612           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4613             :                                         servername, PRINTER_ENUM_ICON8, info, count);
    4614             : }
    4615             : 
    4616             : /********************************************************************
    4617             :  enum_all_printers_info_1_network.
    4618             : *********************************************************************/
    4619             : 
    4620           0 : static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
    4621             :                                                const struct auth_session_info *session_info,
    4622             :                                                struct messaging_context *msg_ctx,
    4623             :                                                const char *servername,
    4624             :                                                union spoolss_PrinterInfo **info,
    4625             :                                                uint32_t *count)
    4626             : {
    4627           0 :         const char *s = servername;
    4628             : 
    4629           0 :         DEBUG(4,("enum_all_printers_info_1_network\n"));
    4630             : 
    4631             :         /* If we respond to a enum_printers level 1 on our name with flags
    4632             :            set to PRINTER_ENUM_REMOTE with a list of printers then these
    4633             :            printers incorrectly appear in the APW browse list.
    4634             :            Specifically the printers for the server appear at the workgroup
    4635             :            level where all the other servers in the domain are
    4636             :            listed. Windows responds to this call with a
    4637             :            WERR_CAN_NOT_COMPLETE so we should do the same. */
    4638             : 
    4639           0 :         if (servername != NULL &&
    4640           0 :             (servername[0] == '\\') && (servername[1] == '\\')) {
    4641           0 :                  s = servername + 2;
    4642             :         }
    4643             : 
    4644           0 :         if (is_myname_or_ipaddr(s)) {
    4645           0 :                  return WERR_CAN_NOT_COMPLETE;
    4646             :         }
    4647             : 
    4648           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4649             :                                         servername, PRINTER_ENUM_NAME, info, count);
    4650             : }
    4651             : 
    4652             : /********************************************************************
    4653             :  * api_spoolss_enumprinters
    4654             :  *
    4655             :  * called from api_spoolss_enumprinters (see this to understand)
    4656             :  ********************************************************************/
    4657             : 
    4658          64 : static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
    4659             :                                        const struct auth_session_info *session_info,
    4660             :                                        struct messaging_context *msg_ctx,
    4661             :                                        const char *servername,
    4662             :                                        union spoolss_PrinterInfo **info,
    4663             :                                        uint32_t *count)
    4664             : {
    4665          64 :         DEBUG(4,("enum_all_printers_info_2\n"));
    4666             : 
    4667          64 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4668             :                                             servername, 2, 0, info, count);
    4669             : }
    4670             : 
    4671             : /********************************************************************
    4672             :  * handle enumeration of printers at level 1
    4673             :  ********************************************************************/
    4674             : 
    4675          60 : static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
    4676             :                                   const struct auth_session_info *session_info,
    4677             :                                   struct messaging_context *msg_ctx,
    4678             :                                   uint32_t flags,
    4679             :                                   const char *servername,
    4680             :                                   union spoolss_PrinterInfo **info,
    4681             :                                   uint32_t *count)
    4682             : {
    4683             :         /* Not all the flags are equals */
    4684             : 
    4685          60 :         if (flags & PRINTER_ENUM_LOCAL) {
    4686          60 :                 return enum_all_printers_info_1_local(mem_ctx, session_info,
    4687             :                                                       msg_ctx, servername, info, count);
    4688             :         }
    4689             : 
    4690           0 :         if (flags & PRINTER_ENUM_NAME) {
    4691           0 :                 return enum_all_printers_info_1_name(mem_ctx, session_info,
    4692             :                                                      msg_ctx, servername, info,
    4693             :                                                      count);
    4694             :         }
    4695             : 
    4696           0 :         if (flags & PRINTER_ENUM_NETWORK) {
    4697           0 :                 return enum_all_printers_info_1_network(mem_ctx, session_info,
    4698             :                                                         msg_ctx, servername, info,
    4699             :                                                         count);
    4700             :         }
    4701             : 
    4702           0 :         return WERR_OK; /* NT4sp5 does that */
    4703             : }
    4704             : 
    4705             : /********************************************************************
    4706             :  * handle enumeration of printers at level 2
    4707             :  ********************************************************************/
    4708             : 
    4709          64 : static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
    4710             :                                   const struct auth_session_info *session_info,
    4711             :                                   struct messaging_context *msg_ctx,
    4712             :                                   uint32_t flags,
    4713             :                                   const char *servername,
    4714             :                                   union spoolss_PrinterInfo **info,
    4715             :                                   uint32_t *count)
    4716             : {
    4717          64 :         if (flags & PRINTER_ENUM_LOCAL) {
    4718             : 
    4719          48 :                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
    4720             :                                                 servername,
    4721             :                                                 info, count);
    4722             :         }
    4723             : 
    4724          16 :         if (flags & PRINTER_ENUM_NAME) {
    4725          16 :                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
    4726           0 :                         return WERR_INVALID_NAME;
    4727             :                 }
    4728             : 
    4729          16 :                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
    4730             :                                                 servername,
    4731             :                                                 info, count);
    4732             :         }
    4733             : 
    4734           0 :         if (flags & PRINTER_ENUM_REMOTE) {
    4735           0 :                 return WERR_INVALID_LEVEL;
    4736             :         }
    4737             : 
    4738           0 :         return WERR_OK;
    4739             : }
    4740             : 
    4741             : /********************************************************************
    4742             :  * handle enumeration of printers at level 4
    4743             :  ********************************************************************/
    4744             : 
    4745          16 : static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
    4746             :                                   const struct auth_session_info *session_info,
    4747             :                                   struct messaging_context *msg_ctx,
    4748             :                                   uint32_t flags,
    4749             :                                   const char *servername,
    4750             :                                   union spoolss_PrinterInfo **info,
    4751             :                                   uint32_t *count)
    4752             : {
    4753          16 :         DEBUG(4,("enum_all_printers_info_4\n"));
    4754             : 
    4755          16 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4756             :                                             servername, 4, flags, info, count);
    4757             : }
    4758             : 
    4759             : 
    4760             : /********************************************************************
    4761             :  * handle enumeration of printers at level 5
    4762             :  ********************************************************************/
    4763             : 
    4764          16 : static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
    4765             :                                   const struct auth_session_info *session_info,
    4766             :                                   struct messaging_context *msg_ctx,
    4767             :                                   uint32_t flags,
    4768             :                                   const char *servername,
    4769             :                                   union spoolss_PrinterInfo **info,
    4770             :                                   uint32_t *count)
    4771             : {
    4772          16 :         DEBUG(4,("enum_all_printers_info_5\n"));
    4773             : 
    4774          16 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4775             :                                             servername, 5, flags, info, count);
    4776             : }
    4777             : 
    4778             : /****************************************************************
    4779             :  _spoolss_EnumPrinters
    4780             : ****************************************************************/
    4781             : 
    4782         164 : WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
    4783             :                              struct spoolss_EnumPrinters *r)
    4784             : {
    4785         164 :         const struct auth_session_info *session_info = get_session_info_system();
    4786             :         WERROR result;
    4787             : 
    4788             :         /* that's an [in out] buffer */
    4789             : 
    4790         164 :         if (!r->in.buffer && (r->in.offered != 0)) {
    4791           0 :                 return WERR_INVALID_PARAMETER;
    4792             :         }
    4793             : 
    4794         164 :         DEBUG(4,("_spoolss_EnumPrinters\n"));
    4795             : 
    4796         164 :         *r->out.needed = 0;
    4797         164 :         *r->out.count = 0;
    4798         164 :         *r->out.info = NULL;
    4799             : 
    4800             :         /*
    4801             :          * Level 1:
    4802             :          *          flags==PRINTER_ENUM_NAME
    4803             :          *           if name=="" then enumerates all printers
    4804             :          *           if name!="" then enumerate the printer
    4805             :          *          flags==PRINTER_ENUM_REMOTE
    4806             :          *          name is NULL, enumerate printers
    4807             :          * Level 2: name!="" enumerates printers, name can't be NULL
    4808             :          * Level 3: doesn't exist
    4809             :          * Level 4: does a local registry lookup
    4810             :          * Level 5: same as Level 2
    4811             :          */
    4812             : 
    4813         164 :         if (r->in.server && r->in.server[0] == '\0') {
    4814          80 :                 r->in.server = NULL;
    4815             :         }
    4816             : 
    4817         164 :         switch (r->in.level) {
    4818           8 :         case 0:
    4819           8 :                 result = enumprinters_level0(p->mem_ctx, session_info,
    4820             :                                              p->msg_ctx, r->in.flags,
    4821             :                                              r->in.server,
    4822             :                                              r->out.info, r->out.count);
    4823           8 :                 break;
    4824          60 :         case 1:
    4825          60 :                 result = enumprinters_level1(p->mem_ctx, session_info,
    4826             :                                              p->msg_ctx, r->in.flags,
    4827             :                                              r->in.server,
    4828             :                                              r->out.info, r->out.count);
    4829          60 :                 break;
    4830          64 :         case 2:
    4831          64 :                 result = enumprinters_level2(p->mem_ctx, session_info,
    4832             :                                              p->msg_ctx, r->in.flags,
    4833             :                                              r->in.server,
    4834             :                                              r->out.info, r->out.count);
    4835          64 :                 break;
    4836          16 :         case 4:
    4837          16 :                 result = enumprinters_level4(p->mem_ctx, session_info,
    4838             :                                              p->msg_ctx, r->in.flags,
    4839             :                                              r->in.server,
    4840             :                                              r->out.info, r->out.count);
    4841          16 :                 break;
    4842          16 :         case 5:
    4843          16 :                 result = enumprinters_level5(p->mem_ctx, session_info,
    4844             :                                              p->msg_ctx, r->in.flags,
    4845             :                                              r->in.server,
    4846             :                                              r->out.info, r->out.count);
    4847          16 :                 break;
    4848           0 :         default:
    4849           0 :                 return WERR_INVALID_LEVEL;
    4850             :         }
    4851             : 
    4852         164 :         if (!W_ERROR_IS_OK(result)) {
    4853           0 :                 return result;
    4854             :         }
    4855             : 
    4856         164 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    4857             :                                                      spoolss_EnumPrinters,
    4858             :                                                      *r->out.info, r->in.level,
    4859             :                                                      *r->out.count);
    4860         164 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    4861         164 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    4862             : 
    4863         164 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    4864             : }
    4865             : 
    4866             : /****************************************************************
    4867             :  _spoolss_GetPrinter
    4868             : ****************************************************************/
    4869             : 
    4870        3480 : WERROR _spoolss_GetPrinter(struct pipes_struct *p,
    4871             :                            struct spoolss_GetPrinter *r)
    4872             : {
    4873        3480 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    4874        3480 :         struct spoolss_PrinterInfo2 *info2 = NULL;
    4875        3480 :         WERROR result = WERR_OK;
    4876             :         int snum;
    4877             : 
    4878             :         /* that's an [in out] buffer */
    4879             : 
    4880        3480 :         if (!r->in.buffer && (r->in.offered != 0)) {
    4881           0 :                 result = WERR_INVALID_PARAMETER;
    4882           0 :                 goto err_info_free;
    4883             :         }
    4884             : 
    4885        3480 :         *r->out.needed = 0;
    4886             : 
    4887        3480 :         if (Printer == NULL) {
    4888           0 :                 result = WERR_INVALID_HANDLE;
    4889           0 :                 goto err_info_free;
    4890             :         }
    4891             : 
    4892        3480 :         if (Printer->printer_type == SPLHND_SERVER) {
    4893             : 
    4894             :                 struct dcerpc_binding_handle *b;
    4895             : 
    4896          72 :                 if (r->in.level != 3) {
    4897          32 :                         result = WERR_INVALID_LEVEL;
    4898          56 :                         goto err_info_free;
    4899             :                 }
    4900             : 
    4901          40 :                 result = winreg_printer_binding_handle(p->mem_ctx,
    4902             :                                                        get_session_info_system(),
    4903             :                                                        p->msg_ctx,
    4904             :                                                        &b);
    4905          40 :                 if (!W_ERROR_IS_OK(result)) {
    4906           0 :                         goto err_info_free;
    4907             :                 }
    4908             : 
    4909          40 :                 result = winreg_get_printserver_secdesc(p->mem_ctx,
    4910             :                                                         b,
    4911          40 :                                                         &r->out.info->info3.secdesc);
    4912          40 :                 if (!W_ERROR_IS_OK(result)) {
    4913           0 :                         goto err_info_free;
    4914             :                 }
    4915             : 
    4916          40 :                 goto done;
    4917             :         }
    4918             : 
    4919        3408 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    4920           0 :                 result = WERR_INVALID_HANDLE;
    4921           0 :                 goto err_info_free;
    4922             :         }
    4923             : 
    4924        3408 :         result = winreg_get_printer_internal(p->mem_ctx,
    4925             :                                     get_session_info_system(),
    4926             :                                     p->msg_ctx,
    4927             :                                     lp_const_servicename(snum),
    4928             :                                     &info2);
    4929        3408 :         if (!W_ERROR_IS_OK(result)) {
    4930           0 :                 goto err_info_free;
    4931             :         }
    4932             : 
    4933        3408 :         switch (r->in.level) {
    4934         232 :         case 0:
    4935         405 :                 result = construct_printer_info0(p->mem_ctx,
    4936             :                                                  get_session_info_system(),
    4937             :                                                  p->msg_ctx,
    4938             :                                                  info2,
    4939             :                                                  Printer->servername,
    4940         232 :                                                  &r->out.info->info0,
    4941             :                                                  snum);
    4942         232 :                 break;
    4943          84 :         case 1:
    4944         146 :                 result = construct_printer_info1(p->mem_ctx, info2,
    4945             :                                                  PRINTER_ENUM_ICON8,
    4946             :                                                  Printer->servername,
    4947          84 :                                                  &r->out.info->info1, snum);
    4948          84 :                 break;
    4949         928 :         case 2:
    4950        1623 :                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
    4951             :                                                  Printer->servername,
    4952         928 :                                                  &r->out.info->info2, snum);
    4953         928 :                 break;
    4954         140 :         case 3:
    4955         244 :                 result = construct_printer_info3(p->mem_ctx, info2,
    4956             :                                                  Printer->servername,
    4957         140 :                                                  &r->out.info->info3, snum);
    4958         140 :                 break;
    4959          84 :         case 4:
    4960         146 :                 result = construct_printer_info4(p->mem_ctx, info2,
    4961             :                                                  Printer->servername,
    4962          84 :                                                  &r->out.info->info4, snum);
    4963          84 :                 break;
    4964          84 :         case 5:
    4965         146 :                 result = construct_printer_info5(p->mem_ctx, info2,
    4966             :                                                  Printer->servername,
    4967          84 :                                                  &r->out.info->info5, snum);
    4968          84 :                 break;
    4969          84 :         case 6:
    4970         146 :                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
    4971             :                                                  Printer->servername,
    4972          84 :                                                  &r->out.info->info6, snum);
    4973          84 :                 break;
    4974         108 :         case 7:
    4975         188 :                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
    4976             :                                                  Printer->servername,
    4977         108 :                                                  &r->out.info->info7, snum);
    4978         108 :                 break;
    4979        1664 :         case 8:
    4980        2912 :                 result = construct_printer_info8(p->mem_ctx, info2,
    4981             :                                                  Printer->servername,
    4982        1664 :                                                  &r->out.info->info8, snum);
    4983        1664 :                 break;
    4984           0 :         default:
    4985           0 :                 result = WERR_INVALID_LEVEL;
    4986           0 :                 break;
    4987             :         }
    4988        3408 :         TALLOC_FREE(info2);
    4989             : 
    4990        3408 :         if (!W_ERROR_IS_OK(result)) {
    4991           0 :                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
    4992             :                           r->in.level, win_errstr(result)));
    4993           0 :                 goto err_info_free;
    4994             :         }
    4995        3408 :  done:
    4996        3448 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
    4997             :                                                r->out.info, r->in.level);
    4998        3448 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    4999             : 
    5000        3448 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    5001             : 
    5002          32 : err_info_free:
    5003          32 :         TALLOC_FREE(r->out.info);
    5004          32 :         return result;
    5005             : }
    5006             : 
    5007             : /********************************************************************
    5008             :  ********************************************************************/
    5009             : 
    5010             : #define FILL_DRIVER_STRING(mem_ctx, in, out) \
    5011             :         do { \
    5012             :                 if (in && strlen(in)) { \
    5013             :                         out = talloc_strdup(mem_ctx, in); \
    5014             :                 } else { \
    5015             :                         out = talloc_strdup(mem_ctx, ""); \
    5016             :                 } \
    5017             :                 W_ERROR_HAVE_NO_MEMORY(out); \
    5018             :         } while (0);
    5019             : 
    5020             : #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
    5021             :         do { \
    5022             :                 if (in && strlen(in)) { \
    5023             :                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
    5024             :                 } else { \
    5025             :                         out = talloc_strdup(mem_ctx, ""); \
    5026             :                 } \
    5027             :                 W_ERROR_HAVE_NO_MEMORY(out); \
    5028             :         } while (0);
    5029             : 
    5030           0 : static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
    5031             :                                                   const char **string_array,
    5032             :                                                   const char ***presult,
    5033             :                                                   const char *cservername,
    5034             :                                                   const char *arch,
    5035             :                                                   int version)
    5036             : {
    5037             :         size_t i;
    5038           0 :         size_t num_strings = 0;
    5039           0 :         const char **array = NULL;
    5040             : 
    5041           0 :         if (string_array == NULL) {
    5042           0 :                 return WERR_INVALID_PARAMETER;
    5043             :         }
    5044             : 
    5045           0 :         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
    5046           0 :                 const char *str = NULL;
    5047             : 
    5048           0 :                 if (cservername == NULL || arch == NULL) {
    5049           0 :                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
    5050             :                 } else {
    5051           0 :                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
    5052             :                 }
    5053             : 
    5054           0 :                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
    5055           0 :                         TALLOC_FREE(array);
    5056           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    5057             :                 }
    5058             :         }
    5059             : 
    5060           0 :         if (i > 0) {
    5061           0 :                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
    5062             :                              &array, &num_strings);
    5063             :         }
    5064             : 
    5065           0 :         if (presult != NULL) {
    5066           0 :                 *presult = array;
    5067             :         } else {
    5068           0 :                 talloc_free(array);
    5069             :         }
    5070             : 
    5071           0 :         return WERR_OK;
    5072             : }
    5073             : 
    5074             : /********************************************************************
    5075             :  * fill a spoolss_DriverInfo1 struct
    5076             :  ********************************************************************/
    5077             : 
    5078           0 : static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
    5079             :                                         struct spoolss_DriverInfo1 *r,
    5080             :                                         const struct spoolss_DriverInfo8 *driver,
    5081             :                                         const char *servername)
    5082             : {
    5083           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5084           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5085             : 
    5086           0 :         return WERR_OK;
    5087             : }
    5088             : 
    5089             : /********************************************************************
    5090             :  * fill a spoolss_DriverInfo2 struct
    5091             :  ********************************************************************/
    5092             : 
    5093           0 : static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
    5094             :                                         struct spoolss_DriverInfo2 *r,
    5095             :                                         const struct spoolss_DriverInfo8 *driver,
    5096             :                                         const char *servername)
    5097             : 
    5098             : {
    5099           0 :         const char *cservername = canon_servername(servername);
    5100             : 
    5101           0 :         r->version           = driver->version;
    5102             : 
    5103           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5104           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5105           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5106           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5107             : 
    5108           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5109             :                                driver->architecture,
    5110             :                                driver->version,
    5111             :                                driver->driver_path,
    5112             :                                r->driver_path);
    5113             : 
    5114           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5115             :                                driver->architecture,
    5116             :                                driver->version,
    5117             :                                driver->data_file,
    5118             :                                r->data_file);
    5119             : 
    5120           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5121             :                                driver->architecture,
    5122             :                                driver->version,
    5123             :                                driver->config_file,
    5124             :                                r->config_file);
    5125             : 
    5126           0 :         return WERR_OK;
    5127             : }
    5128             : 
    5129             : /********************************************************************
    5130             :  * fill a spoolss_DriverInfo3 struct
    5131             :  ********************************************************************/
    5132             : 
    5133           0 : static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
    5134             :                                         struct spoolss_DriverInfo3 *r,
    5135             :                                         const struct spoolss_DriverInfo8 *driver,
    5136             :                                         const char *servername)
    5137             : {
    5138           0 :         const char *cservername = canon_servername(servername);
    5139             : 
    5140           0 :         r->version           = driver->version;
    5141             : 
    5142           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5143           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5144           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5145           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5146             : 
    5147           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5148             :                                driver->architecture,
    5149             :                                driver->version,
    5150             :                                driver->driver_path,
    5151             :                                r->driver_path);
    5152             : 
    5153           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5154             :                                driver->architecture,
    5155             :                                driver->version,
    5156             :                                driver->data_file,
    5157             :                                r->data_file);
    5158             : 
    5159           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5160             :                                driver->architecture,
    5161             :                                driver->version,
    5162             :                                driver->config_file,
    5163             :                                r->config_file);
    5164             : 
    5165           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5166             :                                driver->architecture,
    5167             :                                driver->version,
    5168             :                                driver->help_file,
    5169             :                                r->help_file);
    5170             : 
    5171           0 :         FILL_DRIVER_STRING(mem_ctx,
    5172             :                            driver->monitor_name,
    5173             :                            r->monitor_name);
    5174             : 
    5175           0 :         FILL_DRIVER_STRING(mem_ctx,
    5176             :                            driver->default_datatype,
    5177             :                            r->default_datatype);
    5178             : 
    5179           0 :         return string_array_from_driver_info(mem_ctx,
    5180           0 :                                              driver->dependent_files,
    5181             :                                              &r->dependent_files,
    5182             :                                              cservername,
    5183           0 :                                              driver->architecture,
    5184           0 :                                              driver->version);
    5185             : }
    5186             : 
    5187             : /********************************************************************
    5188             :  * fill a spoolss_DriverInfo4 struct
    5189             :  ********************************************************************/
    5190             : 
    5191           0 : static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
    5192             :                                         struct spoolss_DriverInfo4 *r,
    5193             :                                         const struct spoolss_DriverInfo8 *driver,
    5194             :                                         const char *servername)
    5195             : {
    5196           0 :         const char *cservername = canon_servername(servername);
    5197             :         WERROR result;
    5198             : 
    5199           0 :         r->version           = driver->version;
    5200             : 
    5201           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5202           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5203           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5204           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5205             : 
    5206           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5207             :                                driver->architecture,
    5208             :                                driver->version,
    5209             :                                driver->driver_path,
    5210             :                                r->driver_path);
    5211             : 
    5212           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5213             :                                driver->architecture,
    5214             :                                driver->version,
    5215             :                                driver->data_file,
    5216             :                                r->data_file);
    5217             : 
    5218           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5219             :                                driver->architecture,
    5220             :                                driver->version,
    5221             :                                driver->config_file,
    5222             :                                r->config_file);
    5223             : 
    5224           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5225             :                                driver->architecture,
    5226             :                                driver->version,
    5227             :                                driver->help_file,
    5228             :                                r->help_file);
    5229             : 
    5230           0 :         result = string_array_from_driver_info(mem_ctx,
    5231           0 :                                                driver->dependent_files,
    5232             :                                                &r->dependent_files,
    5233             :                                                cservername,
    5234           0 :                                                driver->architecture,
    5235           0 :                                                driver->version);
    5236           0 :         if (!W_ERROR_IS_OK(result)) {
    5237           0 :                 return result;
    5238             :         }
    5239             : 
    5240           0 :         FILL_DRIVER_STRING(mem_ctx,
    5241             :                            driver->monitor_name,
    5242             :                            r->monitor_name);
    5243             : 
    5244           0 :         FILL_DRIVER_STRING(mem_ctx,
    5245             :                            driver->default_datatype,
    5246             :                            r->default_datatype);
    5247             : 
    5248             : 
    5249           0 :         result = string_array_from_driver_info(mem_ctx,
    5250           0 :                                                driver->previous_names,
    5251             :                                                &r->previous_names,
    5252             :                                                NULL, NULL, 0);
    5253             : 
    5254           0 :         return result;
    5255             : }
    5256             : 
    5257             : /********************************************************************
    5258             :  * fill a spoolss_DriverInfo5 struct
    5259             :  ********************************************************************/
    5260             : 
    5261           0 : static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
    5262             :                                         struct spoolss_DriverInfo5 *r,
    5263             :                                         const struct spoolss_DriverInfo8 *driver,
    5264             :                                         const char *servername)
    5265             : {
    5266           0 :         const char *cservername = canon_servername(servername);
    5267             : 
    5268           0 :         r->version           = driver->version;
    5269             : 
    5270           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5271           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5272           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5273           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5274             : 
    5275           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5276             :                                driver->architecture,
    5277             :                                driver->version,
    5278             :                                driver->driver_path,
    5279             :                                r->driver_path);
    5280             : 
    5281           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5282             :                                driver->architecture,
    5283             :                                driver->version,
    5284             :                                driver->data_file,
    5285             :                                r->data_file);
    5286             : 
    5287           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5288             :                                driver->architecture,
    5289             :                                driver->version,
    5290             :                                driver->config_file,
    5291             :                                r->config_file);
    5292             : 
    5293           0 :         r->driver_attributes = 0;
    5294           0 :         r->config_version    = 0;
    5295           0 :         r->driver_version    = 0;
    5296             : 
    5297           0 :         return WERR_OK;
    5298             : }
    5299             : /********************************************************************
    5300             :  * fill a spoolss_DriverInfo6 struct
    5301             :  ********************************************************************/
    5302             : 
    5303           0 : static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
    5304             :                                         struct spoolss_DriverInfo6 *r,
    5305             :                                         const struct spoolss_DriverInfo8 *driver,
    5306             :                                         const char *servername)
    5307             : {
    5308           0 :         const char *cservername = canon_servername(servername);
    5309             :         WERROR result;
    5310             : 
    5311           0 :         r->version           = driver->version;
    5312             : 
    5313           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5314           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5315           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5316           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5317             : 
    5318           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5319             :                                driver->architecture,
    5320             :                                driver->version,
    5321             :                                driver->driver_path,
    5322             :                                r->driver_path);
    5323             : 
    5324           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5325             :                                driver->architecture,
    5326             :                                driver->version,
    5327             :                                driver->data_file,
    5328             :                                r->data_file);
    5329             : 
    5330           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5331             :                                driver->architecture,
    5332             :                                driver->version,
    5333             :                                driver->config_file,
    5334             :                                r->config_file);
    5335             : 
    5336           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5337             :                                driver->architecture,
    5338             :                                driver->version,
    5339             :                                driver->help_file,
    5340             :                                r->help_file);
    5341             : 
    5342           0 :         FILL_DRIVER_STRING(mem_ctx,
    5343             :                            driver->monitor_name,
    5344             :                            r->monitor_name);
    5345             : 
    5346           0 :         FILL_DRIVER_STRING(mem_ctx,
    5347             :                            driver->default_datatype,
    5348             :                            r->default_datatype);
    5349             : 
    5350           0 :         result = string_array_from_driver_info(mem_ctx,
    5351           0 :                                                driver->dependent_files,
    5352             :                                                &r->dependent_files,
    5353             :                                                cservername,
    5354           0 :                                                driver->architecture,
    5355           0 :                                                driver->version);
    5356           0 :         if (!W_ERROR_IS_OK(result)) {
    5357           0 :                 return result;
    5358             :         }
    5359             : 
    5360           0 :         result = string_array_from_driver_info(mem_ctx,
    5361           0 :                                                driver->previous_names,
    5362             :                                                &r->previous_names,
    5363             :                                                NULL, NULL, 0);
    5364           0 :         if (!W_ERROR_IS_OK(result)) {
    5365           0 :                 return result;
    5366             :         }
    5367             : 
    5368           0 :         r->driver_date               = driver->driver_date;
    5369           0 :         r->driver_version    = driver->driver_version;
    5370             : 
    5371           0 :         FILL_DRIVER_STRING(mem_ctx,
    5372             :                            driver->manufacturer_name,
    5373             :                            r->manufacturer_name);
    5374           0 :         FILL_DRIVER_STRING(mem_ctx,
    5375             :                            driver->manufacturer_url,
    5376             :                            r->manufacturer_url);
    5377           0 :         FILL_DRIVER_STRING(mem_ctx,
    5378             :                            driver->hardware_id,
    5379             :                            r->hardware_id);
    5380           0 :         FILL_DRIVER_STRING(mem_ctx,
    5381             :                            driver->provider,
    5382             :                            r->provider);
    5383             : 
    5384           0 :         return WERR_OK;
    5385             : }
    5386             : 
    5387             : /********************************************************************
    5388             :  * fill a spoolss_DriverInfo8 struct
    5389             :  ********************************************************************/
    5390             : 
    5391           0 : static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
    5392             :                                         struct spoolss_DriverInfo8 *r,
    5393             :                                         const struct spoolss_DriverInfo8 *driver,
    5394             :                                         const char *servername)
    5395             : {
    5396           0 :         const char *cservername = canon_servername(servername);
    5397             :         WERROR result;
    5398             : 
    5399           0 :         r->version           = driver->version;
    5400             : 
    5401           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5402           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5403           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5404           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5405             : 
    5406           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5407             :                                driver->architecture,
    5408             :                                driver->version,
    5409             :                                driver->driver_path,
    5410             :                                r->driver_path);
    5411             : 
    5412           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5413             :                                driver->architecture,
    5414             :                                driver->version,
    5415             :                                driver->data_file,
    5416             :                                r->data_file);
    5417             : 
    5418           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5419             :                                driver->architecture,
    5420             :                                driver->version,
    5421             :                                driver->config_file,
    5422             :                                r->config_file);
    5423             : 
    5424           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5425             :                                driver->architecture,
    5426             :                                driver->version,
    5427             :                                driver->help_file,
    5428             :                                r->help_file);
    5429             : 
    5430           0 :         FILL_DRIVER_STRING(mem_ctx,
    5431             :                            driver->monitor_name,
    5432             :                            r->monitor_name);
    5433             : 
    5434           0 :         FILL_DRIVER_STRING(mem_ctx,
    5435             :                            driver->default_datatype,
    5436             :                            r->default_datatype);
    5437             : 
    5438           0 :         result = string_array_from_driver_info(mem_ctx,
    5439           0 :                                                driver->dependent_files,
    5440             :                                                &r->dependent_files,
    5441             :                                                cservername,
    5442           0 :                                                driver->architecture,
    5443           0 :                                                driver->version);
    5444           0 :         if (!W_ERROR_IS_OK(result)) {
    5445           0 :                 return result;
    5446             :         }
    5447             : 
    5448           0 :         result = string_array_from_driver_info(mem_ctx,
    5449           0 :                                                driver->previous_names,
    5450             :                                                &r->previous_names,
    5451             :                                                NULL, NULL, 0);
    5452           0 :         if (!W_ERROR_IS_OK(result)) {
    5453           0 :                 return result;
    5454             :         }
    5455             : 
    5456           0 :         r->driver_date               = driver->driver_date;
    5457           0 :         r->driver_version    = driver->driver_version;
    5458             : 
    5459           0 :         FILL_DRIVER_STRING(mem_ctx,
    5460             :                            driver->manufacturer_name,
    5461             :                            r->manufacturer_name);
    5462           0 :         FILL_DRIVER_STRING(mem_ctx,
    5463             :                            driver->manufacturer_url,
    5464             :                            r->manufacturer_url);
    5465           0 :         FILL_DRIVER_STRING(mem_ctx,
    5466             :                            driver->hardware_id,
    5467             :                            r->hardware_id);
    5468           0 :         FILL_DRIVER_STRING(mem_ctx,
    5469             :                            driver->provider,
    5470             :                            r->provider);
    5471             : 
    5472           0 :         FILL_DRIVER_STRING(mem_ctx,
    5473             :                            driver->print_processor,
    5474             :                            r->print_processor);
    5475           0 :         FILL_DRIVER_STRING(mem_ctx,
    5476             :                            driver->vendor_setup,
    5477             :                            r->vendor_setup);
    5478             : 
    5479           0 :         result = string_array_from_driver_info(mem_ctx,
    5480           0 :                                                driver->color_profiles,
    5481             :                                                &r->color_profiles,
    5482             :                                                NULL, NULL, 0);
    5483           0 :         if (!W_ERROR_IS_OK(result)) {
    5484           0 :                 return result;
    5485             :         }
    5486             : 
    5487           0 :         FILL_DRIVER_STRING(mem_ctx,
    5488             :                            driver->inf_path,
    5489             :                            r->inf_path);
    5490             : 
    5491           0 :         r->printer_driver_attributes = driver->printer_driver_attributes;
    5492             : 
    5493           0 :         result = string_array_from_driver_info(mem_ctx,
    5494           0 :                                                driver->core_driver_dependencies,
    5495             :                                                &r->core_driver_dependencies,
    5496             :                                                NULL, NULL, 0);
    5497           0 :         if (!W_ERROR_IS_OK(result)) {
    5498           0 :                 return result;
    5499             :         }
    5500             : 
    5501           0 :         r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
    5502           0 :         r->min_inbox_driver_ver_version      = driver->min_inbox_driver_ver_version;
    5503             : 
    5504           0 :         return WERR_OK;
    5505             : }
    5506             : 
    5507             : #if 0 /* disabled until marshalling issues are resolved - gd */
    5508             : /********************************************************************
    5509             :  ********************************************************************/
    5510             : 
    5511             : static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
    5512             :                                           struct spoolss_DriverFileInfo *r,
    5513             :                                           const char *cservername,
    5514             :                                           const char *file_name,
    5515             :                                           enum spoolss_DriverFileType file_type,
    5516             :                                           uint32_t file_version)
    5517             : {
    5518             :         r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
    5519             :                                           cservername, file_name);
    5520             :         W_ERROR_HAVE_NO_MEMORY(r->file_name);
    5521             :         r->file_type = file_type;
    5522             :         r->file_version      = file_version;
    5523             : 
    5524             :         return WERR_OK;
    5525             : }
    5526             : 
    5527             : /********************************************************************
    5528             :  ********************************************************************/
    5529             : 
    5530             : static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
    5531             :                                                  const struct spoolss_DriverInfo8 *driver,
    5532             :                                                  const char *cservername,
    5533             :                                                  struct spoolss_DriverFileInfo **info_p,
    5534             :                                                  uint32_t *count_p)
    5535             : {
    5536             :         struct spoolss_DriverFileInfo *info = NULL;
    5537             :         uint32_t count = 0;
    5538             :         WERROR result;
    5539             :         uint32_t i;
    5540             : 
    5541             :         *info_p = NULL;
    5542             :         *count_p = 0;
    5543             : 
    5544             :         if (strlen(driver->driver_path)) {
    5545             :                 info = talloc_realloc(mem_ctx, info,
    5546             :                                             struct spoolss_DriverFileInfo,
    5547             :                                             count + 1);
    5548             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5549             :                 result = fill_spoolss_DriverFileInfo(info,
    5550             :                                                      &info[count],
    5551             :                                                      cservername,
    5552             :                                                      driver->driver_path,
    5553             :                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
    5554             :                                                      0);
    5555             :                 W_ERROR_NOT_OK_RETURN(result);
    5556             :                 count++;
    5557             :         }
    5558             : 
    5559             :         if (strlen(driver->config_file)) {
    5560             :                 info = talloc_realloc(mem_ctx, info,
    5561             :                                             struct spoolss_DriverFileInfo,
    5562             :                                             count + 1);
    5563             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5564             :                 result = fill_spoolss_DriverFileInfo(info,
    5565             :                                                      &info[count],
    5566             :                                                      cservername,
    5567             :                                                      driver->config_file,
    5568             :                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
    5569             :                                                      0);
    5570             :                 W_ERROR_NOT_OK_RETURN(result);
    5571             :                 count++;
    5572             :         }
    5573             : 
    5574             :         if (strlen(driver->data_file)) {
    5575             :                 info = talloc_realloc(mem_ctx, info,
    5576             :                                             struct spoolss_DriverFileInfo,
    5577             :                                             count + 1);
    5578             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5579             :                 result = fill_spoolss_DriverFileInfo(info,
    5580             :                                                      &info[count],
    5581             :                                                      cservername,
    5582             :                                                      driver->data_file,
    5583             :                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
    5584             :                                                      0);
    5585             :                 W_ERROR_NOT_OK_RETURN(result);
    5586             :                 count++;
    5587             :         }
    5588             : 
    5589             :         if (strlen(driver->help_file)) {
    5590             :                 info = talloc_realloc(mem_ctx, info,
    5591             :                                             struct spoolss_DriverFileInfo,
    5592             :                                             count + 1);
    5593             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5594             :                 result = fill_spoolss_DriverFileInfo(info,
    5595             :                                                      &info[count],
    5596             :                                                      cservername,
    5597             :                                                      driver->help_file,
    5598             :                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
    5599             :                                                      0);
    5600             :                 W_ERROR_NOT_OK_RETURN(result);
    5601             :                 count++;
    5602             :         }
    5603             : 
    5604             :         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
    5605             :                 info = talloc_realloc(mem_ctx, info,
    5606             :                                             struct spoolss_DriverFileInfo,
    5607             :                                             count + 1);
    5608             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5609             :                 result = fill_spoolss_DriverFileInfo(info,
    5610             :                                                      &info[count],
    5611             :                                                      cservername,
    5612             :                                                      driver->dependent_files[i],
    5613             :                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
    5614             :                                                      0);
    5615             :                 W_ERROR_NOT_OK_RETURN(result);
    5616             :                 count++;
    5617             :         }
    5618             : 
    5619             :         *info_p = info;
    5620             :         *count_p = count;
    5621             : 
    5622             :         return WERR_OK;
    5623             : }
    5624             : 
    5625             : /********************************************************************
    5626             :  * fill a spoolss_DriverInfo101 struct
    5627             :  ********************************************************************/
    5628             : 
    5629             : static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
    5630             :                                           struct spoolss_DriverInfo101 *r,
    5631             :                                           const struct spoolss_DriverInfo8 *driver,
    5632             :                                           const char *servername)
    5633             : {
    5634             :         const char *cservername = canon_servername(servername);
    5635             :         WERROR result;
    5636             : 
    5637             :         r->version           = driver->version;
    5638             : 
    5639             :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5640             :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5641             :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5642             :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5643             : 
    5644             :         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
    5645             :                                                     cservername,
    5646             :                                                     &r->file_info,
    5647             :                                                     &r->file_count);
    5648             :         if (!W_ERROR_IS_OK(result)) {
    5649             :                 return result;
    5650             :         }
    5651             : 
    5652             :         FILL_DRIVER_STRING(mem_ctx,
    5653             :                            driver->monitor_name,
    5654             :                            r->monitor_name);
    5655             : 
    5656             :         FILL_DRIVER_STRING(mem_ctx,
    5657             :                            driver->default_datatype,
    5658             :                            r->default_datatype);
    5659             : 
    5660             :         result = string_array_from_driver_info(mem_ctx,
    5661             :                                                driver->previous_names,
    5662             :                                                &r->previous_names,
    5663             :                                                NULL, NULL, 0);
    5664             :         if (!W_ERROR_IS_OK(result)) {
    5665             :                 return result;
    5666             :         }
    5667             : 
    5668             :         r->driver_date               = driver->driver_date;
    5669             :         r->driver_version    = driver->driver_version;
    5670             : 
    5671             :         FILL_DRIVER_STRING(mem_ctx,
    5672             :                            driver->manufacturer_name,
    5673             :                            r->manufacturer_name);
    5674             :         FILL_DRIVER_STRING(mem_ctx,
    5675             :                            driver->manufacturer_url,
    5676             :                            r->manufacturer_url);
    5677             :         FILL_DRIVER_STRING(mem_ctx,
    5678             :                            driver->hardware_id,
    5679             :                            r->hardware_id);
    5680             :         FILL_DRIVER_STRING(mem_ctx,
    5681             :                            driver->provider,
    5682             :                            r->provider);
    5683             : 
    5684             :         return WERR_OK;
    5685             : }
    5686             : #endif
    5687             : /********************************************************************
    5688             :  ********************************************************************/
    5689             : 
    5690           4 : static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
    5691             :                                                   const struct auth_session_info *session_info,
    5692             :                                                   struct messaging_context *msg_ctx,
    5693             :                                                   uint32_t level,
    5694             :                                                   union spoolss_DriverInfo *r,
    5695             :                                                   int snum,
    5696             :                                                   const char *servername,
    5697             :                                                   const char *architecture,
    5698             :                                                   uint32_t version)
    5699             : {
    5700           4 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    5701             :         struct spoolss_DriverInfo8 *driver;
    5702             :         WERROR result;
    5703             :         struct dcerpc_binding_handle *b;
    5704           4 :         TALLOC_CTX *tmp_ctx = NULL;
    5705             : 
    5706           4 :         if (level == 101) {
    5707           4 :                 return WERR_INVALID_LEVEL;
    5708             :         }
    5709             : 
    5710           0 :         tmp_ctx = talloc_new(mem_ctx);
    5711           0 :         if (!tmp_ctx) {
    5712           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    5713             :         }
    5714             : 
    5715           0 :         result = winreg_printer_binding_handle(tmp_ctx,
    5716             :                                                session_info,
    5717             :                                                msg_ctx,
    5718             :                                                &b);
    5719           0 :         if (!W_ERROR_IS_OK(result)) {
    5720           0 :                 goto done;
    5721             :         }
    5722             : 
    5723           0 :         result = winreg_get_printer(tmp_ctx, b,
    5724             :                                     lp_const_servicename(snum),
    5725             :                                     &pinfo2);
    5726           0 :         if (!W_ERROR_IS_OK(result)) {
    5727           0 :                 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
    5728             :                         lp_const_servicename(snum), win_errstr(result));
    5729           0 :                 result = WERR_INVALID_PRINTER_NAME;
    5730           0 :                 goto done;
    5731             :         }
    5732             : 
    5733           0 :         if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
    5734           0 :                 result = WERR_UNKNOWN_PRINTER_DRIVER;
    5735           0 :                 goto done;
    5736             :         }
    5737             : 
    5738           0 :         DBG_INFO("Construct printer driver [%s] for [%s]\n",
    5739             :                  pinfo2->drivername,
    5740             :                  pinfo2->sharename);
    5741             : 
    5742           0 :         result = winreg_get_driver(tmp_ctx, b,
    5743             :                                    architecture,
    5744           0 :                                    pinfo2->drivername, version, &driver);
    5745             : 
    5746           0 :         DBG_INFO("winreg_get_driver() status: %s\n",
    5747             :                  win_errstr(result));
    5748             : 
    5749           0 :         if (!W_ERROR_IS_OK(result)) {
    5750             :                 /*
    5751             :                  * Is this a W2k client ?
    5752             :                  */
    5753             : 
    5754           0 :                 if (version < 3) {
    5755           0 :                         result = WERR_UNKNOWN_PRINTER_DRIVER;
    5756           0 :                         goto done;
    5757             :                 }
    5758             : 
    5759             :                 /* Yes - try again with a WinNT driver. */
    5760           0 :                 version = 2;
    5761           0 :                 result = winreg_get_driver(tmp_ctx, b,
    5762             :                                            architecture,
    5763           0 :                                            pinfo2->drivername,
    5764             :                                            version, &driver);
    5765           0 :                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
    5766             :                         win_errstr(result)));
    5767           0 :                 if (!W_ERROR_IS_OK(result)) {
    5768           0 :                         result = WERR_UNKNOWN_PRINTER_DRIVER;
    5769           0 :                         goto done;
    5770             :                 }
    5771             :         }
    5772             : 
    5773             :         /* these are allocated on mem_ctx and not tmp_ctx because they are
    5774             :          * the 'return value' and need to utlive this call */
    5775           0 :         switch (level) {
    5776           0 :         case 1:
    5777           0 :                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
    5778           0 :                 break;
    5779           0 :         case 2:
    5780           0 :                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
    5781           0 :                 break;
    5782           0 :         case 3:
    5783           0 :                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
    5784           0 :                 break;
    5785           0 :         case 4:
    5786           0 :                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
    5787           0 :                 break;
    5788           0 :         case 5:
    5789           0 :                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
    5790           0 :                 break;
    5791           0 :         case 6:
    5792           0 :                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
    5793           0 :                 break;
    5794           0 :         case 8:
    5795           0 :                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
    5796           0 :                 break;
    5797             : #if 0 /* disabled until marshalling issues are resolved - gd */
    5798             :         case 101:
    5799             :                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
    5800             :                 break;
    5801             : #endif
    5802           0 :         default:
    5803           0 :                 result = WERR_INVALID_LEVEL;
    5804           0 :                 break;
    5805             :         }
    5806             : 
    5807           0 : done:
    5808           0 :         talloc_free(tmp_ctx);
    5809           0 :         return result;
    5810             : }
    5811             : 
    5812             : /****************************************************************
    5813             :  _spoolss_GetPrinterDriver2
    5814             : ****************************************************************/
    5815             : 
    5816           4 : WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
    5817             :                                   struct spoolss_GetPrinterDriver2 *r)
    5818             : {
    5819             :         struct printer_handle *printer;
    5820             :         WERROR result;
    5821           4 :         uint32_t version = r->in.client_major_version;
    5822             : 
    5823             :         int snum;
    5824             : 
    5825             :         /* that's an [in out] buffer */
    5826             : 
    5827           4 :         if (!r->in.buffer && (r->in.offered != 0)) {
    5828           0 :                 result = WERR_INVALID_PARAMETER;
    5829           0 :                 goto err_info_free;
    5830             :         }
    5831             : 
    5832           4 :         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
    5833             : 
    5834           4 :         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
    5835           0 :                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
    5836           0 :                 result = WERR_INVALID_PRINTER_NAME;
    5837           0 :                 goto err_info_free;
    5838             :         }
    5839             : 
    5840           4 :         *r->out.needed = 0;
    5841           4 :         *r->out.server_major_version = 0;
    5842           4 :         *r->out.server_minor_version = 0;
    5843             : 
    5844           4 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    5845           0 :                 result = WERR_INVALID_HANDLE;
    5846           0 :                 goto err_info_free;
    5847             :         }
    5848             : 
    5849           4 :         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
    5850           0 :                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
    5851             :                         "downgrading to v3\n"));
    5852           0 :                 version = SPOOLSS_DRIVER_VERSION_200X;
    5853             :         }
    5854             : 
    5855           4 :         result = construct_printer_driver_info_level(p->mem_ctx,
    5856             :                                                      get_session_info_system(),
    5857             :                                                      p->msg_ctx,
    5858             :                                                      r->in.level, r->out.info,
    5859             :                                                      snum, printer->servername,
    5860             :                                                      r->in.architecture,
    5861             :                                                      version);
    5862           4 :         if (!W_ERROR_IS_OK(result)) {
    5863           4 :                 goto err_info_free;
    5864             :         }
    5865             : 
    5866           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
    5867             :                                                r->out.info, r->in.level);
    5868           0 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    5869             : 
    5870           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    5871             : 
    5872           4 : err_info_free:
    5873           4 :         TALLOC_FREE(r->out.info);
    5874           4 :         return result;
    5875             : }
    5876             : 
    5877             : 
    5878             : /****************************************************************
    5879             :  _spoolss_StartPagePrinter
    5880             : ****************************************************************/
    5881             : 
    5882        1920 : WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
    5883             :                                  struct spoolss_StartPagePrinter *r)
    5884             : {
    5885        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5886             : 
    5887        1920 :         if (!Printer) {
    5888           0 :                 DEBUG(3,("_spoolss_StartPagePrinter: "
    5889             :                         "Error in startpageprinter printer handle\n"));
    5890           0 :                 return WERR_INVALID_HANDLE;
    5891             :         }
    5892             : 
    5893        1920 :         Printer->page_started = true;
    5894        1920 :         return WERR_OK;
    5895             : }
    5896             : 
    5897             : /****************************************************************
    5898             :  _spoolss_EndPagePrinter
    5899             : ****************************************************************/
    5900             : 
    5901        1920 : WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
    5902             :                                struct spoolss_EndPagePrinter *r)
    5903             : {
    5904             :         int snum;
    5905             : 
    5906        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5907             : 
    5908        1920 :         if (!Printer) {
    5909           0 :                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
    5910             :                         OUR_HANDLE(r->in.handle)));
    5911           0 :                 return WERR_INVALID_HANDLE;
    5912             :         }
    5913             : 
    5914        1920 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    5915           0 :                 return WERR_INVALID_HANDLE;
    5916             : 
    5917        1920 :         Printer->page_started = false;
    5918        1920 :         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
    5919             : 
    5920        1920 :         return WERR_OK;
    5921             : }
    5922             : 
    5923             : /****************************************************************
    5924             :  _spoolss_StartDocPrinter
    5925             : ****************************************************************/
    5926             : 
    5927         668 : WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
    5928             :                                 struct spoolss_StartDocPrinter *r)
    5929             : {
    5930             :         struct spoolss_DocumentInfo1 *info_1;
    5931             :         int snum;
    5932         668 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5933             :         WERROR werr;
    5934             :         char *rhost;
    5935             :         int rc;
    5936             : 
    5937         668 :         if (!Printer) {
    5938           0 :                 DEBUG(2,("_spoolss_StartDocPrinter: "
    5939             :                         "Invalid handle (%s:%u:%u)\n",
    5940             :                         OUR_HANDLE(r->in.handle)));
    5941           0 :                 return WERR_INVALID_HANDLE;
    5942             :         }
    5943             : 
    5944         668 :         if (Printer->jobid) {
    5945           0 :                 DEBUG(2, ("_spoolss_StartDocPrinter: "
    5946             :                           "StartDocPrinter called twice! "
    5947             :                           "(existing jobid = %d)\n", Printer->jobid));
    5948           0 :                 return WERR_INVALID_HANDLE;
    5949             :         }
    5950             : 
    5951         668 :         if (r->in.info_ctr->level != 1) {
    5952           0 :                 return WERR_INVALID_LEVEL;
    5953             :         }
    5954             : 
    5955         668 :         info_1 = r->in.info_ctr->info.info1;
    5956             : 
    5957             :         /*
    5958             :          * a nice thing with NT is it doesn't listen to what you tell it.
    5959             :          * when asked to send _only_ RAW datas, it tries to send datas
    5960             :          * in EMF format.
    5961             :          *
    5962             :          * So I add checks like in NT Server ...
    5963             :          */
    5964             : 
    5965         668 :         if (info_1->datatype) {
    5966             :                 /*
    5967             :                  * The v4 driver model used in Windows 8 declares print jobs
    5968             :                  * intended to bypass the XPS processing layer by setting
    5969             :                  * datatype to "XPS_PASS" instead of "RAW".
    5970             :                  */
    5971         668 :                 if ((strcmp(info_1->datatype, "RAW") != 0)
    5972         224 :                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
    5973           0 :                         *r->out.job_id = 0;
    5974           0 :                         return WERR_INVALID_DATATYPE;
    5975             :                 }
    5976             :         }
    5977             : 
    5978             :         /* get the share number of the printer */
    5979         668 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    5980           0 :                 return WERR_INVALID_HANDLE;
    5981             :         }
    5982             : 
    5983         668 :         rc = get_remote_hostname(p->remote_address,
    5984             :                                  &rhost,
    5985             :                                  p->mem_ctx);
    5986         668 :         if (rc < 0) {
    5987           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    5988             :         }
    5989         668 :         if (strequal(rhost,"UNKNOWN")) {
    5990           0 :                 rhost = tsocket_address_inet_addr_string(p->remote_address,
    5991             :                                                          p->mem_ctx);
    5992           0 :                 if (rhost == NULL) {
    5993           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    5994             :                 }
    5995             :         }
    5996             : 
    5997         668 :         werr = print_job_start(p->session_info,
    5998             :                                p->msg_ctx,
    5999             :                                rhost,
    6000             :                                snum,
    6001             :                                info_1->document_name,
    6002             :                                info_1->output_file,
    6003             :                                Printer->devmode,
    6004             :                                &Printer->jobid);
    6005             : 
    6006             :         /* An error occurred in print_job_start() so return an appropriate
    6007             :            NT error code. */
    6008             : 
    6009         668 :         if (!W_ERROR_IS_OK(werr)) {
    6010           0 :                 return werr;
    6011             :         }
    6012             : 
    6013         668 :         Printer->document_started = true;
    6014         668 :         *r->out.job_id = Printer->jobid;
    6015             : 
    6016         668 :         return WERR_OK;
    6017             : }
    6018             : 
    6019             : /****************************************************************
    6020             :  _spoolss_EndDocPrinter
    6021             : ****************************************************************/
    6022             : 
    6023         668 : WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
    6024             :                               struct spoolss_EndDocPrinter *r)
    6025             : {
    6026         668 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6027             :         NTSTATUS status;
    6028             :         int snum;
    6029             : 
    6030         668 :         if (!Printer) {
    6031           0 :                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
    6032             :                         OUR_HANDLE(r->in.handle)));
    6033           0 :                 return WERR_INVALID_HANDLE;
    6034             :         }
    6035             : 
    6036         668 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    6037           0 :                 return WERR_INVALID_HANDLE;
    6038             :         }
    6039             : 
    6040         668 :         Printer->document_started = false;
    6041         668 :         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
    6042         664 :         if (!NT_STATUS_IS_OK(status)) {
    6043         288 :                 DEBUG(2, ("_spoolss_EndDocPrinter: "
    6044             :                           "print_job_end failed [%s]\n",
    6045             :                           nt_errstr(status)));
    6046             :         }
    6047             : 
    6048         664 :         Printer->jobid = 0;
    6049         664 :         return ntstatus_to_werror(status);
    6050             : }
    6051             : 
    6052             : /****************************************************************
    6053             :  _spoolss_WritePrinter
    6054             : ****************************************************************/
    6055             : 
    6056        1920 : WERROR _spoolss_WritePrinter(struct pipes_struct *p,
    6057             :                              struct spoolss_WritePrinter *r)
    6058             : {
    6059             :         ssize_t buffer_written;
    6060             :         int snum;
    6061        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6062             : 
    6063        1920 :         if (!Printer) {
    6064           0 :                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
    6065             :                         OUR_HANDLE(r->in.handle)));
    6066           0 :                 *r->out.num_written = r->in._data_size;
    6067           0 :                 return WERR_INVALID_HANDLE;
    6068             :         }
    6069             : 
    6070        1920 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    6071           0 :                 return WERR_INVALID_HANDLE;
    6072             : 
    6073             :         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
    6074        3360 :         buffer_written = print_job_write(global_event_context(),p->msg_ctx,
    6075             :                                                    snum, Printer->jobid,
    6076        1920 :                                                    (const char *)r->in.data.data,
    6077        1920 :                                                    (size_t)r->in._data_size);
    6078        1920 :         if (buffer_written == (ssize_t)-1) {
    6079           0 :                 *r->out.num_written = 0;
    6080           0 :                 if (errno == ENOSPC)
    6081           0 :                         return WERR_NO_SPOOL_SPACE;
    6082             :                 else
    6083           0 :                         return WERR_ACCESS_DENIED;
    6084             :         }
    6085             : 
    6086        1920 :         *r->out.num_written = r->in._data_size;
    6087             : 
    6088        1920 :         return WERR_OK;
    6089             : }
    6090             : 
    6091             : /********************************************************************
    6092             :  * api_spoolss_getprinter
    6093             :  * called from the spoolss dispatcher
    6094             :  *
    6095             :  ********************************************************************/
    6096             : 
    6097         104 : static WERROR control_printer(struct policy_handle *handle, uint32_t command,
    6098             :                               struct pipes_struct *p)
    6099             : {
    6100         104 :         const struct auth_session_info *session_info = p->session_info;
    6101             :         int snum;
    6102         104 :         WERROR errcode = WERR_INVALID_FUNCTION;
    6103         104 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6104             : 
    6105         104 :         if (!Printer) {
    6106           0 :                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
    6107             :                         OUR_HANDLE(handle)));
    6108           0 :                 return WERR_INVALID_HANDLE;
    6109             :         }
    6110             : 
    6111         104 :         if (!get_printer_snum(p, handle, &snum, NULL))
    6112           0 :                 return WERR_INVALID_HANDLE;
    6113             : 
    6114         104 :         switch (command) {
    6115          52 :         case SPOOLSS_PRINTER_CONTROL_PAUSE:
    6116          52 :                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
    6117          52 :                 break;
    6118          40 :         case SPOOLSS_PRINTER_CONTROL_RESUME:
    6119             :         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
    6120          40 :                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
    6121          40 :                 break;
    6122          12 :         case SPOOLSS_PRINTER_CONTROL_PURGE:
    6123          12 :                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
    6124          12 :                 break;
    6125           0 :         default:
    6126           0 :                 return WERR_INVALID_LEVEL;
    6127             :         }
    6128             : 
    6129         104 :         return errcode;
    6130             : }
    6131             : 
    6132             : 
    6133             : /****************************************************************
    6134             :  _spoolss_AbortPrinter
    6135             :  * From MSDN: "Deletes printer's spool file if printer is configured
    6136             :  * for spooling"
    6137             : ****************************************************************/
    6138             : 
    6139           0 : WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
    6140             :                              struct spoolss_AbortPrinter *r)
    6141             : {
    6142           0 :         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6143             :         int             snum;
    6144           0 :         WERROR          errcode = WERR_OK;
    6145             : 
    6146           0 :         if (!Printer) {
    6147           0 :                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
    6148             :                         OUR_HANDLE(r->in.handle)));
    6149           0 :                 return WERR_INVALID_HANDLE;
    6150             :         }
    6151             : 
    6152           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    6153           0 :                 return WERR_INVALID_HANDLE;
    6154             : 
    6155           0 :         if (!Printer->document_started) {
    6156           0 :                 return WERR_SPL_NO_STARTDOC;
    6157             :         }
    6158             : 
    6159           0 :         errcode = print_job_delete(p->session_info,
    6160             :                                    p->msg_ctx,
    6161             :                                    snum,
    6162             :                                    Printer->jobid);
    6163             : 
    6164           0 :         return errcode;
    6165             : }
    6166             : 
    6167             : /********************************************************************
    6168             :  * called by spoolss_api_setprinter
    6169             :  * when updating a printer description
    6170             :  ********************************************************************/
    6171             : 
    6172         120 : static WERROR update_printer_sec(struct policy_handle *handle,
    6173             :                                  struct pipes_struct *p,
    6174             :                                  struct sec_desc_buf *secdesc_ctr)
    6175             : {
    6176         120 :         struct spoolss_security_descriptor *new_secdesc = NULL;
    6177         120 :         struct spoolss_security_descriptor *old_secdesc = NULL;
    6178         120 :         const char *printer = NULL;
    6179             :         WERROR result;
    6180         120 :         int snum = -1;
    6181         120 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6182             :         struct dcerpc_binding_handle *b;
    6183         120 :         TALLOC_CTX *tmp_ctx = NULL;
    6184         120 :         bool ok = false;
    6185             : 
    6186         120 :         if (!Printer) {
    6187           0 :                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
    6188             :                          OUR_HANDLE(handle)));
    6189             : 
    6190           0 :                 result = WERR_INVALID_HANDLE;
    6191           0 :                 goto done;
    6192             :         }
    6193             : 
    6194         120 :         if (secdesc_ctr == NULL) {
    6195           0 :                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
    6196           0 :                 result = WERR_INVALID_PARAMETER;
    6197           0 :                 goto done;
    6198             :         }
    6199             : 
    6200         120 :         switch (Printer->printer_type) {
    6201           8 :         case SPLHND_SERVER:
    6202           8 :                 break;
    6203         112 :         case SPLHND_PRINTER:
    6204         112 :                 if (!get_printer_snum(p, handle, &snum, NULL)) {
    6205           0 :                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
    6206             :                                  OUR_HANDLE(handle)));
    6207           0 :                         result = WERR_INVALID_HANDLE;
    6208           0 :                         goto done;
    6209             :                 }
    6210         112 :                 printer = lp_const_servicename(snum);
    6211         112 :                 break;
    6212           0 :         default:
    6213           0 :                 break;
    6214             :         }
    6215             : 
    6216             :         /* Check the user has permissions to change the security
    6217             :            descriptor.  By experimentation with two NT machines, the user
    6218             :            requires Full Access to the printer to change security
    6219             :            information. */
    6220             : 
    6221         120 :         switch (Printer->printer_type) {
    6222           8 :         case SPLHND_SERVER:
    6223           8 :                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
    6224           8 :                 break;
    6225         112 :         case SPLHND_PRINTER:
    6226         112 :                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
    6227         112 :                 break;
    6228           0 :         default:
    6229           0 :                 break;
    6230             :         }
    6231             : 
    6232         120 :         if (!ok) {
    6233           0 :                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
    6234             :                         "(access_granted: 0x%08x)\n", Printer->access_granted));
    6235           0 :                 result = WERR_ACCESS_DENIED;
    6236           0 :                 goto done;
    6237             :         }
    6238             : 
    6239         120 :         tmp_ctx = talloc_new(p->mem_ctx);
    6240         120 :         if (!tmp_ctx) {
    6241           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6242             :         }
    6243             : 
    6244         120 :         result = winreg_printer_binding_handle(tmp_ctx,
    6245             :                                                get_session_info_system(),
    6246             :                                                p->msg_ctx,
    6247             :                                                &b);
    6248         120 :         if (!W_ERROR_IS_OK(result)) {
    6249           0 :                 goto done;
    6250             :         }
    6251             : 
    6252             :         /* NT seems to like setting the security descriptor even though
    6253             :            nothing may have actually changed. */
    6254             : 
    6255         120 :         if (printer != NULL) {
    6256         112 :                 result = winreg_get_printer_secdesc(tmp_ctx, b,
    6257             :                                                     printer,
    6258             :                                                     &old_secdesc);
    6259             :         } else {
    6260           8 :                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
    6261             :                                                         &old_secdesc);
    6262             :         }
    6263         120 :         if (!W_ERROR_IS_OK(result)) {
    6264           0 :                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
    6265           0 :                 result = WERR_INVALID_HANDLE;
    6266           0 :                 goto done;
    6267             :         }
    6268             : 
    6269         120 :         if (DEBUGLEVEL >= 10) {
    6270             :                 struct dom_sid_buf buf;
    6271             :                 struct security_acl *the_acl;
    6272             :                 int i;
    6273             : 
    6274           0 :                 the_acl = old_secdesc->dacl;
    6275           0 :                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
    6276             :                            printer, the_acl->num_aces));
    6277             : 
    6278           0 :                 for (i = 0; i < the_acl->num_aces; i++) {
    6279           0 :                         DEBUG(10, ("%s 0x%08x\n",
    6280             :                                    dom_sid_str_buf(
    6281             :                                            &the_acl->aces[i].trustee,
    6282             :                                            &buf),
    6283             :                                   the_acl->aces[i].access_mask));
    6284             :                 }
    6285             : 
    6286           0 :                 the_acl = secdesc_ctr->sd->dacl;
    6287             : 
    6288           0 :                 if (the_acl) {
    6289           0 :                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
    6290             :                                    printer, the_acl->num_aces));
    6291             : 
    6292           0 :                         for (i = 0; i < the_acl->num_aces; i++) {
    6293           0 :                                 DEBUG(10, ("%s 0x%08x\n",
    6294             :                                            dom_sid_str_buf(
    6295             :                                                    &the_acl->aces[i].trustee,
    6296             :                                                    &buf),
    6297             :                                            the_acl->aces[i].access_mask));
    6298             :                         }
    6299             :                 } else {
    6300           0 :                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
    6301             :                 }
    6302             :         }
    6303             : 
    6304         120 :         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
    6305         120 :         if (new_secdesc == NULL) {
    6306           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    6307           0 :                 goto done;
    6308             :         }
    6309             : 
    6310         120 :         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
    6311          56 :                 result = WERR_OK;
    6312          56 :                 goto done;
    6313             :         }
    6314             : 
    6315          64 :         if (printer != NULL) {
    6316          56 :                 result = winreg_set_printer_secdesc(tmp_ctx, b,
    6317             :                                                     printer,
    6318             :                                                     new_secdesc);
    6319             :         } else {
    6320           8 :                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
    6321             :                                                         new_secdesc);
    6322             :         }
    6323             : 
    6324         120 : done:
    6325         120 :         talloc_free(tmp_ctx);
    6326         120 :         return result;
    6327             : }
    6328             : 
    6329             : /********************************************************************
    6330             :  Canonicalize printer info from a client
    6331             :  ********************************************************************/
    6332             : 
    6333         100 : static bool check_printer_ok(TALLOC_CTX *mem_ctx,
    6334             :                              struct spoolss_SetPrinterInfo2 *info2,
    6335             :                              int snum)
    6336             : {
    6337             :         fstring printername;
    6338             :         const char *p;
    6339             : 
    6340         100 :         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
    6341             :                 "portname=%s drivername=%s comment=%s location=%s\n",
    6342             :                 info2->servername, info2->printername, info2->sharename,
    6343             :                 info2->portname, info2->drivername, info2->comment,
    6344             :                 info2->location));
    6345             : 
    6346             :         /* we force some elements to "correct" values */
    6347         100 :         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
    6348         100 :         if (info2->servername == NULL) {
    6349           0 :                 return false;
    6350             :         }
    6351         100 :         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
    6352         100 :         if (info2->sharename == NULL) {
    6353           0 :                 return false;
    6354             :         }
    6355             : 
    6356             :         /* check to see if we allow printername != sharename */
    6357         100 :         if (lp_force_printername(snum)) {
    6358           0 :                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
    6359             :                                         lp_netbios_name(), info2->sharename);
    6360             :         } else {
    6361             :                 /* make sure printername is in \\server\printername format */
    6362         100 :                 fstrcpy(printername, info2->printername);
    6363         100 :                 p = printername;
    6364         100 :                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
    6365          56 :                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
    6366          56 :                                 p++;
    6367             :                 }
    6368             : 
    6369         100 :                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
    6370             :                                         lp_netbios_name(), p);
    6371             :         }
    6372         100 :         if (info2->printername == NULL) {
    6373           0 :                 return false;
    6374             :         }
    6375             : 
    6376         100 :         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
    6377         100 :         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
    6378             : 
    6379         100 :         return true;
    6380             : }
    6381             : 
    6382             : /****************************************************************************
    6383             : ****************************************************************************/
    6384             : 
    6385           0 : static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
    6386             : {
    6387           0 :         const struct loadparm_substitution *lp_sub =
    6388           0 :                 loadparm_s3_global_substitution();
    6389           0 :         char *cmd = lp_addport_command(talloc_tos(), lp_sub);
    6390           0 :         char *command = NULL;
    6391             :         int ret;
    6392           0 :         bool is_print_op = false;
    6393             : 
    6394           0 :         if ( !*cmd ) {
    6395           0 :                 return WERR_ACCESS_DENIED;
    6396             :         }
    6397             : 
    6398           0 :         command = talloc_asprintf(ctx,
    6399             :                         "%s \"%s\" \"%s\"", cmd, portname, uri );
    6400           0 :         if (!command) {
    6401           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6402             :         }
    6403             : 
    6404           0 :         if ( token )
    6405           0 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
    6406             : 
    6407           0 :         DEBUG(10,("Running [%s]\n", command));
    6408             : 
    6409             :         /********* BEGIN SePrintOperatorPrivilege **********/
    6410             : 
    6411           0 :         if ( is_print_op )
    6412           0 :                 become_root();
    6413             : 
    6414           0 :         ret = smbrun(command, NULL, NULL);
    6415             : 
    6416           0 :         if ( is_print_op )
    6417           0 :                 unbecome_root();
    6418             : 
    6419             :         /********* END SePrintOperatorPrivilege **********/
    6420             : 
    6421           0 :         DEBUGADD(10,("returned [%d]\n", ret));
    6422             : 
    6423           0 :         TALLOC_FREE(command);
    6424             : 
    6425           0 :         if ( ret != 0 ) {
    6426           0 :                 return WERR_ACCESS_DENIED;
    6427             :         }
    6428             : 
    6429           0 :         return WERR_OK;
    6430             : }
    6431             : 
    6432             : /****************************************************************************
    6433             : ****************************************************************************/
    6434             : 
    6435        4198 : static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
    6436             :                                    int snum)
    6437             : {
    6438             :         /*
    6439             :          * As we do not know if we are embedded in the file server process
    6440             :          * or not, we have to pretend that all shares are in use.
    6441             :          */
    6442        4198 :         return true;
    6443             : }
    6444             : 
    6445          66 : static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
    6446             :                              struct spoolss_SetPrinterInfo2 *info2,
    6447             :                              const char *remote_machine,
    6448             :                              struct messaging_context *msg_ctx)
    6449             : {
    6450          52 :         const struct loadparm_substitution *lp_sub =
    6451          14 :                 loadparm_s3_global_substitution();
    6452          66 :         char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
    6453             :         char **qlines;
    6454          66 :         char *command = NULL;
    6455             :         int numlines;
    6456             :         int ret;
    6457             :         int fd;
    6458          66 :         bool is_print_op = false;
    6459             : 
    6460          66 :         if (!remote_machine) {
    6461           0 :                 return false;
    6462             :         }
    6463             : 
    6464          66 :         command = talloc_asprintf(ctx,
    6465             :                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
    6466             :                         cmd, info2->printername, info2->sharename,
    6467             :                         info2->portname, info2->drivername,
    6468             :                         info2->location, info2->comment, remote_machine);
    6469          66 :         if (!command) {
    6470           0 :                 return false;
    6471             :         }
    6472             : 
    6473          66 :         if ( token )
    6474          66 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
    6475             : 
    6476          66 :         DEBUG(10,("Running [%s]\n", command));
    6477             : 
    6478             :         /********* BEGIN SePrintOperatorPrivilege **********/
    6479             : 
    6480          66 :         if ( is_print_op )
    6481           0 :                 become_root();
    6482             : 
    6483          66 :         ret = smbrun(command, &fd, NULL);
    6484          66 :         if (ret == 0) {
    6485             :                 /* Tell everyone we updated smb.conf. */
    6486          66 :                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
    6487             :         }
    6488             : 
    6489          66 :         if ( is_print_op )
    6490           0 :                 unbecome_root();
    6491             : 
    6492             :         /********* END SePrintOperatorPrivilege **********/
    6493             : 
    6494          66 :         DEBUGADD(10,("returned [%d]\n", ret));
    6495             : 
    6496          66 :         TALLOC_FREE(command);
    6497             : 
    6498          66 :         if ( ret != 0 ) {
    6499           0 :                 if (fd != -1)
    6500           0 :                         close(fd);
    6501           0 :                 return false;
    6502             :         }
    6503             : 
    6504             :         /* reload our services immediately */
    6505          66 :         become_root();
    6506          66 :         reload_services(NULL, spoolss_conn_snum_used, false);
    6507          66 :         unbecome_root();
    6508             : 
    6509          66 :         numlines = 0;
    6510             :         /* Get lines and convert them back to dos-codepage */
    6511          66 :         qlines = fd_lines_load(fd, &numlines, 0, NULL);
    6512          66 :         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
    6513          66 :         close(fd);
    6514             : 
    6515             :         /* Set the portname to what the script says the portname should be. */
    6516             :         /* but don't require anything to be return from the script exit a good error code */
    6517             : 
    6518          66 :         if (numlines) {
    6519             :                 /* Set the portname to what the script says the portname should be. */
    6520           0 :                 info2->portname = talloc_strdup(ctx, qlines[0]);
    6521           0 :                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
    6522             :         }
    6523             : 
    6524          66 :         TALLOC_FREE(qlines);
    6525          66 :         return true;
    6526             : }
    6527             : 
    6528         100 : static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
    6529             :                                const struct auth_session_info *session_info,
    6530             :                                struct messaging_context *msg_ctx,
    6531             :                                int snum,
    6532             :                                struct spoolss_SetPrinterInfo2 *printer,
    6533             :                                struct spoolss_PrinterInfo2 *old_printer)
    6534             : {
    6535         100 :         bool force_update = (old_printer == NULL);
    6536             :         const char *dnsdomname;
    6537             :         const char *longname;
    6538             :         const char *uncname;
    6539             :         const char *spooling;
    6540             :         DATA_BLOB buffer;
    6541         100 :         WERROR result = WERR_OK;
    6542             :         struct dcerpc_binding_handle *b;
    6543             :         TALLOC_CTX *tmp_ctx;
    6544             :         bool ok;
    6545             : 
    6546         100 :         tmp_ctx = talloc_new(mem_ctx);
    6547         100 :         if (!tmp_ctx) {
    6548           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6549             :         }
    6550             : 
    6551         100 :         result = winreg_printer_binding_handle(tmp_ctx,
    6552             :                                                session_info,
    6553             :                                                msg_ctx,
    6554             :                                                &b);
    6555         100 :         if (!W_ERROR_IS_OK(result)) {
    6556           0 :                 goto done;
    6557             :         }
    6558             : 
    6559         100 :         if (printer->drivername != NULL &&
    6560          84 :             (force_update ||
    6561          84 :              !strequal(printer->drivername, old_printer->drivername))) {
    6562          24 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
    6563          24 :                 if (!ok) {
    6564           0 :                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
    6565           0 :                         result = WERR_INVALID_DATA;
    6566           0 :                         goto done;
    6567             :                 }
    6568          24 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6569             :                                           printer->sharename,
    6570             :                                           SPOOL_DSSPOOLER_KEY,
    6571             :                                           SPOOL_REG_DRIVERNAME,
    6572             :                                           REG_SZ,
    6573             :                                           buffer.data,
    6574          24 :                                           buffer.length);
    6575          24 :                 if (!W_ERROR_IS_OK(result)) {
    6576           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
    6577           0 :                         goto done;
    6578             :                 }
    6579             : 
    6580          24 :                 if (!force_update) {
    6581           8 :                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
    6582             :                                 printer->drivername));
    6583             : 
    6584           8 :                         notify_printer_driver(global_event_context(), msg_ctx,
    6585           8 :                                               snum, printer->drivername ?
    6586             :                                               printer->drivername : "");
    6587             :                 }
    6588             :         }
    6589             : 
    6590         100 :         if (printer->comment != NULL &&
    6591          84 :             (force_update ||
    6592          84 :              !strequal(printer->comment, old_printer->comment))) {
    6593          34 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
    6594          34 :                 if (!ok) {
    6595           0 :                         DEBUG(0, ("comment data corrupted\n"));
    6596           0 :                         result = WERR_INVALID_DATA;
    6597           0 :                         goto done;
    6598             :                 }
    6599          34 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6600             :                                           printer->sharename,
    6601             :                                           SPOOL_DSSPOOLER_KEY,
    6602             :                                           SPOOL_REG_DESCRIPTION,
    6603             :                                           REG_SZ,
    6604             :                                           buffer.data,
    6605          34 :                                           buffer.length);
    6606          34 :                 if (!W_ERROR_IS_OK(result)) {
    6607           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
    6608           0 :                         goto done;
    6609             :                 }
    6610             : 
    6611          34 :                 if (!force_update) {
    6612          34 :                         notify_printer_comment(global_event_context(), msg_ctx,
    6613          34 :                                                snum, printer->comment ?
    6614             :                                                printer->comment : "");
    6615             :                 }
    6616             :         }
    6617             : 
    6618         100 :         if (printer->sharename != NULL &&
    6619          84 :             (force_update ||
    6620          84 :              !strequal(printer->sharename, old_printer->sharename))) {
    6621          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
    6622          16 :                 if (!ok) {
    6623           0 :                         DEBUG(0, ("sharename data corrupted\n"));
    6624           0 :                         result = WERR_INVALID_DATA;
    6625           0 :                         goto done;
    6626             :                 }
    6627          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6628             :                                           printer->sharename,
    6629             :                                           SPOOL_DSSPOOLER_KEY,
    6630             :                                           SPOOL_REG_PRINTSHARENAME,
    6631             :                                           REG_SZ,
    6632             :                                           buffer.data,
    6633          16 :                                           buffer.length);
    6634          16 :                 if (!W_ERROR_IS_OK(result)) {
    6635           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
    6636           0 :                         goto done;
    6637             :                 }
    6638             : 
    6639          16 :                 if (!force_update) {
    6640           0 :                         notify_printer_sharename(global_event_context(),
    6641             :                                                  msg_ctx,
    6642           0 :                                                  snum, printer->sharename ?
    6643             :                                                  printer->sharename : "");
    6644             :                 }
    6645             : 
    6646             :                 /* name change, purge any cache entries for the old */
    6647          16 :                 prune_printername_cache();
    6648             :         }
    6649             : 
    6650         100 :         if (printer->printername != NULL &&
    6651          84 :             (force_update ||
    6652          84 :              !strequal(printer->printername, old_printer->printername))) {
    6653             :                 const char *p;
    6654             : 
    6655         100 :                 p = strrchr(printer->printername, '\\' );
    6656         100 :                 if (p != NULL) {
    6657         100 :                         p++;
    6658             :                 } else {
    6659           0 :                         p = printer->printername;
    6660             :                 }
    6661             : 
    6662         100 :                 ok = push_reg_sz(tmp_ctx, &buffer, p);
    6663         100 :                 if (!ok) {
    6664           0 :                         DEBUG(0, ("printername data corrupted\n"));
    6665           0 :                         result = WERR_INVALID_DATA;
    6666           0 :                         goto done;
    6667             :                 }
    6668         100 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6669             :                                           printer->sharename,
    6670             :                                           SPOOL_DSSPOOLER_KEY,
    6671             :                                           SPOOL_REG_PRINTERNAME,
    6672             :                                           REG_SZ,
    6673             :                                           buffer.data,
    6674         100 :                                           buffer.length);
    6675         100 :                 if (!W_ERROR_IS_OK(result)) {
    6676           0 :                         DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
    6677           0 :                         goto done;
    6678             :                 }
    6679             : 
    6680         100 :                 if (!force_update) {
    6681          84 :                         notify_printer_printername(global_event_context(),
    6682             :                                                    msg_ctx, snum, p ? p : "");
    6683             :                 }
    6684             : 
    6685             :                 /* name change, purge any cache entries for the old */
    6686         100 :                 prune_printername_cache();
    6687             :         }
    6688             : 
    6689         100 :         if (printer->portname != NULL &&
    6690          84 :             (force_update ||
    6691          84 :              !strequal(printer->portname, old_printer->portname))) {
    6692          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
    6693          16 :                 if (!ok) {
    6694           0 :                         DEBUG(0, ("portname data corrupted\n"));
    6695           0 :                         result = WERR_INVALID_DATA;
    6696           0 :                         goto done;
    6697             :                 }
    6698          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6699             :                                           printer->sharename,
    6700             :                                           SPOOL_DSSPOOLER_KEY,
    6701             :                                           SPOOL_REG_PORTNAME,
    6702             :                                           REG_SZ,
    6703             :                                           buffer.data,
    6704          16 :                                           buffer.length);
    6705          16 :                 if (!W_ERROR_IS_OK(result)) {
    6706           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
    6707           0 :                         goto done;
    6708             :                 }
    6709             : 
    6710          16 :                 if (!force_update) {
    6711           0 :                         notify_printer_port(global_event_context(),
    6712           0 :                                             msg_ctx, snum, printer->portname ?
    6713             :                                             printer->portname : "");
    6714             :                 }
    6715             :         }
    6716             : 
    6717         100 :         if (printer->location != NULL &&
    6718          84 :             (force_update ||
    6719          84 :              !strequal(printer->location, old_printer->location))) {
    6720           8 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
    6721           8 :                 if (!ok) {
    6722           0 :                         DEBUG(0, ("location data corrupted\n"));
    6723           0 :                         result = WERR_INVALID_DATA;
    6724           0 :                         goto done;
    6725             :                 }
    6726           8 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6727             :                                           printer->sharename,
    6728             :                                           SPOOL_DSSPOOLER_KEY,
    6729             :                                           SPOOL_REG_LOCATION,
    6730             :                                           REG_SZ,
    6731             :                                           buffer.data,
    6732           8 :                                           buffer.length);
    6733           8 :                 if (!W_ERROR_IS_OK(result)) {
    6734           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
    6735           0 :                         goto done;
    6736             :                 }
    6737             : 
    6738           8 :                 if (!force_update) {
    6739           8 :                         notify_printer_location(global_event_context(),
    6740             :                                                 msg_ctx, snum,
    6741           8 :                                                 printer->location ?
    6742             :                                                 printer->location : "");
    6743             :                 }
    6744             :         }
    6745             : 
    6746         100 :         if (printer->sepfile != NULL &&
    6747          84 :             (force_update ||
    6748          84 :              !strequal(printer->sepfile, old_printer->sepfile))) {
    6749           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
    6750           0 :                 if (!ok) {
    6751           0 :                         DEBUG(0, ("sepfile data corrupted\n"));
    6752           0 :                         result = WERR_INVALID_DATA;
    6753           0 :                         goto done;
    6754             :                 }
    6755           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6756             :                                           printer->sharename,
    6757             :                                           SPOOL_DSSPOOLER_KEY,
    6758             :                                           SPOOL_REG_PRINTSEPARATORFILE,
    6759             :                                           REG_SZ,
    6760             :                                           buffer.data,
    6761           0 :                                           buffer.length);
    6762           0 :                 if (!W_ERROR_IS_OK(result)) {
    6763           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
    6764           0 :                         goto done;
    6765             :                 }
    6766             : 
    6767           0 :                 if (!force_update) {
    6768           0 :                         notify_printer_sepfile(global_event_context(),
    6769             :                                                msg_ctx, snum,
    6770           0 :                                                printer->sepfile ?
    6771             :                                                printer->sepfile : "");
    6772             :                 }
    6773             :         }
    6774             : 
    6775         100 :         if (printer->starttime != 0 &&
    6776           0 :             (force_update ||
    6777           0 :              printer->starttime != old_printer->starttime)) {
    6778           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6779           0 :                 SIVAL(buffer.data, 0, printer->starttime);
    6780           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6781             :                                           printer->sharename,
    6782             :                                           SPOOL_DSSPOOLER_KEY,
    6783             :                                           SPOOL_REG_PRINTSTARTTIME,
    6784             :                                           REG_DWORD,
    6785             :                                           buffer.data,
    6786           0 :                                           buffer.length);
    6787           0 :                 if (!W_ERROR_IS_OK(result)) {
    6788           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
    6789           0 :                         goto done;
    6790             :                 }
    6791             :         }
    6792             : 
    6793         100 :         if (printer->untiltime != 0 &&
    6794           0 :             (force_update ||
    6795           0 :              printer->untiltime != old_printer->untiltime)) {
    6796           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6797           0 :                 SIVAL(buffer.data, 0, printer->untiltime);
    6798           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6799             :                                           printer->sharename,
    6800             :                                           SPOOL_DSSPOOLER_KEY,
    6801             :                                           SPOOL_REG_PRINTENDTIME,
    6802             :                                           REG_DWORD,
    6803             :                                           buffer.data,
    6804           0 :                                           buffer.length);
    6805           0 :                 if (!W_ERROR_IS_OK(result)) {
    6806           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6807           0 :                         goto done;
    6808             :                 }
    6809             :         }
    6810             : 
    6811         100 :         if (force_update || printer->priority != old_printer->priority) {
    6812          16 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6813          16 :                 SIVAL(buffer.data, 0, printer->priority);
    6814          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6815             :                                           printer->sharename,
    6816             :                                           SPOOL_DSSPOOLER_KEY,
    6817             :                                           SPOOL_REG_PRIORITY,
    6818             :                                           REG_DWORD,
    6819             :                                           buffer.data,
    6820          16 :                                           buffer.length);
    6821          16 :                 if (!W_ERROR_IS_OK(result)) {
    6822           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6823           0 :                         goto done;
    6824             :                 }
    6825             :         }
    6826             : 
    6827         100 :         if (force_update || printer->attributes != old_printer->attributes) {
    6828          16 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6829          16 :                 SIVAL(buffer.data, 0, (printer->attributes &
    6830             :                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
    6831          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6832             :                                           printer->sharename,
    6833             :                                           SPOOL_DSSPOOLER_KEY,
    6834             :                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
    6835             :                                           REG_DWORD,
    6836             :                                           buffer.data,
    6837          16 :                                           buffer.length);
    6838          16 :                 if (!W_ERROR_IS_OK(result)) {
    6839           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6840           0 :                         goto done;
    6841             :                 }
    6842             : 
    6843          16 :                 switch (printer->attributes & 0x3) {
    6844          16 :                         case 0:
    6845          16 :                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
    6846          16 :                                 break;
    6847           0 :                         case 1:
    6848           0 :                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
    6849           0 :                                 break;
    6850           0 :                         case 2:
    6851           0 :                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
    6852           0 :                                 break;
    6853           0 :                         default:
    6854           0 :                                 spooling = "unknown";
    6855             :                 }
    6856          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
    6857          16 :                 if (!ok) {
    6858           0 :                         DEBUG(0, ("printSpooling data corrupted\n"));
    6859           0 :                         result = WERR_INVALID_DATA;
    6860           0 :                         goto done;
    6861             :                 }
    6862          16 :                 winreg_set_printer_dataex(tmp_ctx, b,
    6863             :                                           printer->sharename,
    6864             :                                           SPOOL_DSSPOOLER_KEY,
    6865             :                                           SPOOL_REG_PRINTSPOOLING,
    6866             :                                           REG_SZ,
    6867             :                                           buffer.data,
    6868          16 :                                           buffer.length);
    6869             :         }
    6870             : 
    6871         100 :         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
    6872         100 :         if (!ok) {
    6873           0 :                 DEBUG(0, ("shortServerName data corrupted\n"));
    6874           0 :                 result = WERR_INVALID_DATA;
    6875           0 :                 goto done;
    6876             :         }
    6877         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6878             :                                   printer->sharename,
    6879             :                                   SPOOL_DSSPOOLER_KEY,
    6880             :                                   SPOOL_REG_SHORTSERVERNAME,
    6881             :                                   REG_SZ,
    6882             :                                   buffer.data,
    6883         100 :                                   buffer.length);
    6884         100 :         if (!W_ERROR_IS_OK(result)) {
    6885           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
    6886           0 :                 goto done;
    6887             :         }
    6888             : 
    6889         100 :         dnsdomname = get_mydnsfullname();
    6890         100 :         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
    6891         100 :                 longname = talloc_strdup(tmp_ctx, dnsdomname);
    6892             :         } else {
    6893           0 :                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
    6894             :         }
    6895         100 :         if (longname == NULL) {
    6896           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    6897           0 :                 goto done;
    6898             :         }
    6899             : 
    6900         100 :         ok = push_reg_sz(tmp_ctx, &buffer, longname);
    6901         100 :         if (!ok) {
    6902           0 :                 DEBUG(0, ("longname data corrupted\n"));
    6903           0 :                 result = WERR_INVALID_DATA;
    6904           0 :                 goto done;
    6905             :         }
    6906         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6907             :                                            printer->sharename,
    6908             :                                            SPOOL_DSSPOOLER_KEY,
    6909             :                                            SPOOL_REG_SERVERNAME,
    6910             :                                            REG_SZ,
    6911             :                                            buffer.data,
    6912         100 :                                            buffer.length);
    6913         100 :         if (!W_ERROR_IS_OK(result)) {
    6914           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
    6915           0 :                 goto done;
    6916             :         }
    6917             : 
    6918         100 :         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
    6919             :                                   lp_netbios_name(), printer->sharename);
    6920         100 :         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
    6921         100 :         if (!ok) {
    6922           0 :                 DEBUG(0, ("uncName data corrupted\n"));
    6923           0 :                 result = WERR_INVALID_DATA;
    6924           0 :                 goto done;
    6925             :         }
    6926         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6927             :                                   printer->sharename,
    6928             :                                   SPOOL_DSSPOOLER_KEY,
    6929             :                                   SPOOL_REG_UNCNAME,
    6930             :                                   REG_SZ,
    6931             :                                   buffer.data,
    6932         100 :                                   buffer.length);
    6933         100 :         if (!W_ERROR_IS_OK(result)) {
    6934           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
    6935           0 :                 goto done;
    6936             :         }
    6937             : 
    6938         175 : done:
    6939         100 :         talloc_free(tmp_ctx);
    6940         100 :         return result;
    6941             : }
    6942             : 
    6943             : /********************************************************************
    6944             :  * Called by spoolss_api_setprinter
    6945             :  * when updating a printer description.
    6946             :  ********************************************************************/
    6947             : 
    6948          84 : static WERROR update_printer(struct pipes_struct *p,
    6949             :                              struct policy_handle *handle,
    6950             :                              struct spoolss_SetPrinterInfoCtr *info_ctr,
    6951             :                              struct spoolss_DeviceMode *devmode)
    6952             : {
    6953          84 :         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
    6954          84 :         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
    6955             :         struct spoolss_PrinterInfo2 *old_printer;
    6956          84 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6957          63 :         const struct loadparm_substitution *lp_sub =
    6958          21 :                 loadparm_s3_global_substitution();
    6959             :         int snum;
    6960          84 :         WERROR result = WERR_OK;
    6961             :         TALLOC_CTX *tmp_ctx;
    6962             :         struct dcerpc_binding_handle *b;
    6963             : 
    6964          84 :         DEBUG(8,("update_printer\n"));
    6965             : 
    6966          84 :         tmp_ctx = talloc_new(p->mem_ctx);
    6967          84 :         if (tmp_ctx == NULL) {
    6968           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6969             :         }
    6970             : 
    6971          84 :         if (!Printer) {
    6972           0 :                 result = WERR_INVALID_HANDLE;
    6973           0 :                 goto done;
    6974             :         }
    6975             : 
    6976          84 :         if (!get_printer_snum(p, handle, &snum, NULL)) {
    6977           0 :                 result = WERR_INVALID_HANDLE;
    6978           0 :                 goto done;
    6979             :         }
    6980             : 
    6981          84 :         result = winreg_printer_binding_handle(tmp_ctx,
    6982             :                                                get_session_info_system(),
    6983             :                                                p->msg_ctx,
    6984             :                                                &b);
    6985          84 :         if (!W_ERROR_IS_OK(result)) {
    6986           0 :                 goto done;
    6987             :         }
    6988             : 
    6989          84 :         result = winreg_get_printer(tmp_ctx, b,
    6990             :                                     lp_const_servicename(snum),
    6991             :                                     &old_printer);
    6992          84 :         if (!W_ERROR_IS_OK(result)) {
    6993           0 :                 result = WERR_INVALID_HANDLE;
    6994           0 :                 goto done;
    6995             :         }
    6996             : 
    6997             :         /* Do sanity check on the requested changes for Samba */
    6998          84 :         if (!check_printer_ok(tmp_ctx, printer, snum)) {
    6999           0 :                 result = WERR_INVALID_PARAMETER;
    7000           0 :                 goto done;
    7001             :         }
    7002             : 
    7003             :         /* FIXME!!! If the driver has changed we really should verify that
    7004             :            it is installed before doing much else   --jerry */
    7005             : 
    7006             :         /* Check calling user has permission to update printer description */
    7007          84 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
    7008           0 :                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
    7009           0 :                 result = WERR_ACCESS_DENIED;
    7010           0 :                 goto done;
    7011             :         }
    7012             : 
    7013             :         /* Call addprinter hook */
    7014             :         /* Check changes to see if this is really needed */
    7015             : 
    7016         147 :         if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
    7017         141 :                         (!strequal(printer->drivername, old_printer->drivername) ||
    7018         105 :                          !strequal(printer->comment, old_printer->comment) ||
    7019          71 :                          !strequal(printer->portname, old_printer->portname) ||
    7020          42 :                          !strequal(printer->location, old_printer->location)) )
    7021             :         {
    7022             :                 char *raddr;
    7023             : 
    7024          50 :                 raddr = tsocket_address_inet_addr_string(p->remote_address,
    7025             :                                                          p->mem_ctx);
    7026          50 :                 if (raddr == NULL) {
    7027           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    7028           0 :                         goto done;
    7029             :                 }
    7030             : 
    7031             :                 /* add_printer_hook() will call reload_services() */
    7032          50 :                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
    7033             :                                       printer, raddr,
    7034             :                                       p->msg_ctx)) {
    7035           0 :                         result = WERR_ACCESS_DENIED;
    7036           0 :                         goto done;
    7037             :                 }
    7038             :         }
    7039             : 
    7040          84 :         result = update_dsspooler(tmp_ctx,
    7041             :                                   get_session_info_system(),
    7042             :                                   p->msg_ctx,
    7043             :                                   snum,
    7044             :                                   printer,
    7045             :                                   old_printer);
    7046          84 :         if (!W_ERROR_IS_OK(result)) {
    7047           0 :                 goto done;
    7048             :         }
    7049             : 
    7050          84 :         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
    7051             : 
    7052          84 :         if (devmode == NULL) {
    7053          76 :                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
    7054             :         }
    7055          84 :         result = winreg_update_printer(tmp_ctx, b,
    7056             :                                        printer->sharename,
    7057             :                                        printer_mask,
    7058             :                                        printer,
    7059             :                                        devmode,
    7060             :                                        NULL);
    7061             : 
    7062          84 : done:
    7063          84 :         talloc_free(tmp_ctx);
    7064             : 
    7065          84 :         return result;
    7066             : }
    7067             : 
    7068             : /****************************************************************************
    7069             : ****************************************************************************/
    7070           8 : static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
    7071             :                                            struct policy_handle *handle,
    7072             :                                            struct spoolss_SetPrinterInfo7 *info7)
    7073             : {
    7074             : #ifdef HAVE_ADS
    7075           4 :         const struct loadparm_substitution *lp_sub =
    7076           2 :                 loadparm_s3_global_substitution();
    7077           6 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    7078             :         WERROR result;
    7079             :         int snum;
    7080             :         struct printer_handle *Printer;
    7081             : 
    7082           6 :         if ( lp_security() != SEC_ADS ) {
    7083           6 :                 return WERR_INVALID_LEVEL;
    7084             :         }
    7085             : 
    7086           0 :         Printer = find_printer_index_by_hnd(p, handle);
    7087             : 
    7088           0 :         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
    7089             : 
    7090           0 :         if (!Printer)
    7091           0 :                 return WERR_INVALID_HANDLE;
    7092             : 
    7093           0 :         if (!get_printer_snum(p, handle, &snum, NULL))
    7094           0 :                 return WERR_INVALID_HANDLE;
    7095             : 
    7096           0 :         result = winreg_get_printer_internal(p->mem_ctx,
    7097             :                                     get_session_info_system(),
    7098             :                                     p->msg_ctx,
    7099           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum),
    7100             :                                     &pinfo2);
    7101           0 :         if (!W_ERROR_IS_OK(result)) {
    7102           0 :                 return WERR_INVALID_HANDLE;
    7103             :         }
    7104             : 
    7105           0 :         nt_printer_publish(pinfo2,
    7106             :                            get_session_info_system(),
    7107             :                            p->msg_ctx,
    7108             :                            pinfo2,
    7109           0 :                            info7->action);
    7110             : 
    7111           0 :         TALLOC_FREE(pinfo2);
    7112           0 :         return WERR_OK;
    7113             : #else
    7114           2 :         return WERR_INVALID_LEVEL;
    7115             : #endif
    7116             : }
    7117             : 
    7118             : /********************************************************************
    7119             :  ********************************************************************/
    7120             : 
    7121         296 : static WERROR update_printer_devmode(struct pipes_struct *p,
    7122             :                                      struct policy_handle *handle,
    7123             :                                      struct spoolss_DeviceMode *devmode)
    7124             : {
    7125             :         int snum;
    7126         296 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    7127         296 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
    7128             : 
    7129         296 :         DEBUG(8,("update_printer_devmode\n"));
    7130             : 
    7131         296 :         if (!Printer) {
    7132           0 :                 return WERR_INVALID_HANDLE;
    7133             :         }
    7134             : 
    7135         296 :         if (!get_printer_snum(p, handle, &snum, NULL)) {
    7136           0 :                 return WERR_INVALID_HANDLE;
    7137             :         }
    7138             : 
    7139             :         /* Check calling user has permission to update printer description */
    7140         296 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
    7141           0 :                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
    7142           0 :                 return WERR_ACCESS_DENIED;
    7143             :         }
    7144             : 
    7145         296 :         return winreg_update_printer_internal(p->mem_ctx,
    7146             :                                      get_session_info_system(),
    7147             :                                      p->msg_ctx,
    7148             :                                      lp_const_servicename(snum),
    7149             :                                      info2_mask,
    7150             :                                      NULL,
    7151             :                                      devmode,
    7152             :                                      NULL);
    7153             : }
    7154             : 
    7155             : 
    7156             : /****************************************************************
    7157             :  _spoolss_SetPrinter
    7158             : ****************************************************************/
    7159             : 
    7160         584 : WERROR _spoolss_SetPrinter(struct pipes_struct *p,
    7161             :                            struct spoolss_SetPrinter *r)
    7162             : {
    7163             :         WERROR result;
    7164             : 
    7165         584 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    7166             : 
    7167         584 :         if (!Printer) {
    7168           0 :                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
    7169             :                         OUR_HANDLE(r->in.handle)));
    7170           0 :                 return WERR_INVALID_HANDLE;
    7171             :         }
    7172             : 
    7173             :         /* check the level */
    7174         584 :         switch (r->in.info_ctr->level) {
    7175         104 :                 case 0:
    7176         104 :                         return control_printer(r->in.handle, r->in.command, p);
    7177          84 :                 case 2:
    7178          84 :                         result = update_printer(p, r->in.handle,
    7179             :                                                 r->in.info_ctr,
    7180          84 :                                                 r->in.devmode_ctr->devmode);
    7181          84 :                         if (!W_ERROR_IS_OK(result))
    7182           0 :                                 return result;
    7183          84 :                         if (r->in.secdesc_ctr->sd)
    7184          28 :                                 result = update_printer_sec(r->in.handle, p,
    7185             :                                                             r->in.secdesc_ctr);
    7186          84 :                         return result;
    7187          92 :                 case 3:
    7188          92 :                         return update_printer_sec(r->in.handle, p,
    7189             :                                                   r->in.secdesc_ctr);
    7190           0 :                 case 4: {
    7191             :                         struct spoolss_PrinterInfo2 *old_printer;
    7192             :                         struct spoolss_SetPrinterInfo2 *set_old_printer;
    7193             :                         struct spoolss_SetPrinterInfoCtr *info_ctr;
    7194             :                         struct dcerpc_binding_handle *b;
    7195             :                         int snum;
    7196             :                         TALLOC_CTX *tmp_ctx;
    7197             : 
    7198           0 :                         tmp_ctx = talloc_new(p->mem_ctx);
    7199           0 :                         if (tmp_ctx == NULL) {
    7200           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7201             :                         }
    7202             : 
    7203           0 :                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7204           0 :                                 TALLOC_FREE(tmp_ctx);
    7205           0 :                                 return WERR_INVALID_HANDLE;
    7206             :                         }
    7207             : 
    7208           0 :                         result = winreg_printer_binding_handle(tmp_ctx,
    7209             :                                                                get_session_info_system(),
    7210             :                                                                p->msg_ctx,
    7211             :                                                                &b);
    7212           0 :                         if (!W_ERROR_IS_OK(result)) {
    7213           0 :                                 TALLOC_FREE(tmp_ctx);
    7214           0 :                                 return result;
    7215             :                         }
    7216             : 
    7217           0 :                         result = winreg_get_printer(tmp_ctx, b,
    7218             :                                                     lp_const_servicename(snum),
    7219             :                                                     &old_printer);
    7220           0 :                         if (!W_ERROR_IS_OK(result)) {
    7221           0 :                                 TALLOC_FREE(tmp_ctx);
    7222           0 :                                 return WERR_INVALID_HANDLE;
    7223             :                         }
    7224             : 
    7225           0 :                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
    7226           0 :                         if (old_printer->servername == NULL) {
    7227           0 :                                 TALLOC_FREE(tmp_ctx);
    7228           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7229             :                         }
    7230             : 
    7231           0 :                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
    7232           0 :                         if (old_printer->printername == NULL) {
    7233           0 :                                 TALLOC_FREE(tmp_ctx);
    7234           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7235             :                         }
    7236             : 
    7237           0 :                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
    7238             : 
    7239           0 :                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
    7240           0 :                         if (set_old_printer == NULL) {
    7241           0 :                                 TALLOC_FREE(tmp_ctx);
    7242           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7243             :                         }
    7244             : 
    7245           0 :                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
    7246             : 
    7247           0 :                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
    7248           0 :                         if (info_ctr == NULL) {
    7249           0 :                                 TALLOC_FREE(tmp_ctx);
    7250           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7251             :                         }
    7252             : 
    7253           0 :                         info_ctr->level = 2;
    7254           0 :                         info_ctr->info.info2 = set_old_printer;
    7255             : 
    7256           0 :                         result = update_printer(p, r->in.handle,
    7257             :                                                 info_ctr,
    7258           0 :                                                 r->in.devmode_ctr->devmode);
    7259             : 
    7260           0 :                         if (!W_ERROR_IS_OK(result)) {
    7261           0 :                                 TALLOC_FREE(tmp_ctx);
    7262           0 :                                 return result;
    7263             :                         }
    7264             : 
    7265           0 :                         if (r->in.secdesc_ctr->sd) {
    7266           0 :                                 result = update_printer_sec(r->in.handle, p,
    7267             :                                                             r->in.secdesc_ctr);
    7268             :                         }
    7269             : 
    7270           0 :                         TALLOC_FREE(tmp_ctx);
    7271           0 :                         return result;
    7272             :                 }
    7273           8 :                 case 7:
    7274           8 :                         return publish_or_unpublish_printer(p, r->in.handle,
    7275           8 :                                                             r->in.info_ctr->info.info7);
    7276         296 :                 case 8:
    7277         296 :                         return update_printer_devmode(p, r->in.handle,
    7278         296 :                                                       r->in.devmode_ctr->devmode);
    7279           0 :                 default:
    7280           0 :                         return WERR_INVALID_LEVEL;
    7281             :         }
    7282             : }
    7283             : 
    7284             : /****************************************************************
    7285             :  _spoolss_FindClosePrinterNotify
    7286             : ****************************************************************/
    7287             : 
    7288           0 : WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
    7289             :                                        struct spoolss_FindClosePrinterNotify *r)
    7290             : {
    7291           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    7292             : 
    7293           0 :         if (!Printer) {
    7294           0 :                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
    7295             :                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
    7296           0 :                 return WERR_INVALID_HANDLE;
    7297             :         }
    7298             : 
    7299           0 :         if (Printer->notify.cli_chan != NULL &&
    7300           0 :             Printer->notify.cli_chan->active_connections > 0) {
    7301           0 :                 int snum = -1;
    7302             : 
    7303           0 :                 if (Printer->printer_type == SPLHND_PRINTER) {
    7304           0 :                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7305           0 :                                 return WERR_INVALID_HANDLE;
    7306             :                         }
    7307             :                 }
    7308             : 
    7309           0 :                 srv_spoolss_replycloseprinter(snum, Printer);
    7310             :         }
    7311             : 
    7312           0 :         Printer->notify.flags=0;
    7313           0 :         Printer->notify.options=0;
    7314           0 :         Printer->notify.localmachine[0]='\0';
    7315           0 :         Printer->notify.printerlocal=0;
    7316           0 :         TALLOC_FREE(Printer->notify.option);
    7317             : 
    7318           0 :         return WERR_OK;
    7319             : }
    7320             : 
    7321             : /****************************************************************
    7322             :  _spoolss_AddJob
    7323             : ****************************************************************/
    7324             : 
    7325          16 : WERROR _spoolss_AddJob(struct pipes_struct *p,
    7326             :                        struct spoolss_AddJob *r)
    7327             : {
    7328          16 :         if (!r->in.buffer && (r->in.offered != 0)) {
    7329           0 :                 return WERR_INVALID_PARAMETER;
    7330             :         }
    7331             : 
    7332             :         /* this is what a NT server returns for AddJob. AddJob must fail on
    7333             :          * non-local printers */
    7334             : 
    7335          16 :         if (r->in.level != 1) {
    7336           8 :                 return WERR_INVALID_LEVEL;
    7337             :         }
    7338             : 
    7339           8 :         return WERR_INVALID_PARAMETER;
    7340             : }
    7341             : 
    7342             : /****************************************************************************
    7343             : fill_job_info1
    7344             : ****************************************************************************/
    7345             : 
    7346         320 : static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
    7347             :                              struct spoolss_JobInfo1 *r,
    7348             :                              const print_queue_struct *queue,
    7349             :                              uint32_t jobid,
    7350             :                              int position, int snum,
    7351             :                              struct spoolss_PrinterInfo2 *pinfo2)
    7352             : {
    7353         160 :         const struct loadparm_substitution *lp_sub =
    7354         160 :                 loadparm_s3_global_substitution();
    7355             :         struct tm *t;
    7356             : 
    7357         320 :         t = gmtime(&queue->time);
    7358             : 
    7359         320 :         r->job_id            = jobid;
    7360             : 
    7361         320 :         r->printer_name              = lp_servicename(mem_ctx, lp_sub, snum);
    7362         320 :         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
    7363         320 :         r->server_name               = talloc_strdup(mem_ctx, pinfo2->servername);
    7364         320 :         W_ERROR_HAVE_NO_MEMORY(r->server_name);
    7365         320 :         r->user_name         = talloc_strdup(mem_ctx, queue->fs_user);
    7366         320 :         W_ERROR_HAVE_NO_MEMORY(r->user_name);
    7367         320 :         r->document_name     = talloc_strdup(mem_ctx, queue->fs_file);
    7368         320 :         W_ERROR_HAVE_NO_MEMORY(r->document_name);
    7369         320 :         r->data_type         = talloc_strdup(mem_ctx, "RAW");
    7370         320 :         W_ERROR_HAVE_NO_MEMORY(r->data_type);
    7371         320 :         r->text_status               = talloc_strdup(mem_ctx, "");
    7372         320 :         W_ERROR_HAVE_NO_MEMORY(r->text_status);
    7373             : 
    7374         320 :         r->status            = nt_printj_status(queue->status);
    7375         320 :         r->priority          = queue->priority;
    7376         320 :         r->position          = position;
    7377         320 :         r->total_pages               = queue->page_count;
    7378         320 :         r->pages_printed     = 0; /* ??? */
    7379             : 
    7380         320 :         init_systemtime(&r->submitted, t);
    7381             : 
    7382         320 :         return WERR_OK;
    7383             : }
    7384             : 
    7385             : /****************************************************************************
    7386             : fill_job_info2
    7387             : ****************************************************************************/
    7388             : 
    7389          64 : static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
    7390             :                              struct spoolss_JobInfo2 *r,
    7391             :                              const print_queue_struct *queue,
    7392             :                              uint32_t jobid,
    7393             :                              int position, int snum,
    7394             :                              struct spoolss_PrinterInfo2 *pinfo2,
    7395             :                              struct spoolss_DeviceMode *devmode)
    7396             : {
    7397          32 :         const struct loadparm_substitution *lp_sub =
    7398          32 :                 loadparm_s3_global_substitution();
    7399             :         struct tm *t;
    7400             : 
    7401          64 :         t = gmtime(&queue->time);
    7402             : 
    7403          64 :         r->job_id            = jobid;
    7404             : 
    7405          64 :         r->printer_name              = lp_servicename(mem_ctx, lp_sub, snum);
    7406          64 :         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
    7407          64 :         r->server_name               = talloc_strdup(mem_ctx, pinfo2->servername);
    7408          64 :         W_ERROR_HAVE_NO_MEMORY(r->server_name);
    7409          64 :         r->user_name         = talloc_strdup(mem_ctx, queue->fs_user);
    7410          64 :         W_ERROR_HAVE_NO_MEMORY(r->user_name);
    7411          64 :         r->document_name     = talloc_strdup(mem_ctx, queue->fs_file);
    7412          64 :         W_ERROR_HAVE_NO_MEMORY(r->document_name);
    7413          64 :         r->notify_name               = talloc_strdup(mem_ctx, queue->fs_user);
    7414          64 :         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
    7415          64 :         r->data_type         = talloc_strdup(mem_ctx, "RAW");
    7416          64 :         W_ERROR_HAVE_NO_MEMORY(r->data_type);
    7417          64 :         r->print_processor   = talloc_strdup(mem_ctx, "winprint");
    7418          64 :         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
    7419          64 :         r->parameters                = talloc_strdup(mem_ctx, "");
    7420          64 :         W_ERROR_HAVE_NO_MEMORY(r->parameters);
    7421          64 :         r->driver_name               = talloc_strdup(mem_ctx, pinfo2->drivername);
    7422          64 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    7423             : 
    7424          64 :         r->devmode           = devmode;
    7425             : 
    7426          64 :         r->text_status               = talloc_strdup(mem_ctx, "");
    7427          64 :         W_ERROR_HAVE_NO_MEMORY(r->text_status);
    7428             : 
    7429          64 :         r->secdesc           = NULL;
    7430             : 
    7431          64 :         r->status            = nt_printj_status(queue->status);
    7432          64 :         r->priority          = queue->priority;
    7433          64 :         r->position          = position;
    7434          64 :         r->start_time                = 0;
    7435          64 :         r->until_time                = 0;
    7436          64 :         r->total_pages               = queue->page_count;
    7437          64 :         r->size                      = queue->size;
    7438          64 :         init_systemtime(&r->submitted, t);
    7439          64 :         r->time                      = 0;
    7440          64 :         r->pages_printed     = 0; /* ??? */
    7441             : 
    7442          64 :         return WERR_OK;
    7443             : }
    7444             : 
    7445             : /****************************************************************************
    7446             :  Enumjobs at level 1.
    7447             : ****************************************************************************/
    7448             : 
    7449          24 : static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
    7450             :                               const print_queue_struct *queue,
    7451             :                               uint32_t num_queues, int snum,
    7452             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7453             :                               union spoolss_JobInfo **info_p,
    7454             :                               uint32_t *count)
    7455             : {
    7456             :         union spoolss_JobInfo *info;
    7457             :         int i;
    7458          24 :         WERROR result = WERR_OK;
    7459             :         uint32_t num_filled;
    7460             :         struct tdb_print_db *pdb;
    7461             : 
    7462          24 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7463          24 :         if (info == NULL) {
    7464           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7465           0 :                 goto err_out;
    7466             :         }
    7467             : 
    7468          24 :         pdb = get_print_db_byname(pinfo2->sharename);
    7469          24 :         if (pdb == NULL) {
    7470           0 :                 result = WERR_INVALID_PARAMETER;
    7471           0 :                 goto err_info_free;
    7472             :         }
    7473             : 
    7474          24 :         num_filled = 0;
    7475         216 :         for (i = 0; i < num_queues; i++) {
    7476         192 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7477         192 :                 if (jobid == (uint32_t)-1) {
    7478           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7479           0 :                         continue;
    7480             :                 }
    7481             : 
    7482         288 :                 result = fill_job_info1(info,
    7483         192 :                                         &info[num_filled].info1,
    7484         192 :                                         &queue[i],
    7485             :                                         jobid,
    7486             :                                         i,
    7487             :                                         snum,
    7488             :                                         pinfo2);
    7489         192 :                 if (!W_ERROR_IS_OK(result)) {
    7490           0 :                         goto err_pdb_drop;
    7491             :                 }
    7492             : 
    7493         192 :                 num_filled++;
    7494             :         }
    7495             : 
    7496          24 :         release_print_db(pdb);
    7497          24 :         *info_p = info;
    7498          24 :         *count = num_filled;
    7499             : 
    7500          24 :         return WERR_OK;
    7501             : 
    7502           0 : err_pdb_drop:
    7503           0 :         release_print_db(pdb);
    7504           0 : err_info_free:
    7505           0 :         TALLOC_FREE(info);
    7506           0 : err_out:
    7507           0 :         *count = 0;
    7508           0 :         return result;
    7509             : }
    7510             : 
    7511             : /****************************************************************************
    7512             :  Enumjobs at level 2.
    7513             : ****************************************************************************/
    7514             : 
    7515           8 : static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
    7516             :                               const print_queue_struct *queue,
    7517             :                               uint32_t num_queues, int snum,
    7518             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7519             :                               union spoolss_JobInfo **info_p,
    7520             :                               uint32_t *count)
    7521             : {
    7522             :         union spoolss_JobInfo *info;
    7523             :         int i;
    7524           8 :         WERROR result = WERR_OK;
    7525             :         uint32_t num_filled;
    7526             :         struct tdb_print_db *pdb;
    7527             : 
    7528           8 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7529           8 :         if (info == NULL) {
    7530           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7531           0 :                 goto err_out;
    7532             :         }
    7533             : 
    7534           8 :         pdb = get_print_db_byname(pinfo2->sharename);
    7535           8 :         if (pdb == NULL) {
    7536           0 :                 result = WERR_INVALID_PARAMETER;
    7537           0 :                 goto err_info_free;
    7538             :         }
    7539             : 
    7540           8 :         num_filled = 0;
    7541          72 :         for (i = 0; i< num_queues; i++) {
    7542             :                 struct spoolss_DeviceMode *devmode;
    7543          64 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7544          64 :                 if (jobid == (uint32_t)-1) {
    7545           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7546           0 :                         continue;
    7547             :                 }
    7548             : 
    7549          64 :                 result = spoolss_create_default_devmode(info,
    7550             :                                                         pinfo2->printername,
    7551             :                                                         &devmode);
    7552          64 :                 if (!W_ERROR_IS_OK(result)) {
    7553           0 :                         DEBUG(3, ("Can't proceed w/o a devmode!"));
    7554           0 :                         goto err_pdb_drop;
    7555             :                 }
    7556             : 
    7557         128 :                 result = fill_job_info2(info,
    7558          64 :                                         &info[num_filled].info2,
    7559          64 :                                         &queue[i],
    7560             :                                         jobid,
    7561             :                                         i,
    7562             :                                         snum,
    7563             :                                         pinfo2,
    7564             :                                         devmode);
    7565          64 :                 if (!W_ERROR_IS_OK(result)) {
    7566           0 :                         goto err_pdb_drop;
    7567             :                 }
    7568          64 :                 num_filled++;
    7569             :         }
    7570             : 
    7571           8 :         release_print_db(pdb);
    7572           8 :         *info_p = info;
    7573           8 :         *count = num_filled;
    7574             : 
    7575           8 :         return WERR_OK;
    7576             : 
    7577           0 : err_pdb_drop:
    7578           0 :         release_print_db(pdb);
    7579           0 : err_info_free:
    7580           0 :         TALLOC_FREE(info);
    7581           0 : err_out:
    7582           0 :         *count = 0;
    7583           0 :         return result;
    7584             : }
    7585             : 
    7586             : /****************************************************************************
    7587             :  Enumjobs at level 3.
    7588             : ****************************************************************************/
    7589             : 
    7590           0 : static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
    7591             :                               const print_queue_struct *queue,
    7592             :                               uint32_t num_queues, int snum,
    7593             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7594             :                               union spoolss_JobInfo **info_p,
    7595             :                               uint32_t *count)
    7596             : {
    7597             :         union spoolss_JobInfo *info;
    7598             :         int i;
    7599           0 :         WERROR result = WERR_OK;
    7600             :         uint32_t num_filled;
    7601             :         struct tdb_print_db *pdb;
    7602             : 
    7603           0 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7604           0 :         if (info == NULL) {
    7605           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7606           0 :                 goto err_out;
    7607             :         }
    7608             : 
    7609           0 :         pdb = get_print_db_byname(pinfo2->sharename);
    7610           0 :         if (pdb == NULL) {
    7611           0 :                 result = WERR_INVALID_PARAMETER;
    7612           0 :                 goto err_info_free;
    7613             :         }
    7614             : 
    7615           0 :         num_filled = 0;
    7616           0 :         for (i = 0; i < num_queues; i++) {
    7617           0 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7618           0 :                 if (jobid == (uint32_t)-1) {
    7619           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7620           0 :                         continue;
    7621             :                 }
    7622             : 
    7623           0 :                 info[num_filled].info3.job_id = jobid;
    7624             :                 /* next_job_id is overwritten on next iteration */
    7625           0 :                 info[num_filled].info3.next_job_id = 0;
    7626           0 :                 info[num_filled].info3.reserved = 0;
    7627             : 
    7628           0 :                 if (num_filled > 0) {
    7629           0 :                         info[num_filled - 1].info3.next_job_id = jobid;
    7630             :                 }
    7631           0 :                 num_filled++;
    7632             :         }
    7633             : 
    7634           0 :         release_print_db(pdb);
    7635           0 :         *info_p = info;
    7636           0 :         *count = num_filled;
    7637             : 
    7638           0 :         return WERR_OK;
    7639             : 
    7640           0 : err_info_free:
    7641           0 :         TALLOC_FREE(info);
    7642           0 : err_out:
    7643           0 :         *count = 0;
    7644           0 :         return result;
    7645             : }
    7646             : 
    7647             : /****************************************************************
    7648             :  _spoolss_EnumJobs
    7649             : ****************************************************************/
    7650             : 
    7651          88 : WERROR _spoolss_EnumJobs(struct pipes_struct *p,
    7652             :                          struct spoolss_EnumJobs *r)
    7653             : {
    7654             :         WERROR result;
    7655          88 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    7656             :         int snum;
    7657             :         print_status_struct prt_status;
    7658          88 :         print_queue_struct *queue = NULL;
    7659             :         uint32_t count;
    7660             : 
    7661             :         /* that's an [in out] buffer */
    7662             : 
    7663          88 :         if (!r->in.buffer && (r->in.offered != 0)) {
    7664           0 :                 return WERR_INVALID_PARAMETER;
    7665             :         }
    7666             : 
    7667          88 :         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
    7668          12 :                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
    7669          12 :                 return WERR_INVALID_LEVEL;
    7670             :         }
    7671             : 
    7672          76 :         DEBUG(4,("_spoolss_EnumJobs\n"));
    7673             : 
    7674          76 :         *r->out.needed = 0;
    7675          76 :         *r->out.count = 0;
    7676          76 :         *r->out.info = NULL;
    7677             : 
    7678             :         /* lookup the printer snum and tdb entry */
    7679             : 
    7680          76 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7681           0 :                 return WERR_INVALID_HANDLE;
    7682             :         }
    7683             : 
    7684          76 :         result = winreg_get_printer_internal(p->mem_ctx,
    7685             :                                     get_session_info_system(),
    7686             :                                     p->msg_ctx,
    7687             :                                     lp_const_servicename(snum),
    7688             :                                     &pinfo2);
    7689          76 :         if (!W_ERROR_IS_OK(result)) {
    7690           0 :                 return result;
    7691             :         }
    7692             : 
    7693          76 :         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
    7694          76 :         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
    7695             :                 count, prt_status.status, prt_status.message));
    7696             : 
    7697          76 :         if (count == 0) {
    7698          44 :                 SAFE_FREE(queue);
    7699          44 :                 TALLOC_FREE(pinfo2);
    7700          44 :                 return WERR_OK;
    7701             :         }
    7702             : 
    7703          32 :         switch (r->in.level) {
    7704          24 :         case 1:
    7705          24 :                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
    7706             :                                          pinfo2, r->out.info, r->out.count);
    7707          24 :                 break;
    7708           8 :         case 2:
    7709           8 :                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
    7710             :                                          pinfo2, r->out.info, r->out.count);
    7711           8 :                 break;
    7712           0 :         case 3:
    7713           0 :                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
    7714             :                                          pinfo2, r->out.info, r->out.count);
    7715           0 :                 break;
    7716           0 :         default:
    7717           0 :                 SMB_ASSERT(false);      /* level checked on entry */
    7718             :                 break;
    7719             :         }
    7720             : 
    7721          32 :         SAFE_FREE(queue);
    7722          32 :         TALLOC_FREE(pinfo2);
    7723             : 
    7724          32 :         if (!W_ERROR_IS_OK(result)) {
    7725           0 :                 return result;
    7726             :         }
    7727             : 
    7728          32 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    7729             :                                                      spoolss_EnumJobs,
    7730             :                                                      *r->out.info, r->in.level,
    7731             :                                                      *r->out.count);
    7732          32 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    7733          32 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    7734             : 
    7735          32 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    7736             : }
    7737             : 
    7738             : /****************************************************************
    7739             :  _spoolss_ScheduleJob
    7740             : ****************************************************************/
    7741             : 
    7742           0 : WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
    7743             :                             struct spoolss_ScheduleJob *r)
    7744             : {
    7745           0 :         return WERR_OK;
    7746             : }
    7747             : 
    7748             : /****************************************************************
    7749             : ****************************************************************/
    7750             : 
    7751          32 : static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
    7752             :                                struct messaging_context *msg_ctx,
    7753             :                                const char *printer_name,
    7754             :                                uint32_t job_id,
    7755             :                                struct spoolss_SetJobInfo1 *r)
    7756             : {
    7757             :         char *old_doc_name;
    7758             : 
    7759          32 :         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
    7760           0 :                 return WERR_INVALID_HANDLE;
    7761             :         }
    7762             : 
    7763          32 :         if (strequal(old_doc_name, r->document_name)) {
    7764           0 :                 return WERR_OK;
    7765             :         }
    7766             : 
    7767          32 :         if (!print_job_set_name(global_event_context(), msg_ctx,
    7768             :                                 printer_name, job_id, r->document_name)) {
    7769           0 :                 return WERR_INVALID_HANDLE;
    7770             :         }
    7771             : 
    7772          32 :         return WERR_OK;
    7773             : }
    7774             : 
    7775             : /****************************************************************
    7776             :  _spoolss_SetJob
    7777             : ****************************************************************/
    7778             : 
    7779         640 : WERROR _spoolss_SetJob(struct pipes_struct *p,
    7780             :                        struct spoolss_SetJob *r)
    7781             : {
    7782         640 :         const struct auth_session_info *session_info = p->session_info;
    7783             :         int snum;
    7784         640 :         WERROR errcode = WERR_INVALID_FUNCTION;
    7785             : 
    7786         640 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7787           0 :                 return WERR_INVALID_HANDLE;
    7788             :         }
    7789             : 
    7790         640 :         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
    7791         251 :                 return WERR_INVALID_PRINTER_NAME;
    7792             :         }
    7793             : 
    7794         389 :         switch (r->in.command) {
    7795         293 :         case SPOOLSS_JOB_CONTROL_CANCEL:
    7796             :         case SPOOLSS_JOB_CONTROL_DELETE:
    7797         293 :                 errcode = print_job_delete(session_info, p->msg_ctx,
    7798             :                                            snum, r->in.job_id);
    7799         293 :                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
    7800         293 :                         errcode = WERR_OK;
    7801             :                 }
    7802         293 :                 break;
    7803          32 :         case SPOOLSS_JOB_CONTROL_PAUSE:
    7804          32 :                 errcode = print_job_pause(session_info, p->msg_ctx,
    7805             :                                           snum, r->in.job_id);
    7806          32 :                 break;
    7807          32 :         case SPOOLSS_JOB_CONTROL_RESTART:
    7808             :         case SPOOLSS_JOB_CONTROL_RESUME:
    7809          32 :                 errcode = print_job_resume(session_info, p->msg_ctx,
    7810             :                                            snum, r->in.job_id);
    7811          32 :                 break;
    7812          32 :         case SPOOLSS_JOB_CONTROL_NOOP:
    7813          32 :                 errcode = WERR_OK;
    7814          32 :                 break;
    7815           0 :         default:
    7816           0 :                 return WERR_INVALID_LEVEL;
    7817             :         }
    7818             : 
    7819         389 :         if (!W_ERROR_IS_OK(errcode)) {
    7820           0 :                 return errcode;
    7821             :         }
    7822             : 
    7823         389 :         if (r->in.ctr == NULL) {
    7824         357 :                 return errcode;
    7825             :         }
    7826             : 
    7827          32 :         switch (r->in.ctr->level) {
    7828          32 :         case 1:
    7829          32 :                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
    7830             :                                            lp_const_servicename(snum),
    7831             :                                            r->in.job_id,
    7832          32 :                                            r->in.ctr->info.info1);
    7833          32 :                 break;
    7834           0 :         case 2:
    7835             :         case 3:
    7836             :         case 4:
    7837             :         default:
    7838           0 :                 return WERR_INVALID_LEVEL;
    7839             :         }
    7840             : 
    7841          32 :         return errcode;
    7842             : }
    7843             : 
    7844             : /****************************************************************************
    7845             :  Enumerates all printer drivers by level and architecture.
    7846             : ****************************************************************************/
    7847             : 
    7848         460 : static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
    7849             :                                                        const struct auth_session_info *session_info,
    7850             :                                                        struct messaging_context *msg_ctx,
    7851             :                                                        const char *servername,
    7852             :                                                        const char *architecture,
    7853             :                                                        uint32_t level,
    7854             :                                                        union spoolss_DriverInfo **info_p,
    7855             :                                                        uint32_t *count_p)
    7856             : {
    7857             :         int i;
    7858             :         uint32_t version;
    7859             :         struct spoolss_DriverInfo8 *driver;
    7860         460 :         union spoolss_DriverInfo *info = NULL;
    7861         460 :         uint32_t count = 0;
    7862         460 :         WERROR result = WERR_OK;
    7863             :         uint32_t num_drivers;
    7864             :         const char **drivers;
    7865             :         struct dcerpc_binding_handle *b;
    7866         460 :         TALLOC_CTX *tmp_ctx = NULL;
    7867             : 
    7868         460 :         *count_p = 0;
    7869         460 :         *info_p = NULL;
    7870             : 
    7871         460 :         tmp_ctx = talloc_new(mem_ctx);
    7872         460 :         if (!tmp_ctx) {
    7873           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    7874             :         }
    7875             : 
    7876         460 :         result = winreg_printer_binding_handle(tmp_ctx,
    7877             :                                                session_info,
    7878             :                                                msg_ctx,
    7879             :                                                &b);
    7880         460 :         if (!W_ERROR_IS_OK(result)) {
    7881           0 :                 goto out;
    7882             :         }
    7883             : 
    7884        2300 :         for (version=0; version<DRIVER_MAX_VERSION; version++) {
    7885        1840 :                 result = winreg_get_driver_list(tmp_ctx, b,
    7886             :                                                 architecture, version,
    7887             :                                                 &num_drivers, &drivers);
    7888        1840 :                 if (!W_ERROR_IS_OK(result)) {
    7889           0 :                         goto out;
    7890             :                 }
    7891        1840 :                 DEBUG(4, ("we have:[%d] drivers in environment"
    7892             :                           " [%s] and version [%d]\n",
    7893             :                           num_drivers, architecture, version));
    7894             : 
    7895        1840 :                 if (num_drivers != 0) {
    7896           0 :                         info = talloc_realloc(tmp_ctx, info,
    7897             :                                                     union spoolss_DriverInfo,
    7898             :                                                     count + num_drivers);
    7899           0 :                         if (!info) {
    7900           0 :                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
    7901             :                                         "failed to enlarge driver info buffer!\n"));
    7902           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
    7903           0 :                                 goto out;
    7904             :                         }
    7905             :                 }
    7906             : 
    7907        1840 :                 for (i = 0; i < num_drivers; i++) {
    7908           0 :                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
    7909             : 
    7910           0 :                         result = winreg_get_driver(tmp_ctx, b,
    7911           0 :                                                    architecture, drivers[i],
    7912             :                                                    version, &driver);
    7913           0 :                         if (!W_ERROR_IS_OK(result)) {
    7914           0 :                                 goto out;
    7915             :                         }
    7916             : 
    7917           0 :                         switch (level) {
    7918           0 :                         case 1:
    7919           0 :                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
    7920             :                                                                    driver, servername);
    7921           0 :                                 break;
    7922           0 :                         case 2:
    7923           0 :                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
    7924             :                                                                    driver, servername);
    7925           0 :                                 break;
    7926           0 :                         case 3:
    7927           0 :                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
    7928             :                                                                    driver, servername);
    7929           0 :                                 break;
    7930           0 :                         case 4:
    7931           0 :                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
    7932             :                                                                    driver, servername);
    7933           0 :                                 break;
    7934           0 :                         case 5:
    7935           0 :                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
    7936             :                                                                    driver, servername);
    7937           0 :                                 break;
    7938           0 :                         case 6:
    7939           0 :                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
    7940             :                                                                    driver, servername);
    7941           0 :                                 break;
    7942           0 :                         case 8:
    7943           0 :                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
    7944             :                                                                    driver, servername);
    7945           0 :                                 break;
    7946           0 :                         default:
    7947           0 :                                 result = WERR_INVALID_LEVEL;
    7948           0 :                                 break;
    7949             :                         }
    7950             : 
    7951           0 :                         TALLOC_FREE(driver);
    7952             : 
    7953           0 :                         if (!W_ERROR_IS_OK(result)) {
    7954           0 :                                 goto out;
    7955             :                         }
    7956             :                 }
    7957             : 
    7958        1840 :                 count += num_drivers;
    7959        1840 :                 TALLOC_FREE(drivers);
    7960             :         }
    7961             : 
    7962         460 : out:
    7963         460 :         if (W_ERROR_IS_OK(result)) {
    7964         460 :                 *info_p = talloc_move(mem_ctx, &info);
    7965         460 :                 *count_p = count;
    7966             :         }
    7967             : 
    7968         460 :         talloc_free(tmp_ctx);
    7969         460 :         return result;
    7970             : }
    7971             : 
    7972             : /****************************************************************************
    7973             :  Enumerates all printer drivers by level.
    7974             : ****************************************************************************/
    7975             : 
    7976         108 : static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
    7977             :                                        const struct auth_session_info *session_info,
    7978             :                                        struct messaging_context *msg_ctx,
    7979             :                                        const char *servername,
    7980             :                                        const char *architecture,
    7981             :                                        uint32_t level,
    7982             :                                        union spoolss_DriverInfo **info_p,
    7983             :                                        uint32_t *count_p)
    7984             : {
    7985             :         uint32_t a,i;
    7986         108 :         WERROR result = WERR_OK;
    7987             : 
    7988         108 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
    7989             : 
    7990         440 :                 for (a=0; archi_table[a].long_archi != NULL; a++) {
    7991             : 
    7992         396 :                         union spoolss_DriverInfo *info = NULL;
    7993         396 :                         uint32_t count = 0;
    7994             : 
    7995         396 :                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
    7996             :                                                                           session_info,
    7997             :                                                                           msg_ctx,
    7998             :                                                                           servername,
    7999          99 :                                                                           archi_table[a].long_archi,
    8000             :                                                                           level,
    8001             :                                                                           &info,
    8002             :                                                                           &count);
    8003         396 :                         if (!W_ERROR_IS_OK(result)) {
    8004           0 :                                 continue;
    8005             :                         }
    8006             : 
    8007         396 :                         for (i=0; i < count; i++) {
    8008           0 :                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
    8009             :                                              info[i], info_p, count_p);
    8010             :                         }
    8011             :                 }
    8012             : 
    8013          44 :                 return result;
    8014             :         }
    8015             : 
    8016          64 :         return enumprinterdrivers_level_by_architecture(mem_ctx,
    8017             :                                                         session_info,
    8018             :                                                         msg_ctx,
    8019             :                                                         servername,
    8020             :                                                         architecture,
    8021             :                                                         level,
    8022             :                                                         info_p,
    8023             :                                                         count_p);
    8024             : }
    8025             : 
    8026             : /****************************************************************
    8027             :  _spoolss_EnumPrinterDrivers
    8028             : ****************************************************************/
    8029             : 
    8030         108 : WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
    8031             :                                    struct spoolss_EnumPrinterDrivers *r)
    8032             : {
    8033             :         const char *cservername;
    8034             :         WERROR result;
    8035             : 
    8036             :         /* that's an [in out] buffer */
    8037             : 
    8038         108 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8039           0 :                 return WERR_INVALID_PARAMETER;
    8040             :         }
    8041             : 
    8042         108 :         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
    8043             : 
    8044         108 :         *r->out.needed = 0;
    8045         108 :         *r->out.count = 0;
    8046         108 :         *r->out.info = NULL;
    8047             : 
    8048         108 :         cservername = canon_servername(r->in.server);
    8049             : 
    8050         108 :         if (!is_myname_or_ipaddr(cservername)) {
    8051           0 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    8052             :         }
    8053             : 
    8054         108 :         result = enumprinterdrivers_level(p->mem_ctx,
    8055             :                                           get_session_info_system(),
    8056             :                                           p->msg_ctx,
    8057             :                                           cservername,
    8058             :                                           r->in.environment,
    8059             :                                           r->in.level,
    8060             :                                           r->out.info,
    8061             :                                           r->out.count);
    8062         108 :         if (!W_ERROR_IS_OK(result)) {
    8063           0 :                 return result;
    8064             :         }
    8065             : 
    8066         108 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8067             :                                                      spoolss_EnumPrinterDrivers,
    8068             :                                                      *r->out.info, r->in.level,
    8069             :                                                      *r->out.count);
    8070         108 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8071         108 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8072             : 
    8073         108 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8074             : }
    8075             : 
    8076             : /****************************************************************
    8077             :  _spoolss_EnumForms
    8078             : ****************************************************************/
    8079             : 
    8080         560 : WERROR _spoolss_EnumForms(struct pipes_struct *p,
    8081             :                           struct spoolss_EnumForms *r)
    8082             : {
    8083             :         WERROR result;
    8084             : 
    8085         560 :         *r->out.count = 0;
    8086         560 :         *r->out.needed = 0;
    8087         560 :         *r->out.info = NULL;
    8088             : 
    8089             :         /* that's an [in out] buffer */
    8090             : 
    8091         560 :         if (!r->in.buffer && (r->in.offered != 0) ) {
    8092           0 :                 return WERR_INVALID_PARAMETER;
    8093             :         }
    8094             : 
    8095         560 :         DEBUG(4,("_spoolss_EnumForms\n"));
    8096         560 :         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
    8097         560 :         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
    8098             : 
    8099         560 :         switch (r->in.level) {
    8100         536 :         case 1:
    8101         536 :                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
    8102             :                                                    get_session_info_system(),
    8103             :                                                    p->msg_ctx,
    8104             :                                                    r->out.count,
    8105             :                                                    r->out.info);
    8106         536 :                 break;
    8107          24 :         default:
    8108          24 :                 result = WERR_INVALID_LEVEL;
    8109          24 :                 break;
    8110             :         }
    8111             : 
    8112         560 :         if (!W_ERROR_IS_OK(result)) {
    8113          24 :                 return result;
    8114             :         }
    8115             : 
    8116         536 :         if (*r->out.count == 0) {
    8117           0 :                 return WERR_NO_MORE_ITEMS;
    8118             :         }
    8119             : 
    8120         536 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8121             :                                                      spoolss_EnumForms,
    8122             :                                                      *r->out.info, r->in.level,
    8123             :                                                      *r->out.count);
    8124         536 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8125         536 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8126             : 
    8127         536 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8128             : }
    8129             : 
    8130             : /****************************************************************
    8131             :  _spoolss_GetForm
    8132             : ****************************************************************/
    8133             : 
    8134        5040 : WERROR _spoolss_GetForm(struct pipes_struct *p,
    8135             :                         struct spoolss_GetForm *r)
    8136             : {
    8137             :         WERROR result;
    8138             : 
    8139             :         /* that's an [in out] buffer */
    8140             : 
    8141        5040 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8142           0 :                 TALLOC_FREE(r->out.info);
    8143           0 :                 return WERR_INVALID_PARAMETER;
    8144             :         }
    8145             : 
    8146        5040 :         DEBUG(4,("_spoolss_GetForm\n"));
    8147        5040 :         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
    8148        5040 :         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
    8149             : 
    8150        5040 :         switch (r->in.level) {
    8151        5040 :         case 1:
    8152        5040 :                 result = winreg_printer_getform1_internal(p->mem_ctx,
    8153             :                                                  get_session_info_system(),
    8154             :                                                  p->msg_ctx,
    8155             :                                                  r->in.form_name,
    8156        5040 :                                                  &r->out.info->info1);
    8157        5040 :                 break;
    8158           0 :         default:
    8159           0 :                 result = WERR_INVALID_LEVEL;
    8160           0 :                 break;
    8161             :         }
    8162             : 
    8163        5040 :         if (!W_ERROR_IS_OK(result)) {
    8164           0 :                 TALLOC_FREE(r->out.info);
    8165           0 :                 return result;
    8166             :         }
    8167             : 
    8168        5040 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
    8169             :                                                r->out.info, r->in.level);
    8170        5040 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    8171             : 
    8172        5040 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8173             : }
    8174             : 
    8175             : /****************************************************************************
    8176             : ****************************************************************************/
    8177             : 
    8178           8 : static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
    8179             :                           struct spoolss_PortInfo1 *r,
    8180             :                           const char *name)
    8181             : {
    8182           8 :         r->port_name = talloc_strdup(mem_ctx, name);
    8183           8 :         W_ERROR_HAVE_NO_MEMORY(r->port_name);
    8184             : 
    8185           8 :         return WERR_OK;
    8186             : }
    8187             : 
    8188             : /****************************************************************************
    8189             :  TODO: This probably needs distinguish between TCP/IP and Local ports
    8190             :  somehow.
    8191             : ****************************************************************************/
    8192             : 
    8193          16 : static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
    8194             :                           struct spoolss_PortInfo2 *r,
    8195             :                           const char *name)
    8196             : {
    8197          16 :         r->port_name = talloc_strdup(mem_ctx, name);
    8198          16 :         W_ERROR_HAVE_NO_MEMORY(r->port_name);
    8199             : 
    8200          16 :         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
    8201          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    8202             : 
    8203          16 :         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
    8204          16 :         W_ERROR_HAVE_NO_MEMORY(r->description);
    8205             : 
    8206          16 :         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
    8207          16 :         r->reserved = 0;
    8208             : 
    8209          16 :         return WERR_OK;
    8210             : }
    8211             : 
    8212             : 
    8213             : /****************************************************************************
    8214             :  wrapper around the enumer ports command
    8215             : ****************************************************************************/
    8216             : 
    8217          24 : static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
    8218             : {
    8219          18 :         const struct loadparm_substitution *lp_sub =
    8220           6 :                 loadparm_s3_global_substitution();
    8221          24 :         char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
    8222          24 :         char **qlines = NULL;
    8223          24 :         char *command = NULL;
    8224             :         int numlines;
    8225             :         int ret;
    8226             :         int fd;
    8227             : 
    8228          24 :         *count = 0;
    8229          24 :         *lines = NULL;
    8230             : 
    8231             :         /* if no hook then just fill in the default port */
    8232             : 
    8233          24 :         if ( !*cmd ) {
    8234          24 :                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
    8235           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8236             :                 }
    8237          24 :                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
    8238           0 :                         TALLOC_FREE(qlines);
    8239           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8240             :                 }
    8241          24 :                 qlines[1] = NULL;
    8242          24 :                 numlines = 1;
    8243             :         }
    8244             :         else {
    8245             :                 /* we have a valid enumport command */
    8246             : 
    8247           0 :                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
    8248           0 :                 if (!command) {
    8249           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8250             :                 }
    8251             : 
    8252           0 :                 DEBUG(10,("Running [%s]\n", command));
    8253           0 :                 ret = smbrun(command, &fd, NULL);
    8254           0 :                 DEBUG(10,("Returned [%d]\n", ret));
    8255           0 :                 TALLOC_FREE(command);
    8256           0 :                 if (ret != 0) {
    8257           0 :                         if (fd != -1) {
    8258           0 :                                 close(fd);
    8259             :                         }
    8260           0 :                         return WERR_ACCESS_DENIED;
    8261             :                 }
    8262             : 
    8263           0 :                 numlines = 0;
    8264           0 :                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
    8265           0 :                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
    8266           0 :                 close(fd);
    8267             :         }
    8268             : 
    8269          24 :         *count = numlines;
    8270          24 :         *lines = qlines;
    8271             : 
    8272          24 :         return WERR_OK;
    8273             : }
    8274             : 
    8275             : /****************************************************************************
    8276             :  enumports level 1.
    8277             : ****************************************************************************/
    8278             : 
    8279           8 : static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
    8280             :                                 union spoolss_PortInfo **info_p,
    8281             :                                 uint32_t *count)
    8282             : {
    8283           8 :         union spoolss_PortInfo *info = NULL;
    8284           8 :         int i=0;
    8285           8 :         WERROR result = WERR_OK;
    8286           8 :         char **qlines = NULL;
    8287           8 :         int numlines = 0;
    8288             : 
    8289           8 :         result = enumports_hook(talloc_tos(), &numlines, &qlines );
    8290           8 :         if (!W_ERROR_IS_OK(result)) {
    8291           0 :                 goto out;
    8292             :         }
    8293             : 
    8294           8 :         if (numlines) {
    8295           8 :                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
    8296           8 :                 if (!info) {
    8297           0 :                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
    8298           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    8299           0 :                         goto out;
    8300             :                 }
    8301             : 
    8302          16 :                 for (i=0; i<numlines; i++) {
    8303           8 :                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
    8304           8 :                         result = fill_port_1(info, &info[i].info1, qlines[i]);
    8305           8 :                         if (!W_ERROR_IS_OK(result)) {
    8306           0 :                                 goto out;
    8307             :                         }
    8308             :                 }
    8309             :         }
    8310          14 :         TALLOC_FREE(qlines);
    8311             : 
    8312           6 : out:
    8313           8 :         if (!W_ERROR_IS_OK(result)) {
    8314           0 :                 TALLOC_FREE(info);
    8315           0 :                 TALLOC_FREE(qlines);
    8316           0 :                 *count = 0;
    8317           0 :                 *info_p = NULL;
    8318           0 :                 return result;
    8319             :         }
    8320             : 
    8321           8 :         *info_p = info;
    8322           8 :         *count = numlines;
    8323             : 
    8324           8 :         return WERR_OK;
    8325             : }
    8326             : 
    8327             : /****************************************************************************
    8328             :  enumports level 2.
    8329             : ****************************************************************************/
    8330             : 
    8331          16 : static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
    8332             :                                 union spoolss_PortInfo **info_p,
    8333             :                                 uint32_t *count)
    8334             : {
    8335          16 :         union spoolss_PortInfo *info = NULL;
    8336          16 :         int i=0;
    8337          16 :         WERROR result = WERR_OK;
    8338          16 :         char **qlines = NULL;
    8339          16 :         int numlines = 0;
    8340             : 
    8341          16 :         result = enumports_hook(talloc_tos(), &numlines, &qlines );
    8342          16 :         if (!W_ERROR_IS_OK(result)) {
    8343           0 :                 goto out;
    8344             :         }
    8345             : 
    8346          16 :         if (numlines) {
    8347          16 :                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
    8348          16 :                 if (!info) {
    8349           0 :                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
    8350           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    8351           0 :                         goto out;
    8352             :                 }
    8353             : 
    8354          32 :                 for (i=0; i<numlines; i++) {
    8355          16 :                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
    8356          16 :                         result = fill_port_2(info, &info[i].info2, qlines[i]);
    8357          16 :                         if (!W_ERROR_IS_OK(result)) {
    8358           0 :                                 goto out;
    8359             :                         }
    8360             :                 }
    8361             :         }
    8362          28 :         TALLOC_FREE(qlines);
    8363             : 
    8364          12 : out:
    8365          16 :         if (!W_ERROR_IS_OK(result)) {
    8366           0 :                 TALLOC_FREE(info);
    8367           0 :                 TALLOC_FREE(qlines);
    8368           0 :                 *count = 0;
    8369           0 :                 *info_p = NULL;
    8370           0 :                 return result;
    8371             :         }
    8372             : 
    8373          16 :         *info_p = info;
    8374          16 :         *count = numlines;
    8375             : 
    8376          16 :         return WERR_OK;
    8377             : }
    8378             : 
    8379             : /****************************************************************
    8380             :  _spoolss_EnumPorts
    8381             : ****************************************************************/
    8382             : 
    8383          24 : WERROR _spoolss_EnumPorts(struct pipes_struct *p,
    8384             :                           struct spoolss_EnumPorts *r)
    8385             : {
    8386             :         WERROR result;
    8387             : 
    8388             :         /* that's an [in out] buffer */
    8389             : 
    8390          24 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8391           0 :                 return WERR_INVALID_PARAMETER;
    8392             :         }
    8393             : 
    8394          24 :         DEBUG(4,("_spoolss_EnumPorts\n"));
    8395             : 
    8396          24 :         *r->out.count = 0;
    8397          24 :         *r->out.needed = 0;
    8398          24 :         *r->out.info = NULL;
    8399             : 
    8400          24 :         switch (r->in.level) {
    8401           8 :         case 1:
    8402           8 :                 result = enumports_level_1(p->mem_ctx, r->out.info,
    8403             :                                            r->out.count);
    8404           8 :                 break;
    8405          16 :         case 2:
    8406          16 :                 result = enumports_level_2(p->mem_ctx, r->out.info,
    8407             :                                            r->out.count);
    8408          16 :                 break;
    8409           0 :         default:
    8410           0 :                 return WERR_INVALID_LEVEL;
    8411             :         }
    8412             : 
    8413          24 :         if (!W_ERROR_IS_OK(result)) {
    8414           0 :                 return result;
    8415             :         }
    8416             : 
    8417          24 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8418             :                                                      spoolss_EnumPorts,
    8419             :                                                      *r->out.info, r->in.level,
    8420             :                                                      *r->out.count);
    8421          24 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8422          24 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8423             : 
    8424          24 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8425             : }
    8426             : 
    8427             : /****************************************************************************
    8428             : ****************************************************************************/
    8429             : 
    8430          96 : static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
    8431             :                                            const char *server,
    8432             :                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
    8433             :                                            struct spoolss_DeviceMode *devmode,
    8434             :                                            struct security_descriptor *secdesc,
    8435             :                                            struct spoolss_UserLevelCtr *user_ctr,
    8436             :                                            struct policy_handle *handle)
    8437             : {
    8438          96 :         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
    8439          96 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
    8440          72 :         const struct loadparm_substitution *lp_sub =
    8441          24 :                 loadparm_s3_global_substitution();
    8442             :         int     snum;
    8443          96 :         WERROR err = WERR_OK;
    8444             : 
    8445             :         /* samba does not have a concept of local, non-shared printers yet, so
    8446             :          * make sure we always setup sharename - gd */
    8447         168 :         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
    8448         156 :             (info2->printername != NULL && info2->printername[0] != '\0')) {
    8449          80 :                 DEBUG(5, ("spoolss_addprinterex_level_2: "
    8450             :                         "no sharename has been set, setting printername %s as sharename\n",
    8451             :                         info2->printername));
    8452          80 :                 info2->sharename = info2->printername;
    8453             :         }
    8454             : 
    8455             :         /* check to see if the printer already exists */
    8456          96 :         if ((snum = print_queue_snum(info2->sharename)) != -1) {
    8457          16 :                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
    8458             :                         info2->sharename));
    8459          16 :                 return WERR_PRINTER_ALREADY_EXISTS;
    8460             :         }
    8461             : 
    8462          80 :         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
    8463          80 :                 if ((snum = print_queue_snum(info2->printername)) != -1) {
    8464           0 :                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
    8465             :                                 info2->printername));
    8466           0 :                         return WERR_PRINTER_ALREADY_EXISTS;
    8467             :                 }
    8468             :         }
    8469             : 
    8470             :         /* validate printer info struct */
    8471          80 :         if (!info2->printername || strlen(info2->printername) == 0) {
    8472          16 :                 return WERR_INVALID_PRINTER_NAME;
    8473             :         }
    8474          64 :         if (!info2->portname || strlen(info2->portname) == 0) {
    8475          16 :                 return WERR_UNKNOWN_PORT;
    8476             :         }
    8477          48 :         if (!info2->drivername || strlen(info2->drivername) == 0) {
    8478          16 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    8479             :         }
    8480          32 :         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
    8481          16 :                 return WERR_UNKNOWN_PRINTPROCESSOR;
    8482             :         }
    8483             : 
    8484             :         /* FIXME!!!  smbd should check to see if the driver is installed before
    8485             :            trying to add a printer like this  --jerry */
    8486             : 
    8487          16 :         if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
    8488             :                 char *raddr;
    8489             : 
    8490          16 :                 raddr = tsocket_address_inet_addr_string(p->remote_address,
    8491             :                                                          p->mem_ctx);
    8492          16 :                 if (raddr == NULL) {
    8493           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8494             :                 }
    8495             : 
    8496          16 :                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
    8497             :                                        info2, raddr,
    8498             :                                        p->msg_ctx) ) {
    8499           0 :                         return WERR_ACCESS_DENIED;
    8500             :                 }
    8501             :         } else {
    8502           0 :                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
    8503             :                         "smb.conf parameter \"addprinter command\" is defined. This "
    8504             :                         "parameter must exist for this call to succeed\n",
    8505             :                         info2->sharename ));
    8506             :         }
    8507             : 
    8508          16 :         if ((snum = print_queue_snum(info2->sharename)) == -1) {
    8509           0 :                 return WERR_ACCESS_DENIED;
    8510             :         }
    8511             : 
    8512             :         /* you must be a printer admin to add a new printer */
    8513          16 :         if (!W_ERROR_IS_OK(print_access_check(p->session_info,
    8514             :                                               p->msg_ctx,
    8515             :                                               snum,
    8516             :                                               PRINTER_ACCESS_ADMINISTER))) {
    8517           0 :                 return WERR_ACCESS_DENIED;
    8518             :         }
    8519             : 
    8520             :         /*
    8521             :          * Do sanity check on the requested changes for Samba.
    8522             :          */
    8523             : 
    8524          16 :         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
    8525           0 :                 return WERR_INVALID_PARAMETER;
    8526             :         }
    8527             : 
    8528          16 :         if (devmode == NULL) {
    8529          16 :                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
    8530             :         }
    8531             : 
    8532          16 :         err = update_dsspooler(p->mem_ctx,
    8533             :                                get_session_info_system(),
    8534             :                                p->msg_ctx,
    8535             :                                0,
    8536             :                                info2,
    8537             :                                NULL);
    8538          16 :         if (!W_ERROR_IS_OK(err)) {
    8539           0 :                 return err;
    8540             :         }
    8541             : 
    8542          16 :         err = winreg_update_printer_internal(p->mem_ctx,
    8543             :                                     get_session_info_system(),
    8544             :                                     p->msg_ctx,
    8545             :                                     info2->sharename,
    8546             :                                     info2_mask,
    8547             :                                     info2,
    8548             :                                     devmode,
    8549             :                                     secdesc);
    8550          16 :         if (!W_ERROR_IS_OK(err)) {
    8551           0 :                 return err;
    8552             :         }
    8553             : 
    8554          16 :         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
    8555          16 :         if (!W_ERROR_IS_OK(err)) {
    8556             :                 /* Handle open failed - remove addition. */
    8557           0 :                 ZERO_STRUCTP(handle);
    8558           0 :                 return err;
    8559             :         }
    8560             : 
    8561          16 :         return WERR_OK;
    8562             : }
    8563             : 
    8564             : /****************************************************************
    8565             :  _spoolss_AddPrinterEx
    8566             : ****************************************************************/
    8567             : 
    8568          96 : WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
    8569             :                              struct spoolss_AddPrinterEx *r)
    8570             : {
    8571          96 :         switch (r->in.info_ctr->level) {
    8572           0 :         case 1:
    8573             :                 /* we don't handle yet */
    8574             :                 /* but I know what to do ... */
    8575           0 :                 return WERR_INVALID_LEVEL;
    8576          96 :         case 2:
    8577         240 :                 return spoolss_addprinterex_level_2(p, r->in.server,
    8578             :                                                     r->in.info_ctr,
    8579          96 :                                                     r->in.devmode_ctr->devmode,
    8580          96 :                                                     r->in.secdesc_ctr->sd,
    8581             :                                                     r->in.userlevel_ctr,
    8582             :                                                     r->out.handle);
    8583           0 :         default:
    8584           0 :                 return WERR_INVALID_LEVEL;
    8585             :         }
    8586             : }
    8587             : 
    8588             : /****************************************************************
    8589             :  _spoolss_AddPrinter
    8590             : ****************************************************************/
    8591             : 
    8592          72 : WERROR _spoolss_AddPrinter(struct pipes_struct *p,
    8593             :                            struct spoolss_AddPrinter *r)
    8594             : {
    8595             :         struct spoolss_AddPrinterEx a;
    8596             :         struct spoolss_UserLevelCtr userlevel_ctr;
    8597             : 
    8598          72 :         ZERO_STRUCT(userlevel_ctr);
    8599             : 
    8600          72 :         userlevel_ctr.level = 1;
    8601             : 
    8602          72 :         a.in.server             = r->in.server;
    8603          72 :         a.in.info_ctr           = r->in.info_ctr;
    8604          72 :         a.in.devmode_ctr        = r->in.devmode_ctr;
    8605          72 :         a.in.secdesc_ctr        = r->in.secdesc_ctr;
    8606          72 :         a.in.userlevel_ctr      = &userlevel_ctr;
    8607          72 :         a.out.handle            = r->out.handle;
    8608             : 
    8609          72 :         return _spoolss_AddPrinterEx(p, &a);
    8610             : }
    8611             : 
    8612             : /****************************************************************
    8613             :  _spoolss_AddPrinterDriverEx
    8614             : ****************************************************************/
    8615             : 
    8616           0 : WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
    8617             :                                    struct spoolss_AddPrinterDriverEx *r)
    8618             : {
    8619           0 :         WERROR err = WERR_OK;
    8620           0 :         const char *driver_name = NULL;
    8621           0 :         const char *driver_directory = NULL;
    8622             :         uint32_t version;
    8623             : 
    8624             :         /*
    8625             :          * we only support the semantics of AddPrinterDriver()
    8626             :          * i.e. only copy files that are newer than existing ones
    8627             :          */
    8628             : 
    8629           0 :         if (r->in.flags == 0) {
    8630           0 :                 return WERR_INVALID_PARAMETER;
    8631             :         }
    8632             : 
    8633           0 :         if (!(r->in.flags & APD_COPY_ALL_FILES) &&
    8634           0 :             !(r->in.flags & APD_COPY_NEW_FILES)) {
    8635           0 :                 return WERR_ACCESS_DENIED;
    8636             :         }
    8637             : 
    8638             :         /* FIXME */
    8639           0 :         if (r->in.info_ctr->level != 3 &&
    8640           0 :             r->in.info_ctr->level != 6 &&
    8641           0 :             r->in.info_ctr->level != 8) {
    8642           0 :                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
    8643             :                         r->in.info_ctr->level));
    8644           0 :                 return WERR_INVALID_LEVEL;
    8645             :         }
    8646             : 
    8647           0 :         DEBUG(5,("Cleaning driver's information\n"));
    8648           0 :         err = clean_up_driver_struct(p->mem_ctx,
    8649           0 :                                      p->session_info,
    8650           0 :                                      r->in.info_ctr,
    8651             :                                      r->in.flags,
    8652             :                                      &driver_directory);
    8653           0 :         if (!W_ERROR_IS_OK(err)) {
    8654           0 :                 DBG_ERR("clean_up_driver_struct failed - %s\n",
    8655             :                         win_errstr(err));
    8656           0 :                 goto done;
    8657             :         }
    8658             : 
    8659           0 :         DEBUG(5,("Moving driver to final destination\n"));
    8660           0 :         err = move_driver_to_download_area(p->session_info,
    8661           0 :                                            r->in.info_ctr,
    8662             :                                            driver_directory);
    8663           0 :         if (!W_ERROR_IS_OK(err)) {
    8664           0 :                 DBG_ERR("move_driver_to_download_area failed - %s\n",
    8665             :                         win_errstr(err));
    8666           0 :                 goto done;
    8667             :         }
    8668             : 
    8669           0 :         err = winreg_add_driver_internal(p->mem_ctx,
    8670             :                                 get_session_info_system(),
    8671             :                                 p->msg_ctx,
    8672             :                                 r->in.info_ctr,
    8673             :                                 &driver_name,
    8674             :                                 &version);
    8675           0 :         if (!W_ERROR_IS_OK(err)) {
    8676           0 :                 DBG_ERR("winreg_add_driver_internal failed - %s\n",
    8677             :                         win_errstr(err));
    8678           0 :                 goto done;
    8679             :         }
    8680             : 
    8681             :         /*
    8682             :          * I think this is where he DrvUpgradePrinter() hook would be
    8683             :          * be called in a driver's interface DLL on a Windows NT 4.0/2k
    8684             :          * server.  Right now, we just need to send ourselves a message
    8685             :          * to update each printer bound to this driver.   --jerry
    8686             :          */
    8687             : 
    8688           0 :         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
    8689           0 :                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
    8690             :                         __func__, driver_name));
    8691             :         }
    8692             : 
    8693           0 : done:
    8694           0 :         return err;
    8695             : }
    8696             : 
    8697             : /****************************************************************
    8698             :  _spoolss_AddPrinterDriver
    8699             : ****************************************************************/
    8700             : 
    8701           0 : WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
    8702             :                                  struct spoolss_AddPrinterDriver *r)
    8703             : {
    8704             :         struct spoolss_AddPrinterDriverEx a;
    8705             : 
    8706           0 :         switch (r->in.info_ctr->level) {
    8707           0 :         case 2:
    8708             :         case 3:
    8709             :         case 4:
    8710             :         case 5:
    8711           0 :                 break;
    8712           0 :         default:
    8713           0 :                 return WERR_INVALID_LEVEL;
    8714             :         }
    8715             : 
    8716           0 :         a.in.servername         = r->in.servername;
    8717           0 :         a.in.info_ctr           = r->in.info_ctr;
    8718           0 :         a.in.flags              = APD_COPY_NEW_FILES;
    8719             : 
    8720           0 :         return _spoolss_AddPrinterDriverEx(p, &a);
    8721             : }
    8722             : 
    8723             : /****************************************************************************
    8724             : ****************************************************************************/
    8725             : 
    8726             : struct _spoolss_paths {
    8727             :         int type;
    8728             :         const char *share;
    8729             :         const char *dir;
    8730             : };
    8731             : 
    8732             : enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
    8733             : 
    8734             : static const struct _spoolss_paths spoolss_paths[]= {
    8735             :         { SPOOLSS_DRIVER_PATH,          "print$",     "DRIVERS" },
    8736             :         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",   "PRTPROCS" }
    8737             : };
    8738             : 
    8739         152 : static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
    8740             :                                           const char *servername,
    8741             :                                           const char *environment,
    8742             :                                           int component,
    8743             :                                           char **path)
    8744             : {
    8745         152 :         const char *pservername = NULL;
    8746             :         const char *long_archi;
    8747             :         const char *short_archi;
    8748             : 
    8749         152 :         *path = NULL;
    8750             : 
    8751             :         /* environment may be empty */
    8752         152 :         if (environment && strlen(environment)) {
    8753         152 :                 long_archi = environment;
    8754             :         } else {
    8755           0 :                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    8756             :                                                   "spoolss", "architecture",
    8757             :                                                   GLOBAL_SPOOLSS_ARCHITECTURE);
    8758             :         }
    8759             : 
    8760             :         /* servername may be empty */
    8761         152 :         if (servername && strlen(servername)) {
    8762          88 :                 pservername = canon_servername(servername);
    8763             : 
    8764          88 :                 if (!is_myname_or_ipaddr(pservername)) {
    8765           0 :                         return WERR_INVALID_PARAMETER;
    8766             :                 }
    8767             :         }
    8768             : 
    8769         152 :         if (!(short_archi = get_short_archi(long_archi))) {
    8770           0 :                 return WERR_INVALID_ENVIRONMENT;
    8771             :         }
    8772             : 
    8773         152 :         switch (component) {
    8774         152 :         case SPOOLSS_PRTPROCS_PATH:
    8775             :         case SPOOLSS_DRIVER_PATH:
    8776         152 :                 if (pservername) {
    8777          88 :                         *path = talloc_asprintf(mem_ctx,
    8778             :                                         "\\\\%s\\%s\\%s",
    8779             :                                         pservername,
    8780          36 :                                         spoolss_paths[component].share,
    8781             :                                         short_archi);
    8782             :                 } else {
    8783          64 :                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
    8784             :                                         SPOOLSS_DEFAULT_SERVER_PATH,
    8785          16 :                                         spoolss_paths[component].dir,
    8786             :                                         short_archi);
    8787             :                 }
    8788         152 :                 break;
    8789           0 :         default:
    8790           0 :                 return WERR_INVALID_PARAMETER;
    8791             :         }
    8792             : 
    8793         152 :         if (!*path) {
    8794           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    8795             :         }
    8796             : 
    8797         152 :         return WERR_OK;
    8798             : }
    8799             : 
    8800             : /****************************************************************************
    8801             : ****************************************************************************/
    8802             : 
    8803         112 : static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
    8804             :                                           const char *servername,
    8805             :                                           const char *environment,
    8806             :                                           struct spoolss_DriverDirectoryInfo1 *r)
    8807             : {
    8808             :         WERROR werr;
    8809         112 :         char *path = NULL;
    8810             : 
    8811         112 :         werr = compose_spoolss_server_path(mem_ctx,
    8812             :                                            servername,
    8813             :                                            environment,
    8814             :                                            SPOOLSS_DRIVER_PATH,
    8815             :                                            &path);
    8816         112 :         if (!W_ERROR_IS_OK(werr)) {
    8817           0 :                 return werr;
    8818             :         }
    8819             : 
    8820         112 :         DEBUG(4,("printer driver directory: [%s]\n", path));
    8821             : 
    8822         112 :         r->directory_name = path;
    8823             : 
    8824         112 :         return WERR_OK;
    8825             : }
    8826             : 
    8827             : /****************************************************************
    8828             :  _spoolss_GetPrinterDriverDirectory
    8829             : ****************************************************************/
    8830             : 
    8831         112 : WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
    8832             :                                           struct spoolss_GetPrinterDriverDirectory *r)
    8833             : {
    8834             :         WERROR werror;
    8835             : 
    8836             :         /* that's an [in out] buffer */
    8837             : 
    8838         112 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8839           0 :                 TALLOC_FREE(r->out.info);
    8840           0 :                 return WERR_INVALID_PARAMETER;
    8841             :         }
    8842             : 
    8843         112 :         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
    8844             :                 r->in.level));
    8845             : 
    8846         112 :         *r->out.needed = 0;
    8847             : 
    8848             :         /* r->in.level is ignored */
    8849             : 
    8850         112 :         werror = getprinterdriverdir_level_1(p->mem_ctx,
    8851             :                                              r->in.server,
    8852             :                                              r->in.environment,
    8853         112 :                                              &r->out.info->info1);
    8854         112 :         if (!W_ERROR_IS_OK(werror)) {
    8855           0 :                 TALLOC_FREE(r->out.info);
    8856           0 :                 return werror;
    8857             :         }
    8858             : 
    8859         112 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
    8860             :                                                r->out.info, r->in.level);
    8861         112 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    8862             : 
    8863         112 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8864             : }
    8865             : 
    8866             : /****************************************************************
    8867             :  _spoolss_EnumPrinterData
    8868             : ****************************************************************/
    8869             : 
    8870         152 : WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
    8871             :                                 struct spoolss_EnumPrinterData *r)
    8872             : {
    8873             :         WERROR result;
    8874             :         struct spoolss_EnumPrinterDataEx r2;
    8875             :         uint32_t count;
    8876         152 :         struct spoolss_PrinterEnumValues *info, *val = NULL;
    8877             :         uint32_t needed;
    8878             : 
    8879         152 :         r2.in.handle    = r->in.handle;
    8880         152 :         r2.in.key_name  = "PrinterDriverData";
    8881         152 :         r2.in.offered   = 0;
    8882         152 :         r2.out.count    = &count;
    8883         152 :         r2.out.info     = &info;
    8884         152 :         r2.out.needed   = &needed;
    8885             : 
    8886         152 :         result = _spoolss_EnumPrinterDataEx(p, &r2);
    8887         152 :         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
    8888         112 :                 r2.in.offered = needed;
    8889         112 :                 result = _spoolss_EnumPrinterDataEx(p, &r2);
    8890             :         }
    8891         152 :         if (!W_ERROR_IS_OK(result)) {
    8892           0 :                 return result;
    8893             :         }
    8894             : 
    8895             :         /*
    8896             :          * The NT machine wants to know the biggest size of value and data
    8897             :          *
    8898             :          * cf: MSDN EnumPrinterData remark section
    8899             :          */
    8900             : 
    8901         152 :         if (!r->in.value_offered && !r->in.data_offered) {
    8902          48 :                 uint32_t biggest_valuesize = 0;
    8903          48 :                 uint32_t biggest_datasize = 0;
    8904             :                 int i, name_length;
    8905             : 
    8906          48 :                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
    8907             : 
    8908         132 :                 for (i=0; i<count; i++) {
    8909             : 
    8910          84 :                         name_length = strlen(info[i].value_name);
    8911          84 :                         if (strlen(info[i].value_name) > biggest_valuesize) {
    8912          28 :                                 biggest_valuesize = name_length;
    8913             :                         }
    8914             : 
    8915          84 :                         if (info[i].data_length > biggest_datasize) {
    8916          28 :                                 biggest_datasize = info[i].data_length;
    8917             :                         }
    8918             : 
    8919          84 :                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
    8920             :                                 biggest_datasize));
    8921             :                 }
    8922             : 
    8923             :                 /* the value is an UNICODE string but real_value_size is the length
    8924             :                    in bytes including the trailing 0 */
    8925             : 
    8926          48 :                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
    8927          48 :                 *r->out.data_needed  = biggest_datasize;
    8928             : 
    8929          48 :                 DEBUG(6,("final values: [%d], [%d]\n",
    8930             :                         *r->out.value_needed, *r->out.data_needed));
    8931             : 
    8932          48 :                 return WERR_OK;
    8933             :         }
    8934             : 
    8935         104 :         if (r->in.enum_index < count) {
    8936          84 :                 val = &info[r->in.enum_index];
    8937             :         }
    8938             : 
    8939         104 :         if (val == NULL) {
    8940             :                 /* out_value should default to "" or else NT4 has
    8941             :                    problems unmarshalling the response */
    8942             : 
    8943          20 :                 if (r->in.value_offered) {
    8944          20 :                         *r->out.value_needed = 1;
    8945          20 :                         r->out.value_name = talloc_strdup(r, "");
    8946          20 :                         if (!r->out.value_name) {
    8947           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    8948             :                         }
    8949             :                 } else {
    8950           0 :                         r->out.value_name = NULL;
    8951           0 :                         *r->out.value_needed = 0;
    8952             :                 }
    8953             : 
    8954             :                 /* the data is counted in bytes */
    8955             : 
    8956          20 :                 *r->out.data_needed = r->in.data_offered;
    8957             : 
    8958          20 :                 result = WERR_NO_MORE_ITEMS;
    8959             :         } else {
    8960             :                 /*
    8961             :                  * the value is:
    8962             :                  * - counted in bytes in the request
    8963             :                  * - counted in UNICODE chars in the max reply
    8964             :                  * - counted in bytes in the real size
    8965             :                  *
    8966             :                  * take a pause *before* coding not *during* coding
    8967             :                  */
    8968             : 
    8969             :                 /* name */
    8970          84 :                 if (r->in.value_offered) {
    8971          84 :                         r->out.value_name = talloc_strdup(r, val->value_name);
    8972          84 :                         if (!r->out.value_name) {
    8973           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    8974             :                         }
    8975          84 :                         *r->out.value_needed = val->value_name_len;
    8976             :                 } else {
    8977           0 :                         r->out.value_name = NULL;
    8978           0 :                         *r->out.value_needed = 0;
    8979             :                 }
    8980             : 
    8981             :                 /* type */
    8982             : 
    8983          84 :                 *r->out.type = val->type;
    8984             : 
    8985             :                 /* data - counted in bytes */
    8986             : 
    8987             :                 /*
    8988             :                  * See the section "Dynamically Typed Query Parameters"
    8989             :                  * in MS-RPRN.
    8990             :                  */
    8991             : 
    8992         147 :                 if (r->out.data && val->data && val->data->data &&
    8993         147 :                                 val->data_length && r->in.data_offered) {
    8994          84 :                         memcpy(r->out.data, val->data->data,
    8995          84 :                                 MIN(val->data_length,r->in.data_offered));
    8996             :                 }
    8997             : 
    8998          84 :                 *r->out.data_needed = val->data_length;
    8999             : 
    9000          84 :                 result = WERR_OK;
    9001             :         }
    9002             : 
    9003         104 :         return result;
    9004             : }
    9005             : 
    9006             : /****************************************************************
    9007             :  _spoolss_SetPrinterData
    9008             : ****************************************************************/
    9009             : 
    9010         168 : WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
    9011             :                                struct spoolss_SetPrinterData *r)
    9012             : {
    9013             :         struct spoolss_SetPrinterDataEx r2;
    9014             : 
    9015         168 :         r2.in.handle            = r->in.handle;
    9016         168 :         r2.in.key_name          = "PrinterDriverData";
    9017         168 :         r2.in.value_name        = r->in.value_name;
    9018         168 :         r2.in.type              = r->in.type;
    9019         168 :         r2.in.data              = r->in.data;
    9020         168 :         r2.in.offered           = r->in.offered;
    9021             : 
    9022         168 :         return _spoolss_SetPrinterDataEx(p, &r2);
    9023             : }
    9024             : 
    9025             : /****************************************************************
    9026             :  _spoolss_ResetPrinter
    9027             : ****************************************************************/
    9028             : 
    9029           0 : WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
    9030             :                              struct spoolss_ResetPrinter *r)
    9031             : {
    9032           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9033             :         int             snum;
    9034             : 
    9035           0 :         DEBUG(5,("_spoolss_ResetPrinter\n"));
    9036             : 
    9037             :         /*
    9038             :          * All we do is to check to see if the handle and queue is valid.
    9039             :          * This call really doesn't mean anything to us because we only
    9040             :          * support RAW printing.   --jerry
    9041             :          */
    9042             : 
    9043           0 :         if (!Printer) {
    9044           0 :                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
    9045             :                         OUR_HANDLE(r->in.handle)));
    9046           0 :                 return WERR_INVALID_HANDLE;
    9047             :         }
    9048             : 
    9049           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    9050           0 :                 return WERR_INVALID_HANDLE;
    9051             : 
    9052             : 
    9053             :         /* blindly return success */
    9054           0 :         return WERR_OK;
    9055             : }
    9056             : 
    9057             : /****************************************************************
    9058             :  _spoolss_DeletePrinterData
    9059             : ****************************************************************/
    9060             : 
    9061         168 : WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
    9062             :                                   struct spoolss_DeletePrinterData *r)
    9063             : {
    9064             :         struct spoolss_DeletePrinterDataEx r2;
    9065             : 
    9066         168 :         r2.in.handle            = r->in.handle;
    9067         168 :         r2.in.key_name          = "PrinterDriverData";
    9068         168 :         r2.in.value_name        = r->in.value_name;
    9069             : 
    9070         168 :         return _spoolss_DeletePrinterDataEx(p, &r2);
    9071             : }
    9072             : 
    9073             : /****************************************************************
    9074             :  _spoolss_AddForm
    9075             : ****************************************************************/
    9076             : 
    9077         576 : WERROR _spoolss_AddForm(struct pipes_struct *p,
    9078             :                         struct spoolss_AddForm *r)
    9079             : {
    9080             :         struct spoolss_AddFormInfo1 *form;
    9081         576 :         int snum = -1;
    9082         576 :         WERROR status = WERR_OK;
    9083         576 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9084             :         struct dcerpc_binding_handle *b;
    9085         576 :         TALLOC_CTX *tmp_ctx = NULL;
    9086             : 
    9087         576 :         DEBUG(5,("_spoolss_AddForm\n"));
    9088             : 
    9089         576 :         if (!Printer) {
    9090           0 :                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
    9091             :                         OUR_HANDLE(r->in.handle)));
    9092           0 :                 return WERR_INVALID_HANDLE;
    9093             :         }
    9094             : 
    9095             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    9096             :            and not a printer admin, then fail */
    9097             : 
    9098         576 :         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
    9099           0 :             !security_token_has_privilege(p->session_info->security_token,
    9100             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    9101           0 :                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
    9102           0 :                 return WERR_ACCESS_DENIED;
    9103             :         }
    9104             : 
    9105         576 :         if (r->in.info_ctr->level != 1) {
    9106           0 :                 return WERR_INVALID_LEVEL;
    9107             :         }
    9108             : 
    9109         576 :         form = r->in.info_ctr->info.info1;
    9110         576 :         if (!form) {
    9111           0 :                 return WERR_INVALID_PARAMETER;
    9112             :         }
    9113             : 
    9114         576 :         switch (form->flags) {
    9115         480 :         case SPOOLSS_FORM_USER:
    9116             :         case SPOOLSS_FORM_BUILTIN:
    9117             :         case SPOOLSS_FORM_PRINTER:
    9118         480 :                 break;
    9119          96 :         default:
    9120          96 :                 return WERR_INVALID_PARAMETER;
    9121             :         }
    9122             : 
    9123         480 :         tmp_ctx = talloc_new(p->mem_ctx);
    9124         480 :         if (!tmp_ctx) {
    9125           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9126             :         }
    9127             : 
    9128         480 :         status = winreg_printer_binding_handle(tmp_ctx,
    9129             :                                                get_session_info_system(),
    9130             :                                                p->msg_ctx,
    9131             :                                                &b);
    9132         480 :         if (!W_ERROR_IS_OK(status)) {
    9133           0 :                 goto done;
    9134             :         }
    9135             : 
    9136         480 :         status = winreg_printer_addform1(tmp_ctx, b, form);
    9137         480 :         if (!W_ERROR_IS_OK(status)) {
    9138         384 :                 goto done;
    9139             :         }
    9140             : 
    9141             :         /*
    9142             :          * ChangeID must always be set if this is a printer
    9143             :          */
    9144          96 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9145          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9146           0 :                         status = WERR_INVALID_HANDLE;
    9147           0 :                         goto done;
    9148             :                 }
    9149             : 
    9150          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9151             :                                                         lp_const_servicename(snum));
    9152             :         }
    9153             : 
    9154         376 : done:
    9155         480 :         talloc_free(tmp_ctx);
    9156         480 :         return status;
    9157             : }
    9158             : 
    9159             : /****************************************************************
    9160             :  _spoolss_DeleteForm
    9161             : ****************************************************************/
    9162             : 
    9163         384 : WERROR _spoolss_DeleteForm(struct pipes_struct *p,
    9164             :                            struct spoolss_DeleteForm *r)
    9165             : {
    9166         384 :         const char *form_name = r->in.form_name;
    9167         384 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9168         384 :         int snum = -1;
    9169         384 :         WERROR status = WERR_OK;
    9170             :         struct dcerpc_binding_handle *b;
    9171         384 :         TALLOC_CTX *tmp_ctx = NULL;
    9172             : 
    9173         384 :         DEBUG(5,("_spoolss_DeleteForm\n"));
    9174             : 
    9175         384 :         if (!Printer) {
    9176           0 :                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
    9177             :                         OUR_HANDLE(r->in.handle)));
    9178           0 :                 return WERR_INVALID_HANDLE;
    9179             :         }
    9180             : 
    9181         384 :         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
    9182           0 :             !security_token_has_privilege(p->session_info->security_token,
    9183             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    9184           0 :                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
    9185           0 :                 return WERR_ACCESS_DENIED;
    9186             :         }
    9187             : 
    9188         384 :         tmp_ctx = talloc_new(p->mem_ctx);
    9189         384 :         if (!tmp_ctx) {
    9190           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9191             :         }
    9192             : 
    9193         384 :         status = winreg_printer_binding_handle(tmp_ctx,
    9194             :                                                get_session_info_system(),
    9195             :                                                p->msg_ctx,
    9196             :                                                &b);
    9197         384 :         if (!W_ERROR_IS_OK(status)) {
    9198           0 :                 goto done;
    9199             :         }
    9200             : 
    9201         384 :         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
    9202         384 :         if (!W_ERROR_IS_OK(status)) {
    9203         288 :                 goto done;
    9204             :         }
    9205             : 
    9206             :         /*
    9207             :          * ChangeID must always be set if this is a printer
    9208             :          */
    9209          96 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9210          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9211           0 :                         status = WERR_INVALID_HANDLE;
    9212           0 :                         goto done;
    9213             :                 }
    9214             : 
    9215          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9216             :                                                         lp_const_servicename(snum));
    9217             :         }
    9218             : 
    9219         304 : done:
    9220         384 :         talloc_free(tmp_ctx);
    9221         384 :         return status;
    9222             : }
    9223             : 
    9224             : /****************************************************************
    9225             :  _spoolss_SetForm
    9226             : ****************************************************************/
    9227             : 
    9228          80 : WERROR _spoolss_SetForm(struct pipes_struct *p,
    9229             :                         struct spoolss_SetForm *r)
    9230             : {
    9231             :         struct spoolss_AddFormInfo1 *form;
    9232          80 :         const char *form_name = r->in.form_name;
    9233          80 :         int snum = -1;
    9234          80 :         WERROR status = WERR_OK;
    9235             :         struct dcerpc_binding_handle *b;
    9236          80 :         TALLOC_CTX *tmp_ctx = NULL;
    9237             : 
    9238          80 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9239             : 
    9240          80 :         DEBUG(5,("_spoolss_SetForm\n"));
    9241             : 
    9242          80 :         if (!Printer) {
    9243           0 :                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
    9244             :                         OUR_HANDLE(r->in.handle)));
    9245           0 :                 return WERR_INVALID_HANDLE;
    9246             :         }
    9247             : 
    9248             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    9249             :            and not a printer admin, then fail */
    9250             : 
    9251          80 :         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
    9252           0 :              !security_token_has_privilege(p->session_info->security_token,
    9253             :                                            SEC_PRIV_PRINT_OPERATOR)) {
    9254           0 :                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
    9255           0 :                 return WERR_ACCESS_DENIED;
    9256             :         }
    9257             : 
    9258          80 :         if (r->in.info_ctr->level != 1) {
    9259           0 :                 return WERR_INVALID_LEVEL;
    9260             :         }
    9261             : 
    9262          80 :         form = r->in.info_ctr->info.info1;
    9263          80 :         if (!form) {
    9264           0 :                 return WERR_INVALID_PARAMETER;
    9265             :         }
    9266             : 
    9267          80 :         tmp_ctx = talloc_new(p->mem_ctx);
    9268          80 :         if (!tmp_ctx) {
    9269           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9270             :         }
    9271             : 
    9272          80 :         status = winreg_printer_binding_handle(tmp_ctx,
    9273             :                                                get_session_info_system(),
    9274             :                                                p->msg_ctx,
    9275             :                                                &b);
    9276          80 :         if (!W_ERROR_IS_OK(status)) {
    9277           0 :                 goto done;
    9278             :         }
    9279             : 
    9280          80 :         status = winreg_printer_setform1(tmp_ctx, b,
    9281             :                                          form_name,
    9282             :                                          form);
    9283          80 :         if (!W_ERROR_IS_OK(status)) {
    9284           0 :                 goto done;
    9285             :         }
    9286             : 
    9287             :         /*
    9288             :          * ChangeID must always be set if this is a printer
    9289             :          */
    9290          80 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9291          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9292           0 :                         status = WERR_INVALID_HANDLE;
    9293           0 :                         goto done;
    9294             :                 }
    9295             : 
    9296          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9297             :                                                         lp_const_servicename(snum));
    9298             :         }
    9299             : 
    9300          60 : done:
    9301          80 :         talloc_free(tmp_ctx);
    9302          80 :         return status;
    9303             : }
    9304             : 
    9305             : /****************************************************************************
    9306             :  fill_print_processor1
    9307             : ****************************************************************************/
    9308             : 
    9309          24 : static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
    9310             :                                     struct spoolss_PrintProcessorInfo1 *r,
    9311             :                                     const char *print_processor_name)
    9312             : {
    9313          24 :         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
    9314          24 :         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
    9315             : 
    9316          24 :         return WERR_OK;
    9317             : }
    9318             : 
    9319             : /****************************************************************************
    9320             :  enumprintprocessors level 1.
    9321             : ****************************************************************************/
    9322             : 
    9323          24 : static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
    9324             :                                           union spoolss_PrintProcessorInfo **info_p,
    9325             :                                           uint32_t *count)
    9326             : {
    9327             :         union spoolss_PrintProcessorInfo *info;
    9328             :         WERROR result;
    9329             : 
    9330          24 :         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
    9331          24 :         W_ERROR_HAVE_NO_MEMORY(info);
    9332             : 
    9333          24 :         *count = 1;
    9334             : 
    9335          24 :         result = fill_print_processor1(info, &info[0].info1, "winprint");
    9336          24 :         if (!W_ERROR_IS_OK(result)) {
    9337           0 :                 goto out;
    9338             :         }
    9339             : 
    9340          42 :  out:
    9341          24 :         if (!W_ERROR_IS_OK(result)) {
    9342           0 :                 TALLOC_FREE(info);
    9343           0 :                 *count = 0;
    9344           0 :                 return result;
    9345             :         }
    9346             : 
    9347          24 :         *info_p = info;
    9348             : 
    9349          24 :         return WERR_OK;
    9350             : }
    9351             : 
    9352             : /****************************************************************
    9353             :  _spoolss_EnumPrintProcessors
    9354             : ****************************************************************/
    9355             : 
    9356          48 : WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
    9357             :                                     struct spoolss_EnumPrintProcessors *r)
    9358             : {
    9359             :         WERROR result;
    9360             : 
    9361             :         /* that's an [in out] buffer */
    9362             : 
    9363          48 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9364           0 :                 return WERR_INVALID_PARAMETER;
    9365             :         }
    9366             : 
    9367          48 :         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
    9368             : 
    9369             :         /*
    9370             :          * Enumerate the print processors ...
    9371             :          *
    9372             :          * Just reply with "winprint", to keep NT happy
    9373             :          * and I can use my nice printer checker.
    9374             :          */
    9375             : 
    9376          48 :         *r->out.count = 0;
    9377          48 :         *r->out.needed = 0;
    9378          48 :         *r->out.info = NULL;
    9379             : 
    9380          48 :         if (!get_short_archi(r->in.environment)) {
    9381           4 :                 return WERR_INVALID_ENVIRONMENT;
    9382             :         }
    9383             : 
    9384          44 :         switch (r->in.level) {
    9385          24 :         case 1:
    9386          24 :                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
    9387             :                                                      r->out.count);
    9388          24 :                 break;
    9389          20 :         default:
    9390          20 :                 return WERR_INVALID_LEVEL;
    9391             :         }
    9392             : 
    9393          24 :         if (!W_ERROR_IS_OK(result)) {
    9394           0 :                 return result;
    9395             :         }
    9396             : 
    9397          24 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9398             :                                                      spoolss_EnumPrintProcessors,
    9399             :                                                      *r->out.info, r->in.level,
    9400             :                                                      *r->out.count);
    9401          24 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9402          24 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9403             : 
    9404          24 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9405             : }
    9406             : 
    9407             : /****************************************************************************
    9408             :  fill_printprocdatatype1
    9409             : ****************************************************************************/
    9410             : 
    9411          16 : static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
    9412             :                                       struct spoolss_PrintProcDataTypesInfo1 *r,
    9413             :                                       const char *name_array)
    9414             : {
    9415          16 :         r->name_array = talloc_strdup(mem_ctx, name_array);
    9416          16 :         W_ERROR_HAVE_NO_MEMORY(r->name_array);
    9417             : 
    9418          16 :         return WERR_OK;
    9419             : }
    9420             : 
    9421             : /****************************************************************************
    9422             :  enumprintprocdatatypes level 1.
    9423             : ****************************************************************************/
    9424             : 
    9425          16 : static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
    9426             :                                              union spoolss_PrintProcDataTypesInfo **info_p,
    9427             :                                              uint32_t *count)
    9428             : {
    9429             :         WERROR result;
    9430             :         union spoolss_PrintProcDataTypesInfo *info;
    9431             : 
    9432          16 :         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
    9433          16 :         W_ERROR_HAVE_NO_MEMORY(info);
    9434             : 
    9435          16 :         *count = 1;
    9436             : 
    9437          16 :         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
    9438          16 :         if (!W_ERROR_IS_OK(result)) {
    9439           0 :                 goto out;
    9440             :         }
    9441             : 
    9442          28 :  out:
    9443          16 :         if (!W_ERROR_IS_OK(result)) {
    9444           0 :                 TALLOC_FREE(info);
    9445           0 :                 *count = 0;
    9446           0 :                 return result;
    9447             :         }
    9448             : 
    9449          16 :         *info_p = info;
    9450             : 
    9451          16 :         return WERR_OK;
    9452             : }
    9453             : 
    9454             : /****************************************************************
    9455             :  _spoolss_EnumPrintProcessorDataTypes
    9456             : ****************************************************************/
    9457             : 
    9458          44 : WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
    9459             :                                             struct spoolss_EnumPrintProcessorDataTypes *r)
    9460             : {
    9461             :         WERROR result;
    9462             : 
    9463             :         /* that's an [in out] buffer */
    9464             : 
    9465          44 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9466           0 :                 return WERR_INVALID_PARAMETER;
    9467             :         }
    9468             : 
    9469          44 :         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
    9470             : 
    9471          44 :         *r->out.count = 0;
    9472          44 :         *r->out.needed = 0;
    9473          44 :         *r->out.info = NULL;
    9474             : 
    9475          74 :         if (r->in.print_processor_name == NULL ||
    9476          40 :             !strequal(r->in.print_processor_name, "winprint")) {
    9477           8 :                 return WERR_UNKNOWN_PRINTPROCESSOR;
    9478             :         }
    9479             : 
    9480          36 :         switch (r->in.level) {
    9481          16 :         case 1:
    9482          16 :                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
    9483             :                                                         r->out.count);
    9484          16 :                 break;
    9485          20 :         default:
    9486          20 :                 return WERR_INVALID_LEVEL;
    9487             :         }
    9488             : 
    9489          16 :         if (!W_ERROR_IS_OK(result)) {
    9490           0 :                 return result;
    9491             :         }
    9492             : 
    9493          16 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9494             :                                                      spoolss_EnumPrintProcessorDataTypes,
    9495             :                                                      *r->out.info, r->in.level,
    9496             :                                                      *r->out.count);
    9497          16 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9498          16 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9499             : 
    9500          16 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9501             : }
    9502             : 
    9503             : /****************************************************************************
    9504             :  fill_monitor_1
    9505             : ****************************************************************************/
    9506             : 
    9507          16 : static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
    9508             :                              struct spoolss_MonitorInfo1 *r,
    9509             :                              const char *monitor_name)
    9510             : {
    9511          16 :         r->monitor_name                      = talloc_strdup(mem_ctx, monitor_name);
    9512          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    9513             : 
    9514          16 :         return WERR_OK;
    9515             : }
    9516             : 
    9517             : /****************************************************************************
    9518             :  fill_monitor_2
    9519             : ****************************************************************************/
    9520             : 
    9521          16 : static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
    9522             :                              struct spoolss_MonitorInfo2 *r,
    9523             :                              const char *monitor_name,
    9524             :                              const char *environment,
    9525             :                              const char *dll_name)
    9526             : {
    9527          16 :         r->monitor_name                      = talloc_strdup(mem_ctx, monitor_name);
    9528          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    9529          16 :         r->environment                       = talloc_strdup(mem_ctx, environment);
    9530          16 :         W_ERROR_HAVE_NO_MEMORY(r->environment);
    9531          16 :         r->dll_name                  = talloc_strdup(mem_ctx, dll_name);
    9532          16 :         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
    9533             : 
    9534          16 :         return WERR_OK;
    9535             : }
    9536             : 
    9537             : /****************************************************************************
    9538             :  enumprintmonitors level 1.
    9539             : ****************************************************************************/
    9540             : 
    9541           8 : static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
    9542             :                                         union spoolss_MonitorInfo **info_p,
    9543             :                                         uint32_t *count)
    9544             : {
    9545             :         union spoolss_MonitorInfo *info;
    9546           8 :         WERROR result = WERR_OK;
    9547             : 
    9548           8 :         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
    9549           8 :         W_ERROR_HAVE_NO_MEMORY(info);
    9550             : 
    9551           8 :         *count = 2;
    9552             : 
    9553           8 :         result = fill_monitor_1(info, &info[0].info1,
    9554             :                                 SPL_LOCAL_PORT);
    9555           8 :         if (!W_ERROR_IS_OK(result)) {
    9556           0 :                 goto out;
    9557             :         }
    9558             : 
    9559           8 :         result = fill_monitor_1(info, &info[1].info1,
    9560             :                                 SPL_TCPIP_PORT);
    9561           8 :         if (!W_ERROR_IS_OK(result)) {
    9562           0 :                 goto out;
    9563             :         }
    9564             : 
    9565          14 : out:
    9566           8 :         if (!W_ERROR_IS_OK(result)) {
    9567           0 :                 TALLOC_FREE(info);
    9568           0 :                 *count = 0;
    9569           0 :                 return result;
    9570             :         }
    9571             : 
    9572           8 :         *info_p = info;
    9573             : 
    9574           8 :         return WERR_OK;
    9575             : }
    9576             : 
    9577             : /****************************************************************************
    9578             :  enumprintmonitors level 2.
    9579             : ****************************************************************************/
    9580             : 
    9581           8 : static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
    9582             :                                         union spoolss_MonitorInfo **info_p,
    9583             :                                         uint32_t *count)
    9584             : {
    9585             :         union spoolss_MonitorInfo *info;
    9586           8 :         WERROR result = WERR_OK;
    9587             :         const char *architecture;
    9588             : 
    9589           8 :         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
    9590           8 :         W_ERROR_HAVE_NO_MEMORY(info);
    9591             : 
    9592           8 :         *count = 2;
    9593             : 
    9594           8 :         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    9595             :                                             "spoolss",
    9596             :                                             "architecture",
    9597             :                                             GLOBAL_SPOOLSS_ARCHITECTURE);
    9598             : 
    9599           8 :         result = fill_monitor_2(info, &info[0].info2,
    9600             :                                 SPL_LOCAL_PORT,
    9601             :                                 architecture,
    9602             :                                 "localmon.dll");
    9603           8 :         if (!W_ERROR_IS_OK(result)) {
    9604           0 :                 goto out;
    9605             :         }
    9606             : 
    9607           8 :         result = fill_monitor_2(info, &info[1].info2,
    9608             :                                 SPL_TCPIP_PORT,
    9609             :                                 architecture,
    9610             :                                 "tcpmon.dll");
    9611           8 :         if (!W_ERROR_IS_OK(result)) {
    9612           0 :                 goto out;
    9613             :         }
    9614             : 
    9615          14 : out:
    9616           8 :         if (!W_ERROR_IS_OK(result)) {
    9617           0 :                 TALLOC_FREE(info);
    9618           0 :                 *count = 0;
    9619           0 :                 return result;
    9620             :         }
    9621             : 
    9622           8 :         *info_p = info;
    9623             : 
    9624           8 :         return WERR_OK;
    9625             : }
    9626             : 
    9627             : /****************************************************************
    9628             :  _spoolss_EnumMonitors
    9629             : ****************************************************************/
    9630             : 
    9631          16 : WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
    9632             :                              struct spoolss_EnumMonitors *r)
    9633             : {
    9634             :         WERROR result;
    9635             : 
    9636             :         /* that's an [in out] buffer */
    9637             : 
    9638          16 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9639           0 :                 return WERR_INVALID_PARAMETER;
    9640             :         }
    9641             : 
    9642          16 :         DEBUG(5,("_spoolss_EnumMonitors\n"));
    9643             : 
    9644             :         /*
    9645             :          * Enumerate the print monitors ...
    9646             :          *
    9647             :          * Just reply with "Local Port", to keep NT happy
    9648             :          * and I can use my nice printer checker.
    9649             :          */
    9650             : 
    9651          16 :         *r->out.count = 0;
    9652          16 :         *r->out.needed = 0;
    9653          16 :         *r->out.info = NULL;
    9654             : 
    9655          16 :         switch (r->in.level) {
    9656           8 :         case 1:
    9657           8 :                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
    9658             :                                                    r->out.count);
    9659           8 :                 break;
    9660           8 :         case 2:
    9661           8 :                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
    9662             :                                                    r->out.count);
    9663           8 :                 break;
    9664           0 :         default:
    9665           0 :                 return WERR_INVALID_LEVEL;
    9666             :         }
    9667             : 
    9668          16 :         if (!W_ERROR_IS_OK(result)) {
    9669           0 :                 return result;
    9670             :         }
    9671             : 
    9672          16 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9673             :                                                      spoolss_EnumMonitors,
    9674             :                                                      *r->out.info, r->in.level,
    9675             :                                                      *r->out.count);
    9676          16 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9677          16 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9678             : 
    9679          16 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9680             : }
    9681             : 
    9682             : /****************************************************************************
    9683             : ****************************************************************************/
    9684             : 
    9685         128 : static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
    9686             :                              const print_queue_struct *queue,
    9687             :                              int count, int snum,
    9688             :                              struct spoolss_PrinterInfo2 *pinfo2,
    9689             :                              uint32_t jobid,
    9690             :                              int sysjob,
    9691             :                              struct spoolss_JobInfo1 *r)
    9692             : {
    9693         128 :         int i = 0;
    9694         128 :         bool found = false;
    9695             : 
    9696         576 :         for (i=0; i<count; i++) {
    9697         576 :                 if (queue[i].sysjob == sysjob) {
    9698         128 :                         found = true;
    9699         128 :                         break;
    9700             :                 }
    9701             :         }
    9702             : 
    9703         128 :         if (found == false) {
    9704             :                 /* NT treats not found as bad param... yet another bad choice */
    9705           0 :                 return WERR_INVALID_PARAMETER;
    9706             :         }
    9707             : 
    9708         128 :         return fill_job_info1(mem_ctx,
    9709             :                               r,
    9710         128 :                               &queue[i],
    9711             :                               jobid,
    9712             :                               i,
    9713             :                               snum,
    9714             :                               pinfo2);
    9715             : }
    9716             : 
    9717             : /****************************************************************************
    9718             : ****************************************************************************/
    9719             : 
    9720           0 : static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
    9721             :                              const print_queue_struct *queue,
    9722             :                              int count, int snum,
    9723             :                              struct spoolss_PrinterInfo2 *pinfo2,
    9724             :                              uint32_t jobid,
    9725             :                              int sysjob,
    9726             :                              struct spoolss_JobInfo2 *r)
    9727             : {
    9728           0 :         int i = 0;
    9729           0 :         bool found = false;
    9730             :         struct spoolss_DeviceMode *devmode;
    9731             :         WERROR result;
    9732             : 
    9733           0 :         for (i=0; i<count; i++) {
    9734           0 :                 if (queue[i].sysjob == sysjob) {
    9735           0 :                         found = true;
    9736           0 :                         break;
    9737             :                 }
    9738             :         }
    9739             : 
    9740           0 :         if (found == false) {
    9741             :                 /* NT treats not found as bad param... yet another bad
    9742             :                    choice */
    9743           0 :                 return WERR_INVALID_PARAMETER;
    9744             :         }
    9745             : 
    9746             :         /*
    9747             :          * if the print job does not have a DEVMODE associated with it,
    9748             :          * just use the one for the printer. A NULL devicemode is not
    9749             :          *  a failure condition
    9750             :          */
    9751             : 
    9752           0 :         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
    9753           0 :         if (!devmode) {
    9754           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    9755             :                                                 pinfo2->printername,
    9756             :                                                 &devmode);
    9757           0 :                 if (!W_ERROR_IS_OK(result)) {
    9758           0 :                         DEBUG(3, ("Can't proceed w/o a devmode!"));
    9759           0 :                         return result;
    9760             :                 }
    9761             :         }
    9762             : 
    9763           0 :         return fill_job_info2(mem_ctx,
    9764             :                               r,
    9765           0 :                               &queue[i],
    9766             :                               jobid,
    9767             :                               i,
    9768             :                               snum,
    9769             :                               pinfo2,
    9770             :                               devmode);
    9771             : }
    9772             : 
    9773             : /****************************************************************
    9774             :  _spoolss_GetJob
    9775             : ****************************************************************/
    9776             : 
    9777        2048 : WERROR _spoolss_GetJob(struct pipes_struct *p,
    9778             :                        struct spoolss_GetJob *r)
    9779             : {
    9780        2048 :         WERROR result = WERR_OK;
    9781        2048 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    9782             :         const char *svc_name;
    9783             :         int sysjob;
    9784             :         int snum;
    9785             :         int count;
    9786             :         struct tdb_print_db *pdb;
    9787        2048 :         print_queue_struct      *queue = NULL;
    9788             :         print_status_struct prt_status;
    9789             : 
    9790             :         /* that's an [in out] buffer */
    9791             : 
    9792        2048 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9793           0 :                 result = WERR_INVALID_PARAMETER;
    9794           0 :                 goto err_jinfo_free;
    9795             :         }
    9796             : 
    9797        2048 :         DEBUG(5,("_spoolss_GetJob\n"));
    9798             : 
    9799        2048 :         *r->out.needed = 0;
    9800             : 
    9801        2048 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9802           0 :                 result = WERR_INVALID_HANDLE;
    9803           0 :                 goto err_jinfo_free;
    9804             :         }
    9805             : 
    9806        2048 :         svc_name = lp_const_servicename(snum);
    9807        2048 :         if (svc_name == NULL) {
    9808           0 :                 result = WERR_INVALID_PARAMETER;
    9809           0 :                 goto err_jinfo_free;
    9810             :         }
    9811             : 
    9812        2048 :         result = winreg_get_printer_internal(p->mem_ctx,
    9813             :                                     get_session_info_system(),
    9814             :                                     p->msg_ctx,
    9815             :                                     svc_name,
    9816             :                                     &pinfo2);
    9817        2048 :         if (!W_ERROR_IS_OK(result)) {
    9818           0 :                 goto err_jinfo_free;
    9819             :         }
    9820             : 
    9821        2048 :         pdb = get_print_db_byname(svc_name);
    9822        2048 :         if (pdb == NULL) {
    9823           0 :                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
    9824           0 :                 result = WERR_INVALID_PARAMETER;
    9825           0 :                 goto err_pinfo_free;
    9826             :         }
    9827             : 
    9828        2048 :         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
    9829        2048 :         release_print_db(pdb);
    9830        2048 :         if (sysjob == -1) {
    9831        1920 :                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
    9832        1920 :                 result = WERR_INVALID_PARAMETER;
    9833        1920 :                 goto err_pinfo_free;
    9834             :         }
    9835             : 
    9836         128 :         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
    9837             : 
    9838         128 :         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
    9839             :                      count, prt_status.status, prt_status.message));
    9840             : 
    9841         128 :         switch (r->in.level) {
    9842         128 :         case 1:
    9843         128 :                 result = getjob_level_1(p->mem_ctx,
    9844             :                                         queue, count, snum, pinfo2,
    9845             :                                         r->in.job_id, sysjob,
    9846         128 :                                         &r->out.info->info1);
    9847         128 :                 break;
    9848           0 :         case 2:
    9849           0 :                 result = getjob_level_2(p->mem_ctx,
    9850             :                                         queue, count, snum, pinfo2,
    9851             :                                         r->in.job_id, sysjob,
    9852           0 :                                         &r->out.info->info2);
    9853           0 :                 break;
    9854           0 :         default:
    9855           0 :                 result = WERR_INVALID_LEVEL;
    9856           0 :                 break;
    9857             :         }
    9858             : 
    9859         128 :         SAFE_FREE(queue);
    9860         128 :         TALLOC_FREE(pinfo2);
    9861             : 
    9862         128 :         if (!W_ERROR_IS_OK(result)) {
    9863           0 :                 goto err_jinfo_free;
    9864             :         }
    9865             : 
    9866         128 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
    9867             :                                                                                    r->in.level);
    9868         128 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    9869             : 
    9870         128 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9871             : 
    9872        1920 : err_pinfo_free:
    9873        3360 :         TALLOC_FREE(pinfo2);
    9874        1440 : err_jinfo_free:
    9875        1920 :         TALLOC_FREE(r->out.info);
    9876        1920 :         return result;
    9877             : }
    9878             : 
    9879             : /****************************************************************
    9880             :  _spoolss_GetPrinterDataEx
    9881             : ****************************************************************/
    9882             : 
    9883        3124 : WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
    9884             :                                  struct spoolss_GetPrinterDataEx *r)
    9885             : {
    9886             : 
    9887        3124 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9888             :         const char *printer;
    9889        3124 :         int                     snum = 0;
    9890        3124 :         WERROR result = WERR_OK;
    9891             :         DATA_BLOB blob;
    9892        3124 :         enum winreg_Type val_type = REG_NONE;
    9893        3124 :         uint8_t *val_data = NULL;
    9894        3124 :         uint32_t val_size = 0;
    9895             :         struct dcerpc_binding_handle *b;
    9896             :         TALLOC_CTX *tmp_ctx;
    9897             : 
    9898        3124 :         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
    9899             : 
    9900        3124 :         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
    9901             :                 r->in.key_name, r->in.value_name));
    9902             : 
    9903             :         /* in case of problem, return some default values */
    9904             : 
    9905        3124 :         *r->out.needed       = 0;
    9906        3124 :         *r->out.type = REG_NONE;
    9907             : 
    9908        3124 :         tmp_ctx = talloc_new(p->mem_ctx);
    9909        3124 :         if (!tmp_ctx) {
    9910           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9911             :         }
    9912             : 
    9913        3124 :         if (!Printer) {
    9914           0 :                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
    9915             :                         OUR_HANDLE(r->in.handle)));
    9916           0 :                 result = WERR_INVALID_HANDLE;
    9917           0 :                 goto done;
    9918             :         }
    9919             : 
    9920             :         /* Is the handle to a printer or to the server? */
    9921             : 
    9922        3124 :         if (Printer->printer_type == SPLHND_SERVER) {
    9923             : 
    9924             :                 union spoolss_PrinterData data;
    9925             : 
    9926         348 :                 result = getprinterdata_printer_server(tmp_ctx,
    9927             :                                                        r->in.value_name,
    9928             :                                                        r->out.type,
    9929             :                                                        &data);
    9930         348 :                 if (!W_ERROR_IS_OK(result)) {
    9931           4 :                         goto done;
    9932             :                 }
    9933             : 
    9934         344 :                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
    9935         344 :                                                   *r->out.type, &data);
    9936         344 :                 if (!W_ERROR_IS_OK(result)) {
    9937           0 :                         goto done;
    9938             :                 }
    9939             : 
    9940         344 :                 *r->out.needed = blob.length;
    9941             : 
    9942         344 :                 if (r->in.offered >= *r->out.needed) {
    9943         176 :                         memcpy(r->out.data, blob.data, blob.length);
    9944             :                 }
    9945             : 
    9946         344 :                 result = WERR_OK;
    9947         344 :                 goto done;
    9948             :         }
    9949             : 
    9950             :         /* check to see if the keyname is valid */
    9951        2776 :         if (!strlen(r->in.key_name)) {
    9952           0 :                 result = WERR_INVALID_PARAMETER;
    9953           0 :                 goto done;
    9954             :         }
    9955             : 
    9956        2776 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9957           0 :                 result = WERR_INVALID_HANDLE;
    9958           0 :                 goto done;
    9959             :         }
    9960        2776 :         printer = lp_const_servicename(snum);
    9961             : 
    9962        2776 :         result = winreg_printer_binding_handle(tmp_ctx,
    9963             :                                                get_session_info_system(),
    9964             :                                                p->msg_ctx,
    9965             :                                                &b);
    9966        2776 :         if (!W_ERROR_IS_OK(result)) {
    9967           0 :                 goto done;
    9968             :         }
    9969             : 
    9970             :         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
    9971        3076 :         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
    9972         300 :             strequal(r->in.value_name, "ChangeId")) {
    9973         128 :                 *r->out.type = REG_DWORD;
    9974         128 :                 *r->out.needed = 4;
    9975         128 :                 if (r->in.offered >= *r->out.needed) {
    9976          64 :                         uint32_t changeid = 0;
    9977             : 
    9978          64 :                         result = winreg_printer_get_changeid(tmp_ctx, b,
    9979             :                                                              printer,
    9980             :                                                              &changeid);
    9981          64 :                         if (!W_ERROR_IS_OK(result)) {
    9982           0 :                                 goto done;
    9983             :                         }
    9984             : 
    9985          64 :                         SIVAL(r->out.data, 0, changeid);
    9986          64 :                         result = WERR_OK;
    9987             :                 }
    9988         128 :                 goto done;
    9989             :         }
    9990             : 
    9991        2648 :         result = winreg_get_printer_dataex(tmp_ctx, b,
    9992             :                                            printer,
    9993             :                                            r->in.key_name,
    9994             :                                            r->in.value_name,
    9995             :                                            &val_type,
    9996             :                                            &val_data,
    9997             :                                            &val_size);
    9998        2648 :         if (!W_ERROR_IS_OK(result)) {
    9999           4 :                 goto done;
   10000             :         }
   10001             : 
   10002        2644 :         *r->out.needed = val_size;
   10003        2644 :         *r->out.type = val_type;
   10004             : 
   10005        2644 :         if (r->in.offered >= *r->out.needed) {
   10006        1340 :                 memcpy(r->out.data, val_data, val_size);
   10007             :         }
   10008             : 
   10009        3633 : done:
   10010             :         /* NOTE: do not replace type when returning WERR_MORE_DATA */
   10011             : 
   10012        3124 :         if (W_ERROR_IS_OK(result)) {
   10013        3116 :                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
   10014             :         }
   10015             : 
   10016        3124 :         talloc_free(tmp_ctx);
   10017        3124 :         return result;
   10018             : }
   10019             : 
   10020             : /****************************************************************
   10021             :  _spoolss_SetPrinterDataEx
   10022             : ****************************************************************/
   10023             : 
   10024        1368 : WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
   10025             :                                  struct spoolss_SetPrinterDataEx *r)
   10026             : {
   10027        1026 :         const struct loadparm_substitution *lp_sub =
   10028         342 :                 loadparm_s3_global_substitution();
   10029        1368 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
   10030        1368 :         int                     snum = 0;
   10031        1368 :         WERROR                  result = WERR_OK;
   10032        1368 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10033             :         char                    *oid_string;
   10034             :         struct dcerpc_binding_handle *b;
   10035             :         TALLOC_CTX *tmp_ctx;
   10036             : 
   10037        1368 :         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
   10038             : 
   10039             :         /* From MSDN documentation of SetPrinterDataEx: pass request to
   10040             :            SetPrinterData if key is "PrinterDriverData" */
   10041             : 
   10042        1368 :         if (!Printer) {
   10043           0 :                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
   10044             :                         OUR_HANDLE(r->in.handle)));
   10045           0 :                 return WERR_INVALID_HANDLE;
   10046             :         }
   10047             : 
   10048        1368 :         if (Printer->printer_type == SPLHND_SERVER) {
   10049           0 :                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
   10050             :                         "Not implemented for server handles yet\n"));
   10051           0 :                 return WERR_INVALID_PARAMETER;
   10052             :         }
   10053             : 
   10054        1368 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10055           0 :                 return WERR_INVALID_HANDLE;
   10056             :         }
   10057             : 
   10058             :         /*
   10059             :          * Access check : NT returns "access denied" if you make a
   10060             :          * SetPrinterData call without the necessary privildge.
   10061             :          * we were originally returning OK if nothing changed
   10062             :          * which made Win2k issue **a lot** of SetPrinterData
   10063             :          * when connecting to a printer  --jerry
   10064             :          */
   10065             : 
   10066        1368 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10067           0 :                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
   10068             :                         "change denied by handle access permissions\n"));
   10069           0 :                 return WERR_ACCESS_DENIED;
   10070             :         }
   10071             : 
   10072        1368 :         tmp_ctx = talloc_new(p->mem_ctx);
   10073        1368 :         if (!tmp_ctx) {
   10074           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10075             :         }
   10076             : 
   10077        1368 :         result = winreg_printer_binding_handle(tmp_ctx,
   10078             :                                                get_session_info_system(),
   10079             :                                                p->msg_ctx,
   10080             :                                                &b);
   10081        1368 :         if (!W_ERROR_IS_OK(result)) {
   10082           0 :                 goto done;
   10083             :         }
   10084             : 
   10085        2394 :         result = winreg_get_printer(tmp_ctx, b,
   10086        1368 :                                     lp_servicename(talloc_tos(), lp_sub, snum),
   10087             :                                     &pinfo2);
   10088        1368 :         if (!W_ERROR_IS_OK(result)) {
   10089           0 :                 goto done;
   10090             :         }
   10091             : 
   10092             :         /* check for OID in valuename */
   10093             : 
   10094        1368 :         oid_string = strchr(r->in.value_name, ',');
   10095        1368 :         if (oid_string) {
   10096           0 :                 *oid_string = '\0';
   10097           0 :                 oid_string++;
   10098             :         }
   10099             : 
   10100             :         /* save the registry data */
   10101             : 
   10102        2394 :         result = winreg_set_printer_dataex(tmp_ctx, b,
   10103        1368 :                                            pinfo2->sharename,
   10104             :                                            r->in.key_name,
   10105             :                                            r->in.value_name,
   10106             :                                            r->in.type,
   10107             :                                            r->in.data,
   10108             :                                            r->in.offered);
   10109             : 
   10110        1368 :         if (W_ERROR_IS_OK(result)) {
   10111             :                 /* save the OID if one was specified */
   10112        1368 :                 if (oid_string) {
   10113           0 :                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
   10114             :                                 r->in.key_name, SPOOL_OID_KEY);
   10115           0 :                         if (!str) {
   10116           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
   10117           0 :                                 goto done;
   10118             :                         }
   10119             : 
   10120             :                         /*
   10121             :                          * I'm not checking the status here on purpose.  Don't know
   10122             :                          * if this is right, but I'm returning the status from the
   10123             :                          * previous set_printer_dataex() call.  I have no idea if
   10124             :                          * this is right.    --jerry
   10125             :                          */
   10126           0 :                         winreg_set_printer_dataex(tmp_ctx, b,
   10127           0 :                                                   pinfo2->sharename,
   10128             :                                                   str,
   10129             :                                                   r->in.value_name,
   10130             :                                                   REG_SZ,
   10131             :                                                   (uint8_t *) oid_string,
   10132           0 :                                                   strlen(oid_string) + 1);
   10133             :                 }
   10134             : 
   10135        1368 :                 result = winreg_printer_update_changeid(tmp_ctx, b,
   10136             :                                                         lp_const_servicename(snum));
   10137             : 
   10138             :         }
   10139             : 
   10140        1026 : done:
   10141        1368 :         talloc_free(tmp_ctx);
   10142        1368 :         return result;
   10143             : }
   10144             : 
   10145             : /****************************************************************
   10146             :  _spoolss_DeletePrinterDataEx
   10147             : ****************************************************************/
   10148             : 
   10149        1368 : WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
   10150             :                                     struct spoolss_DeletePrinterDataEx *r)
   10151             : {
   10152             :         const char *printer;
   10153        1368 :         int             snum=0;
   10154        1368 :         WERROR          status = WERR_OK;
   10155        1368 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10156             : 
   10157        1368 :         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
   10158             : 
   10159        1368 :         if (!Printer) {
   10160           0 :                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
   10161             :                         "Invalid handle (%s:%u:%u).\n",
   10162             :                         OUR_HANDLE(r->in.handle)));
   10163           0 :                 return WERR_INVALID_HANDLE;
   10164             :         }
   10165             : 
   10166        1368 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10167           0 :                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
   10168             :                         "printer properties change denied by handle\n"));
   10169           0 :                 return WERR_ACCESS_DENIED;
   10170             :         }
   10171             : 
   10172        1368 :         if (!r->in.value_name || !r->in.key_name) {
   10173           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10174             :         }
   10175             : 
   10176        1368 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10177           0 :                 return WERR_INVALID_HANDLE;
   10178             :         }
   10179        1368 :         printer = lp_const_servicename(snum);
   10180             : 
   10181        1368 :         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
   10182             :                                               get_session_info_system(),
   10183             :                                               p->msg_ctx,
   10184             :                                               printer,
   10185             :                                               r->in.key_name,
   10186             :                                               r->in.value_name);
   10187        1368 :         if (W_ERROR_IS_OK(status)) {
   10188        1368 :                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
   10189             :                                                         get_session_info_system(),
   10190             :                                                         p->msg_ctx,
   10191             :                                                         printer);
   10192             :         }
   10193             : 
   10194        1368 :         return status;
   10195             : }
   10196             : 
   10197             : /****************************************************************
   10198             :  _spoolss_EnumPrinterKey
   10199             : ****************************************************************/
   10200             : 
   10201        3384 : WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
   10202             :                                struct spoolss_EnumPrinterKey *r)
   10203             : {
   10204             :         uint32_t        num_keys;
   10205        3384 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10206        3384 :         int             snum = 0;
   10207        3384 :         WERROR          result = WERR_FILE_NOT_FOUND;
   10208        3384 :         const char **array = NULL;
   10209             :         DATA_BLOB blob;
   10210             : 
   10211        3384 :         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
   10212             : 
   10213        3384 :         if (!Printer) {
   10214           0 :                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
   10215             :                         OUR_HANDLE(r->in.handle)));
   10216           0 :                 return WERR_INVALID_HANDLE;
   10217             :         }
   10218             : 
   10219        3384 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10220           0 :                 return WERR_INVALID_HANDLE;
   10221             :         }
   10222             : 
   10223        3384 :         result = winreg_enum_printer_key_internal(p->mem_ctx,
   10224             :                                          get_session_info_system(),
   10225             :                                          p->msg_ctx,
   10226             :                                          lp_const_servicename(snum),
   10227             :                                          r->in.key_name,
   10228             :                                          &num_keys,
   10229             :                                          &array);
   10230        3384 :         if (!W_ERROR_IS_OK(result)) {
   10231           0 :                 goto done;
   10232             :         }
   10233             : 
   10234        3384 :         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
   10235           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
   10236           0 :                 goto done;
   10237             :         }
   10238             : 
   10239        3384 :         *r->out._ndr_size = r->in.offered / 2;
   10240        3384 :         *r->out.needed = blob.length;
   10241             : 
   10242        3384 :         if (r->in.offered < *r->out.needed) {
   10243        1304 :                 result = WERR_MORE_DATA;
   10244             :         } else {
   10245        2080 :                 result = WERR_OK;
   10246        2080 :                 r->out.key_buffer->string_array = array;
   10247             :         }
   10248             : 
   10249        3384 :  done:
   10250        3384 :         if (!W_ERROR_IS_OK(result)) {
   10251        1304 :                 TALLOC_FREE(array);
   10252        1304 :                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
   10253           0 :                         *r->out.needed = 0;
   10254             :                 }
   10255             :         }
   10256             : 
   10257        3384 :         return result;
   10258             : }
   10259             : 
   10260             : /****************************************************************
   10261             :  _spoolss_DeletePrinterKey
   10262             : ****************************************************************/
   10263             : 
   10264         216 : WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
   10265             :                                  struct spoolss_DeletePrinterKey *r)
   10266             : {
   10267         216 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10268         216 :         int                     snum=0;
   10269             :         WERROR                  status;
   10270             :         const char *printer;
   10271             :         struct dcerpc_binding_handle *b;
   10272             :         TALLOC_CTX *tmp_ctx;
   10273             : 
   10274         216 :         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
   10275             : 
   10276         216 :         if (!Printer) {
   10277           0 :                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
   10278             :                         OUR_HANDLE(r->in.handle)));
   10279           0 :                 return WERR_INVALID_HANDLE;
   10280             :         }
   10281             : 
   10282             :         /* if keyname == NULL, return error */
   10283         216 :         if ( !r->in.key_name )
   10284           0 :                 return WERR_INVALID_PARAMETER;
   10285             : 
   10286         216 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10287           0 :                 return WERR_INVALID_HANDLE;
   10288             :         }
   10289             : 
   10290         216 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10291           0 :                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
   10292             :                         "printer properties change denied by handle\n"));
   10293           0 :                 return WERR_ACCESS_DENIED;
   10294             :         }
   10295             : 
   10296         216 :         printer = lp_const_servicename(snum);
   10297             : 
   10298         216 :         tmp_ctx = talloc_new(p->mem_ctx);
   10299         216 :         if (!tmp_ctx) {
   10300           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10301             :         }
   10302             : 
   10303         216 :         status = winreg_printer_binding_handle(tmp_ctx,
   10304             :                                                get_session_info_system(),
   10305             :                                                p->msg_ctx,
   10306             :                                                &b);
   10307         216 :         if (!W_ERROR_IS_OK(status)) {
   10308           0 :                 goto done;
   10309             :         }
   10310             : 
   10311             :         /* delete the key and all subkeys */
   10312         216 :         status = winreg_delete_printer_key(tmp_ctx, b,
   10313             :                                            printer,
   10314             :                                            r->in.key_name);
   10315         216 :         if (W_ERROR_IS_OK(status)) {
   10316         216 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
   10317             :                                                         printer);
   10318             :         }
   10319             : 
   10320         162 : done:
   10321         216 :         talloc_free(tmp_ctx);
   10322         216 :         return status;
   10323             : }
   10324             : 
   10325             : /****************************************************************
   10326             :  _spoolss_EnumPrinterDataEx
   10327             : ****************************************************************/
   10328             : 
   10329        2860 : WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
   10330             :                                   struct spoolss_EnumPrinterDataEx *r)
   10331             : {
   10332        2860 :         uint32_t        count = 0;
   10333        2860 :         struct spoolss_PrinterEnumValues *info = NULL;
   10334        2860 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10335             :         int             snum;
   10336             :         WERROR          result;
   10337             : 
   10338        2860 :         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
   10339             : 
   10340        2860 :         *r->out.count = 0;
   10341        2860 :         *r->out.needed = 0;
   10342        2860 :         *r->out.info = NULL;
   10343             : 
   10344        2860 :         if (!Printer) {
   10345           0 :                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
   10346             :                         OUR_HANDLE(r->in.handle)));
   10347           0 :                 return WERR_INVALID_HANDLE;
   10348             :         }
   10349             : 
   10350             :         /*
   10351             :          * first check for a keyname of NULL or "".  Win2k seems to send
   10352             :          * this a lot and we should send back WERR_INVALID_PARAMETER
   10353             :          * no need to spend time looking up the printer in this case.
   10354             :          * --jerry
   10355             :          */
   10356             : 
   10357        2860 :         if (!strlen(r->in.key_name)) {
   10358           4 :                 result = WERR_INVALID_PARAMETER;
   10359           4 :                 goto done;
   10360             :         }
   10361             : 
   10362        2856 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10363           0 :                 return WERR_INVALID_HANDLE;
   10364             :         }
   10365             : 
   10366             :         /* now look for a match on the key name */
   10367        2856 :         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
   10368             :                                             get_session_info_system(),
   10369             :                                             p->msg_ctx,
   10370             :                                             lp_const_servicename(snum),
   10371             :                                             r->in.key_name,
   10372             :                                             &count,
   10373             :                                             &info);
   10374        2856 :         if (!W_ERROR_IS_OK(result)) {
   10375           0 :                 goto done;
   10376             :         }
   10377             : 
   10378             : #if 0 /* FIXME - gd */
   10379             :         /* housekeeping information in the reply */
   10380             : 
   10381             :         /* Fix from Martin Zielinski <mz@seh.de> - ensure
   10382             :          * the hand marshalled container size is a multiple
   10383             :          * of 4 bytes for RPC alignment.
   10384             :          */
   10385             : 
   10386             :         if (needed % 4) {
   10387             :                 needed += 4-(needed % 4);
   10388             :         }
   10389             : #endif
   10390        2856 :         *r->out.count        = count;
   10391        2856 :         *r->out.info = info;
   10392             : 
   10393        2860 :  done:
   10394        2860 :         if (!W_ERROR_IS_OK(result)) {
   10395           4 :                 return result;
   10396             :         }
   10397             : 
   10398        2856 :         *r->out.needed       = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
   10399             :                                                spoolss_EnumPrinterDataEx,
   10400             :                                                *r->out.info,
   10401             :                                                *r->out.count);
   10402        2856 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
   10403        2856 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
   10404             : 
   10405        2856 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
   10406             : }
   10407             : 
   10408             : /****************************************************************************
   10409             : ****************************************************************************/
   10410             : 
   10411          40 : static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
   10412             :                                                  const char *servername,
   10413             :                                                  const char *environment,
   10414             :                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
   10415             : {
   10416             :         WERROR werr;
   10417          40 :         char *path = NULL;
   10418             : 
   10419          40 :         werr = compose_spoolss_server_path(mem_ctx,
   10420             :                                            servername,
   10421             :                                            environment,
   10422             :                                            SPOOLSS_PRTPROCS_PATH,
   10423             :                                            &path);
   10424          40 :         if (!W_ERROR_IS_OK(werr)) {
   10425           0 :                 return werr;
   10426             :         }
   10427             : 
   10428          40 :         DEBUG(4,("print processor directory: [%s]\n", path));
   10429             : 
   10430          40 :         r->directory_name = path;
   10431             : 
   10432          40 :         return WERR_OK;
   10433             : }
   10434             : 
   10435             : /****************************************************************
   10436             :  _spoolss_GetPrintProcessorDirectory
   10437             : ****************************************************************/
   10438             : 
   10439          40 : WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
   10440             :                                            struct spoolss_GetPrintProcessorDirectory *r)
   10441             : {
   10442             :         WERROR result;
   10443          40 :         char *prnproc_share = NULL;
   10444          40 :         bool prnproc_share_exists = false;
   10445             :         int snum;
   10446             : 
   10447             :         /* that's an [in out] buffer */
   10448             : 
   10449          40 :         if (!r->in.buffer && (r->in.offered != 0)) {
   10450           0 :                 result = WERR_INVALID_PARAMETER;
   10451           0 :                 goto err_info_free;
   10452             :         }
   10453             : 
   10454          40 :         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
   10455             :                 r->in.level));
   10456             : 
   10457          40 :         *r->out.needed = 0;
   10458             : 
   10459             :         /* r->in.level is ignored */
   10460             : 
   10461             :         /* We always should reply with a local print processor directory so that
   10462             :          * users are not forced to have a [prnproc$] share on the Samba spoolss
   10463             :          * server, if users decide to do so, lets announce it though - Guenther */
   10464             : 
   10465          40 :         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
   10466          40 :         if (!prnproc_share) {
   10467           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
   10468           0 :                 goto err_info_free;
   10469             :         }
   10470          40 :         if (snum != -1) {
   10471           0 :                 prnproc_share_exists = true;
   10472             :         }
   10473             : 
   10474          40 :         result = getprintprocessordirectory_level_1(p->mem_ctx,
   10475             :                                                     prnproc_share_exists ? r->in.server : NULL,
   10476             :                                                     r->in.environment,
   10477          40 :                                                     &r->out.info->info1);
   10478          40 :         if (!W_ERROR_IS_OK(result)) {
   10479           0 :                 goto err_info_free;
   10480             :         }
   10481             : 
   10482          40 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
   10483             :                                                                                    r->out.info, r->in.level);
   10484          40 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
   10485             : 
   10486          40 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
   10487             : 
   10488           0 : err_info_free:
   10489           0 :         TALLOC_FREE(r->out.info);
   10490           0 :         return result;
   10491             : }
   10492             : 
   10493             : /*******************************************************************
   10494             :  ********************************************************************/
   10495             : 
   10496           0 : static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
   10497             :                                const char *dllname)
   10498             : {
   10499             :         enum ndr_err_code ndr_err;
   10500             :         struct spoolss_MonitorUi ui;
   10501             : 
   10502           0 :         ui.dll_name = dllname;
   10503             : 
   10504           0 :         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
   10505             :                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
   10506           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10507           0 :                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
   10508             :         }
   10509           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10510             : }
   10511             : 
   10512             : /*******************************************************************
   10513             :  Streams the monitor UI DLL name in UNICODE
   10514             : *******************************************************************/
   10515             : 
   10516           0 : static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
   10517             :                                struct security_token *token, DATA_BLOB *in,
   10518             :                                DATA_BLOB *out, uint32_t *needed)
   10519             : {
   10520           0 :         const char *dllname = "tcpmonui.dll";
   10521             : 
   10522           0 :         *needed = (strlen(dllname)+1) * 2;
   10523             : 
   10524           0 :         if (out->length < *needed) {
   10525           0 :                 return WERR_INSUFFICIENT_BUFFER;
   10526             :         }
   10527             : 
   10528           0 :         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
   10529           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10530             :         }
   10531             : 
   10532           0 :         return WERR_OK;
   10533             : }
   10534             : 
   10535             : /*******************************************************************
   10536             :  ********************************************************************/
   10537             : 
   10538           0 : static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
   10539             :                              struct spoolss_PortData1 *port1,
   10540             :                              const DATA_BLOB *buf)
   10541             : {
   10542             :         enum ndr_err_code ndr_err;
   10543           0 :         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
   10544             :                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
   10545           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10546           0 :                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
   10547             :         }
   10548           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10549             : }
   10550             : 
   10551             : /*******************************************************************
   10552             :  ********************************************************************/
   10553             : 
   10554           0 : static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
   10555             :                              struct spoolss_PortData2 *port2,
   10556             :                              const DATA_BLOB *buf)
   10557             : {
   10558             :         enum ndr_err_code ndr_err;
   10559           0 :         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
   10560             :                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
   10561           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10562           0 :                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
   10563             :         }
   10564           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10565             : }
   10566             : 
   10567             : /*******************************************************************
   10568             :  Create a new TCP/IP port
   10569             : *******************************************************************/
   10570             : 
   10571           0 : static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
   10572             :                              struct security_token *token, DATA_BLOB *in,
   10573             :                              DATA_BLOB *out, uint32_t *needed)
   10574             : {
   10575             :         struct spoolss_PortData1 port1;
   10576             :         struct spoolss_PortData2 port2;
   10577           0 :         char *device_uri = NULL;
   10578             :         uint32_t version;
   10579             : 
   10580             :         const char *portname;
   10581             :         const char *hostaddress;
   10582             :         const char *queue;
   10583             :         uint32_t port_number;
   10584             :         uint32_t protocol;
   10585             : 
   10586             :         /* peek for spoolss_PortData version */
   10587             : 
   10588           0 :         if (!in || (in->length < (128 + 4))) {
   10589           0 :                 return WERR_GEN_FAILURE;
   10590             :         }
   10591             : 
   10592           0 :         version = IVAL(in->data, 128);
   10593             : 
   10594           0 :         switch (version) {
   10595           0 :                 case 1:
   10596           0 :                         ZERO_STRUCT(port1);
   10597             : 
   10598           0 :                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
   10599           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
   10600             :                         }
   10601             : 
   10602           0 :                         portname        = port1.portname;
   10603           0 :                         hostaddress     = port1.hostaddress;
   10604           0 :                         queue           = port1.queue;
   10605           0 :                         protocol        = port1.protocol;
   10606           0 :                         port_number     = port1.port_number;
   10607             : 
   10608           0 :                         break;
   10609           0 :                 case 2:
   10610           0 :                         ZERO_STRUCT(port2);
   10611             : 
   10612           0 :                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
   10613           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
   10614             :                         }
   10615             : 
   10616           0 :                         portname        = port2.portname;
   10617           0 :                         hostaddress     = port2.hostaddress;
   10618           0 :                         queue           = port2.queue;
   10619           0 :                         protocol        = port2.protocol;
   10620           0 :                         port_number     = port2.port_number;
   10621             : 
   10622           0 :                         break;
   10623           0 :                 default:
   10624           0 :                         DEBUG(1,("xcvtcp_addport: "
   10625             :                                 "unknown version of port_data: %d\n", version));
   10626           0 :                         return WERR_UNKNOWN_PORT;
   10627             :         }
   10628             : 
   10629             :         /* create the device URI and call the add_port_hook() */
   10630             : 
   10631           0 :         switch (protocol) {
   10632           0 :         case PROTOCOL_RAWTCP_TYPE:
   10633           0 :                 device_uri = talloc_asprintf(mem_ctx,
   10634             :                                 "socket://%s:%d/", hostaddress,
   10635             :                                 port_number);
   10636           0 :                 break;
   10637             : 
   10638           0 :         case PROTOCOL_LPR_TYPE:
   10639           0 :                 device_uri = talloc_asprintf(mem_ctx,
   10640             :                         "lpr://%s/%s", hostaddress, queue );
   10641           0 :                 break;
   10642             : 
   10643           0 :         default:
   10644           0 :                 return WERR_UNKNOWN_PORT;
   10645             :         }
   10646             : 
   10647           0 :         if (!device_uri) {
   10648           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10649             :         }
   10650             : 
   10651           0 :         return add_port_hook(mem_ctx, token, portname, device_uri);
   10652             : }
   10653             : 
   10654             : /*******************************************************************
   10655             : *******************************************************************/
   10656             : 
   10657             : struct xcv_api_table xcvtcp_cmds[] = {
   10658             :         { "MonitorUI",        xcvtcp_monitorui },
   10659             :         { "AddPort",  xcvtcp_addport},
   10660             :         { NULL,         NULL }
   10661             : };
   10662             : 
   10663           0 : static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
   10664             :                                      struct security_token *token, const char *command,
   10665             :                                      DATA_BLOB *inbuf,
   10666             :                                      DATA_BLOB *outbuf,
   10667             :                                      uint32_t *needed )
   10668             : {
   10669             :         int i;
   10670             : 
   10671           0 :         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
   10672             : 
   10673           0 :         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
   10674           0 :                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
   10675           0 :                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
   10676             :         }
   10677             : 
   10678           0 :         return WERR_INVALID_FUNCTION;
   10679             : }
   10680             : 
   10681             : /*******************************************************************
   10682             : *******************************************************************/
   10683             : #if 0   /* don't support management using the "Local Port" monitor */
   10684             : 
   10685             : static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
   10686             :                                  struct security_token *token, DATA_BLOB *in,
   10687             :                                  DATA_BLOB *out, uint32_t *needed)
   10688             : {
   10689             :         const char *dllname = "localui.dll";
   10690             : 
   10691             :         *needed = (strlen(dllname)+1) * 2;
   10692             : 
   10693             :         if (out->length < *needed) {
   10694             :                 return WERR_INSUFFICIENT_BUFFER;
   10695             :         }
   10696             : 
   10697             :         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
   10698             :                 return WERR_NOT_ENOUGH_MEMORY;
   10699             :         }
   10700             : 
   10701             :         return WERR_OK;
   10702             : }
   10703             : 
   10704             : /*******************************************************************
   10705             : *******************************************************************/
   10706             : 
   10707             : struct xcv_api_table xcvlocal_cmds[] = {
   10708             :         { "MonitorUI",        xcvlocal_monitorui },
   10709             :         { NULL,         NULL }
   10710             : };
   10711             : #else
   10712             : struct xcv_api_table xcvlocal_cmds[] = {
   10713             :         { NULL,         NULL }
   10714             : };
   10715             : #endif
   10716             : 
   10717             : 
   10718             : 
   10719             : /*******************************************************************
   10720             : *******************************************************************/
   10721             : 
   10722           0 : static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
   10723             :                                        struct security_token *token, const char *command,
   10724             :                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
   10725             :                                        uint32_t *needed)
   10726             : {
   10727             :         int i;
   10728             : 
   10729           0 :         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
   10730             : 
   10731           0 :         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
   10732           0 :                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
   10733           0 :                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
   10734             :         }
   10735           0 :         return WERR_INVALID_FUNCTION;
   10736             : }
   10737             : 
   10738             : /****************************************************************
   10739             :  _spoolss_XcvData
   10740             : ****************************************************************/
   10741             : 
   10742           0 : WERROR _spoolss_XcvData(struct pipes_struct *p,
   10743             :                         struct spoolss_XcvData *r)
   10744             : {
   10745           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10746           0 :         DATA_BLOB out_data = data_blob_null;
   10747             :         WERROR werror;
   10748             : 
   10749           0 :         if (!Printer) {
   10750           0 :                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
   10751             :                         OUR_HANDLE(r->in.handle)));
   10752           0 :                 return WERR_INVALID_HANDLE;
   10753             :         }
   10754             : 
   10755             :         /* Has to be a handle to the TCP/IP port monitor */
   10756             : 
   10757           0 :         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
   10758           0 :                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
   10759           0 :                 return WERR_INVALID_HANDLE;
   10760             :         }
   10761             : 
   10762             :         /* requires administrative access to the server */
   10763             : 
   10764           0 :         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
   10765           0 :                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
   10766           0 :                 return WERR_ACCESS_DENIED;
   10767             :         }
   10768             : 
   10769             :         /* Allocate the outgoing buffer */
   10770             : 
   10771           0 :         if (r->in.out_data_size) {
   10772           0 :                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
   10773           0 :                 if (out_data.data == NULL) {
   10774           0 :                         return WERR_NOT_ENOUGH_MEMORY;
   10775             :                 }
   10776             :         }
   10777             : 
   10778           0 :         switch ( Printer->printer_type ) {
   10779           0 :         case SPLHND_PORTMON_TCP:
   10780           0 :                 werror = process_xcvtcp_command(p->mem_ctx,
   10781           0 :                                                 p->session_info->security_token,
   10782             :                                                 r->in.function_name,
   10783             :                                                 &r->in.in_data, &out_data,
   10784             :                                                 r->out.needed);
   10785           0 :                 break;
   10786           0 :         case SPLHND_PORTMON_LOCAL:
   10787           0 :                 werror = process_xcvlocal_command(p->mem_ctx,
   10788           0 :                                                   p->session_info->security_token,
   10789             :                                                   r->in.function_name,
   10790             :                                                   &r->in.in_data, &out_data,
   10791             :                                                   r->out.needed);
   10792           0 :                 break;
   10793           0 :         default:
   10794           0 :                 werror = WERR_INVALID_PRINT_MONITOR;
   10795             :         }
   10796             : 
   10797           0 :         if (!W_ERROR_IS_OK(werror)) {
   10798           0 :                 return werror;
   10799             :         }
   10800             : 
   10801           0 :         *r->out.status_code = 0;
   10802             : 
   10803           0 :         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
   10804           0 :                 memcpy(r->out.out_data, out_data.data,
   10805           0 :                         MIN(r->in.out_data_size, out_data.length));
   10806             :         }
   10807             : 
   10808           0 :         return WERR_OK;
   10809             : }
   10810             : 
   10811             : /****************************************************************
   10812             :  _spoolss_AddPrintProcessor
   10813             : ****************************************************************/
   10814             : 
   10815           4 : WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
   10816             :                                   struct spoolss_AddPrintProcessor *r)
   10817             : {
   10818             :         /* for now, just indicate success and ignore the add.  We'll
   10819             :            automatically set the winprint processor for printer
   10820             :            entries later.  Used to debug the LexMark Optra S 1855 PCL
   10821             :            driver --jerry */
   10822             : 
   10823           4 :         return WERR_OK;
   10824             : }
   10825             : 
   10826             : /****************************************************************
   10827             :  _spoolss_AddPort
   10828             : ****************************************************************/
   10829             : 
   10830           4 : WERROR _spoolss_AddPort(struct pipes_struct *p,
   10831             :                         struct spoolss_AddPort *r)
   10832             : {
   10833             :         /* do what w2k3 does */
   10834             : 
   10835           4 :         return WERR_NOT_SUPPORTED;
   10836             : }
   10837             : 
   10838             : /****************************************************************
   10839             :  _spoolss_GetPrinterDriver
   10840             : ****************************************************************/
   10841             : 
   10842           0 : WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
   10843             :                                  struct spoolss_GetPrinterDriver *r)
   10844             : {
   10845           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10846           0 :         return WERR_NOT_SUPPORTED;
   10847             : }
   10848             : 
   10849             : /****************************************************************
   10850             :  _spoolss_ReadPrinter
   10851             : ****************************************************************/
   10852             : 
   10853           0 : WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
   10854             :                             struct spoolss_ReadPrinter *r)
   10855             : {
   10856           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10857           0 :         return WERR_NOT_SUPPORTED;
   10858             : }
   10859             : 
   10860             : /****************************************************************
   10861             :  _spoolss_WaitForPrinterChange
   10862             : ****************************************************************/
   10863             : 
   10864           0 : WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
   10865             :                                      struct spoolss_WaitForPrinterChange *r)
   10866             : {
   10867           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10868           0 :         return WERR_NOT_SUPPORTED;
   10869             : }
   10870             : 
   10871             : /****************************************************************
   10872             :  _spoolss_ConfigurePort
   10873             : ****************************************************************/
   10874             : 
   10875           0 : WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
   10876             :                               struct spoolss_ConfigurePort *r)
   10877             : {
   10878           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10879           0 :         return WERR_NOT_SUPPORTED;
   10880             : }
   10881             : 
   10882             : /****************************************************************
   10883             :  _spoolss_DeletePort
   10884             : ****************************************************************/
   10885             : 
   10886           0 : WERROR _spoolss_DeletePort(struct pipes_struct *p,
   10887             :                            struct spoolss_DeletePort *r)
   10888             : {
   10889           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10890           0 :         return WERR_NOT_SUPPORTED;
   10891             : }
   10892             : 
   10893             : /****************************************************************
   10894             :  _spoolss_CreatePrinterIC
   10895             : ****************************************************************/
   10896             : 
   10897           0 : WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
   10898             :                                 struct spoolss_CreatePrinterIC *r)
   10899             : {
   10900           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10901           0 :         return WERR_NOT_SUPPORTED;
   10902             : }
   10903             : 
   10904             : /****************************************************************
   10905             :  _spoolss_PlayGDIScriptOnPrinterIC
   10906             : ****************************************************************/
   10907             : 
   10908           0 : WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
   10909             :                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
   10910             : {
   10911           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10912           0 :         return WERR_NOT_SUPPORTED;
   10913             : }
   10914             : 
   10915             : /****************************************************************
   10916             :  _spoolss_DeletePrinterIC
   10917             : ****************************************************************/
   10918             : 
   10919           0 : WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
   10920             :                                 struct spoolss_DeletePrinterIC *r)
   10921             : {
   10922           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10923           0 :         return WERR_NOT_SUPPORTED;
   10924             : }
   10925             : 
   10926             : /****************************************************************
   10927             :  _spoolss_AddPrinterConnection
   10928             : ****************************************************************/
   10929             : 
   10930           0 : WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
   10931             :                                      struct spoolss_AddPrinterConnection *r)
   10932             : {
   10933           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10934           0 :         return WERR_NOT_SUPPORTED;
   10935             : }
   10936             : 
   10937             : /****************************************************************
   10938             :  _spoolss_DeletePrinterConnection
   10939             : ****************************************************************/
   10940             : 
   10941           0 : WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
   10942             :                                         struct spoolss_DeletePrinterConnection *r)
   10943             : {
   10944           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10945           0 :         return WERR_NOT_SUPPORTED;
   10946             : }
   10947             : 
   10948             : /****************************************************************
   10949             :  _spoolss_PrinterMessageBox
   10950             : ****************************************************************/
   10951             : 
   10952           0 : WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
   10953             :                                   struct spoolss_PrinterMessageBox *r)
   10954             : {
   10955           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10956           0 :         return WERR_NOT_SUPPORTED;
   10957             : }
   10958             : 
   10959             : /****************************************************************
   10960             :  _spoolss_AddMonitor
   10961             : ****************************************************************/
   10962             : 
   10963           0 : WERROR _spoolss_AddMonitor(struct pipes_struct *p,
   10964             :                            struct spoolss_AddMonitor *r)
   10965             : {
   10966           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10967           0 :         return WERR_NOT_SUPPORTED;
   10968             : }
   10969             : 
   10970             : /****************************************************************
   10971             :  _spoolss_DeleteMonitor
   10972             : ****************************************************************/
   10973             : 
   10974           0 : WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
   10975             :                               struct spoolss_DeleteMonitor *r)
   10976             : {
   10977           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10978           0 :         return WERR_NOT_SUPPORTED;
   10979             : }
   10980             : 
   10981             : /****************************************************************
   10982             :  _spoolss_DeletePrintProcessor
   10983             : ****************************************************************/
   10984             : 
   10985           0 : WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
   10986             :                                      struct spoolss_DeletePrintProcessor *r)
   10987             : {
   10988           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10989           0 :         return WERR_NOT_SUPPORTED;
   10990             : }
   10991             : 
   10992             : /****************************************************************
   10993             :  _spoolss_AddPrintProvidor
   10994             : ****************************************************************/
   10995             : 
   10996           0 : WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
   10997             :                                  struct spoolss_AddPrintProvidor *r)
   10998             : {
   10999           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11000           0 :         return WERR_NOT_SUPPORTED;
   11001             : }
   11002             : 
   11003             : /****************************************************************
   11004             :  _spoolss_DeletePrintProvidor
   11005             : ****************************************************************/
   11006             : 
   11007           0 : WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
   11008             :                                     struct spoolss_DeletePrintProvidor *r)
   11009             : {
   11010           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11011           0 :         return WERR_NOT_SUPPORTED;
   11012             : }
   11013             : 
   11014             : /****************************************************************
   11015             :  _spoolss_FindFirstPrinterChangeNotification
   11016             : ****************************************************************/
   11017             : 
   11018           0 : WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
   11019             :                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
   11020             : {
   11021           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11022           0 :         return WERR_NOT_SUPPORTED;
   11023             : }
   11024             : 
   11025             : /****************************************************************
   11026             :  _spoolss_FindNextPrinterChangeNotification
   11027             : ****************************************************************/
   11028             : 
   11029           0 : WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
   11030             :                                                   struct spoolss_FindNextPrinterChangeNotification *r)
   11031             : {
   11032           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11033           0 :         return WERR_NOT_SUPPORTED;
   11034             : }
   11035             : 
   11036             : /****************************************************************
   11037             :  _spoolss_RouterFindFirstPrinterChangeNotificationOld
   11038             : ****************************************************************/
   11039             : 
   11040           0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
   11041             :                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
   11042             : {
   11043           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11044           0 :         return WERR_NOT_SUPPORTED;
   11045             : }
   11046             : 
   11047             : /****************************************************************
   11048             :  _spoolss_ReplyOpenPrinter
   11049             : ****************************************************************/
   11050             : 
   11051           0 : WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
   11052             :                                  struct spoolss_ReplyOpenPrinter *r)
   11053             : {
   11054           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11055           0 :         return WERR_NOT_SUPPORTED;
   11056             : }
   11057             : 
   11058             : /****************************************************************
   11059             :  _spoolss_RouterReplyPrinter
   11060             : ****************************************************************/
   11061             : 
   11062           0 : WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
   11063             :                                    struct spoolss_RouterReplyPrinter *r)
   11064             : {
   11065           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11066           0 :         return WERR_NOT_SUPPORTED;
   11067             : }
   11068             : 
   11069             : /****************************************************************
   11070             :  _spoolss_ReplyClosePrinter
   11071             : ****************************************************************/
   11072             : 
   11073           0 : WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
   11074             :                                   struct spoolss_ReplyClosePrinter *r)
   11075             : {
   11076           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11077           0 :         return WERR_NOT_SUPPORTED;
   11078             : }
   11079             : 
   11080             : /****************************************************************
   11081             :  _spoolss_AddPortEx
   11082             : ****************************************************************/
   11083             : 
   11084           0 : WERROR _spoolss_AddPortEx(struct pipes_struct *p,
   11085             :                           struct spoolss_AddPortEx *r)
   11086             : {
   11087           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11088           0 :         return WERR_NOT_SUPPORTED;
   11089             : }
   11090             : 
   11091             : /****************************************************************
   11092             :  _spoolss_RouterFindFirstPrinterChangeNotification
   11093             : ****************************************************************/
   11094             : 
   11095           0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
   11096             :                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
   11097             : {
   11098           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11099           0 :         return WERR_NOT_SUPPORTED;
   11100             : }
   11101             : 
   11102             : /****************************************************************
   11103             :  _spoolss_SpoolerInit
   11104             : ****************************************************************/
   11105             : 
   11106           0 : WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
   11107             :                             struct spoolss_SpoolerInit *r)
   11108             : {
   11109           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11110           0 :         return WERR_NOT_SUPPORTED;
   11111             : }
   11112             : 
   11113             : /****************************************************************
   11114             :  _spoolss_ResetPrinterEx
   11115             : ****************************************************************/
   11116             : 
   11117           0 : WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
   11118             :                                struct spoolss_ResetPrinterEx *r)
   11119             : {
   11120           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11121           0 :         return WERR_NOT_SUPPORTED;
   11122             : }
   11123             : 
   11124             : /****************************************************************
   11125             :  _spoolss_RouterReplyPrinterEx
   11126             : ****************************************************************/
   11127             : 
   11128           0 : WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
   11129             :                                      struct spoolss_RouterReplyPrinterEx *r)
   11130             : {
   11131           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11132           0 :         return WERR_NOT_SUPPORTED;
   11133             : }
   11134             : 
   11135             : /****************************************************************
   11136             :  _spoolss_44
   11137             : ****************************************************************/
   11138             : 
   11139           0 : WERROR _spoolss_44(struct pipes_struct *p,
   11140             :                    struct spoolss_44 *r)
   11141             : {
   11142           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11143           0 :         return WERR_NOT_SUPPORTED;
   11144             : }
   11145             : 
   11146             : /****************************************************************
   11147             :  _spoolss_SetPort
   11148             : ****************************************************************/
   11149             : 
   11150           0 : WERROR _spoolss_SetPort(struct pipes_struct *p,
   11151             :                         struct spoolss_SetPort *r)
   11152             : {
   11153           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11154           0 :         return WERR_NOT_SUPPORTED;
   11155             : }
   11156             : 
   11157             : /****************************************************************
   11158             :  _spoolss_4a
   11159             : ****************************************************************/
   11160             : 
   11161           0 : WERROR _spoolss_4a(struct pipes_struct *p,
   11162             :                    struct spoolss_4a *r)
   11163             : {
   11164           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11165           0 :         return WERR_NOT_SUPPORTED;
   11166             : }
   11167             : 
   11168             : /****************************************************************
   11169             :  _spoolss_4b
   11170             : ****************************************************************/
   11171             : 
   11172           0 : WERROR _spoolss_4b(struct pipes_struct *p,
   11173             :                    struct spoolss_4b *r)
   11174             : {
   11175           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11176           0 :         return WERR_NOT_SUPPORTED;
   11177             : }
   11178             : 
   11179             : /****************************************************************
   11180             :  _spoolss_4c
   11181             : ****************************************************************/
   11182             : 
   11183           0 : WERROR _spoolss_4c(struct pipes_struct *p,
   11184             :                    struct spoolss_4c *r)
   11185             : {
   11186           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11187           0 :         return WERR_NOT_SUPPORTED;
   11188             : }
   11189             : 
   11190             : /****************************************************************
   11191             :  _spoolss_53
   11192             : ****************************************************************/
   11193             : 
   11194           0 : WERROR _spoolss_53(struct pipes_struct *p,
   11195             :                    struct spoolss_53 *r)
   11196             : {
   11197           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11198           0 :         return WERR_NOT_SUPPORTED;
   11199             : }
   11200             : 
   11201             : /****************************************************************
   11202             :  _spoolss_AddPerMachineConnection
   11203             : ****************************************************************/
   11204             : 
   11205           4 : WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
   11206             :                                         struct spoolss_AddPerMachineConnection *r)
   11207             : {
   11208           4 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11209           4 :         return WERR_NOT_SUPPORTED;
   11210             : }
   11211             : 
   11212             : /****************************************************************
   11213             :  _spoolss_DeletePerMachineConnection
   11214             : ****************************************************************/
   11215             : 
   11216           0 : WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
   11217             :                                            struct spoolss_DeletePerMachineConnection *r)
   11218             : {
   11219           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11220           0 :         return WERR_NOT_SUPPORTED;
   11221             : }
   11222             : 
   11223             : /****************************************************************
   11224             :  _spoolss_EnumPerMachineConnections
   11225             : ****************************************************************/
   11226             : 
   11227           0 : WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
   11228             :                                           struct spoolss_EnumPerMachineConnections *r)
   11229             : {
   11230           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11231           0 :         return WERR_NOT_SUPPORTED;
   11232             : }
   11233             : 
   11234             : /****************************************************************
   11235             :  _spoolss_5a
   11236             : ****************************************************************/
   11237             : 
   11238           0 : WERROR _spoolss_5a(struct pipes_struct *p,
   11239             :                    struct spoolss_5a *r)
   11240             : {
   11241           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11242           0 :         return WERR_NOT_SUPPORTED;
   11243             : }
   11244             : 
   11245             : /****************************************************************
   11246             :  _spoolss_5b
   11247             : ****************************************************************/
   11248             : 
   11249           0 : WERROR _spoolss_5b(struct pipes_struct *p,
   11250             :                    struct spoolss_5b *r)
   11251             : {
   11252           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11253           0 :         return WERR_NOT_SUPPORTED;
   11254             : }
   11255             : 
   11256             : /****************************************************************
   11257             :  _spoolss_5c
   11258             : ****************************************************************/
   11259             : 
   11260           0 : WERROR _spoolss_5c(struct pipes_struct *p,
   11261             :                    struct spoolss_5c *r)
   11262             : {
   11263           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11264           0 :         return WERR_NOT_SUPPORTED;
   11265             : }
   11266             : 
   11267             : /****************************************************************
   11268             :  _spoolss_5d
   11269             : ****************************************************************/
   11270             : 
   11271           0 : WERROR _spoolss_5d(struct pipes_struct *p,
   11272             :                    struct spoolss_5d *r)
   11273             : {
   11274           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11275           0 :         return WERR_NOT_SUPPORTED;
   11276             : }
   11277             : 
   11278             : /****************************************************************
   11279             :  _spoolss_5e
   11280             : ****************************************************************/
   11281             : 
   11282           0 : WERROR _spoolss_5e(struct pipes_struct *p,
   11283             :                    struct spoolss_5e *r)
   11284             : {
   11285           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11286           0 :         return WERR_NOT_SUPPORTED;
   11287             : }
   11288             : 
   11289             : /****************************************************************
   11290             :  _spoolss_5f
   11291             : ****************************************************************/
   11292             : 
   11293           0 : WERROR _spoolss_5f(struct pipes_struct *p,
   11294             :                    struct spoolss_5f *r)
   11295             : {
   11296           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11297           0 :         return WERR_NOT_SUPPORTED;
   11298             : }
   11299             : 
   11300             : /****************************************************************
   11301             :  _spoolss_60
   11302             : ****************************************************************/
   11303             : 
   11304           0 : WERROR _spoolss_60(struct pipes_struct *p,
   11305             :                    struct spoolss_60 *r)
   11306             : {
   11307           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11308           0 :         return WERR_NOT_SUPPORTED;
   11309             : }
   11310             : 
   11311             : /****************************************************************
   11312             :  _spoolss_SendRecvBidiData
   11313             : ****************************************************************/
   11314             : 
   11315           0 : WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
   11316             :                                  struct spoolss_SendRecvBidiData *r)
   11317             : {
   11318           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11319           0 :         return WERR_NOT_SUPPORTED;
   11320             : }
   11321             : 
   11322             : /****************************************************************
   11323             :  _spoolss_62
   11324             : ****************************************************************/
   11325             : 
   11326           0 : WERROR _spoolss_62(struct pipes_struct *p,
   11327             :                    struct spoolss_62 *r)
   11328             : {
   11329           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11330           0 :         return WERR_NOT_SUPPORTED;
   11331             : }
   11332             : 
   11333             : /****************************************************************
   11334             :  _spoolss_63
   11335             : ****************************************************************/
   11336             : 
   11337           0 : WERROR _spoolss_63(struct pipes_struct *p,
   11338             :                    struct spoolss_63 *r)
   11339             : {
   11340           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11341           0 :         return WERR_NOT_SUPPORTED;
   11342             : }
   11343             : 
   11344             : /****************************************************************
   11345             :  _spoolss_64
   11346             : ****************************************************************/
   11347             : 
   11348           0 : WERROR _spoolss_64(struct pipes_struct *p,
   11349             :                    struct spoolss_64 *r)
   11350             : {
   11351           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11352           0 :         return WERR_NOT_SUPPORTED;
   11353             : }
   11354             : 
   11355             : /****************************************************************
   11356             :  _spoolss_65
   11357             : ****************************************************************/
   11358             : 
   11359           0 : WERROR _spoolss_65(struct pipes_struct *p,
   11360             :                    struct spoolss_65 *r)
   11361             : {
   11362           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11363           0 :         return WERR_NOT_SUPPORTED;
   11364             : }
   11365             : 
   11366             : /****************************************************************
   11367             :  _spoolss_GetCorePrinterDrivers
   11368             : ****************************************************************/
   11369             : 
   11370           8 : HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
   11371             :                                        struct spoolss_GetCorePrinterDrivers *r)
   11372             : {
   11373           8 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11374           8 :         return HRES_ERROR_NOT_SUPPORTED;
   11375             : }
   11376             : 
   11377             : /****************************************************************
   11378             :  _spoolss_67
   11379             : ****************************************************************/
   11380             : 
   11381           0 : WERROR _spoolss_67(struct pipes_struct *p,
   11382             :                    struct spoolss_67 *r)
   11383             : {
   11384           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11385           0 :         return WERR_NOT_SUPPORTED;
   11386             : }
   11387             : 
   11388             : /****************************************************************
   11389             :  _spoolss_GetPrinterDriverPackagePath
   11390             : ****************************************************************/
   11391             : 
   11392           4 : HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
   11393             :                                              struct spoolss_GetPrinterDriverPackagePath *r)
   11394             : {
   11395           4 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11396           4 :         return HRES_ERROR_NOT_SUPPORTED;
   11397             : }
   11398             : 
   11399             : /****************************************************************
   11400             :  _spoolss_69
   11401             : ****************************************************************/
   11402             : 
   11403           0 : WERROR _spoolss_69(struct pipes_struct *p,
   11404             :                    struct spoolss_69 *r)
   11405             : {
   11406           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11407           0 :         return WERR_NOT_SUPPORTED;
   11408             : }
   11409             : 
   11410             : /****************************************************************
   11411             :  _spoolss_6a
   11412             : ****************************************************************/
   11413             : 
   11414           0 : WERROR _spoolss_6a(struct pipes_struct *p,
   11415             :                    struct spoolss_6a *r)
   11416             : {
   11417           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11418           0 :         return WERR_NOT_SUPPORTED;
   11419             : }
   11420             : 
   11421             : /****************************************************************
   11422             :  _spoolss_6b
   11423             : ****************************************************************/
   11424             : 
   11425           0 : WERROR _spoolss_6b(struct pipes_struct *p,
   11426             :                    struct spoolss_6b *r)
   11427             : {
   11428           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11429           0 :         return WERR_NOT_SUPPORTED;
   11430             : }
   11431             : 
   11432             : /****************************************************************
   11433             :  _spoolss_6c
   11434             : ****************************************************************/
   11435             : 
   11436           0 : WERROR _spoolss_6c(struct pipes_struct *p,
   11437             :                    struct spoolss_6c *r)
   11438             : {
   11439           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11440           0 :         return WERR_NOT_SUPPORTED;
   11441             : }
   11442             : 
   11443             : /****************************************************************
   11444             :  _spoolss_6d
   11445             : ****************************************************************/
   11446             : 
   11447           0 : WERROR _spoolss_6d(struct pipes_struct *p,
   11448             :                    struct spoolss_6d *r)
   11449             : {
   11450           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11451           0 :         return WERR_NOT_SUPPORTED;
   11452             : }
   11453             : 
   11454             : /****************************************************************
   11455             :  _spoolss_GetJobNamedPropertyValue
   11456             : ****************************************************************/
   11457             : 
   11458           0 : WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
   11459             :                                          struct spoolss_GetJobNamedPropertyValue *r)
   11460             : {
   11461           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11462           0 :         return WERR_NOT_SUPPORTED;
   11463             : }
   11464             : 
   11465             : /****************************************************************
   11466             :  _spoolss_SetJobNamedProperty
   11467             : ****************************************************************/
   11468             : 
   11469           0 : WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
   11470             :                                     struct spoolss_SetJobNamedProperty *r)
   11471             : {
   11472           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11473           0 :         return WERR_NOT_SUPPORTED;
   11474             : }
   11475             : 
   11476             : /****************************************************************
   11477             :  _spoolss_DeleteJobNamedProperty
   11478             : ****************************************************************/
   11479             : 
   11480           0 : WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
   11481             :                                        struct spoolss_DeleteJobNamedProperty *r)
   11482             : {
   11483           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11484           0 :         return WERR_NOT_SUPPORTED;
   11485             : }
   11486             : 
   11487             : /****************************************************************
   11488             :  _spoolss_EnumJobNamedProperties
   11489             : ****************************************************************/
   11490             : 
   11491           0 : WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
   11492             :                                        struct spoolss_EnumJobNamedProperties *r)
   11493             : {
   11494           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11495           0 :         return WERR_NOT_SUPPORTED;
   11496             : }
   11497             : 
   11498             : /****************************************************************
   11499             :  _spoolss_72
   11500             : ****************************************************************/
   11501             : 
   11502           0 : WERROR _spoolss_72(struct pipes_struct *p,
   11503             :                    struct spoolss_72 *r)
   11504             : {
   11505           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11506           0 :         return WERR_NOT_SUPPORTED;
   11507             : }
   11508             : 
   11509             : /****************************************************************
   11510             :  _spoolss_73
   11511             : ****************************************************************/
   11512             : 
   11513           0 : WERROR _spoolss_73(struct pipes_struct *p,
   11514             :                    struct spoolss_73 *r)
   11515             : {
   11516           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11517           0 :         return WERR_NOT_SUPPORTED;
   11518             : }
   11519             : 
   11520             : /****************************************************************
   11521             :  _spoolss_RpcLogJobInfoForBranchOffice
   11522             : ****************************************************************/
   11523             : 
   11524           8 : WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
   11525             :                                           struct spoolss_LogJobInfoForBranchOffice *r)
   11526             : {
   11527           8 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11528           8 :         return WERR_NOT_SUPPORTED;
   11529             : }
   11530             : 
   11531             : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
   11532             :                 const struct dcesrv_endpoint_server *ep_server);
   11533             : 
   11534             : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
   11535             :                 const struct dcesrv_endpoint_server *ep_server);
   11536             : 
   11537             : #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
   11538             :         spoolss_init_server
   11539             : 
   11540             : #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
   11541             :         spoolss_shutdown_server
   11542             : 
   11543          60 : static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
   11544             :                 const struct dcesrv_endpoint_server *ep_server)
   11545             : {
   11546          60 :         struct messaging_context *msg_ctx = global_messaging_context();
   11547             :         NTSTATUS status;
   11548             :         bool ok;
   11549             : 
   11550          60 :         status = dcesrv_init_ep_server(dce_ctx, "winreg");
   11551          60 :         if (!NT_STATUS_IS_OK(status)) {
   11552           0 :                 return status;
   11553             :         }
   11554             : 
   11555             :         /*
   11556             :          * Migrate the printers first.
   11557             :          */
   11558          60 :         ok = nt_printing_tdb_migrate(msg_ctx);
   11559          60 :         if (!ok) {
   11560           0 :                 return NT_STATUS_UNSUCCESSFUL;
   11561             :         }
   11562             : 
   11563          60 :         return spoolss__op_init_server(dce_ctx, ep_server);
   11564             : }
   11565             : 
   11566           1 : static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
   11567             :                 const struct dcesrv_endpoint_server *ep_server)
   11568             : {
   11569           1 :         srv_spoolss_cleanup();
   11570             : 
   11571           1 :         return spoolss__op_shutdown_server(dce_ctx, ep_server);
   11572             : }
   11573             : 
   11574             : /* include the generated boilerplate */
   11575             : #include "librpc/gen_ndr/ndr_spoolss_scompat.c"

Generated by: LCOV version 1.13