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 master 2b515b7d Lines: 2245 4837 46.4 %
Date: 2024-02-28 12:06:22 Functions: 128 275 46.5 %

          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         520 : static const char *canon_servername(const char *servername)
     151             : {
     152         520 :         const char *pservername = servername;
     153             : 
     154         520 :         if (servername == NULL) {
     155           0 :                 return "";
     156             :         }
     157             : 
     158        1568 :         while (*pservername == '\\') {
     159        1048 :                 pservername++;
     160             :         }
     161         520 :         return pservername;
     162             : }
     163             : 
     164             : /* translate between internal status numbers and NT status numbers */
     165         388 : static int nt_printj_status(int v)
     166             : {
     167         388 :         switch (v) {
     168         388 :         case LPQ_QUEUED:
     169         388 :                 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        1636 : static int nt_printq_status(int v)
     197             : {
     198        1636 :         switch (v) {
     199         220 :         case LPQ_PAUSED:
     200         220 :                 return PRINTER_STATUS_PAUSED;
     201        1416 :         case LPQ_QUEUED:
     202             :         case LPQ_SPOOLING:
     203             :         case LPQ_PRINTING:
     204        1416 :                 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           0 :         WERROR result;
     217           0 :         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           2 :         if (prn_hnd->notify.cli_chan == NULL ||
     231           2 :             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
     232           2 :             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           2 :         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         972 : static int printer_entry_destructor(struct printer_handle *Printer)
     278             : {
     279         972 :         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             :         }
     298             : 
     299         972 :         Printer->notify.flags=0;
     300         972 :         Printer->notify.options=0;
     301         972 :         Printer->notify.localmachine[0]='\0';
     302         972 :         Printer->notify.printerlocal=0;
     303         972 :         TALLOC_FREE(Printer->notify.option);
     304         972 :         TALLOC_FREE(Printer->devmode);
     305             : 
     306             :         /* Remove from the internal list. */
     307         972 :         DLIST_REMOVE(printers_list, Printer);
     308         972 :         return 0;
     309             : }
     310             : 
     311             : /****************************************************************************
     312             :   find printer index by handle
     313             : ****************************************************************************/
     314             : 
     315       52176 : static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
     316             :                                                         struct policy_handle *hnd)
     317             : {
     318       52176 :         struct printer_handle *find_printer = NULL;
     319           0 :         NTSTATUS status;
     320             : 
     321       52176 :         find_printer = find_policy_by_hnd(p,
     322             :                                           hnd,
     323             :                                           DCESRV_HANDLE_ANY,
     324             :                                           struct printer_handle,
     325           0 :                                           &status);
     326       52176 :         if (!NT_STATUS_IS_OK(status)) {
     327           0 :                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: %s\n",
     328             :                          nt_errstr(status)));
     329           0 :                 return NULL;
     330             :         }
     331             : 
     332       52176 :         return find_printer;
     333             : }
     334             : 
     335             : /****************************************************************************
     336             :  Close printer index by handle.
     337             : ****************************************************************************/
     338             : 
     339         956 : static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
     340             : {
     341         956 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     342             : 
     343         956 :         if (!Printer) {
     344           0 :                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
     345             :                         OUR_HANDLE(hnd)));
     346           0 :                 return false;
     347             :         }
     348             : 
     349         956 :         close_policy_hnd(p, hnd);
     350             : 
     351         956 :         return true;
     352             : }
     353             : 
     354             : /****************************************************************************
     355             :  Delete a printer given a handle.
     356             : ****************************************************************************/
     357             : 
     358          16 : static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
     359             :                                   const char *sharename,
     360             :                                   struct messaging_context *msg_ctx)
     361             : {
     362           0 :         const struct loadparm_substitution *lp_sub =
     363          16 :                 loadparm_s3_global_substitution();
     364          16 :         char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
     365          16 :         char *command = NULL;
     366           0 :         int ret;
     367          16 :         bool is_print_op = false;
     368             : 
     369             :         /* can't fail if we don't try */
     370             : 
     371          16 :         if ( !*cmd )
     372           0 :                 return WERR_OK;
     373             : 
     374          16 :         command = talloc_asprintf(ctx,
     375             :                         "%s \"%s\"",
     376             :                         cmd, sharename);
     377          16 :         if (!command) {
     378           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     379             :         }
     380          16 :         if ( token )
     381          16 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
     382             : 
     383          16 :         DEBUG(10,("Running [%s]\n", command));
     384             : 
     385             :         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
     386             : 
     387          16 :         if ( is_print_op )
     388           0 :                 become_root();
     389             : 
     390          16 :         ret = smbrun(command, NULL, NULL);
     391          16 :         if (ret == 0) {
     392             :                 /* Tell everyone we updated smb.conf. */
     393          16 :                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
     394             :         }
     395             : 
     396          16 :         if ( is_print_op )
     397           0 :                 unbecome_root();
     398             : 
     399             :         /********** END SePrintOperatorPrivlege BLOCK **********/
     400             : 
     401          16 :         DEBUGADD(10,("returned [%d]\n", ret));
     402             : 
     403          16 :         TALLOC_FREE(command);
     404             : 
     405          16 :         if (ret != 0)
     406           0 :                 return WERR_INVALID_HANDLE; /* What to return here? */
     407             : 
     408          16 :         return WERR_OK;
     409             : }
     410             : 
     411             : /****************************************************************************
     412             :  Delete a printer given a handle.
     413             : ****************************************************************************/
     414             : 
     415          16 : static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
     416             : {
     417          16 :         struct dcesrv_call_state *dce_call = p->dce_call;
     418           0 :         struct auth_session_info *session_info =
     419          16 :                 dcesrv_call_session_info(dce_call);
     420          16 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     421           0 :         WERROR result;
     422             : 
     423          16 :         if (!Printer) {
     424           0 :                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
     425             :                         OUR_HANDLE(hnd)));
     426           0 :                 return WERR_INVALID_HANDLE;
     427             :         }
     428             : 
     429             :         /*
     430             :          * It turns out that Windows allows delete printer on a handle
     431             :          * opened by an admin user, then used on a pipe handle created
     432             :          * by an anonymous user..... but they're working on security.... riiight !
     433             :          * JRA.
     434             :          */
     435             : 
     436          16 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
     437           0 :                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
     438           0 :                 return WERR_ACCESS_DENIED;
     439             :         }
     440             : 
     441             :         /* this does not need a become root since the access check has been
     442             :            done on the handle already */
     443             : 
     444          16 :         result = winreg_delete_printer_key_internal(p->mem_ctx,
     445             :                                            get_session_info_system(),
     446             :                                            p->msg_ctx,
     447          16 :                                            Printer->sharename,
     448             :                                            "");
     449          16 :         if (!W_ERROR_IS_OK(result)) {
     450           0 :                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
     451           0 :                 return WERR_INVALID_HANDLE;
     452             :         }
     453             : 
     454          16 :         result = delete_printer_hook(p->mem_ctx, session_info->security_token,
     455          16 :                                      Printer->sharename, p->msg_ctx);
     456          16 :         if (!W_ERROR_IS_OK(result)) {
     457           0 :                 return result;
     458             :         }
     459          16 :         prune_printername_cache();
     460          16 :         return WERR_OK;
     461             : }
     462             : 
     463             : /****************************************************************************
     464             :  Return the snum of a printer corresponding to an handle.
     465             : ****************************************************************************/
     466             : 
     467       24718 : static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
     468             :                              int *number, struct share_params **params)
     469             : {
     470       24718 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     471             : 
     472       24718 :         if (!Printer) {
     473           0 :                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
     474             :                         OUR_HANDLE(hnd)));
     475           0 :                 return false;
     476             :         }
     477             : 
     478       24718 :         switch (Printer->printer_type) {
     479       24718 :                 case SPLHND_PRINTER:
     480       24718 :                         DEBUG(4,("short name:%s\n", Printer->sharename));
     481       24718 :                         *number = print_queue_snum(Printer->sharename);
     482       24718 :                         return (*number != -1);
     483           0 :                 case SPLHND_SERVER:
     484           0 :                         return false;
     485           0 :                 default:
     486           0 :                         return false;
     487             :         }
     488             : }
     489             : 
     490             : /****************************************************************************
     491             :  Set printer handle type.
     492             :  Check if it's \\server or \\server\printer
     493             : ****************************************************************************/
     494             : 
     495         972 : static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
     496             : {
     497         972 :         DEBUG(3,("Setting printer type=%s\n", handlename));
     498             : 
     499             :         /* it's a print server */
     500         972 :         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
     501         122 :                 DEBUGADD(4,("Printer is a print server\n"));
     502         122 :                 Printer->printer_type = SPLHND_SERVER;
     503             :         }
     504             :         /* it's a printer (set_printer_hnd_name() will handle port monitors */
     505             :         else {
     506         850 :                 DEBUGADD(4,("Printer is a printer\n"));
     507         850 :                 Printer->printer_type = SPLHND_PRINTER;
     508             :         }
     509             : 
     510         972 :         return true;
     511             : }
     512             : 
     513         372 : static void prune_printername_cache_fn(const char *key, const char *value,
     514             :                                        time_t timeout, void *private_data)
     515             : {
     516         372 :         gencache_del(key);
     517         372 : }
     518             : 
     519         132 : static void prune_printername_cache(void)
     520             : {
     521         132 :         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
     522         132 : }
     523             : 
     524             : /****************************************************************************
     525             :  Set printer handle name..  Accept names like \\server, \\server\printer,
     526             :  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
     527             :  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
     528             :  XcvDataPort() interface.
     529             : ****************************************************************************/
     530             : 
     531         972 : static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
     532             :                                    const struct auth_session_info *session_info,
     533             :                                    struct messaging_context *msg_ctx,
     534             :                                    struct printer_handle *Printer,
     535             :                                    const char *handlename)
     536             : {
     537           0 :         int snum;
     538         972 :         int n_services=lp_numservices();
     539           0 :         char *aprinter;
     540           0 :         const char *printername;
     541         972 :         const char *servername = NULL;
     542           0 :         fstring sname;
     543         972 :         bool found = false;
     544         972 :         struct spoolss_PrinterInfo2 *info2 = NULL;
     545           0 :         WERROR result;
     546           0 :         char *p;
     547             : 
     548             :         /*
     549             :          * Hopefully nobody names his printers like this. Maybe \ or ,
     550             :          * are illegal in printer names even?
     551             :          */
     552         972 :         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
     553           0 :         char *cache_key;
     554           0 :         char *tmp;
     555             : 
     556         972 :         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
     557             :                 (unsigned long)strlen(handlename)));
     558             : 
     559         972 :         aprinter = discard_const_p(char, handlename);
     560         972 :         if ( *handlename == '\\' ) {
     561         252 :                 servername = canon_servername(handlename);
     562         252 :                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
     563         122 :                         *aprinter = '\0';
     564         122 :                         aprinter++;
     565             :                 }
     566         252 :                 if (!is_myname_or_ipaddr(servername)) {
     567          12 :                         return WERR_INVALID_PRINTER_NAME;
     568             :                 }
     569         240 :                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
     570         240 :                 if (Printer->servername == NULL) {
     571           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     572             :                 }
     573             :         }
     574             : 
     575         960 :         if (Printer->printer_type == SPLHND_SERVER) {
     576         118 :                 return WERR_OK;
     577             :         }
     578             : 
     579         842 :         if (Printer->printer_type != SPLHND_PRINTER) {
     580           0 :                 return WERR_INVALID_HANDLE;
     581             :         }
     582             : 
     583         842 :         DEBUGADD(5, ("searching for [%s]\n", aprinter));
     584             : 
     585         842 :         p = strchr(aprinter, ',');
     586         842 :         if (p != NULL) {
     587         504 :                 char *p2 = p;
     588         504 :                 p++;
     589         504 :                 if (*p == ' ') {
     590         308 :                         p++;
     591             :                 }
     592         504 :                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
     593         140 :                         *p2 = '\0';
     594         364 :                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
     595         140 :                         *p2 = '\0';
     596             :                 }
     597             :         }
     598             : 
     599         842 :         if (p) {
     600         504 :                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
     601             :         }
     602             : 
     603             :         /* check for the Port Monitor Interface */
     604         842 :         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
     605           0 :                 Printer->printer_type = SPLHND_PORTMON_TCP;
     606           0 :                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
     607           0 :                 found = true;
     608             :         }
     609         842 :         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
     610           0 :                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
     611           0 :                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
     612           0 :                 found = true;
     613             :         }
     614             : 
     615         842 :         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
     616         842 :         if (cache_key == NULL) {
     617           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     618             :         }
     619             : 
     620             :         /*
     621             :          * With hundreds of printers, the "for" loop iterating all
     622             :          * shares can be quite expensive, as it is done on every
     623             :          * OpenPrinter. The loop maps "aprinter" to "sname", the
     624             :          * result of which we cache in gencache.
     625             :          */
     626         842 :         if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
     627         462 :                 found = (strcmp(tmp, printer_not_found) != 0);
     628         462 :                 if (!found) {
     629          32 :                         DEBUG(4, ("Printer %s not found\n", aprinter));
     630          32 :                         TALLOC_FREE(tmp);
     631          32 :                         return WERR_INVALID_PRINTER_NAME;
     632             :                 }
     633         430 :                 fstrcpy(sname, tmp);
     634         430 :                 TALLOC_FREE(tmp);
     635             :         }
     636             : 
     637             :         /* Search all sharenames first as this is easier than pulling
     638             :            the printer_info_2 off of disk. Don't use find_service() since
     639             :            that calls out to map_username() */
     640             : 
     641             :         /* do another loop to look for printernames */
     642       23566 :         for (snum = 0; !found && snum < n_services; snum++) {
     643       22848 :                 const char *printer = lp_const_servicename(snum);
     644             : 
     645             :                 /* no point going on if this is not a printer */
     646       22848 :                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
     647       20970 :                         continue;
     648             :                 }
     649             : 
     650             :                 /* ignore [printers] share */
     651        1878 :                 if (strequal(printer, "printers")) {
     652           0 :                         continue;
     653             :                 }
     654             : 
     655        1878 :                 fstrcpy(sname, printer);
     656        1878 :                 if (strequal(aprinter, printer)) {
     657          84 :                         found = true;
     658          84 :                         break;
     659             :                 }
     660             : 
     661             :                 /* no point looking up the printer object if
     662             :                    we aren't allowing printername != sharename */
     663        1794 :                 if (lp_force_printername(snum)) {
     664           0 :                         continue;
     665             :                 }
     666             : 
     667        1794 :                 result = winreg_get_printer_internal(mem_ctx,
     668             :                                             session_info,
     669             :                                             msg_ctx,
     670             :                                             sname,
     671             :                                             &info2);
     672        1794 :                 if ( !W_ERROR_IS_OK(result) ) {
     673          54 :                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
     674             :                                  sname, win_errstr(result)));
     675          54 :                         continue;
     676             :                 }
     677             : 
     678        1740 :                 printername = strrchr(info2->printername, '\\');
     679        1740 :                 if (printername == NULL) {
     680        1740 :                         printername = info2->printername;
     681             :                 } else {
     682           0 :                         printername++;
     683             :                 }
     684             : 
     685        1740 :                 if (strequal(printername, aprinter)) {
     686           8 :                         found = true;
     687           8 :                         break;
     688             :                 }
     689             : 
     690        1732 :                 DEBUGADD(10, ("printername: %s\n", printername));
     691             : 
     692        1732 :                 TALLOC_FREE(info2);
     693             :         }
     694             : 
     695         810 :         if (!found) {
     696         288 :                 gencache_set(cache_key, printer_not_found,
     697         288 :                              time(NULL) + 300);
     698         288 :                 TALLOC_FREE(cache_key);
     699         288 :                 DEBUGADD(4,("Printer not found\n"));
     700         288 :                 return WERR_INVALID_PRINTER_NAME;
     701             :         }
     702             : 
     703         522 :         gencache_set(cache_key, sname, time(NULL) + 300);
     704         522 :         TALLOC_FREE(cache_key);
     705             : 
     706         522 :         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
     707             : 
     708         522 :         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
     709             : 
     710         522 :         return WERR_OK;
     711             : }
     712             : 
     713             : /****************************************************************************
     714             :  Find first available printer slot. creates a printer handle for you.
     715             :  ****************************************************************************/
     716             : 
     717         972 : static WERROR open_printer_hnd(struct pipes_struct *p,
     718             :                                struct policy_handle *hnd,
     719             :                                const char *name,
     720             :                                uint32_t access_granted)
     721             : {
     722           0 :         struct printer_handle *new_printer;
     723           0 :         WERROR result;
     724             : 
     725         972 :         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
     726             : 
     727         972 :         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
     728         972 :         if (new_printer == NULL) {
     729           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     730             :         }
     731         972 :         talloc_set_destructor(new_printer, printer_entry_destructor);
     732             : 
     733             :         /* This also steals the printer_handle on the policy_handle */
     734         972 :         if (!create_policy_hnd(p, hnd, 0, new_printer)) {
     735           0 :                 TALLOC_FREE(new_printer);
     736           0 :                 return WERR_INVALID_HANDLE;
     737             :         }
     738             : 
     739             :         /* Add to the internal list. */
     740         972 :         DLIST_ADD(printers_list, new_printer);
     741             : 
     742         972 :         new_printer->notify.option=NULL;
     743             : 
     744         972 :         if (!set_printer_hnd_printertype(new_printer, name)) {
     745           0 :                 close_printer_handle(p, hnd);
     746           0 :                 return WERR_INVALID_HANDLE;
     747             :         }
     748             : 
     749         972 :         result = set_printer_hnd_name(p->mem_ctx,
     750             :                                       get_session_info_system(),
     751             :                                       p->msg_ctx,
     752             :                                       new_printer, name);
     753         972 :         if (!W_ERROR_IS_OK(result)) {
     754         332 :                 close_printer_handle(p, hnd);
     755         332 :                 return result;
     756             :         }
     757             : 
     758         640 :         new_printer->access_granted = access_granted;
     759             : 
     760         640 :         DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
     761             : 
     762         640 :         return WERR_OK;
     763             : }
     764             : 
     765             : /***************************************************************************
     766             :  check to see if the client notify handle is monitoring the notification
     767             :  given by (notify_type, notify_field).
     768             :  **************************************************************************/
     769             : 
     770           0 : static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
     771             :                                       uint16_t notify_field)
     772             : {
     773           0 :         return true;
     774             : }
     775             : 
     776           0 : static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
     777             :                                 uint16_t notify_field)
     778             : {
     779           0 :         struct spoolss_NotifyOption *option = p->notify.option;
     780           0 :         uint32_t i, j;
     781             : 
     782             :         /*
     783             :          * Flags should always be zero when the change notify
     784             :          * is registered by the client's spooler.  A user Win32 app
     785             :          * might use the flags though instead of the NOTIFY_OPTION_INFO
     786             :          * --jerry
     787             :          */
     788             : 
     789           0 :         if (!option) {
     790           0 :                 return false;
     791             :         }
     792             : 
     793           0 :         if (p->notify.flags)
     794           0 :                 return is_monitoring_event_flags(
     795             :                         p->notify.flags, notify_type, notify_field);
     796             : 
     797           0 :         for (i = 0; i < option->count; i++) {
     798             : 
     799             :                 /* Check match for notify_type */
     800             : 
     801           0 :                 if (option->types[i].type != notify_type)
     802           0 :                         continue;
     803             : 
     804             :                 /* Check match for field */
     805             : 
     806           0 :                 for (j = 0; j < option->types[i].count; j++) {
     807           0 :                         if (option->types[i].fields[j].field == notify_field) {
     808           0 :                                 return true;
     809             :                         }
     810             :                 }
     811             :         }
     812             : 
     813           0 :         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
     814             :                    p->servername, p->sharename, notify_type, notify_field));
     815             : 
     816           0 :         return false;
     817             : }
     818             : 
     819             : #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
     820             :         _data->data.integer[0] = _integer; \
     821             :         _data->data.integer[1] = 0;
     822             : 
     823             : 
     824             : #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
     825             :         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
     826             :         if (!_data->data.string.string) {\
     827             :                 _data->data.string.size = 0; \
     828             :         } \
     829             :         _data->data.string.size = strlen_m_term(_p) * 2;
     830             : 
     831             : #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
     832             :         _data->data.devmode.devmode = _devmode;
     833             : 
     834           0 : static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
     835             :                                    struct tm *t,
     836             :                                    const char **pp,
     837             :                                    uint32_t *plen)
     838             : {
     839           0 :         struct spoolss_Time st;
     840           0 :         uint32_t len = 16;
     841           0 :         char *p;
     842             : 
     843           0 :         if (!init_systemtime(&st, t)) {
     844           0 :                 return;
     845             :         }
     846             : 
     847           0 :         p = talloc_array(mem_ctx, char, len);
     848           0 :         if (!p) {
     849           0 :                 return;
     850             :         }
     851             : 
     852             :         /*
     853             :          * Systemtime must be linearized as a set of UINT16's.
     854             :          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
     855             :          */
     856             : 
     857           0 :         SSVAL(p, 0, st.year);
     858           0 :         SSVAL(p, 2, st.month);
     859           0 :         SSVAL(p, 4, st.day_of_week);
     860           0 :         SSVAL(p, 6, st.day);
     861           0 :         SSVAL(p, 8, st.hour);
     862           0 :         SSVAL(p, 10, st.minute);
     863           0 :         SSVAL(p, 12, st.second);
     864           0 :         SSVAL(p, 14, st.millisecond);
     865             : 
     866           0 :         *pp = p;
     867           0 :         *plen = len;
     868             : }
     869             : 
     870             : /* Convert a notification message to a struct spoolss_Notify */
     871             : 
     872           0 : static void notify_one_value(struct spoolss_notify_msg *msg,
     873             :                              struct spoolss_Notify *data,
     874             :                              TALLOC_CTX *mem_ctx)
     875             : {
     876           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
     877           0 : }
     878             : 
     879           0 : static void notify_string(struct spoolss_notify_msg *msg,
     880             :                           struct spoolss_Notify *data,
     881             :                           TALLOC_CTX *mem_ctx)
     882             : {
     883             :         /* The length of the message includes the trailing \0 */
     884             : 
     885           0 :         data->data.string.size = msg->len * 2;
     886           0 :         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
     887           0 :         if (!data->data.string.string) {
     888           0 :                 data->data.string.size = 0;
     889           0 :                 return;
     890             :         }
     891             : }
     892             : 
     893           0 : static void notify_system_time(struct spoolss_notify_msg *msg,
     894             :                                struct spoolss_Notify *data,
     895             :                                TALLOC_CTX *mem_ctx)
     896             : {
     897           0 :         data->data.string.string = NULL;
     898           0 :         data->data.string.size = 0;
     899             : 
     900           0 :         if (msg->len != sizeof(time_t)) {
     901           0 :                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
     902             :                           msg->len));
     903           0 :                 return;
     904             :         }
     905             : 
     906           0 :         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
     907             :                                &data->data.string.string,
     908             :                                &data->data.string.size);
     909             : }
     910             : 
     911             : struct notify2_message_table {
     912             :         const char *name;
     913             :         void (*fn)(struct spoolss_notify_msg *msg,
     914             :                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
     915             : };
     916             : 
     917             : static struct notify2_message_table printer_notify_table[] = {
     918             :         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
     919             :         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
     920             :         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
     921             :         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
     922             :         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
     923             :         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
     924             :         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
     925             :         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
     926             :         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
     927             :         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
     928             :         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
     929             :         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
     930             :         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
     931             :         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
     932             :         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
     933             :         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
     934             :         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
     935             :         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
     936             :         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
     937             : };
     938             : 
     939             : static struct notify2_message_table job_notify_table[] = {
     940             :         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
     941             :         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
     942             :         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
     943             :         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
     944             :         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
     945             :         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
     946             :         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
     947             :         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
     948             :         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
     949             :         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
     950             :         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
     951             :         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
     952             :         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
     953             :         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
     954             :         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
     955             :         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
     956             :         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
     957             :         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
     958             :         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
     959             :         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
     960             :         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
     961             :         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
     962             :         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
     963             :         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
     964             : };
     965             : 
     966             : 
     967             : /***********************************************************************
     968             :  Allocate talloc context for container object
     969             :  **********************************************************************/
     970             : 
     971           0 : static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     972             : {
     973           0 :         if ( !ctr )
     974           0 :                 return;
     975             : 
     976           0 :         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
     977             : 
     978           0 :         return;
     979             : }
     980             : 
     981             : /***********************************************************************
     982             :  release all allocated memory and zero out structure
     983             :  **********************************************************************/
     984             : 
     985           0 : static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     986             : {
     987           0 :         if ( !ctr )
     988           0 :                 return;
     989             : 
     990           0 :         if ( ctr->ctx )
     991           0 :                 talloc_destroy(ctr->ctx);
     992             : 
     993           0 :         ZERO_STRUCTP(ctr);
     994             : 
     995           0 :         return;
     996             : }
     997             : 
     998             : /***********************************************************************
     999             :  **********************************************************************/
    1000             : 
    1001           0 : static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
    1002             : {
    1003           0 :         if ( !ctr )
    1004           0 :                 return NULL;
    1005             : 
    1006           0 :         return ctr->ctx;
    1007             : }
    1008             : 
    1009             : /***********************************************************************
    1010             :  **********************************************************************/
    1011             : 
    1012           0 : static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
    1013             : {
    1014           0 :         if ( !ctr || !ctr->msg_groups )
    1015           0 :                 return NULL;
    1016             : 
    1017           0 :         if ( idx >= ctr->num_groups )
    1018           0 :                 return NULL;
    1019             : 
    1020           0 :         return &ctr->msg_groups[idx];
    1021             : 
    1022             : }
    1023             : 
    1024             : /***********************************************************************
    1025             :  How many groups of change messages do we have ?
    1026             :  **********************************************************************/
    1027             : 
    1028           0 : static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
    1029             : {
    1030           0 :         if ( !ctr )
    1031           0 :                 return 0;
    1032             : 
    1033           0 :         return ctr->num_groups;
    1034             : }
    1035             : 
    1036             : /***********************************************************************
    1037             :  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
    1038             :  **********************************************************************/
    1039             : 
    1040           0 : static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
    1041             : {
    1042           0 :         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
    1043           0 :         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
    1044           0 :         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
    1045           0 :         uint32_t                        i, new_slot;
    1046             : 
    1047           0 :         if ( !ctr || !msg )
    1048           0 :                 return 0;
    1049             : 
    1050             :         /* loop over all groups looking for a matching printer name */
    1051             : 
    1052           0 :         for ( i=0; i<ctr->num_groups; i++ ) {
    1053           0 :                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
    1054           0 :                         break;
    1055             :         }
    1056             : 
    1057             :         /* add a new group? */
    1058             : 
    1059           0 :         if ( i == ctr->num_groups ) {
    1060           0 :                 ctr->num_groups++;
    1061             : 
    1062           0 :                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
    1063           0 :                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
    1064           0 :                         return 0;
    1065             :                 }
    1066           0 :                 ctr->msg_groups = groups;
    1067             : 
    1068             :                 /* clear the new entry and set the printer name */
    1069             : 
    1070           0 :                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
    1071           0 :                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
    1072             :         }
    1073             : 
    1074             :         /* add the change messages; 'i' is the correct index now regardless */
    1075             : 
    1076           0 :         msg_grp = &ctr->msg_groups[i];
    1077             : 
    1078           0 :         msg_grp->num_msgs++;
    1079             : 
    1080           0 :         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
    1081           0 :                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
    1082           0 :                 return 0;
    1083             :         }
    1084           0 :         msg_grp->msgs = msg_list;
    1085             : 
    1086           0 :         new_slot = msg_grp->num_msgs-1;
    1087           0 :         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
    1088             : 
    1089             :         /* need to allocate own copy of data */
    1090             : 
    1091           0 :         if ( msg->len != 0 )
    1092           0 :                 msg_grp->msgs[new_slot].notify.data = (char *)
    1093           0 :                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
    1094             : 
    1095           0 :         return ctr->num_groups;
    1096             : }
    1097             : 
    1098             : static void construct_info_data(struct spoolss_Notify *info_data,
    1099             :                                 enum spoolss_NotifyType type,
    1100             :                                 uint16_t field, int id);
    1101             : 
    1102             : /***********************************************************************
    1103             :  Send a change notification message on all handles which have a call
    1104             :  back registered
    1105             :  **********************************************************************/
    1106             : 
    1107           0 : static int build_notify2_messages(TALLOC_CTX *mem_ctx,
    1108             :                                   struct printer_handle *prn_hnd,
    1109             :                                   SPOOLSS_NOTIFY_MSG *messages,
    1110             :                                   uint32_t num_msgs,
    1111             :                                   struct spoolss_Notify **_notifies,
    1112             :                                   size_t *_count)
    1113             : {
    1114           0 :         struct spoolss_Notify *notifies;
    1115           0 :         SPOOLSS_NOTIFY_MSG *msg;
    1116           0 :         size_t count = 0;
    1117           0 :         uint32_t id;
    1118           0 :         uint32_t i;
    1119             : 
    1120           0 :         notifies = talloc_zero_array(mem_ctx,
    1121             :                                      struct spoolss_Notify, num_msgs);
    1122           0 :         if (!notifies) {
    1123           0 :                 return ENOMEM;
    1124             :         }
    1125             : 
    1126           0 :         for (i = 0; i < num_msgs; i++) {
    1127             : 
    1128           0 :                 msg = &messages[i];
    1129             : 
    1130             :                 /* Are we monitoring this event? */
    1131             : 
    1132           0 :                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
    1133           0 :                         continue;
    1134             :                 }
    1135             : 
    1136           0 :                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
    1137             :                            "for printer [%s]\n",
    1138             :                            msg->type, msg->field, prn_hnd->sharename));
    1139             : 
    1140             :                 /*
    1141             :                  * if the is a printer notification handle and not a job
    1142             :                  * notification type, then set the id to 0.
    1143             :                  * Otherwise just use what was specified in the message.
    1144             :                  *
    1145             :                  * When registering change notification on a print server
    1146             :                  * handle we always need to send back the id (snum) matching
    1147             :                  * the printer for which the change took place.
    1148             :                  * For change notify registered on a printer handle,
    1149             :                  * this does not matter and the id should be 0.
    1150             :                  *
    1151             :                  * --jerry
    1152             :                  */
    1153             : 
    1154           0 :                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
    1155           0 :                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
    1156           0 :                         id = 0;
    1157             :                 } else {
    1158           0 :                         id = msg->id;
    1159             :                 }
    1160             : 
    1161             :                 /* Convert unix jobid to smb jobid */
    1162             : 
    1163           0 :                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
    1164           0 :                         id = sysjob_to_jobid(msg->id);
    1165             : 
    1166           0 :                         if (id == -1) {
    1167           0 :                                 DEBUG(3, ("no such unix jobid %d\n",
    1168             :                                           msg->id));
    1169           0 :                                 continue;
    1170             :                         }
    1171             :                 }
    1172             : 
    1173           0 :                 construct_info_data(&notifies[count],
    1174           0 :                                     msg->type, msg->field, id);
    1175             : 
    1176           0 :                 switch(msg->type) {
    1177           0 :                 case PRINTER_NOTIFY_TYPE:
    1178           0 :                         if (printer_notify_table[msg->field].fn) {
    1179           0 :                                 printer_notify_table[msg->field].fn(msg,
    1180           0 :                                                 &notifies[count], mem_ctx);
    1181             :                         }
    1182           0 :                         break;
    1183             : 
    1184           0 :                 case JOB_NOTIFY_TYPE:
    1185           0 :                         if (job_notify_table[msg->field].fn) {
    1186           0 :                                 job_notify_table[msg->field].fn(msg,
    1187           0 :                                                 &notifies[count], mem_ctx);
    1188             :                         }
    1189           0 :                         break;
    1190             : 
    1191           0 :                 default:
    1192           0 :                         DEBUG(5, ("Unknown notification type %d\n",
    1193             :                                   msg->type));
    1194           0 :                         continue;
    1195             :                 }
    1196             : 
    1197           0 :                 count++;
    1198             :         }
    1199             : 
    1200           0 :         *_notifies = notifies;
    1201           0 :         *_count = count;
    1202             : 
    1203           0 :         return 0;
    1204             : }
    1205             : 
    1206           0 : static int send_notify2_printer(TALLOC_CTX *mem_ctx,
    1207             :                                 struct printer_handle *prn_hnd,
    1208             :                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
    1209             : {
    1210           0 :         struct spoolss_Notify *notifies;
    1211           0 :         size_t count = 0;
    1212           0 :         union spoolss_ReplyPrinterInfo info;
    1213           0 :         struct spoolss_NotifyInfo info0;
    1214           0 :         uint32_t reply_result;
    1215           0 :         NTSTATUS status;
    1216           0 :         WERROR werr;
    1217           0 :         int ret;
    1218             : 
    1219             :         /* Is there notification on this handle? */
    1220           0 :         if (prn_hnd->notify.cli_chan == NULL ||
    1221           0 :             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
    1222           0 :             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
    1223           0 :             prn_hnd->notify.cli_chan->active_connections == 0) {
    1224           0 :                 return 0;
    1225             :         }
    1226             : 
    1227           0 :         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
    1228             :                    prn_hnd->servername, prn_hnd->sharename));
    1229             : 
    1230             :         /* For this printer? Print servers always receive notifications. */
    1231           0 :         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
    1232           0 :             (!strequal(msg_group->printername, prn_hnd->sharename))) {
    1233           0 :                 return 0;
    1234             :         }
    1235             : 
    1236           0 :         DEBUG(10,("Our printer\n"));
    1237             : 
    1238             :         /* build the array of change notifications */
    1239           0 :         ret = build_notify2_messages(mem_ctx, prn_hnd,
    1240             :                                      msg_group->msgs,
    1241             :                                      msg_group->num_msgs,
    1242             :                                      &notifies, &count);
    1243           0 :         if (ret) {
    1244           0 :                 return ret;
    1245             :         }
    1246             : 
    1247           0 :         info0.version   = 0x2;
    1248           0 :         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
    1249           0 :         info0.count     = count;
    1250           0 :         info0.notifies  = notifies;
    1251             : 
    1252           0 :         info.info0 = &info0;
    1253             : 
    1254           0 :         status = dcerpc_spoolss_RouterReplyPrinterEx(
    1255           0 :                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
    1256             :                                 mem_ctx,
    1257             :                                 &prn_hnd->notify.cli_hnd,
    1258             :                                 prn_hnd->notify.change, /* color */
    1259             :                                 prn_hnd->notify.flags,
    1260             :                                 &reply_result,
    1261             :                                 0, /* reply_type, must be 0 */
    1262             :                                 info, &werr);
    1263           0 :         if (!NT_STATUS_IS_OK(status)) {
    1264           0 :                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
    1265             :                           "failed: %s\n",
    1266             :                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
    1267             :                           nt_errstr(status)));
    1268           0 :                 werr = ntstatus_to_werror(status);
    1269           0 :         } else if (!W_ERROR_IS_OK(werr)) {
    1270           0 :                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
    1271             :                           "failed: %s\n",
    1272             :                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
    1273             :                           win_errstr(werr)));
    1274             :         }
    1275           0 :         switch (reply_result) {
    1276           0 :         case 0:
    1277           0 :                 break;
    1278           0 :         case PRINTER_NOTIFY_INFO_DISCARDED:
    1279             :         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
    1280             :         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
    1281           0 :                 break;
    1282           0 :         default:
    1283           0 :                 break;
    1284             :         }
    1285             : 
    1286           0 :         return 0;
    1287             : }
    1288             : 
    1289           0 : static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
    1290             : {
    1291           0 :         struct printer_handle    *p;
    1292           0 :         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
    1293           0 :         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
    1294           0 :         int ret;
    1295             : 
    1296           0 :         if ( !msg_group ) {
    1297           0 :                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
    1298           0 :                 return;
    1299             :         }
    1300             : 
    1301           0 :         if (!msg_group->msgs) {
    1302           0 :                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
    1303           0 :                 return;
    1304             :         }
    1305             : 
    1306           0 :         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
    1307             : 
    1308             :         /* loop over all printers */
    1309             : 
    1310           0 :         for (p = printers_list; p; p = p->next) {
    1311           0 :                 ret = send_notify2_printer(mem_ctx, p, msg_group);
    1312           0 :                 if (ret) {
    1313           0 :                         goto done;
    1314             :                 }
    1315             :         }
    1316             : 
    1317           0 : done:
    1318           0 :         DEBUG(8,("send_notify2_changes: Exit...\n"));
    1319           0 :         return;
    1320             : }
    1321             : 
    1322             : /***********************************************************************
    1323             :  **********************************************************************/
    1324             : 
    1325           0 : static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
    1326             : {
    1327             : 
    1328           0 :         uint32_t tv_sec, tv_usec;
    1329           0 :         size_t offset = 0;
    1330             : 
    1331             :         /* Unpack message */
    1332             : 
    1333           0 :         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
    1334           0 :                              msg->printer);
    1335             : 
    1336           0 :         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
    1337             :                                 &tv_sec, &tv_usec,
    1338             :                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
    1339             : 
    1340           0 :         if (msg->len == 0)
    1341           0 :                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
    1342             :                            &msg->notify.value[0], &msg->notify.value[1]);
    1343             :         else
    1344           0 :                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
    1345             :                            &msg->len, &msg->notify.data);
    1346             : 
    1347           0 :         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
    1348             :                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
    1349             : 
    1350           0 :         tv->tv_sec = tv_sec;
    1351           0 :         tv->tv_usec = tv_usec;
    1352             : 
    1353           0 :         if (msg->len == 0)
    1354           0 :                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
    1355             :                           msg->notify.value[1]));
    1356             :         else
    1357           0 :                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
    1358             : 
    1359           0 :         return true;
    1360             : }
    1361             : 
    1362             : /********************************************************************
    1363             :  Receive a notify2 message list
    1364             :  ********************************************************************/
    1365             : 
    1366           0 : static void receive_notify2_message_list(struct messaging_context *msg,
    1367             :                                          void *private_data,
    1368             :                                          uint32_t msg_type,
    1369             :                                          struct server_id server_id,
    1370             :                                          DATA_BLOB *data)
    1371             : {
    1372           0 :         size_t                  msg_count, i, num_groups;
    1373           0 :         char                    *buf = (char *)data->data;
    1374           0 :         char                    *msg_ptr;
    1375           0 :         size_t                  msg_len;
    1376           0 :         SPOOLSS_NOTIFY_MSG      notify;
    1377           0 :         SPOOLSS_NOTIFY_MSG_CTR  messages;
    1378             : 
    1379           0 :         if (data->length < 4) {
    1380           0 :                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
    1381           0 :                 return;
    1382             :         }
    1383             : 
    1384           0 :         msg_count = IVAL(buf, 0);
    1385           0 :         msg_ptr = buf + 4;
    1386             : 
    1387           0 :         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
    1388             : 
    1389           0 :         if (msg_count == 0) {
    1390           0 :                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
    1391           0 :                 return;
    1392             :         }
    1393             : 
    1394             :         /* initialize the container */
    1395             : 
    1396           0 :         ZERO_STRUCT( messages );
    1397           0 :         notify_msg_ctr_init( &messages );
    1398             : 
    1399             :         /*
    1400             :          * build message groups for each printer identified
    1401             :          * in a change_notify msg.  Remember that a PCN message
    1402             :          * includes the handle returned for the srv_spoolss_replyopenprinter()
    1403             :          * call.  Therefore messages are grouped according to printer handle.
    1404             :          */
    1405             : 
    1406           0 :         for ( i=0; i<msg_count; i++ ) {
    1407           0 :                 struct timeval msg_tv;
    1408             : 
    1409           0 :                 if (msg_ptr + 4 - buf > data->length) {
    1410           0 :                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
    1411           0 :                         return;
    1412             :                 }
    1413             : 
    1414           0 :                 msg_len = IVAL(msg_ptr,0);
    1415           0 :                 msg_ptr += 4;
    1416             : 
    1417           0 :                 if (msg_ptr + msg_len - buf > data->length) {
    1418           0 :                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
    1419           0 :                         return;
    1420             :                 }
    1421             : 
    1422             :                 /* unpack messages */
    1423             : 
    1424           0 :                 ZERO_STRUCT( notify );
    1425           0 :                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
    1426           0 :                 msg_ptr += msg_len;
    1427             : 
    1428             :                 /* add to correct list in container */
    1429             : 
    1430           0 :                 notify_msg_ctr_addmsg( &messages, &notify );
    1431             : 
    1432             :                 /* free memory that might have been allocated by notify2_unpack_msg() */
    1433             : 
    1434           0 :                 if ( notify.len != 0 )
    1435           0 :                         SAFE_FREE( notify.notify.data );
    1436             :         }
    1437             : 
    1438             :         /* process each group of messages */
    1439             : 
    1440           0 :         num_groups = notify_msg_ctr_numgroups( &messages );
    1441           0 :         for ( i=0; i<num_groups; i++ )
    1442           0 :                 send_notify2_changes( &messages, i );
    1443             : 
    1444             : 
    1445             :         /* cleanup */
    1446             : 
    1447           0 :         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
    1448             :                 (uint32_t)msg_count ));
    1449             : 
    1450           0 :         notify_msg_ctr_destroy( &messages );
    1451             : 
    1452           0 :         return;
    1453             : }
    1454             : 
    1455             : /********************************************************************
    1456             :  Send a message to ourself about new driver being installed
    1457             :  so we can upgrade the information for each printer bound to this
    1458             :  driver
    1459             :  ********************************************************************/
    1460             : 
    1461           0 : static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
    1462             :                                             struct messaging_context *msg_ctx)
    1463             : {
    1464           0 :         int len = strlen(drivername);
    1465             : 
    1466           0 :         if (!len)
    1467           0 :                 return false;
    1468             : 
    1469           0 :         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
    1470             :                 drivername));
    1471             : 
    1472           0 :         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
    1473             :                            MSG_PRINTER_DRVUPGRADE,
    1474           0 :                            (const uint8_t *)drivername, len+1);
    1475             : 
    1476           0 :         return true;
    1477             : }
    1478             : 
    1479          28 : void srv_spoolss_cleanup(void)
    1480             : {
    1481           0 :         struct printer_session_counter *session_counter;
    1482             : 
    1483          28 :         for (session_counter = counter_list;
    1484          68 :              session_counter != NULL;
    1485          40 :              session_counter = counter_list) {
    1486          40 :                 DLIST_REMOVE(counter_list, session_counter);
    1487          40 :                 TALLOC_FREE(session_counter);
    1488             :         }
    1489          28 : }
    1490             : 
    1491             : /**********************************************************************
    1492             :  callback to receive a MSG_PRINTER_DRVUPGRADE message and iterate
    1493             :  over all printers, upgrading ones as necessary
    1494             :  This is now *ONLY* called inside the background lpq updater. JRA.
    1495             :  **********************************************************************/
    1496             : 
    1497           0 : void do_drv_upgrade_printer(struct messaging_context *msg,
    1498             :                             void *private_data,
    1499             :                             uint32_t msg_type,
    1500             :                             struct server_id server_id,
    1501             :                             DATA_BLOB *data)
    1502             : {
    1503           0 :         TALLOC_CTX *tmp_ctx;
    1504           0 :         const struct auth_session_info *session_info = get_session_info_system();
    1505           0 :         struct spoolss_PrinterInfo2 *pinfo2;
    1506           0 :         WERROR result;
    1507           0 :         const char *drivername;
    1508           0 :         int snum;
    1509           0 :         int n_services = lp_numservices();
    1510           0 :         struct dcerpc_binding_handle *b = NULL;
    1511             : 
    1512           0 :         tmp_ctx = talloc_new(NULL);
    1513           0 :         if (!tmp_ctx) return;
    1514             : 
    1515           0 :         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
    1516           0 :         if (!drivername) {
    1517           0 :                 DEBUG(0, ("do_drv_upgrade_printer: Out of memory ?!\n"));
    1518           0 :                 goto done;
    1519             :         }
    1520             : 
    1521           0 :         DEBUG(10, ("do_drv_upgrade_printer: "
    1522             :                    "Got message for new driver [%s]\n", drivername));
    1523             : 
    1524             :         /* Iterate the printer list */
    1525             : 
    1526           0 :         for (snum = 0; snum < n_services; snum++) {
    1527           0 :                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
    1528           0 :                         continue;
    1529             :                 }
    1530             : 
    1531             :                 /* ignore [printers] share */
    1532           0 :                 if (strequal(lp_const_servicename(snum), "printers")) {
    1533           0 :                         continue;
    1534             :                 }
    1535             : 
    1536           0 :                 if (b == NULL) {
    1537           0 :                         result = winreg_printer_binding_handle(tmp_ctx,
    1538             :                                                                session_info,
    1539             :                                                                msg,
    1540             :                                                                &b);
    1541           0 :                         if (!W_ERROR_IS_OK(result)) {
    1542           0 :                                 break;
    1543             :                         }
    1544             :                 }
    1545             : 
    1546           0 :                 result = winreg_get_printer(tmp_ctx, b,
    1547             :                                             lp_const_servicename(snum),
    1548             :                                             &pinfo2);
    1549             : 
    1550           0 :                 if (!W_ERROR_IS_OK(result)) {
    1551           0 :                         continue;
    1552             :                 }
    1553             : 
    1554           0 :                 if (!pinfo2->drivername) {
    1555           0 :                         continue;
    1556             :                 }
    1557             : 
    1558           0 :                 if (strcmp(drivername, pinfo2->drivername) != 0) {
    1559           0 :                         continue;
    1560             :                 }
    1561             : 
    1562           0 :                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
    1563             : 
    1564             :                 /* all we care about currently is the change_id */
    1565           0 :                 result = winreg_printer_update_changeid(tmp_ctx, b,
    1566           0 :                                                         pinfo2->printername);
    1567             : 
    1568           0 :                 if (!W_ERROR_IS_OK(result)) {
    1569           0 :                         DEBUG(3, ("do_drv_upgrade_printer: "
    1570             :                                   "Failed to update changeid [%s]\n",
    1571             :                                   win_errstr(result)));
    1572             :                 }
    1573             :         }
    1574             : 
    1575             :         /* all done */
    1576           0 : done:
    1577           0 :         talloc_free(tmp_ctx);
    1578             : }
    1579             : 
    1580             : /********************************************************************
    1581             :  Update the cache for all printq's with a registered client
    1582             :  connection
    1583             :  ********************************************************************/
    1584             : 
    1585           0 : void update_monitored_printq_cache(struct messaging_context *msg_ctx)
    1586             : {
    1587           0 :         struct printer_handle *printer = printers_list;
    1588           0 :         int snum;
    1589             : 
    1590             :         /* loop through all printers and update the cache where
    1591             :            a client is connected */
    1592           0 :         while (printer) {
    1593           0 :                 if ((printer->printer_type == SPLHND_PRINTER) &&
    1594           0 :                     ((printer->notify.cli_chan != NULL) &&
    1595           0 :                      (printer->notify.cli_chan->active_connections > 0))) {
    1596           0 :                         snum = print_queue_snum(printer->sharename);
    1597           0 :                         print_queue_status(msg_ctx, snum, NULL, NULL);
    1598             :                 }
    1599             : 
    1600           0 :                 printer = printer->next;
    1601             :         }
    1602             : 
    1603           0 :         return;
    1604             : }
    1605             : 
    1606             : /****************************************************************
    1607             :  _spoolss_OpenPrinter
    1608             : ****************************************************************/
    1609             : 
    1610         194 : WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
    1611             :                             struct spoolss_OpenPrinter *r)
    1612             : {
    1613           0 :         struct spoolss_OpenPrinterEx e;
    1614           0 :         struct spoolss_UserLevel1 level1;
    1615           0 :         WERROR werr;
    1616             : 
    1617         194 :         ZERO_STRUCT(level1);
    1618             : 
    1619         194 :         e.in.printername        = r->in.printername;
    1620         194 :         e.in.datatype           = r->in.datatype;
    1621         194 :         e.in.devmode_ctr        = r->in.devmode_ctr;
    1622         194 :         e.in.access_mask        = r->in.access_mask;
    1623         194 :         e.in.userlevel_ctr.level                = 1;
    1624         194 :         e.in.userlevel_ctr.user_info.level1     = &level1;
    1625             : 
    1626         194 :         e.out.handle            = r->out.handle;
    1627             : 
    1628         194 :         werr = _spoolss_OpenPrinterEx(p, &e);
    1629             : 
    1630         194 :         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
    1631             :                 /* OpenPrinterEx returns this for a bad
    1632             :                  * printer name. We must return WERR_INVALID_PRINTER_NAME
    1633             :                  * instead.
    1634             :                  */
    1635           4 :                 werr = WERR_INVALID_PRINTER_NAME;
    1636             :         }
    1637             : 
    1638         194 :         return werr;
    1639             : }
    1640             : 
    1641        2850 : static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
    1642             :                               struct spoolss_DeviceMode *orig,
    1643             :                               struct spoolss_DeviceMode **dest)
    1644             : {
    1645           0 :         struct spoolss_DeviceMode *dm;
    1646             : 
    1647        2850 :         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
    1648        2850 :         if (!dm) {
    1649           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1650             :         }
    1651             : 
    1652             :         /* copy all values, then duplicate strings and structs */
    1653        2850 :         *dm = *orig;
    1654             : 
    1655        2850 :         dm->devicename = talloc_strdup(dm, orig->devicename);
    1656        2850 :         if (!dm->devicename) {
    1657           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1658             :         }
    1659        2850 :         dm->formname = talloc_strdup(dm, orig->formname);
    1660        2850 :         if (!dm->formname) {
    1661           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1662             :         }
    1663        2850 :         if (orig->driverextra_data.data) {
    1664        1392 :                 dm->driverextra_data.data =
    1665        1392 :                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
    1666             :                                         orig->driverextra_data.length);
    1667        1392 :                 if (!dm->driverextra_data.data) {
    1668           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1669             :                 }
    1670             :         }
    1671             : 
    1672        2850 :         *dest = dm;
    1673        2850 :         return WERR_OK;
    1674             : }
    1675             : 
    1676             : /****************************************************************
    1677             :  _spoolss_OpenPrinterEx
    1678             : ****************************************************************/
    1679             : 
    1680         988 : WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
    1681             :                               struct spoolss_OpenPrinterEx *r)
    1682             : {
    1683         988 :         struct dcesrv_call_state *dce_call = p->dce_call;
    1684         988 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    1685           0 :         const struct tsocket_address *remote_address =
    1686         988 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    1687           0 :         struct auth_session_info *session_info =
    1688         988 :                 dcesrv_call_session_info(dce_call);
    1689           0 :         int snum;
    1690           0 :         char *raddr;
    1691           0 :         char *rhost;
    1692         988 :         struct printer_handle *Printer=NULL;
    1693           0 :         WERROR result;
    1694           0 :         int rc;
    1695             : 
    1696         988 :         if (!r->in.printername) {
    1697           0 :                 return WERR_INVALID_PARAMETER;
    1698             :         }
    1699             : 
    1700         988 :         if (!*r->in.printername) {
    1701           8 :                 return WERR_INVALID_PARAMETER;
    1702             :         }
    1703             : 
    1704         980 :         if (r->in.userlevel_ctr.level > 3) {
    1705           0 :                 return WERR_INVALID_PARAMETER;
    1706             :         }
    1707         980 :         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
    1708         956 :             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
    1709         956 :             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
    1710          24 :                 return WERR_INVALID_PARAMETER;
    1711             :         }
    1712             : 
    1713             :         /*
    1714             :          * The printcap printer share inventory is updated on client
    1715             :          * enumeration. For clients that do not perform enumeration prior to
    1716             :          * access, such as cupssmbadd, we reinitialise the printer share
    1717             :          * inventory on open as well.
    1718             :          */
    1719         956 :         become_root();
    1720         956 :         delete_and_reload_printers();
    1721         956 :         unbecome_root();
    1722             : 
    1723             :         /* some sanity check because you can open a printer or a print server */
    1724             :         /* aka: \\server\printer or \\server */
    1725             : 
    1726         956 :         DEBUGADD(3,("checking name: %s\n", r->in.printername));
    1727             : 
    1728         956 :         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
    1729         956 :         if (!W_ERROR_IS_OK(result)) {
    1730         332 :                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
    1731             :                         "for printer %s\n", r->in.printername));
    1732         332 :                 ZERO_STRUCTP(r->out.handle);
    1733         332 :                 return result;
    1734             :         }
    1735             : 
    1736         624 :         Printer = find_printer_index_by_hnd(p, r->out.handle);
    1737         624 :         if ( !Printer ) {
    1738           0 :                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
    1739             :                         "handle we created for printer %s\n", r->in.printername));
    1740           0 :                 close_printer_handle(p, r->out.handle);
    1741           0 :                 ZERO_STRUCTP(r->out.handle);
    1742           0 :                 return WERR_INVALID_PARAMETER;
    1743             :         }
    1744             : 
    1745             :         /*
    1746             :          * First case: the user is opening the print server:
    1747             :          *
    1748             :          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
    1749             :          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
    1750             :          *
    1751             :          * Then both Win2k and WinNT clients try an OpenPrinterEx with
    1752             :          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
    1753             :          * or if the user is listed in the smb.conf printer admin parameter.
    1754             :          *
    1755             :          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
    1756             :          * client view printer folder, but does not show the MSAPW.
    1757             :          *
    1758             :          * Note: this test needs code to check access rights here too. Jeremy
    1759             :          * could you look at this?
    1760             :          *
    1761             :          * Second case: the user is opening a printer:
    1762             :          * NT doesn't let us connect to a printer if the connecting user
    1763             :          * doesn't have print permission.
    1764             :          *
    1765             :          * Third case: user is opening a Port Monitor
    1766             :          * access checks same as opening a handle to the print server.
    1767             :          */
    1768             : 
    1769         624 :         switch (Printer->printer_type )
    1770             :         {
    1771         118 :         case SPLHND_SERVER:
    1772             :         case SPLHND_PORTMON_TCP:
    1773             :         case SPLHND_PORTMON_LOCAL:
    1774             :                 /* Printserver handles use global struct... */
    1775             : 
    1776         118 :                 snum = -1;
    1777             : 
    1778         118 :                 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
    1779          90 :                         r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
    1780          90 :                         r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
    1781             :                 }
    1782             : 
    1783             :                 /* Map standard access rights to object specific access rights */
    1784             : 
    1785         118 :                 se_map_standard(&r->in.access_mask,
    1786             :                                 &printserver_std_mapping);
    1787             : 
    1788             :                 /* Deny any object specific bits that don't apply to print
    1789             :                    servers (i.e printer and job specific bits) */
    1790             : 
    1791         118 :                 r->in.access_mask &= SEC_MASK_SPECIFIC;
    1792             : 
    1793         118 :                 if (r->in.access_mask &
    1794             :                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
    1795           0 :                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
    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             :                 /* Allow admin access */
    1802             : 
    1803         118 :                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
    1804             :                 {
    1805          94 :                         if (!lp_show_add_printer_wizard()) {
    1806           0 :                                 close_printer_handle(p, r->out.handle);
    1807           0 :                                 ZERO_STRUCTP(r->out.handle);
    1808           0 :                                 return WERR_ACCESS_DENIED;
    1809             :                         }
    1810             : 
    1811             :                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    1812             :                            and not a printer admin, then fail */
    1813             : 
    1814          94 :                         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    1815           2 :                             !security_token_has_privilege(
    1816           2 :                                     session_info->security_token,
    1817           0 :                                     SEC_PRIV_PRINT_OPERATOR) &&
    1818           0 :                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
    1819           0 :                                                 session_info->security_token)) {
    1820           0 :                                 close_printer_handle(p, r->out.handle);
    1821           0 :                                 ZERO_STRUCTP(r->out.handle);
    1822           0 :                                 DEBUG(3,("access DENIED as user is not root, "
    1823             :                                         "has no printoperator privilege and is "
    1824             :                                         "not a member of the printoperator builtin group\n"));
    1825           0 :                                 return WERR_ACCESS_DENIED;
    1826             :                         }
    1827             : 
    1828          94 :                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
    1829             :                 }
    1830             :                 else
    1831             :                 {
    1832          24 :                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
    1833             :                 }
    1834             : 
    1835         118 :                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
    1836             :                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
    1837             : 
    1838         118 :                 break;
    1839             : 
    1840         506 :         case SPLHND_PRINTER:
    1841             :                 /* NT doesn't let us connect to a printer if the connecting user
    1842             :                    doesn't have print permission.  */
    1843             : 
    1844         506 :                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
    1845           0 :                         close_printer_handle(p, r->out.handle);
    1846           0 :                         ZERO_STRUCTP(r->out.handle);
    1847           0 :                         return WERR_INVALID_HANDLE;
    1848             :                 }
    1849             : 
    1850         506 :                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
    1851         170 :                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
    1852             :                 }
    1853             : 
    1854         506 :                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
    1855             : 
    1856             :                 /* map an empty access mask to the minimum access mask */
    1857         506 :                 if (r->in.access_mask == 0x0)
    1858         296 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1859             : 
    1860             :                 /*
    1861             :                  * If we are not serving the printer driver for this printer,
    1862             :                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
    1863             :                  * will keep NT clients happy  --jerry
    1864             :                  */
    1865             : 
    1866         506 :                 if (lp_use_client_driver(snum)
    1867           0 :                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
    1868             :                 {
    1869           0 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1870             :                 }
    1871             : 
    1872             :                 /* check smb.conf parameters and the the sec_desc */
    1873         506 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    1874             :                                                          p->mem_ctx);
    1875         506 :                 if (raddr == NULL) {
    1876           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1877             :                 }
    1878             : 
    1879         506 :                 rc = get_remote_hostname(remote_address,
    1880             :                                          &rhost,
    1881             :                                          p->mem_ctx);
    1882         506 :                 if (rc < 0) {
    1883           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1884             :                 }
    1885         506 :                 if (strequal(rhost, "UNKNOWN")) {
    1886         506 :                         rhost = raddr;
    1887             :                 }
    1888             : 
    1889         506 :                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
    1890             :                                   rhost, raddr)) {
    1891           0 :                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
    1892           0 :                         ZERO_STRUCTP(r->out.handle);
    1893           0 :                         return WERR_ACCESS_DENIED;
    1894             :                 }
    1895             : 
    1896         506 :                 if (!user_ok_token(session_info->unix_info->unix_name,
    1897         506 :                                    session_info->info->domain_name,
    1898         506 :                                    session_info->security_token, snum) ||
    1899         506 :                     !W_ERROR_IS_OK(print_access_check(session_info,
    1900             :                                                       p->msg_ctx,
    1901             :                                                       snum,
    1902             :                                                       r->in.access_mask))) {
    1903           0 :                         DEBUG(3, ("access DENIED for printer open\n"));
    1904           0 :                         close_printer_handle(p, r->out.handle);
    1905           0 :                         ZERO_STRUCTP(r->out.handle);
    1906           0 :                         return WERR_ACCESS_DENIED;
    1907             :                 }
    1908             : 
    1909         506 :                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
    1910           4 :                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
    1911           4 :                         close_printer_handle(p, r->out.handle);
    1912           4 :                         ZERO_STRUCTP(r->out.handle);
    1913           4 :                         return WERR_ACCESS_DENIED;
    1914             :                 }
    1915             : 
    1916         502 :                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
    1917         170 :                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
    1918             :                 else
    1919         332 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1920             : 
    1921         502 :                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
    1922             :                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
    1923             : 
    1924         502 :                 winreg_create_printer_internal(p->mem_ctx,
    1925             :                                       get_session_info_system(),
    1926             :                                       p->msg_ctx,
    1927             :                                       lp_const_servicename(snum));
    1928             : 
    1929         502 :                 break;
    1930             : 
    1931           0 :         default:
    1932             :                 /* sanity check to prevent programmer error */
    1933           0 :                 ZERO_STRUCTP(r->out.handle);
    1934           0 :                 return WERR_INVALID_HANDLE;
    1935             :         }
    1936             : 
    1937         620 :         Printer->access_granted = r->in.access_mask;
    1938             : 
    1939             :         /*
    1940             :          * If the client sent a devmode in the OpenPrinter() call, then
    1941             :          * save it here in case we get a job submission on this handle
    1942             :          */
    1943             : 
    1944         620 :          if ((Printer->printer_type != SPLHND_SERVER)
    1945         502 :           && (r->in.devmode_ctr.devmode != NULL)) {
    1946           8 :                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
    1947             :                                 &Printer->devmode);
    1948             :          }
    1949             : 
    1950         620 :         return WERR_OK;
    1951             : }
    1952             : 
    1953             : /****************************************************************
    1954             :  _spoolss_ClosePrinter
    1955             : ****************************************************************/
    1956             : 
    1957         620 : WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
    1958             :                              struct spoolss_ClosePrinter *r)
    1959             : {
    1960         620 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    1961             : 
    1962         620 :         if (Printer && Printer->document_started) {
    1963           0 :                 struct spoolss_EndDocPrinter e;
    1964             : 
    1965          28 :                 e.in.handle = r->in.handle;
    1966             : 
    1967          28 :                 _spoolss_EndDocPrinter(p, &e);
    1968             :         }
    1969             : 
    1970         620 :         if (!close_printer_handle(p, r->in.handle))
    1971           0 :                 return WERR_INVALID_HANDLE;
    1972             : 
    1973             :         /* clear the returned printer handle.  Observed behavior
    1974             :            from Win2k server.  Don't think this really matters.
    1975             :            Previous code just copied the value of the closed
    1976             :            handle.    --jerry */
    1977             : 
    1978         620 :         ZERO_STRUCTP(r->out.handle);
    1979             : 
    1980         620 :         return WERR_OK;
    1981             : }
    1982             : 
    1983             : /****************************************************************
    1984             :  _spoolss_DeletePrinter
    1985             : ****************************************************************/
    1986             : 
    1987          16 : WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
    1988             :                               struct spoolss_DeletePrinter *r)
    1989             : {
    1990          16 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    1991           0 :         WERROR result;
    1992           0 :         int snum;
    1993             : 
    1994          16 :         if (Printer && Printer->document_started) {
    1995           0 :                 struct spoolss_EndDocPrinter e;
    1996             : 
    1997           0 :                 e.in.handle = r->in.handle;
    1998             : 
    1999           0 :                 _spoolss_EndDocPrinter(p, &e);
    2000             :         }
    2001             : 
    2002          16 :         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
    2003          16 :                 winreg_delete_printer_key_internal(p->mem_ctx,
    2004             :                                           get_session_info_system(),
    2005             :                                           p->msg_ctx,
    2006             :                                           lp_const_servicename(snum),
    2007             :                                           "");
    2008             :         }
    2009             : 
    2010          16 :         result = delete_printer_handle(p, r->in.handle);
    2011             : 
    2012          16 :         return result;
    2013             : }
    2014             : 
    2015             : /*******************************************************************
    2016             :  * static function to lookup the version id corresponding to an
    2017             :  * long architecture string
    2018             :  ******************************************************************/
    2019             : 
    2020             : static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
    2021             :                                    SPOOLSS_DRIVER_VERSION_NT35,
    2022             :                                    SPOOLSS_DRIVER_VERSION_NT4,
    2023             :                                    SPOOLSS_DRIVER_VERSION_200X,
    2024             :                                    -1};
    2025             : 
    2026           0 : static int get_version_id(const char *arch)
    2027             : {
    2028           0 :         int i;
    2029             : 
    2030           0 :         for (i=0; archi_table[i].long_archi != NULL; i++)
    2031             :         {
    2032           0 :                 if (strcmp(arch, archi_table[i].long_archi) == 0)
    2033           0 :                         return (archi_table[i].version);
    2034             :         }
    2035             : 
    2036           0 :         return -1;
    2037             : }
    2038             : 
    2039             : /****************************************************************
    2040             :  _spoolss_DeletePrinterDriver
    2041             : ****************************************************************/
    2042             : 
    2043           0 : WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
    2044             :                                     struct spoolss_DeletePrinterDriver *r)
    2045             : {
    2046             : 
    2047           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2048           0 :         struct auth_session_info *session_info =
    2049           0 :                 dcesrv_call_session_info(dce_call);
    2050           0 :         struct spoolss_DriverInfo8 *info = NULL;
    2051           0 :         int                             version;
    2052           0 :         WERROR                          status;
    2053           0 :         struct dcerpc_binding_handle *b;
    2054           0 :         TALLOC_CTX *tmp_ctx = NULL;
    2055           0 :         int i;
    2056           0 :         bool found;
    2057             : 
    2058             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    2059             :            and not a printer admin, then fail */
    2060             : 
    2061           0 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    2062           0 :             !security_token_has_privilege(session_info->security_token,
    2063             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    2064           0 :                 return WERR_ACCESS_DENIED;
    2065             :         }
    2066             : 
    2067           0 :         if (r->in.architecture == NULL || r->in.driver == NULL) {
    2068           0 :                 return WERR_INVALID_ENVIRONMENT;
    2069             :         }
    2070             : 
    2071             :         /* check that we have a valid driver name first */
    2072             : 
    2073           0 :         if ((version = get_version_id(r->in.architecture)) == -1) {
    2074           0 :                 return WERR_INVALID_ENVIRONMENT;
    2075             :         }
    2076             : 
    2077           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    2078           0 :         if (!tmp_ctx) {
    2079           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2080             :         }
    2081             : 
    2082           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    2083             :                                                get_session_info_system(),
    2084             :                                                p->msg_ctx,
    2085             :                                                &b);
    2086           0 :         if (!W_ERROR_IS_OK(status)) {
    2087           0 :                 goto done;
    2088             :         }
    2089             : 
    2090           0 :         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
    2091           0 :                 status = winreg_get_driver(tmp_ctx, b,
    2092             :                                            r->in.architecture, r->in.driver,
    2093           0 :                                            drv_cversion[i], &info);
    2094           0 :                 if (!W_ERROR_IS_OK(status)) {
    2095           0 :                         DEBUG(5, ("skipping del of driver with version %d\n",
    2096             :                                   drv_cversion[i]));
    2097           0 :                         continue;
    2098             :                 }
    2099           0 :                 found = true;
    2100             : 
    2101           0 :                 if (printer_driver_in_use(tmp_ctx, b, info)) {
    2102           0 :                         status = WERR_PRINTER_DRIVER_IN_USE;
    2103           0 :                         goto done;
    2104             :                 }
    2105             : 
    2106           0 :                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
    2107           0 :                 if (!W_ERROR_IS_OK(status)) {
    2108           0 :                         DEBUG(0, ("failed del of driver with version %d\n",
    2109             :                                   drv_cversion[i]));
    2110           0 :                         goto done;
    2111             :                 }
    2112             :         }
    2113           0 :         if (found == false) {
    2114           0 :                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
    2115           0 :                 status = WERR_UNKNOWN_PRINTER_DRIVER;
    2116             :         } else {
    2117           0 :                 status = WERR_OK;
    2118             :         }
    2119             : 
    2120           0 : done:
    2121           0 :         talloc_free(tmp_ctx);
    2122             : 
    2123           0 :         return status;
    2124             : }
    2125             : 
    2126           0 : static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
    2127             :                                   struct pipes_struct *p,
    2128             :                                   struct spoolss_DeletePrinterDriverEx *r,
    2129             :                                   struct dcerpc_binding_handle *b,
    2130             :                                   struct spoolss_DriverInfo8 *info)
    2131             : {
    2132           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2133           0 :         struct auth_session_info *session_info =
    2134           0 :                 dcesrv_call_session_info(dce_call);
    2135           0 :         WERROR status;
    2136           0 :         bool delete_files;
    2137             : 
    2138           0 :         if (printer_driver_in_use(mem_ctx, b, info)) {
    2139           0 :                 status = WERR_PRINTER_DRIVER_IN_USE;
    2140           0 :                 goto done;
    2141             :         }
    2142             : 
    2143             :         /*
    2144             :          * we have a couple of cases to consider.
    2145             :          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
    2146             :          *     then the delete should fail if **any** files overlap with
    2147             :          *     other drivers
    2148             :          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
    2149             :          *     non-overlapping files
    2150             :          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
    2151             :          *     are set, then do not delete any files
    2152             :          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
    2153             :          */
    2154             : 
    2155           0 :         delete_files = r->in.delete_flags
    2156           0 :                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
    2157             : 
    2158             : 
    2159           0 :         if (delete_files) {
    2160           0 :                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
    2161           0 :                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
    2162           0 :                         status = WERR_PRINTER_DRIVER_IN_USE;
    2163           0 :                         goto done;
    2164             :                 }
    2165             :                 /*
    2166             :                  * printer_driver_files_in_use() has trimmed overlapping files
    2167             :                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
    2168             :                  */
    2169             :         }
    2170             : 
    2171             : 
    2172           0 :         status = winreg_del_driver(mem_ctx, b, info, info->version);
    2173           0 :         if (!W_ERROR_IS_OK(status)) {
    2174           0 :                 goto done;
    2175             :         }
    2176             : 
    2177             :         /*
    2178             :          * now delete any associated files if delete_files is
    2179             :          * true. Even if this part fails, we return success
    2180             :          * because the driver does not exist any more
    2181             :          */
    2182           0 :         if (delete_files) {
    2183           0 :                 delete_driver_files(session_info, info);
    2184             :         }
    2185             : 
    2186           0 : done:
    2187           0 :         return status;
    2188             : }
    2189             : 
    2190             : /****************************************************************
    2191             :  _spoolss_DeletePrinterDriverEx
    2192             : ****************************************************************/
    2193             : 
    2194           0 : WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
    2195             :                                       struct spoolss_DeletePrinterDriverEx *r)
    2196             : {
    2197           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2198           0 :         struct auth_session_info *session_info =
    2199           0 :                 dcesrv_call_session_info(dce_call);
    2200           0 :         struct spoolss_DriverInfo8 *info = NULL;
    2201           0 :         WERROR                          status;
    2202           0 :         struct dcerpc_binding_handle *b;
    2203           0 :         TALLOC_CTX *tmp_ctx = NULL;
    2204           0 :         int i;
    2205           0 :         bool found;
    2206             : 
    2207             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    2208             :            and not a printer admin, then fail */
    2209             : 
    2210           0 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    2211           0 :             !security_token_has_privilege(session_info->security_token,
    2212             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    2213           0 :                 return WERR_ACCESS_DENIED;
    2214             :         }
    2215             : 
    2216           0 :         if (r->in.architecture == NULL || r->in.driver == NULL) {
    2217           0 :                 return WERR_INVALID_ENVIRONMENT;
    2218             :         }
    2219             : 
    2220             :         /* check that we have a valid driver name first */
    2221           0 :         if (get_version_id(r->in.architecture) == -1) {
    2222             :                 /* this is what NT returns */
    2223           0 :                 return WERR_INVALID_ENVIRONMENT;
    2224             :         }
    2225             : 
    2226           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    2227           0 :         if (!tmp_ctx) {
    2228           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2229             :         }
    2230             : 
    2231           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    2232             :                                                get_session_info_system(),
    2233             :                                                p->msg_ctx,
    2234             :                                                &b);
    2235           0 :         if (!W_ERROR_IS_OK(status)) {
    2236           0 :                 goto done;
    2237             :         }
    2238             : 
    2239           0 :         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
    2240           0 :                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
    2241           0 :                  && (drv_cversion[i] != r->in.version)) {
    2242           0 :                         continue;
    2243             :                 }
    2244             : 
    2245             :                 /* check if a driver with this version exists before delete */
    2246           0 :                 status = winreg_get_driver(tmp_ctx, b,
    2247             :                                            r->in.architecture, r->in.driver,
    2248           0 :                                            drv_cversion[i], &info);
    2249           0 :                 if (!W_ERROR_IS_OK(status)) {
    2250           0 :                         DEBUG(5, ("skipping del of driver with version %d\n",
    2251             :                                   drv_cversion[i]));
    2252           0 :                         continue;
    2253             :                 }
    2254           0 :                 found = true;
    2255             : 
    2256           0 :                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
    2257           0 :                 if (!W_ERROR_IS_OK(status)) {
    2258           0 :                         DEBUG(0, ("failed to delete driver with version %d\n",
    2259             :                                   drv_cversion[i]));
    2260           0 :                         goto done;
    2261             :                 }
    2262             :         }
    2263           0 :         if (found == false) {
    2264           0 :                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
    2265           0 :                 status = WERR_UNKNOWN_PRINTER_DRIVER;
    2266             :         } else {
    2267           0 :                 status = WERR_OK;
    2268             :         }
    2269             : 
    2270           0 : done:
    2271           0 :         talloc_free(tmp_ctx);
    2272           0 :         return status;
    2273             : }
    2274             : 
    2275             : 
    2276             : /********************************************************************
    2277             :  GetPrinterData on a printer server Handle.
    2278             : ********************************************************************/
    2279             : 
    2280         404 : static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
    2281             :                                             const char *value,
    2282             :                                             enum winreg_Type *type,
    2283             :                                             union spoolss_PrinterData *data)
    2284             : {
    2285         404 :         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
    2286             : 
    2287         404 :         if (!strcasecmp_m(value, "W3SvcInstalled")) {
    2288          28 :                 *type = REG_DWORD;
    2289          28 :                 SIVAL(&data->value, 0, 0x00);
    2290          28 :                 return WERR_OK;
    2291             :         }
    2292             : 
    2293         376 :         if (!strcasecmp_m(value, "BeepEnabled")) {
    2294          24 :                 *type = REG_DWORD;
    2295          24 :                 SIVAL(&data->value, 0, 0x00);
    2296          24 :                 return WERR_OK;
    2297             :         }
    2298             : 
    2299         352 :         if (!strcasecmp_m(value, "EventLog")) {
    2300          24 :                 *type = REG_DWORD;
    2301             :                 /* formally was 0x1b */
    2302          24 :                 SIVAL(&data->value, 0, 0x00);
    2303          24 :                 return WERR_OK;
    2304             :         }
    2305             : 
    2306         328 :         if (!strcasecmp_m(value, "NetPopup")) {
    2307           0 :                 *type = REG_DWORD;
    2308           0 :                 SIVAL(&data->value, 0, 0x00);
    2309           0 :                 return WERR_OK;
    2310             :         }
    2311             : 
    2312         328 :         if (!strcasecmp_m(value, "MajorVersion")) {
    2313          28 :                 *type = REG_DWORD;
    2314             : 
    2315             :                 /* Windows NT 4.0 seems to not allow uploading of drivers
    2316             :                    to a server that reports 0x3 as the MajorVersion.
    2317             :                    need to investigate more how Win2k gets around this .
    2318             :                    -- jerry */
    2319             : 
    2320          28 :                 if (RA_WINNT == get_remote_arch()) {
    2321           0 :                         SIVAL(&data->value, 0, 0x02);
    2322             :                 } else {
    2323          28 :                         SIVAL(&data->value, 0, 0x03);
    2324             :                 }
    2325             : 
    2326          28 :                 return WERR_OK;
    2327             :         }
    2328             : 
    2329         300 :         if (!strcasecmp_m(value, "MinorVersion")) {
    2330          24 :                 *type = REG_DWORD;
    2331          24 :                 SIVAL(&data->value, 0, 0x00);
    2332          24 :                 return WERR_OK;
    2333             :         }
    2334             : 
    2335             :         /* REG_BINARY
    2336             :          *  uint32_t size        = 0x114
    2337             :          *  uint32_t major       = 5
    2338             :          *  uint32_t minor       = [0|1]
    2339             :          *  uint32_t build       = [2195|2600]
    2340             :          *  extra unicode string = e.g. "Service Pack 3"
    2341             :          */
    2342         276 :         if (!strcasecmp_m(value, "OSVersion")) {
    2343           0 :                 DATA_BLOB blob;
    2344           0 :                 enum ndr_err_code ndr_err;
    2345           0 :                 struct spoolss_OSVersion os;
    2346             : 
    2347             :                 /*
    2348             :                  * Set the default OSVersion to:
    2349             :                  *
    2350             :                  *     Windows Server 2003R2 SP2 (5.2.3790)
    2351             :                  *
    2352             :                  * used to be Windows 2000 (5.0.2195)
    2353             :                  */
    2354          40 :                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2355             :                                                       "spoolss", "os_major",
    2356             :                                                       GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
    2357          40 :                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2358             :                                                       "spoolss", "os_minor",
    2359             :                                                       GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
    2360          40 :                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2361             :                                                       "spoolss", "os_build",
    2362             :                                                       GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
    2363          40 :                 os.extra_string         = ""; /* leave extra string empty */
    2364             : 
    2365          40 :                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
    2366             :                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
    2367          40 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    2368           0 :                         return WERR_GEN_FAILURE;
    2369             :                 }
    2370             : 
    2371          40 :                 if (DEBUGLEVEL >= 10) {
    2372           0 :                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
    2373             :                 }
    2374             : 
    2375          40 :                 *type = REG_BINARY;
    2376          40 :                 data->binary = blob;
    2377             : 
    2378          40 :                 return WERR_OK;
    2379             :         }
    2380             : 
    2381             : 
    2382         236 :         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
    2383          24 :                 *type = REG_SZ;
    2384             : 
    2385          24 :                 data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
    2386          24 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2387             : 
    2388          24 :                 return WERR_OK;
    2389             :         }
    2390             : 
    2391         212 :         if (!strcasecmp_m(value, "Architecture")) {
    2392         160 :                 *type = REG_SZ;
    2393         160 :                 data->string = talloc_strdup(mem_ctx,
    2394             :                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
    2395         160 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2396             : 
    2397         160 :                 return WERR_OK;
    2398             :         }
    2399             : 
    2400          52 :         if (!strcasecmp_m(value, "DsPresent")) {
    2401          24 :                 *type = REG_DWORD;
    2402             : 
    2403             :                 /* only show the publish check box if we are a
    2404             :                    member of a AD domain */
    2405             : 
    2406          24 :                 if (lp_security() == SEC_ADS) {
    2407           0 :                         SIVAL(&data->value, 0, 0x01);
    2408             :                 } else {
    2409          24 :                         SIVAL(&data->value, 0, 0x00);
    2410             :                 }
    2411          24 :                 return WERR_OK;
    2412             :         }
    2413             : 
    2414          28 :         if (!strcasecmp_m(value, "DNSMachineName")) {
    2415          24 :                 const char *hostname = get_mydnsfullname();
    2416             : 
    2417          24 :                 if (!hostname) {
    2418           0 :                         return WERR_FILE_NOT_FOUND;
    2419             :                 }
    2420             : 
    2421          24 :                 *type = REG_SZ;
    2422          24 :                 data->string = talloc_strdup(mem_ctx, hostname);
    2423          24 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2424             : 
    2425          24 :                 return WERR_OK;
    2426             :         }
    2427             : 
    2428           4 :         *type = REG_NONE;
    2429             : 
    2430           4 :         return WERR_INVALID_PARAMETER;
    2431             : }
    2432             : 
    2433             : /****************************************************************
    2434             :  _spoolss_GetPrinterData
    2435             : ****************************************************************/
    2436             : 
    2437         480 : WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
    2438             :                                struct spoolss_GetPrinterData *r)
    2439             : {
    2440           0 :         struct spoolss_GetPrinterDataEx r2;
    2441             : 
    2442         480 :         r2.in.handle            = r->in.handle;
    2443         480 :         r2.in.key_name          = "PrinterDriverData";
    2444         480 :         r2.in.value_name        = r->in.value_name;
    2445         480 :         r2.in.offered           = r->in.offered;
    2446         480 :         r2.out.type             = r->out.type;
    2447         480 :         r2.out.data             = r->out.data;
    2448         480 :         r2.out.needed           = r->out.needed;
    2449             : 
    2450         480 :         return _spoolss_GetPrinterDataEx(p, &r2);
    2451             : }
    2452             : 
    2453             : /*********************************************************
    2454             :  Connect to the client machine.
    2455             : **********************************************************/
    2456             : 
    2457           2 : static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
    2458             :                                       struct sockaddr_storage *client_ss, const char *remote_machine)
    2459             : {
    2460           0 :         NTSTATUS ret;
    2461           0 :         struct sockaddr_storage rm_addr;
    2462           0 :         char addr[INET6_ADDRSTRLEN];
    2463           2 :         struct cli_credentials *anon_creds = NULL;
    2464             : 
    2465           2 :         if ( is_zero_addr(client_ss) ) {
    2466           0 :                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
    2467             :                         remote_machine));
    2468           0 :                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
    2469           0 :                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
    2470           0 :                         return false;
    2471             :                 }
    2472           0 :                 print_sockaddr(addr, sizeof(addr), &rm_addr);
    2473             :         } else {
    2474           2 :                 rm_addr = *client_ss;
    2475           2 :                 print_sockaddr(addr, sizeof(addr), &rm_addr);
    2476           2 :                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
    2477             :                         addr));
    2478             :         }
    2479             : 
    2480           2 :         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
    2481           0 :                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
    2482             :                         addr));
    2483           0 :                 return false;
    2484             :         }
    2485             : 
    2486           2 :         anon_creds = cli_credentials_init_anon(NULL);
    2487           2 :         if (anon_creds == NULL) {
    2488           0 :                 DBG_ERR("cli_credentials_init_anon() failed\n");
    2489           0 :                 return false;
    2490             :         }
    2491             : 
    2492             :         /* setup the connection */
    2493           2 :         ret = cli_full_connection_creds( pp_cli, lp_netbios_name(), remote_machine,
    2494             :                 &rm_addr, 0, "IPC$", "IPC",
    2495             :                 anon_creds,
    2496             :                 CLI_FULL_CONNECTION_IPC);
    2497           2 :         TALLOC_FREE(anon_creds);
    2498           2 :         if ( !NT_STATUS_IS_OK( ret ) ) {
    2499           0 :                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
    2500             :                         remote_machine ));
    2501           0 :                 return false;
    2502             :         }
    2503             : 
    2504           2 :         if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
    2505           0 :                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
    2506           0 :                 cli_shutdown(*pp_cli);
    2507           0 :                 return false;
    2508             :         }
    2509             : 
    2510             :         /*
    2511             :          * Ok - we have an anonymous connection to the IPC$ share.
    2512             :          * Now start the NT Domain stuff :-).
    2513             :          */
    2514             : 
    2515           2 :         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
    2516           2 :         if (!NT_STATUS_IS_OK(ret)) {
    2517           0 :                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
    2518             :                         remote_machine, nt_errstr(ret)));
    2519           0 :                 cli_shutdown(*pp_cli);
    2520           0 :                 return false;
    2521             :         }
    2522             : 
    2523           2 :         return true;
    2524             : }
    2525             : 
    2526             : /***************************************************************************
    2527             :  Connect to the client.
    2528             : ****************************************************************************/
    2529             : 
    2530           2 : static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
    2531             :                                         uint32_t localprinter,
    2532             :                                         enum winreg_Type type,
    2533             :                                         struct policy_handle *handle,
    2534             :                                         struct notify_back_channel **_chan,
    2535             :                                         struct sockaddr_storage *client_ss,
    2536             :                                         struct messaging_context *msg_ctx)
    2537             : {
    2538           0 :         WERROR result;
    2539           0 :         NTSTATUS status;
    2540           0 :         struct notify_back_channel *chan;
    2541             : 
    2542           2 :         for (chan = back_channels; chan; chan = chan->next) {
    2543           0 :                 if (memcmp(&chan->client_address, client_ss,
    2544             :                            sizeof(struct sockaddr_storage)) == 0) {
    2545           0 :                         break;
    2546             :                 }
    2547             :         }
    2548             : 
    2549             :         /*
    2550             :          * If it's the first connection, contact the client
    2551             :          * and connect to the IPC$ share anonymously
    2552             :          */
    2553           2 :         if (!chan) {
    2554           0 :                 fstring unix_printer;
    2555             : 
    2556             :                 /* the +2 is to strip the leading 2 backslashes */
    2557           2 :                 fstrcpy(unix_printer, printer + 2);
    2558             : 
    2559           2 :                 chan = talloc_zero(NULL, struct notify_back_channel);
    2560           2 :                 if (!chan) {
    2561           0 :                         return false;
    2562             :                 }
    2563           2 :                 chan->client_address = *client_ss;
    2564             : 
    2565           2 :                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
    2566           0 :                         TALLOC_FREE(chan);
    2567           0 :                         return false;
    2568             :                 }
    2569             : 
    2570           2 :                 DLIST_ADD(back_channels, chan);
    2571             : 
    2572           2 :                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
    2573             :                                    receive_notify2_message_list);
    2574             :         }
    2575             : 
    2576           2 :         if (chan->cli_pipe == NULL ||
    2577           2 :             chan->cli_pipe->binding_handle == NULL) {
    2578           0 :                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
    2579             :                         "NULL %s for printer %s\n",
    2580             :                         chan->cli_pipe == NULL ?
    2581             :                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
    2582             :                         printer));
    2583           0 :                 return false;
    2584             :         }
    2585             : 
    2586             :         /*
    2587             :          * Tell the specific printing tdb we want messages for this printer
    2588             :          * by registering our PID.
    2589             :          */
    2590             : 
    2591           2 :         if (!print_notify_register_pid(snum)) {
    2592           0 :                 DEBUG(0, ("Failed to register our pid for printer %s\n",
    2593             :                           printer));
    2594             :         }
    2595             : 
    2596           2 :         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
    2597             :                                                  talloc_tos(),
    2598             :                                                  printer,
    2599             :                                                  localprinter,
    2600             :                                                  type,
    2601             :                                                  0,
    2602             :                                                  NULL,
    2603             :                                                  handle,
    2604             :                                                  &result);
    2605           2 :         if (!NT_STATUS_IS_OK(status)) {
    2606           0 :                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
    2607           0 :                 result = ntstatus_to_werror(status);
    2608           2 :         } else if (!W_ERROR_IS_OK(result)) {
    2609           0 :                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
    2610             :         }
    2611             : 
    2612           2 :         chan->active_connections++;
    2613           2 :         *_chan = chan;
    2614             : 
    2615           2 :         return (W_ERROR_IS_OK(result));
    2616             : }
    2617             : 
    2618             : /****************************************************************
    2619             :  ****************************************************************/
    2620             : 
    2621           2 : static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
    2622             :                                                              const struct spoolss_NotifyOption *r)
    2623             : {
    2624           0 :         struct spoolss_NotifyOption *option;
    2625           0 :         uint32_t i,k;
    2626             : 
    2627           2 :         if (!r) {
    2628           0 :                 return NULL;
    2629             :         }
    2630             : 
    2631           2 :         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
    2632           2 :         if (!option) {
    2633           0 :                 return NULL;
    2634             :         }
    2635             : 
    2636           2 :         *option = *r;
    2637             : 
    2638           2 :         if (!option->count) {
    2639           0 :                 return option;
    2640             :         }
    2641             : 
    2642           2 :         option->types = talloc_zero_array(option,
    2643             :                 struct spoolss_NotifyOptionType, option->count);
    2644           2 :         if (!option->types) {
    2645           0 :                 talloc_free(option);
    2646           0 :                 return NULL;
    2647             :         }
    2648             : 
    2649           6 :         for (i=0; i < option->count; i++) {
    2650           4 :                 option->types[i] = r->types[i];
    2651             : 
    2652           4 :                 if (option->types[i].count) {
    2653           4 :                         option->types[i].fields = talloc_zero_array(option,
    2654             :                                 union spoolss_Field, option->types[i].count);
    2655           4 :                         if (!option->types[i].fields) {
    2656           0 :                                 talloc_free(option);
    2657           0 :                                 return NULL;
    2658             :                         }
    2659           8 :                         for (k=0; k<option->types[i].count; k++) {
    2660           4 :                                 option->types[i].fields[k] =
    2661           4 :                                         r->types[i].fields[k];
    2662             :                         }
    2663             :                 }
    2664             :         }
    2665             : 
    2666           2 :         return option;
    2667             : }
    2668             : 
    2669             : /****************************************************************
    2670             :  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
    2671             :  *
    2672             :  * before replying OK: status=0 a rpc call is made to the workstation
    2673             :  * asking ReplyOpenPrinter
    2674             :  *
    2675             :  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
    2676             :  * called from api_spoolss_rffpcnex
    2677             : ****************************************************************/
    2678             : 
    2679           2 : WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
    2680             :                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
    2681             : {
    2682           2 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2683           2 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    2684           0 :         const struct tsocket_address *remote_address =
    2685           2 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    2686           2 :         int snum = -1;
    2687           2 :         struct spoolss_NotifyOption *option = r->in.notify_options;
    2688           0 :         struct sockaddr_storage client_ss;
    2689           0 :         ssize_t client_len;
    2690             : 
    2691             :         /* store the notify value in the printer struct */
    2692             : 
    2693           2 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    2694             : 
    2695           2 :         if (!Printer) {
    2696           0 :                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2697             :                         "Invalid handle (%s:%u:%u).\n",
    2698             :                         OUR_HANDLE(r->in.handle)));
    2699           0 :                 return WERR_INVALID_HANDLE;
    2700             :         }
    2701             : 
    2702           2 :         Printer->notify.flags                = r->in.flags;
    2703           2 :         Printer->notify.options              = r->in.options;
    2704           2 :         Printer->notify.printerlocal = r->in.printer_local;
    2705           2 :         Printer->notify.msg_ctx              = p->msg_ctx;
    2706             : 
    2707           2 :         TALLOC_FREE(Printer->notify.option);
    2708           2 :         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
    2709             : 
    2710           2 :         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
    2711             : 
    2712             :         /* Connect to the client machine and send a ReplyOpenPrinter */
    2713             : 
    2714           2 :         if ( Printer->printer_type == SPLHND_SERVER)
    2715           2 :                 snum = -1;
    2716           0 :         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
    2717           0 :                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
    2718           0 :                 return WERR_INVALID_HANDLE;
    2719             : 
    2720           2 :         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2721             :                   "remote_address is %s\n",
    2722             :                   tsocket_address_string(remote_address, p->mem_ctx)));
    2723             : 
    2724           2 :         if (!lp_print_notify_backchannel(snum)) {
    2725           0 :                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2726             :                         "backchannel disabled\n"));
    2727           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
    2728             :         }
    2729             : 
    2730           2 :         client_len = tsocket_address_bsd_sockaddr(remote_address,
    2731             :                                                   (struct sockaddr *) &client_ss,
    2732             :                                                   sizeof(struct sockaddr_storage));
    2733           2 :         if (client_len < 0) {
    2734           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2735             :         }
    2736             : 
    2737           2 :         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
    2738             :                                         Printer->notify.printerlocal, REG_SZ,
    2739             :                                         &Printer->notify.cli_hnd,
    2740             :                                         &Printer->notify.cli_chan,
    2741             :                                         &client_ss, p->msg_ctx)) {
    2742           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
    2743             :         }
    2744             : 
    2745           2 :         return WERR_OK;
    2746             : }
    2747             : 
    2748             : /*******************************************************************
    2749             :  * fill a notify_info_data with the servername
    2750             :  ********************************************************************/
    2751             : 
    2752           0 : static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
    2753             :                                        int snum,
    2754             :                                        struct spoolss_Notify *data,
    2755             :                                        print_queue_struct *queue,
    2756             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    2757             :                                        TALLOC_CTX *mem_ctx)
    2758             : {
    2759           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
    2760           0 : }
    2761             : 
    2762             : /*******************************************************************
    2763             :  * fill a notify_info_data with the printername (not including the servername).
    2764             :  ********************************************************************/
    2765             : 
    2766           0 : static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
    2767             :                                         int snum,
    2768             :                                         struct spoolss_Notify *data,
    2769             :                                         print_queue_struct *queue,
    2770             :                                         struct spoolss_PrinterInfo2 *pinfo2,
    2771             :                                         TALLOC_CTX *mem_ctx)
    2772             : {
    2773             :         /* the notify name should not contain the \\server\ part */
    2774           0 :         const char *p = strrchr(pinfo2->printername, '\\');
    2775             : 
    2776           0 :         if (!p) {
    2777           0 :                 p = pinfo2->printername;
    2778             :         } else {
    2779           0 :                 p++;
    2780             :         }
    2781             : 
    2782           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    2783           0 : }
    2784             : 
    2785             : /*******************************************************************
    2786             :  * fill a notify_info_data with the servicename
    2787             :  ********************************************************************/
    2788             : 
    2789           0 : static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
    2790             :                                       int snum,
    2791             :                                       struct spoolss_Notify *data,
    2792             :                                       print_queue_struct *queue,
    2793             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2794             :                                       TALLOC_CTX *mem_ctx)
    2795             : {
    2796           0 :         const struct loadparm_substitution *lp_sub =
    2797           0 :                 loadparm_s3_global_substitution();
    2798             : 
    2799           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
    2800           0 : }
    2801             : 
    2802             : /*******************************************************************
    2803             :  * fill a notify_info_data with the port name
    2804             :  ********************************************************************/
    2805             : 
    2806           0 : static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
    2807             :                                      int snum,
    2808             :                                      struct spoolss_Notify *data,
    2809             :                                      print_queue_struct *queue,
    2810             :                                      struct spoolss_PrinterInfo2 *pinfo2,
    2811             :                                      TALLOC_CTX *mem_ctx)
    2812             : {
    2813           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
    2814           0 : }
    2815             : 
    2816             : /*******************************************************************
    2817             :  * fill a notify_info_data with the printername
    2818             :  * but it doesn't exist, have to see what to do
    2819             :  ********************************************************************/
    2820             : 
    2821           0 : static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
    2822             :                                        int snum,
    2823             :                                        struct spoolss_Notify *data,
    2824             :                                        print_queue_struct *queue,
    2825             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    2826             :                                        TALLOC_CTX *mem_ctx)
    2827             : {
    2828           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
    2829           0 : }
    2830             : 
    2831             : /*******************************************************************
    2832             :  * fill a notify_info_data with the comment
    2833             :  ********************************************************************/
    2834             : 
    2835           0 : static void spoolss_notify_comment(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 struct loadparm_substitution *lp_sub =
    2843           0 :                 loadparm_s3_global_substitution();
    2844           0 :         const char *p;
    2845             : 
    2846           0 :         if (*pinfo2->comment == '\0') {
    2847           0 :                 p = lp_comment(talloc_tos(), lp_sub, snum);
    2848             :         } else {
    2849           0 :                 p = pinfo2->comment;
    2850             :         }
    2851             : 
    2852           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    2853           0 : }
    2854             : 
    2855             : /*******************************************************************
    2856             :  * fill a notify_info_data with the comment
    2857             :  * location = "Room 1, floor 2, building 3"
    2858             :  ********************************************************************/
    2859             : 
    2860           0 : static void spoolss_notify_location(struct messaging_context *msg_ctx,
    2861             :                                     int snum,
    2862             :                                     struct spoolss_Notify *data,
    2863             :                                     print_queue_struct *queue,
    2864             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2865             :                                     TALLOC_CTX *mem_ctx)
    2866             : {
    2867           0 :         const char *loc = pinfo2->location;
    2868           0 :         NTSTATUS status;
    2869             : 
    2870           0 :         status = printer_list_get_printer(mem_ctx,
    2871             :                                           pinfo2->sharename,
    2872             :                                           NULL,
    2873             :                                           &loc,
    2874             :                                           NULL);
    2875           0 :         if (NT_STATUS_IS_OK(status)) {
    2876           0 :                 if (loc == NULL) {
    2877           0 :                         loc = pinfo2->location;
    2878             :                 }
    2879             :         }
    2880             : 
    2881           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
    2882           0 : }
    2883             : 
    2884             : /*******************************************************************
    2885             :  * fill a notify_info_data with the device mode
    2886             :  * jfm:xxxx don't to it for know but that's a real problem !!!
    2887             :  ********************************************************************/
    2888             : 
    2889           0 : static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
    2890             :                                    int snum,
    2891             :                                    struct spoolss_Notify *data,
    2892             :                                    print_queue_struct *queue,
    2893             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2894             :                                    TALLOC_CTX *mem_ctx)
    2895             : {
    2896             :         /* for a dummy implementation we have to zero the fields */
    2897           0 :         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
    2898           0 : }
    2899             : 
    2900             : /*******************************************************************
    2901             :  * fill a notify_info_data with the separator file name
    2902             :  ********************************************************************/
    2903             : 
    2904           0 : static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
    2905             :                                    int snum,
    2906             :                                    struct spoolss_Notify *data,
    2907             :                                    print_queue_struct *queue,
    2908             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2909             :                                    TALLOC_CTX *mem_ctx)
    2910             : {
    2911           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
    2912           0 : }
    2913             : 
    2914             : /*******************************************************************
    2915             :  * fill a notify_info_data with the print processor
    2916             :  * jfm:xxxx return always winprint to indicate we don't do anything to it
    2917             :  ********************************************************************/
    2918             : 
    2919           0 : static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
    2920             :                                            int snum,
    2921             :                                            struct spoolss_Notify *data,
    2922             :                                            print_queue_struct *queue,
    2923             :                                            struct spoolss_PrinterInfo2 *pinfo2,
    2924             :                                            TALLOC_CTX *mem_ctx)
    2925             : {
    2926           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
    2927           0 : }
    2928             : 
    2929             : /*******************************************************************
    2930             :  * fill a notify_info_data with the print processor options
    2931             :  * jfm:xxxx send an empty string
    2932             :  ********************************************************************/
    2933             : 
    2934           0 : static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
    2935             :                                       int snum,
    2936             :                                       struct spoolss_Notify *data,
    2937             :                                       print_queue_struct *queue,
    2938             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2939             :                                       TALLOC_CTX *mem_ctx)
    2940             : {
    2941           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
    2942           0 : }
    2943             : 
    2944             : /*******************************************************************
    2945             :  * fill a notify_info_data with the data type
    2946             :  * jfm:xxxx always send RAW as data type
    2947             :  ********************************************************************/
    2948             : 
    2949           0 : static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
    2950             :                                     int snum,
    2951             :                                     struct spoolss_Notify *data,
    2952             :                                     print_queue_struct *queue,
    2953             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2954             :                                     TALLOC_CTX *mem_ctx)
    2955             : {
    2956           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
    2957           0 : }
    2958             : 
    2959             : /*******************************************************************
    2960             :  * fill a notify_info_data with the security descriptor
    2961             :  * jfm:xxxx send an null pointer to say no security desc
    2962             :  * have to implement security before !
    2963             :  ********************************************************************/
    2964             : 
    2965           0 : static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
    2966             :                                          int snum,
    2967             :                                          struct spoolss_Notify *data,
    2968             :                                          print_queue_struct *queue,
    2969             :                                          struct spoolss_PrinterInfo2 *pinfo2,
    2970             :                                          TALLOC_CTX *mem_ctx)
    2971             : {
    2972           0 :         if (pinfo2->secdesc == NULL) {
    2973           0 :                 data->data.sd.sd = NULL;
    2974             :         } else {
    2975           0 :                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
    2976           0 :                                                             pinfo2->secdesc);
    2977             :         }
    2978           0 :         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
    2979             :                                                              0);
    2980           0 : }
    2981             : 
    2982             : /*******************************************************************
    2983             :  * fill a notify_info_data with the attributes
    2984             :  * jfm:xxxx a samba printer is always shared
    2985             :  ********************************************************************/
    2986             : 
    2987           0 : static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
    2988             :                                       int snum,
    2989             :                                       struct spoolss_Notify *data,
    2990             :                                       print_queue_struct *queue,
    2991             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2992             :                                       TALLOC_CTX *mem_ctx)
    2993             : {
    2994           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
    2995           0 : }
    2996             : 
    2997             : /*******************************************************************
    2998             :  * fill a notify_info_data with the priority
    2999             :  ********************************************************************/
    3000             : 
    3001           0 : static void spoolss_notify_priority(struct messaging_context *msg_ctx,
    3002             :                                     int snum,
    3003             :                                     struct spoolss_Notify *data,
    3004             :                                     print_queue_struct *queue,
    3005             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3006             :                                     TALLOC_CTX *mem_ctx)
    3007             : {
    3008           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
    3009           0 : }
    3010             : 
    3011             : /*******************************************************************
    3012             :  * fill a notify_info_data with the default priority
    3013             :  ********************************************************************/
    3014             : 
    3015           0 : static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
    3016             :                                             int snum,
    3017             :                                             struct spoolss_Notify *data,
    3018             :                                             print_queue_struct *queue,
    3019             :                                             struct spoolss_PrinterInfo2 *pinfo2,
    3020             :                                             TALLOC_CTX *mem_ctx)
    3021             : {
    3022           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
    3023           0 : }
    3024             : 
    3025             : /*******************************************************************
    3026             :  * fill a notify_info_data with the start time
    3027             :  ********************************************************************/
    3028             : 
    3029           0 : static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
    3030             :                                       int snum,
    3031             :                                       struct spoolss_Notify *data,
    3032             :                                       print_queue_struct *queue,
    3033             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3034             :                                       TALLOC_CTX *mem_ctx)
    3035             : {
    3036           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
    3037           0 : }
    3038             : 
    3039             : /*******************************************************************
    3040             :  * fill a notify_info_data with the until time
    3041             :  ********************************************************************/
    3042             : 
    3043           0 : static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
    3044             :                                       int snum,
    3045             :                                       struct spoolss_Notify *data,
    3046             :                                       print_queue_struct *queue,
    3047             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3048             :                                       TALLOC_CTX *mem_ctx)
    3049             : {
    3050           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
    3051           0 : }
    3052             : 
    3053             : /*******************************************************************
    3054             :  * fill a notify_info_data with the status
    3055             :  ********************************************************************/
    3056             : 
    3057           0 : static void spoolss_notify_status(struct messaging_context *msg_ctx,
    3058             :                                   int snum,
    3059             :                                   struct spoolss_Notify *data,
    3060             :                                   print_queue_struct *queue,
    3061             :                                   struct spoolss_PrinterInfo2 *pinfo2,
    3062             :                                   TALLOC_CTX *mem_ctx)
    3063             : {
    3064           0 :         print_status_struct status;
    3065             : 
    3066           0 :         print_queue_length(msg_ctx, snum, &status);
    3067           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
    3068           0 : }
    3069             : 
    3070             : /*******************************************************************
    3071             :  * fill a notify_info_data with the number of jobs queued
    3072             :  ********************************************************************/
    3073             : 
    3074           0 : static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
    3075             :                                  int snum,
    3076             :                                  struct spoolss_Notify *data,
    3077             :                                  print_queue_struct *queue,
    3078             :                                  struct spoolss_PrinterInfo2 *pinfo2,
    3079             :                                  TALLOC_CTX *mem_ctx)
    3080             : {
    3081           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
    3082           0 :                 data, print_queue_length(msg_ctx, snum, NULL));
    3083           0 : }
    3084             : 
    3085             : /*******************************************************************
    3086             :  * fill a notify_info_data with the average ppm
    3087             :  ********************************************************************/
    3088             : 
    3089           0 : static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
    3090             :                                        int snum,
    3091             :                                        struct spoolss_Notify *data,
    3092             :                                        print_queue_struct *queue,
    3093             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    3094             :                                        TALLOC_CTX *mem_ctx)
    3095             : {
    3096             :         /* always respond 8 pages per minutes */
    3097             :         /* a little hard ! */
    3098           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
    3099           0 : }
    3100             : 
    3101             : /*******************************************************************
    3102             :  * fill a notify_info_data with username
    3103             :  ********************************************************************/
    3104             : 
    3105           0 : static void spoolss_notify_username(struct messaging_context *msg_ctx,
    3106             :                                     int snum,
    3107             :                                     struct spoolss_Notify *data,
    3108             :                                     print_queue_struct *queue,
    3109             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3110             :                                     TALLOC_CTX *mem_ctx)
    3111             : {
    3112           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
    3113           0 : }
    3114             : 
    3115             : /*******************************************************************
    3116             :  * fill a notify_info_data with job status
    3117             :  ********************************************************************/
    3118             : 
    3119           0 : static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
    3120             :                                       int snum,
    3121             :                                       struct spoolss_Notify *data,
    3122             :                                       print_queue_struct *queue,
    3123             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3124             :                                       TALLOC_CTX *mem_ctx)
    3125             : {
    3126           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
    3127           0 : }
    3128             : 
    3129             : /*******************************************************************
    3130             :  * fill a notify_info_data with job name
    3131             :  ********************************************************************/
    3132             : 
    3133           0 : static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
    3134             :                                     int snum,
    3135             :                                     struct spoolss_Notify *data,
    3136             :                                     print_queue_struct *queue,
    3137             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3138             :                                     TALLOC_CTX *mem_ctx)
    3139             : {
    3140           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
    3141           0 : }
    3142             : 
    3143             : /*******************************************************************
    3144             :  * fill a notify_info_data with job status
    3145             :  ********************************************************************/
    3146             : 
    3147           0 : static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
    3148             :                                              int snum,
    3149             :                                              struct spoolss_Notify *data,
    3150             :                                              print_queue_struct *queue,
    3151             :                                              struct spoolss_PrinterInfo2 *pinfo2,
    3152             :                                              TALLOC_CTX *mem_ctx)
    3153             : {
    3154             :         /*
    3155             :          * Now we're returning job status codes we just return a "" here. JRA.
    3156             :          */
    3157             : 
    3158           0 :         const char *p = "";
    3159             : 
    3160             : #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
    3161             :         p = "unknown";
    3162             : 
    3163             :         switch (queue->status) {
    3164             :         case LPQ_QUEUED:
    3165             :                 p = "Queued";
    3166             :                 break;
    3167             :         case LPQ_PAUSED:
    3168             :                 p = "";    /* NT provides the paused string */
    3169             :                 break;
    3170             :         case LPQ_SPOOLING:
    3171             :                 p = "Spooling";
    3172             :                 break;
    3173             :         case LPQ_PRINTING:
    3174             :                 p = "Printing";
    3175             :                 break;
    3176             :         }
    3177             : #endif /* NO LONGER NEEDED. */
    3178             : 
    3179           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    3180           0 : }
    3181             : 
    3182             : /*******************************************************************
    3183             :  * fill a notify_info_data with job time
    3184             :  ********************************************************************/
    3185             : 
    3186           0 : static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
    3187             :                                     int snum,
    3188             :                                     struct spoolss_Notify *data,
    3189             :                                     print_queue_struct *queue,
    3190             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3191             :                                     TALLOC_CTX *mem_ctx)
    3192             : {
    3193           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
    3194           0 : }
    3195             : 
    3196             : /*******************************************************************
    3197             :  * fill a notify_info_data with job size
    3198             :  ********************************************************************/
    3199             : 
    3200           0 : static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
    3201             :                                     int snum,
    3202             :                                     struct spoolss_Notify *data,
    3203             :                                     print_queue_struct *queue,
    3204             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3205             :                                     TALLOC_CTX *mem_ctx)
    3206             : {
    3207           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
    3208           0 : }
    3209             : 
    3210             : /*******************************************************************
    3211             :  * fill a notify_info_data with page info
    3212             :  ********************************************************************/
    3213           0 : static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
    3214             :                                        int snum,
    3215             :                                 struct spoolss_Notify *data,
    3216             :                                 print_queue_struct *queue,
    3217             :                                 struct spoolss_PrinterInfo2 *pinfo2,
    3218             :                                 TALLOC_CTX *mem_ctx)
    3219             : {
    3220           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
    3221           0 : }
    3222             : 
    3223             : /*******************************************************************
    3224             :  * fill a notify_info_data with pages printed info.
    3225             :  ********************************************************************/
    3226           0 : static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
    3227             :                                          int snum,
    3228             :                                 struct spoolss_Notify *data,
    3229             :                                 print_queue_struct *queue,
    3230             :                                 struct spoolss_PrinterInfo2 *pinfo2,
    3231             :                                 TALLOC_CTX *mem_ctx)
    3232             : {
    3233             :         /* Add code when back-end tracks this */
    3234           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
    3235           0 : }
    3236             : 
    3237             : /*******************************************************************
    3238             :  Fill a notify_info_data with job position.
    3239             :  ********************************************************************/
    3240             : 
    3241           0 : static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
    3242             :                                         int snum,
    3243             :                                         struct spoolss_Notify *data,
    3244             :                                         print_queue_struct *queue,
    3245             :                                         struct spoolss_PrinterInfo2 *pinfo2,
    3246             :                                         TALLOC_CTX *mem_ctx)
    3247             : {
    3248           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
    3249           0 : }
    3250             : 
    3251             : /*******************************************************************
    3252             :  Fill a notify_info_data with submitted time.
    3253             :  ********************************************************************/
    3254             : 
    3255           0 : static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
    3256             :                                           int snum,
    3257             :                                           struct spoolss_Notify *data,
    3258             :                                           print_queue_struct *queue,
    3259             :                                           struct spoolss_PrinterInfo2 *pinfo2,
    3260             :                                           TALLOC_CTX *mem_ctx)
    3261             : {
    3262           0 :         data->data.string.string = NULL;
    3263           0 :         data->data.string.size = 0;
    3264             : 
    3265           0 :         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
    3266             :                                &data->data.string.string,
    3267             :                                &data->data.string.size);
    3268             : 
    3269           0 : }
    3270             : 
    3271             : struct s_notify_info_data_table
    3272             : {
    3273             :         enum spoolss_NotifyType type;
    3274             :         uint16_t field;
    3275             :         const char *name;
    3276             :         enum spoolss_NotifyTable variable_type;
    3277             :         void (*fn) (struct messaging_context *msg_ctx,
    3278             :                     int snum, struct spoolss_Notify *data,
    3279             :                     print_queue_struct *queue,
    3280             :                     struct spoolss_PrinterInfo2 *pinfo2,
    3281             :                     TALLOC_CTX *mem_ctx);
    3282             : };
    3283             : 
    3284             : /* A table describing the various print notification constants and
    3285             :    whether the notification data is a pointer to a variable sized
    3286             :    buffer, a one value uint32_t or a two value uint32_t. */
    3287             : 
    3288             : static const struct s_notify_info_data_table notify_info_data_table[] =
    3289             : {
    3290             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
    3291             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
    3292             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
    3293             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
    3294             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
    3295             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
    3296             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
    3297             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
    3298             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
    3299             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
    3300             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
    3301             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
    3302             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
    3303             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
    3304             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
    3305             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
    3306             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
    3307             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
    3308             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
    3309             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
    3310             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
    3311             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
    3312             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
    3313             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
    3314             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
    3315             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
    3316             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
    3317             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
    3318             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
    3319             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
    3320             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
    3321             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
    3322             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
    3323             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
    3324             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
    3325             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
    3326             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
    3327             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
    3328             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
    3329             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
    3330             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
    3331             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
    3332             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
    3333             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
    3334             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
    3335             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
    3336             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
    3337             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
    3338             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
    3339             : };
    3340             : 
    3341             : /*******************************************************************
    3342             :  Return the variable_type of info_data structure.
    3343             : ********************************************************************/
    3344             : 
    3345           0 : static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
    3346             :                                                                   uint16_t field)
    3347             : {
    3348           0 :         int i=0;
    3349             : 
    3350           0 :         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
    3351           0 :                 if ( (notify_info_data_table[i].type == type) &&
    3352           0 :                      (notify_info_data_table[i].field == field) ) {
    3353           0 :                         return notify_info_data_table[i].variable_type;
    3354             :                 }
    3355             :         }
    3356             : 
    3357           0 :         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
    3358             : 
    3359           0 :         return (enum spoolss_NotifyTable) 0;
    3360             : }
    3361             : 
    3362             : /****************************************************************************
    3363             : ****************************************************************************/
    3364             : 
    3365           0 : static bool search_notify(enum spoolss_NotifyType type,
    3366             :                           uint16_t field,
    3367             :                           int *value)
    3368             : {
    3369           0 :         int i;
    3370             : 
    3371           0 :         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
    3372           0 :                 if (notify_info_data_table[i].type == type &&
    3373           0 :                     notify_info_data_table[i].field == field &&
    3374           0 :                     notify_info_data_table[i].fn != NULL) {
    3375           0 :                         *value = i;
    3376           0 :                         return true;
    3377             :                 }
    3378             :         }
    3379             : 
    3380           0 :         return false;
    3381             : }
    3382             : 
    3383             : /****************************************************************************
    3384             : ****************************************************************************/
    3385             : 
    3386           0 : static void construct_info_data(struct spoolss_Notify *info_data,
    3387             :                                 enum spoolss_NotifyType type,
    3388             :                                 uint16_t field, int id)
    3389             : {
    3390           0 :         info_data->type                      = type;
    3391           0 :         info_data->field.field               = field;
    3392           0 :         info_data->variable_type     = variable_type_of_notify_info_data(type, field);
    3393           0 :         info_data->job_id            = id;
    3394           0 : }
    3395             : 
    3396             : /*******************************************************************
    3397             :  *
    3398             :  * fill a notify_info struct with info asked
    3399             :  *
    3400             :  ********************************************************************/
    3401             : 
    3402           0 : static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
    3403             :                                           struct printer_handle *print_hnd,
    3404             :                                           struct spoolss_NotifyInfo *info,
    3405             :                                           struct spoolss_PrinterInfo2 *pinfo2,
    3406             :                                           int snum,
    3407             :                                           const struct spoolss_NotifyOptionType *option_type,
    3408             :                                           uint32_t id,
    3409             :                                           TALLOC_CTX *mem_ctx)
    3410             : {
    3411           0 :         const struct loadparm_substitution *lp_sub =
    3412           0 :                 loadparm_s3_global_substitution();
    3413           0 :         int field_num,j;
    3414           0 :         enum spoolss_NotifyType type;
    3415           0 :         uint16_t field;
    3416             : 
    3417           0 :         struct spoolss_Notify *current_data;
    3418             : 
    3419           0 :         type = option_type->type;
    3420             : 
    3421           0 :         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
    3422             :                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
    3423             :                 option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
    3424             : 
    3425           0 :         for(field_num=0; field_num < option_type->count; field_num++) {
    3426           0 :                 field = option_type->fields[field_num].field;
    3427             : 
    3428           0 :                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
    3429             : 
    3430           0 :                 if (!search_notify(type, field, &j) )
    3431           0 :                         continue;
    3432             : 
    3433           0 :                 info->notifies = talloc_realloc(info, info->notifies,
    3434             :                                                       struct spoolss_Notify,
    3435             :                                                       info->count + 1);
    3436           0 :                 if (info->notifies == NULL) {
    3437           0 :                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
    3438           0 :                         return false;
    3439             :                 }
    3440             : 
    3441           0 :                 current_data = &info->notifies[info->count];
    3442             : 
    3443           0 :                 construct_info_data(current_data, type, field, id);
    3444             : 
    3445           0 :                 DEBUG(10, ("construct_notify_printer_info: "
    3446             :                            "calling [%s]  snum=%d  printername=[%s])\n",
    3447             :                            notify_info_data_table[j].name, snum,
    3448             :                            pinfo2->printername));
    3449             : 
    3450           0 :                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
    3451             :                                              NULL, pinfo2, mem_ctx);
    3452             : 
    3453           0 :                 info->count++;
    3454             :         }
    3455             : 
    3456           0 :         return true;
    3457             : }
    3458             : 
    3459             : /*******************************************************************
    3460             :  *
    3461             :  * fill a notify_info struct with info asked
    3462             :  *
    3463             :  ********************************************************************/
    3464             : 
    3465           0 : static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
    3466             :                                        print_queue_struct *queue,
    3467             :                                        struct spoolss_NotifyInfo *info,
    3468             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    3469             :                                        int snum,
    3470             :                                        const struct spoolss_NotifyOptionType *option_type,
    3471             :                                        uint32_t id,
    3472             :                                        TALLOC_CTX *mem_ctx)
    3473             : {
    3474           0 :         int field_num,j;
    3475           0 :         enum spoolss_NotifyType type;
    3476           0 :         uint16_t field;
    3477           0 :         struct spoolss_Notify *current_data;
    3478             : 
    3479           0 :         DEBUG(4,("construct_notify_jobs_info\n"));
    3480             : 
    3481           0 :         type = option_type->type;
    3482             : 
    3483           0 :         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
    3484             :                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
    3485             :                 option_type->count));
    3486             : 
    3487           0 :         for(field_num=0; field_num<option_type->count; field_num++) {
    3488           0 :                 field = option_type->fields[field_num].field;
    3489             : 
    3490           0 :                 if (!search_notify(type, field, &j) )
    3491           0 :                         continue;
    3492             : 
    3493           0 :                 info->notifies = talloc_realloc(info, info->notifies,
    3494             :                                                       struct spoolss_Notify,
    3495             :                                                       info->count + 1);
    3496           0 :                 if (info->notifies == NULL) {
    3497           0 :                         DEBUG(2,("construct_notify_jobs_info: failed to enlarge buffer info->data!\n"));
    3498           0 :                         return false;
    3499             :                 }
    3500             : 
    3501           0 :                 current_data=&(info->notifies[info->count]);
    3502             : 
    3503           0 :                 construct_info_data(current_data, type, field, id);
    3504           0 :                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
    3505             :                                              queue, pinfo2, mem_ctx);
    3506           0 :                 info->count++;
    3507             :         }
    3508             : 
    3509           0 :         return true;
    3510             : }
    3511             : 
    3512             : /*
    3513             :  * JFM: The enumeration is not that simple, it's even non obvious.
    3514             :  *
    3515             :  * let's take an example: I want to monitor the PRINTER SERVER for
    3516             :  * the printer's name and the number of jobs currently queued.
    3517             :  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
    3518             :  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
    3519             :  *
    3520             :  * I have 3 printers on the back of my server.
    3521             :  *
    3522             :  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
    3523             :  * structures.
    3524             :  *   Number     Data                    Id
    3525             :  *      1       printer 1 name          1
    3526             :  *      2       printer 1 cjob          1
    3527             :  *      3       printer 2 name          2
    3528             :  *      4       printer 2 cjob          2
    3529             :  *      5       printer 3 name          3
    3530             :  *      6       printer 3 name          3
    3531             :  *
    3532             :  * that's the print server case, the printer case is even worse.
    3533             :  */
    3534             : 
    3535             : /*******************************************************************
    3536             :  *
    3537             :  * enumerate all printers on the printserver
    3538             :  * fill a notify_info struct with info asked
    3539             :  *
    3540             :  ********************************************************************/
    3541             : 
    3542           4 : static WERROR printserver_notify_info(struct pipes_struct *p,
    3543             :                                       struct policy_handle *hnd,
    3544             :                                       struct spoolss_NotifyInfo *info,
    3545             :                                       TALLOC_CTX *mem_ctx)
    3546             : {
    3547           0 :         const struct loadparm_substitution *lp_sub =
    3548           4 :                 loadparm_s3_global_substitution();
    3549           0 :         int snum;
    3550           4 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
    3551           4 :         int n_services=lp_numservices();
    3552           0 :         int i;
    3553           0 :         struct spoolss_NotifyOption *option;
    3554           0 :         struct spoolss_NotifyOptionType option_type;
    3555           4 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    3556           0 :         WERROR result;
    3557             : 
    3558           4 :         DEBUG(4,("printserver_notify_info\n"));
    3559             : 
    3560           4 :         if (!Printer)
    3561           0 :                 return WERR_INVALID_HANDLE;
    3562             : 
    3563           4 :         option = Printer->notify.option;
    3564             : 
    3565           4 :         info->version        = 2;
    3566           4 :         info->notifies       = NULL;
    3567           4 :         info->count  = 0;
    3568             : 
    3569             :         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
    3570             :            sending a ffpcn() request first */
    3571             : 
    3572           4 :         if ( !option )
    3573           0 :                 return WERR_INVALID_HANDLE;
    3574             : 
    3575          12 :         for (i=0; i<option->count; i++) {
    3576           8 :                 option_type = option->types[i];
    3577             : 
    3578           8 :                 if (option_type.type != PRINTER_NOTIFY_TYPE)
    3579           4 :                         continue;
    3580             : 
    3581         492 :                 for (snum = 0; snum < n_services; snum++) {
    3582         488 :                         if (!lp_browseable(snum) ||
    3583         488 :                             !lp_snum_ok(snum) ||
    3584         488 :                             !lp_printable(snum)) {
    3585         468 :                                 continue; /* skip */
    3586             :                         }
    3587             : 
    3588             :                         /* Maybe we should use the SYSTEM session_info here... */
    3589          20 :                         result = winreg_get_printer_internal(mem_ctx,
    3590             :                                                     get_session_info_system(),
    3591             :                                                     p->msg_ctx,
    3592          20 :                                                     lp_servicename(talloc_tos(), lp_sub, snum),
    3593             :                                                     &pinfo2);
    3594          20 :                         if (!W_ERROR_IS_OK(result)) {
    3595          20 :                                 DEBUG(4, ("printserver_notify_info: "
    3596             :                                           "Failed to get printer [%s]\n",
    3597             :                                           lp_servicename(talloc_tos(), lp_sub, snum)));
    3598          20 :                                 continue;
    3599             :                         }
    3600             : 
    3601             : 
    3602           0 :                         construct_notify_printer_info(p->msg_ctx,
    3603             :                                                       Printer, info,
    3604             :                                                       pinfo2, snum,
    3605             :                                                       &option_type, snum,
    3606             :                                                       mem_ctx);
    3607             : 
    3608           0 :                         TALLOC_FREE(pinfo2);
    3609             :                 }
    3610             :         }
    3611             : 
    3612             : #if 0
    3613             :         /*
    3614             :          * Debugging information, don't delete.
    3615             :          */
    3616             : 
    3617             :         DEBUG(1,("dumping the NOTIFY_INFO\n"));
    3618             :         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
    3619             :         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
    3620             : 
    3621             :         for (i=0; i<info->count; i++) {
    3622             :                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
    3623             :                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
    3624             :                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
    3625             :         }
    3626             : #endif
    3627             : 
    3628           4 :         return WERR_OK;
    3629             : }
    3630             : 
    3631             : /*******************************************************************
    3632             :  *
    3633             :  * fill a notify_info struct with info asked
    3634             :  *
    3635             :  ********************************************************************/
    3636             : 
    3637           0 : static WERROR printer_notify_info(struct pipes_struct *p,
    3638             :                                   struct policy_handle *hnd,
    3639             :                                   struct spoolss_NotifyInfo *info,
    3640             :                                   TALLOC_CTX *mem_ctx)
    3641             : {
    3642           0 :         const struct loadparm_substitution *lp_sub =
    3643           0 :                 loadparm_s3_global_substitution();
    3644           0 :         int snum;
    3645           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
    3646           0 :         int i;
    3647           0 :         uint32_t id;
    3648           0 :         struct spoolss_NotifyOption *option;
    3649           0 :         struct spoolss_NotifyOptionType option_type;
    3650           0 :         int count,j;
    3651           0 :         print_queue_struct *queue=NULL;
    3652           0 :         print_status_struct status;
    3653           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    3654           0 :         WERROR result;
    3655           0 :         struct tdb_print_db *pdb;
    3656             : 
    3657           0 :         DEBUG(4,("printer_notify_info\n"));
    3658             : 
    3659           0 :         if (!Printer)
    3660           0 :                 return WERR_INVALID_HANDLE;
    3661             : 
    3662           0 :         option = Printer->notify.option;
    3663           0 :         id = 0x0;
    3664             : 
    3665           0 :         info->version        = 2;
    3666           0 :         info->notifies       = NULL;
    3667           0 :         info->count  = 0;
    3668             : 
    3669             :         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
    3670             :            sending a ffpcn() request first */
    3671             : 
    3672           0 :         if ( !option )
    3673           0 :                 return WERR_INVALID_HANDLE;
    3674             : 
    3675           0 :         if (!get_printer_snum(p, hnd, &snum, NULL)) {
    3676           0 :                 return WERR_INVALID_HANDLE;
    3677             :         }
    3678             : 
    3679           0 :         pdb = get_print_db_byname(Printer->sharename);
    3680           0 :         if (pdb == NULL) {
    3681           0 :                 return WERR_INVALID_HANDLE;
    3682             :         }
    3683             : 
    3684             :         /* Maybe we should use the SYSTEM session_info here... */
    3685           0 :         result = winreg_get_printer_internal(mem_ctx,
    3686             :                                     get_session_info_system(),
    3687             :                                     p->msg_ctx,
    3688           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
    3689           0 :         if (!W_ERROR_IS_OK(result)) {
    3690           0 :                 result = WERR_INVALID_HANDLE;
    3691           0 :                 goto err_pdb_drop;
    3692             :         }
    3693             : 
    3694             :         /*
    3695             :          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
    3696             :          * correct servername.
    3697             :          */
    3698           0 :         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
    3699           0 :         if (pinfo2->servername == NULL) {
    3700           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3701           0 :                 goto err_pdb_drop;
    3702             :         }
    3703             : 
    3704           0 :         for (i = 0; i < option->count; i++) {
    3705           0 :                 option_type = option->types[i];
    3706             : 
    3707           0 :                 switch (option_type.type) {
    3708           0 :                 case PRINTER_NOTIFY_TYPE:
    3709           0 :                         if (construct_notify_printer_info(p->msg_ctx,
    3710             :                                                           Printer, info,
    3711             :                                                           pinfo2, snum,
    3712             :                                                           &option_type, id,
    3713             :                                                           mem_ctx)) {
    3714           0 :                                 id--;
    3715             :                         }
    3716           0 :                         break;
    3717             : 
    3718           0 :                 case JOB_NOTIFY_TYPE:
    3719             : 
    3720           0 :                         count = print_queue_status(p->msg_ctx, snum, &queue,
    3721             :                                                    &status);
    3722             : 
    3723           0 :                         for (j = 0; j < count; j++) {
    3724           0 :                                 uint32_t jobid;
    3725           0 :                                 jobid = sysjob_to_jobid_pdb(pdb,
    3726           0 :                                                             queue[j].sysjob);
    3727           0 :                                 if (jobid == (uint32_t)-1) {
    3728           0 :                                         DEBUG(2, ("ignoring untracked job %d\n",
    3729             :                                                   queue[j].sysjob));
    3730           0 :                                         continue;
    3731             :                                 }
    3732             :                                 /* FIXME check return value */
    3733           0 :                                 construct_notify_jobs_info(p->msg_ctx,
    3734           0 :                                                            &queue[j], info,
    3735             :                                                            pinfo2, snum,
    3736             :                                                            &option_type,
    3737             :                                                            jobid,
    3738             :                                                            mem_ctx);
    3739             :                         }
    3740             : 
    3741           0 :                         SAFE_FREE(queue);
    3742           0 :                         break;
    3743             :                 }
    3744             :         }
    3745             : 
    3746             :         /*
    3747             :          * Debugging information, don't delete.
    3748             :          */
    3749             :         /*
    3750             :         DEBUG(1,("dumping the NOTIFY_INFO\n"));
    3751             :         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
    3752             :         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
    3753             : 
    3754             :         for (i=0; i<info->count; i++) {
    3755             :                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
    3756             :                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
    3757             :                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
    3758             :         }
    3759             :         */
    3760             : 
    3761           0 :         talloc_free(pinfo2);
    3762           0 :         result = WERR_OK;
    3763           0 : err_pdb_drop:
    3764           0 :         release_print_db(pdb);
    3765           0 :         return result;
    3766             : }
    3767             : 
    3768             : /****************************************************************
    3769             :  _spoolss_RouterRefreshPrinterChangeNotify
    3770             : ****************************************************************/
    3771             : 
    3772           4 : WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
    3773             :                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
    3774             : {
    3775           0 :         struct spoolss_NotifyInfo *info;
    3776             : 
    3777           4 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    3778           4 :         WERROR result = WERR_INVALID_HANDLE;
    3779             : 
    3780             :         /* we always have a spoolss_NotifyInfo struct */
    3781           4 :         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
    3782           4 :         if (!info) {
    3783           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3784           0 :                 goto done;
    3785             :         }
    3786             : 
    3787           4 :         *r->out.info = info;
    3788             : 
    3789           4 :         if (!Printer) {
    3790           0 :                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
    3791             :                         "Invalid handle (%s:%u:%u).\n",
    3792             :                         OUR_HANDLE(r->in.handle)));
    3793           0 :                 goto done;
    3794             :         }
    3795             : 
    3796           4 :         DEBUG(4,("Printer type %x\n",Printer->printer_type));
    3797             : 
    3798             :         /*
    3799             :          *      We are now using the change value, and
    3800             :          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
    3801             :          *      I don't have a global notification system, I'm sending back all the
    3802             :          *      information even when _NOTHING_ has changed.
    3803             :          */
    3804             : 
    3805             :         /* We need to keep track of the change value to send back in
    3806             :            RRPCN replies otherwise our updates are ignored. */
    3807             : 
    3808           4 :         Printer->notify.fnpcn = true;
    3809             : 
    3810           4 :         if (Printer->notify.cli_chan != NULL &&
    3811           4 :             Printer->notify.cli_chan->active_connections > 0) {
    3812           4 :                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
    3813             :                         "Saving change value in request [%x]\n",
    3814             :                         r->in.change_low));
    3815           4 :                 Printer->notify.change = r->in.change_low;
    3816             :         }
    3817             : 
    3818             :         /* just ignore the spoolss_NotifyOption */
    3819             : 
    3820           4 :         switch (Printer->printer_type) {
    3821           4 :                 case SPLHND_SERVER:
    3822           4 :                         result = printserver_notify_info(p, r->in.handle,
    3823             :                                                          info, p->mem_ctx);
    3824           4 :                         break;
    3825             : 
    3826           0 :                 case SPLHND_PRINTER:
    3827           0 :                         result = printer_notify_info(p, r->in.handle,
    3828             :                                                      info, p->mem_ctx);
    3829           0 :                         break;
    3830             :         }
    3831             : 
    3832           4 :         Printer->notify.fnpcn = false;
    3833             : 
    3834           4 : done:
    3835           4 :         return result;
    3836             : }
    3837             : 
    3838             : /********************************************************************
    3839             :  ********************************************************************/
    3840             : 
    3841        4076 : static WERROR create_printername(TALLOC_CTX *mem_ctx,
    3842             :                                  const char *servername,
    3843             :                                  const char *printername,
    3844             :                                  const char **printername_p)
    3845             : {
    3846             :         /* FIXME: add lp_force_printername() */
    3847             : 
    3848        4076 :         if (servername == NULL) {
    3849        1732 :                 *printername_p = talloc_strdup(mem_ctx, printername);
    3850        1732 :                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
    3851        1732 :                 return WERR_OK;
    3852             :         }
    3853             : 
    3854        2344 :         if (servername[0] == '\\' && servername[1] == '\\') {
    3855        2344 :                 servername += 2;
    3856             :         }
    3857             : 
    3858        2344 :         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
    3859        2344 :         W_ERROR_HAVE_NO_MEMORY(*printername_p);
    3860             : 
    3861        2344 :         return WERR_OK;
    3862             : }
    3863             : 
    3864             : /********************************************************************
    3865             :  ********************************************************************/
    3866             : 
    3867        2936 : static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
    3868             :                                           const char *printername)
    3869             : {
    3870        2936 :         if (dm == NULL) {
    3871          94 :                 return;
    3872             :         }
    3873             : 
    3874        2842 :         dm->devicename = talloc_strndup(dm, printername,
    3875        2842 :                                         MIN(strlen(printername), 31));
    3876             : }
    3877             : 
    3878             : /********************************************************************
    3879             :  * construct_printer_info_0
    3880             :  * fill a printer_info_0 struct
    3881             :  ********************************************************************/
    3882             : 
    3883         276 : static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
    3884             :                                       const struct auth_session_info *session_info,
    3885             :                                       struct messaging_context *msg_ctx,
    3886             :                                       struct spoolss_PrinterInfo2 *info2,
    3887             :                                       const char *servername,
    3888             :                                       struct spoolss_PrinterInfo0 *r,
    3889             :                                       int snum)
    3890             : {
    3891           0 :         int count;
    3892           0 :         struct printer_session_counter *session_counter;
    3893           0 :         struct timeval setuptime;
    3894           0 :         print_status_struct status;
    3895           0 :         WERROR result;
    3896           0 :         int os_major, os_minor, os_build;
    3897           0 :         const char *architecture;
    3898           0 :         uint32_t processor_architecture, processor_type;
    3899             : 
    3900         276 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    3901         276 :         if (!W_ERROR_IS_OK(result)) {
    3902           0 :                 return result;
    3903             :         }
    3904             : 
    3905         276 :         if (servername) {
    3906         140 :                 r->servername = talloc_strdup(mem_ctx, servername);
    3907         140 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    3908             :         } else {
    3909         136 :                 r->servername = NULL;
    3910             :         }
    3911             : 
    3912         276 :         count = print_queue_length(msg_ctx, snum, &status);
    3913             : 
    3914             :         /* check if we already have a counter for this printer */
    3915         660 :         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
    3916         620 :                 if (session_counter->snum == snum)
    3917         236 :                         break;
    3918             :         }
    3919             : 
    3920             :         /* it's the first time, add it to the list */
    3921         276 :         if (session_counter == NULL) {
    3922          40 :                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
    3923          40 :                 W_ERROR_HAVE_NO_MEMORY(session_counter);
    3924          40 :                 session_counter->snum                = snum;
    3925          40 :                 session_counter->counter     = 0;
    3926          40 :                 DLIST_ADD(counter_list, session_counter);
    3927             :         }
    3928             : 
    3929             :         /* increment it */
    3930         276 :         session_counter->counter++;
    3931             : 
    3932         276 :         r->cjobs                     = count;
    3933         276 :         r->total_jobs                        = 0;
    3934         276 :         r->total_bytes                       = 0;
    3935             : 
    3936         276 :         get_startup_time(&setuptime);
    3937         276 :         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
    3938             : 
    3939             :         /* JFM:
    3940             :          * the global_counter should be stored in a TDB as it's common to all the clients
    3941             :          * and should be zeroed on samba startup
    3942             :          */
    3943         276 :         r->global_counter            = session_counter->counter;
    3944         276 :         r->total_pages                       = 0;
    3945             : 
    3946             :         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
    3947         276 :         os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
    3948             :                                "spoolss", "os_major",
    3949             :                                GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
    3950         276 :         os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
    3951             :                                "spoolss", "os_minor",
    3952             :                                GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
    3953         276 :         os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
    3954             :                                "spoolss", "os_build",
    3955             :                                GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
    3956             : 
    3957         276 :         SCVAL(&r->version, 0, os_major);
    3958         276 :         SCVAL(&r->version, 1, os_minor);
    3959         276 :         SSVAL(&r->version, 2, os_build);
    3960             : 
    3961         276 :         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    3962             :                                             "spoolss",
    3963             :                                             "architecture",
    3964             :                                             GLOBAL_SPOOLSS_ARCHITECTURE);
    3965             : 
    3966         276 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
    3967         276 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_AMD64;
    3968         276 :                 processor_type          = PROCESSOR_AMD_X8664;
    3969           0 :         } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
    3970           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_ARM64;
    3971           0 :                 processor_type          = PROCESSOR_ARM820;
    3972             :         } else {
    3973           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_INTEL;
    3974           0 :                 processor_type          = PROCESSOR_INTEL_PENTIUM;
    3975             :         }
    3976             : 
    3977         276 :         r->free_build                        = SPOOLSS_RELEASE_BUILD;
    3978         276 :         r->spooling                  = 0;
    3979         276 :         r->max_spooling                      = 0;
    3980         276 :         r->session_counter           = session_counter->counter;
    3981         276 :         r->num_error_out_of_paper    = 0x0;
    3982         276 :         r->num_error_not_ready               = 0x0;          /* number of print failure */
    3983         276 :         r->job_error                 = 0x0;
    3984         276 :         r->number_of_processors              = 0x1;
    3985         276 :         r->processor_type            = processor_type;
    3986         276 :         r->high_part_total_bytes     = 0x0;
    3987             : 
    3988             :         /* ChangeID in milliseconds*/
    3989         276 :         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
    3990             :                                     info2->sharename, &r->change_id);
    3991             : 
    3992         276 :         r->last_error                        = WERR_OK;
    3993         276 :         r->status                    = nt_printq_status(status.status);
    3994         276 :         r->enumerate_network_printers        = 0x0;
    3995         276 :         r->c_setprinter                      = 0x0;
    3996         276 :         r->processor_architecture    = processor_architecture;
    3997         276 :         r->processor_level           = 0x6;          /* 6  ???*/
    3998         276 :         r->ref_ic                    = 0;
    3999         276 :         r->reserved2                 = 0;
    4000         276 :         r->reserved3                 = 0;
    4001             : 
    4002         276 :         return WERR_OK;
    4003             : }
    4004             : 
    4005             : 
    4006             : /********************************************************************
    4007             :  * construct_printer_info1
    4008             :  * fill a spoolss_PrinterInfo1 struct
    4009             : ********************************************************************/
    4010             : 
    4011         528 : static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
    4012             :                                       const struct spoolss_PrinterInfo2 *info2,
    4013             :                                       uint32_t flags,
    4014             :                                       const char *servername,
    4015             :                                       struct spoolss_PrinterInfo1 *r,
    4016             :                                       int snum)
    4017             : {
    4018           0 :         const struct loadparm_substitution *lp_sub =
    4019         528 :                 loadparm_s3_global_substitution();
    4020           0 :         WERROR result;
    4021             : 
    4022         528 :         r->flags             = flags;
    4023             : 
    4024         528 :         if (info2->comment == NULL || info2->comment[0] == '\0') {
    4025         388 :                 r->comment   = lp_comment(mem_ctx, lp_sub, snum);
    4026             :         } else {
    4027         140 :                 r->comment   = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
    4028             :         }
    4029         528 :         W_ERROR_HAVE_NO_MEMORY(r->comment);
    4030             : 
    4031         528 :         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
    4032         528 :         if (!W_ERROR_IS_OK(result)) {
    4033           0 :                 return result;
    4034             :         }
    4035             : 
    4036        1056 :         r->description               = talloc_asprintf(mem_ctx, "%s,%s,%s",
    4037             :                                                   r->name,
    4038         528 :                                                   info2->drivername,
    4039             :                                                   r->comment);
    4040         528 :         W_ERROR_HAVE_NO_MEMORY(r->description);
    4041             : 
    4042         528 :         return WERR_OK;
    4043             : }
    4044             : 
    4045             : /********************************************************************
    4046             :  * construct_printer_info2
    4047             :  * fill a spoolss_PrinterInfo2 struct
    4048             : ********************************************************************/
    4049             : 
    4050        1272 : static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
    4051             :                                       struct messaging_context *msg_ctx,
    4052             :                                       const struct spoolss_PrinterInfo2 *info2,
    4053             :                                       const char *servername,
    4054             :                                       struct spoolss_PrinterInfo2 *r,
    4055             :                                       int snum)
    4056             : {
    4057           0 :         const struct loadparm_substitution *lp_sub =
    4058        1272 :                 loadparm_s3_global_substitution();
    4059           0 :         int count;
    4060           0 :         print_status_struct status;
    4061           0 :         WERROR result;
    4062             : 
    4063        1272 :         count = print_queue_length(msg_ctx, snum, &status);
    4064             : 
    4065        1272 :         if (servername) {
    4066         572 :                 r->servername                = talloc_strdup(mem_ctx, servername);
    4067         572 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    4068             :         } else {
    4069         700 :                 r->servername                = NULL;
    4070             :         }
    4071             : 
    4072        1272 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4073        1272 :         if (!W_ERROR_IS_OK(result)) {
    4074           0 :                 return result;
    4075             :         }
    4076             : 
    4077        1272 :         r->sharename         = lp_servicename(mem_ctx, lp_sub, snum);
    4078        1272 :         W_ERROR_HAVE_NO_MEMORY(r->sharename);
    4079        1272 :         r->portname          = talloc_strdup(mem_ctx, info2->portname);
    4080        1272 :         W_ERROR_HAVE_NO_MEMORY(r->portname);
    4081        1272 :         r->drivername                = talloc_strdup(mem_ctx, info2->drivername);
    4082        1272 :         W_ERROR_HAVE_NO_MEMORY(r->drivername);
    4083             : 
    4084        1272 :         if (info2->comment[0] == '\0') {
    4085         876 :                 r->comment   = lp_comment(mem_ctx, lp_sub, snum);
    4086             :         } else {
    4087         396 :                 r->comment   = talloc_strdup(mem_ctx, info2->comment);
    4088             :         }
    4089        1272 :         W_ERROR_HAVE_NO_MEMORY(r->comment);
    4090             : 
    4091        1272 :         r->location  = talloc_strdup(mem_ctx, info2->location);
    4092        1272 :         if (info2->location[0] == '\0') {
    4093        1192 :                 const char *loc = NULL;
    4094           0 :                 NTSTATUS nt_status;
    4095             : 
    4096        1192 :                 nt_status = printer_list_get_printer(mem_ctx,
    4097        1192 :                                                      info2->sharename,
    4098             :                                                      NULL,
    4099             :                                                      &loc,
    4100             :                                                      NULL);
    4101        1192 :                 if (NT_STATUS_IS_OK(nt_status)) {
    4102           0 :                         if (loc != NULL) {
    4103           0 :                                 r->location = talloc_strdup(mem_ctx, loc);
    4104             :                         }
    4105             :                 }
    4106             :         }
    4107        1272 :         W_ERROR_HAVE_NO_MEMORY(r->location);
    4108             : 
    4109        1272 :         r->sepfile           = talloc_strdup(mem_ctx, info2->sepfile);
    4110        1272 :         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
    4111        1272 :         r->printprocessor    = talloc_strdup(mem_ctx, info2->printprocessor);
    4112        1272 :         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
    4113        1272 :         r->datatype          = talloc_strdup(mem_ctx, info2->datatype);
    4114        1272 :         W_ERROR_HAVE_NO_MEMORY(r->datatype);
    4115        1272 :         r->parameters                = talloc_strdup(mem_ctx, info2->parameters);
    4116        1272 :         W_ERROR_HAVE_NO_MEMORY(r->parameters);
    4117             : 
    4118        1272 :         r->attributes                = info2->attributes;
    4119             : 
    4120        1272 :         r->priority          = info2->priority;
    4121        1272 :         r->defaultpriority   = info2->defaultpriority;
    4122        1272 :         r->starttime         = info2->starttime;
    4123        1272 :         r->untiltime         = info2->untiltime;
    4124        1272 :         r->status            = nt_printq_status(status.status);
    4125        1272 :         r->cjobs             = count;
    4126        1272 :         r->averageppm                = info2->averageppm;
    4127             : 
    4128        1272 :         if (info2->devmode != NULL) {
    4129        1186 :                 result = copy_devicemode(mem_ctx,
    4130        1186 :                                          info2->devmode,
    4131             :                                          &r->devmode);
    4132        1186 :                 if (!W_ERROR_IS_OK(result)) {
    4133           0 :                         return result;
    4134             :                 }
    4135          86 :         } else if (lp_default_devmode(snum)) {
    4136           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    4137           0 :                                                         info2->printername,
    4138             :                                                         &r->devmode);
    4139           0 :                 if (!W_ERROR_IS_OK(result)) {
    4140           0 :                         return result;
    4141             :                 }
    4142             :         } else {
    4143          86 :                 r->devmode = NULL;
    4144          86 :                 DEBUG(8,("Returning NULL Devicemode!\n"));
    4145             :         }
    4146             : 
    4147        1272 :         compose_devicemode_devicename(r->devmode, r->printername);
    4148             : 
    4149        1272 :         r->secdesc = NULL;
    4150             : 
    4151        1272 :         if (info2->secdesc != NULL) {
    4152             :                 /* don't use talloc_steal() here unless you do a deep steal of all
    4153             :                    the SEC_DESC members */
    4154             : 
    4155        1272 :                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
    4156        1272 :                 if (r->secdesc == NULL) {
    4157           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    4158             :                 }
    4159             :         }
    4160             : 
    4161        1272 :         return WERR_OK;
    4162             : }
    4163             : 
    4164             : /********************************************************************
    4165             :  * construct_printer_info3
    4166             :  * fill a spoolss_PrinterInfo3 struct
    4167             :  ********************************************************************/
    4168             : 
    4169         144 : static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
    4170             :                                       const struct spoolss_PrinterInfo2 *info2,
    4171             :                                       const char *servername,
    4172             :                                       struct spoolss_PrinterInfo3 *r,
    4173             :                                       int snum)
    4174             : {
    4175             :         /* These are the components of the SD we are returning. */
    4176             : 
    4177         144 :         if (info2->secdesc != NULL) {
    4178             :                 /* don't use talloc_steal() here unless you do a deep steal of all
    4179             :                    the SEC_DESC members */
    4180             : 
    4181         144 :                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
    4182         144 :                 if (r->secdesc == NULL) {
    4183           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    4184             :                 }
    4185             :         }
    4186             : 
    4187         144 :         return WERR_OK;
    4188             : }
    4189             : 
    4190             : /********************************************************************
    4191             :  * construct_printer_info4
    4192             :  * fill a spoolss_PrinterInfo4 struct
    4193             :  ********************************************************************/
    4194             : 
    4195         168 : static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
    4196             :                                       const struct spoolss_PrinterInfo2 *info2,
    4197             :                                       const char *servername,
    4198             :                                       struct spoolss_PrinterInfo4 *r,
    4199             :                                       int snum)
    4200             : {
    4201           0 :         WERROR result;
    4202             : 
    4203         168 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4204         168 :         if (!W_ERROR_IS_OK(result)) {
    4205           0 :                 return result;
    4206             :         }
    4207             : 
    4208         168 :         if (servername) {
    4209           8 :                 r->servername        = talloc_strdup(mem_ctx, servername);
    4210           8 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    4211             :         } else {
    4212         160 :                 r->servername = NULL;
    4213             :         }
    4214             : 
    4215         168 :         r->attributes        = info2->attributes;
    4216             : 
    4217         168 :         return WERR_OK;
    4218             : }
    4219             : 
    4220             : /********************************************************************
    4221             :  * construct_printer_info5
    4222             :  * fill a spoolss_PrinterInfo5 struct
    4223             :  ********************************************************************/
    4224             : 
    4225         168 : static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
    4226             :                                       const struct spoolss_PrinterInfo2 *info2,
    4227             :                                       const char *servername,
    4228             :                                       struct spoolss_PrinterInfo5 *r,
    4229             :                                       int snum)
    4230             : {
    4231           0 :         WERROR result;
    4232             : 
    4233         168 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4234         168 :         if (!W_ERROR_IS_OK(result)) {
    4235           0 :                 return result;
    4236             :         }
    4237             : 
    4238         168 :         r->portname  = talloc_strdup(mem_ctx, info2->portname);
    4239         168 :         W_ERROR_HAVE_NO_MEMORY(r->portname);
    4240             : 
    4241         168 :         r->attributes        = info2->attributes;
    4242             : 
    4243             :         /*
    4244             :          * These two are not used by NT+ according to MSDN. However the values
    4245             :          * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
    4246             :          */
    4247         168 :         r->device_not_selected_timeout               = 0xafc8; /* 45 sec */
    4248         168 :         r->transmission_retry_timeout                = 0xafc8; /* 45 sec */
    4249             : 
    4250         168 :         return WERR_OK;
    4251             : }
    4252             : 
    4253             : /********************************************************************
    4254             :  * construct_printer_info_6
    4255             :  * fill a spoolss_PrinterInfo6 struct
    4256             :  ********************************************************************/
    4257             : 
    4258          88 : static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
    4259             :                                       struct messaging_context *msg_ctx,
    4260             :                                       const struct spoolss_PrinterInfo2 *info2,
    4261             :                                       const char *servername,
    4262             :                                       struct spoolss_PrinterInfo6 *r,
    4263             :                                       int snum)
    4264             : {
    4265           0 :         print_status_struct status;
    4266             : 
    4267          88 :         print_queue_length(msg_ctx, snum, &status);
    4268             : 
    4269          88 :         r->status = nt_printq_status(status.status);
    4270             : 
    4271          88 :         return WERR_OK;
    4272             : }
    4273             : 
    4274             : /********************************************************************
    4275             :  * construct_printer_info7
    4276             :  * fill a spoolss_PrinterInfo7 struct
    4277             :  ********************************************************************/
    4278             : 
    4279         112 : static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
    4280             :                                       struct messaging_context *msg_ctx,
    4281             :                                       const char *servername,
    4282             :                                       struct spoolss_PrinterInfo7 *r,
    4283             :                                       int snum)
    4284             : {
    4285           0 :         const struct loadparm_substitution *lp_sub =
    4286         112 :                 loadparm_s3_global_substitution();
    4287           0 :         const struct auth_session_info *session_info;
    4288         112 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    4289           0 :         char *printer;
    4290           0 :         WERROR werr;
    4291         112 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    4292         112 :         if (tmp_ctx == NULL) {
    4293           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4294             :         }
    4295             : 
    4296         112 :         session_info = get_session_info_system();
    4297         112 :         SMB_ASSERT(session_info != NULL);
    4298             : 
    4299         112 :         printer = lp_servicename(tmp_ctx, lp_sub, snum);
    4300         112 :         if (printer == NULL) {
    4301           0 :                 DEBUG(0, ("invalid printer snum %d\n", snum));
    4302           0 :                 werr = WERR_INVALID_PARAMETER;
    4303           0 :                 goto out_tmp_free;
    4304             :         }
    4305             : 
    4306         112 :         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
    4307             :                                  servername, printer, &pinfo2)) {
    4308           0 :                 struct GUID guid;
    4309           0 :                 char *guidstr;
    4310           0 :                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
    4311             :                                            printer, &guid);
    4312           0 :                 if (!W_ERROR_IS_OK(werr)) {
    4313             :                         /*
    4314             :                          * If we do not have a GUID entry in the registry, then
    4315             :                          * try to retrieve it from AD and store it now.
    4316             :                          */
    4317           0 :                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
    4318             :                                                         &guid);
    4319           0 :                         if (!W_ERROR_IS_OK(werr)) {
    4320           0 :                                 DBG_NOTICE("Failed to retrieve GUID for "
    4321             :                                            "printer [%s] from AD - %s\n",
    4322             :                                            printer,
    4323             :                                            win_errstr(werr));
    4324           0 :                                 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
    4325             :                                         /*
    4326             :                                          * If we did not find it in AD, then it
    4327             :                                          * is unpublished and we should reflect
    4328             :                                          * this in the registry and return
    4329             :                                          * success.
    4330             :                                          */
    4331           0 :                                         DBG_WARNING("Unpublish printer [%s]\n",
    4332             :                                                     pinfo2->sharename);
    4333           0 :                                         nt_printer_publish(tmp_ctx,
    4334             :                                                            session_info,
    4335             :                                                            msg_ctx,
    4336             :                                                            pinfo2,
    4337             :                                                            DSPRINT_UNPUBLISH);
    4338           0 :                                         r->guid = talloc_strdup(mem_ctx, "");
    4339           0 :                                         r->action = DSPRINT_UNPUBLISH;
    4340             : 
    4341           0 :                                         if (r->guid == NULL) {
    4342           0 :                                                 werr = WERR_NOT_ENOUGH_MEMORY;
    4343             :                                         } else {
    4344           0 :                                                 werr = WERR_OK;
    4345             :                                         }
    4346             :                                 }
    4347           0 :                                 goto out_tmp_free;
    4348             :                         }
    4349             : 
    4350           0 :                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
    4351           0 :                         if (!W_ERROR_IS_OK(werr)) {
    4352           0 :                                 DEBUG(3, ("failed to store printer %s guid\n",
    4353             :                                           printer));
    4354             :                         }
    4355             :                 }
    4356             : 
    4357             :                 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
    4358           0 :                 guidstr = GUID_string2(mem_ctx, &guid);
    4359           0 :                 if (guidstr == NULL) {
    4360           0 :                         werr = WERR_NOT_ENOUGH_MEMORY;
    4361           0 :                         goto out_tmp_free;
    4362             :                 }
    4363             :                 /* Convert GUID string to uppercase otherwise printers
    4364             :                  * are pruned */
    4365           0 :                 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
    4366           0 :                 r->action = DSPRINT_PUBLISH;
    4367             : 
    4368           0 :                 TALLOC_FREE(guidstr);
    4369             :         } else {
    4370         112 :                 r->guid = talloc_strdup(mem_ctx, "");
    4371         112 :                 r->action = DSPRINT_UNPUBLISH;
    4372             :         }
    4373         112 :         if (r->guid == NULL) {
    4374           0 :                 werr = WERR_NOT_ENOUGH_MEMORY;
    4375           0 :                 goto out_tmp_free;
    4376             :         }
    4377             : 
    4378         112 :         werr = WERR_OK;
    4379         112 : out_tmp_free:
    4380         112 :         talloc_free(tmp_ctx);
    4381         112 :         return werr;
    4382             : }
    4383             : 
    4384             : /********************************************************************
    4385             :  * construct_printer_info8
    4386             :  * fill a spoolss_PrinterInfo8 struct
    4387             :  ********************************************************************/
    4388             : 
    4389        1664 : static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
    4390             :                                       const struct spoolss_PrinterInfo2 *info2,
    4391             :                                       const char *servername,
    4392             :                                       struct spoolss_DeviceModeInfo *r,
    4393             :                                       int snum)
    4394             : {
    4395           0 :         WERROR result;
    4396           0 :         const char *printername;
    4397             : 
    4398        1664 :         result = create_printername(mem_ctx, servername, info2->printername, &printername);
    4399        1664 :         if (!W_ERROR_IS_OK(result)) {
    4400           0 :                 return result;
    4401             :         }
    4402             : 
    4403        1664 :         if (info2->devmode != NULL) {
    4404        1656 :                 result = copy_devicemode(mem_ctx,
    4405        1656 :                                          info2->devmode,
    4406             :                                          &r->devmode);
    4407        1656 :                 if (!W_ERROR_IS_OK(result)) {
    4408           0 :                         return result;
    4409             :                 }
    4410           8 :         } else if (lp_default_devmode(snum)) {
    4411           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    4412           0 :                                                         info2->printername,
    4413             :                                                         &r->devmode);
    4414           0 :                 if (!W_ERROR_IS_OK(result)) {
    4415           0 :                         return result;
    4416             :                 }
    4417             :         } else {
    4418           8 :                 r->devmode = NULL;
    4419           8 :                 DEBUG(8,("Returning NULL Devicemode!\n"));
    4420             :         }
    4421             : 
    4422        1664 :         compose_devicemode_devicename(r->devmode, printername);
    4423             : 
    4424        1664 :         return WERR_OK;
    4425             : }
    4426             : 
    4427             : /********************************************************************
    4428             :  Spoolss_enumprinters.
    4429             : ********************************************************************/
    4430             : 
    4431         180 : static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
    4432             :                                            const struct auth_session_info *session_info,
    4433             :                                            struct messaging_context *msg_ctx,
    4434             :                                            const char *servername,
    4435             :                                            uint32_t level,
    4436             :                                            uint32_t flags,
    4437             :                                            union spoolss_PrinterInfo **info_p,
    4438             :                                            uint32_t *count_p)
    4439             : {
    4440           0 :         int snum;
    4441           0 :         int n_services;
    4442         180 :         union spoolss_PrinterInfo *info = NULL;
    4443         180 :         uint32_t count = 0;
    4444         180 :         WERROR result = WERR_OK;
    4445         180 :         struct dcerpc_binding_handle *b = NULL;
    4446         180 :         TALLOC_CTX *tmp_ctx = NULL;
    4447             : 
    4448         180 :         tmp_ctx = talloc_new(mem_ctx);
    4449         180 :         if (!tmp_ctx) {
    4450           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4451             :         }
    4452             : 
    4453             :         /*
    4454             :          * printer shares are updated on client enumeration. The background
    4455             :          * printer process updates printer_list.tdb at regular intervals.
    4456             :          */
    4457         180 :         become_root();
    4458         180 :         delete_and_reload_printers();
    4459         180 :         unbecome_root();
    4460             : 
    4461         180 :         n_services = lp_numservices();
    4462         180 :         *count_p = 0;
    4463         180 :         *info_p = NULL;
    4464             : 
    4465       12230 :         for (snum = 0; snum < n_services; snum++) {
    4466             : 
    4467           0 :                 const char *printer;
    4468           0 :                 struct spoolss_PrinterInfo2 *info2;
    4469             : 
    4470       12050 :                 if (!snum_is_shared_printer(snum)) {
    4471       11070 :                         continue;
    4472             :                 }
    4473             : 
    4474         980 :                 printer = lp_const_servicename(snum);
    4475             : 
    4476         980 :                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
    4477             :                         printer, snum));
    4478             : 
    4479         980 :                 if (b == NULL) {
    4480         180 :                         result = winreg_printer_binding_handle(tmp_ctx,
    4481             :                                                                session_info,
    4482             :                                                                msg_ctx,
    4483             :                                                                &b);
    4484         180 :                         if (!W_ERROR_IS_OK(result)) {
    4485           0 :                                 goto out;
    4486             :                         }
    4487             :                 }
    4488             : 
    4489         980 :                 result = winreg_create_printer(tmp_ctx, b,
    4490             :                                                printer);
    4491         980 :                 if (!W_ERROR_IS_OK(result)) {
    4492           0 :                         goto out;
    4493             :                 }
    4494             : 
    4495         980 :                 info = talloc_realloc(tmp_ctx, info,
    4496             :                                             union spoolss_PrinterInfo,
    4497             :                                             count + 1);
    4498         980 :                 if (!info) {
    4499           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    4500           0 :                         goto out;
    4501             :                 }
    4502             : 
    4503         980 :                 result = winreg_get_printer(tmp_ctx, b,
    4504             :                                             printer, &info2);
    4505         980 :                 if (!W_ERROR_IS_OK(result)) {
    4506           0 :                         goto out;
    4507             :                 }
    4508             : 
    4509         980 :                 switch (level) {
    4510          40 :                 case 0:
    4511          40 :                         result = construct_printer_info0(info, session_info,
    4512             :                                                          msg_ctx, info2,
    4513             :                                                          servername,
    4514          40 :                                                          &info[count].info0, snum);
    4515          40 :                         break;
    4516         440 :                 case 1:
    4517         440 :                         result = construct_printer_info1(info, info2, flags,
    4518             :                                                          servername,
    4519         440 :                                                          &info[count].info1, snum);
    4520         440 :                         break;
    4521         340 :                 case 2:
    4522         340 :                         result = construct_printer_info2(info, msg_ctx, info2,
    4523             :                                                          servername,
    4524         340 :                                                          &info[count].info2, snum);
    4525         340 :                         break;
    4526          80 :                 case 4:
    4527          80 :                         result = construct_printer_info4(info, info2,
    4528             :                                                          servername,
    4529          80 :                                                          &info[count].info4, snum);
    4530          80 :                         break;
    4531          80 :                 case 5:
    4532          80 :                         result = construct_printer_info5(info, info2,
    4533             :                                                          servername,
    4534          80 :                                                          &info[count].info5, snum);
    4535          80 :                         break;
    4536             : 
    4537           0 :                 default:
    4538           0 :                         result = WERR_INVALID_LEVEL;
    4539           0 :                         goto out;
    4540             :                 }
    4541             : 
    4542         980 :                 if (!W_ERROR_IS_OK(result)) {
    4543           0 :                         goto out;
    4544             :                 }
    4545             : 
    4546         980 :                 count++;
    4547             :         }
    4548             : 
    4549         180 : out:
    4550         180 :         if (W_ERROR_IS_OK(result)) {
    4551         180 :                 *info_p = talloc_move(mem_ctx, &info);
    4552         180 :                 *count_p = count;
    4553             :         }
    4554             : 
    4555         180 :         talloc_free(tmp_ctx);
    4556             : 
    4557         180 :         return result;
    4558             : }
    4559             : 
    4560             : /********************************************************************
    4561             :  * handle enumeration of printers at level 0
    4562             :  ********************************************************************/
    4563             : 
    4564           8 : static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
    4565             :                                   const struct auth_session_info *session_info,
    4566             :                                   struct messaging_context *msg_ctx,
    4567             :                                   uint32_t flags,
    4568             :                                   const char *servername,
    4569             :                                   union spoolss_PrinterInfo **info,
    4570             :                                   uint32_t *count)
    4571             : {
    4572           8 :         DEBUG(4,("enum_all_printers_info_0\n"));
    4573             : 
    4574           8 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4575             :                                             servername, 0, flags, info, count);
    4576             : }
    4577             : 
    4578             : 
    4579             : /********************************************************************
    4580             : ********************************************************************/
    4581             : 
    4582          72 : static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
    4583             :                                        const struct auth_session_info *session_info,
    4584             :                                        struct messaging_context *msg_ctx,
    4585             :                                        const char *servername,
    4586             :                                        uint32_t flags,
    4587             :                                        union spoolss_PrinterInfo **info,
    4588             :                                        uint32_t *count)
    4589             : {
    4590          72 :         DEBUG(4,("enum_all_printers_info_1\n"));
    4591             : 
    4592          72 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4593             :                                             servername, 1, flags, info, count);
    4594             : }
    4595             : 
    4596             : /********************************************************************
    4597             :  enum_all_printers_info_1_local.
    4598             : *********************************************************************/
    4599             : 
    4600          72 : static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
    4601             :                                              const struct auth_session_info *session_info,
    4602             :                                              struct messaging_context *msg_ctx,
    4603             :                                              const char *servername,
    4604             :                                              union spoolss_PrinterInfo **info,
    4605             :                                              uint32_t *count)
    4606             : {
    4607          72 :         DEBUG(4,("enum_all_printers_info_1_local\n"));
    4608             : 
    4609          72 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4610             :                                         servername, PRINTER_ENUM_ICON8, info, count);
    4611             : }
    4612             : 
    4613             : /********************************************************************
    4614             :  enum_all_printers_info_1_name.
    4615             : *********************************************************************/
    4616             : 
    4617           0 : static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
    4618             :                                             const struct auth_session_info *session_info,
    4619             :                                             struct messaging_context *msg_ctx,
    4620             :                                             const char *servername,
    4621             :                                             union spoolss_PrinterInfo **info,
    4622             :                                             uint32_t *count)
    4623             : {
    4624           0 :         const char *s = servername;
    4625             : 
    4626           0 :         DEBUG(4,("enum_all_printers_info_1_name\n"));
    4627             : 
    4628           0 :         if (servername != NULL &&
    4629           0 :             (servername[0] == '\\') && (servername[1] == '\\')) {
    4630           0 :                 s = servername + 2;
    4631             :         }
    4632             : 
    4633           0 :         if (!is_myname_or_ipaddr(s)) {
    4634           0 :                 return WERR_INVALID_NAME;
    4635             :         }
    4636             : 
    4637           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4638             :                                         servername, PRINTER_ENUM_ICON8, info, count);
    4639             : }
    4640             : 
    4641             : /********************************************************************
    4642             :  enum_all_printers_info_1_network.
    4643             : *********************************************************************/
    4644             : 
    4645           0 : static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
    4646             :                                                const struct auth_session_info *session_info,
    4647             :                                                struct messaging_context *msg_ctx,
    4648             :                                                const char *servername,
    4649             :                                                union spoolss_PrinterInfo **info,
    4650             :                                                uint32_t *count)
    4651             : {
    4652           0 :         const char *s = servername;
    4653             : 
    4654           0 :         DEBUG(4,("enum_all_printers_info_1_network\n"));
    4655             : 
    4656             :         /* If we respond to a enum_printers level 1 on our name with flags
    4657             :            set to PRINTER_ENUM_REMOTE with a list of printers then these
    4658             :            printers incorrectly appear in the APW browse list.
    4659             :            Specifically the printers for the server appear at the workgroup
    4660             :            level where all the other servers in the domain are
    4661             :            listed. Windows responds to this call with a
    4662             :            WERR_CAN_NOT_COMPLETE so we should do the same. */
    4663             : 
    4664           0 :         if (servername != NULL &&
    4665           0 :             (servername[0] == '\\') && (servername[1] == '\\')) {
    4666           0 :                  s = servername + 2;
    4667             :         }
    4668             : 
    4669           0 :         if (is_myname_or_ipaddr(s)) {
    4670           0 :                  return WERR_CAN_NOT_COMPLETE;
    4671             :         }
    4672             : 
    4673           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4674             :                                         servername, PRINTER_ENUM_NAME, info, count);
    4675             : }
    4676             : 
    4677             : /********************************************************************
    4678             :  * api_spoolss_enumprinters
    4679             :  *
    4680             :  * called from api_spoolss_enumprinters (see this to understand)
    4681             :  ********************************************************************/
    4682             : 
    4683          68 : static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
    4684             :                                        const struct auth_session_info *session_info,
    4685             :                                        struct messaging_context *msg_ctx,
    4686             :                                        const char *servername,
    4687             :                                        union spoolss_PrinterInfo **info,
    4688             :                                        uint32_t *count)
    4689             : {
    4690          68 :         DEBUG(4,("enum_all_printers_info_2\n"));
    4691             : 
    4692          68 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4693             :                                             servername, 2, 0, info, count);
    4694             : }
    4695             : 
    4696             : /********************************************************************
    4697             :  * handle enumeration of printers at level 1
    4698             :  ********************************************************************/
    4699             : 
    4700          72 : static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
    4701             :                                   const struct auth_session_info *session_info,
    4702             :                                   struct messaging_context *msg_ctx,
    4703             :                                   uint32_t flags,
    4704             :                                   const char *servername,
    4705             :                                   union spoolss_PrinterInfo **info,
    4706             :                                   uint32_t *count)
    4707             : {
    4708             :         /* Not all the flags are equals */
    4709             : 
    4710          72 :         if (flags & PRINTER_ENUM_LOCAL) {
    4711          72 :                 return enum_all_printers_info_1_local(mem_ctx, session_info,
    4712             :                                                       msg_ctx, servername, info, count);
    4713             :         }
    4714             : 
    4715           0 :         if (flags & PRINTER_ENUM_NAME) {
    4716           0 :                 return enum_all_printers_info_1_name(mem_ctx, session_info,
    4717             :                                                      msg_ctx, servername, info,
    4718             :                                                      count);
    4719             :         }
    4720             : 
    4721           0 :         if (flags & PRINTER_ENUM_NETWORK) {
    4722           0 :                 return enum_all_printers_info_1_network(mem_ctx, session_info,
    4723             :                                                         msg_ctx, servername, info,
    4724             :                                                         count);
    4725             :         }
    4726             : 
    4727           0 :         return WERR_OK; /* NT4sp5 does that */
    4728             : }
    4729             : 
    4730             : /********************************************************************
    4731             :  * handle enumeration of printers at level 2
    4732             :  ********************************************************************/
    4733             : 
    4734          68 : static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
    4735             :                                   const struct auth_session_info *session_info,
    4736             :                                   struct messaging_context *msg_ctx,
    4737             :                                   uint32_t flags,
    4738             :                                   const char *servername,
    4739             :                                   union spoolss_PrinterInfo **info,
    4740             :                                   uint32_t *count)
    4741             : {
    4742          68 :         if (flags & PRINTER_ENUM_LOCAL) {
    4743             : 
    4744          52 :                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
    4745             :                                                 servername,
    4746             :                                                 info, count);
    4747             :         }
    4748             : 
    4749          16 :         if (flags & PRINTER_ENUM_NAME) {
    4750          16 :                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
    4751           0 :                         return WERR_INVALID_NAME;
    4752             :                 }
    4753             : 
    4754          16 :                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
    4755             :                                                 servername,
    4756             :                                                 info, count);
    4757             :         }
    4758             : 
    4759           0 :         if (flags & PRINTER_ENUM_REMOTE) {
    4760           0 :                 return WERR_INVALID_LEVEL;
    4761             :         }
    4762             : 
    4763           0 :         return WERR_OK;
    4764             : }
    4765             : 
    4766             : /********************************************************************
    4767             :  * handle enumeration of printers at level 4
    4768             :  ********************************************************************/
    4769             : 
    4770          16 : static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
    4771             :                                   const struct auth_session_info *session_info,
    4772             :                                   struct messaging_context *msg_ctx,
    4773             :                                   uint32_t flags,
    4774             :                                   const char *servername,
    4775             :                                   union spoolss_PrinterInfo **info,
    4776             :                                   uint32_t *count)
    4777             : {
    4778          16 :         DEBUG(4,("enum_all_printers_info_4\n"));
    4779             : 
    4780          16 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4781             :                                             servername, 4, flags, info, count);
    4782             : }
    4783             : 
    4784             : 
    4785             : /********************************************************************
    4786             :  * handle enumeration of printers at level 5
    4787             :  ********************************************************************/
    4788             : 
    4789          16 : static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
    4790             :                                   const struct auth_session_info *session_info,
    4791             :                                   struct messaging_context *msg_ctx,
    4792             :                                   uint32_t flags,
    4793             :                                   const char *servername,
    4794             :                                   union spoolss_PrinterInfo **info,
    4795             :                                   uint32_t *count)
    4796             : {
    4797          16 :         DEBUG(4,("enum_all_printers_info_5\n"));
    4798             : 
    4799          16 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4800             :                                             servername, 5, flags, info, count);
    4801             : }
    4802             : 
    4803             : /****************************************************************
    4804             :  _spoolss_EnumPrinters
    4805             : ****************************************************************/
    4806             : 
    4807         180 : WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
    4808             :                              struct spoolss_EnumPrinters *r)
    4809             : {
    4810         180 :         const struct auth_session_info *session_info = get_session_info_system();
    4811           0 :         WERROR result;
    4812             : 
    4813             :         /* that's an [in out] buffer */
    4814             : 
    4815         180 :         if (!r->in.buffer && (r->in.offered != 0)) {
    4816           0 :                 return WERR_INVALID_PARAMETER;
    4817             :         }
    4818             : 
    4819         180 :         DEBUG(4,("_spoolss_EnumPrinters\n"));
    4820             : 
    4821         180 :         *r->out.needed = 0;
    4822         180 :         *r->out.count = 0;
    4823         180 :         *r->out.info = NULL;
    4824             : 
    4825             :         /*
    4826             :          * Level 1:
    4827             :          *          flags==PRINTER_ENUM_NAME
    4828             :          *           if name=="" then enumerates all printers
    4829             :          *           if name!="" then enumerate the printer
    4830             :          *          flags==PRINTER_ENUM_REMOTE
    4831             :          *          name is NULL, enumerate printers
    4832             :          * Level 2: name!="" enumerates printers, name can't be NULL
    4833             :          * Level 3: doesn't exist
    4834             :          * Level 4: does a local registry lookup
    4835             :          * Level 5: same as Level 2
    4836             :          */
    4837             : 
    4838         180 :         if (r->in.server && r->in.server[0] == '\0') {
    4839          80 :                 r->in.server = NULL;
    4840             :         }
    4841             : 
    4842         180 :         switch (r->in.level) {
    4843           8 :         case 0:
    4844           8 :                 result = enumprinters_level0(p->mem_ctx, session_info,
    4845             :                                              p->msg_ctx, r->in.flags,
    4846             :                                              r->in.server,
    4847             :                                              r->out.info, r->out.count);
    4848           8 :                 break;
    4849          72 :         case 1:
    4850          72 :                 result = enumprinters_level1(p->mem_ctx, session_info,
    4851             :                                              p->msg_ctx, r->in.flags,
    4852             :                                              r->in.server,
    4853             :                                              r->out.info, r->out.count);
    4854          72 :                 break;
    4855          68 :         case 2:
    4856          68 :                 result = enumprinters_level2(p->mem_ctx, session_info,
    4857             :                                              p->msg_ctx, r->in.flags,
    4858             :                                              r->in.server,
    4859             :                                              r->out.info, r->out.count);
    4860          68 :                 break;
    4861          16 :         case 4:
    4862          16 :                 result = enumprinters_level4(p->mem_ctx, session_info,
    4863             :                                              p->msg_ctx, r->in.flags,
    4864             :                                              r->in.server,
    4865             :                                              r->out.info, r->out.count);
    4866          16 :                 break;
    4867          16 :         case 5:
    4868          16 :                 result = enumprinters_level5(p->mem_ctx, session_info,
    4869             :                                              p->msg_ctx, r->in.flags,
    4870             :                                              r->in.server,
    4871             :                                              r->out.info, r->out.count);
    4872          16 :                 break;
    4873           0 :         default:
    4874           0 :                 return WERR_INVALID_LEVEL;
    4875             :         }
    4876             : 
    4877         180 :         if (!W_ERROR_IS_OK(result)) {
    4878           0 :                 return result;
    4879             :         }
    4880             : 
    4881         180 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    4882             :                                                      spoolss_EnumPrinters,
    4883             :                                                      *r->out.info, r->in.level,
    4884             :                                                      *r->out.count);
    4885         180 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    4886         180 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    4887             : 
    4888         180 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    4889             : }
    4890             : 
    4891             : /****************************************************************
    4892             :  _spoolss_GetPrinter
    4893             : ****************************************************************/
    4894             : 
    4895        3512 : WERROR _spoolss_GetPrinter(struct pipes_struct *p,
    4896             :                            struct spoolss_GetPrinter *r)
    4897             : {
    4898        3512 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    4899        3512 :         struct spoolss_PrinterInfo2 *info2 = NULL;
    4900        3512 :         WERROR result = WERR_OK;
    4901           0 :         int snum;
    4902             : 
    4903             :         /* that's an [in out] buffer */
    4904             : 
    4905        3512 :         if (!r->in.buffer && (r->in.offered != 0)) {
    4906           0 :                 result = WERR_INVALID_PARAMETER;
    4907           0 :                 goto err_info_free;
    4908             :         }
    4909             : 
    4910        3512 :         *r->out.needed = 0;
    4911             : 
    4912        3512 :         if (Printer == NULL) {
    4913           0 :                 result = WERR_INVALID_HANDLE;
    4914           0 :                 goto err_info_free;
    4915             :         }
    4916             : 
    4917        3512 :         if (Printer->printer_type == SPLHND_SERVER) {
    4918             : 
    4919           0 :                 struct dcerpc_binding_handle *b;
    4920             : 
    4921          72 :                 if (r->in.level != 3) {
    4922          32 :                         result = WERR_INVALID_LEVEL;
    4923          32 :                         goto err_info_free;
    4924             :                 }
    4925             : 
    4926          40 :                 result = winreg_printer_binding_handle(p->mem_ctx,
    4927             :                                                        get_session_info_system(),
    4928             :                                                        p->msg_ctx,
    4929             :                                                        &b);
    4930          40 :                 if (!W_ERROR_IS_OK(result)) {
    4931           0 :                         goto err_info_free;
    4932             :                 }
    4933             : 
    4934          40 :                 result = winreg_get_printserver_secdesc(p->mem_ctx,
    4935             :                                                         b,
    4936          40 :                                                         &r->out.info->info3.secdesc);
    4937          40 :                 if (!W_ERROR_IS_OK(result)) {
    4938           0 :                         goto err_info_free;
    4939             :                 }
    4940             : 
    4941          40 :                 goto done;
    4942             :         }
    4943             : 
    4944        3440 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    4945           0 :                 result = WERR_INVALID_HANDLE;
    4946           0 :                 goto err_info_free;
    4947             :         }
    4948             : 
    4949        3440 :         result = winreg_get_printer_internal(p->mem_ctx,
    4950             :                                     get_session_info_system(),
    4951             :                                     p->msg_ctx,
    4952             :                                     lp_const_servicename(snum),
    4953             :                                     &info2);
    4954        3440 :         if (!W_ERROR_IS_OK(result)) {
    4955           0 :                 goto err_info_free;
    4956             :         }
    4957             : 
    4958        3440 :         switch (r->in.level) {
    4959         236 :         case 0:
    4960         236 :                 result = construct_printer_info0(p->mem_ctx,
    4961             :                                                  get_session_info_system(),
    4962             :                                                  p->msg_ctx,
    4963             :                                                  info2,
    4964             :                                                  Printer->servername,
    4965         236 :                                                  &r->out.info->info0,
    4966             :                                                  snum);
    4967         236 :                 break;
    4968          88 :         case 1:
    4969          88 :                 result = construct_printer_info1(p->mem_ctx, info2,
    4970             :                                                  PRINTER_ENUM_ICON8,
    4971             :                                                  Printer->servername,
    4972          88 :                                                  &r->out.info->info1, snum);
    4973          88 :                 break;
    4974         932 :         case 2:
    4975         932 :                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
    4976             :                                                  Printer->servername,
    4977         932 :                                                  &r->out.info->info2, snum);
    4978         932 :                 break;
    4979         144 :         case 3:
    4980         144 :                 result = construct_printer_info3(p->mem_ctx, info2,
    4981             :                                                  Printer->servername,
    4982         144 :                                                  &r->out.info->info3, snum);
    4983         144 :                 break;
    4984          88 :         case 4:
    4985          88 :                 result = construct_printer_info4(p->mem_ctx, info2,
    4986             :                                                  Printer->servername,
    4987          88 :                                                  &r->out.info->info4, snum);
    4988          88 :                 break;
    4989          88 :         case 5:
    4990          88 :                 result = construct_printer_info5(p->mem_ctx, info2,
    4991             :                                                  Printer->servername,
    4992          88 :                                                  &r->out.info->info5, snum);
    4993          88 :                 break;
    4994          88 :         case 6:
    4995          88 :                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
    4996             :                                                  Printer->servername,
    4997          88 :                                                  &r->out.info->info6, snum);
    4998          88 :                 break;
    4999         112 :         case 7:
    5000         112 :                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
    5001             :                                                  Printer->servername,
    5002         112 :                                                  &r->out.info->info7, snum);
    5003         112 :                 break;
    5004        1664 :         case 8:
    5005        1664 :                 result = construct_printer_info8(p->mem_ctx, info2,
    5006             :                                                  Printer->servername,
    5007        1664 :                                                  &r->out.info->info8, snum);
    5008        1664 :                 break;
    5009           0 :         default:
    5010           0 :                 result = WERR_INVALID_LEVEL;
    5011           0 :                 break;
    5012             :         }
    5013        3440 :         TALLOC_FREE(info2);
    5014             : 
    5015        3440 :         if (!W_ERROR_IS_OK(result)) {
    5016           0 :                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
    5017             :                           r->in.level, win_errstr(result)));
    5018           0 :                 goto err_info_free;
    5019             :         }
    5020        3440 :  done:
    5021        3480 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
    5022             :                                                r->out.info, r->in.level);
    5023        3480 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    5024             : 
    5025        3480 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    5026             : 
    5027          32 : err_info_free:
    5028          32 :         TALLOC_FREE(r->out.info);
    5029          32 :         return result;
    5030             : }
    5031             : 
    5032             : /********************************************************************
    5033             :  ********************************************************************/
    5034             : 
    5035             : #define FILL_DRIVER_STRING(mem_ctx, in, out) \
    5036             :         do { \
    5037             :                 if (in && strlen(in)) { \
    5038             :                         out = talloc_strdup(mem_ctx, in); \
    5039             :                 } else { \
    5040             :                         out = talloc_strdup(mem_ctx, ""); \
    5041             :                 } \
    5042             :                 W_ERROR_HAVE_NO_MEMORY(out); \
    5043             :         } while (0);
    5044             : 
    5045             : #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
    5046             :         do { \
    5047             :                 if (in && strlen(in)) { \
    5048             :                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
    5049             :                 } else { \
    5050             :                         out = talloc_strdup(mem_ctx, ""); \
    5051             :                 } \
    5052             :                 W_ERROR_HAVE_NO_MEMORY(out); \
    5053             :         } while (0);
    5054             : 
    5055           0 : static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
    5056             :                                                   const char **string_array,
    5057             :                                                   const char ***presult,
    5058             :                                                   const char *cservername,
    5059             :                                                   const char *arch,
    5060             :                                                   int version)
    5061             : {
    5062           0 :         size_t i;
    5063           0 :         size_t num_strings = 0;
    5064           0 :         const char **array = NULL;
    5065             : 
    5066           0 :         if (string_array == NULL) {
    5067           0 :                 return WERR_INVALID_PARAMETER;
    5068             :         }
    5069             : 
    5070           0 :         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
    5071           0 :                 const char *str = NULL;
    5072             : 
    5073           0 :                 if (cservername == NULL || arch == NULL) {
    5074           0 :                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
    5075             :                 } else {
    5076           0 :                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
    5077             :                 }
    5078             : 
    5079           0 :                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
    5080           0 :                         TALLOC_FREE(array);
    5081           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    5082             :                 }
    5083             :         }
    5084             : 
    5085           0 :         if (i > 0) {
    5086           0 :                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
    5087             :                              &array, &num_strings);
    5088             :         }
    5089             : 
    5090           0 :         if (presult != NULL) {
    5091           0 :                 *presult = array;
    5092             :         } else {
    5093           0 :                 talloc_free(array);
    5094             :         }
    5095             : 
    5096           0 :         return WERR_OK;
    5097             : }
    5098             : 
    5099             : /********************************************************************
    5100             :  * fill a spoolss_DriverInfo1 struct
    5101             :  ********************************************************************/
    5102             : 
    5103           0 : static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
    5104             :                                         struct spoolss_DriverInfo1 *r,
    5105             :                                         const struct spoolss_DriverInfo8 *driver,
    5106             :                                         const char *servername)
    5107             : {
    5108           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5109           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5110             : 
    5111           0 :         return WERR_OK;
    5112             : }
    5113             : 
    5114             : /********************************************************************
    5115             :  * fill a spoolss_DriverInfo2 struct
    5116             :  ********************************************************************/
    5117             : 
    5118           0 : static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
    5119             :                                         struct spoolss_DriverInfo2 *r,
    5120             :                                         const struct spoolss_DriverInfo8 *driver,
    5121             :                                         const char *servername)
    5122             : 
    5123             : {
    5124           0 :         const char *cservername = canon_servername(servername);
    5125             : 
    5126           0 :         r->version           = driver->version;
    5127             : 
    5128           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5129           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5130           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5131           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5132             : 
    5133           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5134             :                                driver->architecture,
    5135             :                                driver->version,
    5136             :                                driver->driver_path,
    5137           0 :                                r->driver_path);
    5138             : 
    5139           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5140             :                                driver->architecture,
    5141             :                                driver->version,
    5142             :                                driver->data_file,
    5143           0 :                                r->data_file);
    5144             : 
    5145           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5146             :                                driver->architecture,
    5147             :                                driver->version,
    5148             :                                driver->config_file,
    5149           0 :                                r->config_file);
    5150             : 
    5151           0 :         return WERR_OK;
    5152             : }
    5153             : 
    5154             : /********************************************************************
    5155             :  * fill a spoolss_DriverInfo3 struct
    5156             :  ********************************************************************/
    5157             : 
    5158           0 : static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
    5159             :                                         struct spoolss_DriverInfo3 *r,
    5160             :                                         const struct spoolss_DriverInfo8 *driver,
    5161             :                                         const char *servername)
    5162             : {
    5163           0 :         const char *cservername = canon_servername(servername);
    5164             : 
    5165           0 :         r->version           = driver->version;
    5166             : 
    5167           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5168           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5169           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5170           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5171             : 
    5172           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5173             :                                driver->architecture,
    5174             :                                driver->version,
    5175             :                                driver->driver_path,
    5176           0 :                                r->driver_path);
    5177             : 
    5178           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5179             :                                driver->architecture,
    5180             :                                driver->version,
    5181             :                                driver->data_file,
    5182           0 :                                r->data_file);
    5183             : 
    5184           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5185             :                                driver->architecture,
    5186             :                                driver->version,
    5187             :                                driver->config_file,
    5188           0 :                                r->config_file);
    5189             : 
    5190           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5191             :                                driver->architecture,
    5192             :                                driver->version,
    5193             :                                driver->help_file,
    5194           0 :                                r->help_file);
    5195             : 
    5196           0 :         FILL_DRIVER_STRING(mem_ctx,
    5197             :                            driver->monitor_name,
    5198           0 :                            r->monitor_name);
    5199             : 
    5200           0 :         FILL_DRIVER_STRING(mem_ctx,
    5201             :                            driver->default_datatype,
    5202           0 :                            r->default_datatype);
    5203             : 
    5204           0 :         return string_array_from_driver_info(mem_ctx,
    5205           0 :                                              driver->dependent_files,
    5206             :                                              &r->dependent_files,
    5207             :                                              cservername,
    5208           0 :                                              driver->architecture,
    5209           0 :                                              driver->version);
    5210             : }
    5211             : 
    5212             : /********************************************************************
    5213             :  * fill a spoolss_DriverInfo4 struct
    5214             :  ********************************************************************/
    5215             : 
    5216           0 : static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
    5217             :                                         struct spoolss_DriverInfo4 *r,
    5218             :                                         const struct spoolss_DriverInfo8 *driver,
    5219             :                                         const char *servername)
    5220             : {
    5221           0 :         const char *cservername = canon_servername(servername);
    5222           0 :         WERROR result;
    5223             : 
    5224           0 :         r->version           = driver->version;
    5225             : 
    5226           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5227           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5228           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5229           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5230             : 
    5231           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5232             :                                driver->architecture,
    5233             :                                driver->version,
    5234             :                                driver->driver_path,
    5235           0 :                                r->driver_path);
    5236             : 
    5237           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5238             :                                driver->architecture,
    5239             :                                driver->version,
    5240             :                                driver->data_file,
    5241           0 :                                r->data_file);
    5242             : 
    5243           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5244             :                                driver->architecture,
    5245             :                                driver->version,
    5246             :                                driver->config_file,
    5247           0 :                                r->config_file);
    5248             : 
    5249           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5250             :                                driver->architecture,
    5251             :                                driver->version,
    5252             :                                driver->help_file,
    5253           0 :                                r->help_file);
    5254             : 
    5255           0 :         result = string_array_from_driver_info(mem_ctx,
    5256           0 :                                                driver->dependent_files,
    5257             :                                                &r->dependent_files,
    5258             :                                                cservername,
    5259           0 :                                                driver->architecture,
    5260           0 :                                                driver->version);
    5261           0 :         if (!W_ERROR_IS_OK(result)) {
    5262           0 :                 return result;
    5263             :         }
    5264             : 
    5265           0 :         FILL_DRIVER_STRING(mem_ctx,
    5266             :                            driver->monitor_name,
    5267           0 :                            r->monitor_name);
    5268             : 
    5269           0 :         FILL_DRIVER_STRING(mem_ctx,
    5270             :                            driver->default_datatype,
    5271           0 :                            r->default_datatype);
    5272             : 
    5273             : 
    5274           0 :         result = string_array_from_driver_info(mem_ctx,
    5275           0 :                                                driver->previous_names,
    5276             :                                                &r->previous_names,
    5277             :                                                NULL, NULL, 0);
    5278             : 
    5279           0 :         return result;
    5280             : }
    5281             : 
    5282             : /********************************************************************
    5283             :  * fill a spoolss_DriverInfo5 struct
    5284             :  ********************************************************************/
    5285             : 
    5286           0 : static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
    5287             :                                         struct spoolss_DriverInfo5 *r,
    5288             :                                         const struct spoolss_DriverInfo8 *driver,
    5289             :                                         const char *servername)
    5290             : {
    5291           0 :         const char *cservername = canon_servername(servername);
    5292             : 
    5293           0 :         r->version           = driver->version;
    5294             : 
    5295           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5296           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5297           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5298           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5299             : 
    5300           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5301             :                                driver->architecture,
    5302             :                                driver->version,
    5303             :                                driver->driver_path,
    5304           0 :                                r->driver_path);
    5305             : 
    5306           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5307             :                                driver->architecture,
    5308             :                                driver->version,
    5309             :                                driver->data_file,
    5310           0 :                                r->data_file);
    5311             : 
    5312           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5313             :                                driver->architecture,
    5314             :                                driver->version,
    5315             :                                driver->config_file,
    5316           0 :                                r->config_file);
    5317             : 
    5318           0 :         r->driver_attributes = 0;
    5319           0 :         r->config_version    = 0;
    5320           0 :         r->driver_version    = 0;
    5321             : 
    5322           0 :         return WERR_OK;
    5323             : }
    5324             : /********************************************************************
    5325             :  * fill a spoolss_DriverInfo6 struct
    5326             :  ********************************************************************/
    5327             : 
    5328           0 : static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
    5329             :                                         struct spoolss_DriverInfo6 *r,
    5330             :                                         const struct spoolss_DriverInfo8 *driver,
    5331             :                                         const char *servername)
    5332             : {
    5333           0 :         const char *cservername = canon_servername(servername);
    5334           0 :         WERROR result;
    5335             : 
    5336           0 :         r->version           = driver->version;
    5337             : 
    5338           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5339           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5340           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5341           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5342             : 
    5343           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5344             :                                driver->architecture,
    5345             :                                driver->version,
    5346             :                                driver->driver_path,
    5347           0 :                                r->driver_path);
    5348             : 
    5349           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5350             :                                driver->architecture,
    5351             :                                driver->version,
    5352             :                                driver->data_file,
    5353           0 :                                r->data_file);
    5354             : 
    5355           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5356             :                                driver->architecture,
    5357             :                                driver->version,
    5358             :                                driver->config_file,
    5359           0 :                                r->config_file);
    5360             : 
    5361           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5362             :                                driver->architecture,
    5363             :                                driver->version,
    5364             :                                driver->help_file,
    5365           0 :                                r->help_file);
    5366             : 
    5367           0 :         FILL_DRIVER_STRING(mem_ctx,
    5368             :                            driver->monitor_name,
    5369           0 :                            r->monitor_name);
    5370             : 
    5371           0 :         FILL_DRIVER_STRING(mem_ctx,
    5372             :                            driver->default_datatype,
    5373           0 :                            r->default_datatype);
    5374             : 
    5375           0 :         result = string_array_from_driver_info(mem_ctx,
    5376           0 :                                                driver->dependent_files,
    5377             :                                                &r->dependent_files,
    5378             :                                                cservername,
    5379           0 :                                                driver->architecture,
    5380           0 :                                                driver->version);
    5381           0 :         if (!W_ERROR_IS_OK(result)) {
    5382           0 :                 return result;
    5383             :         }
    5384             : 
    5385           0 :         result = string_array_from_driver_info(mem_ctx,
    5386           0 :                                                driver->previous_names,
    5387             :                                                &r->previous_names,
    5388             :                                                NULL, NULL, 0);
    5389           0 :         if (!W_ERROR_IS_OK(result)) {
    5390           0 :                 return result;
    5391             :         }
    5392             : 
    5393           0 :         r->driver_date               = driver->driver_date;
    5394           0 :         r->driver_version    = driver->driver_version;
    5395             : 
    5396           0 :         FILL_DRIVER_STRING(mem_ctx,
    5397             :                            driver->manufacturer_name,
    5398           0 :                            r->manufacturer_name);
    5399           0 :         FILL_DRIVER_STRING(mem_ctx,
    5400             :                            driver->manufacturer_url,
    5401           0 :                            r->manufacturer_url);
    5402           0 :         FILL_DRIVER_STRING(mem_ctx,
    5403             :                            driver->hardware_id,
    5404           0 :                            r->hardware_id);
    5405           0 :         FILL_DRIVER_STRING(mem_ctx,
    5406             :                            driver->provider,
    5407           0 :                            r->provider);
    5408             : 
    5409           0 :         return WERR_OK;
    5410             : }
    5411             : 
    5412             : /********************************************************************
    5413             :  * fill a spoolss_DriverInfo8 struct
    5414             :  ********************************************************************/
    5415             : 
    5416           0 : static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
    5417             :                                         struct spoolss_DriverInfo8 *r,
    5418             :                                         const struct spoolss_DriverInfo8 *driver,
    5419             :                                         const char *servername)
    5420             : {
    5421           0 :         const char *cservername = canon_servername(servername);
    5422           0 :         WERROR result;
    5423             : 
    5424           0 :         r->version           = driver->version;
    5425             : 
    5426           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5427           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5428           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5429           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5430             : 
    5431           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5432             :                                driver->architecture,
    5433             :                                driver->version,
    5434             :                                driver->driver_path,
    5435           0 :                                r->driver_path);
    5436             : 
    5437           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5438             :                                driver->architecture,
    5439             :                                driver->version,
    5440             :                                driver->data_file,
    5441           0 :                                r->data_file);
    5442             : 
    5443           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5444             :                                driver->architecture,
    5445             :                                driver->version,
    5446             :                                driver->config_file,
    5447           0 :                                r->config_file);
    5448             : 
    5449           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5450             :                                driver->architecture,
    5451             :                                driver->version,
    5452             :                                driver->help_file,
    5453           0 :                                r->help_file);
    5454             : 
    5455           0 :         FILL_DRIVER_STRING(mem_ctx,
    5456             :                            driver->monitor_name,
    5457           0 :                            r->monitor_name);
    5458             : 
    5459           0 :         FILL_DRIVER_STRING(mem_ctx,
    5460             :                            driver->default_datatype,
    5461           0 :                            r->default_datatype);
    5462             : 
    5463           0 :         result = string_array_from_driver_info(mem_ctx,
    5464           0 :                                                driver->dependent_files,
    5465             :                                                &r->dependent_files,
    5466             :                                                cservername,
    5467           0 :                                                driver->architecture,
    5468           0 :                                                driver->version);
    5469           0 :         if (!W_ERROR_IS_OK(result)) {
    5470           0 :                 return result;
    5471             :         }
    5472             : 
    5473           0 :         result = string_array_from_driver_info(mem_ctx,
    5474           0 :                                                driver->previous_names,
    5475             :                                                &r->previous_names,
    5476             :                                                NULL, NULL, 0);
    5477           0 :         if (!W_ERROR_IS_OK(result)) {
    5478           0 :                 return result;
    5479             :         }
    5480             : 
    5481           0 :         r->driver_date               = driver->driver_date;
    5482           0 :         r->driver_version    = driver->driver_version;
    5483             : 
    5484           0 :         FILL_DRIVER_STRING(mem_ctx,
    5485             :                            driver->manufacturer_name,
    5486           0 :                            r->manufacturer_name);
    5487           0 :         FILL_DRIVER_STRING(mem_ctx,
    5488             :                            driver->manufacturer_url,
    5489           0 :                            r->manufacturer_url);
    5490           0 :         FILL_DRIVER_STRING(mem_ctx,
    5491             :                            driver->hardware_id,
    5492           0 :                            r->hardware_id);
    5493           0 :         FILL_DRIVER_STRING(mem_ctx,
    5494             :                            driver->provider,
    5495           0 :                            r->provider);
    5496             : 
    5497           0 :         FILL_DRIVER_STRING(mem_ctx,
    5498             :                            driver->print_processor,
    5499           0 :                            r->print_processor);
    5500           0 :         FILL_DRIVER_STRING(mem_ctx,
    5501             :                            driver->vendor_setup,
    5502           0 :                            r->vendor_setup);
    5503             : 
    5504           0 :         result = string_array_from_driver_info(mem_ctx,
    5505           0 :                                                driver->color_profiles,
    5506             :                                                &r->color_profiles,
    5507             :                                                NULL, NULL, 0);
    5508           0 :         if (!W_ERROR_IS_OK(result)) {
    5509           0 :                 return result;
    5510             :         }
    5511             : 
    5512           0 :         FILL_DRIVER_STRING(mem_ctx,
    5513             :                            driver->inf_path,
    5514           0 :                            r->inf_path);
    5515             : 
    5516           0 :         r->printer_driver_attributes = driver->printer_driver_attributes;
    5517             : 
    5518           0 :         result = string_array_from_driver_info(mem_ctx,
    5519           0 :                                                driver->core_driver_dependencies,
    5520             :                                                &r->core_driver_dependencies,
    5521             :                                                NULL, NULL, 0);
    5522           0 :         if (!W_ERROR_IS_OK(result)) {
    5523           0 :                 return result;
    5524             :         }
    5525             : 
    5526           0 :         r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
    5527           0 :         r->min_inbox_driver_ver_version      = driver->min_inbox_driver_ver_version;
    5528             : 
    5529           0 :         return WERR_OK;
    5530             : }
    5531             : 
    5532             : #if 0 /* disabled until marshalling issues are resolved - gd */
    5533             : /********************************************************************
    5534             :  ********************************************************************/
    5535             : 
    5536             : static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
    5537             :                                           struct spoolss_DriverFileInfo *r,
    5538             :                                           const char *cservername,
    5539             :                                           const char *file_name,
    5540             :                                           enum spoolss_DriverFileType file_type,
    5541             :                                           uint32_t file_version)
    5542             : {
    5543             :         r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
    5544             :                                           cservername, file_name);
    5545             :         W_ERROR_HAVE_NO_MEMORY(r->file_name);
    5546             :         r->file_type = file_type;
    5547             :         r->file_version      = file_version;
    5548             : 
    5549             :         return WERR_OK;
    5550             : }
    5551             : 
    5552             : /********************************************************************
    5553             :  ********************************************************************/
    5554             : 
    5555             : static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
    5556             :                                                  const struct spoolss_DriverInfo8 *driver,
    5557             :                                                  const char *cservername,
    5558             :                                                  struct spoolss_DriverFileInfo **info_p,
    5559             :                                                  uint32_t *count_p)
    5560             : {
    5561             :         struct spoolss_DriverFileInfo *info = NULL;
    5562             :         uint32_t count = 0;
    5563             :         WERROR result;
    5564             :         uint32_t i;
    5565             : 
    5566             :         *info_p = NULL;
    5567             :         *count_p = 0;
    5568             : 
    5569             :         if (strlen(driver->driver_path)) {
    5570             :                 info = talloc_realloc(mem_ctx, info,
    5571             :                                             struct spoolss_DriverFileInfo,
    5572             :                                             count + 1);
    5573             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5574             :                 result = fill_spoolss_DriverFileInfo(info,
    5575             :                                                      &info[count],
    5576             :                                                      cservername,
    5577             :                                                      driver->driver_path,
    5578             :                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
    5579             :                                                      0);
    5580             :                 W_ERROR_NOT_OK_RETURN(result);
    5581             :                 count++;
    5582             :         }
    5583             : 
    5584             :         if (strlen(driver->config_file)) {
    5585             :                 info = talloc_realloc(mem_ctx, info,
    5586             :                                             struct spoolss_DriverFileInfo,
    5587             :                                             count + 1);
    5588             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5589             :                 result = fill_spoolss_DriverFileInfo(info,
    5590             :                                                      &info[count],
    5591             :                                                      cservername,
    5592             :                                                      driver->config_file,
    5593             :                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
    5594             :                                                      0);
    5595             :                 W_ERROR_NOT_OK_RETURN(result);
    5596             :                 count++;
    5597             :         }
    5598             : 
    5599             :         if (strlen(driver->data_file)) {
    5600             :                 info = talloc_realloc(mem_ctx, info,
    5601             :                                             struct spoolss_DriverFileInfo,
    5602             :                                             count + 1);
    5603             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5604             :                 result = fill_spoolss_DriverFileInfo(info,
    5605             :                                                      &info[count],
    5606             :                                                      cservername,
    5607             :                                                      driver->data_file,
    5608             :                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
    5609             :                                                      0);
    5610             :                 W_ERROR_NOT_OK_RETURN(result);
    5611             :                 count++;
    5612             :         }
    5613             : 
    5614             :         if (strlen(driver->help_file)) {
    5615             :                 info = talloc_realloc(mem_ctx, info,
    5616             :                                             struct spoolss_DriverFileInfo,
    5617             :                                             count + 1);
    5618             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5619             :                 result = fill_spoolss_DriverFileInfo(info,
    5620             :                                                      &info[count],
    5621             :                                                      cservername,
    5622             :                                                      driver->help_file,
    5623             :                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
    5624             :                                                      0);
    5625             :                 W_ERROR_NOT_OK_RETURN(result);
    5626             :                 count++;
    5627             :         }
    5628             : 
    5629             :         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
    5630             :                 info = talloc_realloc(mem_ctx, info,
    5631             :                                             struct spoolss_DriverFileInfo,
    5632             :                                             count + 1);
    5633             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5634             :                 result = fill_spoolss_DriverFileInfo(info,
    5635             :                                                      &info[count],
    5636             :                                                      cservername,
    5637             :                                                      driver->dependent_files[i],
    5638             :                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
    5639             :                                                      0);
    5640             :                 W_ERROR_NOT_OK_RETURN(result);
    5641             :                 count++;
    5642             :         }
    5643             : 
    5644             :         *info_p = info;
    5645             :         *count_p = count;
    5646             : 
    5647             :         return WERR_OK;
    5648             : }
    5649             : 
    5650             : /********************************************************************
    5651             :  * fill a spoolss_DriverInfo101 struct
    5652             :  ********************************************************************/
    5653             : 
    5654             : static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
    5655             :                                           struct spoolss_DriverInfo101 *r,
    5656             :                                           const struct spoolss_DriverInfo8 *driver,
    5657             :                                           const char *servername)
    5658             : {
    5659             :         const char *cservername = canon_servername(servername);
    5660             :         WERROR result;
    5661             : 
    5662             :         r->version           = driver->version;
    5663             : 
    5664             :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5665             :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5666             :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5667             :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5668             : 
    5669             :         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
    5670             :                                                     cservername,
    5671             :                                                     &r->file_info,
    5672             :                                                     &r->file_count);
    5673             :         if (!W_ERROR_IS_OK(result)) {
    5674             :                 return result;
    5675             :         }
    5676             : 
    5677             :         FILL_DRIVER_STRING(mem_ctx,
    5678             :                            driver->monitor_name,
    5679             :                            r->monitor_name);
    5680             : 
    5681             :         FILL_DRIVER_STRING(mem_ctx,
    5682             :                            driver->default_datatype,
    5683             :                            r->default_datatype);
    5684             : 
    5685             :         result = string_array_from_driver_info(mem_ctx,
    5686             :                                                driver->previous_names,
    5687             :                                                &r->previous_names,
    5688             :                                                NULL, NULL, 0);
    5689             :         if (!W_ERROR_IS_OK(result)) {
    5690             :                 return result;
    5691             :         }
    5692             : 
    5693             :         r->driver_date               = driver->driver_date;
    5694             :         r->driver_version    = driver->driver_version;
    5695             : 
    5696             :         FILL_DRIVER_STRING(mem_ctx,
    5697             :                            driver->manufacturer_name,
    5698             :                            r->manufacturer_name);
    5699             :         FILL_DRIVER_STRING(mem_ctx,
    5700             :                            driver->manufacturer_url,
    5701             :                            r->manufacturer_url);
    5702             :         FILL_DRIVER_STRING(mem_ctx,
    5703             :                            driver->hardware_id,
    5704             :                            r->hardware_id);
    5705             :         FILL_DRIVER_STRING(mem_ctx,
    5706             :                            driver->provider,
    5707             :                            r->provider);
    5708             : 
    5709             :         return WERR_OK;
    5710             : }
    5711             : #endif
    5712             : /********************************************************************
    5713             :  ********************************************************************/
    5714             : 
    5715           4 : static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
    5716             :                                                   const struct auth_session_info *session_info,
    5717             :                                                   struct messaging_context *msg_ctx,
    5718             :                                                   uint32_t level,
    5719             :                                                   union spoolss_DriverInfo *r,
    5720             :                                                   int snum,
    5721             :                                                   const char *servername,
    5722             :                                                   const char *architecture,
    5723             :                                                   uint32_t version)
    5724             : {
    5725           4 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    5726           0 :         struct spoolss_DriverInfo8 *driver;
    5727           0 :         WERROR result;
    5728           0 :         struct dcerpc_binding_handle *b;
    5729           4 :         TALLOC_CTX *tmp_ctx = NULL;
    5730             : 
    5731           4 :         if (level == 101) {
    5732           4 :                 return WERR_INVALID_LEVEL;
    5733             :         }
    5734             : 
    5735           0 :         tmp_ctx = talloc_new(mem_ctx);
    5736           0 :         if (!tmp_ctx) {
    5737           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    5738             :         }
    5739             : 
    5740           0 :         result = winreg_printer_binding_handle(tmp_ctx,
    5741             :                                                session_info,
    5742             :                                                msg_ctx,
    5743             :                                                &b);
    5744           0 :         if (!W_ERROR_IS_OK(result)) {
    5745           0 :                 goto done;
    5746             :         }
    5747             : 
    5748           0 :         result = winreg_get_printer(tmp_ctx, b,
    5749             :                                     lp_const_servicename(snum),
    5750             :                                     &pinfo2);
    5751           0 :         if (!W_ERROR_IS_OK(result)) {
    5752           0 :                 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
    5753             :                         lp_const_servicename(snum), win_errstr(result));
    5754           0 :                 result = WERR_INVALID_PRINTER_NAME;
    5755           0 :                 goto done;
    5756             :         }
    5757             : 
    5758           0 :         if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
    5759           0 :                 result = WERR_UNKNOWN_PRINTER_DRIVER;
    5760           0 :                 goto done;
    5761             :         }
    5762             : 
    5763           0 :         DBG_INFO("Construct printer driver [%s] for [%s]\n",
    5764             :                  pinfo2->drivername,
    5765             :                  pinfo2->sharename);
    5766             : 
    5767           0 :         result = winreg_get_driver(tmp_ctx, b,
    5768             :                                    architecture,
    5769           0 :                                    pinfo2->drivername, version, &driver);
    5770             : 
    5771           0 :         DBG_INFO("winreg_get_driver() status: %s\n",
    5772             :                  win_errstr(result));
    5773             : 
    5774           0 :         if (!W_ERROR_IS_OK(result)) {
    5775             :                 /*
    5776             :                  * Is this a W2k client ?
    5777             :                  */
    5778             : 
    5779           0 :                 if (version < 3) {
    5780           0 :                         result = WERR_UNKNOWN_PRINTER_DRIVER;
    5781           0 :                         goto done;
    5782             :                 }
    5783             : 
    5784             :                 /* Yes - try again with a WinNT driver. */
    5785           0 :                 version = 2;
    5786           0 :                 result = winreg_get_driver(tmp_ctx, b,
    5787             :                                            architecture,
    5788           0 :                                            pinfo2->drivername,
    5789             :                                            version, &driver);
    5790           0 :                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
    5791             :                         win_errstr(result)));
    5792           0 :                 if (!W_ERROR_IS_OK(result)) {
    5793           0 :                         result = WERR_UNKNOWN_PRINTER_DRIVER;
    5794           0 :                         goto done;
    5795             :                 }
    5796             :         }
    5797             : 
    5798             :         /* these are allocated on mem_ctx and not tmp_ctx because they are
    5799             :          * the 'return value' and need to outlive this call */
    5800           0 :         switch (level) {
    5801           0 :         case 1:
    5802           0 :                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
    5803           0 :                 break;
    5804           0 :         case 2:
    5805           0 :                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
    5806           0 :                 break;
    5807           0 :         case 3:
    5808           0 :                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
    5809           0 :                 break;
    5810           0 :         case 4:
    5811           0 :                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
    5812           0 :                 break;
    5813           0 :         case 5:
    5814           0 :                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
    5815           0 :                 break;
    5816           0 :         case 6:
    5817           0 :                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
    5818           0 :                 break;
    5819           0 :         case 8:
    5820           0 :                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
    5821           0 :                 break;
    5822             : #if 0 /* disabled until marshalling issues are resolved - gd */
    5823             :         case 101:
    5824             :                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
    5825             :                 break;
    5826             : #endif
    5827           0 :         default:
    5828           0 :                 result = WERR_INVALID_LEVEL;
    5829           0 :                 break;
    5830             :         }
    5831             : 
    5832           0 : done:
    5833           0 :         talloc_free(tmp_ctx);
    5834           0 :         return result;
    5835             : }
    5836             : 
    5837             : /****************************************************************
    5838             :  _spoolss_GetPrinterDriver2
    5839             : ****************************************************************/
    5840             : 
    5841           4 : WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
    5842             :                                   struct spoolss_GetPrinterDriver2 *r)
    5843             : {
    5844           0 :         struct printer_handle *printer;
    5845           0 :         WERROR result;
    5846           4 :         uint32_t version = r->in.client_major_version;
    5847             : 
    5848           0 :         int snum;
    5849             : 
    5850             :         /* that's an [in out] buffer */
    5851             : 
    5852           4 :         if (!r->in.buffer && (r->in.offered != 0)) {
    5853           0 :                 result = WERR_INVALID_PARAMETER;
    5854           0 :                 goto err_info_free;
    5855             :         }
    5856             : 
    5857           4 :         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
    5858             : 
    5859           4 :         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
    5860           0 :                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
    5861           0 :                 result = WERR_INVALID_PRINTER_NAME;
    5862           0 :                 goto err_info_free;
    5863             :         }
    5864             : 
    5865           4 :         *r->out.needed = 0;
    5866           4 :         *r->out.server_major_version = 0;
    5867           4 :         *r->out.server_minor_version = 0;
    5868             : 
    5869           4 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    5870           0 :                 result = WERR_INVALID_HANDLE;
    5871           0 :                 goto err_info_free;
    5872             :         }
    5873             : 
    5874           4 :         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
    5875           0 :                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
    5876             :                         "downgrading to v3\n"));
    5877           0 :                 version = SPOOLSS_DRIVER_VERSION_200X;
    5878             :         }
    5879             : 
    5880           4 :         result = construct_printer_driver_info_level(p->mem_ctx,
    5881             :                                                      get_session_info_system(),
    5882             :                                                      p->msg_ctx,
    5883             :                                                      r->in.level, r->out.info,
    5884             :                                                      snum, printer->servername,
    5885             :                                                      r->in.architecture,
    5886             :                                                      version);
    5887           4 :         if (!W_ERROR_IS_OK(result)) {
    5888           4 :                 goto err_info_free;
    5889             :         }
    5890             : 
    5891           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
    5892             :                                                r->out.info, r->in.level);
    5893           0 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    5894             : 
    5895           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    5896             : 
    5897           4 : err_info_free:
    5898           4 :         TALLOC_FREE(r->out.info);
    5899           4 :         return result;
    5900             : }
    5901             : 
    5902             : 
    5903             : /****************************************************************
    5904             :  _spoolss_StartPagePrinter
    5905             : ****************************************************************/
    5906             : 
    5907        1920 : WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
    5908             :                                  struct spoolss_StartPagePrinter *r)
    5909             : {
    5910        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5911             : 
    5912        1920 :         if (!Printer) {
    5913           0 :                 DEBUG(3,("_spoolss_StartPagePrinter: "
    5914             :                         "Error in startpageprinter printer handle\n"));
    5915           0 :                 return WERR_INVALID_HANDLE;
    5916             :         }
    5917             : 
    5918        1920 :         Printer->page_started = true;
    5919        1920 :         return WERR_OK;
    5920             : }
    5921             : 
    5922             : /****************************************************************
    5923             :  _spoolss_EndPagePrinter
    5924             : ****************************************************************/
    5925             : 
    5926        1920 : WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
    5927             :                                struct spoolss_EndPagePrinter *r)
    5928             : {
    5929           0 :         int snum;
    5930             : 
    5931        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5932             : 
    5933        1920 :         if (!Printer) {
    5934           0 :                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
    5935             :                         OUR_HANDLE(r->in.handle)));
    5936           0 :                 return WERR_INVALID_HANDLE;
    5937             :         }
    5938             : 
    5939        1920 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    5940           0 :                 return WERR_INVALID_HANDLE;
    5941             : 
    5942        1920 :         Printer->page_started = false;
    5943        1920 :         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
    5944             : 
    5945        1920 :         return WERR_OK;
    5946             : }
    5947             : 
    5948             : /****************************************************************
    5949             :  _spoolss_StartDocPrinter
    5950             : ****************************************************************/
    5951             : 
    5952         668 : WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
    5953             :                                 struct spoolss_StartDocPrinter *r)
    5954             : {
    5955         668 :         struct dcesrv_call_state *dce_call = p->dce_call;
    5956         668 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    5957           0 :         const struct tsocket_address *remote_address =
    5958         668 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    5959           0 :         struct auth_session_info *session_info =
    5960         668 :                 dcesrv_call_session_info(dce_call);
    5961           0 :         struct spoolss_DocumentInfo1 *info_1;
    5962           0 :         int snum;
    5963         668 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5964           0 :         WERROR werr;
    5965           0 :         char *rhost;
    5966           0 :         int rc;
    5967             : 
    5968         668 :         if (!Printer) {
    5969           0 :                 DEBUG(2,("_spoolss_StartDocPrinter: "
    5970             :                         "Invalid handle (%s:%u:%u)\n",
    5971             :                         OUR_HANDLE(r->in.handle)));
    5972           0 :                 return WERR_INVALID_HANDLE;
    5973             :         }
    5974             : 
    5975         668 :         if (Printer->jobid) {
    5976           0 :                 DEBUG(2, ("_spoolss_StartDocPrinter: "
    5977             :                           "StartDocPrinter called twice! "
    5978             :                           "(existing jobid = %d)\n", Printer->jobid));
    5979           0 :                 return WERR_INVALID_HANDLE;
    5980             :         }
    5981             : 
    5982         668 :         if (r->in.info_ctr->level != 1) {
    5983           0 :                 return WERR_INVALID_LEVEL;
    5984             :         }
    5985             : 
    5986         668 :         info_1 = r->in.info_ctr->info.info1;
    5987             : 
    5988             :         /*
    5989             :          * a nice thing with NT is it doesn't listen to what you tell it.
    5990             :          * when asked to send _only_ RAW data, it tries to send data
    5991             :          * in EMF format.
    5992             :          *
    5993             :          * So I add checks like in NT Server ...
    5994             :          */
    5995             : 
    5996         668 :         if (info_1->datatype) {
    5997             :                 /*
    5998             :                  * The v4 driver model used in Windows 8 declares print jobs
    5999             :                  * intended to bypass the XPS processing layer by setting
    6000             :                  * datatype to "XPS_PASS" instead of "RAW".
    6001             :                  */
    6002         668 :                 if ((strcmp(info_1->datatype, "RAW") != 0)
    6003         224 :                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
    6004           0 :                         *r->out.job_id = 0;
    6005           0 :                         return WERR_INVALID_DATATYPE;
    6006             :                 }
    6007             :         }
    6008             : 
    6009             :         /* get the share number of the printer */
    6010         668 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    6011           0 :                 return WERR_INVALID_HANDLE;
    6012             :         }
    6013             : 
    6014         668 :         rc = get_remote_hostname(remote_address,
    6015             :                                  &rhost,
    6016             :                                  p->mem_ctx);
    6017         668 :         if (rc < 0) {
    6018           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6019             :         }
    6020         668 :         if (strequal(rhost,"UNKNOWN")) {
    6021         668 :                 rhost = tsocket_address_inet_addr_string(remote_address,
    6022             :                                                          p->mem_ctx);
    6023         668 :                 if (rhost == NULL) {
    6024           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    6025             :                 }
    6026             :         }
    6027             : 
    6028         668 :         werr = print_job_start(session_info,
    6029             :                                p->msg_ctx,
    6030             :                                rhost,
    6031             :                                snum,
    6032             :                                info_1->document_name,
    6033             :                                info_1->output_file,
    6034             :                                Printer->devmode,
    6035             :                                &Printer->jobid);
    6036             : 
    6037             :         /* An error occurred in print_job_start() so return an appropriate
    6038             :            NT error code. */
    6039             : 
    6040         668 :         if (!W_ERROR_IS_OK(werr)) {
    6041           0 :                 return werr;
    6042             :         }
    6043             : 
    6044         668 :         Printer->document_started = true;
    6045         668 :         *r->out.job_id = Printer->jobid;
    6046             : 
    6047         668 :         return WERR_OK;
    6048             : }
    6049             : 
    6050             : /****************************************************************
    6051             :  _spoolss_EndDocPrinter
    6052             : ****************************************************************/
    6053             : 
    6054         668 : WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
    6055             :                               struct spoolss_EndDocPrinter *r)
    6056             : {
    6057         668 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6058           0 :         NTSTATUS status;
    6059           0 :         int snum;
    6060             : 
    6061         668 :         if (!Printer) {
    6062           0 :                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
    6063             :                         OUR_HANDLE(r->in.handle)));
    6064           0 :                 return WERR_INVALID_HANDLE;
    6065             :         }
    6066             : 
    6067         668 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    6068           0 :                 return WERR_INVALID_HANDLE;
    6069             :         }
    6070             : 
    6071         668 :         Printer->document_started = false;
    6072         668 :         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
    6073         668 :         if (!NT_STATUS_IS_OK(status)) {
    6074         292 :                 DEBUG(2, ("_spoolss_EndDocPrinter: "
    6075             :                           "print_job_end failed [%s]\n",
    6076             :                           nt_errstr(status)));
    6077             :         }
    6078             : 
    6079         668 :         Printer->jobid = 0;
    6080         668 :         return ntstatus_to_werror(status);
    6081             : }
    6082             : 
    6083             : /****************************************************************
    6084             :  _spoolss_WritePrinter
    6085             : ****************************************************************/
    6086             : 
    6087        1920 : WERROR _spoolss_WritePrinter(struct pipes_struct *p,
    6088             :                              struct spoolss_WritePrinter *r)
    6089             : {
    6090           0 :         ssize_t buffer_written;
    6091           0 :         int snum;
    6092        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6093             : 
    6094        1920 :         if (!Printer) {
    6095           0 :                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
    6096             :                         OUR_HANDLE(r->in.handle)));
    6097           0 :                 *r->out.num_written = r->in._data_size;
    6098           0 :                 return WERR_INVALID_HANDLE;
    6099             :         }
    6100             : 
    6101        1920 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    6102           0 :                 return WERR_INVALID_HANDLE;
    6103             : 
    6104             :         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
    6105        1920 :         buffer_written = print_job_write(global_event_context(),p->msg_ctx,
    6106             :                                                    snum, Printer->jobid,
    6107        1920 :                                                    (const char *)r->in.data.data,
    6108        1920 :                                                    (size_t)r->in._data_size);
    6109        1920 :         if (buffer_written == (ssize_t)-1) {
    6110           0 :                 *r->out.num_written = 0;
    6111           0 :                 if (errno == ENOSPC)
    6112           0 :                         return WERR_NO_SPOOL_SPACE;
    6113             :                 else
    6114           0 :                         return WERR_ACCESS_DENIED;
    6115             :         }
    6116             : 
    6117        1920 :         *r->out.num_written = r->in._data_size;
    6118             : 
    6119        1920 :         return WERR_OK;
    6120             : }
    6121             : 
    6122             : /********************************************************************
    6123             :  * api_spoolss_getprinter
    6124             :  * called from the spoolss dispatcher
    6125             :  *
    6126             :  ********************************************************************/
    6127             : 
    6128         104 : static WERROR control_printer(struct policy_handle *handle, uint32_t command,
    6129             :                               struct pipes_struct *p)
    6130             : {
    6131         104 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6132           0 :         struct auth_session_info *session_info =
    6133         104 :                 dcesrv_call_session_info(dce_call);
    6134           0 :         int snum;
    6135         104 :         WERROR errcode = WERR_INVALID_FUNCTION;
    6136         104 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6137             : 
    6138         104 :         if (!Printer) {
    6139           0 :                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
    6140             :                         OUR_HANDLE(handle)));
    6141           0 :                 return WERR_INVALID_HANDLE;
    6142             :         }
    6143             : 
    6144         104 :         if (!get_printer_snum(p, handle, &snum, NULL))
    6145           0 :                 return WERR_INVALID_HANDLE;
    6146             : 
    6147         104 :         switch (command) {
    6148          52 :         case SPOOLSS_PRINTER_CONTROL_PAUSE:
    6149          52 :                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
    6150          52 :                 break;
    6151          40 :         case SPOOLSS_PRINTER_CONTROL_RESUME:
    6152             :         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
    6153          40 :                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
    6154          40 :                 break;
    6155          12 :         case SPOOLSS_PRINTER_CONTROL_PURGE:
    6156          12 :                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
    6157          12 :                 break;
    6158           0 :         default:
    6159           0 :                 return WERR_INVALID_LEVEL;
    6160             :         }
    6161             : 
    6162         104 :         return errcode;
    6163             : }
    6164             : 
    6165             : 
    6166             : /****************************************************************
    6167             :  _spoolss_AbortPrinter
    6168             :  * From MSDN: "Deletes printer's spool file if printer is configured
    6169             :  * for spooling"
    6170             : ****************************************************************/
    6171             : 
    6172           0 : WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
    6173             :                              struct spoolss_AbortPrinter *r)
    6174             : {
    6175           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6176           0 :         struct auth_session_info *session_info =
    6177           0 :                 dcesrv_call_session_info(dce_call);
    6178           0 :         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6179           0 :         int             snum;
    6180           0 :         WERROR          errcode = WERR_OK;
    6181             : 
    6182           0 :         if (!Printer) {
    6183           0 :                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
    6184             :                         OUR_HANDLE(r->in.handle)));
    6185           0 :                 return WERR_INVALID_HANDLE;
    6186             :         }
    6187             : 
    6188           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    6189           0 :                 return WERR_INVALID_HANDLE;
    6190             : 
    6191           0 :         if (!Printer->document_started) {
    6192           0 :                 return WERR_SPL_NO_STARTDOC;
    6193             :         }
    6194             : 
    6195           0 :         errcode = print_job_delete(session_info,
    6196             :                                    p->msg_ctx,
    6197             :                                    snum,
    6198             :                                    Printer->jobid);
    6199             : 
    6200           0 :         return errcode;
    6201             : }
    6202             : 
    6203             : /********************************************************************
    6204             :  * called by spoolss_api_setprinter
    6205             :  * when updating a printer description
    6206             :  ********************************************************************/
    6207             : 
    6208         120 : static WERROR update_printer_sec(struct policy_handle *handle,
    6209             :                                  struct pipes_struct *p,
    6210             :                                  struct sec_desc_buf *secdesc_ctr)
    6211             : {
    6212         120 :         struct spoolss_security_descriptor *new_secdesc = NULL;
    6213         120 :         struct spoolss_security_descriptor *old_secdesc = NULL;
    6214         120 :         const char *printer = NULL;
    6215           0 :         WERROR result;
    6216         120 :         int snum = -1;
    6217         120 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6218           0 :         struct dcerpc_binding_handle *b;
    6219         120 :         TALLOC_CTX *tmp_ctx = NULL;
    6220         120 :         bool ok = false;
    6221             : 
    6222         120 :         if (!Printer) {
    6223           0 :                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
    6224             :                          OUR_HANDLE(handle)));
    6225             : 
    6226           0 :                 result = WERR_INVALID_HANDLE;
    6227           0 :                 goto done;
    6228             :         }
    6229             : 
    6230         120 :         if (secdesc_ctr == NULL) {
    6231           0 :                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
    6232           0 :                 result = WERR_INVALID_PARAMETER;
    6233           0 :                 goto done;
    6234             :         }
    6235             : 
    6236         120 :         switch (Printer->printer_type) {
    6237           8 :         case SPLHND_SERVER:
    6238           8 :                 break;
    6239         112 :         case SPLHND_PRINTER:
    6240         112 :                 if (!get_printer_snum(p, handle, &snum, NULL)) {
    6241           0 :                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
    6242             :                                  OUR_HANDLE(handle)));
    6243           0 :                         result = WERR_INVALID_HANDLE;
    6244           0 :                         goto done;
    6245             :                 }
    6246         112 :                 printer = lp_const_servicename(snum);
    6247         112 :                 break;
    6248           0 :         default:
    6249           0 :                 break;
    6250             :         }
    6251             : 
    6252             :         /* Check the user has permissions to change the security
    6253             :            descriptor.  By experimentation with two NT machines, the user
    6254             :            requires Full Access to the printer to change security
    6255             :            information. */
    6256             : 
    6257         120 :         switch (Printer->printer_type) {
    6258           8 :         case SPLHND_SERVER:
    6259           8 :                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
    6260           8 :                 break;
    6261         112 :         case SPLHND_PRINTER:
    6262         112 :                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
    6263         112 :                 break;
    6264           0 :         default:
    6265           0 :                 break;
    6266             :         }
    6267             : 
    6268         120 :         if (!ok) {
    6269           0 :                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
    6270             :                         "(access_granted: 0x%08x)\n", Printer->access_granted));
    6271           0 :                 result = WERR_ACCESS_DENIED;
    6272           0 :                 goto done;
    6273             :         }
    6274             : 
    6275         120 :         tmp_ctx = talloc_new(p->mem_ctx);
    6276         120 :         if (!tmp_ctx) {
    6277           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6278             :         }
    6279             : 
    6280         120 :         result = winreg_printer_binding_handle(tmp_ctx,
    6281             :                                                get_session_info_system(),
    6282             :                                                p->msg_ctx,
    6283             :                                                &b);
    6284         120 :         if (!W_ERROR_IS_OK(result)) {
    6285           0 :                 goto done;
    6286             :         }
    6287             : 
    6288             :         /* NT seems to like setting the security descriptor even though
    6289             :            nothing may have actually changed. */
    6290             : 
    6291         120 :         if (printer != NULL) {
    6292         112 :                 result = winreg_get_printer_secdesc(tmp_ctx, b,
    6293             :                                                     printer,
    6294             :                                                     &old_secdesc);
    6295             :         } else {
    6296           8 :                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
    6297             :                                                         &old_secdesc);
    6298             :         }
    6299         120 :         if (!W_ERROR_IS_OK(result)) {
    6300           0 :                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
    6301           0 :                 result = WERR_INVALID_HANDLE;
    6302           0 :                 goto done;
    6303             :         }
    6304             : 
    6305         120 :         if (DEBUGLEVEL >= 10) {
    6306           0 :                 struct dom_sid_buf buf;
    6307           0 :                 struct security_acl *the_acl;
    6308           0 :                 int i;
    6309             : 
    6310           0 :                 the_acl = old_secdesc->dacl;
    6311           0 :                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
    6312             :                            printer, the_acl->num_aces));
    6313             : 
    6314           0 :                 for (i = 0; i < the_acl->num_aces; i++) {
    6315           0 :                         DEBUG(10, ("%s 0x%08x\n",
    6316             :                                    dom_sid_str_buf(
    6317             :                                            &the_acl->aces[i].trustee,
    6318             :                                            &buf),
    6319             :                                   the_acl->aces[i].access_mask));
    6320             :                 }
    6321             : 
    6322           0 :                 the_acl = secdesc_ctr->sd->dacl;
    6323             : 
    6324           0 :                 if (the_acl) {
    6325           0 :                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
    6326             :                                    printer, the_acl->num_aces));
    6327             : 
    6328           0 :                         for (i = 0; i < the_acl->num_aces; i++) {
    6329           0 :                                 DEBUG(10, ("%s 0x%08x\n",
    6330             :                                            dom_sid_str_buf(
    6331             :                                                    &the_acl->aces[i].trustee,
    6332             :                                                    &buf),
    6333             :                                            the_acl->aces[i].access_mask));
    6334             :                         }
    6335             :                 } else {
    6336           0 :                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
    6337             :                 }
    6338             :         }
    6339             : 
    6340         120 :         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
    6341         120 :         if (new_secdesc == NULL) {
    6342           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    6343           0 :                 goto done;
    6344             :         }
    6345             : 
    6346         120 :         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
    6347          56 :                 result = WERR_OK;
    6348          56 :                 goto done;
    6349             :         }
    6350             : 
    6351          64 :         if (printer != NULL) {
    6352          56 :                 result = winreg_set_printer_secdesc(tmp_ctx, b,
    6353             :                                                     printer,
    6354             :                                                     new_secdesc);
    6355             :         } else {
    6356           8 :                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
    6357             :                                                         new_secdesc);
    6358             :         }
    6359             : 
    6360         120 : done:
    6361         120 :         talloc_free(tmp_ctx);
    6362         120 :         return result;
    6363             : }
    6364             : 
    6365             : /********************************************************************
    6366             :  Canonicalize printer info from a client
    6367             :  ********************************************************************/
    6368             : 
    6369         100 : static bool check_printer_ok(TALLOC_CTX *mem_ctx,
    6370             :                              struct spoolss_SetPrinterInfo2 *info2,
    6371             :                              int snum)
    6372             : {
    6373           0 :         fstring printername;
    6374           0 :         const char *p;
    6375             : 
    6376         100 :         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
    6377             :                 "portname=%s drivername=%s comment=%s location=%s\n",
    6378             :                 info2->servername, info2->printername, info2->sharename,
    6379             :                 info2->portname, info2->drivername, info2->comment,
    6380             :                 info2->location));
    6381             : 
    6382             :         /* we force some elements to "correct" values */
    6383         100 :         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
    6384         100 :         if (info2->servername == NULL) {
    6385           0 :                 return false;
    6386             :         }
    6387         100 :         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
    6388         100 :         if (info2->sharename == NULL) {
    6389           0 :                 return false;
    6390             :         }
    6391             : 
    6392             :         /* check to see if we allow printername != sharename */
    6393         100 :         if (lp_force_printername(snum)) {
    6394           0 :                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
    6395             :                                         lp_netbios_name(), info2->sharename);
    6396             :         } else {
    6397             :                 /* make sure printername is in \\server\printername format */
    6398         100 :                 fstrcpy(printername, info2->printername);
    6399         100 :                 p = printername;
    6400         100 :                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
    6401          56 :                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
    6402          56 :                                 p++;
    6403             :                 }
    6404             : 
    6405         100 :                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
    6406             :                                         lp_netbios_name(), p);
    6407             :         }
    6408         100 :         if (info2->printername == NULL) {
    6409           0 :                 return false;
    6410             :         }
    6411             : 
    6412         100 :         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
    6413         100 :         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
    6414             : 
    6415         100 :         return true;
    6416             : }
    6417             : 
    6418             : /****************************************************************************
    6419             : ****************************************************************************/
    6420             : 
    6421           0 : static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
    6422             : {
    6423           0 :         const struct loadparm_substitution *lp_sub =
    6424           0 :                 loadparm_s3_global_substitution();
    6425           0 :         char *cmd = lp_addport_command(talloc_tos(), lp_sub);
    6426           0 :         char *command = NULL;
    6427           0 :         int ret;
    6428           0 :         bool is_print_op = false;
    6429             : 
    6430           0 :         if ( !*cmd ) {
    6431           0 :                 return WERR_ACCESS_DENIED;
    6432             :         }
    6433             : 
    6434           0 :         command = talloc_asprintf(ctx,
    6435             :                         "%s \"%s\" \"%s\"", cmd, portname, uri );
    6436           0 :         if (!command) {
    6437           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6438             :         }
    6439             : 
    6440           0 :         if ( token )
    6441           0 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
    6442             : 
    6443           0 :         DEBUG(10,("Running [%s]\n", command));
    6444             : 
    6445             :         /********* BEGIN SePrintOperatorPrivilege **********/
    6446             : 
    6447           0 :         if ( is_print_op )
    6448           0 :                 become_root();
    6449             : 
    6450           0 :         ret = smbrun(command, NULL, NULL);
    6451             : 
    6452           0 :         if ( is_print_op )
    6453           0 :                 unbecome_root();
    6454             : 
    6455             :         /********* END SePrintOperatorPrivilege **********/
    6456             : 
    6457           0 :         DEBUGADD(10,("returned [%d]\n", ret));
    6458             : 
    6459           0 :         TALLOC_FREE(command);
    6460             : 
    6461           0 :         if ( ret != 0 ) {
    6462           0 :                 return WERR_ACCESS_DENIED;
    6463             :         }
    6464             : 
    6465           0 :         return WERR_OK;
    6466             : }
    6467             : 
    6468             : /****************************************************************************
    6469             : ****************************************************************************/
    6470             : 
    6471        4902 : static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
    6472             :                                    int snum)
    6473             : {
    6474             :         /*
    6475             :          * As we do not know if we are embedded in the file server process
    6476             :          * or not, we have to pretend that all shares are in use.
    6477             :          */
    6478        4902 :         return true;
    6479             : }
    6480             : 
    6481          66 : static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
    6482             :                              struct spoolss_SetPrinterInfo2 *info2,
    6483             :                              const char *remote_machine,
    6484             :                              struct messaging_context *msg_ctx)
    6485             : {
    6486           0 :         const struct loadparm_substitution *lp_sub =
    6487          66 :                 loadparm_s3_global_substitution();
    6488          66 :         char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
    6489           0 :         char **qlines;
    6490          66 :         char *command = NULL;
    6491           0 :         int numlines;
    6492           0 :         int ret;
    6493           0 :         int fd;
    6494          66 :         bool is_print_op = false;
    6495             : 
    6496          66 :         if (!remote_machine) {
    6497           0 :                 return false;
    6498             :         }
    6499             : 
    6500          66 :         command = talloc_asprintf(ctx,
    6501             :                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
    6502             :                         cmd, info2->printername, info2->sharename,
    6503             :                         info2->portname, info2->drivername,
    6504             :                         info2->location, info2->comment, remote_machine);
    6505          66 :         if (!command) {
    6506           0 :                 return false;
    6507             :         }
    6508             : 
    6509          66 :         if ( token )
    6510          66 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
    6511             : 
    6512          66 :         DEBUG(10,("Running [%s]\n", command));
    6513             : 
    6514             :         /********* BEGIN SePrintOperatorPrivilege **********/
    6515             : 
    6516          66 :         if ( is_print_op )
    6517           0 :                 become_root();
    6518             : 
    6519          66 :         ret = smbrun(command, &fd, NULL);
    6520          66 :         if (ret == 0) {
    6521             :                 /* Tell everyone we updated smb.conf. */
    6522          66 :                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
    6523             :         }
    6524             : 
    6525          66 :         if ( is_print_op )
    6526           0 :                 unbecome_root();
    6527             : 
    6528             :         /********* END SePrintOperatorPrivilege **********/
    6529             : 
    6530          66 :         DEBUGADD(10,("returned [%d]\n", ret));
    6531             : 
    6532          66 :         TALLOC_FREE(command);
    6533             : 
    6534          66 :         if ( ret != 0 ) {
    6535           0 :                 if (fd != -1)
    6536           0 :                         close(fd);
    6537           0 :                 return false;
    6538             :         }
    6539             : 
    6540             :         /* reload our services immediately */
    6541          66 :         become_root();
    6542          66 :         reload_services(NULL, spoolss_conn_snum_used, false);
    6543          66 :         unbecome_root();
    6544             : 
    6545          66 :         numlines = 0;
    6546             :         /* Get lines and convert them back to dos-codepage */
    6547          66 :         qlines = fd_lines_load(fd, &numlines, 0, NULL);
    6548          66 :         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
    6549          66 :         close(fd);
    6550             : 
    6551             :         /* Set the portname to what the script says the portname should be. */
    6552             :         /* but don't require anything to be return from the script exit a good error code */
    6553             : 
    6554          66 :         if (numlines) {
    6555             :                 /* Set the portname to what the script says the portname should be. */
    6556           0 :                 info2->portname = talloc_strdup(ctx, qlines[0]);
    6557           0 :                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
    6558             :         }
    6559             : 
    6560          66 :         TALLOC_FREE(qlines);
    6561          66 :         return true;
    6562             : }
    6563             : 
    6564         100 : static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
    6565             :                                const struct auth_session_info *session_info,
    6566             :                                struct messaging_context *msg_ctx,
    6567             :                                int snum,
    6568             :                                struct spoolss_SetPrinterInfo2 *printer,
    6569             :                                struct spoolss_PrinterInfo2 *old_printer)
    6570             : {
    6571         100 :         bool force_update = (old_printer == NULL);
    6572           0 :         const char *dnsdomname;
    6573           0 :         const char *longname;
    6574           0 :         const char *uncname;
    6575           0 :         const char *spooling;
    6576           0 :         DATA_BLOB buffer;
    6577         100 :         WERROR result = WERR_OK;
    6578           0 :         struct dcerpc_binding_handle *b;
    6579           0 :         TALLOC_CTX *tmp_ctx;
    6580           0 :         bool ok;
    6581             : 
    6582         100 :         tmp_ctx = talloc_new(mem_ctx);
    6583         100 :         if (!tmp_ctx) {
    6584           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6585             :         }
    6586             : 
    6587         100 :         result = winreg_printer_binding_handle(tmp_ctx,
    6588             :                                                session_info,
    6589             :                                                msg_ctx,
    6590             :                                                &b);
    6591         100 :         if (!W_ERROR_IS_OK(result)) {
    6592           0 :                 goto done;
    6593             :         }
    6594             : 
    6595         100 :         if (printer->drivername != NULL &&
    6596          84 :             (force_update ||
    6597          84 :              !strequal(printer->drivername, old_printer->drivername))) {
    6598          24 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
    6599          24 :                 if (!ok) {
    6600           0 :                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
    6601           0 :                         result = WERR_INVALID_DATA;
    6602           0 :                         goto done;
    6603             :                 }
    6604          24 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6605             :                                           printer->sharename,
    6606             :                                           SPOOL_DSSPOOLER_KEY,
    6607             :                                           SPOOL_REG_DRIVERNAME,
    6608             :                                           REG_SZ,
    6609             :                                           buffer.data,
    6610          24 :                                           buffer.length);
    6611          24 :                 if (!W_ERROR_IS_OK(result)) {
    6612           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
    6613           0 :                         goto done;
    6614             :                 }
    6615             : 
    6616          24 :                 if (!force_update) {
    6617           8 :                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
    6618             :                                 printer->drivername));
    6619             : 
    6620           8 :                         notify_printer_driver(global_event_context(), msg_ctx,
    6621           8 :                                               snum, printer->drivername ?
    6622             :                                               printer->drivername : "");
    6623             :                 }
    6624             :         }
    6625             : 
    6626         100 :         if (printer->comment != NULL &&
    6627          84 :             (force_update ||
    6628          84 :              !strequal(printer->comment, old_printer->comment))) {
    6629          34 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
    6630          34 :                 if (!ok) {
    6631           0 :                         DEBUG(0, ("comment data corrupted\n"));
    6632           0 :                         result = WERR_INVALID_DATA;
    6633           0 :                         goto done;
    6634             :                 }
    6635          34 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6636             :                                           printer->sharename,
    6637             :                                           SPOOL_DSSPOOLER_KEY,
    6638             :                                           SPOOL_REG_DESCRIPTION,
    6639             :                                           REG_SZ,
    6640             :                                           buffer.data,
    6641          34 :                                           buffer.length);
    6642          34 :                 if (!W_ERROR_IS_OK(result)) {
    6643           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
    6644           0 :                         goto done;
    6645             :                 }
    6646             : 
    6647          34 :                 if (!force_update) {
    6648          34 :                         notify_printer_comment(global_event_context(), msg_ctx,
    6649          34 :                                                snum, printer->comment ?
    6650             :                                                printer->comment : "");
    6651             :                 }
    6652             :         }
    6653             : 
    6654         100 :         if (printer->sharename != NULL &&
    6655          84 :             (force_update ||
    6656          84 :              !strequal(printer->sharename, old_printer->sharename))) {
    6657          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
    6658          16 :                 if (!ok) {
    6659           0 :                         DEBUG(0, ("sharename data corrupted\n"));
    6660           0 :                         result = WERR_INVALID_DATA;
    6661           0 :                         goto done;
    6662             :                 }
    6663          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6664             :                                           printer->sharename,
    6665             :                                           SPOOL_DSSPOOLER_KEY,
    6666             :                                           SPOOL_REG_PRINTSHARENAME,
    6667             :                                           REG_SZ,
    6668             :                                           buffer.data,
    6669          16 :                                           buffer.length);
    6670          16 :                 if (!W_ERROR_IS_OK(result)) {
    6671           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
    6672           0 :                         goto done;
    6673             :                 }
    6674             : 
    6675          16 :                 if (!force_update) {
    6676           0 :                         notify_printer_sharename(global_event_context(),
    6677             :                                                  msg_ctx,
    6678           0 :                                                  snum, printer->sharename ?
    6679             :                                                  printer->sharename : "");
    6680             :                 }
    6681             : 
    6682             :                 /* name change, purge any cache entries for the old */
    6683          16 :                 prune_printername_cache();
    6684             :         }
    6685             : 
    6686         100 :         if (printer->printername != NULL &&
    6687          84 :             (force_update ||
    6688          84 :              !strequal(printer->printername, old_printer->printername))) {
    6689           0 :                 const char *p;
    6690             : 
    6691         100 :                 p = strrchr(printer->printername, '\\' );
    6692         100 :                 if (p != NULL) {
    6693         100 :                         p++;
    6694             :                 } else {
    6695           0 :                         p = printer->printername;
    6696             :                 }
    6697             : 
    6698         100 :                 ok = push_reg_sz(tmp_ctx, &buffer, p);
    6699         100 :                 if (!ok) {
    6700           0 :                         DEBUG(0, ("printername data corrupted\n"));
    6701           0 :                         result = WERR_INVALID_DATA;
    6702           0 :                         goto done;
    6703             :                 }
    6704         100 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6705             :                                           printer->sharename,
    6706             :                                           SPOOL_DSSPOOLER_KEY,
    6707             :                                           SPOOL_REG_PRINTERNAME,
    6708             :                                           REG_SZ,
    6709             :                                           buffer.data,
    6710         100 :                                           buffer.length);
    6711         100 :                 if (!W_ERROR_IS_OK(result)) {
    6712           0 :                         DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
    6713           0 :                         goto done;
    6714             :                 }
    6715             : 
    6716         100 :                 if (!force_update) {
    6717          84 :                         notify_printer_printername(global_event_context(),
    6718             :                                                    msg_ctx, snum, p ? p : "");
    6719             :                 }
    6720             : 
    6721             :                 /* name change, purge any cache entries for the old */
    6722         100 :                 prune_printername_cache();
    6723             :         }
    6724             : 
    6725         100 :         if (printer->portname != NULL &&
    6726          84 :             (force_update ||
    6727          84 :              !strequal(printer->portname, old_printer->portname))) {
    6728          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
    6729          16 :                 if (!ok) {
    6730           0 :                         DEBUG(0, ("portname data corrupted\n"));
    6731           0 :                         result = WERR_INVALID_DATA;
    6732           0 :                         goto done;
    6733             :                 }
    6734          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6735             :                                           printer->sharename,
    6736             :                                           SPOOL_DSSPOOLER_KEY,
    6737             :                                           SPOOL_REG_PORTNAME,
    6738             :                                           REG_SZ,
    6739             :                                           buffer.data,
    6740          16 :                                           buffer.length);
    6741          16 :                 if (!W_ERROR_IS_OK(result)) {
    6742           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
    6743           0 :                         goto done;
    6744             :                 }
    6745             : 
    6746          16 :                 if (!force_update) {
    6747           0 :                         notify_printer_port(global_event_context(),
    6748           0 :                                             msg_ctx, snum, printer->portname ?
    6749             :                                             printer->portname : "");
    6750             :                 }
    6751             :         }
    6752             : 
    6753         100 :         if (printer->location != NULL &&
    6754          84 :             (force_update ||
    6755          84 :              !strequal(printer->location, old_printer->location))) {
    6756           8 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
    6757           8 :                 if (!ok) {
    6758           0 :                         DEBUG(0, ("location data corrupted\n"));
    6759           0 :                         result = WERR_INVALID_DATA;
    6760           0 :                         goto done;
    6761             :                 }
    6762           8 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6763             :                                           printer->sharename,
    6764             :                                           SPOOL_DSSPOOLER_KEY,
    6765             :                                           SPOOL_REG_LOCATION,
    6766             :                                           REG_SZ,
    6767             :                                           buffer.data,
    6768           8 :                                           buffer.length);
    6769           8 :                 if (!W_ERROR_IS_OK(result)) {
    6770           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
    6771           0 :                         goto done;
    6772             :                 }
    6773             : 
    6774           8 :                 if (!force_update) {
    6775           8 :                         notify_printer_location(global_event_context(),
    6776             :                                                 msg_ctx, snum,
    6777           8 :                                                 printer->location ?
    6778             :                                                 printer->location : "");
    6779             :                 }
    6780             :         }
    6781             : 
    6782         100 :         if (printer->sepfile != NULL &&
    6783          84 :             (force_update ||
    6784          84 :              !strequal(printer->sepfile, old_printer->sepfile))) {
    6785           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
    6786           0 :                 if (!ok) {
    6787           0 :                         DEBUG(0, ("sepfile data corrupted\n"));
    6788           0 :                         result = WERR_INVALID_DATA;
    6789           0 :                         goto done;
    6790             :                 }
    6791           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6792             :                                           printer->sharename,
    6793             :                                           SPOOL_DSSPOOLER_KEY,
    6794             :                                           SPOOL_REG_PRINTSEPARATORFILE,
    6795             :                                           REG_SZ,
    6796             :                                           buffer.data,
    6797           0 :                                           buffer.length);
    6798           0 :                 if (!W_ERROR_IS_OK(result)) {
    6799           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
    6800           0 :                         goto done;
    6801             :                 }
    6802             : 
    6803           0 :                 if (!force_update) {
    6804           0 :                         notify_printer_sepfile(global_event_context(),
    6805             :                                                msg_ctx, snum,
    6806           0 :                                                printer->sepfile ?
    6807             :                                                printer->sepfile : "");
    6808             :                 }
    6809             :         }
    6810             : 
    6811         100 :         if (printer->starttime != 0 &&
    6812           0 :             (force_update ||
    6813           0 :              printer->starttime != old_printer->starttime)) {
    6814           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6815           0 :                 SIVAL(buffer.data, 0, printer->starttime);
    6816           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6817             :                                           printer->sharename,
    6818             :                                           SPOOL_DSSPOOLER_KEY,
    6819             :                                           SPOOL_REG_PRINTSTARTTIME,
    6820             :                                           REG_DWORD,
    6821             :                                           buffer.data,
    6822           0 :                                           buffer.length);
    6823           0 :                 if (!W_ERROR_IS_OK(result)) {
    6824           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
    6825           0 :                         goto done;
    6826             :                 }
    6827             :         }
    6828             : 
    6829         100 :         if (printer->untiltime != 0 &&
    6830           0 :             (force_update ||
    6831           0 :              printer->untiltime != old_printer->untiltime)) {
    6832           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6833           0 :                 SIVAL(buffer.data, 0, printer->untiltime);
    6834           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6835             :                                           printer->sharename,
    6836             :                                           SPOOL_DSSPOOLER_KEY,
    6837             :                                           SPOOL_REG_PRINTENDTIME,
    6838             :                                           REG_DWORD,
    6839             :                                           buffer.data,
    6840           0 :                                           buffer.length);
    6841           0 :                 if (!W_ERROR_IS_OK(result)) {
    6842           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6843           0 :                         goto done;
    6844             :                 }
    6845             :         }
    6846             : 
    6847         100 :         if (force_update || printer->priority != old_printer->priority) {
    6848          16 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6849          16 :                 SIVAL(buffer.data, 0, printer->priority);
    6850          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6851             :                                           printer->sharename,
    6852             :                                           SPOOL_DSSPOOLER_KEY,
    6853             :                                           SPOOL_REG_PRIORITY,
    6854             :                                           REG_DWORD,
    6855             :                                           buffer.data,
    6856          16 :                                           buffer.length);
    6857          16 :                 if (!W_ERROR_IS_OK(result)) {
    6858           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6859           0 :                         goto done;
    6860             :                 }
    6861             :         }
    6862             : 
    6863         100 :         if (force_update || printer->attributes != old_printer->attributes) {
    6864          16 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6865          16 :                 SIVAL(buffer.data, 0, (printer->attributes &
    6866             :                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
    6867          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6868             :                                           printer->sharename,
    6869             :                                           SPOOL_DSSPOOLER_KEY,
    6870             :                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
    6871             :                                           REG_DWORD,
    6872             :                                           buffer.data,
    6873          16 :                                           buffer.length);
    6874          16 :                 if (!W_ERROR_IS_OK(result)) {
    6875           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6876           0 :                         goto done;
    6877             :                 }
    6878             : 
    6879          16 :                 switch (printer->attributes & 0x3) {
    6880          16 :                         case 0:
    6881          16 :                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
    6882          16 :                                 break;
    6883           0 :                         case 1:
    6884           0 :                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
    6885           0 :                                 break;
    6886           0 :                         case 2:
    6887           0 :                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
    6888           0 :                                 break;
    6889           0 :                         default:
    6890           0 :                                 spooling = "unknown";
    6891             :                 }
    6892          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
    6893          16 :                 if (!ok) {
    6894           0 :                         DEBUG(0, ("printSpooling data corrupted\n"));
    6895           0 :                         result = WERR_INVALID_DATA;
    6896           0 :                         goto done;
    6897             :                 }
    6898          16 :                 winreg_set_printer_dataex(tmp_ctx, b,
    6899             :                                           printer->sharename,
    6900             :                                           SPOOL_DSSPOOLER_KEY,
    6901             :                                           SPOOL_REG_PRINTSPOOLING,
    6902             :                                           REG_SZ,
    6903             :                                           buffer.data,
    6904          16 :                                           buffer.length);
    6905             :         }
    6906             : 
    6907         100 :         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
    6908         100 :         if (!ok) {
    6909           0 :                 DEBUG(0, ("shortServerName data corrupted\n"));
    6910           0 :                 result = WERR_INVALID_DATA;
    6911           0 :                 goto done;
    6912             :         }
    6913         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6914             :                                   printer->sharename,
    6915             :                                   SPOOL_DSSPOOLER_KEY,
    6916             :                                   SPOOL_REG_SHORTSERVERNAME,
    6917             :                                   REG_SZ,
    6918             :                                   buffer.data,
    6919         100 :                                   buffer.length);
    6920         100 :         if (!W_ERROR_IS_OK(result)) {
    6921           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
    6922           0 :                 goto done;
    6923             :         }
    6924             : 
    6925         100 :         dnsdomname = get_mydnsfullname();
    6926         100 :         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
    6927         100 :                 longname = talloc_strdup(tmp_ctx, dnsdomname);
    6928             :         } else {
    6929           0 :                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
    6930             :         }
    6931         100 :         if (longname == NULL) {
    6932           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    6933           0 :                 goto done;
    6934             :         }
    6935             : 
    6936         100 :         ok = push_reg_sz(tmp_ctx, &buffer, longname);
    6937         100 :         if (!ok) {
    6938           0 :                 DEBUG(0, ("longname data corrupted\n"));
    6939           0 :                 result = WERR_INVALID_DATA;
    6940           0 :                 goto done;
    6941             :         }
    6942         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6943             :                                            printer->sharename,
    6944             :                                            SPOOL_DSSPOOLER_KEY,
    6945             :                                            SPOOL_REG_SERVERNAME,
    6946             :                                            REG_SZ,
    6947             :                                            buffer.data,
    6948         100 :                                            buffer.length);
    6949         100 :         if (!W_ERROR_IS_OK(result)) {
    6950           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
    6951           0 :                 goto done;
    6952             :         }
    6953             : 
    6954         100 :         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
    6955             :                                   lp_netbios_name(), printer->sharename);
    6956         100 :         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
    6957         100 :         if (!ok) {
    6958           0 :                 DEBUG(0, ("uncName data corrupted\n"));
    6959           0 :                 result = WERR_INVALID_DATA;
    6960           0 :                 goto done;
    6961             :         }
    6962         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6963             :                                   printer->sharename,
    6964             :                                   SPOOL_DSSPOOLER_KEY,
    6965             :                                   SPOOL_REG_UNCNAME,
    6966             :                                   REG_SZ,
    6967             :                                   buffer.data,
    6968         100 :                                   buffer.length);
    6969         100 :         if (!W_ERROR_IS_OK(result)) {
    6970           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
    6971           0 :                 goto done;
    6972             :         }
    6973             : 
    6974         100 : done:
    6975         100 :         talloc_free(tmp_ctx);
    6976         100 :         return result;
    6977             : }
    6978             : 
    6979             : /********************************************************************
    6980             :  * Called by spoolss_api_setprinter
    6981             :  * when updating a printer description.
    6982             :  ********************************************************************/
    6983             : 
    6984          84 : static WERROR update_printer(struct pipes_struct *p,
    6985             :                              struct policy_handle *handle,
    6986             :                              struct spoolss_SetPrinterInfoCtr *info_ctr,
    6987             :                              struct spoolss_DeviceMode *devmode)
    6988             : {
    6989          84 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6990          84 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    6991           0 :         const struct tsocket_address *remote_address =
    6992          84 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    6993           0 :         struct auth_session_info *session_info =
    6994          84 :                 dcesrv_call_session_info(dce_call);
    6995          84 :         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
    6996          84 :         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
    6997           0 :         struct spoolss_PrinterInfo2 *old_printer;
    6998          84 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6999           0 :         const struct loadparm_substitution *lp_sub =
    7000          84 :                 loadparm_s3_global_substitution();
    7001           0 :         int snum;
    7002          84 :         WERROR result = WERR_OK;
    7003           0 :         TALLOC_CTX *tmp_ctx;
    7004           0 :         struct dcerpc_binding_handle *b;
    7005             : 
    7006          84 :         DEBUG(8,("update_printer\n"));
    7007             : 
    7008          84 :         tmp_ctx = talloc_new(p->mem_ctx);
    7009          84 :         if (tmp_ctx == NULL) {
    7010           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    7011             :         }
    7012             : 
    7013          84 :         if (!Printer) {
    7014           0 :                 result = WERR_INVALID_HANDLE;
    7015           0 :                 goto done;
    7016             :         }
    7017             : 
    7018          84 :         if (!get_printer_snum(p, handle, &snum, NULL)) {
    7019           0 :                 result = WERR_INVALID_HANDLE;
    7020           0 :                 goto done;
    7021             :         }
    7022             : 
    7023          84 :         result = winreg_printer_binding_handle(tmp_ctx,
    7024             :                                                get_session_info_system(),
    7025             :                                                p->msg_ctx,
    7026             :                                                &b);
    7027          84 :         if (!W_ERROR_IS_OK(result)) {
    7028           0 :                 goto done;
    7029             :         }
    7030             : 
    7031          84 :         result = winreg_get_printer(tmp_ctx, b,
    7032             :                                     lp_const_servicename(snum),
    7033             :                                     &old_printer);
    7034          84 :         if (!W_ERROR_IS_OK(result)) {
    7035           0 :                 result = WERR_INVALID_HANDLE;
    7036           0 :                 goto done;
    7037             :         }
    7038             : 
    7039             :         /* Do sanity check on the requested changes for Samba */
    7040          84 :         if (!check_printer_ok(tmp_ctx, printer, snum)) {
    7041           0 :                 result = WERR_INVALID_PARAMETER;
    7042           0 :                 goto done;
    7043             :         }
    7044             : 
    7045             :         /* FIXME!!! If the driver has changed we really should verify that
    7046             :            it is installed before doing much else   --jerry */
    7047             : 
    7048             :         /* Check calling user has permission to update printer description */
    7049          84 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
    7050           0 :                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
    7051           0 :                 result = WERR_ACCESS_DENIED;
    7052           0 :                 goto done;
    7053             :         }
    7054             : 
    7055             :         /* Call addprinter hook */
    7056             :         /* Check changes to see if this is really needed */
    7057             : 
    7058          84 :         if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
    7059          84 :                         (!strequal(printer->drivername, old_printer->drivername) ||
    7060          76 :                          !strequal(printer->comment, old_printer->comment) ||
    7061          42 :                          !strequal(printer->portname, old_printer->portname) ||
    7062          42 :                          !strequal(printer->location, old_printer->location)) )
    7063             :         {
    7064           0 :                 char *raddr;
    7065             : 
    7066          50 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    7067             :                                                          p->mem_ctx);
    7068          50 :                 if (raddr == NULL) {
    7069           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    7070           0 :                         goto done;
    7071             :                 }
    7072             : 
    7073             :                 /* add_printer_hook() will call reload_services() */
    7074          50 :                 if (!add_printer_hook(tmp_ctx, session_info->security_token,
    7075             :                                       printer, raddr,
    7076             :                                       p->msg_ctx)) {
    7077           0 :                         result = WERR_ACCESS_DENIED;
    7078           0 :                         goto done;
    7079             :                 }
    7080             :         }
    7081             : 
    7082          84 :         result = update_dsspooler(tmp_ctx,
    7083             :                                   get_session_info_system(),
    7084             :                                   p->msg_ctx,
    7085             :                                   snum,
    7086             :                                   printer,
    7087             :                                   old_printer);
    7088          84 :         if (!W_ERROR_IS_OK(result)) {
    7089           0 :                 goto done;
    7090             :         }
    7091             : 
    7092          84 :         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
    7093             : 
    7094          84 :         if (devmode == NULL) {
    7095          76 :                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
    7096             :         }
    7097          84 :         result = winreg_update_printer(tmp_ctx, b,
    7098             :                                        printer->sharename,
    7099             :                                        printer_mask,
    7100             :                                        printer,
    7101             :                                        devmode,
    7102             :                                        NULL);
    7103             : 
    7104          84 : done:
    7105          84 :         talloc_free(tmp_ctx);
    7106             : 
    7107          84 :         return result;
    7108             : }
    7109             : 
    7110             : /****************************************************************************
    7111             : ****************************************************************************/
    7112           8 : static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
    7113             :                                            struct policy_handle *handle,
    7114             :                                            struct spoolss_SetPrinterInfo7 *info7)
    7115             : {
    7116             : #ifdef HAVE_ADS
    7117           0 :         const struct loadparm_substitution *lp_sub =
    7118           6 :                 loadparm_s3_global_substitution();
    7119           6 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    7120           0 :         WERROR result;
    7121           0 :         int snum;
    7122           0 :         struct printer_handle *Printer;
    7123             : 
    7124           6 :         if ( lp_security() != SEC_ADS ) {
    7125           6 :                 return WERR_INVALID_LEVEL;
    7126             :         }
    7127             : 
    7128           0 :         Printer = find_printer_index_by_hnd(p, handle);
    7129             : 
    7130           0 :         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
    7131             : 
    7132           0 :         if (!Printer)
    7133           0 :                 return WERR_INVALID_HANDLE;
    7134             : 
    7135           0 :         if (!get_printer_snum(p, handle, &snum, NULL))
    7136           0 :                 return WERR_INVALID_HANDLE;
    7137             : 
    7138           0 :         result = winreg_get_printer_internal(p->mem_ctx,
    7139             :                                     get_session_info_system(),
    7140             :                                     p->msg_ctx,
    7141           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum),
    7142             :                                     &pinfo2);
    7143           0 :         if (!W_ERROR_IS_OK(result)) {
    7144           0 :                 return WERR_INVALID_HANDLE;
    7145             :         }
    7146             : 
    7147           0 :         nt_printer_publish(pinfo2,
    7148             :                            get_session_info_system(),
    7149             :                            p->msg_ctx,
    7150             :                            pinfo2,
    7151           0 :                            info7->action);
    7152             : 
    7153           0 :         TALLOC_FREE(pinfo2);
    7154           0 :         return WERR_OK;
    7155             : #else
    7156           2 :         return WERR_INVALID_LEVEL;
    7157             : #endif
    7158             : }
    7159             : 
    7160             : /********************************************************************
    7161             :  ********************************************************************/
    7162             : 
    7163         296 : static WERROR update_printer_devmode(struct pipes_struct *p,
    7164             :                                      struct policy_handle *handle,
    7165             :                                      struct spoolss_DeviceMode *devmode)
    7166             : {
    7167           0 :         int snum;
    7168         296 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    7169         296 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
    7170             : 
    7171         296 :         DEBUG(8,("update_printer_devmode\n"));
    7172             : 
    7173         296 :         if (!Printer) {
    7174           0 :                 return WERR_INVALID_HANDLE;
    7175             :         }
    7176             : 
    7177         296 :         if (!get_printer_snum(p, handle, &snum, NULL)) {
    7178           0 :                 return WERR_INVALID_HANDLE;
    7179             :         }
    7180             : 
    7181             :         /* Check calling user has permission to update printer description */
    7182         296 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
    7183           0 :                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
    7184           0 :                 return WERR_ACCESS_DENIED;
    7185             :         }
    7186             : 
    7187         296 :         return winreg_update_printer_internal(p->mem_ctx,
    7188             :                                      get_session_info_system(),
    7189             :                                      p->msg_ctx,
    7190             :                                      lp_const_servicename(snum),
    7191             :                                      info2_mask,
    7192             :                                      NULL,
    7193             :                                      devmode,
    7194             :                                      NULL);
    7195             : }
    7196             : 
    7197             : 
    7198             : /****************************************************************
    7199             :  _spoolss_SetPrinter
    7200             : ****************************************************************/
    7201             : 
    7202         584 : WERROR _spoolss_SetPrinter(struct pipes_struct *p,
    7203             :                            struct spoolss_SetPrinter *r)
    7204             : {
    7205           0 :         WERROR result;
    7206             : 
    7207         584 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    7208             : 
    7209         584 :         if (!Printer) {
    7210           0 :                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
    7211             :                         OUR_HANDLE(r->in.handle)));
    7212           0 :                 return WERR_INVALID_HANDLE;
    7213             :         }
    7214             : 
    7215             :         /* check the level */
    7216         584 :         switch (r->in.info_ctr->level) {
    7217         104 :                 case 0:
    7218         104 :                         return control_printer(r->in.handle, r->in.command, p);
    7219          84 :                 case 2:
    7220          84 :                         result = update_printer(p, r->in.handle,
    7221             :                                                 r->in.info_ctr,
    7222          84 :                                                 r->in.devmode_ctr->devmode);
    7223          84 :                         if (!W_ERROR_IS_OK(result))
    7224           0 :                                 return result;
    7225          84 :                         if (r->in.secdesc_ctr->sd)
    7226          28 :                                 result = update_printer_sec(r->in.handle, p,
    7227             :                                                             r->in.secdesc_ctr);
    7228          84 :                         return result;
    7229          92 :                 case 3:
    7230          92 :                         return update_printer_sec(r->in.handle, p,
    7231             :                                                   r->in.secdesc_ctr);
    7232           0 :                 case 4: {
    7233           0 :                         struct spoolss_PrinterInfo2 *old_printer;
    7234           0 :                         struct spoolss_SetPrinterInfo2 *set_old_printer;
    7235           0 :                         struct spoolss_SetPrinterInfoCtr *info_ctr;
    7236           0 :                         struct dcerpc_binding_handle *b;
    7237           0 :                         int snum;
    7238           0 :                         TALLOC_CTX *tmp_ctx;
    7239             : 
    7240           0 :                         tmp_ctx = talloc_new(p->mem_ctx);
    7241           0 :                         if (tmp_ctx == NULL) {
    7242           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7243             :                         }
    7244             : 
    7245           0 :                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7246           0 :                                 TALLOC_FREE(tmp_ctx);
    7247           0 :                                 return WERR_INVALID_HANDLE;
    7248             :                         }
    7249             : 
    7250           0 :                         result = winreg_printer_binding_handle(tmp_ctx,
    7251             :                                                                get_session_info_system(),
    7252             :                                                                p->msg_ctx,
    7253             :                                                                &b);
    7254           0 :                         if (!W_ERROR_IS_OK(result)) {
    7255           0 :                                 TALLOC_FREE(tmp_ctx);
    7256           0 :                                 return result;
    7257             :                         }
    7258             : 
    7259           0 :                         result = winreg_get_printer(tmp_ctx, b,
    7260             :                                                     lp_const_servicename(snum),
    7261             :                                                     &old_printer);
    7262           0 :                         if (!W_ERROR_IS_OK(result)) {
    7263           0 :                                 TALLOC_FREE(tmp_ctx);
    7264           0 :                                 return WERR_INVALID_HANDLE;
    7265             :                         }
    7266             : 
    7267           0 :                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
    7268           0 :                         if (old_printer->servername == NULL) {
    7269           0 :                                 TALLOC_FREE(tmp_ctx);
    7270           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7271             :                         }
    7272             : 
    7273           0 :                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
    7274           0 :                         if (old_printer->printername == NULL) {
    7275           0 :                                 TALLOC_FREE(tmp_ctx);
    7276           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7277             :                         }
    7278             : 
    7279           0 :                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
    7280             : 
    7281           0 :                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
    7282           0 :                         if (set_old_printer == NULL) {
    7283           0 :                                 TALLOC_FREE(tmp_ctx);
    7284           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7285             :                         }
    7286             : 
    7287           0 :                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
    7288             : 
    7289           0 :                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
    7290           0 :                         if (info_ctr == NULL) {
    7291           0 :                                 TALLOC_FREE(tmp_ctx);
    7292           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7293             :                         }
    7294             : 
    7295           0 :                         info_ctr->level = 2;
    7296           0 :                         info_ctr->info.info2 = set_old_printer;
    7297             : 
    7298           0 :                         result = update_printer(p, r->in.handle,
    7299             :                                                 info_ctr,
    7300           0 :                                                 r->in.devmode_ctr->devmode);
    7301             : 
    7302           0 :                         if (!W_ERROR_IS_OK(result)) {
    7303           0 :                                 TALLOC_FREE(tmp_ctx);
    7304           0 :                                 return result;
    7305             :                         }
    7306             : 
    7307           0 :                         if (r->in.secdesc_ctr->sd) {
    7308           0 :                                 result = update_printer_sec(r->in.handle, p,
    7309             :                                                             r->in.secdesc_ctr);
    7310             :                         }
    7311             : 
    7312           0 :                         TALLOC_FREE(tmp_ctx);
    7313           0 :                         return result;
    7314             :                 }
    7315           8 :                 case 7:
    7316           8 :                         return publish_or_unpublish_printer(p, r->in.handle,
    7317           8 :                                                             r->in.info_ctr->info.info7);
    7318         296 :                 case 8:
    7319         296 :                         return update_printer_devmode(p, r->in.handle,
    7320         296 :                                                       r->in.devmode_ctr->devmode);
    7321           0 :                 default:
    7322           0 :                         return WERR_INVALID_LEVEL;
    7323             :         }
    7324             : }
    7325             : 
    7326             : /****************************************************************
    7327             :  _spoolss_FindClosePrinterNotify
    7328             : ****************************************************************/
    7329             : 
    7330           0 : WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
    7331             :                                        struct spoolss_FindClosePrinterNotify *r)
    7332             : {
    7333           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    7334             : 
    7335           0 :         if (!Printer) {
    7336           0 :                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
    7337             :                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
    7338           0 :                 return WERR_INVALID_HANDLE;
    7339             :         }
    7340             : 
    7341           0 :         if (Printer->notify.cli_chan != NULL &&
    7342           0 :             Printer->notify.cli_chan->active_connections > 0) {
    7343           0 :                 int snum = -1;
    7344             : 
    7345           0 :                 if (Printer->printer_type == SPLHND_PRINTER) {
    7346           0 :                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7347           0 :                                 return WERR_INVALID_HANDLE;
    7348             :                         }
    7349             :                 }
    7350             : 
    7351           0 :                 srv_spoolss_replycloseprinter(snum, Printer);
    7352             :         }
    7353             : 
    7354           0 :         Printer->notify.flags=0;
    7355           0 :         Printer->notify.options=0;
    7356           0 :         Printer->notify.localmachine[0]='\0';
    7357           0 :         Printer->notify.printerlocal=0;
    7358           0 :         TALLOC_FREE(Printer->notify.option);
    7359             : 
    7360           0 :         return WERR_OK;
    7361             : }
    7362             : 
    7363             : /****************************************************************
    7364             :  _spoolss_AddJob
    7365             : ****************************************************************/
    7366             : 
    7367          16 : WERROR _spoolss_AddJob(struct pipes_struct *p,
    7368             :                        struct spoolss_AddJob *r)
    7369             : {
    7370          16 :         if (!r->in.buffer && (r->in.offered != 0)) {
    7371           0 :                 return WERR_INVALID_PARAMETER;
    7372             :         }
    7373             : 
    7374             :         /* this is what a NT server returns for AddJob. AddJob must fail on
    7375             :          * non-local printers */
    7376             : 
    7377          16 :         if (r->in.level != 1) {
    7378           8 :                 return WERR_INVALID_LEVEL;
    7379             :         }
    7380             : 
    7381           8 :         return WERR_INVALID_PARAMETER;
    7382             : }
    7383             : 
    7384             : /****************************************************************************
    7385             : fill_job_info1
    7386             : ****************************************************************************/
    7387             : 
    7388         320 : static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
    7389             :                              struct spoolss_JobInfo1 *r,
    7390             :                              const print_queue_struct *queue,
    7391             :                              uint32_t jobid,
    7392             :                              int position, int snum,
    7393             :                              struct spoolss_PrinterInfo2 *pinfo2)
    7394             : {
    7395           0 :         const struct loadparm_substitution *lp_sub =
    7396         320 :                 loadparm_s3_global_substitution();
    7397           0 :         struct tm *t;
    7398             : 
    7399         320 :         t = gmtime(&queue->time);
    7400             : 
    7401         320 :         r->job_id            = jobid;
    7402             : 
    7403         320 :         r->printer_name              = lp_servicename(mem_ctx, lp_sub, snum);
    7404         320 :         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
    7405         320 :         r->server_name               = talloc_strdup(mem_ctx, pinfo2->servername);
    7406         320 :         W_ERROR_HAVE_NO_MEMORY(r->server_name);
    7407         320 :         r->user_name         = talloc_strdup(mem_ctx, queue->fs_user);
    7408         320 :         W_ERROR_HAVE_NO_MEMORY(r->user_name);
    7409         320 :         r->document_name     = talloc_strdup(mem_ctx, queue->fs_file);
    7410         320 :         W_ERROR_HAVE_NO_MEMORY(r->document_name);
    7411         320 :         r->data_type         = talloc_strdup(mem_ctx, "RAW");
    7412         320 :         W_ERROR_HAVE_NO_MEMORY(r->data_type);
    7413         320 :         r->text_status               = talloc_strdup(mem_ctx, "");
    7414         320 :         W_ERROR_HAVE_NO_MEMORY(r->text_status);
    7415             : 
    7416         320 :         r->status            = nt_printj_status(queue->status);
    7417         320 :         r->priority          = queue->priority;
    7418         320 :         r->position          = position;
    7419         320 :         r->total_pages               = queue->page_count;
    7420         320 :         r->pages_printed     = 0; /* ??? */
    7421             : 
    7422         320 :         init_systemtime(&r->submitted, t);
    7423             : 
    7424         320 :         return WERR_OK;
    7425             : }
    7426             : 
    7427             : /****************************************************************************
    7428             : fill_job_info2
    7429             : ****************************************************************************/
    7430             : 
    7431          68 : static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
    7432             :                              struct spoolss_JobInfo2 *r,
    7433             :                              const print_queue_struct *queue,
    7434             :                              uint32_t jobid,
    7435             :                              int position, int snum,
    7436             :                              struct spoolss_PrinterInfo2 *pinfo2,
    7437             :                              struct spoolss_DeviceMode *devmode)
    7438             : {
    7439           0 :         const struct loadparm_substitution *lp_sub =
    7440          68 :                 loadparm_s3_global_substitution();
    7441           0 :         struct tm *t;
    7442             : 
    7443          68 :         t = gmtime(&queue->time);
    7444             : 
    7445          68 :         r->job_id            = jobid;
    7446             : 
    7447          68 :         r->printer_name              = lp_servicename(mem_ctx, lp_sub, snum);
    7448          68 :         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
    7449          68 :         r->server_name               = talloc_strdup(mem_ctx, pinfo2->servername);
    7450          68 :         W_ERROR_HAVE_NO_MEMORY(r->server_name);
    7451          68 :         r->user_name         = talloc_strdup(mem_ctx, queue->fs_user);
    7452          68 :         W_ERROR_HAVE_NO_MEMORY(r->user_name);
    7453          68 :         r->document_name     = talloc_strdup(mem_ctx, queue->fs_file);
    7454          68 :         W_ERROR_HAVE_NO_MEMORY(r->document_name);
    7455          68 :         r->notify_name               = talloc_strdup(mem_ctx, queue->fs_user);
    7456          68 :         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
    7457          68 :         r->data_type         = talloc_strdup(mem_ctx, "RAW");
    7458          68 :         W_ERROR_HAVE_NO_MEMORY(r->data_type);
    7459          68 :         r->print_processor   = talloc_strdup(mem_ctx, "winprint");
    7460          68 :         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
    7461          68 :         r->parameters                = talloc_strdup(mem_ctx, "");
    7462          68 :         W_ERROR_HAVE_NO_MEMORY(r->parameters);
    7463          68 :         r->driver_name               = talloc_strdup(mem_ctx, pinfo2->drivername);
    7464          68 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    7465             : 
    7466          68 :         r->devmode           = devmode;
    7467             : 
    7468          68 :         r->text_status               = talloc_strdup(mem_ctx, "");
    7469          68 :         W_ERROR_HAVE_NO_MEMORY(r->text_status);
    7470             : 
    7471          68 :         r->secdesc           = NULL;
    7472             : 
    7473          68 :         r->status            = nt_printj_status(queue->status);
    7474          68 :         r->priority          = queue->priority;
    7475          68 :         r->position          = position;
    7476          68 :         r->start_time                = 0;
    7477          68 :         r->until_time                = 0;
    7478          68 :         r->total_pages               = queue->page_count;
    7479          68 :         r->size                      = queue->size;
    7480          68 :         init_systemtime(&r->submitted, t);
    7481          68 :         r->time                      = 0;
    7482          68 :         r->pages_printed     = 0; /* ??? */
    7483             : 
    7484          68 :         return WERR_OK;
    7485             : }
    7486             : 
    7487             : /****************************************************************************
    7488             :  Enumjobs at level 1.
    7489             : ****************************************************************************/
    7490             : 
    7491          24 : static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
    7492             :                               const print_queue_struct *queue,
    7493             :                               uint32_t num_queues, int snum,
    7494             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7495             :                               union spoolss_JobInfo **info_p,
    7496             :                               uint32_t *count)
    7497             : {
    7498           0 :         union spoolss_JobInfo *info;
    7499           0 :         int i;
    7500          24 :         WERROR result = WERR_OK;
    7501           0 :         uint32_t num_filled;
    7502           0 :         struct tdb_print_db *pdb;
    7503             : 
    7504          24 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7505          24 :         if (info == NULL) {
    7506           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7507           0 :                 goto err_out;
    7508             :         }
    7509             : 
    7510          24 :         pdb = get_print_db_byname(pinfo2->sharename);
    7511          24 :         if (pdb == NULL) {
    7512           0 :                 result = WERR_INVALID_PARAMETER;
    7513           0 :                 goto err_info_free;
    7514             :         }
    7515             : 
    7516          24 :         num_filled = 0;
    7517         216 :         for (i = 0; i < num_queues; i++) {
    7518         192 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7519         192 :                 if (jobid == (uint32_t)-1) {
    7520           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7521           0 :                         continue;
    7522             :                 }
    7523             : 
    7524         192 :                 result = fill_job_info1(info,
    7525         192 :                                         &info[num_filled].info1,
    7526         192 :                                         &queue[i],
    7527             :                                         jobid,
    7528             :                                         i,
    7529             :                                         snum,
    7530             :                                         pinfo2);
    7531         192 :                 if (!W_ERROR_IS_OK(result)) {
    7532           0 :                         goto err_pdb_drop;
    7533             :                 }
    7534             : 
    7535         192 :                 num_filled++;
    7536             :         }
    7537             : 
    7538          24 :         release_print_db(pdb);
    7539          24 :         *info_p = info;
    7540          24 :         *count = num_filled;
    7541             : 
    7542          24 :         return WERR_OK;
    7543             : 
    7544           0 : err_pdb_drop:
    7545           0 :         release_print_db(pdb);
    7546           0 : err_info_free:
    7547           0 :         TALLOC_FREE(info);
    7548           0 : err_out:
    7549           0 :         *count = 0;
    7550           0 :         return result;
    7551             : }
    7552             : 
    7553             : /****************************************************************************
    7554             :  Enumjobs at level 2.
    7555             : ****************************************************************************/
    7556             : 
    7557          12 : static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
    7558             :                               const print_queue_struct *queue,
    7559             :                               uint32_t num_queues, int snum,
    7560             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7561             :                               union spoolss_JobInfo **info_p,
    7562             :                               uint32_t *count)
    7563             : {
    7564           0 :         union spoolss_JobInfo *info;
    7565           0 :         int i;
    7566          12 :         WERROR result = WERR_OK;
    7567           0 :         uint32_t num_filled;
    7568           0 :         struct tdb_print_db *pdb;
    7569             : 
    7570          12 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7571          12 :         if (info == NULL) {
    7572           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7573           0 :                 goto err_out;
    7574             :         }
    7575             : 
    7576          12 :         pdb = get_print_db_byname(pinfo2->sharename);
    7577          12 :         if (pdb == NULL) {
    7578           0 :                 result = WERR_INVALID_PARAMETER;
    7579           0 :                 goto err_info_free;
    7580             :         }
    7581             : 
    7582          12 :         num_filled = 0;
    7583          80 :         for (i = 0; i< num_queues; i++) {
    7584           0 :                 struct spoolss_DeviceMode *devmode;
    7585          68 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7586          68 :                 if (jobid == (uint32_t)-1) {
    7587           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7588           0 :                         continue;
    7589             :                 }
    7590             : 
    7591          68 :                 result = spoolss_create_default_devmode(info,
    7592             :                                                         pinfo2->printername,
    7593             :                                                         &devmode);
    7594          68 :                 if (!W_ERROR_IS_OK(result)) {
    7595           0 :                         DEBUG(3, ("Can't proceed w/o a devmode!\n"));
    7596           0 :                         goto err_pdb_drop;
    7597             :                 }
    7598             : 
    7599          68 :                 result = fill_job_info2(info,
    7600          68 :                                         &info[num_filled].info2,
    7601          68 :                                         &queue[i],
    7602             :                                         jobid,
    7603             :                                         i,
    7604             :                                         snum,
    7605             :                                         pinfo2,
    7606             :                                         devmode);
    7607          68 :                 if (!W_ERROR_IS_OK(result)) {
    7608           0 :                         goto err_pdb_drop;
    7609             :                 }
    7610          68 :                 num_filled++;
    7611             :         }
    7612             : 
    7613          12 :         release_print_db(pdb);
    7614          12 :         *info_p = info;
    7615          12 :         *count = num_filled;
    7616             : 
    7617          12 :         return WERR_OK;
    7618             : 
    7619           0 : err_pdb_drop:
    7620           0 :         release_print_db(pdb);
    7621           0 : err_info_free:
    7622           0 :         TALLOC_FREE(info);
    7623           0 : err_out:
    7624           0 :         *count = 0;
    7625           0 :         return result;
    7626             : }
    7627             : 
    7628             : /****************************************************************************
    7629             :  Enumjobs at level 3.
    7630             : ****************************************************************************/
    7631             : 
    7632           0 : static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
    7633             :                               const print_queue_struct *queue,
    7634             :                               uint32_t num_queues, int snum,
    7635             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7636             :                               union spoolss_JobInfo **info_p,
    7637             :                               uint32_t *count)
    7638             : {
    7639           0 :         union spoolss_JobInfo *info;
    7640           0 :         int i;
    7641           0 :         WERROR result = WERR_OK;
    7642           0 :         uint32_t num_filled;
    7643           0 :         struct tdb_print_db *pdb;
    7644             : 
    7645           0 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7646           0 :         if (info == NULL) {
    7647           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7648           0 :                 goto err_out;
    7649             :         }
    7650             : 
    7651           0 :         pdb = get_print_db_byname(pinfo2->sharename);
    7652           0 :         if (pdb == NULL) {
    7653           0 :                 result = WERR_INVALID_PARAMETER;
    7654           0 :                 goto err_info_free;
    7655             :         }
    7656             : 
    7657           0 :         num_filled = 0;
    7658           0 :         for (i = 0; i < num_queues; i++) {
    7659           0 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7660           0 :                 if (jobid == (uint32_t)-1) {
    7661           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7662           0 :                         continue;
    7663             :                 }
    7664             : 
    7665           0 :                 info[num_filled].info3.job_id = jobid;
    7666             :                 /* next_job_id is overwritten on next iteration */
    7667           0 :                 info[num_filled].info3.next_job_id = 0;
    7668           0 :                 info[num_filled].info3.reserved = 0;
    7669             : 
    7670           0 :                 if (num_filled > 0) {
    7671           0 :                         info[num_filled - 1].info3.next_job_id = jobid;
    7672             :                 }
    7673           0 :                 num_filled++;
    7674             :         }
    7675             : 
    7676           0 :         release_print_db(pdb);
    7677           0 :         *info_p = info;
    7678           0 :         *count = num_filled;
    7679             : 
    7680           0 :         return WERR_OK;
    7681             : 
    7682           0 : err_info_free:
    7683           0 :         TALLOC_FREE(info);
    7684           0 : err_out:
    7685           0 :         *count = 0;
    7686           0 :         return result;
    7687             : }
    7688             : 
    7689             : /****************************************************************
    7690             :  _spoolss_EnumJobs
    7691             : ****************************************************************/
    7692             : 
    7693          96 : WERROR _spoolss_EnumJobs(struct pipes_struct *p,
    7694             :                          struct spoolss_EnumJobs *r)
    7695             : {
    7696           0 :         WERROR result;
    7697          96 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    7698           0 :         int snum;
    7699           0 :         print_status_struct prt_status;
    7700          96 :         print_queue_struct *queue = NULL;
    7701           0 :         uint32_t count;
    7702             : 
    7703             :         /* that's an [in out] buffer */
    7704             : 
    7705          96 :         if (!r->in.buffer && (r->in.offered != 0)) {
    7706           0 :                 return WERR_INVALID_PARAMETER;
    7707             :         }
    7708             : 
    7709          96 :         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
    7710          12 :                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
    7711          12 :                 return WERR_INVALID_LEVEL;
    7712             :         }
    7713             : 
    7714          84 :         DEBUG(4,("_spoolss_EnumJobs\n"));
    7715             : 
    7716          84 :         *r->out.needed = 0;
    7717          84 :         *r->out.count = 0;
    7718          84 :         *r->out.info = NULL;
    7719             : 
    7720             :         /* lookup the printer snum and tdb entry */
    7721             : 
    7722          84 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7723           0 :                 return WERR_INVALID_HANDLE;
    7724             :         }
    7725             : 
    7726          84 :         result = winreg_get_printer_internal(p->mem_ctx,
    7727             :                                     get_session_info_system(),
    7728             :                                     p->msg_ctx,
    7729             :                                     lp_const_servicename(snum),
    7730             :                                     &pinfo2);
    7731          84 :         if (!W_ERROR_IS_OK(result)) {
    7732           0 :                 return result;
    7733             :         }
    7734             : 
    7735          84 :         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
    7736          84 :         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
    7737             :                 count, prt_status.status, prt_status.message));
    7738             : 
    7739          84 :         if (count == 0) {
    7740          48 :                 SAFE_FREE(queue);
    7741          48 :                 TALLOC_FREE(pinfo2);
    7742          48 :                 return WERR_OK;
    7743             :         }
    7744             : 
    7745          36 :         switch (r->in.level) {
    7746          24 :         case 1:
    7747          24 :                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
    7748             :                                          pinfo2, r->out.info, r->out.count);
    7749          24 :                 break;
    7750          12 :         case 2:
    7751          12 :                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
    7752             :                                          pinfo2, r->out.info, r->out.count);
    7753          12 :                 break;
    7754           0 :         case 3:
    7755           0 :                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
    7756             :                                          pinfo2, r->out.info, r->out.count);
    7757           0 :                 break;
    7758           0 :         default:
    7759           0 :                 SMB_ASSERT(false);      /* level checked on entry */
    7760             :                 break;
    7761             :         }
    7762             : 
    7763          36 :         SAFE_FREE(queue);
    7764          36 :         TALLOC_FREE(pinfo2);
    7765             : 
    7766          36 :         if (!W_ERROR_IS_OK(result)) {
    7767           0 :                 return result;
    7768             :         }
    7769             : 
    7770          36 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    7771             :                                                      spoolss_EnumJobs,
    7772             :                                                      *r->out.info, r->in.level,
    7773             :                                                      *r->out.count);
    7774          36 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    7775          36 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    7776             : 
    7777          36 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    7778             : }
    7779             : 
    7780             : /****************************************************************
    7781             :  _spoolss_ScheduleJob
    7782             : ****************************************************************/
    7783             : 
    7784           0 : WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
    7785             :                             struct spoolss_ScheduleJob *r)
    7786             : {
    7787           0 :         return WERR_OK;
    7788             : }
    7789             : 
    7790             : /****************************************************************
    7791             : ****************************************************************/
    7792             : 
    7793          32 : static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
    7794             :                                struct messaging_context *msg_ctx,
    7795             :                                const char *printer_name,
    7796             :                                uint32_t job_id,
    7797             :                                struct spoolss_SetJobInfo1 *r)
    7798             : {
    7799           0 :         char *old_doc_name;
    7800             : 
    7801          32 :         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
    7802           0 :                 return WERR_INVALID_HANDLE;
    7803             :         }
    7804             : 
    7805          32 :         if (strequal(old_doc_name, r->document_name)) {
    7806           0 :                 return WERR_OK;
    7807             :         }
    7808             : 
    7809          32 :         if (!print_job_set_name(global_event_context(), msg_ctx,
    7810             :                                 printer_name, job_id, r->document_name)) {
    7811           0 :                 return WERR_INVALID_HANDLE;
    7812             :         }
    7813             : 
    7814          32 :         return WERR_OK;
    7815             : }
    7816             : 
    7817             : /****************************************************************
    7818             :  _spoolss_SetJob
    7819             : ****************************************************************/
    7820             : 
    7821         640 : WERROR _spoolss_SetJob(struct pipes_struct *p,
    7822             :                        struct spoolss_SetJob *r)
    7823             : {
    7824         640 :         struct dcesrv_call_state *dce_call = p->dce_call;
    7825           0 :         struct auth_session_info *session_info =
    7826         640 :                 dcesrv_call_session_info(dce_call);
    7827           0 :         int snum;
    7828         640 :         WERROR errcode = WERR_INVALID_FUNCTION;
    7829             : 
    7830         640 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7831           0 :                 return WERR_INVALID_HANDLE;
    7832             :         }
    7833             : 
    7834         640 :         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
    7835         241 :                 return WERR_INVALID_PRINTER_NAME;
    7836             :         }
    7837             : 
    7838         399 :         switch (r->in.command) {
    7839         303 :         case SPOOLSS_JOB_CONTROL_CANCEL:
    7840             :         case SPOOLSS_JOB_CONTROL_DELETE:
    7841         303 :                 errcode = print_job_delete(session_info, p->msg_ctx,
    7842             :                                            snum, r->in.job_id);
    7843         303 :                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
    7844         303 :                         errcode = WERR_OK;
    7845             :                 }
    7846         303 :                 break;
    7847          32 :         case SPOOLSS_JOB_CONTROL_PAUSE:
    7848          32 :                 errcode = print_job_pause(session_info, p->msg_ctx,
    7849             :                                           snum, r->in.job_id);
    7850          32 :                 break;
    7851          32 :         case SPOOLSS_JOB_CONTROL_RESTART:
    7852             :         case SPOOLSS_JOB_CONTROL_RESUME:
    7853          32 :                 errcode = print_job_resume(session_info, p->msg_ctx,
    7854             :                                            snum, r->in.job_id);
    7855          32 :                 break;
    7856          32 :         case SPOOLSS_JOB_CONTROL_NOOP:
    7857          32 :                 errcode = WERR_OK;
    7858          32 :                 break;
    7859           0 :         default:
    7860           0 :                 return WERR_INVALID_LEVEL;
    7861             :         }
    7862             : 
    7863         399 :         if (!W_ERROR_IS_OK(errcode)) {
    7864           0 :                 return errcode;
    7865             :         }
    7866             : 
    7867         399 :         if (r->in.ctr == NULL) {
    7868         367 :                 return errcode;
    7869             :         }
    7870             : 
    7871          32 :         switch (r->in.ctr->level) {
    7872          32 :         case 1:
    7873          32 :                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
    7874             :                                            lp_const_servicename(snum),
    7875             :                                            r->in.job_id,
    7876          32 :                                            r->in.ctr->info.info1);
    7877          32 :                 break;
    7878           0 :         case 2:
    7879             :         case 3:
    7880             :         case 4:
    7881             :         default:
    7882           0 :                 return WERR_INVALID_LEVEL;
    7883             :         }
    7884             : 
    7885          32 :         return errcode;
    7886             : }
    7887             : 
    7888             : /****************************************************************************
    7889             :  Enumerates all printer drivers by level and architecture.
    7890             : ****************************************************************************/
    7891             : 
    7892         460 : static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
    7893             :                                                        const struct auth_session_info *session_info,
    7894             :                                                        struct messaging_context *msg_ctx,
    7895             :                                                        const char *servername,
    7896             :                                                        const char *architecture,
    7897             :                                                        uint32_t level,
    7898             :                                                        union spoolss_DriverInfo **info_p,
    7899             :                                                        uint32_t *count_p)
    7900             : {
    7901           0 :         int i;
    7902           0 :         uint32_t version;
    7903           0 :         struct spoolss_DriverInfo8 *driver;
    7904         460 :         union spoolss_DriverInfo *info = NULL;
    7905         460 :         uint32_t count = 0;
    7906         460 :         WERROR result = WERR_OK;
    7907           0 :         uint32_t num_drivers;
    7908           0 :         const char **drivers;
    7909           0 :         struct dcerpc_binding_handle *b;
    7910         460 :         TALLOC_CTX *tmp_ctx = NULL;
    7911             : 
    7912         460 :         *count_p = 0;
    7913         460 :         *info_p = NULL;
    7914             : 
    7915         460 :         tmp_ctx = talloc_new(mem_ctx);
    7916         460 :         if (!tmp_ctx) {
    7917           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    7918             :         }
    7919             : 
    7920         460 :         result = winreg_printer_binding_handle(tmp_ctx,
    7921             :                                                session_info,
    7922             :                                                msg_ctx,
    7923             :                                                &b);
    7924         460 :         if (!W_ERROR_IS_OK(result)) {
    7925           0 :                 goto out;
    7926             :         }
    7927             : 
    7928        2300 :         for (version=0; version<DRIVER_MAX_VERSION; version++) {
    7929        1840 :                 result = winreg_get_driver_list(tmp_ctx, b,
    7930             :                                                 architecture, version,
    7931             :                                                 &num_drivers, &drivers);
    7932        1840 :                 if (!W_ERROR_IS_OK(result)) {
    7933           0 :                         goto out;
    7934             :                 }
    7935        1840 :                 DEBUG(4, ("we have:[%d] drivers in environment"
    7936             :                           " [%s] and version [%d]\n",
    7937             :                           num_drivers, architecture, version));
    7938             : 
    7939        1840 :                 if (num_drivers != 0) {
    7940           0 :                         info = talloc_realloc(tmp_ctx, info,
    7941             :                                                     union spoolss_DriverInfo,
    7942             :                                                     count + num_drivers);
    7943           0 :                         if (!info) {
    7944           0 :                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
    7945             :                                         "failed to enlarge driver info buffer!\n"));
    7946           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
    7947           0 :                                 goto out;
    7948             :                         }
    7949             :                 }
    7950             : 
    7951        1840 :                 for (i = 0; i < num_drivers; i++) {
    7952           0 :                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
    7953             : 
    7954           0 :                         result = winreg_get_driver(tmp_ctx, b,
    7955           0 :                                                    architecture, drivers[i],
    7956             :                                                    version, &driver);
    7957           0 :                         if (!W_ERROR_IS_OK(result)) {
    7958           0 :                                 goto out;
    7959             :                         }
    7960             : 
    7961           0 :                         switch (level) {
    7962           0 :                         case 1:
    7963           0 :                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
    7964             :                                                                    driver, servername);
    7965           0 :                                 break;
    7966           0 :                         case 2:
    7967           0 :                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
    7968             :                                                                    driver, servername);
    7969           0 :                                 break;
    7970           0 :                         case 3:
    7971           0 :                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
    7972             :                                                                    driver, servername);
    7973           0 :                                 break;
    7974           0 :                         case 4:
    7975           0 :                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
    7976             :                                                                    driver, servername);
    7977           0 :                                 break;
    7978           0 :                         case 5:
    7979           0 :                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
    7980             :                                                                    driver, servername);
    7981           0 :                                 break;
    7982           0 :                         case 6:
    7983           0 :                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
    7984             :                                                                    driver, servername);
    7985           0 :                                 break;
    7986           0 :                         case 8:
    7987           0 :                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
    7988             :                                                                    driver, servername);
    7989           0 :                                 break;
    7990           0 :                         default:
    7991           0 :                                 result = WERR_INVALID_LEVEL;
    7992           0 :                                 break;
    7993             :                         }
    7994             : 
    7995           0 :                         TALLOC_FREE(driver);
    7996             : 
    7997           0 :                         if (!W_ERROR_IS_OK(result)) {
    7998           0 :                                 goto out;
    7999             :                         }
    8000             :                 }
    8001             : 
    8002        1840 :                 count += num_drivers;
    8003        1840 :                 TALLOC_FREE(drivers);
    8004             :         }
    8005             : 
    8006         460 : out:
    8007         460 :         if (W_ERROR_IS_OK(result)) {
    8008         460 :                 *info_p = talloc_move(mem_ctx, &info);
    8009         460 :                 *count_p = count;
    8010             :         }
    8011             : 
    8012         460 :         talloc_free(tmp_ctx);
    8013         460 :         return result;
    8014             : }
    8015             : 
    8016             : /****************************************************************************
    8017             :  Enumerates all printer drivers by level.
    8018             : ****************************************************************************/
    8019             : 
    8020         108 : static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
    8021             :                                        const struct auth_session_info *session_info,
    8022             :                                        struct messaging_context *msg_ctx,
    8023             :                                        const char *servername,
    8024             :                                        const char *architecture,
    8025             :                                        uint32_t level,
    8026             :                                        union spoolss_DriverInfo **info_p,
    8027             :                                        uint32_t *count_p)
    8028             : {
    8029           0 :         uint32_t a,i;
    8030         108 :         WERROR result = WERR_OK;
    8031             : 
    8032         108 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
    8033             : 
    8034         440 :                 for (a=0; archi_table[a].long_archi != NULL; a++) {
    8035             : 
    8036         396 :                         union spoolss_DriverInfo *info = NULL;
    8037         396 :                         uint32_t count = 0;
    8038             : 
    8039         396 :                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
    8040             :                                                                           session_info,
    8041             :                                                                           msg_ctx,
    8042             :                                                                           servername,
    8043         396 :                                                                           archi_table[a].long_archi,
    8044             :                                                                           level,
    8045             :                                                                           &info,
    8046             :                                                                           &count);
    8047         396 :                         if (!W_ERROR_IS_OK(result)) {
    8048           0 :                                 continue;
    8049             :                         }
    8050             : 
    8051         396 :                         for (i=0; i < count; i++) {
    8052           0 :                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
    8053             :                                              info[i], info_p, count_p);
    8054             :                         }
    8055             :                 }
    8056             : 
    8057          44 :                 return result;
    8058             :         }
    8059             : 
    8060          64 :         return enumprinterdrivers_level_by_architecture(mem_ctx,
    8061             :                                                         session_info,
    8062             :                                                         msg_ctx,
    8063             :                                                         servername,
    8064             :                                                         architecture,
    8065             :                                                         level,
    8066             :                                                         info_p,
    8067             :                                                         count_p);
    8068             : }
    8069             : 
    8070             : /****************************************************************
    8071             :  _spoolss_EnumPrinterDrivers
    8072             : ****************************************************************/
    8073             : 
    8074         108 : WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
    8075             :                                    struct spoolss_EnumPrinterDrivers *r)
    8076             : {
    8077           0 :         const char *cservername;
    8078           0 :         WERROR result;
    8079             : 
    8080             :         /* that's an [in out] buffer */
    8081             : 
    8082         108 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8083           0 :                 return WERR_INVALID_PARAMETER;
    8084             :         }
    8085             : 
    8086         108 :         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
    8087             : 
    8088         108 :         *r->out.needed = 0;
    8089         108 :         *r->out.count = 0;
    8090         108 :         *r->out.info = NULL;
    8091             : 
    8092         108 :         cservername = canon_servername(r->in.server);
    8093             : 
    8094         108 :         if (!is_myname_or_ipaddr(cservername)) {
    8095           0 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    8096             :         }
    8097             : 
    8098         108 :         result = enumprinterdrivers_level(p->mem_ctx,
    8099             :                                           get_session_info_system(),
    8100             :                                           p->msg_ctx,
    8101             :                                           cservername,
    8102             :                                           r->in.environment,
    8103             :                                           r->in.level,
    8104             :                                           r->out.info,
    8105             :                                           r->out.count);
    8106         108 :         if (!W_ERROR_IS_OK(result)) {
    8107           0 :                 return result;
    8108             :         }
    8109             : 
    8110         108 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8111             :                                                      spoolss_EnumPrinterDrivers,
    8112             :                                                      *r->out.info, r->in.level,
    8113             :                                                      *r->out.count);
    8114         108 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8115         108 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8116             : 
    8117         108 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8118             : }
    8119             : 
    8120             : /****************************************************************
    8121             :  _spoolss_EnumForms
    8122             : ****************************************************************/
    8123             : 
    8124         560 : WERROR _spoolss_EnumForms(struct pipes_struct *p,
    8125             :                           struct spoolss_EnumForms *r)
    8126             : {
    8127           0 :         WERROR result;
    8128             : 
    8129         560 :         *r->out.count = 0;
    8130         560 :         *r->out.needed = 0;
    8131         560 :         *r->out.info = NULL;
    8132             : 
    8133             :         /* that's an [in out] buffer */
    8134             : 
    8135         560 :         if (!r->in.buffer && (r->in.offered != 0) ) {
    8136           0 :                 return WERR_INVALID_PARAMETER;
    8137             :         }
    8138             : 
    8139         560 :         DEBUG(4,("_spoolss_EnumForms\n"));
    8140         560 :         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
    8141         560 :         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
    8142             : 
    8143         560 :         switch (r->in.level) {
    8144         536 :         case 1:
    8145         536 :                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
    8146             :                                                    get_session_info_system(),
    8147             :                                                    p->msg_ctx,
    8148             :                                                    r->out.count,
    8149             :                                                    r->out.info);
    8150         536 :                 break;
    8151          24 :         default:
    8152          24 :                 result = WERR_INVALID_LEVEL;
    8153          24 :                 break;
    8154             :         }
    8155             : 
    8156         560 :         if (!W_ERROR_IS_OK(result)) {
    8157          24 :                 return result;
    8158             :         }
    8159             : 
    8160         536 :         if (*r->out.count == 0) {
    8161           0 :                 return WERR_NO_MORE_ITEMS;
    8162             :         }
    8163             : 
    8164         536 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8165             :                                                      spoolss_EnumForms,
    8166             :                                                      *r->out.info, r->in.level,
    8167             :                                                      *r->out.count);
    8168         536 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8169         536 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8170             : 
    8171         536 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8172             : }
    8173             : 
    8174             : /****************************************************************
    8175             :  _spoolss_GetForm
    8176             : ****************************************************************/
    8177             : 
    8178        5040 : WERROR _spoolss_GetForm(struct pipes_struct *p,
    8179             :                         struct spoolss_GetForm *r)
    8180             : {
    8181           0 :         WERROR result;
    8182             : 
    8183             :         /* that's an [in out] buffer */
    8184             : 
    8185        5040 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8186           0 :                 TALLOC_FREE(r->out.info);
    8187           0 :                 return WERR_INVALID_PARAMETER;
    8188             :         }
    8189             : 
    8190        5040 :         DEBUG(4,("_spoolss_GetForm\n"));
    8191        5040 :         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
    8192        5040 :         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
    8193             : 
    8194        5040 :         switch (r->in.level) {
    8195        5040 :         case 1:
    8196        5040 :                 result = winreg_printer_getform1_internal(p->mem_ctx,
    8197             :                                                  get_session_info_system(),
    8198             :                                                  p->msg_ctx,
    8199             :                                                  r->in.form_name,
    8200        5040 :                                                  &r->out.info->info1);
    8201        5040 :                 break;
    8202           0 :         default:
    8203           0 :                 result = WERR_INVALID_LEVEL;
    8204           0 :                 break;
    8205             :         }
    8206             : 
    8207        5040 :         if (!W_ERROR_IS_OK(result)) {
    8208           0 :                 TALLOC_FREE(r->out.info);
    8209           0 :                 return result;
    8210             :         }
    8211             : 
    8212        5040 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
    8213             :                                                r->out.info, r->in.level);
    8214        5040 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    8215             : 
    8216        5040 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8217             : }
    8218             : 
    8219             : /****************************************************************************
    8220             : ****************************************************************************/
    8221             : 
    8222           8 : static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
    8223             :                           struct spoolss_PortInfo1 *r,
    8224             :                           const char *name)
    8225             : {
    8226           8 :         r->port_name = talloc_strdup(mem_ctx, name);
    8227           8 :         W_ERROR_HAVE_NO_MEMORY(r->port_name);
    8228             : 
    8229           8 :         return WERR_OK;
    8230             : }
    8231             : 
    8232             : /****************************************************************************
    8233             :  TODO: This probably needs distinguish between TCP/IP and Local ports
    8234             :  somehow.
    8235             : ****************************************************************************/
    8236             : 
    8237          16 : static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
    8238             :                           struct spoolss_PortInfo2 *r,
    8239             :                           const char *name)
    8240             : {
    8241          16 :         r->port_name = talloc_strdup(mem_ctx, name);
    8242          16 :         W_ERROR_HAVE_NO_MEMORY(r->port_name);
    8243             : 
    8244          16 :         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
    8245          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    8246             : 
    8247          16 :         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
    8248          16 :         W_ERROR_HAVE_NO_MEMORY(r->description);
    8249             : 
    8250          16 :         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
    8251          16 :         r->reserved = 0;
    8252             : 
    8253          16 :         return WERR_OK;
    8254             : }
    8255             : 
    8256             : 
    8257             : /****************************************************************************
    8258             :  wrapper around the enum ports command
    8259             : ****************************************************************************/
    8260             : 
    8261          24 : static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
    8262             : {
    8263           0 :         const struct loadparm_substitution *lp_sub =
    8264          24 :                 loadparm_s3_global_substitution();
    8265          24 :         char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
    8266          24 :         char **qlines = NULL;
    8267          24 :         char *command = NULL;
    8268           0 :         int numlines;
    8269           0 :         int ret;
    8270           0 :         int fd;
    8271             : 
    8272          24 :         *count = 0;
    8273          24 :         *lines = NULL;
    8274             : 
    8275             :         /* if no hook then just fill in the default port */
    8276             : 
    8277          24 :         if ( !*cmd ) {
    8278          24 :                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
    8279           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8280             :                 }
    8281          24 :                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
    8282           0 :                         TALLOC_FREE(qlines);
    8283           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8284             :                 }
    8285          24 :                 qlines[1] = NULL;
    8286          24 :                 numlines = 1;
    8287             :         }
    8288             :         else {
    8289             :                 /* we have a valid enumport command */
    8290             : 
    8291           0 :                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
    8292           0 :                 if (!command) {
    8293           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8294             :                 }
    8295             : 
    8296           0 :                 DEBUG(10,("Running [%s]\n", command));
    8297           0 :                 ret = smbrun(command, &fd, NULL);
    8298           0 :                 DEBUG(10,("Returned [%d]\n", ret));
    8299           0 :                 TALLOC_FREE(command);
    8300           0 :                 if (ret != 0) {
    8301           0 :                         if (fd != -1) {
    8302           0 :                                 close(fd);
    8303             :                         }
    8304           0 :                         return WERR_ACCESS_DENIED;
    8305             :                 }
    8306             : 
    8307           0 :                 numlines = 0;
    8308           0 :                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
    8309           0 :                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
    8310           0 :                 close(fd);
    8311             :         }
    8312             : 
    8313          24 :         *count = numlines;
    8314          24 :         *lines = qlines;
    8315             : 
    8316          24 :         return WERR_OK;
    8317             : }
    8318             : 
    8319             : /****************************************************************************
    8320             :  enumports level 1.
    8321             : ****************************************************************************/
    8322             : 
    8323           8 : static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
    8324             :                                 union spoolss_PortInfo **info_p,
    8325             :                                 uint32_t *count)
    8326             : {
    8327           8 :         union spoolss_PortInfo *info = NULL;
    8328           8 :         int i=0;
    8329           8 :         WERROR result = WERR_OK;
    8330           8 :         char **qlines = NULL;
    8331           8 :         int numlines = 0;
    8332             : 
    8333           8 :         result = enumports_hook(talloc_tos(), &numlines, &qlines );
    8334           8 :         if (!W_ERROR_IS_OK(result)) {
    8335           0 :                 goto out;
    8336             :         }
    8337             : 
    8338           8 :         if (numlines) {
    8339           8 :                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
    8340           8 :                 if (!info) {
    8341           0 :                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
    8342           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    8343           0 :                         goto out;
    8344             :                 }
    8345             : 
    8346          16 :                 for (i=0; i<numlines; i++) {
    8347           8 :                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
    8348           8 :                         result = fill_port_1(info, &info[i].info1, qlines[i]);
    8349           8 :                         if (!W_ERROR_IS_OK(result)) {
    8350           0 :                                 goto out;
    8351             :                         }
    8352             :                 }
    8353             :         }
    8354           8 :         TALLOC_FREE(qlines);
    8355             : 
    8356           0 : out:
    8357           8 :         if (!W_ERROR_IS_OK(result)) {
    8358           0 :                 TALLOC_FREE(info);
    8359           0 :                 TALLOC_FREE(qlines);
    8360           0 :                 *count = 0;
    8361           0 :                 *info_p = NULL;
    8362           0 :                 return result;
    8363             :         }
    8364             : 
    8365           8 :         *info_p = info;
    8366           8 :         *count = numlines;
    8367             : 
    8368           8 :         return WERR_OK;
    8369             : }
    8370             : 
    8371             : /****************************************************************************
    8372             :  enumports level 2.
    8373             : ****************************************************************************/
    8374             : 
    8375          16 : static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
    8376             :                                 union spoolss_PortInfo **info_p,
    8377             :                                 uint32_t *count)
    8378             : {
    8379          16 :         union spoolss_PortInfo *info = NULL;
    8380          16 :         int i=0;
    8381          16 :         WERROR result = WERR_OK;
    8382          16 :         char **qlines = NULL;
    8383          16 :         int numlines = 0;
    8384             : 
    8385          16 :         result = enumports_hook(talloc_tos(), &numlines, &qlines );
    8386          16 :         if (!W_ERROR_IS_OK(result)) {
    8387           0 :                 goto out;
    8388             :         }
    8389             : 
    8390          16 :         if (numlines) {
    8391          16 :                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
    8392          16 :                 if (!info) {
    8393           0 :                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
    8394           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    8395           0 :                         goto out;
    8396             :                 }
    8397             : 
    8398          32 :                 for (i=0; i<numlines; i++) {
    8399          16 :                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
    8400          16 :                         result = fill_port_2(info, &info[i].info2, qlines[i]);
    8401          16 :                         if (!W_ERROR_IS_OK(result)) {
    8402           0 :                                 goto out;
    8403             :                         }
    8404             :                 }
    8405             :         }
    8406          16 :         TALLOC_FREE(qlines);
    8407             : 
    8408           0 : out:
    8409          16 :         if (!W_ERROR_IS_OK(result)) {
    8410           0 :                 TALLOC_FREE(info);
    8411           0 :                 TALLOC_FREE(qlines);
    8412           0 :                 *count = 0;
    8413           0 :                 *info_p = NULL;
    8414           0 :                 return result;
    8415             :         }
    8416             : 
    8417          16 :         *info_p = info;
    8418          16 :         *count = numlines;
    8419             : 
    8420          16 :         return WERR_OK;
    8421             : }
    8422             : 
    8423             : /****************************************************************
    8424             :  _spoolss_EnumPorts
    8425             : ****************************************************************/
    8426             : 
    8427          24 : WERROR _spoolss_EnumPorts(struct pipes_struct *p,
    8428             :                           struct spoolss_EnumPorts *r)
    8429             : {
    8430           0 :         WERROR result;
    8431             : 
    8432             :         /* that's an [in out] buffer */
    8433             : 
    8434          24 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8435           0 :                 return WERR_INVALID_PARAMETER;
    8436             :         }
    8437             : 
    8438          24 :         DEBUG(4,("_spoolss_EnumPorts\n"));
    8439             : 
    8440          24 :         *r->out.count = 0;
    8441          24 :         *r->out.needed = 0;
    8442          24 :         *r->out.info = NULL;
    8443             : 
    8444          24 :         switch (r->in.level) {
    8445           8 :         case 1:
    8446           8 :                 result = enumports_level_1(p->mem_ctx, r->out.info,
    8447             :                                            r->out.count);
    8448           8 :                 break;
    8449          16 :         case 2:
    8450          16 :                 result = enumports_level_2(p->mem_ctx, r->out.info,
    8451             :                                            r->out.count);
    8452          16 :                 break;
    8453           0 :         default:
    8454           0 :                 return WERR_INVALID_LEVEL;
    8455             :         }
    8456             : 
    8457          24 :         if (!W_ERROR_IS_OK(result)) {
    8458           0 :                 return result;
    8459             :         }
    8460             : 
    8461          24 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8462             :                                                      spoolss_EnumPorts,
    8463             :                                                      *r->out.info, r->in.level,
    8464             :                                                      *r->out.count);
    8465          24 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8466          24 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8467             : 
    8468          24 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8469             : }
    8470             : 
    8471             : /****************************************************************************
    8472             : ****************************************************************************/
    8473             : 
    8474          96 : static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
    8475             :                                            const char *server,
    8476             :                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
    8477             :                                            struct spoolss_DeviceMode *devmode,
    8478             :                                            struct security_descriptor *secdesc,
    8479             :                                            struct spoolss_UserLevelCtr *user_ctr,
    8480             :                                            struct policy_handle *handle)
    8481             : {
    8482          96 :         struct dcesrv_call_state *dce_call = p->dce_call;
    8483          96 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    8484           0 :         const struct tsocket_address *remote_address =
    8485          96 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    8486           0 :         struct auth_session_info *session_info =
    8487          96 :                 dcesrv_call_session_info(dce_call);
    8488          96 :         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
    8489          96 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
    8490           0 :         const struct loadparm_substitution *lp_sub =
    8491          96 :                 loadparm_s3_global_substitution();
    8492           0 :         int     snum;
    8493          96 :         WERROR err = WERR_OK;
    8494             : 
    8495             :         /* samba does not have a concept of local, non-shared printers yet, so
    8496             :          * make sure we always setup sharename - gd */
    8497          96 :         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
    8498          96 :             (info2->printername != NULL && info2->printername[0] != '\0')) {
    8499          80 :                 DEBUG(5, ("spoolss_addprinterex_level_2: "
    8500             :                         "no sharename has been set, setting printername %s as sharename\n",
    8501             :                         info2->printername));
    8502          80 :                 info2->sharename = info2->printername;
    8503             :         }
    8504             : 
    8505             :         /* check to see if the printer already exists */
    8506          96 :         if ((snum = print_queue_snum(info2->sharename)) != -1) {
    8507          16 :                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
    8508             :                         info2->sharename));
    8509          16 :                 return WERR_PRINTER_ALREADY_EXISTS;
    8510             :         }
    8511             : 
    8512          80 :         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
    8513          80 :                 if ((snum = print_queue_snum(info2->printername)) != -1) {
    8514           0 :                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
    8515             :                                 info2->printername));
    8516           0 :                         return WERR_PRINTER_ALREADY_EXISTS;
    8517             :                 }
    8518             :         }
    8519             : 
    8520             :         /* validate printer info struct */
    8521          80 :         if (!info2->printername || strlen(info2->printername) == 0) {
    8522          16 :                 return WERR_INVALID_PRINTER_NAME;
    8523             :         }
    8524          64 :         if (!info2->portname || strlen(info2->portname) == 0) {
    8525          16 :                 return WERR_UNKNOWN_PORT;
    8526             :         }
    8527          48 :         if (!info2->drivername || strlen(info2->drivername) == 0) {
    8528          16 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    8529             :         }
    8530          32 :         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
    8531          16 :                 return WERR_UNKNOWN_PRINTPROCESSOR;
    8532             :         }
    8533             : 
    8534             :         /* FIXME!!!  smbd should check to see if the driver is installed before
    8535             :            trying to add a printer like this  --jerry */
    8536             : 
    8537          16 :         if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
    8538           0 :                 char *raddr;
    8539             : 
    8540          16 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    8541             :                                                          p->mem_ctx);
    8542          16 :                 if (raddr == NULL) {
    8543           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8544             :                 }
    8545             : 
    8546          16 :                 if ( !add_printer_hook(p->mem_ctx, session_info->security_token,
    8547             :                                        info2, raddr,
    8548             :                                        p->msg_ctx) ) {
    8549           0 :                         return WERR_ACCESS_DENIED;
    8550             :                 }
    8551             :         } else {
    8552           0 :                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
    8553             :                         "smb.conf parameter \"addprinter command\" is defined. This "
    8554             :                         "parameter must exist for this call to succeed\n",
    8555             :                         info2->sharename ));
    8556             :         }
    8557             : 
    8558          16 :         if ((snum = print_queue_snum(info2->sharename)) == -1) {
    8559           0 :                 return WERR_ACCESS_DENIED;
    8560             :         }
    8561             : 
    8562             :         /* you must be a printer admin to add a new printer */
    8563          16 :         if (!W_ERROR_IS_OK(print_access_check(session_info,
    8564             :                                               p->msg_ctx,
    8565             :                                               snum,
    8566             :                                               PRINTER_ACCESS_ADMINISTER))) {
    8567           0 :                 return WERR_ACCESS_DENIED;
    8568             :         }
    8569             : 
    8570             :         /*
    8571             :          * Do sanity check on the requested changes for Samba.
    8572             :          */
    8573             : 
    8574          16 :         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
    8575           0 :                 return WERR_INVALID_PARAMETER;
    8576             :         }
    8577             : 
    8578          16 :         if (devmode == NULL) {
    8579          16 :                 info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
    8580             :         }
    8581             : 
    8582          16 :         err = update_dsspooler(p->mem_ctx,
    8583             :                                get_session_info_system(),
    8584             :                                p->msg_ctx,
    8585             :                                0,
    8586             :                                info2,
    8587             :                                NULL);
    8588          16 :         if (!W_ERROR_IS_OK(err)) {
    8589           0 :                 return err;
    8590             :         }
    8591             : 
    8592          16 :         err = winreg_update_printer_internal(p->mem_ctx,
    8593             :                                     get_session_info_system(),
    8594             :                                     p->msg_ctx,
    8595             :                                     info2->sharename,
    8596             :                                     info2_mask,
    8597             :                                     info2,
    8598             :                                     devmode,
    8599             :                                     secdesc);
    8600          16 :         if (!W_ERROR_IS_OK(err)) {
    8601           0 :                 return err;
    8602             :         }
    8603             : 
    8604          16 :         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
    8605          16 :         if (!W_ERROR_IS_OK(err)) {
    8606             :                 /* Handle open failed - remove addition. */
    8607           0 :                 ZERO_STRUCTP(handle);
    8608           0 :                 return err;
    8609             :         }
    8610             : 
    8611          16 :         return WERR_OK;
    8612             : }
    8613             : 
    8614             : /****************************************************************
    8615             :  _spoolss_AddPrinterEx
    8616             : ****************************************************************/
    8617             : 
    8618          96 : WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
    8619             :                              struct spoolss_AddPrinterEx *r)
    8620             : {
    8621          96 :         switch (r->in.info_ctr->level) {
    8622           0 :         case 1:
    8623             :                 /* we don't handle yet */
    8624             :                 /* but I know what to do ... */
    8625           0 :                 return WERR_INVALID_LEVEL;
    8626          96 :         case 2:
    8627          96 :                 return spoolss_addprinterex_level_2(p, r->in.server,
    8628             :                                                     r->in.info_ctr,
    8629          96 :                                                     r->in.devmode_ctr->devmode,
    8630          96 :                                                     r->in.secdesc_ctr->sd,
    8631             :                                                     r->in.userlevel_ctr,
    8632             :                                                     r->out.handle);
    8633           0 :         default:
    8634           0 :                 return WERR_INVALID_LEVEL;
    8635             :         }
    8636             : }
    8637             : 
    8638             : /****************************************************************
    8639             :  _spoolss_AddPrinter
    8640             : ****************************************************************/
    8641             : 
    8642          72 : WERROR _spoolss_AddPrinter(struct pipes_struct *p,
    8643             :                            struct spoolss_AddPrinter *r)
    8644             : {
    8645           0 :         struct spoolss_AddPrinterEx a;
    8646           0 :         struct spoolss_UserLevelCtr userlevel_ctr;
    8647             : 
    8648          72 :         ZERO_STRUCT(userlevel_ctr);
    8649             : 
    8650          72 :         userlevel_ctr.level = 1;
    8651             : 
    8652          72 :         a.in.server             = r->in.server;
    8653          72 :         a.in.info_ctr           = r->in.info_ctr;
    8654          72 :         a.in.devmode_ctr        = r->in.devmode_ctr;
    8655          72 :         a.in.secdesc_ctr        = r->in.secdesc_ctr;
    8656          72 :         a.in.userlevel_ctr      = &userlevel_ctr;
    8657          72 :         a.out.handle            = r->out.handle;
    8658             : 
    8659          72 :         return _spoolss_AddPrinterEx(p, &a);
    8660             : }
    8661             : 
    8662             : /****************************************************************
    8663             :  _spoolss_AddPrinterDriverEx
    8664             : ****************************************************************/
    8665             : 
    8666           0 : WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
    8667             :                                    struct spoolss_AddPrinterDriverEx *r)
    8668             : {
    8669           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    8670           0 :         struct auth_session_info *session_info =
    8671           0 :                 dcesrv_call_session_info(dce_call);
    8672           0 :         WERROR err = WERR_OK;
    8673           0 :         const char *driver_name = NULL;
    8674           0 :         const char *driver_directory = NULL;
    8675           0 :         uint32_t version;
    8676             : 
    8677             :         /*
    8678             :          * we only support the semantics of AddPrinterDriver()
    8679             :          * i.e. only copy files that are newer than existing ones
    8680             :          */
    8681             : 
    8682           0 :         if (r->in.flags == 0) {
    8683           0 :                 return WERR_INVALID_PARAMETER;
    8684             :         }
    8685             : 
    8686           0 :         if (!(r->in.flags & APD_COPY_ALL_FILES) &&
    8687           0 :             !(r->in.flags & APD_COPY_NEW_FILES)) {
    8688           0 :                 return WERR_ACCESS_DENIED;
    8689             :         }
    8690             : 
    8691             :         /* FIXME */
    8692           0 :         if (r->in.info_ctr->level != 3 &&
    8693           0 :             r->in.info_ctr->level != 6 &&
    8694           0 :             r->in.info_ctr->level != 8) {
    8695           0 :                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
    8696             :                         r->in.info_ctr->level));
    8697           0 :                 return WERR_INVALID_LEVEL;
    8698             :         }
    8699             : 
    8700           0 :         DEBUG(5,("Cleaning driver's information\n"));
    8701           0 :         err = clean_up_driver_struct(p->mem_ctx,
    8702             :                                      session_info,
    8703           0 :                                      r->in.info_ctr,
    8704             :                                      r->in.flags,
    8705             :                                      &driver_directory);
    8706           0 :         if (!W_ERROR_IS_OK(err)) {
    8707           0 :                 DBG_ERR("clean_up_driver_struct failed - %s\n",
    8708             :                         win_errstr(err));
    8709           0 :                 goto done;
    8710             :         }
    8711             : 
    8712           0 :         DEBUG(5,("Moving driver to final destination\n"));
    8713           0 :         err = move_driver_to_download_area(session_info,
    8714           0 :                                            r->in.info_ctr,
    8715             :                                            driver_directory);
    8716           0 :         if (!W_ERROR_IS_OK(err)) {
    8717           0 :                 DBG_ERR("move_driver_to_download_area failed - %s\n",
    8718             :                         win_errstr(err));
    8719           0 :                 goto done;
    8720             :         }
    8721             : 
    8722           0 :         err = winreg_add_driver_internal(p->mem_ctx,
    8723             :                                 get_session_info_system(),
    8724             :                                 p->msg_ctx,
    8725             :                                 r->in.info_ctr,
    8726             :                                 &driver_name,
    8727             :                                 &version);
    8728           0 :         if (!W_ERROR_IS_OK(err)) {
    8729           0 :                 DBG_ERR("winreg_add_driver_internal failed - %s\n",
    8730             :                         win_errstr(err));
    8731           0 :                 goto done;
    8732             :         }
    8733             : 
    8734             :         /*
    8735             :          * I think this is where the DrvUpgradePrinter() hook would be
    8736             :          * be called in a driver's interface DLL on a Windows NT 4.0/2k
    8737             :          * server.  Right now, we just need to send ourselves a message
    8738             :          * to update each printer bound to this driver.   --jerry
    8739             :          */
    8740             : 
    8741           0 :         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
    8742           0 :                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
    8743             :                         __func__, driver_name));
    8744             :         }
    8745             : 
    8746           0 : done:
    8747           0 :         return err;
    8748             : }
    8749             : 
    8750             : /****************************************************************
    8751             :  _spoolss_AddPrinterDriver
    8752             : ****************************************************************/
    8753             : 
    8754           0 : WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
    8755             :                                  struct spoolss_AddPrinterDriver *r)
    8756             : {
    8757           0 :         struct spoolss_AddPrinterDriverEx a;
    8758             : 
    8759           0 :         switch (r->in.info_ctr->level) {
    8760           0 :         case 2:
    8761             :         case 3:
    8762             :         case 4:
    8763             :         case 5:
    8764           0 :                 break;
    8765           0 :         default:
    8766           0 :                 return WERR_INVALID_LEVEL;
    8767             :         }
    8768             : 
    8769           0 :         a.in.servername         = r->in.servername;
    8770           0 :         a.in.info_ctr           = r->in.info_ctr;
    8771           0 :         a.in.flags              = APD_COPY_NEW_FILES;
    8772             : 
    8773           0 :         return _spoolss_AddPrinterDriverEx(p, &a);
    8774             : }
    8775             : 
    8776             : /****************************************************************************
    8777             : ****************************************************************************/
    8778             : 
    8779             : struct _spoolss_paths {
    8780             :         int type;
    8781             :         const char *share;
    8782             :         const char *dir;
    8783             : };
    8784             : 
    8785             : enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
    8786             : 
    8787             : static const struct _spoolss_paths spoolss_paths[]= {
    8788             :         { SPOOLSS_DRIVER_PATH,          "print$",     "DRIVERS" },
    8789             :         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",   "PRTPROCS" }
    8790             : };
    8791             : 
    8792         208 : static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
    8793             :                                           const char *servername,
    8794             :                                           const char *environment,
    8795             :                                           int component,
    8796             :                                           char **path)
    8797             : {
    8798         208 :         const char *pservername = NULL;
    8799           0 :         const char *long_archi;
    8800           0 :         const char *short_archi;
    8801             : 
    8802         208 :         *path = NULL;
    8803             : 
    8804             :         /* environment may be empty */
    8805         208 :         if (environment && strlen(environment)) {
    8806         208 :                 long_archi = environment;
    8807             :         } else {
    8808           0 :                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    8809             :                                                   "spoolss", "architecture",
    8810             :                                                   GLOBAL_SPOOLSS_ARCHITECTURE);
    8811             :         }
    8812             : 
    8813             :         /* servername may be empty */
    8814         208 :         if (servername && strlen(servername)) {
    8815         144 :                 pservername = canon_servername(servername);
    8816             : 
    8817         144 :                 if (!is_myname_or_ipaddr(pservername)) {
    8818           0 :                         return WERR_INVALID_PARAMETER;
    8819             :                 }
    8820             :         }
    8821             : 
    8822         208 :         if (!(short_archi = get_short_archi(long_archi))) {
    8823           0 :                 return WERR_INVALID_ENVIRONMENT;
    8824             :         }
    8825             : 
    8826         208 :         switch (component) {
    8827         208 :         case SPOOLSS_PRTPROCS_PATH:
    8828             :         case SPOOLSS_DRIVER_PATH:
    8829         208 :                 if (pservername) {
    8830         144 :                         *path = talloc_asprintf(mem_ctx,
    8831             :                                         "\\\\%s\\%s\\%s",
    8832             :                                         pservername,
    8833         144 :                                         spoolss_paths[component].share,
    8834             :                                         short_archi);
    8835             :                 } else {
    8836          64 :                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
    8837             :                                         SPOOLSS_DEFAULT_SERVER_PATH,
    8838          64 :                                         spoolss_paths[component].dir,
    8839             :                                         short_archi);
    8840             :                 }
    8841         208 :                 break;
    8842           0 :         default:
    8843           0 :                 return WERR_INVALID_PARAMETER;
    8844             :         }
    8845             : 
    8846         208 :         if (!*path) {
    8847           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    8848             :         }
    8849             : 
    8850         208 :         return WERR_OK;
    8851             : }
    8852             : 
    8853             : /****************************************************************************
    8854             : ****************************************************************************/
    8855             : 
    8856         168 : static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
    8857             :                                           const char *servername,
    8858             :                                           const char *environment,
    8859             :                                           struct spoolss_DriverDirectoryInfo1 *r)
    8860             : {
    8861           0 :         WERROR werr;
    8862         168 :         char *path = NULL;
    8863             : 
    8864         168 :         werr = compose_spoolss_server_path(mem_ctx,
    8865             :                                            servername,
    8866             :                                            environment,
    8867             :                                            SPOOLSS_DRIVER_PATH,
    8868             :                                            &path);
    8869         168 :         if (!W_ERROR_IS_OK(werr)) {
    8870           0 :                 return werr;
    8871             :         }
    8872             : 
    8873         168 :         DEBUG(4,("printer driver directory: [%s]\n", path));
    8874             : 
    8875         168 :         r->directory_name = path;
    8876             : 
    8877         168 :         return WERR_OK;
    8878             : }
    8879             : 
    8880             : /****************************************************************
    8881             :  _spoolss_GetPrinterDriverDirectory
    8882             : ****************************************************************/
    8883             : 
    8884         168 : WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
    8885             :                                           struct spoolss_GetPrinterDriverDirectory *r)
    8886             : {
    8887           0 :         WERROR werror;
    8888             : 
    8889             :         /* that's an [in out] buffer */
    8890             : 
    8891         168 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8892           0 :                 TALLOC_FREE(r->out.info);
    8893           0 :                 return WERR_INVALID_PARAMETER;
    8894             :         }
    8895             : 
    8896         168 :         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
    8897             :                 r->in.level));
    8898             : 
    8899         168 :         *r->out.needed = 0;
    8900             : 
    8901             :         /* r->in.level is ignored */
    8902             : 
    8903         168 :         werror = getprinterdriverdir_level_1(p->mem_ctx,
    8904             :                                              r->in.server,
    8905             :                                              r->in.environment,
    8906         168 :                                              &r->out.info->info1);
    8907         168 :         if (!W_ERROR_IS_OK(werror)) {
    8908           0 :                 TALLOC_FREE(r->out.info);
    8909           0 :                 return werror;
    8910             :         }
    8911             : 
    8912         168 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
    8913             :                                                r->out.info, r->in.level);
    8914         168 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    8915             : 
    8916         168 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8917             : }
    8918             : 
    8919             : /****************************************************************
    8920             :  _spoolss_EnumPrinterData
    8921             : ****************************************************************/
    8922             : 
    8923         152 : WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
    8924             :                                 struct spoolss_EnumPrinterData *r)
    8925             : {
    8926           0 :         WERROR result;
    8927           0 :         struct spoolss_EnumPrinterDataEx r2;
    8928           0 :         uint32_t count;
    8929         152 :         struct spoolss_PrinterEnumValues *info, *val = NULL;
    8930           0 :         uint32_t needed;
    8931             : 
    8932         152 :         r2.in.handle    = r->in.handle;
    8933         152 :         r2.in.key_name  = "PrinterDriverData";
    8934         152 :         r2.in.offered   = 0;
    8935         152 :         r2.out.count    = &count;
    8936         152 :         r2.out.info     = &info;
    8937         152 :         r2.out.needed   = &needed;
    8938             : 
    8939         152 :         result = _spoolss_EnumPrinterDataEx(p, &r2);
    8940         152 :         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
    8941         112 :                 r2.in.offered = needed;
    8942         112 :                 result = _spoolss_EnumPrinterDataEx(p, &r2);
    8943             :         }
    8944         152 :         if (!W_ERROR_IS_OK(result)) {
    8945           0 :                 return result;
    8946             :         }
    8947             : 
    8948             :         /*
    8949             :          * The NT machine wants to know the biggest size of value and data
    8950             :          *
    8951             :          * cf: MSDN EnumPrinterData remark section
    8952             :          */
    8953             : 
    8954         152 :         if (!r->in.value_offered && !r->in.data_offered) {
    8955          48 :                 uint32_t biggest_valuesize = 0;
    8956          48 :                 uint32_t biggest_datasize = 0;
    8957           0 :                 int i, name_length;
    8958             : 
    8959          48 :                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
    8960             : 
    8961         132 :                 for (i=0; i<count; i++) {
    8962             : 
    8963          84 :                         name_length = strlen(info[i].value_name);
    8964          84 :                         if (strlen(info[i].value_name) > biggest_valuesize) {
    8965          28 :                                 biggest_valuesize = name_length;
    8966             :                         }
    8967             : 
    8968          84 :                         if (info[i].data_length > biggest_datasize) {
    8969          28 :                                 biggest_datasize = info[i].data_length;
    8970             :                         }
    8971             : 
    8972          84 :                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
    8973             :                                 biggest_datasize));
    8974             :                 }
    8975             : 
    8976             :                 /* the value is an UNICODE string but real_value_size is the length
    8977             :                    in bytes including the trailing 0 */
    8978             : 
    8979          48 :                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
    8980          48 :                 *r->out.data_needed  = biggest_datasize;
    8981             : 
    8982          48 :                 DEBUG(6,("final values: [%d], [%d]\n",
    8983             :                         *r->out.value_needed, *r->out.data_needed));
    8984             : 
    8985          48 :                 return WERR_OK;
    8986             :         }
    8987             : 
    8988         104 :         if (r->in.enum_index < count) {
    8989          84 :                 val = &info[r->in.enum_index];
    8990             :         }
    8991             : 
    8992         104 :         if (val == NULL) {
    8993             :                 /* out_value should default to "" or else NT4 has
    8994             :                    problems unmarshalling the response */
    8995             : 
    8996          20 :                 if (r->in.value_offered) {
    8997          20 :                         *r->out.value_needed = 1;
    8998          20 :                         r->out.value_name = talloc_strdup(r, "");
    8999          20 :                         if (!r->out.value_name) {
    9000           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    9001             :                         }
    9002             :                 } else {
    9003           0 :                         r->out.value_name = NULL;
    9004           0 :                         *r->out.value_needed = 0;
    9005             :                 }
    9006             : 
    9007             :                 /* the data is counted in bytes */
    9008             : 
    9009          20 :                 *r->out.data_needed = r->in.data_offered;
    9010             : 
    9011          20 :                 result = WERR_NO_MORE_ITEMS;
    9012             :         } else {
    9013             :                 /*
    9014             :                  * the value is:
    9015             :                  * - counted in bytes in the request
    9016             :                  * - counted in UNICODE chars in the max reply
    9017             :                  * - counted in bytes in the real size
    9018             :                  *
    9019             :                  * take a pause *before* coding not *during* coding
    9020             :                  */
    9021             : 
    9022             :                 /* name */
    9023          84 :                 if (r->in.value_offered) {
    9024          84 :                         r->out.value_name = talloc_strdup(r, val->value_name);
    9025          84 :                         if (!r->out.value_name) {
    9026           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    9027             :                         }
    9028          84 :                         *r->out.value_needed = val->value_name_len;
    9029             :                 } else {
    9030           0 :                         r->out.value_name = NULL;
    9031           0 :                         *r->out.value_needed = 0;
    9032             :                 }
    9033             : 
    9034             :                 /* type */
    9035             : 
    9036          84 :                 *r->out.type = val->type;
    9037             : 
    9038             :                 /* data - counted in bytes */
    9039             : 
    9040             :                 /*
    9041             :                  * See the section "Dynamically Typed Query Parameters"
    9042             :                  * in MS-RPRN.
    9043             :                  */
    9044             : 
    9045          84 :                 if (r->out.data && val->data && val->data->data &&
    9046          84 :                                 val->data_length && r->in.data_offered) {
    9047          84 :                         memcpy(r->out.data, val->data->data,
    9048          84 :                                 MIN(val->data_length,r->in.data_offered));
    9049             :                 }
    9050             : 
    9051          84 :                 *r->out.data_needed = val->data_length;
    9052             : 
    9053          84 :                 result = WERR_OK;
    9054             :         }
    9055             : 
    9056         104 :         return result;
    9057             : }
    9058             : 
    9059             : /****************************************************************
    9060             :  _spoolss_SetPrinterData
    9061             : ****************************************************************/
    9062             : 
    9063         168 : WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
    9064             :                                struct spoolss_SetPrinterData *r)
    9065             : {
    9066           0 :         struct spoolss_SetPrinterDataEx r2;
    9067             : 
    9068         168 :         r2.in.handle            = r->in.handle;
    9069         168 :         r2.in.key_name          = "PrinterDriverData";
    9070         168 :         r2.in.value_name        = r->in.value_name;
    9071         168 :         r2.in.type              = r->in.type;
    9072         168 :         r2.in.data              = r->in.data;
    9073         168 :         r2.in.offered           = r->in.offered;
    9074             : 
    9075         168 :         return _spoolss_SetPrinterDataEx(p, &r2);
    9076             : }
    9077             : 
    9078             : /****************************************************************
    9079             :  _spoolss_ResetPrinter
    9080             : ****************************************************************/
    9081             : 
    9082           0 : WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
    9083             :                              struct spoolss_ResetPrinter *r)
    9084             : {
    9085           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9086           0 :         int             snum;
    9087             : 
    9088           0 :         DEBUG(5,("_spoolss_ResetPrinter\n"));
    9089             : 
    9090             :         /*
    9091             :          * All we do is to check to see if the handle and queue is valid.
    9092             :          * This call really doesn't mean anything to us because we only
    9093             :          * support RAW printing.   --jerry
    9094             :          */
    9095             : 
    9096           0 :         if (!Printer) {
    9097           0 :                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
    9098             :                         OUR_HANDLE(r->in.handle)));
    9099           0 :                 return WERR_INVALID_HANDLE;
    9100             :         }
    9101             : 
    9102           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    9103           0 :                 return WERR_INVALID_HANDLE;
    9104             : 
    9105             : 
    9106             :         /* blindly return success */
    9107           0 :         return WERR_OK;
    9108             : }
    9109             : 
    9110             : /****************************************************************
    9111             :  _spoolss_DeletePrinterData
    9112             : ****************************************************************/
    9113             : 
    9114         168 : WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
    9115             :                                   struct spoolss_DeletePrinterData *r)
    9116             : {
    9117           0 :         struct spoolss_DeletePrinterDataEx r2;
    9118             : 
    9119         168 :         r2.in.handle            = r->in.handle;
    9120         168 :         r2.in.key_name          = "PrinterDriverData";
    9121         168 :         r2.in.value_name        = r->in.value_name;
    9122             : 
    9123         168 :         return _spoolss_DeletePrinterDataEx(p, &r2);
    9124             : }
    9125             : 
    9126             : /****************************************************************
    9127             :  _spoolss_AddForm
    9128             : ****************************************************************/
    9129             : 
    9130         576 : WERROR _spoolss_AddForm(struct pipes_struct *p,
    9131             :                         struct spoolss_AddForm *r)
    9132             : {
    9133         576 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9134           0 :         struct auth_session_info *session_info =
    9135         576 :                 dcesrv_call_session_info(dce_call);
    9136           0 :         struct spoolss_AddFormInfo1 *form;
    9137         576 :         int snum = -1;
    9138         576 :         WERROR status = WERR_OK;
    9139         576 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9140           0 :         struct dcerpc_binding_handle *b;
    9141         576 :         TALLOC_CTX *tmp_ctx = NULL;
    9142             : 
    9143         576 :         DEBUG(5,("_spoolss_AddForm\n"));
    9144             : 
    9145         576 :         if (!Printer) {
    9146           0 :                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
    9147             :                         OUR_HANDLE(r->in.handle)));
    9148           0 :                 return WERR_INVALID_HANDLE;
    9149             :         }
    9150             : 
    9151             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    9152             :            and not a printer admin, then fail */
    9153             : 
    9154         576 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9155           0 :             !security_token_has_privilege(session_info->security_token,
    9156             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    9157           0 :                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
    9158           0 :                 return WERR_ACCESS_DENIED;
    9159             :         }
    9160             : 
    9161         576 :         if (r->in.info_ctr->level != 1) {
    9162           0 :                 return WERR_INVALID_LEVEL;
    9163             :         }
    9164             : 
    9165         576 :         form = r->in.info_ctr->info.info1;
    9166         576 :         if (!form) {
    9167           0 :                 return WERR_INVALID_PARAMETER;
    9168             :         }
    9169             : 
    9170         576 :         switch (form->flags) {
    9171         480 :         case SPOOLSS_FORM_USER:
    9172             :         case SPOOLSS_FORM_BUILTIN:
    9173             :         case SPOOLSS_FORM_PRINTER:
    9174         480 :                 break;
    9175          96 :         default:
    9176          96 :                 return WERR_INVALID_PARAMETER;
    9177             :         }
    9178             : 
    9179         480 :         tmp_ctx = talloc_new(p->mem_ctx);
    9180         480 :         if (!tmp_ctx) {
    9181           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9182             :         }
    9183             : 
    9184         480 :         status = winreg_printer_binding_handle(tmp_ctx,
    9185             :                                                get_session_info_system(),
    9186             :                                                p->msg_ctx,
    9187             :                                                &b);
    9188         480 :         if (!W_ERROR_IS_OK(status)) {
    9189           0 :                 goto done;
    9190             :         }
    9191             : 
    9192         480 :         status = winreg_printer_addform1(tmp_ctx, b, form);
    9193         480 :         if (!W_ERROR_IS_OK(status)) {
    9194         384 :                 goto done;
    9195             :         }
    9196             : 
    9197             :         /*
    9198             :          * ChangeID must always be set if this is a printer
    9199             :          */
    9200          96 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9201          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9202           0 :                         status = WERR_INVALID_HANDLE;
    9203           0 :                         goto done;
    9204             :                 }
    9205             : 
    9206          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9207             :                                                         lp_const_servicename(snum));
    9208             :         }
    9209             : 
    9210          16 : done:
    9211         480 :         talloc_free(tmp_ctx);
    9212         480 :         return status;
    9213             : }
    9214             : 
    9215             : /****************************************************************
    9216             :  _spoolss_DeleteForm
    9217             : ****************************************************************/
    9218             : 
    9219         384 : WERROR _spoolss_DeleteForm(struct pipes_struct *p,
    9220             :                            struct spoolss_DeleteForm *r)
    9221             : {
    9222         384 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9223           0 :         struct auth_session_info *session_info =
    9224         384 :                 dcesrv_call_session_info(dce_call);
    9225         384 :         const char *form_name = r->in.form_name;
    9226         384 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9227         384 :         int snum = -1;
    9228         384 :         WERROR status = WERR_OK;
    9229           0 :         struct dcerpc_binding_handle *b;
    9230         384 :         TALLOC_CTX *tmp_ctx = NULL;
    9231             : 
    9232         384 :         DEBUG(5,("_spoolss_DeleteForm\n"));
    9233             : 
    9234         384 :         if (!Printer) {
    9235           0 :                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
    9236             :                         OUR_HANDLE(r->in.handle)));
    9237           0 :                 return WERR_INVALID_HANDLE;
    9238             :         }
    9239             : 
    9240         384 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9241           0 :             !security_token_has_privilege(session_info->security_token,
    9242             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    9243           0 :                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
    9244           0 :                 return WERR_ACCESS_DENIED;
    9245             :         }
    9246             : 
    9247         384 :         tmp_ctx = talloc_new(p->mem_ctx);
    9248         384 :         if (!tmp_ctx) {
    9249           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9250             :         }
    9251             : 
    9252         384 :         status = winreg_printer_binding_handle(tmp_ctx,
    9253             :                                                get_session_info_system(),
    9254             :                                                p->msg_ctx,
    9255             :                                                &b);
    9256         384 :         if (!W_ERROR_IS_OK(status)) {
    9257           0 :                 goto done;
    9258             :         }
    9259             : 
    9260         384 :         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
    9261         384 :         if (!W_ERROR_IS_OK(status)) {
    9262         288 :                 goto done;
    9263             :         }
    9264             : 
    9265             :         /*
    9266             :          * ChangeID must always be set if this is a printer
    9267             :          */
    9268          96 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9269          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9270           0 :                         status = WERR_INVALID_HANDLE;
    9271           0 :                         goto done;
    9272             :                 }
    9273             : 
    9274          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9275             :                                                         lp_const_servicename(snum));
    9276             :         }
    9277             : 
    9278          16 : done:
    9279         384 :         talloc_free(tmp_ctx);
    9280         384 :         return status;
    9281             : }
    9282             : 
    9283             : /****************************************************************
    9284             :  _spoolss_SetForm
    9285             : ****************************************************************/
    9286             : 
    9287          80 : WERROR _spoolss_SetForm(struct pipes_struct *p,
    9288             :                         struct spoolss_SetForm *r)
    9289             : {
    9290          80 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9291           0 :         struct auth_session_info *session_info =
    9292          80 :                 dcesrv_call_session_info(dce_call);
    9293           0 :         struct spoolss_AddFormInfo1 *form;
    9294          80 :         const char *form_name = r->in.form_name;
    9295          80 :         int snum = -1;
    9296          80 :         WERROR status = WERR_OK;
    9297           0 :         struct dcerpc_binding_handle *b;
    9298          80 :         TALLOC_CTX *tmp_ctx = NULL;
    9299             : 
    9300          80 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9301             : 
    9302          80 :         DEBUG(5,("_spoolss_SetForm\n"));
    9303             : 
    9304          80 :         if (!Printer) {
    9305           0 :                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
    9306             :                         OUR_HANDLE(r->in.handle)));
    9307           0 :                 return WERR_INVALID_HANDLE;
    9308             :         }
    9309             : 
    9310             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    9311             :            and not a printer admin, then fail */
    9312             : 
    9313          80 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9314           0 :              !security_token_has_privilege(session_info->security_token,
    9315             :                                            SEC_PRIV_PRINT_OPERATOR)) {
    9316           0 :                 DEBUG(2,("_spoolss_SetForm: denied by insufficient permissions.\n"));
    9317           0 :                 return WERR_ACCESS_DENIED;
    9318             :         }
    9319             : 
    9320          80 :         if (r->in.info_ctr->level != 1) {
    9321           0 :                 return WERR_INVALID_LEVEL;
    9322             :         }
    9323             : 
    9324          80 :         form = r->in.info_ctr->info.info1;
    9325          80 :         if (!form) {
    9326           0 :                 return WERR_INVALID_PARAMETER;
    9327             :         }
    9328             : 
    9329          80 :         tmp_ctx = talloc_new(p->mem_ctx);
    9330          80 :         if (!tmp_ctx) {
    9331           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9332             :         }
    9333             : 
    9334          80 :         status = winreg_printer_binding_handle(tmp_ctx,
    9335             :                                                get_session_info_system(),
    9336             :                                                p->msg_ctx,
    9337             :                                                &b);
    9338          80 :         if (!W_ERROR_IS_OK(status)) {
    9339           0 :                 goto done;
    9340             :         }
    9341             : 
    9342          80 :         status = winreg_printer_setform1(tmp_ctx, b,
    9343             :                                          form_name,
    9344             :                                          form);
    9345          80 :         if (!W_ERROR_IS_OK(status)) {
    9346           0 :                 goto done;
    9347             :         }
    9348             : 
    9349             :         /*
    9350             :          * ChangeID must always be set if this is a printer
    9351             :          */
    9352          80 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9353          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9354           0 :                         status = WERR_INVALID_HANDLE;
    9355           0 :                         goto done;
    9356             :                 }
    9357             : 
    9358          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9359             :                                                         lp_const_servicename(snum));
    9360             :         }
    9361             : 
    9362           0 : done:
    9363          80 :         talloc_free(tmp_ctx);
    9364          80 :         return status;
    9365             : }
    9366             : 
    9367             : /****************************************************************************
    9368             :  fill_print_processor1
    9369             : ****************************************************************************/
    9370             : 
    9371          24 : static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
    9372             :                                     struct spoolss_PrintProcessorInfo1 *r,
    9373             :                                     const char *print_processor_name)
    9374             : {
    9375          24 :         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
    9376          24 :         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
    9377             : 
    9378          24 :         return WERR_OK;
    9379             : }
    9380             : 
    9381             : /****************************************************************************
    9382             :  enumprintprocessors level 1.
    9383             : ****************************************************************************/
    9384             : 
    9385          24 : static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
    9386             :                                           union spoolss_PrintProcessorInfo **info_p,
    9387             :                                           uint32_t *count)
    9388             : {
    9389           0 :         union spoolss_PrintProcessorInfo *info;
    9390           0 :         WERROR result;
    9391             : 
    9392          24 :         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
    9393          24 :         W_ERROR_HAVE_NO_MEMORY(info);
    9394             : 
    9395          24 :         *count = 1;
    9396             : 
    9397          24 :         result = fill_print_processor1(info, &info[0].info1, "winprint");
    9398          24 :         if (!W_ERROR_IS_OK(result)) {
    9399           0 :                 goto out;
    9400             :         }
    9401             : 
    9402          24 :  out:
    9403          24 :         if (!W_ERROR_IS_OK(result)) {
    9404           0 :                 TALLOC_FREE(info);
    9405           0 :                 *count = 0;
    9406           0 :                 return result;
    9407             :         }
    9408             : 
    9409          24 :         *info_p = info;
    9410             : 
    9411          24 :         return WERR_OK;
    9412             : }
    9413             : 
    9414             : /****************************************************************
    9415             :  _spoolss_EnumPrintProcessors
    9416             : ****************************************************************/
    9417             : 
    9418          48 : WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
    9419             :                                     struct spoolss_EnumPrintProcessors *r)
    9420             : {
    9421           0 :         WERROR result;
    9422             : 
    9423             :         /* that's an [in out] buffer */
    9424             : 
    9425          48 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9426           0 :                 return WERR_INVALID_PARAMETER;
    9427             :         }
    9428             : 
    9429          48 :         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
    9430             : 
    9431             :         /*
    9432             :          * Enumerate the print processors ...
    9433             :          *
    9434             :          * Just reply with "winprint", to keep NT happy
    9435             :          * and I can use my nice printer checker.
    9436             :          */
    9437             : 
    9438          48 :         *r->out.count = 0;
    9439          48 :         *r->out.needed = 0;
    9440          48 :         *r->out.info = NULL;
    9441             : 
    9442          48 :         if (!get_short_archi(r->in.environment)) {
    9443           4 :                 return WERR_INVALID_ENVIRONMENT;
    9444             :         }
    9445             : 
    9446          44 :         switch (r->in.level) {
    9447          24 :         case 1:
    9448          24 :                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
    9449             :                                                      r->out.count);
    9450          24 :                 break;
    9451          20 :         default:
    9452          20 :                 return WERR_INVALID_LEVEL;
    9453             :         }
    9454             : 
    9455          24 :         if (!W_ERROR_IS_OK(result)) {
    9456           0 :                 return result;
    9457             :         }
    9458             : 
    9459          24 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9460             :                                                      spoolss_EnumPrintProcessors,
    9461             :                                                      *r->out.info, r->in.level,
    9462             :                                                      *r->out.count);
    9463          24 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9464          24 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9465             : 
    9466          24 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9467             : }
    9468             : 
    9469             : /****************************************************************************
    9470             :  fill_printprocdatatype1
    9471             : ****************************************************************************/
    9472             : 
    9473          16 : static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
    9474             :                                       struct spoolss_PrintProcDataTypesInfo1 *r,
    9475             :                                       const char *name_array)
    9476             : {
    9477          16 :         r->name_array = talloc_strdup(mem_ctx, name_array);
    9478          16 :         W_ERROR_HAVE_NO_MEMORY(r->name_array);
    9479             : 
    9480          16 :         return WERR_OK;
    9481             : }
    9482             : 
    9483             : /****************************************************************************
    9484             :  enumprintprocdatatypes level 1.
    9485             : ****************************************************************************/
    9486             : 
    9487          16 : static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
    9488             :                                              union spoolss_PrintProcDataTypesInfo **info_p,
    9489             :                                              uint32_t *count)
    9490             : {
    9491           0 :         WERROR result;
    9492           0 :         union spoolss_PrintProcDataTypesInfo *info;
    9493             : 
    9494          16 :         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
    9495          16 :         W_ERROR_HAVE_NO_MEMORY(info);
    9496             : 
    9497          16 :         *count = 1;
    9498             : 
    9499          16 :         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
    9500          16 :         if (!W_ERROR_IS_OK(result)) {
    9501           0 :                 goto out;
    9502             :         }
    9503             : 
    9504          16 :  out:
    9505          16 :         if (!W_ERROR_IS_OK(result)) {
    9506           0 :                 TALLOC_FREE(info);
    9507           0 :                 *count = 0;
    9508           0 :                 return result;
    9509             :         }
    9510             : 
    9511          16 :         *info_p = info;
    9512             : 
    9513          16 :         return WERR_OK;
    9514             : }
    9515             : 
    9516             : /****************************************************************
    9517             :  _spoolss_EnumPrintProcessorDataTypes
    9518             : ****************************************************************/
    9519             : 
    9520          44 : WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
    9521             :                                             struct spoolss_EnumPrintProcessorDataTypes *r)
    9522             : {
    9523           0 :         WERROR result;
    9524             : 
    9525             :         /* that's an [in out] buffer */
    9526             : 
    9527          44 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9528           0 :                 return WERR_INVALID_PARAMETER;
    9529             :         }
    9530             : 
    9531          44 :         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
    9532             : 
    9533          44 :         *r->out.count = 0;
    9534          44 :         *r->out.needed = 0;
    9535          44 :         *r->out.info = NULL;
    9536             : 
    9537          44 :         if (r->in.print_processor_name == NULL ||
    9538          40 :             !strequal(r->in.print_processor_name, "winprint")) {
    9539           8 :                 return WERR_UNKNOWN_PRINTPROCESSOR;
    9540             :         }
    9541             : 
    9542          36 :         switch (r->in.level) {
    9543          16 :         case 1:
    9544          16 :                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
    9545             :                                                         r->out.count);
    9546          16 :                 break;
    9547          20 :         default:
    9548          20 :                 return WERR_INVALID_LEVEL;
    9549             :         }
    9550             : 
    9551          16 :         if (!W_ERROR_IS_OK(result)) {
    9552           0 :                 return result;
    9553             :         }
    9554             : 
    9555          16 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9556             :                                                      spoolss_EnumPrintProcessorDataTypes,
    9557             :                                                      *r->out.info, r->in.level,
    9558             :                                                      *r->out.count);
    9559          16 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9560          16 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9561             : 
    9562          16 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9563             : }
    9564             : 
    9565             : /****************************************************************************
    9566             :  fill_monitor_1
    9567             : ****************************************************************************/
    9568             : 
    9569          16 : static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
    9570             :                              struct spoolss_MonitorInfo1 *r,
    9571             :                              const char *monitor_name)
    9572             : {
    9573          16 :         r->monitor_name                      = talloc_strdup(mem_ctx, monitor_name);
    9574          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    9575             : 
    9576          16 :         return WERR_OK;
    9577             : }
    9578             : 
    9579             : /****************************************************************************
    9580             :  fill_monitor_2
    9581             : ****************************************************************************/
    9582             : 
    9583          16 : static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
    9584             :                              struct spoolss_MonitorInfo2 *r,
    9585             :                              const char *monitor_name,
    9586             :                              const char *environment,
    9587             :                              const char *dll_name)
    9588             : {
    9589          16 :         r->monitor_name                      = talloc_strdup(mem_ctx, monitor_name);
    9590          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    9591          16 :         r->environment                       = talloc_strdup(mem_ctx, environment);
    9592          16 :         W_ERROR_HAVE_NO_MEMORY(r->environment);
    9593          16 :         r->dll_name                  = talloc_strdup(mem_ctx, dll_name);
    9594          16 :         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
    9595             : 
    9596          16 :         return WERR_OK;
    9597             : }
    9598             : 
    9599             : /****************************************************************************
    9600             :  enumprintmonitors level 1.
    9601             : ****************************************************************************/
    9602             : 
    9603           8 : static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
    9604             :                                         union spoolss_MonitorInfo **info_p,
    9605             :                                         uint32_t *count)
    9606             : {
    9607           0 :         union spoolss_MonitorInfo *info;
    9608           8 :         WERROR result = WERR_OK;
    9609             : 
    9610           8 :         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
    9611           8 :         W_ERROR_HAVE_NO_MEMORY(info);
    9612             : 
    9613           8 :         *count = 2;
    9614             : 
    9615           8 :         result = fill_monitor_1(info, &info[0].info1,
    9616             :                                 SPL_LOCAL_PORT);
    9617           8 :         if (!W_ERROR_IS_OK(result)) {
    9618           0 :                 goto out;
    9619             :         }
    9620             : 
    9621           8 :         result = fill_monitor_1(info, &info[1].info1,
    9622             :                                 SPL_TCPIP_PORT);
    9623           8 :         if (!W_ERROR_IS_OK(result)) {
    9624           0 :                 goto out;
    9625             :         }
    9626             : 
    9627           8 : out:
    9628           8 :         if (!W_ERROR_IS_OK(result)) {
    9629           0 :                 TALLOC_FREE(info);
    9630           0 :                 *count = 0;
    9631           0 :                 return result;
    9632             :         }
    9633             : 
    9634           8 :         *info_p = info;
    9635             : 
    9636           8 :         return WERR_OK;
    9637             : }
    9638             : 
    9639             : /****************************************************************************
    9640             :  enumprintmonitors level 2.
    9641             : ****************************************************************************/
    9642             : 
    9643           8 : static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
    9644             :                                         union spoolss_MonitorInfo **info_p,
    9645             :                                         uint32_t *count)
    9646             : {
    9647           0 :         union spoolss_MonitorInfo *info;
    9648           8 :         WERROR result = WERR_OK;
    9649           0 :         const char *architecture;
    9650             : 
    9651           8 :         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
    9652           8 :         W_ERROR_HAVE_NO_MEMORY(info);
    9653             : 
    9654           8 :         *count = 2;
    9655             : 
    9656           8 :         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    9657             :                                             "spoolss",
    9658             :                                             "architecture",
    9659             :                                             GLOBAL_SPOOLSS_ARCHITECTURE);
    9660             : 
    9661           8 :         result = fill_monitor_2(info, &info[0].info2,
    9662             :                                 SPL_LOCAL_PORT,
    9663             :                                 architecture,
    9664             :                                 "localmon.dll");
    9665           8 :         if (!W_ERROR_IS_OK(result)) {
    9666           0 :                 goto out;
    9667             :         }
    9668             : 
    9669           8 :         result = fill_monitor_2(info, &info[1].info2,
    9670             :                                 SPL_TCPIP_PORT,
    9671             :                                 architecture,
    9672             :                                 "tcpmon.dll");
    9673           8 :         if (!W_ERROR_IS_OK(result)) {
    9674           0 :                 goto out;
    9675             :         }
    9676             : 
    9677           8 : out:
    9678           8 :         if (!W_ERROR_IS_OK(result)) {
    9679           0 :                 TALLOC_FREE(info);
    9680           0 :                 *count = 0;
    9681           0 :                 return result;
    9682             :         }
    9683             : 
    9684           8 :         *info_p = info;
    9685             : 
    9686           8 :         return WERR_OK;
    9687             : }
    9688             : 
    9689             : /****************************************************************
    9690             :  _spoolss_EnumMonitors
    9691             : ****************************************************************/
    9692             : 
    9693          16 : WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
    9694             :                              struct spoolss_EnumMonitors *r)
    9695             : {
    9696           0 :         WERROR result;
    9697             : 
    9698             :         /* that's an [in out] buffer */
    9699             : 
    9700          16 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9701           0 :                 return WERR_INVALID_PARAMETER;
    9702             :         }
    9703             : 
    9704          16 :         DEBUG(5,("_spoolss_EnumMonitors\n"));
    9705             : 
    9706             :         /*
    9707             :          * Enumerate the print monitors ...
    9708             :          *
    9709             :          * Just reply with "Local Port", to keep NT happy
    9710             :          * and I can use my nice printer checker.
    9711             :          */
    9712             : 
    9713          16 :         *r->out.count = 0;
    9714          16 :         *r->out.needed = 0;
    9715          16 :         *r->out.info = NULL;
    9716             : 
    9717          16 :         switch (r->in.level) {
    9718           8 :         case 1:
    9719           8 :                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
    9720             :                                                    r->out.count);
    9721           8 :                 break;
    9722           8 :         case 2:
    9723           8 :                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
    9724             :                                                    r->out.count);
    9725           8 :                 break;
    9726           0 :         default:
    9727           0 :                 return WERR_INVALID_LEVEL;
    9728             :         }
    9729             : 
    9730          16 :         if (!W_ERROR_IS_OK(result)) {
    9731           0 :                 return result;
    9732             :         }
    9733             : 
    9734          16 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9735             :                                                      spoolss_EnumMonitors,
    9736             :                                                      *r->out.info, r->in.level,
    9737             :                                                      *r->out.count);
    9738          16 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9739          16 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9740             : 
    9741          16 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9742             : }
    9743             : 
    9744             : /****************************************************************************
    9745             : ****************************************************************************/
    9746             : 
    9747         128 : static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
    9748             :                              const print_queue_struct *queue,
    9749             :                              int count, int snum,
    9750             :                              struct spoolss_PrinterInfo2 *pinfo2,
    9751             :                              uint32_t jobid,
    9752             :                              int sysjob,
    9753             :                              struct spoolss_JobInfo1 *r)
    9754             : {
    9755         128 :         int i = 0;
    9756         128 :         bool found = false;
    9757             : 
    9758         576 :         for (i=0; i<count; i++) {
    9759         576 :                 if (queue[i].sysjob == sysjob) {
    9760         128 :                         found = true;
    9761         128 :                         break;
    9762             :                 }
    9763             :         }
    9764             : 
    9765         128 :         if (found == false) {
    9766             :                 /* NT treats not found as bad param... yet another bad choice */
    9767           0 :                 return WERR_INVALID_PARAMETER;
    9768             :         }
    9769             : 
    9770         128 :         return fill_job_info1(mem_ctx,
    9771             :                               r,
    9772         128 :                               &queue[i],
    9773             :                               jobid,
    9774             :                               i,
    9775             :                               snum,
    9776             :                               pinfo2);
    9777             : }
    9778             : 
    9779             : /****************************************************************************
    9780             : ****************************************************************************/
    9781             : 
    9782           0 : static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
    9783             :                              const print_queue_struct *queue,
    9784             :                              int count, int snum,
    9785             :                              struct spoolss_PrinterInfo2 *pinfo2,
    9786             :                              uint32_t jobid,
    9787             :                              int sysjob,
    9788             :                              struct spoolss_JobInfo2 *r)
    9789             : {
    9790           0 :         int i = 0;
    9791           0 :         bool found = false;
    9792           0 :         struct spoolss_DeviceMode *devmode;
    9793           0 :         WERROR result;
    9794             : 
    9795           0 :         for (i=0; i<count; i++) {
    9796           0 :                 if (queue[i].sysjob == sysjob) {
    9797           0 :                         found = true;
    9798           0 :                         break;
    9799             :                 }
    9800             :         }
    9801             : 
    9802           0 :         if (found == false) {
    9803             :                 /* NT treats not found as bad param... yet another bad
    9804             :                    choice */
    9805           0 :                 return WERR_INVALID_PARAMETER;
    9806             :         }
    9807             : 
    9808             :         /*
    9809             :          * if the print job does not have a DEVMODE associated with it,
    9810             :          * just use the one for the printer. A NULL devicemode is not
    9811             :          *  a failure condition
    9812             :          */
    9813             : 
    9814           0 :         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
    9815           0 :         if (!devmode) {
    9816           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    9817             :                                                 pinfo2->printername,
    9818             :                                                 &devmode);
    9819           0 :                 if (!W_ERROR_IS_OK(result)) {
    9820           0 :                         DEBUG(3, ("Can't proceed w/o a devmode!\n"));
    9821           0 :                         return result;
    9822             :                 }
    9823             :         }
    9824             : 
    9825           0 :         return fill_job_info2(mem_ctx,
    9826             :                               r,
    9827           0 :                               &queue[i],
    9828             :                               jobid,
    9829             :                               i,
    9830             :                               snum,
    9831             :                               pinfo2,
    9832             :                               devmode);
    9833             : }
    9834             : 
    9835             : /****************************************************************
    9836             :  _spoolss_GetJob
    9837             : ****************************************************************/
    9838             : 
    9839        2048 : WERROR _spoolss_GetJob(struct pipes_struct *p,
    9840             :                        struct spoolss_GetJob *r)
    9841             : {
    9842        2048 :         WERROR result = WERR_OK;
    9843        2048 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    9844           0 :         const char *svc_name;
    9845           0 :         int sysjob;
    9846           0 :         int snum;
    9847           0 :         int count;
    9848           0 :         struct tdb_print_db *pdb;
    9849        2048 :         print_queue_struct      *queue = NULL;
    9850           0 :         print_status_struct prt_status;
    9851             : 
    9852             :         /* that's an [in out] buffer */
    9853             : 
    9854        2048 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9855           0 :                 result = WERR_INVALID_PARAMETER;
    9856           0 :                 goto err_jinfo_free;
    9857             :         }
    9858             : 
    9859        2048 :         DEBUG(5,("_spoolss_GetJob\n"));
    9860             : 
    9861        2048 :         *r->out.needed = 0;
    9862             : 
    9863        2048 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9864           0 :                 result = WERR_INVALID_HANDLE;
    9865           0 :                 goto err_jinfo_free;
    9866             :         }
    9867             : 
    9868        2048 :         svc_name = lp_const_servicename(snum);
    9869        2048 :         if (svc_name == NULL) {
    9870           0 :                 result = WERR_INVALID_PARAMETER;
    9871           0 :                 goto err_jinfo_free;
    9872             :         }
    9873             : 
    9874        2048 :         result = winreg_get_printer_internal(p->mem_ctx,
    9875             :                                     get_session_info_system(),
    9876             :                                     p->msg_ctx,
    9877             :                                     svc_name,
    9878             :                                     &pinfo2);
    9879        2048 :         if (!W_ERROR_IS_OK(result)) {
    9880           0 :                 goto err_jinfo_free;
    9881             :         }
    9882             : 
    9883        2048 :         pdb = get_print_db_byname(svc_name);
    9884        2048 :         if (pdb == NULL) {
    9885           0 :                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
    9886           0 :                 result = WERR_INVALID_PARAMETER;
    9887           0 :                 goto err_pinfo_free;
    9888             :         }
    9889             : 
    9890        2048 :         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
    9891        2048 :         release_print_db(pdb);
    9892        2048 :         if (sysjob == -1) {
    9893        1920 :                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
    9894        1920 :                 result = WERR_INVALID_PARAMETER;
    9895        1920 :                 goto err_pinfo_free;
    9896             :         }
    9897             : 
    9898         128 :         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
    9899             : 
    9900         128 :         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
    9901             :                      count, prt_status.status, prt_status.message));
    9902             : 
    9903         128 :         switch (r->in.level) {
    9904         128 :         case 1:
    9905         128 :                 result = getjob_level_1(p->mem_ctx,
    9906             :                                         queue, count, snum, pinfo2,
    9907             :                                         r->in.job_id, sysjob,
    9908         128 :                                         &r->out.info->info1);
    9909         128 :                 break;
    9910           0 :         case 2:
    9911           0 :                 result = getjob_level_2(p->mem_ctx,
    9912             :                                         queue, count, snum, pinfo2,
    9913             :                                         r->in.job_id, sysjob,
    9914           0 :                                         &r->out.info->info2);
    9915           0 :                 break;
    9916           0 :         default:
    9917           0 :                 result = WERR_INVALID_LEVEL;
    9918           0 :                 break;
    9919             :         }
    9920             : 
    9921         128 :         SAFE_FREE(queue);
    9922         128 :         TALLOC_FREE(pinfo2);
    9923             : 
    9924         128 :         if (!W_ERROR_IS_OK(result)) {
    9925           0 :                 goto err_jinfo_free;
    9926             :         }
    9927             : 
    9928         128 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
    9929             :                                                                                    r->in.level);
    9930         128 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    9931             : 
    9932         128 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9933             : 
    9934        1920 : err_pinfo_free:
    9935        1920 :         TALLOC_FREE(pinfo2);
    9936           0 : err_jinfo_free:
    9937        1920 :         TALLOC_FREE(r->out.info);
    9938        1920 :         return result;
    9939             : }
    9940             : 
    9941             : /****************************************************************
    9942             :  _spoolss_GetPrinterDataEx
    9943             : ****************************************************************/
    9944             : 
    9945        3180 : WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
    9946             :                                  struct spoolss_GetPrinterDataEx *r)
    9947             : {
    9948             : 
    9949        3180 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9950           0 :         const char *printer;
    9951        3180 :         int                     snum = 0;
    9952        3180 :         WERROR result = WERR_OK;
    9953           0 :         DATA_BLOB blob;
    9954        3180 :         enum winreg_Type val_type = REG_NONE;
    9955        3180 :         uint8_t *val_data = NULL;
    9956        3180 :         uint32_t val_size = 0;
    9957           0 :         struct dcerpc_binding_handle *b;
    9958           0 :         TALLOC_CTX *tmp_ctx;
    9959             : 
    9960        3180 :         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
    9961             : 
    9962        3180 :         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
    9963             :                 r->in.key_name, r->in.value_name));
    9964             : 
    9965             :         /* in case of problem, return some default values */
    9966             : 
    9967        3180 :         *r->out.needed       = 0;
    9968        3180 :         *r->out.type = REG_NONE;
    9969             : 
    9970        3180 :         tmp_ctx = talloc_new(p->mem_ctx);
    9971        3180 :         if (!tmp_ctx) {
    9972           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9973             :         }
    9974             : 
    9975        3180 :         if (!Printer) {
    9976           0 :                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
    9977             :                         OUR_HANDLE(r->in.handle)));
    9978           0 :                 result = WERR_INVALID_HANDLE;
    9979           0 :                 goto done;
    9980             :         }
    9981             : 
    9982             :         /* Is the handle to a printer or to the server? */
    9983             : 
    9984        3180 :         if (Printer->printer_type == SPLHND_SERVER) {
    9985             : 
    9986           0 :                 union spoolss_PrinterData data;
    9987             : 
    9988         404 :                 result = getprinterdata_printer_server(tmp_ctx,
    9989             :                                                        r->in.value_name,
    9990             :                                                        r->out.type,
    9991             :                                                        &data);
    9992         404 :                 if (!W_ERROR_IS_OK(result)) {
    9993           4 :                         goto done;
    9994             :                 }
    9995             : 
    9996         400 :                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
    9997         400 :                                                   *r->out.type, &data);
    9998         400 :                 if (!W_ERROR_IS_OK(result)) {
    9999           0 :                         goto done;
   10000             :                 }
   10001             : 
   10002         400 :                 *r->out.needed = blob.length;
   10003             : 
   10004         400 :                 if (r->in.offered >= *r->out.needed) {
   10005         204 :                         memcpy(r->out.data, blob.data, blob.length);
   10006             :                 }
   10007             : 
   10008         400 :                 result = WERR_OK;
   10009         400 :                 goto done;
   10010             :         }
   10011             : 
   10012             :         /* check to see if the keyname is valid */
   10013        2776 :         if (!strlen(r->in.key_name)) {
   10014           0 :                 result = WERR_INVALID_PARAMETER;
   10015           0 :                 goto done;
   10016             :         }
   10017             : 
   10018        2776 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10019           0 :                 result = WERR_INVALID_HANDLE;
   10020           0 :                 goto done;
   10021             :         }
   10022        2776 :         printer = lp_const_servicename(snum);
   10023             : 
   10024        2776 :         result = winreg_printer_binding_handle(tmp_ctx,
   10025             :                                                get_session_info_system(),
   10026             :                                                p->msg_ctx,
   10027             :                                                &b);
   10028        2776 :         if (!W_ERROR_IS_OK(result)) {
   10029           0 :                 goto done;
   10030             :         }
   10031             : 
   10032             :         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
   10033        3076 :         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
   10034         300 :             strequal(r->in.value_name, "ChangeId")) {
   10035         128 :                 *r->out.type = REG_DWORD;
   10036         128 :                 *r->out.needed = 4;
   10037         128 :                 if (r->in.offered >= *r->out.needed) {
   10038          64 :                         uint32_t changeid = 0;
   10039             : 
   10040          64 :                         result = winreg_printer_get_changeid(tmp_ctx, b,
   10041             :                                                              printer,
   10042             :                                                              &changeid);
   10043          64 :                         if (!W_ERROR_IS_OK(result)) {
   10044           0 :                                 goto done;
   10045             :                         }
   10046             : 
   10047          64 :                         SIVAL(r->out.data, 0, changeid);
   10048          64 :                         result = WERR_OK;
   10049             :                 }
   10050         128 :                 goto done;
   10051             :         }
   10052             : 
   10053        2648 :         result = winreg_get_printer_dataex(tmp_ctx, b,
   10054             :                                            printer,
   10055             :                                            r->in.key_name,
   10056             :                                            r->in.value_name,
   10057             :                                            &val_type,
   10058             :                                            &val_data,
   10059             :                                            &val_size);
   10060        2648 :         if (!W_ERROR_IS_OK(result)) {
   10061           4 :                 goto done;
   10062             :         }
   10063             : 
   10064        2644 :         *r->out.needed = val_size;
   10065        2644 :         *r->out.type = val_type;
   10066             : 
   10067        2644 :         if (r->in.offered >= *r->out.needed) {
   10068        1340 :                 memcpy(r->out.data, val_data, val_size);
   10069             :         }
   10070             : 
   10071        1304 : done:
   10072             :         /* NOTE: do not replace type when returning WERR_MORE_DATA */
   10073             : 
   10074        3180 :         if (W_ERROR_IS_OK(result)) {
   10075        3172 :                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
   10076             :         }
   10077             : 
   10078        3180 :         talloc_free(tmp_ctx);
   10079        3180 :         return result;
   10080             : }
   10081             : 
   10082             : /****************************************************************
   10083             :  _spoolss_SetPrinterDataEx
   10084             : ****************************************************************/
   10085             : 
   10086        1368 : WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
   10087             :                                  struct spoolss_SetPrinterDataEx *r)
   10088             : {
   10089           0 :         const struct loadparm_substitution *lp_sub =
   10090        1368 :                 loadparm_s3_global_substitution();
   10091        1368 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
   10092        1368 :         int                     snum = 0;
   10093        1368 :         WERROR                  result = WERR_OK;
   10094        1368 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10095           0 :         char                    *oid_string;
   10096           0 :         struct dcerpc_binding_handle *b;
   10097           0 :         TALLOC_CTX *tmp_ctx;
   10098             : 
   10099        1368 :         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
   10100             : 
   10101             :         /* From MSDN documentation of SetPrinterDataEx: pass request to
   10102             :            SetPrinterData if key is "PrinterDriverData" */
   10103             : 
   10104        1368 :         if (!Printer) {
   10105           0 :                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
   10106             :                         OUR_HANDLE(r->in.handle)));
   10107           0 :                 return WERR_INVALID_HANDLE;
   10108             :         }
   10109             : 
   10110        1368 :         if (Printer->printer_type == SPLHND_SERVER) {
   10111           0 :                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
   10112             :                         "Not implemented for server handles yet\n"));
   10113           0 :                 return WERR_INVALID_PARAMETER;
   10114             :         }
   10115             : 
   10116        1368 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10117           0 :                 return WERR_INVALID_HANDLE;
   10118             :         }
   10119             : 
   10120             :         /*
   10121             :          * Access check : NT returns "access denied" if you make a
   10122             :          * SetPrinterData call without the necessary privilege.
   10123             :          * we were originally returning OK if nothing changed
   10124             :          * which made Win2k issue **a lot** of SetPrinterData
   10125             :          * when connecting to a printer  --jerry
   10126             :          */
   10127             : 
   10128        1368 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10129           0 :                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
   10130             :                         "change denied by handle access permissions\n"));
   10131           0 :                 return WERR_ACCESS_DENIED;
   10132             :         }
   10133             : 
   10134        1368 :         tmp_ctx = talloc_new(p->mem_ctx);
   10135        1368 :         if (!tmp_ctx) {
   10136           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10137             :         }
   10138             : 
   10139        1368 :         result = winreg_printer_binding_handle(tmp_ctx,
   10140             :                                                get_session_info_system(),
   10141             :                                                p->msg_ctx,
   10142             :                                                &b);
   10143        1368 :         if (!W_ERROR_IS_OK(result)) {
   10144           0 :                 goto done;
   10145             :         }
   10146             : 
   10147        1368 :         result = winreg_get_printer(tmp_ctx, b,
   10148        1368 :                                     lp_servicename(talloc_tos(), lp_sub, snum),
   10149             :                                     &pinfo2);
   10150        1368 :         if (!W_ERROR_IS_OK(result)) {
   10151           0 :                 goto done;
   10152             :         }
   10153             : 
   10154             :         /* check for OID in valuename */
   10155             : 
   10156        1368 :         oid_string = strchr(r->in.value_name, ',');
   10157        1368 :         if (oid_string) {
   10158           0 :                 *oid_string = '\0';
   10159           0 :                 oid_string++;
   10160             :         }
   10161             : 
   10162             :         /* save the registry data */
   10163             : 
   10164        1368 :         result = winreg_set_printer_dataex(tmp_ctx, b,
   10165        1368 :                                            pinfo2->sharename,
   10166             :                                            r->in.key_name,
   10167             :                                            r->in.value_name,
   10168             :                                            r->in.type,
   10169             :                                            r->in.data,
   10170             :                                            r->in.offered);
   10171             : 
   10172        1368 :         if (W_ERROR_IS_OK(result)) {
   10173             :                 /* save the OID if one was specified */
   10174        1368 :                 if (oid_string) {
   10175           0 :                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
   10176             :                                 r->in.key_name, SPOOL_OID_KEY);
   10177           0 :                         if (!str) {
   10178           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
   10179           0 :                                 goto done;
   10180             :                         }
   10181             : 
   10182             :                         /*
   10183             :                          * I'm not checking the status here on purpose.  Don't know
   10184             :                          * if this is right, but I'm returning the status from the
   10185             :                          * previous set_printer_dataex() call.  I have no idea if
   10186             :                          * this is right.    --jerry
   10187             :                          */
   10188           0 :                         winreg_set_printer_dataex(tmp_ctx, b,
   10189           0 :                                                   pinfo2->sharename,
   10190             :                                                   str,
   10191             :                                                   r->in.value_name,
   10192             :                                                   REG_SZ,
   10193             :                                                   (uint8_t *) oid_string,
   10194           0 :                                                   strlen(oid_string) + 1);
   10195             :                 }
   10196             : 
   10197        1368 :                 result = winreg_printer_update_changeid(tmp_ctx, b,
   10198             :                                                         lp_const_servicename(snum));
   10199             : 
   10200             :         }
   10201             : 
   10202           0 : done:
   10203        1368 :         talloc_free(tmp_ctx);
   10204        1368 :         return result;
   10205             : }
   10206             : 
   10207             : /****************************************************************
   10208             :  _spoolss_DeletePrinterDataEx
   10209             : ****************************************************************/
   10210             : 
   10211        1368 : WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
   10212             :                                     struct spoolss_DeletePrinterDataEx *r)
   10213             : {
   10214           0 :         const char *printer;
   10215        1368 :         int             snum=0;
   10216        1368 :         WERROR          status = WERR_OK;
   10217        1368 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10218             : 
   10219        1368 :         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
   10220             : 
   10221        1368 :         if (!Printer) {
   10222           0 :                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
   10223             :                         "Invalid handle (%s:%u:%u).\n",
   10224             :                         OUR_HANDLE(r->in.handle)));
   10225           0 :                 return WERR_INVALID_HANDLE;
   10226             :         }
   10227             : 
   10228        1368 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10229           0 :                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
   10230             :                         "printer properties change denied by handle\n"));
   10231           0 :                 return WERR_ACCESS_DENIED;
   10232             :         }
   10233             : 
   10234        1368 :         if (!r->in.value_name || !r->in.key_name) {
   10235           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10236             :         }
   10237             : 
   10238        1368 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10239           0 :                 return WERR_INVALID_HANDLE;
   10240             :         }
   10241        1368 :         printer = lp_const_servicename(snum);
   10242             : 
   10243        1368 :         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
   10244             :                                               get_session_info_system(),
   10245             :                                               p->msg_ctx,
   10246             :                                               printer,
   10247             :                                               r->in.key_name,
   10248             :                                               r->in.value_name);
   10249        1368 :         if (W_ERROR_IS_OK(status)) {
   10250        1368 :                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
   10251             :                                                         get_session_info_system(),
   10252             :                                                         p->msg_ctx,
   10253             :                                                         printer);
   10254             :         }
   10255             : 
   10256        1368 :         return status;
   10257             : }
   10258             : 
   10259             : /****************************************************************
   10260             :  _spoolss_EnumPrinterKey
   10261             : ****************************************************************/
   10262             : 
   10263        3384 : WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
   10264             :                                struct spoolss_EnumPrinterKey *r)
   10265             : {
   10266           0 :         uint32_t        num_keys;
   10267        3384 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10268        3384 :         int             snum = 0;
   10269        3384 :         WERROR          result = WERR_FILE_NOT_FOUND;
   10270        3384 :         const char **array = NULL;
   10271           0 :         DATA_BLOB blob;
   10272             : 
   10273        3384 :         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
   10274             : 
   10275        3384 :         if (!Printer) {
   10276           0 :                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
   10277             :                         OUR_HANDLE(r->in.handle)));
   10278           0 :                 return WERR_INVALID_HANDLE;
   10279             :         }
   10280             : 
   10281        3384 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10282           0 :                 return WERR_INVALID_HANDLE;
   10283             :         }
   10284             : 
   10285        3384 :         result = winreg_enum_printer_key_internal(p->mem_ctx,
   10286             :                                          get_session_info_system(),
   10287             :                                          p->msg_ctx,
   10288             :                                          lp_const_servicename(snum),
   10289             :                                          r->in.key_name,
   10290             :                                          &num_keys,
   10291             :                                          &array);
   10292        3384 :         if (!W_ERROR_IS_OK(result)) {
   10293           0 :                 goto done;
   10294             :         }
   10295             : 
   10296        3384 :         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
   10297           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
   10298           0 :                 goto done;
   10299             :         }
   10300             : 
   10301        3384 :         *r->out._ndr_size = r->in.offered / 2;
   10302        3384 :         *r->out.needed = blob.length;
   10303             : 
   10304        3384 :         if (r->in.offered < *r->out.needed) {
   10305        1304 :                 result = WERR_MORE_DATA;
   10306             :         } else {
   10307        2080 :                 result = WERR_OK;
   10308        2080 :                 r->out.key_buffer->string_array = array;
   10309             :         }
   10310             : 
   10311        3384 :  done:
   10312        3384 :         if (!W_ERROR_IS_OK(result)) {
   10313        1304 :                 TALLOC_FREE(array);
   10314        1304 :                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
   10315           0 :                         *r->out.needed = 0;
   10316             :                 }
   10317             :         }
   10318             : 
   10319        3384 :         return result;
   10320             : }
   10321             : 
   10322             : /****************************************************************
   10323             :  _spoolss_DeletePrinterKey
   10324             : ****************************************************************/
   10325             : 
   10326         216 : WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
   10327             :                                  struct spoolss_DeletePrinterKey *r)
   10328             : {
   10329         216 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10330         216 :         int                     snum=0;
   10331           0 :         WERROR                  status;
   10332           0 :         const char *printer;
   10333           0 :         struct dcerpc_binding_handle *b;
   10334           0 :         TALLOC_CTX *tmp_ctx;
   10335             : 
   10336         216 :         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
   10337             : 
   10338         216 :         if (!Printer) {
   10339           0 :                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
   10340             :                         OUR_HANDLE(r->in.handle)));
   10341           0 :                 return WERR_INVALID_HANDLE;
   10342             :         }
   10343             : 
   10344             :         /* if keyname == NULL, return error */
   10345         216 :         if ( !r->in.key_name )
   10346           0 :                 return WERR_INVALID_PARAMETER;
   10347             : 
   10348         216 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10349           0 :                 return WERR_INVALID_HANDLE;
   10350             :         }
   10351             : 
   10352         216 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10353           0 :                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
   10354             :                         "printer properties change denied by handle\n"));
   10355           0 :                 return WERR_ACCESS_DENIED;
   10356             :         }
   10357             : 
   10358         216 :         printer = lp_const_servicename(snum);
   10359             : 
   10360         216 :         tmp_ctx = talloc_new(p->mem_ctx);
   10361         216 :         if (!tmp_ctx) {
   10362           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10363             :         }
   10364             : 
   10365         216 :         status = winreg_printer_binding_handle(tmp_ctx,
   10366             :                                                get_session_info_system(),
   10367             :                                                p->msg_ctx,
   10368             :                                                &b);
   10369         216 :         if (!W_ERROR_IS_OK(status)) {
   10370           0 :                 goto done;
   10371             :         }
   10372             : 
   10373             :         /* delete the key and all subkeys */
   10374         216 :         status = winreg_delete_printer_key(tmp_ctx, b,
   10375             :                                            printer,
   10376             :                                            r->in.key_name);
   10377         216 :         if (W_ERROR_IS_OK(status)) {
   10378         216 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
   10379             :                                                         printer);
   10380             :         }
   10381             : 
   10382           0 : done:
   10383         216 :         talloc_free(tmp_ctx);
   10384         216 :         return status;
   10385             : }
   10386             : 
   10387             : /****************************************************************
   10388             :  _spoolss_EnumPrinterDataEx
   10389             : ****************************************************************/
   10390             : 
   10391        2860 : WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
   10392             :                                   struct spoolss_EnumPrinterDataEx *r)
   10393             : {
   10394        2860 :         uint32_t        count = 0;
   10395        2860 :         struct spoolss_PrinterEnumValues *info = NULL;
   10396        2860 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10397           0 :         int             snum;
   10398           0 :         WERROR          result;
   10399             : 
   10400        2860 :         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
   10401             : 
   10402        2860 :         *r->out.count = 0;
   10403        2860 :         *r->out.needed = 0;
   10404        2860 :         *r->out.info = NULL;
   10405             : 
   10406        2860 :         if (!Printer) {
   10407           0 :                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
   10408             :                         OUR_HANDLE(r->in.handle)));
   10409           0 :                 return WERR_INVALID_HANDLE;
   10410             :         }
   10411             : 
   10412             :         /*
   10413             :          * first check for a keyname of NULL or "".  Win2k seems to send
   10414             :          * this a lot and we should send back WERR_INVALID_PARAMETER
   10415             :          * no need to spend time looking up the printer in this case.
   10416             :          * --jerry
   10417             :          */
   10418             : 
   10419        2860 :         if (!strlen(r->in.key_name)) {
   10420           4 :                 result = WERR_INVALID_PARAMETER;
   10421           4 :                 goto done;
   10422             :         }
   10423             : 
   10424        2856 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10425           0 :                 return WERR_INVALID_HANDLE;
   10426             :         }
   10427             : 
   10428             :         /* now look for a match on the key name */
   10429        2856 :         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
   10430             :                                             get_session_info_system(),
   10431             :                                             p->msg_ctx,
   10432             :                                             lp_const_servicename(snum),
   10433             :                                             r->in.key_name,
   10434             :                                             &count,
   10435             :                                             &info);
   10436        2856 :         if (!W_ERROR_IS_OK(result)) {
   10437           0 :                 goto done;
   10438             :         }
   10439             : 
   10440        2856 :         *r->out.count        = count;
   10441        2856 :         *r->out.info = info;
   10442             : 
   10443        2860 :  done:
   10444        2860 :         if (!W_ERROR_IS_OK(result)) {
   10445           4 :                 return result;
   10446             :         }
   10447             : 
   10448        2856 :         *r->out.needed       = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
   10449             :                                                spoolss_EnumPrinterDataEx,
   10450             :                                                *r->out.info,
   10451             :                                                *r->out.count);
   10452        2856 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
   10453        2856 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
   10454             : 
   10455        2856 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
   10456             : }
   10457             : 
   10458             : /****************************************************************************
   10459             : ****************************************************************************/
   10460             : 
   10461          40 : static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
   10462             :                                                  const char *servername,
   10463             :                                                  const char *environment,
   10464             :                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
   10465             : {
   10466           0 :         WERROR werr;
   10467          40 :         char *path = NULL;
   10468             : 
   10469          40 :         werr = compose_spoolss_server_path(mem_ctx,
   10470             :                                            servername,
   10471             :                                            environment,
   10472             :                                            SPOOLSS_PRTPROCS_PATH,
   10473             :                                            &path);
   10474          40 :         if (!W_ERROR_IS_OK(werr)) {
   10475           0 :                 return werr;
   10476             :         }
   10477             : 
   10478          40 :         DEBUG(4,("print processor directory: [%s]\n", path));
   10479             : 
   10480          40 :         r->directory_name = path;
   10481             : 
   10482          40 :         return WERR_OK;
   10483             : }
   10484             : 
   10485             : /****************************************************************
   10486             :  _spoolss_GetPrintProcessorDirectory
   10487             : ****************************************************************/
   10488             : 
   10489          40 : WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
   10490             :                                            struct spoolss_GetPrintProcessorDirectory *r)
   10491             : {
   10492           0 :         WERROR result;
   10493          40 :         char *prnproc_share = NULL;
   10494          40 :         bool prnproc_share_exists = false;
   10495           0 :         int snum;
   10496             : 
   10497             :         /* that's an [in out] buffer */
   10498             : 
   10499          40 :         if (!r->in.buffer && (r->in.offered != 0)) {
   10500           0 :                 result = WERR_INVALID_PARAMETER;
   10501           0 :                 goto err_info_free;
   10502             :         }
   10503             : 
   10504          40 :         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
   10505             :                 r->in.level));
   10506             : 
   10507          40 :         *r->out.needed = 0;
   10508             : 
   10509             :         /* r->in.level is ignored */
   10510             : 
   10511             :         /* We always should reply with a local print processor directory so that
   10512             :          * users are not forced to have a [prnproc$] share on the Samba spoolss
   10513             :          * server, if users decide to do so, lets announce it though - Guenther */
   10514             : 
   10515          40 :         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
   10516          40 :         if (!prnproc_share) {
   10517           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
   10518           0 :                 goto err_info_free;
   10519             :         }
   10520          40 :         if (snum != -1) {
   10521           0 :                 prnproc_share_exists = true;
   10522             :         }
   10523             : 
   10524          40 :         result = getprintprocessordirectory_level_1(p->mem_ctx,
   10525             :                                                     prnproc_share_exists ? r->in.server : NULL,
   10526             :                                                     r->in.environment,
   10527          40 :                                                     &r->out.info->info1);
   10528          40 :         if (!W_ERROR_IS_OK(result)) {
   10529           0 :                 goto err_info_free;
   10530             :         }
   10531             : 
   10532          40 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
   10533             :                                                                                    r->out.info, r->in.level);
   10534          40 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
   10535             : 
   10536          40 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
   10537             : 
   10538           0 : err_info_free:
   10539           0 :         TALLOC_FREE(r->out.info);
   10540           0 :         return result;
   10541             : }
   10542             : 
   10543             : /*******************************************************************
   10544             :  ********************************************************************/
   10545             : 
   10546           0 : static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
   10547             :                                const char *dllname)
   10548             : {
   10549           0 :         enum ndr_err_code ndr_err;
   10550           0 :         struct spoolss_MonitorUi ui;
   10551             : 
   10552           0 :         ui.dll_name = dllname;
   10553             : 
   10554           0 :         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
   10555             :                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
   10556           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10557           0 :                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
   10558             :         }
   10559           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10560             : }
   10561             : 
   10562             : /*******************************************************************
   10563             :  Streams the monitor UI DLL name in UNICODE
   10564             : *******************************************************************/
   10565             : 
   10566           0 : static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
   10567             :                                struct security_token *token, DATA_BLOB *in,
   10568             :                                DATA_BLOB *out, uint32_t *needed)
   10569             : {
   10570           0 :         const char *dllname = "tcpmonui.dll";
   10571             : 
   10572           0 :         *needed = (strlen(dllname)+1) * 2;
   10573             : 
   10574           0 :         if (out->length < *needed) {
   10575           0 :                 return WERR_INSUFFICIENT_BUFFER;
   10576             :         }
   10577             : 
   10578           0 :         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
   10579           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10580             :         }
   10581             : 
   10582           0 :         return WERR_OK;
   10583             : }
   10584             : 
   10585             : /*******************************************************************
   10586             :  ********************************************************************/
   10587             : 
   10588           0 : static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
   10589             :                              struct spoolss_PortData1 *port1,
   10590             :                              const DATA_BLOB *buf)
   10591             : {
   10592           0 :         enum ndr_err_code ndr_err;
   10593           0 :         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
   10594             :                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
   10595           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10596           0 :                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
   10597             :         }
   10598           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10599             : }
   10600             : 
   10601             : /*******************************************************************
   10602             :  ********************************************************************/
   10603             : 
   10604           0 : static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
   10605             :                              struct spoolss_PortData2 *port2,
   10606             :                              const DATA_BLOB *buf)
   10607             : {
   10608           0 :         enum ndr_err_code ndr_err;
   10609           0 :         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
   10610             :                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
   10611           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10612           0 :                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
   10613             :         }
   10614           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10615             : }
   10616             : 
   10617             : /*******************************************************************
   10618             :  Create a new TCP/IP port
   10619             : *******************************************************************/
   10620             : 
   10621           0 : static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
   10622             :                              struct security_token *token, DATA_BLOB *in,
   10623             :                              DATA_BLOB *out, uint32_t *needed)
   10624             : {
   10625           0 :         struct spoolss_PortData1 port1;
   10626           0 :         struct spoolss_PortData2 port2;
   10627           0 :         char *device_uri = NULL;
   10628           0 :         uint32_t version;
   10629             : 
   10630           0 :         const char *portname;
   10631           0 :         const char *hostaddress;
   10632           0 :         const char *queue;
   10633           0 :         uint32_t port_number;
   10634           0 :         uint32_t protocol;
   10635             : 
   10636             :         /* peek for spoolss_PortData version */
   10637             : 
   10638           0 :         if (!in || (in->length < (128 + 4))) {
   10639           0 :                 return WERR_GEN_FAILURE;
   10640             :         }
   10641             : 
   10642           0 :         version = IVAL(in->data, 128);
   10643             : 
   10644           0 :         switch (version) {
   10645           0 :                 case 1:
   10646           0 :                         ZERO_STRUCT(port1);
   10647             : 
   10648           0 :                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
   10649           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
   10650             :                         }
   10651             : 
   10652           0 :                         portname        = port1.portname;
   10653           0 :                         hostaddress     = port1.hostaddress;
   10654           0 :                         queue           = port1.queue;
   10655           0 :                         protocol        = port1.protocol;
   10656           0 :                         port_number     = port1.port_number;
   10657             : 
   10658           0 :                         break;
   10659           0 :                 case 2:
   10660           0 :                         ZERO_STRUCT(port2);
   10661             : 
   10662           0 :                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
   10663           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
   10664             :                         }
   10665             : 
   10666           0 :                         portname        = port2.portname;
   10667           0 :                         hostaddress     = port2.hostaddress;
   10668           0 :                         queue           = port2.queue;
   10669           0 :                         protocol        = port2.protocol;
   10670           0 :                         port_number     = port2.port_number;
   10671             : 
   10672           0 :                         break;
   10673           0 :                 default:
   10674           0 :                         DEBUG(1,("xcvtcp_addport: "
   10675             :                                 "unknown version of port_data: %d\n", version));
   10676           0 :                         return WERR_UNKNOWN_PORT;
   10677             :         }
   10678             : 
   10679             :         /* create the device URI and call the add_port_hook() */
   10680             : 
   10681           0 :         switch (protocol) {
   10682           0 :         case PROTOCOL_RAWTCP_TYPE:
   10683           0 :                 device_uri = talloc_asprintf(mem_ctx,
   10684             :                                 "socket://%s:%d/", hostaddress,
   10685             :                                 port_number);
   10686           0 :                 break;
   10687             : 
   10688           0 :         case PROTOCOL_LPR_TYPE:
   10689           0 :                 device_uri = talloc_asprintf(mem_ctx,
   10690             :                         "lpr://%s/%s", hostaddress, queue );
   10691           0 :                 break;
   10692             : 
   10693           0 :         default:
   10694           0 :                 return WERR_UNKNOWN_PORT;
   10695             :         }
   10696             : 
   10697           0 :         if (!device_uri) {
   10698           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10699             :         }
   10700             : 
   10701           0 :         return add_port_hook(mem_ctx, token, portname, device_uri);
   10702             : }
   10703             : 
   10704             : /*******************************************************************
   10705             : *******************************************************************/
   10706             : 
   10707             : struct xcv_api_table xcvtcp_cmds[] = {
   10708             :         { "MonitorUI",        xcvtcp_monitorui },
   10709             :         { "AddPort",  xcvtcp_addport},
   10710             :         { NULL,         NULL }
   10711             : };
   10712             : 
   10713           0 : static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
   10714             :                                      struct security_token *token, const char *command,
   10715             :                                      DATA_BLOB *inbuf,
   10716             :                                      DATA_BLOB *outbuf,
   10717             :                                      uint32_t *needed )
   10718             : {
   10719           0 :         int i;
   10720             : 
   10721           0 :         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
   10722             : 
   10723           0 :         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
   10724           0 :                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
   10725           0 :                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
   10726             :         }
   10727             : 
   10728           0 :         return WERR_INVALID_FUNCTION;
   10729             : }
   10730             : 
   10731             : /*******************************************************************
   10732             : *******************************************************************/
   10733             : #if 0   /* don't support management using the "Local Port" monitor */
   10734             : 
   10735             : static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
   10736             :                                  struct security_token *token, DATA_BLOB *in,
   10737             :                                  DATA_BLOB *out, uint32_t *needed)
   10738             : {
   10739             :         const char *dllname = "localui.dll";
   10740             : 
   10741             :         *needed = (strlen(dllname)+1) * 2;
   10742             : 
   10743             :         if (out->length < *needed) {
   10744             :                 return WERR_INSUFFICIENT_BUFFER;
   10745             :         }
   10746             : 
   10747             :         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
   10748             :                 return WERR_NOT_ENOUGH_MEMORY;
   10749             :         }
   10750             : 
   10751             :         return WERR_OK;
   10752             : }
   10753             : 
   10754             : /*******************************************************************
   10755             : *******************************************************************/
   10756             : 
   10757             : struct xcv_api_table xcvlocal_cmds[] = {
   10758             :         { "MonitorUI",        xcvlocal_monitorui },
   10759             :         { NULL,         NULL }
   10760             : };
   10761             : #else
   10762             : struct xcv_api_table xcvlocal_cmds[] = {
   10763             :         { NULL,         NULL }
   10764             : };
   10765             : #endif
   10766             : 
   10767             : 
   10768             : 
   10769             : /*******************************************************************
   10770             : *******************************************************************/
   10771             : 
   10772           0 : static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
   10773             :                                        struct security_token *token, const char *command,
   10774             :                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
   10775             :                                        uint32_t *needed)
   10776             : {
   10777           0 :         int i;
   10778             : 
   10779           0 :         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
   10780             : 
   10781           0 :         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
   10782           0 :                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
   10783           0 :                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
   10784             :         }
   10785           0 :         return WERR_INVALID_FUNCTION;
   10786             : }
   10787             : 
   10788             : /****************************************************************
   10789             :  _spoolss_XcvData
   10790             : ****************************************************************/
   10791             : 
   10792           0 : WERROR _spoolss_XcvData(struct pipes_struct *p,
   10793             :                         struct spoolss_XcvData *r)
   10794             : {
   10795           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
   10796           0 :         struct auth_session_info *session_info =
   10797           0 :                 dcesrv_call_session_info(dce_call);
   10798           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10799           0 :         DATA_BLOB out_data = data_blob_null;
   10800           0 :         WERROR werror;
   10801             : 
   10802           0 :         if (!Printer) {
   10803           0 :                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
   10804             :                         OUR_HANDLE(r->in.handle)));
   10805           0 :                 return WERR_INVALID_HANDLE;
   10806             :         }
   10807             : 
   10808             :         /* Has to be a handle to the TCP/IP port monitor */
   10809             : 
   10810           0 :         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
   10811           0 :                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
   10812           0 :                 return WERR_INVALID_HANDLE;
   10813             :         }
   10814             : 
   10815             :         /* requires administrative access to the server */
   10816             : 
   10817           0 :         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
   10818           0 :                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
   10819           0 :                 return WERR_ACCESS_DENIED;
   10820             :         }
   10821             : 
   10822             :         /* Allocate the outgoing buffer */
   10823             : 
   10824           0 :         if (r->in.out_data_size) {
   10825           0 :                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
   10826           0 :                 if (out_data.data == NULL) {
   10827           0 :                         return WERR_NOT_ENOUGH_MEMORY;
   10828             :                 }
   10829             :         }
   10830             : 
   10831           0 :         switch ( Printer->printer_type ) {
   10832           0 :         case SPLHND_PORTMON_TCP:
   10833           0 :                 werror = process_xcvtcp_command(p->mem_ctx,
   10834             :                                                 session_info->security_token,
   10835             :                                                 r->in.function_name,
   10836             :                                                 &r->in.in_data, &out_data,
   10837             :                                                 r->out.needed);
   10838           0 :                 break;
   10839           0 :         case SPLHND_PORTMON_LOCAL:
   10840           0 :                 werror = process_xcvlocal_command(p->mem_ctx,
   10841             :                                                   session_info->security_token,
   10842             :                                                   r->in.function_name,
   10843             :                                                   &r->in.in_data, &out_data,
   10844             :                                                   r->out.needed);
   10845           0 :                 break;
   10846           0 :         default:
   10847           0 :                 werror = WERR_INVALID_PRINT_MONITOR;
   10848             :         }
   10849             : 
   10850           0 :         if (!W_ERROR_IS_OK(werror)) {
   10851           0 :                 return werror;
   10852             :         }
   10853             : 
   10854           0 :         *r->out.status_code = 0;
   10855             : 
   10856           0 :         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
   10857           0 :                 memcpy(r->out.out_data, out_data.data,
   10858           0 :                         MIN(r->in.out_data_size, out_data.length));
   10859             :         }
   10860             : 
   10861           0 :         return WERR_OK;
   10862             : }
   10863             : 
   10864             : /****************************************************************
   10865             :  _spoolss_AddPrintProcessor
   10866             : ****************************************************************/
   10867             : 
   10868           4 : WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
   10869             :                                   struct spoolss_AddPrintProcessor *r)
   10870             : {
   10871             :         /* for now, just indicate success and ignore the add.  We'll
   10872             :            automatically set the winprint processor for printer
   10873             :            entries later.  Used to debug the LexMark Optra S 1855 PCL
   10874             :            driver --jerry */
   10875             : 
   10876           4 :         return WERR_OK;
   10877             : }
   10878             : 
   10879             : /****************************************************************
   10880             :  _spoolss_AddPort
   10881             : ****************************************************************/
   10882             : 
   10883           4 : WERROR _spoolss_AddPort(struct pipes_struct *p,
   10884             :                         struct spoolss_AddPort *r)
   10885             : {
   10886             :         /* do what w2k3 does */
   10887             : 
   10888           4 :         return WERR_NOT_SUPPORTED;
   10889             : }
   10890             : 
   10891             : /****************************************************************
   10892             :  _spoolss_GetPrinterDriver
   10893             : ****************************************************************/
   10894             : 
   10895           0 : WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
   10896             :                                  struct spoolss_GetPrinterDriver *r)
   10897             : {
   10898           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10899           0 :         return WERR_NOT_SUPPORTED;
   10900             : }
   10901             : 
   10902             : /****************************************************************
   10903             :  _spoolss_ReadPrinter
   10904             : ****************************************************************/
   10905             : 
   10906           0 : WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
   10907             :                             struct spoolss_ReadPrinter *r)
   10908             : {
   10909           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10910           0 :         return WERR_NOT_SUPPORTED;
   10911             : }
   10912             : 
   10913             : /****************************************************************
   10914             :  _spoolss_WaitForPrinterChange
   10915             : ****************************************************************/
   10916             : 
   10917           0 : WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
   10918             :                                      struct spoolss_WaitForPrinterChange *r)
   10919             : {
   10920           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10921           0 :         return WERR_NOT_SUPPORTED;
   10922             : }
   10923             : 
   10924             : /****************************************************************
   10925             :  _spoolss_ConfigurePort
   10926             : ****************************************************************/
   10927             : 
   10928           0 : WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
   10929             :                               struct spoolss_ConfigurePort *r)
   10930             : {
   10931           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10932           0 :         return WERR_NOT_SUPPORTED;
   10933             : }
   10934             : 
   10935             : /****************************************************************
   10936             :  _spoolss_DeletePort
   10937             : ****************************************************************/
   10938             : 
   10939           0 : WERROR _spoolss_DeletePort(struct pipes_struct *p,
   10940             :                            struct spoolss_DeletePort *r)
   10941             : {
   10942           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10943           0 :         return WERR_NOT_SUPPORTED;
   10944             : }
   10945             : 
   10946             : /****************************************************************
   10947             :  _spoolss_CreatePrinterIC
   10948             : ****************************************************************/
   10949             : 
   10950           0 : WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
   10951             :                                 struct spoolss_CreatePrinterIC *r)
   10952             : {
   10953           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10954           0 :         return WERR_NOT_SUPPORTED;
   10955             : }
   10956             : 
   10957             : /****************************************************************
   10958             :  _spoolss_PlayGDIScriptOnPrinterIC
   10959             : ****************************************************************/
   10960             : 
   10961           0 : WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
   10962             :                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
   10963             : {
   10964           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10965           0 :         return WERR_NOT_SUPPORTED;
   10966             : }
   10967             : 
   10968             : /****************************************************************
   10969             :  _spoolss_DeletePrinterIC
   10970             : ****************************************************************/
   10971             : 
   10972           0 : WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
   10973             :                                 struct spoolss_DeletePrinterIC *r)
   10974             : {
   10975           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10976           0 :         return WERR_NOT_SUPPORTED;
   10977             : }
   10978             : 
   10979             : /****************************************************************
   10980             :  _spoolss_AddPrinterConnection
   10981             : ****************************************************************/
   10982             : 
   10983           0 : WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
   10984             :                                      struct spoolss_AddPrinterConnection *r)
   10985             : {
   10986           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10987           0 :         return WERR_NOT_SUPPORTED;
   10988             : }
   10989             : 
   10990             : /****************************************************************
   10991             :  _spoolss_DeletePrinterConnection
   10992             : ****************************************************************/
   10993             : 
   10994           0 : WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
   10995             :                                         struct spoolss_DeletePrinterConnection *r)
   10996             : {
   10997           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10998           0 :         return WERR_NOT_SUPPORTED;
   10999             : }
   11000             : 
   11001             : /****************************************************************
   11002             :  _spoolss_PrinterMessageBox
   11003             : ****************************************************************/
   11004             : 
   11005           0 : WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
   11006             :                                   struct spoolss_PrinterMessageBox *r)
   11007             : {
   11008           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11009           0 :         return WERR_NOT_SUPPORTED;
   11010             : }
   11011             : 
   11012             : /****************************************************************
   11013             :  _spoolss_AddMonitor
   11014             : ****************************************************************/
   11015             : 
   11016           0 : WERROR _spoolss_AddMonitor(struct pipes_struct *p,
   11017             :                            struct spoolss_AddMonitor *r)
   11018             : {
   11019           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11020           0 :         return WERR_NOT_SUPPORTED;
   11021             : }
   11022             : 
   11023             : /****************************************************************
   11024             :  _spoolss_DeleteMonitor
   11025             : ****************************************************************/
   11026             : 
   11027           0 : WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
   11028             :                               struct spoolss_DeleteMonitor *r)
   11029             : {
   11030           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11031           0 :         return WERR_NOT_SUPPORTED;
   11032             : }
   11033             : 
   11034             : /****************************************************************
   11035             :  _spoolss_DeletePrintProcessor
   11036             : ****************************************************************/
   11037             : 
   11038           0 : WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
   11039             :                                      struct spoolss_DeletePrintProcessor *r)
   11040             : {
   11041           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11042           0 :         return WERR_NOT_SUPPORTED;
   11043             : }
   11044             : 
   11045             : /****************************************************************
   11046             :  _spoolss_AddPrintProvidor
   11047             : ****************************************************************/
   11048             : 
   11049           0 : WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
   11050             :                                  struct spoolss_AddPrintProvidor *r)
   11051             : {
   11052           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11053           0 :         return WERR_NOT_SUPPORTED;
   11054             : }
   11055             : 
   11056             : /****************************************************************
   11057             :  _spoolss_DeletePrintProvidor
   11058             : ****************************************************************/
   11059             : 
   11060           0 : WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
   11061             :                                     struct spoolss_DeletePrintProvidor *r)
   11062             : {
   11063           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11064           0 :         return WERR_NOT_SUPPORTED;
   11065             : }
   11066             : 
   11067             : /****************************************************************
   11068             :  _spoolss_FindFirstPrinterChangeNotification
   11069             : ****************************************************************/
   11070             : 
   11071           0 : WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
   11072             :                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
   11073             : {
   11074           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11075           0 :         return WERR_NOT_SUPPORTED;
   11076             : }
   11077             : 
   11078             : /****************************************************************
   11079             :  _spoolss_FindNextPrinterChangeNotification
   11080             : ****************************************************************/
   11081             : 
   11082           0 : WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
   11083             :                                                   struct spoolss_FindNextPrinterChangeNotification *r)
   11084             : {
   11085           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11086           0 :         return WERR_NOT_SUPPORTED;
   11087             : }
   11088             : 
   11089             : /****************************************************************
   11090             :  _spoolss_RouterFindFirstPrinterChangeNotificationOld
   11091             : ****************************************************************/
   11092             : 
   11093           0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
   11094             :                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
   11095             : {
   11096           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11097           0 :         return WERR_NOT_SUPPORTED;
   11098             : }
   11099             : 
   11100             : /****************************************************************
   11101             :  _spoolss_ReplyOpenPrinter
   11102             : ****************************************************************/
   11103             : 
   11104           0 : WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
   11105             :                                  struct spoolss_ReplyOpenPrinter *r)
   11106             : {
   11107           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11108           0 :         return WERR_NOT_SUPPORTED;
   11109             : }
   11110             : 
   11111             : /****************************************************************
   11112             :  _spoolss_RouterReplyPrinter
   11113             : ****************************************************************/
   11114             : 
   11115           0 : WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
   11116             :                                    struct spoolss_RouterReplyPrinter *r)
   11117             : {
   11118           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11119           0 :         return WERR_NOT_SUPPORTED;
   11120             : }
   11121             : 
   11122             : /****************************************************************
   11123             :  _spoolss_ReplyClosePrinter
   11124             : ****************************************************************/
   11125             : 
   11126           0 : WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
   11127             :                                   struct spoolss_ReplyClosePrinter *r)
   11128             : {
   11129           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11130           0 :         return WERR_NOT_SUPPORTED;
   11131             : }
   11132             : 
   11133             : /****************************************************************
   11134             :  _spoolss_AddPortEx
   11135             : ****************************************************************/
   11136             : 
   11137           0 : WERROR _spoolss_AddPortEx(struct pipes_struct *p,
   11138             :                           struct spoolss_AddPortEx *r)
   11139             : {
   11140           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11141           0 :         return WERR_NOT_SUPPORTED;
   11142             : }
   11143             : 
   11144             : /****************************************************************
   11145             :  _spoolss_RouterFindFirstPrinterChangeNotification
   11146             : ****************************************************************/
   11147             : 
   11148           0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
   11149             :                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
   11150             : {
   11151           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11152           0 :         return WERR_NOT_SUPPORTED;
   11153             : }
   11154             : 
   11155             : /****************************************************************
   11156             :  _spoolss_SpoolerInit
   11157             : ****************************************************************/
   11158             : 
   11159           0 : WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
   11160             :                             struct spoolss_SpoolerInit *r)
   11161             : {
   11162           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11163           0 :         return WERR_NOT_SUPPORTED;
   11164             : }
   11165             : 
   11166             : /****************************************************************
   11167             :  _spoolss_ResetPrinterEx
   11168             : ****************************************************************/
   11169             : 
   11170           0 : WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
   11171             :                                struct spoolss_ResetPrinterEx *r)
   11172             : {
   11173           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11174           0 :         return WERR_NOT_SUPPORTED;
   11175             : }
   11176             : 
   11177             : /****************************************************************
   11178             :  _spoolss_RouterReplyPrinterEx
   11179             : ****************************************************************/
   11180             : 
   11181           0 : WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
   11182             :                                      struct spoolss_RouterReplyPrinterEx *r)
   11183             : {
   11184           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11185           0 :         return WERR_NOT_SUPPORTED;
   11186             : }
   11187             : 
   11188             : /****************************************************************
   11189             :  _spoolss_44
   11190             : ****************************************************************/
   11191             : 
   11192           0 : WERROR _spoolss_44(struct pipes_struct *p,
   11193             :                    struct spoolss_44 *r)
   11194             : {
   11195           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11196           0 :         return WERR_NOT_SUPPORTED;
   11197             : }
   11198             : 
   11199             : /****************************************************************
   11200             :  _spoolss_SetPort
   11201             : ****************************************************************/
   11202             : 
   11203           0 : WERROR _spoolss_SetPort(struct pipes_struct *p,
   11204             :                         struct spoolss_SetPort *r)
   11205             : {
   11206           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11207           0 :         return WERR_NOT_SUPPORTED;
   11208             : }
   11209             : 
   11210             : /****************************************************************
   11211             :  _spoolss_4a
   11212             : ****************************************************************/
   11213             : 
   11214           0 : WERROR _spoolss_4a(struct pipes_struct *p,
   11215             :                    struct spoolss_4a *r)
   11216             : {
   11217           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11218           0 :         return WERR_NOT_SUPPORTED;
   11219             : }
   11220             : 
   11221             : /****************************************************************
   11222             :  _spoolss_4b
   11223             : ****************************************************************/
   11224             : 
   11225           0 : WERROR _spoolss_4b(struct pipes_struct *p,
   11226             :                    struct spoolss_4b *r)
   11227             : {
   11228           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11229           0 :         return WERR_NOT_SUPPORTED;
   11230             : }
   11231             : 
   11232             : /****************************************************************
   11233             :  _spoolss_4c
   11234             : ****************************************************************/
   11235             : 
   11236           0 : WERROR _spoolss_4c(struct pipes_struct *p,
   11237             :                    struct spoolss_4c *r)
   11238             : {
   11239           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11240           0 :         return WERR_NOT_SUPPORTED;
   11241             : }
   11242             : 
   11243             : /****************************************************************
   11244             :  _spoolss_53
   11245             : ****************************************************************/
   11246             : 
   11247           0 : WERROR _spoolss_53(struct pipes_struct *p,
   11248             :                    struct spoolss_53 *r)
   11249             : {
   11250           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11251           0 :         return WERR_NOT_SUPPORTED;
   11252             : }
   11253             : 
   11254             : /****************************************************************
   11255             :  _spoolss_AddPerMachineConnection
   11256             : ****************************************************************/
   11257             : 
   11258           4 : WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
   11259             :                                         struct spoolss_AddPerMachineConnection *r)
   11260             : {
   11261           4 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11262           4 :         return WERR_NOT_SUPPORTED;
   11263             : }
   11264             : 
   11265             : /****************************************************************
   11266             :  _spoolss_DeletePerMachineConnection
   11267             : ****************************************************************/
   11268             : 
   11269           0 : WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
   11270             :                                            struct spoolss_DeletePerMachineConnection *r)
   11271             : {
   11272           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11273           0 :         return WERR_NOT_SUPPORTED;
   11274             : }
   11275             : 
   11276             : /****************************************************************
   11277             :  _spoolss_EnumPerMachineConnections
   11278             : ****************************************************************/
   11279             : 
   11280           0 : WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
   11281             :                                           struct spoolss_EnumPerMachineConnections *r)
   11282             : {
   11283           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11284           0 :         return WERR_NOT_SUPPORTED;
   11285             : }
   11286             : 
   11287             : /****************************************************************
   11288             :  _spoolss_5a
   11289             : ****************************************************************/
   11290             : 
   11291           0 : WERROR _spoolss_5a(struct pipes_struct *p,
   11292             :                    struct spoolss_5a *r)
   11293             : {
   11294           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11295           0 :         return WERR_NOT_SUPPORTED;
   11296             : }
   11297             : 
   11298             : /****************************************************************
   11299             :  _spoolss_5b
   11300             : ****************************************************************/
   11301             : 
   11302           0 : WERROR _spoolss_5b(struct pipes_struct *p,
   11303             :                    struct spoolss_5b *r)
   11304             : {
   11305           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11306           0 :         return WERR_NOT_SUPPORTED;
   11307             : }
   11308             : 
   11309             : /****************************************************************
   11310             :  _spoolss_5c
   11311             : ****************************************************************/
   11312             : 
   11313           0 : WERROR _spoolss_5c(struct pipes_struct *p,
   11314             :                    struct spoolss_5c *r)
   11315             : {
   11316           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11317           0 :         return WERR_NOT_SUPPORTED;
   11318             : }
   11319             : 
   11320             : /****************************************************************
   11321             :  _spoolss_5d
   11322             : ****************************************************************/
   11323             : 
   11324           0 : WERROR _spoolss_5d(struct pipes_struct *p,
   11325             :                    struct spoolss_5d *r)
   11326             : {
   11327           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11328           0 :         return WERR_NOT_SUPPORTED;
   11329             : }
   11330             : 
   11331             : /****************************************************************
   11332             :  _spoolss_5e
   11333             : ****************************************************************/
   11334             : 
   11335           0 : WERROR _spoolss_5e(struct pipes_struct *p,
   11336             :                    struct spoolss_5e *r)
   11337             : {
   11338           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11339           0 :         return WERR_NOT_SUPPORTED;
   11340             : }
   11341             : 
   11342             : /****************************************************************
   11343             :  _spoolss_5f
   11344             : ****************************************************************/
   11345             : 
   11346           0 : WERROR _spoolss_5f(struct pipes_struct *p,
   11347             :                    struct spoolss_5f *r)
   11348             : {
   11349           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11350           0 :         return WERR_NOT_SUPPORTED;
   11351             : }
   11352             : 
   11353             : /****************************************************************
   11354             :  _spoolss_60
   11355             : ****************************************************************/
   11356             : 
   11357           0 : WERROR _spoolss_60(struct pipes_struct *p,
   11358             :                    struct spoolss_60 *r)
   11359             : {
   11360           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11361           0 :         return WERR_NOT_SUPPORTED;
   11362             : }
   11363             : 
   11364             : /****************************************************************
   11365             :  _spoolss_SendRecvBidiData
   11366             : ****************************************************************/
   11367             : 
   11368           0 : WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
   11369             :                                  struct spoolss_SendRecvBidiData *r)
   11370             : {
   11371           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11372           0 :         return WERR_NOT_SUPPORTED;
   11373             : }
   11374             : 
   11375             : /****************************************************************
   11376             :  _spoolss_62
   11377             : ****************************************************************/
   11378             : 
   11379           0 : WERROR _spoolss_62(struct pipes_struct *p,
   11380             :                    struct spoolss_62 *r)
   11381             : {
   11382           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11383           0 :         return WERR_NOT_SUPPORTED;
   11384             : }
   11385             : 
   11386             : /****************************************************************
   11387             :  _spoolss_63
   11388             : ****************************************************************/
   11389             : 
   11390           0 : WERROR _spoolss_63(struct pipes_struct *p,
   11391             :                    struct spoolss_63 *r)
   11392             : {
   11393           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11394           0 :         return WERR_NOT_SUPPORTED;
   11395             : }
   11396             : 
   11397             : /****************************************************************
   11398             :  _spoolss_64
   11399             : ****************************************************************/
   11400             : 
   11401           0 : WERROR _spoolss_64(struct pipes_struct *p,
   11402             :                    struct spoolss_64 *r)
   11403             : {
   11404           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11405           0 :         return WERR_NOT_SUPPORTED;
   11406             : }
   11407             : 
   11408             : /****************************************************************
   11409             :  _spoolss_65
   11410             : ****************************************************************/
   11411             : 
   11412           0 : WERROR _spoolss_65(struct pipes_struct *p,
   11413             :                    struct spoolss_65 *r)
   11414             : {
   11415           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11416           0 :         return WERR_NOT_SUPPORTED;
   11417             : }
   11418             : 
   11419             : /****************************************************************
   11420             :  _spoolss_GetCorePrinterDrivers
   11421             : ****************************************************************/
   11422             : 
   11423           8 : HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
   11424             :                                        struct spoolss_GetCorePrinterDrivers *r)
   11425             : {
   11426           8 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11427           8 :         return HRES_ERROR_NOT_SUPPORTED;
   11428             : }
   11429             : 
   11430             : /****************************************************************
   11431             :  _spoolss_67
   11432             : ****************************************************************/
   11433             : 
   11434           0 : WERROR _spoolss_67(struct pipes_struct *p,
   11435             :                    struct spoolss_67 *r)
   11436             : {
   11437           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11438           0 :         return WERR_NOT_SUPPORTED;
   11439             : }
   11440             : 
   11441             : /****************************************************************
   11442             :  _spoolss_GetPrinterDriverPackagePath
   11443             : ****************************************************************/
   11444             : 
   11445           4 : HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
   11446             :                                              struct spoolss_GetPrinterDriverPackagePath *r)
   11447             : {
   11448           4 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11449           4 :         return HRES_ERROR_NOT_SUPPORTED;
   11450             : }
   11451             : 
   11452             : /****************************************************************
   11453             :  _spoolss_69
   11454             : ****************************************************************/
   11455             : 
   11456           0 : WERROR _spoolss_69(struct pipes_struct *p,
   11457             :                    struct spoolss_69 *r)
   11458             : {
   11459           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11460           0 :         return WERR_NOT_SUPPORTED;
   11461             : }
   11462             : 
   11463             : /****************************************************************
   11464             :  _spoolss_6a
   11465             : ****************************************************************/
   11466             : 
   11467           0 : WERROR _spoolss_6a(struct pipes_struct *p,
   11468             :                    struct spoolss_6a *r)
   11469             : {
   11470           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11471           0 :         return WERR_NOT_SUPPORTED;
   11472             : }
   11473             : 
   11474             : /****************************************************************
   11475             :  _spoolss_6b
   11476             : ****************************************************************/
   11477             : 
   11478           0 : WERROR _spoolss_6b(struct pipes_struct *p,
   11479             :                    struct spoolss_6b *r)
   11480             : {
   11481           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11482           0 :         return WERR_NOT_SUPPORTED;
   11483             : }
   11484             : 
   11485             : /****************************************************************
   11486             :  _spoolss_6c
   11487             : ****************************************************************/
   11488             : 
   11489           0 : WERROR _spoolss_6c(struct pipes_struct *p,
   11490             :                    struct spoolss_6c *r)
   11491             : {
   11492           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11493           0 :         return WERR_NOT_SUPPORTED;
   11494             : }
   11495             : 
   11496             : /****************************************************************
   11497             :  _spoolss_6d
   11498             : ****************************************************************/
   11499             : 
   11500           0 : WERROR _spoolss_6d(struct pipes_struct *p,
   11501             :                    struct spoolss_6d *r)
   11502             : {
   11503           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11504           0 :         return WERR_NOT_SUPPORTED;
   11505             : }
   11506             : 
   11507             : /****************************************************************
   11508             :  _spoolss_GetJobNamedPropertyValue
   11509             : ****************************************************************/
   11510             : 
   11511           0 : WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
   11512             :                                          struct spoolss_GetJobNamedPropertyValue *r)
   11513             : {
   11514           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11515           0 :         return WERR_NOT_SUPPORTED;
   11516             : }
   11517             : 
   11518             : /****************************************************************
   11519             :  _spoolss_SetJobNamedProperty
   11520             : ****************************************************************/
   11521             : 
   11522           0 : WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
   11523             :                                     struct spoolss_SetJobNamedProperty *r)
   11524             : {
   11525           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11526           0 :         return WERR_NOT_SUPPORTED;
   11527             : }
   11528             : 
   11529             : /****************************************************************
   11530             :  _spoolss_DeleteJobNamedProperty
   11531             : ****************************************************************/
   11532             : 
   11533           0 : WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
   11534             :                                        struct spoolss_DeleteJobNamedProperty *r)
   11535             : {
   11536           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11537           0 :         return WERR_NOT_SUPPORTED;
   11538             : }
   11539             : 
   11540             : /****************************************************************
   11541             :  _spoolss_EnumJobNamedProperties
   11542             : ****************************************************************/
   11543             : 
   11544           0 : WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
   11545             :                                        struct spoolss_EnumJobNamedProperties *r)
   11546             : {
   11547           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11548           0 :         return WERR_NOT_SUPPORTED;
   11549             : }
   11550             : 
   11551             : /****************************************************************
   11552             :  _spoolss_72
   11553             : ****************************************************************/
   11554             : 
   11555           0 : WERROR _spoolss_72(struct pipes_struct *p,
   11556             :                    struct spoolss_72 *r)
   11557             : {
   11558           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11559           0 :         return WERR_NOT_SUPPORTED;
   11560             : }
   11561             : 
   11562             : /****************************************************************
   11563             :  _spoolss_73
   11564             : ****************************************************************/
   11565             : 
   11566           0 : WERROR _spoolss_73(struct pipes_struct *p,
   11567             :                    struct spoolss_73 *r)
   11568             : {
   11569           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11570           0 :         return WERR_NOT_SUPPORTED;
   11571             : }
   11572             : 
   11573             : /****************************************************************
   11574             :  _spoolss_RpcLogJobInfoForBranchOffice
   11575             : ****************************************************************/
   11576             : 
   11577           8 : WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
   11578             :                                           struct spoolss_LogJobInfoForBranchOffice *r)
   11579             : {
   11580           8 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11581           8 :         return WERR_NOT_SUPPORTED;
   11582             : }
   11583             : 
   11584             : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
   11585             :                 const struct dcesrv_endpoint_server *ep_server);
   11586             : 
   11587             : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
   11588             :                 const struct dcesrv_endpoint_server *ep_server);
   11589             : 
   11590             : #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
   11591             :         spoolss_init_server
   11592             : 
   11593             : #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
   11594             :         spoolss_shutdown_server
   11595             : 
   11596          28 : static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
   11597             :                 const struct dcesrv_endpoint_server *ep_server)
   11598             : {
   11599          28 :         struct messaging_context *msg_ctx = global_messaging_context();
   11600           0 :         bool ok;
   11601             : 
   11602             :         /*
   11603             :          * Migrate the printers first.
   11604             :          */
   11605          28 :         ok = nt_printing_tdb_migrate(msg_ctx);
   11606          28 :         if (!ok) {
   11607           0 :                 return NT_STATUS_UNSUCCESSFUL;
   11608             :         }
   11609             : 
   11610          28 :         return spoolss__op_init_server(dce_ctx, ep_server);
   11611             : }
   11612             : 
   11613          28 : static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
   11614             :                 const struct dcesrv_endpoint_server *ep_server)
   11615             : {
   11616          28 :         srv_spoolss_cleanup();
   11617             : 
   11618          28 :         return spoolss__op_shutdown_server(dce_ctx, ep_server);
   11619             : }
   11620             : 
   11621             : /* include the generated boilerplate */
   11622             : #include "librpc/gen_ndr/ndr_spoolss_scompat.c"

Generated by: LCOV version 1.14