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 2f515e9b Lines: 2245 4837 46.4 %
Date: 2024-04-21 15:09:00 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 "lib/util/util_file.h"
      32             : #include "libsmb/namequery.h"
      33             : #include "ntdomain.h"
      34             : #include "nt_printing.h"
      35             : #include "srv_spoolss_util.h"
      36             : #include "librpc/gen_ndr/ndr_spoolss.h"
      37             : #include "librpc/gen_ndr/ndr_spoolss_scompat.h"
      38             : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
      39             : #include "rpc_client/init_spoolss.h"
      40             : #include "rpc_client/cli_pipe.h"
      41             : #include "../libcli/security/security.h"
      42             : #include "librpc/gen_ndr/ndr_security.h"
      43             : #include "registry.h"
      44             : #include "include/printing.h"
      45             : #include "secrets.h"
      46             : #include "../librpc/gen_ndr/netlogon.h"
      47             : #include "rpc_misc.h"
      48             : #include "printing/notify.h"
      49             : #include "serverid.h"
      50             : #include "../libcli/registry/util_reg.h"
      51             : #include "smbd/smbd.h"
      52             : #include "smbd/globals.h"
      53             : #include "auth.h"
      54             : #include "messages.h"
      55             : #include "rpc_server/spoolss/srv_spoolss_nt.h"
      56             : #include "util_tdb.h"
      57             : #include "libsmb/libsmb.h"
      58             : #include "printing/printer_list.h"
      59             : #include "../lib/tsocket/tsocket.h"
      60             : #include "rpc_client/cli_winreg_spoolss.h"
      61             : #include "../libcli/smb/smbXcli_base.h"
      62             : #include "rpc_server/spoolss/srv_spoolss_handle.h"
      63             : #include "lib/gencache.h"
      64             : #include "rpc_server/rpc_server.h"
      65             : #include "librpc/rpc/dcesrv_core.h"
      66             : #include "printing/nt_printing_migrate_internal.h"
      67             : #include "lib/util/string_wrappers.h"
      68             : #include "lib/global_contexts.h"
      69             : 
      70             : /* macros stolen from s4 spoolss server */
      71             : #define SPOOLSS_BUFFER_UNION(fn,info,level) \
      72             :         ((info)?ndr_size_##fn(info, level, 0):0)
      73             : 
      74             : #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
      75             :         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
      76             : 
      77             : #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
      78             :         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
      79             : 
      80             : #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
      81             : 
      82             : #undef DBGC_CLASS
      83             : #define DBGC_CLASS DBGC_RPC_SRV
      84             : 
      85             : #ifndef MAX_OPEN_PRINTER_EXS
      86             : #define MAX_OPEN_PRINTER_EXS 50
      87             : #endif
      88             : 
      89             : #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
      90             : #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
      91             : #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
      92             : #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
      93             : 
      94             : static struct printer_handle *printers_list;
      95             : 
      96             : struct printer_session_counter {
      97             :         struct printer_session_counter *next;
      98             :         struct printer_session_counter *prev;
      99             : 
     100             :         int snum;
     101             :         uint32_t counter;
     102             : };
     103             : 
     104             : static struct printer_session_counter *counter_list;
     105             : 
     106             : struct notify_back_channel {
     107             :         struct notify_back_channel *prev, *next;
     108             : 
     109             :         /* associated client */
     110             :         struct sockaddr_storage client_address;
     111             : 
     112             :         /* print notify back-channel pipe handle*/
     113             :         struct rpc_pipe_client *cli_pipe;
     114             :         struct cli_state *cli;
     115             :         uint32_t active_connections;
     116             : };
     117             : 
     118             : static struct notify_back_channel *back_channels;
     119             : 
     120             : /* Map generic permissions to printer object specific permissions */
     121             : 
     122             : const struct standard_mapping printer_std_mapping = {
     123             :         PRINTER_READ,
     124             :         PRINTER_WRITE,
     125             :         PRINTER_EXECUTE,
     126             :         PRINTER_ALL_ACCESS
     127             : };
     128             : 
     129             : /* Map generic permissions to print server object specific permissions */
     130             : 
     131             : const struct standard_mapping printserver_std_mapping = {
     132             :         SERVER_READ,
     133             :         SERVER_WRITE,
     134             :         SERVER_EXECUTE,
     135             :         SERVER_ALL_ACCESS
     136             : };
     137             : 
     138             : /* API table for Xcv Monitor functions */
     139             : 
     140             : struct xcv_api_table {
     141             :         const char *name;
     142             :         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
     143             : };
     144             : 
     145             : static void prune_printername_cache(void);
     146             : 
     147             : /********************************************************************
     148             :  * Canonicalize servername.
     149             :  ********************************************************************/
     150             : 
     151         520 : static const char *canon_servername(const char *servername)
     152             : {
     153         520 :         const char *pservername = servername;
     154             : 
     155         520 :         if (servername == NULL) {
     156           0 :                 return "";
     157             :         }
     158             : 
     159        1568 :         while (*pservername == '\\') {
     160        1048 :                 pservername++;
     161             :         }
     162         520 :         return pservername;
     163             : }
     164             : 
     165             : /* translate between internal status numbers and NT status numbers */
     166         392 : static int nt_printj_status(int v)
     167             : {
     168         392 :         switch (v) {
     169         392 :         case LPQ_QUEUED:
     170         392 :                 return 0;
     171           0 :         case LPQ_PAUSED:
     172           0 :                 return JOB_STATUS_PAUSED;
     173           0 :         case LPQ_SPOOLING:
     174           0 :                 return JOB_STATUS_SPOOLING;
     175           0 :         case LPQ_PRINTING:
     176           0 :                 return JOB_STATUS_PRINTING;
     177           0 :         case LPQ_ERROR:
     178           0 :                 return JOB_STATUS_ERROR;
     179           0 :         case LPQ_DELETING:
     180           0 :                 return JOB_STATUS_DELETING;
     181           0 :         case LPQ_OFFLINE:
     182           0 :                 return JOB_STATUS_OFFLINE;
     183           0 :         case LPQ_PAPEROUT:
     184           0 :                 return JOB_STATUS_PAPEROUT;
     185           0 :         case LPQ_PRINTED:
     186           0 :                 return JOB_STATUS_PRINTED;
     187           0 :         case LPQ_DELETED:
     188           0 :                 return JOB_STATUS_DELETED;
     189           0 :         case LPQ_BLOCKED:
     190           0 :                 return JOB_STATUS_BLOCKED_DEVQ;
     191           0 :         case LPQ_USER_INTERVENTION:
     192           0 :                 return JOB_STATUS_USER_INTERVENTION;
     193             :         }
     194           0 :         return 0;
     195             : }
     196             : 
     197        1636 : static int nt_printq_status(int v)
     198             : {
     199        1636 :         switch (v) {
     200         236 :         case LPQ_PAUSED:
     201         236 :                 return PRINTER_STATUS_PAUSED;
     202        1400 :         case LPQ_QUEUED:
     203             :         case LPQ_SPOOLING:
     204             :         case LPQ_PRINTING:
     205        1400 :                 return 0;
     206             :         }
     207           0 :         return 0;
     208             : }
     209             : 
     210             : /***************************************************************************
     211             :  Disconnect from the client
     212             : ****************************************************************************/
     213             : 
     214           2 : static void srv_spoolss_replycloseprinter(int snum,
     215             :                                           struct printer_handle *prn_hnd)
     216             : {
     217           0 :         WERROR result;
     218           0 :         NTSTATUS status;
     219             : 
     220             :         /*
     221             :          * Tell the specific printing tdb we no longer want messages for this printer
     222             :          * by deregistering our PID.
     223             :          */
     224             : 
     225           2 :         if (!print_notify_deregister_pid(snum)) {
     226           0 :                 DEBUG(0, ("Failed to register our pid for printer %s\n",
     227             :                           lp_const_servicename(snum)));
     228             :         }
     229             : 
     230             :         /* weird if the test succeeds !!! */
     231           2 :         if (prn_hnd->notify.cli_chan == NULL ||
     232           2 :             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
     233           2 :             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
     234           2 :             prn_hnd->notify.cli_chan->active_connections == 0) {
     235           0 :                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
     236           0 :                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
     237           0 :                 TALLOC_FREE(prn_hnd->notify.cli_chan);
     238           0 :                 return;
     239             :         }
     240             : 
     241           2 :         status = dcerpc_spoolss_ReplyClosePrinter(
     242           2 :                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
     243             :                                         talloc_tos(),
     244             :                                         &prn_hnd->notify.cli_hnd,
     245             :                                         &result);
     246           2 :         if (!NT_STATUS_IS_OK(status)) {
     247           0 :                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
     248             :                           nt_errstr(status)));
     249           0 :                 result = ntstatus_to_werror(status);
     250           2 :         } else if (!W_ERROR_IS_OK(result)) {
     251           0 :                 DEBUG(0, ("reply_close_printer failed [%s].\n",
     252             :                           win_errstr(result)));
     253             :         }
     254             : 
     255             :         /* if it's the last connection, deconnect the IPC$ share */
     256           2 :         if (prn_hnd->notify.cli_chan->active_connections == 1) {
     257             : 
     258           2 :                 cli_shutdown(prn_hnd->notify.cli_chan->cli);
     259           2 :                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
     260           2 :                 TALLOC_FREE(prn_hnd->notify.cli_chan);
     261             : 
     262           2 :                 if (prn_hnd->notify.msg_ctx != NULL) {
     263           2 :                         messaging_deregister(prn_hnd->notify.msg_ctx,
     264             :                                              MSG_PRINTER_NOTIFY2, NULL);
     265             :                 }
     266             :         }
     267             : 
     268           2 :         if (prn_hnd->notify.cli_chan) {
     269           0 :                 prn_hnd->notify.cli_chan->active_connections--;
     270           0 :                 prn_hnd->notify.cli_chan = NULL;
     271             :         }
     272             : }
     273             : 
     274             : /****************************************************************************
     275             :  Functions to free a printer entry datastruct.
     276             : ****************************************************************************/
     277             : 
     278         972 : static int printer_entry_destructor(struct printer_handle *Printer)
     279             : {
     280         972 :         if (Printer->notify.cli_chan != NULL &&
     281           2 :             Printer->notify.cli_chan->active_connections > 0) {
     282           2 :                 int snum = -1;
     283             : 
     284           2 :                 switch(Printer->printer_type) {
     285           2 :                 case SPLHND_SERVER:
     286           2 :                         srv_spoolss_replycloseprinter(snum, Printer);
     287           2 :                         break;
     288             : 
     289           0 :                 case SPLHND_PRINTER:
     290           0 :                         snum = print_queue_snum(Printer->sharename);
     291           0 :                         if (snum != -1) {
     292           0 :                                 srv_spoolss_replycloseprinter(snum, Printer);
     293             :                         }
     294           0 :                         break;
     295           0 :                 default:
     296           0 :                         break;
     297             :                 }
     298             :         }
     299             : 
     300         972 :         Printer->notify.flags=0;
     301         972 :         Printer->notify.options=0;
     302         972 :         Printer->notify.localmachine[0]='\0';
     303         972 :         Printer->notify.printerlocal=0;
     304         972 :         TALLOC_FREE(Printer->notify.option);
     305         972 :         TALLOC_FREE(Printer->devmode);
     306             : 
     307             :         /* Remove from the internal list. */
     308         972 :         DLIST_REMOVE(printers_list, Printer);
     309         972 :         return 0;
     310             : }
     311             : 
     312             : /****************************************************************************
     313             :   find printer index by handle
     314             : ****************************************************************************/
     315             : 
     316       52178 : static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
     317             :                                                         struct policy_handle *hnd)
     318             : {
     319       52178 :         struct printer_handle *find_printer = NULL;
     320           0 :         NTSTATUS status;
     321             : 
     322       52178 :         find_printer = find_policy_by_hnd(p,
     323             :                                           hnd,
     324             :                                           DCESRV_HANDLE_ANY,
     325             :                                           struct printer_handle,
     326           0 :                                           &status);
     327       52178 :         if (!NT_STATUS_IS_OK(status)) {
     328           0 :                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: %s\n",
     329             :                          nt_errstr(status)));
     330           0 :                 return NULL;
     331             :         }
     332             : 
     333       52178 :         return find_printer;
     334             : }
     335             : 
     336             : /****************************************************************************
     337             :  Close printer index by handle.
     338             : ****************************************************************************/
     339             : 
     340         956 : static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
     341             : {
     342         956 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     343             : 
     344         956 :         if (!Printer) {
     345           0 :                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
     346             :                         OUR_HANDLE(hnd)));
     347           0 :                 return false;
     348             :         }
     349             : 
     350         956 :         close_policy_hnd(p, hnd);
     351             : 
     352         956 :         return true;
     353             : }
     354             : 
     355             : /****************************************************************************
     356             :  Delete a printer given a handle.
     357             : ****************************************************************************/
     358             : 
     359          16 : static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
     360             :                                   const char *sharename,
     361             :                                   struct messaging_context *msg_ctx)
     362             : {
     363           0 :         const struct loadparm_substitution *lp_sub =
     364          16 :                 loadparm_s3_global_substitution();
     365          16 :         char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
     366          16 :         char *command = NULL;
     367           0 :         int ret;
     368          16 :         bool is_print_op = false;
     369             : 
     370             :         /* can't fail if we don't try */
     371             : 
     372          16 :         if ( !*cmd )
     373           0 :                 return WERR_OK;
     374             : 
     375          16 :         command = talloc_asprintf(ctx,
     376             :                         "%s \"%s\"",
     377             :                         cmd, sharename);
     378          16 :         if (!command) {
     379           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     380             :         }
     381          16 :         if ( token )
     382          16 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
     383             : 
     384          16 :         DEBUG(10,("Running [%s]\n", command));
     385             : 
     386             :         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
     387             : 
     388          16 :         if ( is_print_op )
     389           0 :                 become_root();
     390             : 
     391          16 :         ret = smbrun(command, NULL, NULL);
     392          16 :         if (ret == 0) {
     393             :                 /* Tell everyone we updated smb.conf. */
     394          16 :                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
     395             :         }
     396             : 
     397          16 :         if ( is_print_op )
     398           0 :                 unbecome_root();
     399             : 
     400             :         /********** END SePrintOperatorPrivlege BLOCK **********/
     401             : 
     402          16 :         DEBUGADD(10,("returned [%d]\n", ret));
     403             : 
     404          16 :         TALLOC_FREE(command);
     405             : 
     406          16 :         if (ret != 0)
     407           0 :                 return WERR_INVALID_HANDLE; /* What to return here? */
     408             : 
     409          16 :         return WERR_OK;
     410             : }
     411             : 
     412             : /****************************************************************************
     413             :  Delete a printer given a handle.
     414             : ****************************************************************************/
     415             : 
     416          16 : static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
     417             : {
     418          16 :         struct dcesrv_call_state *dce_call = p->dce_call;
     419           0 :         struct auth_session_info *session_info =
     420          16 :                 dcesrv_call_session_info(dce_call);
     421          16 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     422           0 :         WERROR result;
     423             : 
     424          16 :         if (!Printer) {
     425           0 :                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
     426             :                         OUR_HANDLE(hnd)));
     427           0 :                 return WERR_INVALID_HANDLE;
     428             :         }
     429             : 
     430             :         /*
     431             :          * It turns out that Windows allows delete printer on a handle
     432             :          * opened by an admin user, then used on a pipe handle created
     433             :          * by an anonymous user..... but they're working on security.... riiight !
     434             :          * JRA.
     435             :          */
     436             : 
     437          16 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
     438           0 :                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
     439           0 :                 return WERR_ACCESS_DENIED;
     440             :         }
     441             : 
     442             :         /* this does not need a become root since the access check has been
     443             :            done on the handle already */
     444             : 
     445          16 :         result = winreg_delete_printer_key_internal(p->mem_ctx,
     446             :                                            get_session_info_system(),
     447             :                                            p->msg_ctx,
     448          16 :                                            Printer->sharename,
     449             :                                            "");
     450          16 :         if (!W_ERROR_IS_OK(result)) {
     451           0 :                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
     452           0 :                 return WERR_INVALID_HANDLE;
     453             :         }
     454             : 
     455          16 :         result = delete_printer_hook(p->mem_ctx, session_info->security_token,
     456          16 :                                      Printer->sharename, p->msg_ctx);
     457          16 :         if (!W_ERROR_IS_OK(result)) {
     458           0 :                 return result;
     459             :         }
     460          16 :         prune_printername_cache();
     461          16 :         return WERR_OK;
     462             : }
     463             : 
     464             : /****************************************************************************
     465             :  Return the snum of a printer corresponding to an handle.
     466             : ****************************************************************************/
     467             : 
     468       24720 : static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
     469             :                              int *number, struct share_params **params)
     470             : {
     471       24720 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     472             : 
     473       24720 :         if (!Printer) {
     474           0 :                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
     475             :                         OUR_HANDLE(hnd)));
     476           0 :                 return false;
     477             :         }
     478             : 
     479       24720 :         switch (Printer->printer_type) {
     480       24720 :                 case SPLHND_PRINTER:
     481       24720 :                         DEBUG(4,("short name:%s\n", Printer->sharename));
     482       24720 :                         *number = print_queue_snum(Printer->sharename);
     483       24720 :                         return (*number != -1);
     484           0 :                 case SPLHND_SERVER:
     485           0 :                         return false;
     486           0 :                 default:
     487           0 :                         return false;
     488             :         }
     489             : }
     490             : 
     491             : /****************************************************************************
     492             :  Set printer handle type.
     493             :  Check if it's \\server or \\server\printer
     494             : ****************************************************************************/
     495             : 
     496         972 : static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
     497             : {
     498         972 :         DEBUG(3,("Setting printer type=%s\n", handlename));
     499             : 
     500             :         /* it's a print server */
     501         972 :         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
     502         122 :                 DEBUGADD(4,("Printer is a print server\n"));
     503         122 :                 Printer->printer_type = SPLHND_SERVER;
     504             :         }
     505             :         /* it's a printer (set_printer_hnd_name() will handle port monitors */
     506             :         else {
     507         850 :                 DEBUGADD(4,("Printer is a printer\n"));
     508         850 :                 Printer->printer_type = SPLHND_PRINTER;
     509             :         }
     510             : 
     511         972 :         return true;
     512             : }
     513             : 
     514         372 : static void prune_printername_cache_fn(const char *key, const char *value,
     515             :                                        time_t timeout, void *private_data)
     516             : {
     517         372 :         gencache_del(key);
     518         372 : }
     519             : 
     520         132 : static void prune_printername_cache(void)
     521             : {
     522         132 :         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
     523         132 : }
     524             : 
     525             : /****************************************************************************
     526             :  Set printer handle name..  Accept names like \\server, \\server\printer,
     527             :  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
     528             :  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
     529             :  XcvDataPort() interface.
     530             : ****************************************************************************/
     531             : 
     532         972 : static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
     533             :                                    const struct auth_session_info *session_info,
     534             :                                    struct messaging_context *msg_ctx,
     535             :                                    struct printer_handle *Printer,
     536             :                                    const char *handlename)
     537             : {
     538           0 :         int snum;
     539         972 :         int n_services=lp_numservices();
     540           0 :         char *aprinter;
     541           0 :         const char *printername;
     542         972 :         const char *servername = NULL;
     543           0 :         fstring sname;
     544         972 :         bool found = false;
     545         972 :         struct spoolss_PrinterInfo2 *info2 = NULL;
     546           0 :         WERROR result;
     547           0 :         char *p;
     548             : 
     549             :         /*
     550             :          * Hopefully nobody names his printers like this. Maybe \ or ,
     551             :          * are illegal in printer names even?
     552             :          */
     553         972 :         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
     554           0 :         char *cache_key;
     555           0 :         char *tmp;
     556             : 
     557         972 :         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
     558             :                 (unsigned long)strlen(handlename)));
     559             : 
     560         972 :         aprinter = discard_const_p(char, handlename);
     561         972 :         if ( *handlename == '\\' ) {
     562         252 :                 servername = canon_servername(handlename);
     563         252 :                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
     564         122 :                         *aprinter = '\0';
     565         122 :                         aprinter++;
     566             :                 }
     567         252 :                 if (!is_myname_or_ipaddr(servername)) {
     568          12 :                         return WERR_INVALID_PRINTER_NAME;
     569             :                 }
     570         240 :                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
     571         240 :                 if (Printer->servername == NULL) {
     572           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     573             :                 }
     574             :         }
     575             : 
     576         960 :         if (Printer->printer_type == SPLHND_SERVER) {
     577         118 :                 return WERR_OK;
     578             :         }
     579             : 
     580         842 :         if (Printer->printer_type != SPLHND_PRINTER) {
     581           0 :                 return WERR_INVALID_HANDLE;
     582             :         }
     583             : 
     584         842 :         DEBUGADD(5, ("searching for [%s]\n", aprinter));
     585             : 
     586         842 :         p = strchr(aprinter, ',');
     587         842 :         if (p != NULL) {
     588         504 :                 char *p2 = p;
     589         504 :                 p++;
     590         504 :                 if (*p == ' ') {
     591         308 :                         p++;
     592             :                 }
     593         504 :                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
     594         140 :                         *p2 = '\0';
     595         364 :                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
     596         140 :                         *p2 = '\0';
     597             :                 }
     598             :         }
     599             : 
     600         842 :         if (p) {
     601         504 :                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
     602             :         }
     603             : 
     604             :         /* check for the Port Monitor Interface */
     605         842 :         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
     606           0 :                 Printer->printer_type = SPLHND_PORTMON_TCP;
     607           0 :                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
     608           0 :                 found = true;
     609             :         }
     610         842 :         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
     611           0 :                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
     612           0 :                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
     613           0 :                 found = true;
     614             :         }
     615             : 
     616         842 :         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
     617         842 :         if (cache_key == NULL) {
     618           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     619             :         }
     620             : 
     621             :         /*
     622             :          * With hundreds of printers, the "for" loop iterating all
     623             :          * shares can be quite expensive, as it is done on every
     624             :          * OpenPrinter. The loop maps "aprinter" to "sname", the
     625             :          * result of which we cache in gencache.
     626             :          */
     627         842 :         if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
     628         462 :                 found = (strcmp(tmp, printer_not_found) != 0);
     629         462 :                 if (!found) {
     630          32 :                         DEBUG(4, ("Printer %s not found\n", aprinter));
     631          32 :                         TALLOC_FREE(tmp);
     632          32 :                         return WERR_INVALID_PRINTER_NAME;
     633             :                 }
     634         430 :                 fstrcpy(sname, tmp);
     635         430 :                 TALLOC_FREE(tmp);
     636             :         }
     637             : 
     638             :         /* Search all sharenames first as this is easier than pulling
     639             :            the printer_info_2 off of disk. Don't use find_service() since
     640             :            that calls out to map_username() */
     641             : 
     642             :         /* do another loop to look for printernames */
     643       23566 :         for (snum = 0; !found && snum < n_services; snum++) {
     644       22848 :                 const char *printer = lp_const_servicename(snum);
     645             : 
     646             :                 /* no point going on if this is not a printer */
     647       22848 :                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
     648       20970 :                         continue;
     649             :                 }
     650             : 
     651             :                 /* ignore [printers] share */
     652        1878 :                 if (strequal(printer, "printers")) {
     653           0 :                         continue;
     654             :                 }
     655             : 
     656        1878 :                 fstrcpy(sname, printer);
     657        1878 :                 if (strequal(aprinter, printer)) {
     658          84 :                         found = true;
     659          84 :                         break;
     660             :                 }
     661             : 
     662             :                 /* no point looking up the printer object if
     663             :                    we aren't allowing printername != sharename */
     664        1794 :                 if (lp_force_printername(snum)) {
     665           0 :                         continue;
     666             :                 }
     667             : 
     668        1794 :                 result = winreg_get_printer_internal(mem_ctx,
     669             :                                             session_info,
     670             :                                             msg_ctx,
     671             :                                             sname,
     672             :                                             &info2);
     673        1794 :                 if ( !W_ERROR_IS_OK(result) ) {
     674          54 :                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
     675             :                                  sname, win_errstr(result)));
     676          54 :                         continue;
     677             :                 }
     678             : 
     679        1740 :                 printername = strrchr(info2->printername, '\\');
     680        1740 :                 if (printername == NULL) {
     681        1740 :                         printername = info2->printername;
     682             :                 } else {
     683           0 :                         printername++;
     684             :                 }
     685             : 
     686        1740 :                 if (strequal(printername, aprinter)) {
     687           8 :                         found = true;
     688           8 :                         break;
     689             :                 }
     690             : 
     691        1732 :                 DEBUGADD(10, ("printername: %s\n", printername));
     692             : 
     693        1732 :                 TALLOC_FREE(info2);
     694             :         }
     695             : 
     696         810 :         if (!found) {
     697         288 :                 gencache_set(cache_key, printer_not_found,
     698         288 :                              time(NULL) + 300);
     699         288 :                 TALLOC_FREE(cache_key);
     700         288 :                 DEBUGADD(4,("Printer not found\n"));
     701         288 :                 return WERR_INVALID_PRINTER_NAME;
     702             :         }
     703             : 
     704         522 :         gencache_set(cache_key, sname, time(NULL) + 300);
     705         522 :         TALLOC_FREE(cache_key);
     706             : 
     707         522 :         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
     708             : 
     709         522 :         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
     710             : 
     711         522 :         return WERR_OK;
     712             : }
     713             : 
     714             : /****************************************************************************
     715             :  Find first available printer slot. creates a printer handle for you.
     716             :  ****************************************************************************/
     717             : 
     718         972 : static WERROR open_printer_hnd(struct pipes_struct *p,
     719             :                                struct policy_handle *hnd,
     720             :                                const char *name,
     721             :                                uint32_t access_granted)
     722             : {
     723           0 :         struct printer_handle *new_printer;
     724           0 :         WERROR result;
     725             : 
     726         972 :         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
     727             : 
     728         972 :         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
     729         972 :         if (new_printer == NULL) {
     730           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     731             :         }
     732         972 :         talloc_set_destructor(new_printer, printer_entry_destructor);
     733             : 
     734             :         /* This also steals the printer_handle on the policy_handle */
     735         972 :         if (!create_policy_hnd(p, hnd, 0, new_printer)) {
     736           0 :                 TALLOC_FREE(new_printer);
     737           0 :                 return WERR_INVALID_HANDLE;
     738             :         }
     739             : 
     740             :         /* Add to the internal list. */
     741         972 :         DLIST_ADD(printers_list, new_printer);
     742             : 
     743         972 :         new_printer->notify.option=NULL;
     744             : 
     745         972 :         if (!set_printer_hnd_printertype(new_printer, name)) {
     746           0 :                 close_printer_handle(p, hnd);
     747           0 :                 return WERR_INVALID_HANDLE;
     748             :         }
     749             : 
     750         972 :         result = set_printer_hnd_name(p->mem_ctx,
     751             :                                       get_session_info_system(),
     752             :                                       p->msg_ctx,
     753             :                                       new_printer, name);
     754         972 :         if (!W_ERROR_IS_OK(result)) {
     755         332 :                 close_printer_handle(p, hnd);
     756         332 :                 return result;
     757             :         }
     758             : 
     759         640 :         new_printer->access_granted = access_granted;
     760             : 
     761         640 :         DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
     762             : 
     763         640 :         return WERR_OK;
     764             : }
     765             : 
     766             : /***************************************************************************
     767             :  check to see if the client notify handle is monitoring the notification
     768             :  given by (notify_type, notify_field).
     769             :  **************************************************************************/
     770             : 
     771           0 : static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
     772             :                                       uint16_t notify_field)
     773             : {
     774           0 :         return true;
     775             : }
     776             : 
     777           0 : static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
     778             :                                 uint16_t notify_field)
     779             : {
     780           0 :         struct spoolss_NotifyOption *option = p->notify.option;
     781           0 :         uint32_t i, j;
     782             : 
     783             :         /*
     784             :          * Flags should always be zero when the change notify
     785             :          * is registered by the client's spooler.  A user Win32 app
     786             :          * might use the flags though instead of the NOTIFY_OPTION_INFO
     787             :          * --jerry
     788             :          */
     789             : 
     790           0 :         if (!option) {
     791           0 :                 return false;
     792             :         }
     793             : 
     794           0 :         if (p->notify.flags)
     795           0 :                 return is_monitoring_event_flags(
     796             :                         p->notify.flags, notify_type, notify_field);
     797             : 
     798           0 :         for (i = 0; i < option->count; i++) {
     799             : 
     800             :                 /* Check match for notify_type */
     801             : 
     802           0 :                 if (option->types[i].type != notify_type)
     803           0 :                         continue;
     804             : 
     805             :                 /* Check match for field */
     806             : 
     807           0 :                 for (j = 0; j < option->types[i].count; j++) {
     808           0 :                         if (option->types[i].fields[j].field == notify_field) {
     809           0 :                                 return true;
     810             :                         }
     811             :                 }
     812             :         }
     813             : 
     814           0 :         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
     815             :                    p->servername, p->sharename, notify_type, notify_field));
     816             : 
     817           0 :         return false;
     818             : }
     819             : 
     820             : #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
     821             :         _data->data.integer[0] = _integer; \
     822             :         _data->data.integer[1] = 0;
     823             : 
     824             : 
     825             : #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
     826             :         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
     827             :         if (!_data->data.string.string) {\
     828             :                 _data->data.string.size = 0; \
     829             :         } \
     830             :         _data->data.string.size = strlen_m_term(_p) * 2;
     831             : 
     832             : #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
     833             :         _data->data.devmode.devmode = _devmode;
     834             : 
     835           0 : static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
     836             :                                    struct tm *t,
     837             :                                    const char **pp,
     838             :                                    uint32_t *plen)
     839             : {
     840           0 :         struct spoolss_Time st;
     841           0 :         uint32_t len = 16;
     842           0 :         char *p;
     843             : 
     844           0 :         if (!init_systemtime(&st, t)) {
     845           0 :                 return;
     846             :         }
     847             : 
     848           0 :         p = talloc_array(mem_ctx, char, len);
     849           0 :         if (!p) {
     850           0 :                 return;
     851             :         }
     852             : 
     853             :         /*
     854             :          * Systemtime must be linearized as a set of UINT16's.
     855             :          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
     856             :          */
     857             : 
     858           0 :         SSVAL(p, 0, st.year);
     859           0 :         SSVAL(p, 2, st.month);
     860           0 :         SSVAL(p, 4, st.day_of_week);
     861           0 :         SSVAL(p, 6, st.day);
     862           0 :         SSVAL(p, 8, st.hour);
     863           0 :         SSVAL(p, 10, st.minute);
     864           0 :         SSVAL(p, 12, st.second);
     865           0 :         SSVAL(p, 14, st.millisecond);
     866             : 
     867           0 :         *pp = p;
     868           0 :         *plen = len;
     869             : }
     870             : 
     871             : /* Convert a notification message to a struct spoolss_Notify */
     872             : 
     873           0 : static void notify_one_value(struct spoolss_notify_msg *msg,
     874             :                              struct spoolss_Notify *data,
     875             :                              TALLOC_CTX *mem_ctx)
     876             : {
     877           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
     878           0 : }
     879             : 
     880           0 : static void notify_string(struct spoolss_notify_msg *msg,
     881             :                           struct spoolss_Notify *data,
     882             :                           TALLOC_CTX *mem_ctx)
     883             : {
     884             :         /* The length of the message includes the trailing \0 */
     885             : 
     886           0 :         data->data.string.size = msg->len * 2;
     887           0 :         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
     888           0 :         if (!data->data.string.string) {
     889           0 :                 data->data.string.size = 0;
     890           0 :                 return;
     891             :         }
     892             : }
     893             : 
     894           0 : static void notify_system_time(struct spoolss_notify_msg *msg,
     895             :                                struct spoolss_Notify *data,
     896             :                                TALLOC_CTX *mem_ctx)
     897             : {
     898           0 :         data->data.string.string = NULL;
     899           0 :         data->data.string.size = 0;
     900             : 
     901           0 :         if (msg->len != sizeof(time_t)) {
     902           0 :                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
     903             :                           msg->len));
     904           0 :                 return;
     905             :         }
     906             : 
     907           0 :         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
     908             :                                &data->data.string.string,
     909             :                                &data->data.string.size);
     910             : }
     911             : 
     912             : struct notify2_message_table {
     913             :         const char *name;
     914             :         void (*fn)(struct spoolss_notify_msg *msg,
     915             :                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
     916             : };
     917             : 
     918             : static struct notify2_message_table printer_notify_table[] = {
     919             :         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
     920             :         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
     921             :         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
     922             :         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
     923             :         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
     924             :         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
     925             :         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
     926             :         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
     927             :         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
     928             :         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
     929             :         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
     930             :         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
     931             :         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
     932             :         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
     933             :         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
     934             :         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
     935             :         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
     936             :         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
     937             :         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
     938             : };
     939             : 
     940             : static struct notify2_message_table job_notify_table[] = {
     941             :         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
     942             :         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
     943             :         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
     944             :         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
     945             :         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
     946             :         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
     947             :         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
     948             :         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
     949             :         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
     950             :         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
     951             :         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
     952             :         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
     953             :         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
     954             :         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
     955             :         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
     956             :         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
     957             :         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
     958             :         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
     959             :         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
     960             :         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
     961             :         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
     962             :         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
     963             :         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
     964             :         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
     965             : };
     966             : 
     967             : 
     968             : /***********************************************************************
     969             :  Allocate talloc context for container object
     970             :  **********************************************************************/
     971             : 
     972           0 : static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     973             : {
     974           0 :         if ( !ctr )
     975           0 :                 return;
     976             : 
     977           0 :         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
     978             : 
     979           0 :         return;
     980             : }
     981             : 
     982             : /***********************************************************************
     983             :  release all allocated memory and zero out structure
     984             :  **********************************************************************/
     985             : 
     986           0 : static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     987             : {
     988           0 :         if ( !ctr )
     989           0 :                 return;
     990             : 
     991           0 :         if ( ctr->ctx )
     992           0 :                 talloc_destroy(ctr->ctx);
     993             : 
     994           0 :         ZERO_STRUCTP(ctr);
     995             : 
     996           0 :         return;
     997             : }
     998             : 
     999             : /***********************************************************************
    1000             :  **********************************************************************/
    1001             : 
    1002           0 : static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
    1003             : {
    1004           0 :         if ( !ctr )
    1005           0 :                 return NULL;
    1006             : 
    1007           0 :         return ctr->ctx;
    1008             : }
    1009             : 
    1010             : /***********************************************************************
    1011             :  **********************************************************************/
    1012             : 
    1013           0 : static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
    1014             : {
    1015           0 :         if ( !ctr || !ctr->msg_groups )
    1016           0 :                 return NULL;
    1017             : 
    1018           0 :         if ( idx >= ctr->num_groups )
    1019           0 :                 return NULL;
    1020             : 
    1021           0 :         return &ctr->msg_groups[idx];
    1022             : 
    1023             : }
    1024             : 
    1025             : /***********************************************************************
    1026             :  How many groups of change messages do we have ?
    1027             :  **********************************************************************/
    1028             : 
    1029           0 : static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
    1030             : {
    1031           0 :         if ( !ctr )
    1032           0 :                 return 0;
    1033             : 
    1034           0 :         return ctr->num_groups;
    1035             : }
    1036             : 
    1037             : /***********************************************************************
    1038             :  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
    1039             :  **********************************************************************/
    1040             : 
    1041           0 : static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
    1042             : {
    1043           0 :         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
    1044           0 :         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
    1045           0 :         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
    1046           0 :         uint32_t                        i, new_slot;
    1047             : 
    1048           0 :         if ( !ctr || !msg )
    1049           0 :                 return 0;
    1050             : 
    1051             :         /* loop over all groups looking for a matching printer name */
    1052             : 
    1053           0 :         for ( i=0; i<ctr->num_groups; i++ ) {
    1054           0 :                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
    1055           0 :                         break;
    1056             :         }
    1057             : 
    1058             :         /* add a new group? */
    1059             : 
    1060           0 :         if ( i == ctr->num_groups ) {
    1061           0 :                 ctr->num_groups++;
    1062             : 
    1063           0 :                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
    1064           0 :                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
    1065           0 :                         return 0;
    1066             :                 }
    1067           0 :                 ctr->msg_groups = groups;
    1068             : 
    1069             :                 /* clear the new entry and set the printer name */
    1070             : 
    1071           0 :                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
    1072           0 :                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
    1073             :         }
    1074             : 
    1075             :         /* add the change messages; 'i' is the correct index now regardless */
    1076             : 
    1077           0 :         msg_grp = &ctr->msg_groups[i];
    1078             : 
    1079           0 :         msg_grp->num_msgs++;
    1080             : 
    1081           0 :         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
    1082           0 :                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
    1083           0 :                 return 0;
    1084             :         }
    1085           0 :         msg_grp->msgs = msg_list;
    1086             : 
    1087           0 :         new_slot = msg_grp->num_msgs-1;
    1088           0 :         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
    1089             : 
    1090             :         /* need to allocate own copy of data */
    1091             : 
    1092           0 :         if ( msg->len != 0 )
    1093           0 :                 msg_grp->msgs[new_slot].notify.data = (char *)
    1094           0 :                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
    1095             : 
    1096           0 :         return ctr->num_groups;
    1097             : }
    1098             : 
    1099             : static void construct_info_data(struct spoolss_Notify *info_data,
    1100             :                                 enum spoolss_NotifyType type,
    1101             :                                 uint16_t field, int id);
    1102             : 
    1103             : /***********************************************************************
    1104             :  Send a change notification message on all handles which have a call
    1105             :  back registered
    1106             :  **********************************************************************/
    1107             : 
    1108           0 : static int build_notify2_messages(TALLOC_CTX *mem_ctx,
    1109             :                                   struct printer_handle *prn_hnd,
    1110             :                                   SPOOLSS_NOTIFY_MSG *messages,
    1111             :                                   uint32_t num_msgs,
    1112             :                                   struct spoolss_Notify **_notifies,
    1113             :                                   size_t *_count)
    1114             : {
    1115           0 :         struct spoolss_Notify *notifies;
    1116           0 :         SPOOLSS_NOTIFY_MSG *msg;
    1117           0 :         size_t count = 0;
    1118           0 :         uint32_t id;
    1119           0 :         uint32_t i;
    1120             : 
    1121           0 :         notifies = talloc_zero_array(mem_ctx,
    1122             :                                      struct spoolss_Notify, num_msgs);
    1123           0 :         if (!notifies) {
    1124           0 :                 return ENOMEM;
    1125             :         }
    1126             : 
    1127           0 :         for (i = 0; i < num_msgs; i++) {
    1128             : 
    1129           0 :                 msg = &messages[i];
    1130             : 
    1131             :                 /* Are we monitoring this event? */
    1132             : 
    1133           0 :                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
    1134           0 :                         continue;
    1135             :                 }
    1136             : 
    1137           0 :                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
    1138             :                            "for printer [%s]\n",
    1139             :                            msg->type, msg->field, prn_hnd->sharename));
    1140             : 
    1141             :                 /*
    1142             :                  * if the is a printer notification handle and not a job
    1143             :                  * notification type, then set the id to 0.
    1144             :                  * Otherwise just use what was specified in the message.
    1145             :                  *
    1146             :                  * When registering change notification on a print server
    1147             :                  * handle we always need to send back the id (snum) matching
    1148             :                  * the printer for which the change took place.
    1149             :                  * For change notify registered on a printer handle,
    1150             :                  * this does not matter and the id should be 0.
    1151             :                  *
    1152             :                  * --jerry
    1153             :                  */
    1154             : 
    1155           0 :                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
    1156           0 :                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
    1157           0 :                         id = 0;
    1158             :                 } else {
    1159           0 :                         id = msg->id;
    1160             :                 }
    1161             : 
    1162             :                 /* Convert unix jobid to smb jobid */
    1163             : 
    1164           0 :                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
    1165           0 :                         id = sysjob_to_jobid(msg->id);
    1166             : 
    1167           0 :                         if (id == -1) {
    1168           0 :                                 DEBUG(3, ("no such unix jobid %d\n",
    1169             :                                           msg->id));
    1170           0 :                                 continue;
    1171             :                         }
    1172             :                 }
    1173             : 
    1174           0 :                 construct_info_data(&notifies[count],
    1175           0 :                                     msg->type, msg->field, id);
    1176             : 
    1177           0 :                 switch(msg->type) {
    1178           0 :                 case PRINTER_NOTIFY_TYPE:
    1179           0 :                         if (printer_notify_table[msg->field].fn) {
    1180           0 :                                 printer_notify_table[msg->field].fn(msg,
    1181           0 :                                                 &notifies[count], mem_ctx);
    1182             :                         }
    1183           0 :                         break;
    1184             : 
    1185           0 :                 case JOB_NOTIFY_TYPE:
    1186           0 :                         if (job_notify_table[msg->field].fn) {
    1187           0 :                                 job_notify_table[msg->field].fn(msg,
    1188           0 :                                                 &notifies[count], mem_ctx);
    1189             :                         }
    1190           0 :                         break;
    1191             : 
    1192           0 :                 default:
    1193           0 :                         DEBUG(5, ("Unknown notification type %d\n",
    1194             :                                   msg->type));
    1195           0 :                         continue;
    1196             :                 }
    1197             : 
    1198           0 :                 count++;
    1199             :         }
    1200             : 
    1201           0 :         *_notifies = notifies;
    1202           0 :         *_count = count;
    1203             : 
    1204           0 :         return 0;
    1205             : }
    1206             : 
    1207           0 : static int send_notify2_printer(TALLOC_CTX *mem_ctx,
    1208             :                                 struct printer_handle *prn_hnd,
    1209             :                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
    1210             : {
    1211           0 :         struct spoolss_Notify *notifies;
    1212           0 :         size_t count = 0;
    1213           0 :         union spoolss_ReplyPrinterInfo info;
    1214           0 :         struct spoolss_NotifyInfo info0;
    1215           0 :         uint32_t reply_result;
    1216           0 :         NTSTATUS status;
    1217           0 :         WERROR werr;
    1218           0 :         int ret;
    1219             : 
    1220             :         /* Is there notification on this handle? */
    1221           0 :         if (prn_hnd->notify.cli_chan == NULL ||
    1222           0 :             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
    1223           0 :             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
    1224           0 :             prn_hnd->notify.cli_chan->active_connections == 0) {
    1225           0 :                 return 0;
    1226             :         }
    1227             : 
    1228           0 :         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
    1229             :                    prn_hnd->servername, prn_hnd->sharename));
    1230             : 
    1231             :         /* For this printer? Print servers always receive notifications. */
    1232           0 :         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
    1233           0 :             (!strequal(msg_group->printername, prn_hnd->sharename))) {
    1234           0 :                 return 0;
    1235             :         }
    1236             : 
    1237           0 :         DEBUG(10,("Our printer\n"));
    1238             : 
    1239             :         /* build the array of change notifications */
    1240           0 :         ret = build_notify2_messages(mem_ctx, prn_hnd,
    1241             :                                      msg_group->msgs,
    1242             :                                      msg_group->num_msgs,
    1243             :                                      &notifies, &count);
    1244           0 :         if (ret) {
    1245           0 :                 return ret;
    1246             :         }
    1247             : 
    1248           0 :         info0.version   = 0x2;
    1249           0 :         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
    1250           0 :         info0.count     = count;
    1251           0 :         info0.notifies  = notifies;
    1252             : 
    1253           0 :         info.info0 = &info0;
    1254             : 
    1255           0 :         status = dcerpc_spoolss_RouterReplyPrinterEx(
    1256           0 :                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
    1257             :                                 mem_ctx,
    1258             :                                 &prn_hnd->notify.cli_hnd,
    1259             :                                 prn_hnd->notify.change, /* color */
    1260             :                                 prn_hnd->notify.flags,
    1261             :                                 &reply_result,
    1262             :                                 0, /* reply_type, must be 0 */
    1263             :                                 info, &werr);
    1264           0 :         if (!NT_STATUS_IS_OK(status)) {
    1265           0 :                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
    1266             :                           "failed: %s\n",
    1267             :                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
    1268             :                           nt_errstr(status)));
    1269           0 :                 werr = ntstatus_to_werror(status);
    1270           0 :         } else if (!W_ERROR_IS_OK(werr)) {
    1271           0 :                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
    1272             :                           "failed: %s\n",
    1273             :                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
    1274             :                           win_errstr(werr)));
    1275             :         }
    1276           0 :         switch (reply_result) {
    1277           0 :         case 0:
    1278           0 :                 break;
    1279           0 :         case PRINTER_NOTIFY_INFO_DISCARDED:
    1280             :         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
    1281             :         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
    1282           0 :                 break;
    1283           0 :         default:
    1284           0 :                 break;
    1285             :         }
    1286             : 
    1287           0 :         return 0;
    1288             : }
    1289             : 
    1290           0 : static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
    1291             : {
    1292           0 :         struct printer_handle    *p;
    1293           0 :         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
    1294           0 :         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
    1295           0 :         int ret;
    1296             : 
    1297           0 :         if ( !msg_group ) {
    1298           0 :                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
    1299           0 :                 return;
    1300             :         }
    1301             : 
    1302           0 :         if (!msg_group->msgs) {
    1303           0 :                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
    1304           0 :                 return;
    1305             :         }
    1306             : 
    1307           0 :         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
    1308             : 
    1309             :         /* loop over all printers */
    1310             : 
    1311           0 :         for (p = printers_list; p; p = p->next) {
    1312           0 :                 ret = send_notify2_printer(mem_ctx, p, msg_group);
    1313           0 :                 if (ret) {
    1314           0 :                         goto done;
    1315             :                 }
    1316             :         }
    1317             : 
    1318           0 : done:
    1319           0 :         DEBUG(8,("send_notify2_changes: Exit...\n"));
    1320           0 :         return;
    1321             : }
    1322             : 
    1323             : /***********************************************************************
    1324             :  **********************************************************************/
    1325             : 
    1326           0 : static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
    1327             : {
    1328             : 
    1329           0 :         uint32_t tv_sec, tv_usec;
    1330           0 :         size_t offset = 0;
    1331             : 
    1332             :         /* Unpack message */
    1333             : 
    1334           0 :         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
    1335           0 :                              msg->printer);
    1336             : 
    1337           0 :         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
    1338             :                                 &tv_sec, &tv_usec,
    1339             :                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
    1340             : 
    1341           0 :         if (msg->len == 0)
    1342           0 :                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
    1343             :                            &msg->notify.value[0], &msg->notify.value[1]);
    1344             :         else
    1345           0 :                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
    1346             :                            &msg->len, &msg->notify.data);
    1347             : 
    1348           0 :         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
    1349             :                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
    1350             : 
    1351           0 :         tv->tv_sec = tv_sec;
    1352           0 :         tv->tv_usec = tv_usec;
    1353             : 
    1354           0 :         if (msg->len == 0)
    1355           0 :                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
    1356             :                           msg->notify.value[1]));
    1357             :         else
    1358           0 :                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
    1359             : 
    1360           0 :         return true;
    1361             : }
    1362             : 
    1363             : /********************************************************************
    1364             :  Receive a notify2 message list
    1365             :  ********************************************************************/
    1366             : 
    1367           0 : static void receive_notify2_message_list(struct messaging_context *msg,
    1368             :                                          void *private_data,
    1369             :                                          uint32_t msg_type,
    1370             :                                          struct server_id server_id,
    1371             :                                          DATA_BLOB *data)
    1372             : {
    1373           0 :         size_t                  msg_count, i, num_groups;
    1374           0 :         char                    *buf = (char *)data->data;
    1375           0 :         char                    *msg_ptr;
    1376           0 :         size_t                  msg_len;
    1377           0 :         SPOOLSS_NOTIFY_MSG      notify;
    1378           0 :         SPOOLSS_NOTIFY_MSG_CTR  messages;
    1379             : 
    1380           0 :         if (data->length < 4) {
    1381           0 :                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
    1382           0 :                 return;
    1383             :         }
    1384             : 
    1385           0 :         msg_count = IVAL(buf, 0);
    1386           0 :         msg_ptr = buf + 4;
    1387             : 
    1388           0 :         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
    1389             : 
    1390           0 :         if (msg_count == 0) {
    1391           0 :                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
    1392           0 :                 return;
    1393             :         }
    1394             : 
    1395             :         /* initialize the container */
    1396             : 
    1397           0 :         ZERO_STRUCT( messages );
    1398           0 :         notify_msg_ctr_init( &messages );
    1399             : 
    1400             :         /*
    1401             :          * build message groups for each printer identified
    1402             :          * in a change_notify msg.  Remember that a PCN message
    1403             :          * includes the handle returned for the srv_spoolss_replyopenprinter()
    1404             :          * call.  Therefore messages are grouped according to printer handle.
    1405             :          */
    1406             : 
    1407           0 :         for ( i=0; i<msg_count; i++ ) {
    1408           0 :                 struct timeval msg_tv;
    1409             : 
    1410           0 :                 if (msg_ptr + 4 - buf > data->length) {
    1411           0 :                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
    1412           0 :                         return;
    1413             :                 }
    1414             : 
    1415           0 :                 msg_len = IVAL(msg_ptr,0);
    1416           0 :                 msg_ptr += 4;
    1417             : 
    1418           0 :                 if (msg_ptr + msg_len - buf > data->length) {
    1419           0 :                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
    1420           0 :                         return;
    1421             :                 }
    1422             : 
    1423             :                 /* unpack messages */
    1424             : 
    1425           0 :                 ZERO_STRUCT( notify );
    1426           0 :                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
    1427           0 :                 msg_ptr += msg_len;
    1428             : 
    1429             :                 /* add to correct list in container */
    1430             : 
    1431           0 :                 notify_msg_ctr_addmsg( &messages, &notify );
    1432             : 
    1433             :                 /* free memory that might have been allocated by notify2_unpack_msg() */
    1434             : 
    1435           0 :                 if ( notify.len != 0 )
    1436           0 :                         SAFE_FREE( notify.notify.data );
    1437             :         }
    1438             : 
    1439             :         /* process each group of messages */
    1440             : 
    1441           0 :         num_groups = notify_msg_ctr_numgroups( &messages );
    1442           0 :         for ( i=0; i<num_groups; i++ )
    1443           0 :                 send_notify2_changes( &messages, i );
    1444             : 
    1445             : 
    1446             :         /* cleanup */
    1447             : 
    1448           0 :         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
    1449             :                 (uint32_t)msg_count ));
    1450             : 
    1451           0 :         notify_msg_ctr_destroy( &messages );
    1452             : 
    1453           0 :         return;
    1454             : }
    1455             : 
    1456             : /********************************************************************
    1457             :  Send a message to ourself about new driver being installed
    1458             :  so we can upgrade the information for each printer bound to this
    1459             :  driver
    1460             :  ********************************************************************/
    1461             : 
    1462           0 : static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
    1463             :                                             struct messaging_context *msg_ctx)
    1464             : {
    1465           0 :         int len = strlen(drivername);
    1466             : 
    1467           0 :         if (!len)
    1468           0 :                 return false;
    1469             : 
    1470           0 :         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
    1471             :                 drivername));
    1472             : 
    1473           0 :         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
    1474             :                            MSG_PRINTER_DRVUPGRADE,
    1475           0 :                            (const uint8_t *)drivername, len+1);
    1476             : 
    1477           0 :         return true;
    1478             : }
    1479             : 
    1480          28 : void srv_spoolss_cleanup(void)
    1481             : {
    1482           0 :         struct printer_session_counter *session_counter;
    1483             : 
    1484          28 :         for (session_counter = counter_list;
    1485          68 :              session_counter != NULL;
    1486          40 :              session_counter = counter_list) {
    1487          40 :                 DLIST_REMOVE(counter_list, session_counter);
    1488          40 :                 TALLOC_FREE(session_counter);
    1489             :         }
    1490          28 : }
    1491             : 
    1492             : /**********************************************************************
    1493             :  callback to receive a MSG_PRINTER_DRVUPGRADE message and iterate
    1494             :  over all printers, upgrading ones as necessary
    1495             :  This is now *ONLY* called inside the background lpq updater. JRA.
    1496             :  **********************************************************************/
    1497             : 
    1498           0 : void do_drv_upgrade_printer(struct messaging_context *msg,
    1499             :                             void *private_data,
    1500             :                             uint32_t msg_type,
    1501             :                             struct server_id server_id,
    1502             :                             DATA_BLOB *data)
    1503             : {
    1504           0 :         TALLOC_CTX *tmp_ctx;
    1505           0 :         const struct auth_session_info *session_info = get_session_info_system();
    1506           0 :         struct spoolss_PrinterInfo2 *pinfo2;
    1507           0 :         WERROR result;
    1508           0 :         const char *drivername;
    1509           0 :         int snum;
    1510           0 :         int n_services = lp_numservices();
    1511           0 :         struct dcerpc_binding_handle *b = NULL;
    1512             : 
    1513           0 :         tmp_ctx = talloc_new(NULL);
    1514           0 :         if (!tmp_ctx) return;
    1515             : 
    1516           0 :         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
    1517           0 :         if (!drivername) {
    1518           0 :                 DEBUG(0, ("do_drv_upgrade_printer: Out of memory ?!\n"));
    1519           0 :                 goto done;
    1520             :         }
    1521             : 
    1522           0 :         DEBUG(10, ("do_drv_upgrade_printer: "
    1523             :                    "Got message for new driver [%s]\n", drivername));
    1524             : 
    1525             :         /* Iterate the printer list */
    1526             : 
    1527           0 :         for (snum = 0; snum < n_services; snum++) {
    1528           0 :                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
    1529           0 :                         continue;
    1530             :                 }
    1531             : 
    1532             :                 /* ignore [printers] share */
    1533           0 :                 if (strequal(lp_const_servicename(snum), "printers")) {
    1534           0 :                         continue;
    1535             :                 }
    1536             : 
    1537           0 :                 if (b == NULL) {
    1538           0 :                         result = winreg_printer_binding_handle(tmp_ctx,
    1539             :                                                                session_info,
    1540             :                                                                msg,
    1541             :                                                                &b);
    1542           0 :                         if (!W_ERROR_IS_OK(result)) {
    1543           0 :                                 break;
    1544             :                         }
    1545             :                 }
    1546             : 
    1547           0 :                 result = winreg_get_printer(tmp_ctx, b,
    1548             :                                             lp_const_servicename(snum),
    1549             :                                             &pinfo2);
    1550             : 
    1551           0 :                 if (!W_ERROR_IS_OK(result)) {
    1552           0 :                         continue;
    1553             :                 }
    1554             : 
    1555           0 :                 if (!pinfo2->drivername) {
    1556           0 :                         continue;
    1557             :                 }
    1558             : 
    1559           0 :                 if (strcmp(drivername, pinfo2->drivername) != 0) {
    1560           0 :                         continue;
    1561             :                 }
    1562             : 
    1563           0 :                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
    1564             : 
    1565             :                 /* all we care about currently is the change_id */
    1566           0 :                 result = winreg_printer_update_changeid(tmp_ctx, b,
    1567           0 :                                                         pinfo2->printername);
    1568             : 
    1569           0 :                 if (!W_ERROR_IS_OK(result)) {
    1570           0 :                         DEBUG(3, ("do_drv_upgrade_printer: "
    1571             :                                   "Failed to update changeid [%s]\n",
    1572             :                                   win_errstr(result)));
    1573             :                 }
    1574             :         }
    1575             : 
    1576             :         /* all done */
    1577           0 : done:
    1578           0 :         talloc_free(tmp_ctx);
    1579             : }
    1580             : 
    1581             : /********************************************************************
    1582             :  Update the cache for all printq's with a registered client
    1583             :  connection
    1584             :  ********************************************************************/
    1585             : 
    1586           0 : void update_monitored_printq_cache(struct messaging_context *msg_ctx)
    1587             : {
    1588           0 :         struct printer_handle *printer = printers_list;
    1589           0 :         int snum;
    1590             : 
    1591             :         /* loop through all printers and update the cache where
    1592             :            a client is connected */
    1593           0 :         while (printer) {
    1594           0 :                 if ((printer->printer_type == SPLHND_PRINTER) &&
    1595           0 :                     ((printer->notify.cli_chan != NULL) &&
    1596           0 :                      (printer->notify.cli_chan->active_connections > 0))) {
    1597           0 :                         snum = print_queue_snum(printer->sharename);
    1598           0 :                         print_queue_status(msg_ctx, snum, NULL, NULL);
    1599             :                 }
    1600             : 
    1601           0 :                 printer = printer->next;
    1602             :         }
    1603             : 
    1604           0 :         return;
    1605             : }
    1606             : 
    1607             : /****************************************************************
    1608             :  _spoolss_OpenPrinter
    1609             : ****************************************************************/
    1610             : 
    1611         194 : WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
    1612             :                             struct spoolss_OpenPrinter *r)
    1613             : {
    1614           0 :         struct spoolss_OpenPrinterEx e;
    1615           0 :         struct spoolss_UserLevel1 level1;
    1616           0 :         WERROR werr;
    1617             : 
    1618         194 :         ZERO_STRUCT(level1);
    1619             : 
    1620         194 :         e.in.printername        = r->in.printername;
    1621         194 :         e.in.datatype           = r->in.datatype;
    1622         194 :         e.in.devmode_ctr        = r->in.devmode_ctr;
    1623         194 :         e.in.access_mask        = r->in.access_mask;
    1624         194 :         e.in.userlevel_ctr.level                = 1;
    1625         194 :         e.in.userlevel_ctr.user_info.level1     = &level1;
    1626             : 
    1627         194 :         e.out.handle            = r->out.handle;
    1628             : 
    1629         194 :         werr = _spoolss_OpenPrinterEx(p, &e);
    1630             : 
    1631         194 :         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
    1632             :                 /* OpenPrinterEx returns this for a bad
    1633             :                  * printer name. We must return WERR_INVALID_PRINTER_NAME
    1634             :                  * instead.
    1635             :                  */
    1636           4 :                 werr = WERR_INVALID_PRINTER_NAME;
    1637             :         }
    1638             : 
    1639         194 :         return werr;
    1640             : }
    1641             : 
    1642        2850 : static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
    1643             :                               struct spoolss_DeviceMode *orig,
    1644             :                               struct spoolss_DeviceMode **dest)
    1645             : {
    1646           0 :         struct spoolss_DeviceMode *dm;
    1647             : 
    1648        2850 :         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
    1649        2850 :         if (!dm) {
    1650           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1651             :         }
    1652             : 
    1653             :         /* copy all values, then duplicate strings and structs */
    1654        2850 :         *dm = *orig;
    1655             : 
    1656        2850 :         dm->devicename = talloc_strdup(dm, orig->devicename);
    1657        2850 :         if (!dm->devicename) {
    1658           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1659             :         }
    1660        2850 :         dm->formname = talloc_strdup(dm, orig->formname);
    1661        2850 :         if (!dm->formname) {
    1662           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1663             :         }
    1664        2850 :         if (orig->driverextra_data.data) {
    1665        1392 :                 dm->driverextra_data.data =
    1666        1392 :                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
    1667             :                                         orig->driverextra_data.length);
    1668        1392 :                 if (!dm->driverextra_data.data) {
    1669           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1670             :                 }
    1671             :         }
    1672             : 
    1673        2850 :         *dest = dm;
    1674        2850 :         return WERR_OK;
    1675             : }
    1676             : 
    1677             : /****************************************************************
    1678             :  _spoolss_OpenPrinterEx
    1679             : ****************************************************************/
    1680             : 
    1681         988 : WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
    1682             :                               struct spoolss_OpenPrinterEx *r)
    1683             : {
    1684         988 :         struct dcesrv_call_state *dce_call = p->dce_call;
    1685         988 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    1686           0 :         const struct tsocket_address *remote_address =
    1687         988 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    1688           0 :         struct auth_session_info *session_info =
    1689         988 :                 dcesrv_call_session_info(dce_call);
    1690           0 :         int snum;
    1691           0 :         char *raddr;
    1692           0 :         char *rhost;
    1693         988 :         struct printer_handle *Printer=NULL;
    1694           0 :         WERROR result;
    1695           0 :         int rc;
    1696             : 
    1697         988 :         if (!r->in.printername) {
    1698           0 :                 return WERR_INVALID_PARAMETER;
    1699             :         }
    1700             : 
    1701         988 :         if (!*r->in.printername) {
    1702           8 :                 return WERR_INVALID_PARAMETER;
    1703             :         }
    1704             : 
    1705         980 :         if (r->in.userlevel_ctr.level > 3) {
    1706           0 :                 return WERR_INVALID_PARAMETER;
    1707             :         }
    1708         980 :         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
    1709         956 :             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
    1710         956 :             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
    1711          24 :                 return WERR_INVALID_PARAMETER;
    1712             :         }
    1713             : 
    1714             :         /*
    1715             :          * The printcap printer share inventory is updated on client
    1716             :          * enumeration. For clients that do not perform enumeration prior to
    1717             :          * access, such as cupssmbadd, we reinitialise the printer share
    1718             :          * inventory on open as well.
    1719             :          */
    1720         956 :         become_root();
    1721         956 :         delete_and_reload_printers();
    1722         956 :         unbecome_root();
    1723             : 
    1724             :         /* some sanity check because you can open a printer or a print server */
    1725             :         /* aka: \\server\printer or \\server */
    1726             : 
    1727         956 :         DEBUGADD(3,("checking name: %s\n", r->in.printername));
    1728             : 
    1729         956 :         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
    1730         956 :         if (!W_ERROR_IS_OK(result)) {
    1731         332 :                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
    1732             :                         "for printer %s\n", r->in.printername));
    1733         332 :                 ZERO_STRUCTP(r->out.handle);
    1734         332 :                 return result;
    1735             :         }
    1736             : 
    1737         624 :         Printer = find_printer_index_by_hnd(p, r->out.handle);
    1738         624 :         if ( !Printer ) {
    1739           0 :                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
    1740             :                         "handle we created for printer %s\n", r->in.printername));
    1741           0 :                 close_printer_handle(p, r->out.handle);
    1742           0 :                 ZERO_STRUCTP(r->out.handle);
    1743           0 :                 return WERR_INVALID_PARAMETER;
    1744             :         }
    1745             : 
    1746             :         /*
    1747             :          * First case: the user is opening the print server:
    1748             :          *
    1749             :          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
    1750             :          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
    1751             :          *
    1752             :          * Then both Win2k and WinNT clients try an OpenPrinterEx with
    1753             :          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
    1754             :          * or if the user is listed in the smb.conf printer admin parameter.
    1755             :          *
    1756             :          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
    1757             :          * client view printer folder, but does not show the MSAPW.
    1758             :          *
    1759             :          * Note: this test needs code to check access rights here too. Jeremy
    1760             :          * could you look at this?
    1761             :          *
    1762             :          * Second case: the user is opening a printer:
    1763             :          * NT doesn't let us connect to a printer if the connecting user
    1764             :          * doesn't have print permission.
    1765             :          *
    1766             :          * Third case: user is opening a Port Monitor
    1767             :          * access checks same as opening a handle to the print server.
    1768             :          */
    1769             : 
    1770         624 :         switch (Printer->printer_type )
    1771             :         {
    1772         118 :         case SPLHND_SERVER:
    1773             :         case SPLHND_PORTMON_TCP:
    1774             :         case SPLHND_PORTMON_LOCAL:
    1775             :                 /* Printserver handles use global struct... */
    1776             : 
    1777         118 :                 snum = -1;
    1778             : 
    1779         118 :                 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
    1780          90 :                         r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
    1781          90 :                         r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
    1782             :                 }
    1783             : 
    1784             :                 /* Map standard access rights to object specific access rights */
    1785             : 
    1786         118 :                 se_map_standard(&r->in.access_mask,
    1787             :                                 &printserver_std_mapping);
    1788             : 
    1789             :                 /* Deny any object specific bits that don't apply to print
    1790             :                    servers (i.e printer and job specific bits) */
    1791             : 
    1792         118 :                 r->in.access_mask &= SEC_MASK_SPECIFIC;
    1793             : 
    1794         118 :                 if (r->in.access_mask &
    1795             :                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
    1796           0 :                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
    1797           0 :                         close_printer_handle(p, r->out.handle);
    1798           0 :                         ZERO_STRUCTP(r->out.handle);
    1799           0 :                         return WERR_ACCESS_DENIED;
    1800             :                 }
    1801             : 
    1802             :                 /* Allow admin access */
    1803             : 
    1804         118 :                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
    1805             :                 {
    1806          94 :                         if (!lp_show_add_printer_wizard()) {
    1807           0 :                                 close_printer_handle(p, r->out.handle);
    1808           0 :                                 ZERO_STRUCTP(r->out.handle);
    1809           0 :                                 return WERR_ACCESS_DENIED;
    1810             :                         }
    1811             : 
    1812             :                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    1813             :                            and not a printer admin, then fail */
    1814             : 
    1815          94 :                         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    1816           2 :                             !security_token_has_privilege(
    1817           2 :                                     session_info->security_token,
    1818           0 :                                     SEC_PRIV_PRINT_OPERATOR) &&
    1819           0 :                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
    1820           0 :                                                 session_info->security_token)) {
    1821           0 :                                 close_printer_handle(p, r->out.handle);
    1822           0 :                                 ZERO_STRUCTP(r->out.handle);
    1823           0 :                                 DEBUG(3,("access DENIED as user is not root, "
    1824             :                                         "has no printoperator privilege and is "
    1825             :                                         "not a member of the printoperator builtin group\n"));
    1826           0 :                                 return WERR_ACCESS_DENIED;
    1827             :                         }
    1828             : 
    1829          94 :                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
    1830             :                 }
    1831             :                 else
    1832             :                 {
    1833          24 :                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
    1834             :                 }
    1835             : 
    1836         118 :                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
    1837             :                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
    1838             : 
    1839         118 :                 break;
    1840             : 
    1841         506 :         case SPLHND_PRINTER:
    1842             :                 /* NT doesn't let us connect to a printer if the connecting user
    1843             :                    doesn't have print permission.  */
    1844             : 
    1845         506 :                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
    1846           0 :                         close_printer_handle(p, r->out.handle);
    1847           0 :                         ZERO_STRUCTP(r->out.handle);
    1848           0 :                         return WERR_INVALID_HANDLE;
    1849             :                 }
    1850             : 
    1851         506 :                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
    1852         170 :                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
    1853             :                 }
    1854             : 
    1855         506 :                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
    1856             : 
    1857             :                 /* map an empty access mask to the minimum access mask */
    1858         506 :                 if (r->in.access_mask == 0x0)
    1859         296 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1860             : 
    1861             :                 /*
    1862             :                  * If we are not serving the printer driver for this printer,
    1863             :                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
    1864             :                  * will keep NT clients happy  --jerry
    1865             :                  */
    1866             : 
    1867         506 :                 if (lp_use_client_driver(snum)
    1868           0 :                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
    1869             :                 {
    1870           0 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1871             :                 }
    1872             : 
    1873             :                 /* check smb.conf parameters and the the sec_desc */
    1874         506 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    1875             :                                                          p->mem_ctx);
    1876         506 :                 if (raddr == NULL) {
    1877           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1878             :                 }
    1879             : 
    1880         506 :                 rc = get_remote_hostname(remote_address,
    1881             :                                          &rhost,
    1882             :                                          p->mem_ctx);
    1883         506 :                 if (rc < 0) {
    1884           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1885             :                 }
    1886         506 :                 if (strequal(rhost, "UNKNOWN")) {
    1887         506 :                         rhost = raddr;
    1888             :                 }
    1889             : 
    1890         506 :                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
    1891             :                                   rhost, raddr)) {
    1892           0 :                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
    1893           0 :                         ZERO_STRUCTP(r->out.handle);
    1894           0 :                         return WERR_ACCESS_DENIED;
    1895             :                 }
    1896             : 
    1897         506 :                 if (!user_ok_token(session_info->unix_info->unix_name,
    1898         506 :                                    session_info->info->domain_name,
    1899         506 :                                    session_info->security_token, snum) ||
    1900         506 :                     !W_ERROR_IS_OK(print_access_check(session_info,
    1901             :                                                       p->msg_ctx,
    1902             :                                                       snum,
    1903             :                                                       r->in.access_mask))) {
    1904           0 :                         DEBUG(3, ("access DENIED for printer open\n"));
    1905           0 :                         close_printer_handle(p, r->out.handle);
    1906           0 :                         ZERO_STRUCTP(r->out.handle);
    1907           0 :                         return WERR_ACCESS_DENIED;
    1908             :                 }
    1909             : 
    1910         506 :                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
    1911           4 :                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
    1912           4 :                         close_printer_handle(p, r->out.handle);
    1913           4 :                         ZERO_STRUCTP(r->out.handle);
    1914           4 :                         return WERR_ACCESS_DENIED;
    1915             :                 }
    1916             : 
    1917         502 :                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
    1918         170 :                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
    1919             :                 else
    1920         332 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1921             : 
    1922         502 :                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
    1923             :                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
    1924             : 
    1925         502 :                 winreg_create_printer_internal(p->mem_ctx,
    1926             :                                       get_session_info_system(),
    1927             :                                       p->msg_ctx,
    1928             :                                       lp_const_servicename(snum));
    1929             : 
    1930         502 :                 break;
    1931             : 
    1932           0 :         default:
    1933             :                 /* sanity check to prevent programmer error */
    1934           0 :                 ZERO_STRUCTP(r->out.handle);
    1935           0 :                 return WERR_INVALID_HANDLE;
    1936             :         }
    1937             : 
    1938         620 :         Printer->access_granted = r->in.access_mask;
    1939             : 
    1940             :         /*
    1941             :          * If the client sent a devmode in the OpenPrinter() call, then
    1942             :          * save it here in case we get a job submission on this handle
    1943             :          */
    1944             : 
    1945         620 :          if ((Printer->printer_type != SPLHND_SERVER)
    1946         502 :           && (r->in.devmode_ctr.devmode != NULL)) {
    1947           8 :                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
    1948             :                                 &Printer->devmode);
    1949             :          }
    1950             : 
    1951         620 :         return WERR_OK;
    1952             : }
    1953             : 
    1954             : /****************************************************************
    1955             :  _spoolss_ClosePrinter
    1956             : ****************************************************************/
    1957             : 
    1958         620 : WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
    1959             :                              struct spoolss_ClosePrinter *r)
    1960             : {
    1961         620 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    1962             : 
    1963         620 :         if (Printer && Printer->document_started) {
    1964           0 :                 struct spoolss_EndDocPrinter e;
    1965             : 
    1966          28 :                 e.in.handle = r->in.handle;
    1967             : 
    1968          28 :                 _spoolss_EndDocPrinter(p, &e);
    1969             :         }
    1970             : 
    1971         620 :         if (!close_printer_handle(p, r->in.handle))
    1972           0 :                 return WERR_INVALID_HANDLE;
    1973             : 
    1974             :         /* clear the returned printer handle.  Observed behavior
    1975             :            from Win2k server.  Don't think this really matters.
    1976             :            Previous code just copied the value of the closed
    1977             :            handle.    --jerry */
    1978             : 
    1979         620 :         ZERO_STRUCTP(r->out.handle);
    1980             : 
    1981         620 :         return WERR_OK;
    1982             : }
    1983             : 
    1984             : /****************************************************************
    1985             :  _spoolss_DeletePrinter
    1986             : ****************************************************************/
    1987             : 
    1988          16 : WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
    1989             :                               struct spoolss_DeletePrinter *r)
    1990             : {
    1991          16 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    1992           0 :         WERROR result;
    1993           0 :         int snum;
    1994             : 
    1995          16 :         if (Printer && Printer->document_started) {
    1996           0 :                 struct spoolss_EndDocPrinter e;
    1997             : 
    1998           0 :                 e.in.handle = r->in.handle;
    1999             : 
    2000           0 :                 _spoolss_EndDocPrinter(p, &e);
    2001             :         }
    2002             : 
    2003          16 :         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
    2004          16 :                 winreg_delete_printer_key_internal(p->mem_ctx,
    2005             :                                           get_session_info_system(),
    2006             :                                           p->msg_ctx,
    2007             :                                           lp_const_servicename(snum),
    2008             :                                           "");
    2009             :         }
    2010             : 
    2011          16 :         result = delete_printer_handle(p, r->in.handle);
    2012             : 
    2013          16 :         return result;
    2014             : }
    2015             : 
    2016             : /*******************************************************************
    2017             :  * static function to lookup the version id corresponding to an
    2018             :  * long architecture string
    2019             :  ******************************************************************/
    2020             : 
    2021             : static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
    2022             :                                    SPOOLSS_DRIVER_VERSION_NT35,
    2023             :                                    SPOOLSS_DRIVER_VERSION_NT4,
    2024             :                                    SPOOLSS_DRIVER_VERSION_200X,
    2025             :                                    -1};
    2026             : 
    2027           0 : static int get_version_id(const char *arch)
    2028             : {
    2029           0 :         int i;
    2030             : 
    2031           0 :         for (i=0; archi_table[i].long_archi != NULL; i++)
    2032             :         {
    2033           0 :                 if (strcmp(arch, archi_table[i].long_archi) == 0)
    2034           0 :                         return (archi_table[i].version);
    2035             :         }
    2036             : 
    2037           0 :         return -1;
    2038             : }
    2039             : 
    2040             : /****************************************************************
    2041             :  _spoolss_DeletePrinterDriver
    2042             : ****************************************************************/
    2043             : 
    2044           0 : WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
    2045             :                                     struct spoolss_DeletePrinterDriver *r)
    2046             : {
    2047             : 
    2048           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2049           0 :         struct auth_session_info *session_info =
    2050           0 :                 dcesrv_call_session_info(dce_call);
    2051           0 :         struct spoolss_DriverInfo8 *info = NULL;
    2052           0 :         int                             version;
    2053           0 :         WERROR                          status;
    2054           0 :         struct dcerpc_binding_handle *b;
    2055           0 :         TALLOC_CTX *tmp_ctx = NULL;
    2056           0 :         int i;
    2057           0 :         bool found;
    2058             : 
    2059             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    2060             :            and not a printer admin, then fail */
    2061             : 
    2062           0 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    2063           0 :             !security_token_has_privilege(session_info->security_token,
    2064             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    2065           0 :                 return WERR_ACCESS_DENIED;
    2066             :         }
    2067             : 
    2068           0 :         if (r->in.architecture == NULL || r->in.driver == NULL) {
    2069           0 :                 return WERR_INVALID_ENVIRONMENT;
    2070             :         }
    2071             : 
    2072             :         /* check that we have a valid driver name first */
    2073             : 
    2074           0 :         if ((version = get_version_id(r->in.architecture)) == -1) {
    2075           0 :                 return WERR_INVALID_ENVIRONMENT;
    2076             :         }
    2077             : 
    2078           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    2079           0 :         if (!tmp_ctx) {
    2080           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2081             :         }
    2082             : 
    2083           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    2084             :                                                get_session_info_system(),
    2085             :                                                p->msg_ctx,
    2086             :                                                &b);
    2087           0 :         if (!W_ERROR_IS_OK(status)) {
    2088           0 :                 goto done;
    2089             :         }
    2090             : 
    2091           0 :         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
    2092           0 :                 status = winreg_get_driver(tmp_ctx, b,
    2093             :                                            r->in.architecture, r->in.driver,
    2094           0 :                                            drv_cversion[i], &info);
    2095           0 :                 if (!W_ERROR_IS_OK(status)) {
    2096           0 :                         DEBUG(5, ("skipping del of driver with version %d\n",
    2097             :                                   drv_cversion[i]));
    2098           0 :                         continue;
    2099             :                 }
    2100           0 :                 found = true;
    2101             : 
    2102           0 :                 if (printer_driver_in_use(tmp_ctx, b, info)) {
    2103           0 :                         status = WERR_PRINTER_DRIVER_IN_USE;
    2104           0 :                         goto done;
    2105             :                 }
    2106             : 
    2107           0 :                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
    2108           0 :                 if (!W_ERROR_IS_OK(status)) {
    2109           0 :                         DEBUG(0, ("failed del of driver with version %d\n",
    2110             :                                   drv_cversion[i]));
    2111           0 :                         goto done;
    2112             :                 }
    2113             :         }
    2114           0 :         if (found == false) {
    2115           0 :                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
    2116           0 :                 status = WERR_UNKNOWN_PRINTER_DRIVER;
    2117             :         } else {
    2118           0 :                 status = WERR_OK;
    2119             :         }
    2120             : 
    2121           0 : done:
    2122           0 :         talloc_free(tmp_ctx);
    2123             : 
    2124           0 :         return status;
    2125             : }
    2126             : 
    2127           0 : static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
    2128             :                                   struct pipes_struct *p,
    2129             :                                   struct spoolss_DeletePrinterDriverEx *r,
    2130             :                                   struct dcerpc_binding_handle *b,
    2131             :                                   struct spoolss_DriverInfo8 *info)
    2132             : {
    2133           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2134           0 :         struct auth_session_info *session_info =
    2135           0 :                 dcesrv_call_session_info(dce_call);
    2136           0 :         WERROR status;
    2137           0 :         bool delete_files;
    2138             : 
    2139           0 :         if (printer_driver_in_use(mem_ctx, b, info)) {
    2140           0 :                 status = WERR_PRINTER_DRIVER_IN_USE;
    2141           0 :                 goto done;
    2142             :         }
    2143             : 
    2144             :         /*
    2145             :          * we have a couple of cases to consider.
    2146             :          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
    2147             :          *     then the delete should fail if **any** files overlap with
    2148             :          *     other drivers
    2149             :          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
    2150             :          *     non-overlapping files
    2151             :          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
    2152             :          *     are set, then do not delete any files
    2153             :          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
    2154             :          */
    2155             : 
    2156           0 :         delete_files = r->in.delete_flags
    2157           0 :                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
    2158             : 
    2159             : 
    2160           0 :         if (delete_files) {
    2161           0 :                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
    2162           0 :                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
    2163           0 :                         status = WERR_PRINTER_DRIVER_IN_USE;
    2164           0 :                         goto done;
    2165             :                 }
    2166             :                 /*
    2167             :                  * printer_driver_files_in_use() has trimmed overlapping files
    2168             :                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
    2169             :                  */
    2170             :         }
    2171             : 
    2172             : 
    2173           0 :         status = winreg_del_driver(mem_ctx, b, info, info->version);
    2174           0 :         if (!W_ERROR_IS_OK(status)) {
    2175           0 :                 goto done;
    2176             :         }
    2177             : 
    2178             :         /*
    2179             :          * now delete any associated files if delete_files is
    2180             :          * true. Even if this part fails, we return success
    2181             :          * because the driver does not exist any more
    2182             :          */
    2183           0 :         if (delete_files) {
    2184           0 :                 delete_driver_files(session_info, info);
    2185             :         }
    2186             : 
    2187           0 : done:
    2188           0 :         return status;
    2189             : }
    2190             : 
    2191             : /****************************************************************
    2192             :  _spoolss_DeletePrinterDriverEx
    2193             : ****************************************************************/
    2194             : 
    2195           0 : WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
    2196             :                                       struct spoolss_DeletePrinterDriverEx *r)
    2197             : {
    2198           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2199           0 :         struct auth_session_info *session_info =
    2200           0 :                 dcesrv_call_session_info(dce_call);
    2201           0 :         struct spoolss_DriverInfo8 *info = NULL;
    2202           0 :         WERROR                          status;
    2203           0 :         struct dcerpc_binding_handle *b;
    2204           0 :         TALLOC_CTX *tmp_ctx = NULL;
    2205           0 :         int i;
    2206           0 :         bool found;
    2207             : 
    2208             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    2209             :            and not a printer admin, then fail */
    2210             : 
    2211           0 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    2212           0 :             !security_token_has_privilege(session_info->security_token,
    2213             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    2214           0 :                 return WERR_ACCESS_DENIED;
    2215             :         }
    2216             : 
    2217           0 :         if (r->in.architecture == NULL || r->in.driver == NULL) {
    2218           0 :                 return WERR_INVALID_ENVIRONMENT;
    2219             :         }
    2220             : 
    2221             :         /* check that we have a valid driver name first */
    2222           0 :         if (get_version_id(r->in.architecture) == -1) {
    2223             :                 /* this is what NT returns */
    2224           0 :                 return WERR_INVALID_ENVIRONMENT;
    2225             :         }
    2226             : 
    2227           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    2228           0 :         if (!tmp_ctx) {
    2229           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2230             :         }
    2231             : 
    2232           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    2233             :                                                get_session_info_system(),
    2234             :                                                p->msg_ctx,
    2235             :                                                &b);
    2236           0 :         if (!W_ERROR_IS_OK(status)) {
    2237           0 :                 goto done;
    2238             :         }
    2239             : 
    2240           0 :         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
    2241           0 :                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
    2242           0 :                  && (drv_cversion[i] != r->in.version)) {
    2243           0 :                         continue;
    2244             :                 }
    2245             : 
    2246             :                 /* check if a driver with this version exists before delete */
    2247           0 :                 status = winreg_get_driver(tmp_ctx, b,
    2248             :                                            r->in.architecture, r->in.driver,
    2249           0 :                                            drv_cversion[i], &info);
    2250           0 :                 if (!W_ERROR_IS_OK(status)) {
    2251           0 :                         DEBUG(5, ("skipping del of driver with version %d\n",
    2252             :                                   drv_cversion[i]));
    2253           0 :                         continue;
    2254             :                 }
    2255           0 :                 found = true;
    2256             : 
    2257           0 :                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
    2258           0 :                 if (!W_ERROR_IS_OK(status)) {
    2259           0 :                         DEBUG(0, ("failed to delete driver with version %d\n",
    2260             :                                   drv_cversion[i]));
    2261           0 :                         goto done;
    2262             :                 }
    2263             :         }
    2264           0 :         if (found == false) {
    2265           0 :                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
    2266           0 :                 status = WERR_UNKNOWN_PRINTER_DRIVER;
    2267             :         } else {
    2268           0 :                 status = WERR_OK;
    2269             :         }
    2270             : 
    2271           0 : done:
    2272           0 :         talloc_free(tmp_ctx);
    2273           0 :         return status;
    2274             : }
    2275             : 
    2276             : 
    2277             : /********************************************************************
    2278             :  GetPrinterData on a printer server Handle.
    2279             : ********************************************************************/
    2280             : 
    2281         404 : static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
    2282             :                                             const char *value,
    2283             :                                             enum winreg_Type *type,
    2284             :                                             union spoolss_PrinterData *data)
    2285             : {
    2286         404 :         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
    2287             : 
    2288         404 :         if (!strcasecmp_m(value, "W3SvcInstalled")) {
    2289          28 :                 *type = REG_DWORD;
    2290          28 :                 SIVAL(&data->value, 0, 0x00);
    2291          28 :                 return WERR_OK;
    2292             :         }
    2293             : 
    2294         376 :         if (!strcasecmp_m(value, "BeepEnabled")) {
    2295          24 :                 *type = REG_DWORD;
    2296          24 :                 SIVAL(&data->value, 0, 0x00);
    2297          24 :                 return WERR_OK;
    2298             :         }
    2299             : 
    2300         352 :         if (!strcasecmp_m(value, "EventLog")) {
    2301          24 :                 *type = REG_DWORD;
    2302             :                 /* formally was 0x1b */
    2303          24 :                 SIVAL(&data->value, 0, 0x00);
    2304          24 :                 return WERR_OK;
    2305             :         }
    2306             : 
    2307         328 :         if (!strcasecmp_m(value, "NetPopup")) {
    2308           0 :                 *type = REG_DWORD;
    2309           0 :                 SIVAL(&data->value, 0, 0x00);
    2310           0 :                 return WERR_OK;
    2311             :         }
    2312             : 
    2313         328 :         if (!strcasecmp_m(value, "MajorVersion")) {
    2314          28 :                 *type = REG_DWORD;
    2315             : 
    2316             :                 /* Windows NT 4.0 seems to not allow uploading of drivers
    2317             :                    to a server that reports 0x3 as the MajorVersion.
    2318             :                    need to investigate more how Win2k gets around this .
    2319             :                    -- jerry */
    2320             : 
    2321          28 :                 if (RA_WINNT == get_remote_arch()) {
    2322           0 :                         SIVAL(&data->value, 0, 0x02);
    2323             :                 } else {
    2324          28 :                         SIVAL(&data->value, 0, 0x03);
    2325             :                 }
    2326             : 
    2327          28 :                 return WERR_OK;
    2328             :         }
    2329             : 
    2330         300 :         if (!strcasecmp_m(value, "MinorVersion")) {
    2331          24 :                 *type = REG_DWORD;
    2332          24 :                 SIVAL(&data->value, 0, 0x00);
    2333          24 :                 return WERR_OK;
    2334             :         }
    2335             : 
    2336             :         /* REG_BINARY
    2337             :          *  uint32_t size        = 0x114
    2338             :          *  uint32_t major       = 5
    2339             :          *  uint32_t minor       = [0|1]
    2340             :          *  uint32_t build       = [2195|2600]
    2341             :          *  extra unicode string = e.g. "Service Pack 3"
    2342             :          */
    2343         276 :         if (!strcasecmp_m(value, "OSVersion")) {
    2344           0 :                 DATA_BLOB blob;
    2345           0 :                 enum ndr_err_code ndr_err;
    2346           0 :                 struct spoolss_OSVersion os;
    2347             : 
    2348             :                 /*
    2349             :                  * Set the default OSVersion to:
    2350             :                  *
    2351             :                  *     Windows Server 2003R2 SP2 (5.2.3790)
    2352             :                  *
    2353             :                  * used to be Windows 2000 (5.0.2195)
    2354             :                  */
    2355          40 :                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2356             :                                                       "spoolss", "os_major",
    2357             :                                                       GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
    2358          40 :                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2359             :                                                       "spoolss", "os_minor",
    2360             :                                                       GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
    2361          40 :                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2362             :                                                       "spoolss", "os_build",
    2363             :                                                       GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
    2364          40 :                 os.extra_string         = ""; /* leave extra string empty */
    2365             : 
    2366          40 :                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
    2367             :                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
    2368          40 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    2369           0 :                         return WERR_GEN_FAILURE;
    2370             :                 }
    2371             : 
    2372          40 :                 if (DEBUGLEVEL >= 10) {
    2373           0 :                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
    2374             :                 }
    2375             : 
    2376          40 :                 *type = REG_BINARY;
    2377          40 :                 data->binary = blob;
    2378             : 
    2379          40 :                 return WERR_OK;
    2380             :         }
    2381             : 
    2382             : 
    2383         236 :         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
    2384          24 :                 *type = REG_SZ;
    2385             : 
    2386          24 :                 data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
    2387          24 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2388             : 
    2389          24 :                 return WERR_OK;
    2390             :         }
    2391             : 
    2392         212 :         if (!strcasecmp_m(value, "Architecture")) {
    2393         160 :                 *type = REG_SZ;
    2394         160 :                 data->string = talloc_strdup(mem_ctx,
    2395             :                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
    2396         160 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2397             : 
    2398         160 :                 return WERR_OK;
    2399             :         }
    2400             : 
    2401          52 :         if (!strcasecmp_m(value, "DsPresent")) {
    2402          24 :                 *type = REG_DWORD;
    2403             : 
    2404             :                 /* only show the publish check box if we are a
    2405             :                    member of a AD domain */
    2406             : 
    2407          24 :                 if (lp_security() == SEC_ADS) {
    2408           0 :                         SIVAL(&data->value, 0, 0x01);
    2409             :                 } else {
    2410          24 :                         SIVAL(&data->value, 0, 0x00);
    2411             :                 }
    2412          24 :                 return WERR_OK;
    2413             :         }
    2414             : 
    2415          28 :         if (!strcasecmp_m(value, "DNSMachineName")) {
    2416          24 :                 const char *hostname = get_mydnsfullname();
    2417             : 
    2418          24 :                 if (!hostname) {
    2419           0 :                         return WERR_FILE_NOT_FOUND;
    2420             :                 }
    2421             : 
    2422          24 :                 *type = REG_SZ;
    2423          24 :                 data->string = talloc_strdup(mem_ctx, hostname);
    2424          24 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2425             : 
    2426          24 :                 return WERR_OK;
    2427             :         }
    2428             : 
    2429           4 :         *type = REG_NONE;
    2430             : 
    2431           4 :         return WERR_INVALID_PARAMETER;
    2432             : }
    2433             : 
    2434             : /****************************************************************
    2435             :  _spoolss_GetPrinterData
    2436             : ****************************************************************/
    2437             : 
    2438         480 : WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
    2439             :                                struct spoolss_GetPrinterData *r)
    2440             : {
    2441           0 :         struct spoolss_GetPrinterDataEx r2;
    2442             : 
    2443         480 :         r2.in.handle            = r->in.handle;
    2444         480 :         r2.in.key_name          = "PrinterDriverData";
    2445         480 :         r2.in.value_name        = r->in.value_name;
    2446         480 :         r2.in.offered           = r->in.offered;
    2447         480 :         r2.out.type             = r->out.type;
    2448         480 :         r2.out.data             = r->out.data;
    2449         480 :         r2.out.needed           = r->out.needed;
    2450             : 
    2451         480 :         return _spoolss_GetPrinterDataEx(p, &r2);
    2452             : }
    2453             : 
    2454             : /*********************************************************
    2455             :  Connect to the client machine.
    2456             : **********************************************************/
    2457             : 
    2458           2 : static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
    2459             :                                       struct sockaddr_storage *client_ss, const char *remote_machine)
    2460             : {
    2461           0 :         NTSTATUS ret;
    2462           0 :         struct sockaddr_storage rm_addr;
    2463           0 :         char addr[INET6_ADDRSTRLEN];
    2464           2 :         struct cli_credentials *anon_creds = NULL;
    2465             : 
    2466           2 :         if ( is_zero_addr(client_ss) ) {
    2467           0 :                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
    2468             :                         remote_machine));
    2469           0 :                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
    2470           0 :                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
    2471           0 :                         return false;
    2472             :                 }
    2473           0 :                 print_sockaddr(addr, sizeof(addr), &rm_addr);
    2474             :         } else {
    2475           2 :                 rm_addr = *client_ss;
    2476           2 :                 print_sockaddr(addr, sizeof(addr), &rm_addr);
    2477           2 :                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
    2478             :                         addr));
    2479             :         }
    2480             : 
    2481           2 :         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
    2482           0 :                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
    2483             :                         addr));
    2484           0 :                 return false;
    2485             :         }
    2486             : 
    2487           2 :         anon_creds = cli_credentials_init_anon(NULL);
    2488           2 :         if (anon_creds == NULL) {
    2489           0 :                 DBG_ERR("cli_credentials_init_anon() failed\n");
    2490           0 :                 return false;
    2491             :         }
    2492             : 
    2493             :         /* setup the connection */
    2494           2 :         ret = cli_full_connection_creds( pp_cli, lp_netbios_name(), remote_machine,
    2495             :                 &rm_addr, 0, "IPC$", "IPC",
    2496             :                 anon_creds,
    2497             :                 CLI_FULL_CONNECTION_IPC);
    2498           2 :         TALLOC_FREE(anon_creds);
    2499           2 :         if ( !NT_STATUS_IS_OK( ret ) ) {
    2500           0 :                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
    2501             :                         remote_machine ));
    2502           0 :                 return false;
    2503             :         }
    2504             : 
    2505           2 :         if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
    2506           0 :                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
    2507           0 :                 cli_shutdown(*pp_cli);
    2508           0 :                 return false;
    2509             :         }
    2510             : 
    2511             :         /*
    2512             :          * Ok - we have an anonymous connection to the IPC$ share.
    2513             :          * Now start the NT Domain stuff :-).
    2514             :          */
    2515             : 
    2516           2 :         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
    2517           2 :         if (!NT_STATUS_IS_OK(ret)) {
    2518           0 :                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
    2519             :                         remote_machine, nt_errstr(ret)));
    2520           0 :                 cli_shutdown(*pp_cli);
    2521           0 :                 return false;
    2522             :         }
    2523             : 
    2524           2 :         return true;
    2525             : }
    2526             : 
    2527             : /***************************************************************************
    2528             :  Connect to the client.
    2529             : ****************************************************************************/
    2530             : 
    2531           2 : static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
    2532             :                                         uint32_t localprinter,
    2533             :                                         enum winreg_Type type,
    2534             :                                         struct policy_handle *handle,
    2535             :                                         struct notify_back_channel **_chan,
    2536             :                                         struct sockaddr_storage *client_ss,
    2537             :                                         struct messaging_context *msg_ctx)
    2538             : {
    2539           0 :         WERROR result;
    2540           0 :         NTSTATUS status;
    2541           0 :         struct notify_back_channel *chan;
    2542             : 
    2543           2 :         for (chan = back_channels; chan; chan = chan->next) {
    2544           0 :                 if (memcmp(&chan->client_address, client_ss,
    2545             :                            sizeof(struct sockaddr_storage)) == 0) {
    2546           0 :                         break;
    2547             :                 }
    2548             :         }
    2549             : 
    2550             :         /*
    2551             :          * If it's the first connection, contact the client
    2552             :          * and connect to the IPC$ share anonymously
    2553             :          */
    2554           2 :         if (!chan) {
    2555           0 :                 fstring unix_printer;
    2556             : 
    2557             :                 /* the +2 is to strip the leading 2 backslashes */
    2558           2 :                 fstrcpy(unix_printer, printer + 2);
    2559             : 
    2560           2 :                 chan = talloc_zero(NULL, struct notify_back_channel);
    2561           2 :                 if (!chan) {
    2562           0 :                         return false;
    2563             :                 }
    2564           2 :                 chan->client_address = *client_ss;
    2565             : 
    2566           2 :                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
    2567           0 :                         TALLOC_FREE(chan);
    2568           0 :                         return false;
    2569             :                 }
    2570             : 
    2571           2 :                 DLIST_ADD(back_channels, chan);
    2572             : 
    2573           2 :                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
    2574             :                                    receive_notify2_message_list);
    2575             :         }
    2576             : 
    2577           2 :         if (chan->cli_pipe == NULL ||
    2578           2 :             chan->cli_pipe->binding_handle == NULL) {
    2579           0 :                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
    2580             :                         "NULL %s for printer %s\n",
    2581             :                         chan->cli_pipe == NULL ?
    2582             :                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
    2583             :                         printer));
    2584           0 :                 return false;
    2585             :         }
    2586             : 
    2587             :         /*
    2588             :          * Tell the specific printing tdb we want messages for this printer
    2589             :          * by registering our PID.
    2590             :          */
    2591             : 
    2592           2 :         if (!print_notify_register_pid(snum)) {
    2593           0 :                 DEBUG(0, ("Failed to register our pid for printer %s\n",
    2594             :                           printer));
    2595             :         }
    2596             : 
    2597           2 :         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
    2598             :                                                  talloc_tos(),
    2599             :                                                  printer,
    2600             :                                                  localprinter,
    2601             :                                                  type,
    2602             :                                                  0,
    2603             :                                                  NULL,
    2604             :                                                  handle,
    2605             :                                                  &result);
    2606           2 :         if (!NT_STATUS_IS_OK(status)) {
    2607           0 :                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
    2608           0 :                 result = ntstatus_to_werror(status);
    2609           2 :         } else if (!W_ERROR_IS_OK(result)) {
    2610           0 :                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
    2611             :         }
    2612             : 
    2613           2 :         chan->active_connections++;
    2614           2 :         *_chan = chan;
    2615             : 
    2616           2 :         return (W_ERROR_IS_OK(result));
    2617             : }
    2618             : 
    2619             : /****************************************************************
    2620             :  ****************************************************************/
    2621             : 
    2622           2 : static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
    2623             :                                                              const struct spoolss_NotifyOption *r)
    2624             : {
    2625           0 :         struct spoolss_NotifyOption *option;
    2626           0 :         uint32_t i,k;
    2627             : 
    2628           2 :         if (!r) {
    2629           0 :                 return NULL;
    2630             :         }
    2631             : 
    2632           2 :         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
    2633           2 :         if (!option) {
    2634           0 :                 return NULL;
    2635             :         }
    2636             : 
    2637           2 :         *option = *r;
    2638             : 
    2639           2 :         if (!option->count) {
    2640           0 :                 return option;
    2641             :         }
    2642             : 
    2643           2 :         option->types = talloc_zero_array(option,
    2644             :                 struct spoolss_NotifyOptionType, option->count);
    2645           2 :         if (!option->types) {
    2646           0 :                 talloc_free(option);
    2647           0 :                 return NULL;
    2648             :         }
    2649             : 
    2650           6 :         for (i=0; i < option->count; i++) {
    2651           4 :                 option->types[i] = r->types[i];
    2652             : 
    2653           4 :                 if (option->types[i].count) {
    2654           4 :                         option->types[i].fields = talloc_zero_array(option,
    2655             :                                 union spoolss_Field, option->types[i].count);
    2656           4 :                         if (!option->types[i].fields) {
    2657           0 :                                 talloc_free(option);
    2658           0 :                                 return NULL;
    2659             :                         }
    2660           8 :                         for (k=0; k<option->types[i].count; k++) {
    2661           4 :                                 option->types[i].fields[k] =
    2662           4 :                                         r->types[i].fields[k];
    2663             :                         }
    2664             :                 }
    2665             :         }
    2666             : 
    2667           2 :         return option;
    2668             : }
    2669             : 
    2670             : /****************************************************************
    2671             :  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
    2672             :  *
    2673             :  * before replying OK: status=0 a rpc call is made to the workstation
    2674             :  * asking ReplyOpenPrinter
    2675             :  *
    2676             :  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
    2677             :  * called from api_spoolss_rffpcnex
    2678             : ****************************************************************/
    2679             : 
    2680           2 : WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
    2681             :                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
    2682             : {
    2683           2 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2684           2 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    2685           0 :         const struct tsocket_address *remote_address =
    2686           2 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    2687           2 :         int snum = -1;
    2688           2 :         struct spoolss_NotifyOption *option = r->in.notify_options;
    2689           0 :         struct sockaddr_storage client_ss;
    2690           0 :         ssize_t client_len;
    2691             : 
    2692             :         /* store the notify value in the printer struct */
    2693             : 
    2694           2 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    2695             : 
    2696           2 :         if (!Printer) {
    2697           0 :                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2698             :                         "Invalid handle (%s:%u:%u).\n",
    2699             :                         OUR_HANDLE(r->in.handle)));
    2700           0 :                 return WERR_INVALID_HANDLE;
    2701             :         }
    2702             : 
    2703           2 :         Printer->notify.flags                = r->in.flags;
    2704           2 :         Printer->notify.options              = r->in.options;
    2705           2 :         Printer->notify.printerlocal = r->in.printer_local;
    2706           2 :         Printer->notify.msg_ctx              = p->msg_ctx;
    2707             : 
    2708           2 :         TALLOC_FREE(Printer->notify.option);
    2709           2 :         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
    2710             : 
    2711           2 :         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
    2712             : 
    2713             :         /* Connect to the client machine and send a ReplyOpenPrinter */
    2714             : 
    2715           2 :         if ( Printer->printer_type == SPLHND_SERVER)
    2716           2 :                 snum = -1;
    2717           0 :         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
    2718           0 :                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
    2719           0 :                 return WERR_INVALID_HANDLE;
    2720             : 
    2721           2 :         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2722             :                   "remote_address is %s\n",
    2723             :                   tsocket_address_string(remote_address, p->mem_ctx)));
    2724             : 
    2725           2 :         if (!lp_print_notify_backchannel(snum)) {
    2726           0 :                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2727             :                         "backchannel disabled\n"));
    2728           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
    2729             :         }
    2730             : 
    2731           2 :         client_len = tsocket_address_bsd_sockaddr(remote_address,
    2732             :                                                   (struct sockaddr *) &client_ss,
    2733             :                                                   sizeof(struct sockaddr_storage));
    2734           2 :         if (client_len < 0) {
    2735           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2736             :         }
    2737             : 
    2738           2 :         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
    2739             :                                         Printer->notify.printerlocal, REG_SZ,
    2740             :                                         &Printer->notify.cli_hnd,
    2741             :                                         &Printer->notify.cli_chan,
    2742             :                                         &client_ss, p->msg_ctx)) {
    2743           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
    2744             :         }
    2745             : 
    2746           2 :         return WERR_OK;
    2747             : }
    2748             : 
    2749             : /*******************************************************************
    2750             :  * fill a notify_info_data with the servername
    2751             :  ********************************************************************/
    2752             : 
    2753           0 : static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
    2754             :                                        int snum,
    2755             :                                        struct spoolss_Notify *data,
    2756             :                                        print_queue_struct *queue,
    2757             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    2758             :                                        TALLOC_CTX *mem_ctx)
    2759             : {
    2760           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
    2761           0 : }
    2762             : 
    2763             : /*******************************************************************
    2764             :  * fill a notify_info_data with the printername (not including the servername).
    2765             :  ********************************************************************/
    2766             : 
    2767           0 : static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
    2768             :                                         int snum,
    2769             :                                         struct spoolss_Notify *data,
    2770             :                                         print_queue_struct *queue,
    2771             :                                         struct spoolss_PrinterInfo2 *pinfo2,
    2772             :                                         TALLOC_CTX *mem_ctx)
    2773             : {
    2774             :         /* the notify name should not contain the \\server\ part */
    2775           0 :         const char *p = strrchr(pinfo2->printername, '\\');
    2776             : 
    2777           0 :         if (!p) {
    2778           0 :                 p = pinfo2->printername;
    2779             :         } else {
    2780           0 :                 p++;
    2781             :         }
    2782             : 
    2783           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    2784           0 : }
    2785             : 
    2786             : /*******************************************************************
    2787             :  * fill a notify_info_data with the servicename
    2788             :  ********************************************************************/
    2789             : 
    2790           0 : static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
    2791             :                                       int snum,
    2792             :                                       struct spoolss_Notify *data,
    2793             :                                       print_queue_struct *queue,
    2794             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2795             :                                       TALLOC_CTX *mem_ctx)
    2796             : {
    2797           0 :         const struct loadparm_substitution *lp_sub =
    2798           0 :                 loadparm_s3_global_substitution();
    2799             : 
    2800           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
    2801           0 : }
    2802             : 
    2803             : /*******************************************************************
    2804             :  * fill a notify_info_data with the port name
    2805             :  ********************************************************************/
    2806             : 
    2807           0 : static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
    2808             :                                      int snum,
    2809             :                                      struct spoolss_Notify *data,
    2810             :                                      print_queue_struct *queue,
    2811             :                                      struct spoolss_PrinterInfo2 *pinfo2,
    2812             :                                      TALLOC_CTX *mem_ctx)
    2813             : {
    2814           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
    2815           0 : }
    2816             : 
    2817             : /*******************************************************************
    2818             :  * fill a notify_info_data with the printername
    2819             :  * but it doesn't exist, have to see what to do
    2820             :  ********************************************************************/
    2821             : 
    2822           0 : static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
    2823             :                                        int snum,
    2824             :                                        struct spoolss_Notify *data,
    2825             :                                        print_queue_struct *queue,
    2826             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    2827             :                                        TALLOC_CTX *mem_ctx)
    2828             : {
    2829           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
    2830           0 : }
    2831             : 
    2832             : /*******************************************************************
    2833             :  * fill a notify_info_data with the comment
    2834             :  ********************************************************************/
    2835             : 
    2836           0 : static void spoolss_notify_comment(struct messaging_context *msg_ctx,
    2837             :                                    int snum,
    2838             :                                    struct spoolss_Notify *data,
    2839             :                                    print_queue_struct *queue,
    2840             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2841             :                                    TALLOC_CTX *mem_ctx)
    2842             : {
    2843           0 :         const struct loadparm_substitution *lp_sub =
    2844           0 :                 loadparm_s3_global_substitution();
    2845           0 :         const char *p;
    2846             : 
    2847           0 :         if (*pinfo2->comment == '\0') {
    2848           0 :                 p = lp_comment(talloc_tos(), lp_sub, snum);
    2849             :         } else {
    2850           0 :                 p = pinfo2->comment;
    2851             :         }
    2852             : 
    2853           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    2854           0 : }
    2855             : 
    2856             : /*******************************************************************
    2857             :  * fill a notify_info_data with the comment
    2858             :  * location = "Room 1, floor 2, building 3"
    2859             :  ********************************************************************/
    2860             : 
    2861           0 : static void spoolss_notify_location(struct messaging_context *msg_ctx,
    2862             :                                     int snum,
    2863             :                                     struct spoolss_Notify *data,
    2864             :                                     print_queue_struct *queue,
    2865             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2866             :                                     TALLOC_CTX *mem_ctx)
    2867             : {
    2868           0 :         const char *loc = pinfo2->location;
    2869           0 :         NTSTATUS status;
    2870             : 
    2871           0 :         status = printer_list_get_printer(mem_ctx,
    2872             :                                           pinfo2->sharename,
    2873             :                                           NULL,
    2874             :                                           &loc,
    2875             :                                           NULL);
    2876           0 :         if (NT_STATUS_IS_OK(status)) {
    2877           0 :                 if (loc == NULL) {
    2878           0 :                         loc = pinfo2->location;
    2879             :                 }
    2880             :         }
    2881             : 
    2882           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
    2883           0 : }
    2884             : 
    2885             : /*******************************************************************
    2886             :  * fill a notify_info_data with the device mode
    2887             :  * jfm:xxxx don't to it for know but that's a real problem !!!
    2888             :  ********************************************************************/
    2889             : 
    2890           0 : static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
    2891             :                                    int snum,
    2892             :                                    struct spoolss_Notify *data,
    2893             :                                    print_queue_struct *queue,
    2894             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2895             :                                    TALLOC_CTX *mem_ctx)
    2896             : {
    2897             :         /* for a dummy implementation we have to zero the fields */
    2898           0 :         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
    2899           0 : }
    2900             : 
    2901             : /*******************************************************************
    2902             :  * fill a notify_info_data with the separator file name
    2903             :  ********************************************************************/
    2904             : 
    2905           0 : static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
    2906             :                                    int snum,
    2907             :                                    struct spoolss_Notify *data,
    2908             :                                    print_queue_struct *queue,
    2909             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2910             :                                    TALLOC_CTX *mem_ctx)
    2911             : {
    2912           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
    2913           0 : }
    2914             : 
    2915             : /*******************************************************************
    2916             :  * fill a notify_info_data with the print processor
    2917             :  * jfm:xxxx return always winprint to indicate we don't do anything to it
    2918             :  ********************************************************************/
    2919             : 
    2920           0 : static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
    2921             :                                            int snum,
    2922             :                                            struct spoolss_Notify *data,
    2923             :                                            print_queue_struct *queue,
    2924             :                                            struct spoolss_PrinterInfo2 *pinfo2,
    2925             :                                            TALLOC_CTX *mem_ctx)
    2926             : {
    2927           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
    2928           0 : }
    2929             : 
    2930             : /*******************************************************************
    2931             :  * fill a notify_info_data with the print processor options
    2932             :  * jfm:xxxx send an empty string
    2933             :  ********************************************************************/
    2934             : 
    2935           0 : static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
    2936             :                                       int snum,
    2937             :                                       struct spoolss_Notify *data,
    2938             :                                       print_queue_struct *queue,
    2939             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2940             :                                       TALLOC_CTX *mem_ctx)
    2941             : {
    2942           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
    2943           0 : }
    2944             : 
    2945             : /*******************************************************************
    2946             :  * fill a notify_info_data with the data type
    2947             :  * jfm:xxxx always send RAW as data type
    2948             :  ********************************************************************/
    2949             : 
    2950           0 : static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
    2951             :                                     int snum,
    2952             :                                     struct spoolss_Notify *data,
    2953             :                                     print_queue_struct *queue,
    2954             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2955             :                                     TALLOC_CTX *mem_ctx)
    2956             : {
    2957           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
    2958           0 : }
    2959             : 
    2960             : /*******************************************************************
    2961             :  * fill a notify_info_data with the security descriptor
    2962             :  * jfm:xxxx send an null pointer to say no security desc
    2963             :  * have to implement security before !
    2964             :  ********************************************************************/
    2965             : 
    2966           0 : static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
    2967             :                                          int snum,
    2968             :                                          struct spoolss_Notify *data,
    2969             :                                          print_queue_struct *queue,
    2970             :                                          struct spoolss_PrinterInfo2 *pinfo2,
    2971             :                                          TALLOC_CTX *mem_ctx)
    2972             : {
    2973           0 :         if (pinfo2->secdesc == NULL) {
    2974           0 :                 data->data.sd.sd = NULL;
    2975             :         } else {
    2976           0 :                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
    2977           0 :                                                             pinfo2->secdesc);
    2978             :         }
    2979           0 :         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
    2980             :                                                              0);
    2981           0 : }
    2982             : 
    2983             : /*******************************************************************
    2984             :  * fill a notify_info_data with the attributes
    2985             :  * jfm:xxxx a samba printer is always shared
    2986             :  ********************************************************************/
    2987             : 
    2988           0 : static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
    2989             :                                       int snum,
    2990             :                                       struct spoolss_Notify *data,
    2991             :                                       print_queue_struct *queue,
    2992             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2993             :                                       TALLOC_CTX *mem_ctx)
    2994             : {
    2995           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
    2996           0 : }
    2997             : 
    2998             : /*******************************************************************
    2999             :  * fill a notify_info_data with the priority
    3000             :  ********************************************************************/
    3001             : 
    3002           0 : static void spoolss_notify_priority(struct messaging_context *msg_ctx,
    3003             :                                     int snum,
    3004             :                                     struct spoolss_Notify *data,
    3005             :                                     print_queue_struct *queue,
    3006             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3007             :                                     TALLOC_CTX *mem_ctx)
    3008             : {
    3009           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
    3010           0 : }
    3011             : 
    3012             : /*******************************************************************
    3013             :  * fill a notify_info_data with the default priority
    3014             :  ********************************************************************/
    3015             : 
    3016           0 : static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
    3017             :                                             int snum,
    3018             :                                             struct spoolss_Notify *data,
    3019             :                                             print_queue_struct *queue,
    3020             :                                             struct spoolss_PrinterInfo2 *pinfo2,
    3021             :                                             TALLOC_CTX *mem_ctx)
    3022             : {
    3023           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
    3024           0 : }
    3025             : 
    3026             : /*******************************************************************
    3027             :  * fill a notify_info_data with the start time
    3028             :  ********************************************************************/
    3029             : 
    3030           0 : static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
    3031             :                                       int snum,
    3032             :                                       struct spoolss_Notify *data,
    3033             :                                       print_queue_struct *queue,
    3034             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3035             :                                       TALLOC_CTX *mem_ctx)
    3036             : {
    3037           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
    3038           0 : }
    3039             : 
    3040             : /*******************************************************************
    3041             :  * fill a notify_info_data with the until time
    3042             :  ********************************************************************/
    3043             : 
    3044           0 : static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
    3045             :                                       int snum,
    3046             :                                       struct spoolss_Notify *data,
    3047             :                                       print_queue_struct *queue,
    3048             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3049             :                                       TALLOC_CTX *mem_ctx)
    3050             : {
    3051           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
    3052           0 : }
    3053             : 
    3054             : /*******************************************************************
    3055             :  * fill a notify_info_data with the status
    3056             :  ********************************************************************/
    3057             : 
    3058           0 : static void spoolss_notify_status(struct messaging_context *msg_ctx,
    3059             :                                   int snum,
    3060             :                                   struct spoolss_Notify *data,
    3061             :                                   print_queue_struct *queue,
    3062             :                                   struct spoolss_PrinterInfo2 *pinfo2,
    3063             :                                   TALLOC_CTX *mem_ctx)
    3064             : {
    3065           0 :         print_status_struct status;
    3066             : 
    3067           0 :         print_queue_length(msg_ctx, snum, &status);
    3068           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
    3069           0 : }
    3070             : 
    3071             : /*******************************************************************
    3072             :  * fill a notify_info_data with the number of jobs queued
    3073             :  ********************************************************************/
    3074             : 
    3075           0 : static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
    3076             :                                  int snum,
    3077             :                                  struct spoolss_Notify *data,
    3078             :                                  print_queue_struct *queue,
    3079             :                                  struct spoolss_PrinterInfo2 *pinfo2,
    3080             :                                  TALLOC_CTX *mem_ctx)
    3081             : {
    3082           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
    3083           0 :                 data, print_queue_length(msg_ctx, snum, NULL));
    3084           0 : }
    3085             : 
    3086             : /*******************************************************************
    3087             :  * fill a notify_info_data with the average ppm
    3088             :  ********************************************************************/
    3089             : 
    3090           0 : static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
    3091             :                                        int snum,
    3092             :                                        struct spoolss_Notify *data,
    3093             :                                        print_queue_struct *queue,
    3094             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    3095             :                                        TALLOC_CTX *mem_ctx)
    3096             : {
    3097             :         /* always respond 8 pages per minutes */
    3098             :         /* a little hard ! */
    3099           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
    3100           0 : }
    3101             : 
    3102             : /*******************************************************************
    3103             :  * fill a notify_info_data with username
    3104             :  ********************************************************************/
    3105             : 
    3106           0 : static void spoolss_notify_username(struct messaging_context *msg_ctx,
    3107             :                                     int snum,
    3108             :                                     struct spoolss_Notify *data,
    3109             :                                     print_queue_struct *queue,
    3110             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3111             :                                     TALLOC_CTX *mem_ctx)
    3112             : {
    3113           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
    3114           0 : }
    3115             : 
    3116             : /*******************************************************************
    3117             :  * fill a notify_info_data with job status
    3118             :  ********************************************************************/
    3119             : 
    3120           0 : static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
    3121             :                                       int snum,
    3122             :                                       struct spoolss_Notify *data,
    3123             :                                       print_queue_struct *queue,
    3124             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3125             :                                       TALLOC_CTX *mem_ctx)
    3126             : {
    3127           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
    3128           0 : }
    3129             : 
    3130             : /*******************************************************************
    3131             :  * fill a notify_info_data with job name
    3132             :  ********************************************************************/
    3133             : 
    3134           0 : static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
    3135             :                                     int snum,
    3136             :                                     struct spoolss_Notify *data,
    3137             :                                     print_queue_struct *queue,
    3138             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3139             :                                     TALLOC_CTX *mem_ctx)
    3140             : {
    3141           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
    3142           0 : }
    3143             : 
    3144             : /*******************************************************************
    3145             :  * fill a notify_info_data with job status
    3146             :  ********************************************************************/
    3147             : 
    3148           0 : static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
    3149             :                                              int snum,
    3150             :                                              struct spoolss_Notify *data,
    3151             :                                              print_queue_struct *queue,
    3152             :                                              struct spoolss_PrinterInfo2 *pinfo2,
    3153             :                                              TALLOC_CTX *mem_ctx)
    3154             : {
    3155             :         /*
    3156             :          * Now we're returning job status codes we just return a "" here. JRA.
    3157             :          */
    3158             : 
    3159           0 :         const char *p = "";
    3160             : 
    3161             : #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
    3162             :         p = "unknown";
    3163             : 
    3164             :         switch (queue->status) {
    3165             :         case LPQ_QUEUED:
    3166             :                 p = "Queued";
    3167             :                 break;
    3168             :         case LPQ_PAUSED:
    3169             :                 p = "";    /* NT provides the paused string */
    3170             :                 break;
    3171             :         case LPQ_SPOOLING:
    3172             :                 p = "Spooling";
    3173             :                 break;
    3174             :         case LPQ_PRINTING:
    3175             :                 p = "Printing";
    3176             :                 break;
    3177             :         }
    3178             : #endif /* NO LONGER NEEDED. */
    3179             : 
    3180           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    3181           0 : }
    3182             : 
    3183             : /*******************************************************************
    3184             :  * fill a notify_info_data with job time
    3185             :  ********************************************************************/
    3186             : 
    3187           0 : static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
    3188             :                                     int snum,
    3189             :                                     struct spoolss_Notify *data,
    3190             :                                     print_queue_struct *queue,
    3191             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3192             :                                     TALLOC_CTX *mem_ctx)
    3193             : {
    3194           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
    3195           0 : }
    3196             : 
    3197             : /*******************************************************************
    3198             :  * fill a notify_info_data with job size
    3199             :  ********************************************************************/
    3200             : 
    3201           0 : static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
    3202             :                                     int snum,
    3203             :                                     struct spoolss_Notify *data,
    3204             :                                     print_queue_struct *queue,
    3205             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3206             :                                     TALLOC_CTX *mem_ctx)
    3207             : {
    3208           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
    3209           0 : }
    3210             : 
    3211             : /*******************************************************************
    3212             :  * fill a notify_info_data with page info
    3213             :  ********************************************************************/
    3214           0 : static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
    3215             :                                        int snum,
    3216             :                                 struct spoolss_Notify *data,
    3217             :                                 print_queue_struct *queue,
    3218             :                                 struct spoolss_PrinterInfo2 *pinfo2,
    3219             :                                 TALLOC_CTX *mem_ctx)
    3220             : {
    3221           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
    3222           0 : }
    3223             : 
    3224             : /*******************************************************************
    3225             :  * fill a notify_info_data with pages printed info.
    3226             :  ********************************************************************/
    3227           0 : static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
    3228             :                                          int snum,
    3229             :                                 struct spoolss_Notify *data,
    3230             :                                 print_queue_struct *queue,
    3231             :                                 struct spoolss_PrinterInfo2 *pinfo2,
    3232             :                                 TALLOC_CTX *mem_ctx)
    3233             : {
    3234             :         /* Add code when back-end tracks this */
    3235           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
    3236           0 : }
    3237             : 
    3238             : /*******************************************************************
    3239             :  Fill a notify_info_data with job position.
    3240             :  ********************************************************************/
    3241             : 
    3242           0 : static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
    3243             :                                         int snum,
    3244             :                                         struct spoolss_Notify *data,
    3245             :                                         print_queue_struct *queue,
    3246             :                                         struct spoolss_PrinterInfo2 *pinfo2,
    3247             :                                         TALLOC_CTX *mem_ctx)
    3248             : {
    3249           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
    3250           0 : }
    3251             : 
    3252             : /*******************************************************************
    3253             :  Fill a notify_info_data with submitted time.
    3254             :  ********************************************************************/
    3255             : 
    3256           0 : static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
    3257             :                                           int snum,
    3258             :                                           struct spoolss_Notify *data,
    3259             :                                           print_queue_struct *queue,
    3260             :                                           struct spoolss_PrinterInfo2 *pinfo2,
    3261             :                                           TALLOC_CTX *mem_ctx)
    3262             : {
    3263           0 :         data->data.string.string = NULL;
    3264           0 :         data->data.string.size = 0;
    3265             : 
    3266           0 :         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
    3267             :                                &data->data.string.string,
    3268             :                                &data->data.string.size);
    3269             : 
    3270           0 : }
    3271             : 
    3272             : struct s_notify_info_data_table
    3273             : {
    3274             :         enum spoolss_NotifyType type;
    3275             :         uint16_t field;
    3276             :         const char *name;
    3277             :         enum spoolss_NotifyTable variable_type;
    3278             :         void (*fn) (struct messaging_context *msg_ctx,
    3279             :                     int snum, struct spoolss_Notify *data,
    3280             :                     print_queue_struct *queue,
    3281             :                     struct spoolss_PrinterInfo2 *pinfo2,
    3282             :                     TALLOC_CTX *mem_ctx);
    3283             : };
    3284             : 
    3285             : /* A table describing the various print notification constants and
    3286             :    whether the notification data is a pointer to a variable sized
    3287             :    buffer, a one value uint32_t or a two value uint32_t. */
    3288             : 
    3289             : static const struct s_notify_info_data_table notify_info_data_table[] =
    3290             : {
    3291             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
    3292             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
    3293             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
    3294             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
    3295             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
    3296             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
    3297             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
    3298             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
    3299             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
    3300             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
    3301             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
    3302             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
    3303             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
    3304             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
    3305             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
    3306             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
    3307             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
    3308             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
    3309             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
    3310             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
    3311             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
    3312             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
    3313             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
    3314             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
    3315             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
    3316             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
    3317             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
    3318             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
    3319             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
    3320             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
    3321             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
    3322             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
    3323             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
    3324             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
    3325             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
    3326             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
    3327             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
    3328             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
    3329             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
    3330             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
    3331             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
    3332             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
    3333             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
    3334             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
    3335             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
    3336             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
    3337             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
    3338             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
    3339             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
    3340             : };
    3341             : 
    3342             : /*******************************************************************
    3343             :  Return the variable_type of info_data structure.
    3344             : ********************************************************************/
    3345             : 
    3346           0 : static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
    3347             :                                                                   uint16_t field)
    3348             : {
    3349           0 :         int i=0;
    3350             : 
    3351           0 :         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
    3352           0 :                 if ( (notify_info_data_table[i].type == type) &&
    3353           0 :                      (notify_info_data_table[i].field == field) ) {
    3354           0 :                         return notify_info_data_table[i].variable_type;
    3355             :                 }
    3356             :         }
    3357             : 
    3358           0 :         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
    3359             : 
    3360           0 :         return (enum spoolss_NotifyTable) 0;
    3361             : }
    3362             : 
    3363             : /****************************************************************************
    3364             : ****************************************************************************/
    3365             : 
    3366           0 : static bool search_notify(enum spoolss_NotifyType type,
    3367             :                           uint16_t field,
    3368             :                           int *value)
    3369             : {
    3370           0 :         int i;
    3371             : 
    3372           0 :         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
    3373           0 :                 if (notify_info_data_table[i].type == type &&
    3374           0 :                     notify_info_data_table[i].field == field &&
    3375           0 :                     notify_info_data_table[i].fn != NULL) {
    3376           0 :                         *value = i;
    3377           0 :                         return true;
    3378             :                 }
    3379             :         }
    3380             : 
    3381           0 :         return false;
    3382             : }
    3383             : 
    3384             : /****************************************************************************
    3385             : ****************************************************************************/
    3386             : 
    3387           0 : static void construct_info_data(struct spoolss_Notify *info_data,
    3388             :                                 enum spoolss_NotifyType type,
    3389             :                                 uint16_t field, int id)
    3390             : {
    3391           0 :         info_data->type                      = type;
    3392           0 :         info_data->field.field               = field;
    3393           0 :         info_data->variable_type     = variable_type_of_notify_info_data(type, field);
    3394           0 :         info_data->job_id            = id;
    3395           0 : }
    3396             : 
    3397             : /*******************************************************************
    3398             :  *
    3399             :  * fill a notify_info struct with info asked
    3400             :  *
    3401             :  ********************************************************************/
    3402             : 
    3403           0 : static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
    3404             :                                           struct printer_handle *print_hnd,
    3405             :                                           struct spoolss_NotifyInfo *info,
    3406             :                                           struct spoolss_PrinterInfo2 *pinfo2,
    3407             :                                           int snum,
    3408             :                                           const struct spoolss_NotifyOptionType *option_type,
    3409             :                                           uint32_t id,
    3410             :                                           TALLOC_CTX *mem_ctx)
    3411             : {
    3412           0 :         const struct loadparm_substitution *lp_sub =
    3413           0 :                 loadparm_s3_global_substitution();
    3414           0 :         int field_num,j;
    3415           0 :         enum spoolss_NotifyType type;
    3416           0 :         uint16_t field;
    3417             : 
    3418           0 :         struct spoolss_Notify *current_data;
    3419             : 
    3420           0 :         type = option_type->type;
    3421             : 
    3422           0 :         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
    3423             :                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
    3424             :                 option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
    3425             : 
    3426           0 :         for(field_num=0; field_num < option_type->count; field_num++) {
    3427           0 :                 field = option_type->fields[field_num].field;
    3428             : 
    3429           0 :                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
    3430             : 
    3431           0 :                 if (!search_notify(type, field, &j) )
    3432           0 :                         continue;
    3433             : 
    3434           0 :                 info->notifies = talloc_realloc(info, info->notifies,
    3435             :                                                       struct spoolss_Notify,
    3436             :                                                       info->count + 1);
    3437           0 :                 if (info->notifies == NULL) {
    3438           0 :                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
    3439           0 :                         return false;
    3440             :                 }
    3441             : 
    3442           0 :                 current_data = &info->notifies[info->count];
    3443             : 
    3444           0 :                 construct_info_data(current_data, type, field, id);
    3445             : 
    3446           0 :                 DEBUG(10, ("construct_notify_printer_info: "
    3447             :                            "calling [%s]  snum=%d  printername=[%s])\n",
    3448             :                            notify_info_data_table[j].name, snum,
    3449             :                            pinfo2->printername));
    3450             : 
    3451           0 :                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
    3452             :                                              NULL, pinfo2, mem_ctx);
    3453             : 
    3454           0 :                 info->count++;
    3455             :         }
    3456             : 
    3457           0 :         return true;
    3458             : }
    3459             : 
    3460             : /*******************************************************************
    3461             :  *
    3462             :  * fill a notify_info struct with info asked
    3463             :  *
    3464             :  ********************************************************************/
    3465             : 
    3466           0 : static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
    3467             :                                        print_queue_struct *queue,
    3468             :                                        struct spoolss_NotifyInfo *info,
    3469             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    3470             :                                        int snum,
    3471             :                                        const struct spoolss_NotifyOptionType *option_type,
    3472             :                                        uint32_t id,
    3473             :                                        TALLOC_CTX *mem_ctx)
    3474             : {
    3475           0 :         int field_num,j;
    3476           0 :         enum spoolss_NotifyType type;
    3477           0 :         uint16_t field;
    3478           0 :         struct spoolss_Notify *current_data;
    3479             : 
    3480           0 :         DEBUG(4,("construct_notify_jobs_info\n"));
    3481             : 
    3482           0 :         type = option_type->type;
    3483             : 
    3484           0 :         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
    3485             :                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
    3486             :                 option_type->count));
    3487             : 
    3488           0 :         for(field_num=0; field_num<option_type->count; field_num++) {
    3489           0 :                 field = option_type->fields[field_num].field;
    3490             : 
    3491           0 :                 if (!search_notify(type, field, &j) )
    3492           0 :                         continue;
    3493             : 
    3494           0 :                 info->notifies = talloc_realloc(info, info->notifies,
    3495             :                                                       struct spoolss_Notify,
    3496             :                                                       info->count + 1);
    3497           0 :                 if (info->notifies == NULL) {
    3498           0 :                         DEBUG(2,("construct_notify_jobs_info: failed to enlarge buffer info->data!\n"));
    3499           0 :                         return false;
    3500             :                 }
    3501             : 
    3502           0 :                 current_data=&(info->notifies[info->count]);
    3503             : 
    3504           0 :                 construct_info_data(current_data, type, field, id);
    3505           0 :                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
    3506             :                                              queue, pinfo2, mem_ctx);
    3507           0 :                 info->count++;
    3508             :         }
    3509             : 
    3510           0 :         return true;
    3511             : }
    3512             : 
    3513             : /*
    3514             :  * JFM: The enumeration is not that simple, it's even non obvious.
    3515             :  *
    3516             :  * let's take an example: I want to monitor the PRINTER SERVER for
    3517             :  * the printer's name and the number of jobs currently queued.
    3518             :  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
    3519             :  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
    3520             :  *
    3521             :  * I have 3 printers on the back of my server.
    3522             :  *
    3523             :  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
    3524             :  * structures.
    3525             :  *   Number     Data                    Id
    3526             :  *      1       printer 1 name          1
    3527             :  *      2       printer 1 cjob          1
    3528             :  *      3       printer 2 name          2
    3529             :  *      4       printer 2 cjob          2
    3530             :  *      5       printer 3 name          3
    3531             :  *      6       printer 3 name          3
    3532             :  *
    3533             :  * that's the print server case, the printer case is even worse.
    3534             :  */
    3535             : 
    3536             : /*******************************************************************
    3537             :  *
    3538             :  * enumerate all printers on the printserver
    3539             :  * fill a notify_info struct with info asked
    3540             :  *
    3541             :  ********************************************************************/
    3542             : 
    3543           4 : static WERROR printserver_notify_info(struct pipes_struct *p,
    3544             :                                       struct policy_handle *hnd,
    3545             :                                       struct spoolss_NotifyInfo *info,
    3546             :                                       TALLOC_CTX *mem_ctx)
    3547             : {
    3548           0 :         const struct loadparm_substitution *lp_sub =
    3549           4 :                 loadparm_s3_global_substitution();
    3550           0 :         int snum;
    3551           4 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
    3552           4 :         int n_services=lp_numservices();
    3553           0 :         int i;
    3554           0 :         struct spoolss_NotifyOption *option;
    3555           0 :         struct spoolss_NotifyOptionType option_type;
    3556           4 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    3557           0 :         WERROR result;
    3558             : 
    3559           4 :         DEBUG(4,("printserver_notify_info\n"));
    3560             : 
    3561           4 :         if (!Printer)
    3562           0 :                 return WERR_INVALID_HANDLE;
    3563             : 
    3564           4 :         option = Printer->notify.option;
    3565             : 
    3566           4 :         info->version        = 2;
    3567           4 :         info->notifies       = NULL;
    3568           4 :         info->count  = 0;
    3569             : 
    3570             :         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
    3571             :            sending a ffpcn() request first */
    3572             : 
    3573           4 :         if ( !option )
    3574           0 :                 return WERR_INVALID_HANDLE;
    3575             : 
    3576          12 :         for (i=0; i<option->count; i++) {
    3577           8 :                 option_type = option->types[i];
    3578             : 
    3579           8 :                 if (option_type.type != PRINTER_NOTIFY_TYPE)
    3580           4 :                         continue;
    3581             : 
    3582         492 :                 for (snum = 0; snum < n_services; snum++) {
    3583         488 :                         if (!lp_browseable(snum) ||
    3584         488 :                             !lp_snum_ok(snum) ||
    3585         488 :                             !lp_printable(snum)) {
    3586         468 :                                 continue; /* skip */
    3587             :                         }
    3588             : 
    3589             :                         /* Maybe we should use the SYSTEM session_info here... */
    3590          20 :                         result = winreg_get_printer_internal(mem_ctx,
    3591             :                                                     get_session_info_system(),
    3592             :                                                     p->msg_ctx,
    3593          20 :                                                     lp_servicename(talloc_tos(), lp_sub, snum),
    3594             :                                                     &pinfo2);
    3595          20 :                         if (!W_ERROR_IS_OK(result)) {
    3596          20 :                                 DEBUG(4, ("printserver_notify_info: "
    3597             :                                           "Failed to get printer [%s]\n",
    3598             :                                           lp_servicename(talloc_tos(), lp_sub, snum)));
    3599          20 :                                 continue;
    3600             :                         }
    3601             : 
    3602             : 
    3603           0 :                         construct_notify_printer_info(p->msg_ctx,
    3604             :                                                       Printer, info,
    3605             :                                                       pinfo2, snum,
    3606             :                                                       &option_type, snum,
    3607             :                                                       mem_ctx);
    3608             : 
    3609           0 :                         TALLOC_FREE(pinfo2);
    3610             :                 }
    3611             :         }
    3612             : 
    3613             : #if 0
    3614             :         /*
    3615             :          * Debugging information, don't delete.
    3616             :          */
    3617             : 
    3618             :         DEBUG(1,("dumping the NOTIFY_INFO\n"));
    3619             :         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
    3620             :         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
    3621             : 
    3622             :         for (i=0; i<info->count; i++) {
    3623             :                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
    3624             :                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
    3625             :                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
    3626             :         }
    3627             : #endif
    3628             : 
    3629           4 :         return WERR_OK;
    3630             : }
    3631             : 
    3632             : /*******************************************************************
    3633             :  *
    3634             :  * fill a notify_info struct with info asked
    3635             :  *
    3636             :  ********************************************************************/
    3637             : 
    3638           0 : static WERROR printer_notify_info(struct pipes_struct *p,
    3639             :                                   struct policy_handle *hnd,
    3640             :                                   struct spoolss_NotifyInfo *info,
    3641             :                                   TALLOC_CTX *mem_ctx)
    3642             : {
    3643           0 :         const struct loadparm_substitution *lp_sub =
    3644           0 :                 loadparm_s3_global_substitution();
    3645           0 :         int snum;
    3646           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
    3647           0 :         int i;
    3648           0 :         uint32_t id;
    3649           0 :         struct spoolss_NotifyOption *option;
    3650           0 :         struct spoolss_NotifyOptionType option_type;
    3651           0 :         int count,j;
    3652           0 :         print_queue_struct *queue=NULL;
    3653           0 :         print_status_struct status;
    3654           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    3655           0 :         WERROR result;
    3656           0 :         struct tdb_print_db *pdb;
    3657             : 
    3658           0 :         DEBUG(4,("printer_notify_info\n"));
    3659             : 
    3660           0 :         if (!Printer)
    3661           0 :                 return WERR_INVALID_HANDLE;
    3662             : 
    3663           0 :         option = Printer->notify.option;
    3664           0 :         id = 0x0;
    3665             : 
    3666           0 :         info->version        = 2;
    3667           0 :         info->notifies       = NULL;
    3668           0 :         info->count  = 0;
    3669             : 
    3670             :         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
    3671             :            sending a ffpcn() request first */
    3672             : 
    3673           0 :         if ( !option )
    3674           0 :                 return WERR_INVALID_HANDLE;
    3675             : 
    3676           0 :         if (!get_printer_snum(p, hnd, &snum, NULL)) {
    3677           0 :                 return WERR_INVALID_HANDLE;
    3678             :         }
    3679             : 
    3680           0 :         pdb = get_print_db_byname(Printer->sharename);
    3681           0 :         if (pdb == NULL) {
    3682           0 :                 return WERR_INVALID_HANDLE;
    3683             :         }
    3684             : 
    3685             :         /* Maybe we should use the SYSTEM session_info here... */
    3686           0 :         result = winreg_get_printer_internal(mem_ctx,
    3687             :                                     get_session_info_system(),
    3688             :                                     p->msg_ctx,
    3689           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
    3690           0 :         if (!W_ERROR_IS_OK(result)) {
    3691           0 :                 result = WERR_INVALID_HANDLE;
    3692           0 :                 goto err_pdb_drop;
    3693             :         }
    3694             : 
    3695             :         /*
    3696             :          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
    3697             :          * correct servername.
    3698             :          */
    3699           0 :         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
    3700           0 :         if (pinfo2->servername == NULL) {
    3701           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3702           0 :                 goto err_pdb_drop;
    3703             :         }
    3704             : 
    3705           0 :         for (i = 0; i < option->count; i++) {
    3706           0 :                 option_type = option->types[i];
    3707             : 
    3708           0 :                 switch (option_type.type) {
    3709           0 :                 case PRINTER_NOTIFY_TYPE:
    3710           0 :                         if (construct_notify_printer_info(p->msg_ctx,
    3711             :                                                           Printer, info,
    3712             :                                                           pinfo2, snum,
    3713             :                                                           &option_type, id,
    3714             :                                                           mem_ctx)) {
    3715           0 :                                 id--;
    3716             :                         }
    3717           0 :                         break;
    3718             : 
    3719           0 :                 case JOB_NOTIFY_TYPE:
    3720             : 
    3721           0 :                         count = print_queue_status(p->msg_ctx, snum, &queue,
    3722             :                                                    &status);
    3723             : 
    3724           0 :                         for (j = 0; j < count; j++) {
    3725           0 :                                 uint32_t jobid;
    3726           0 :                                 jobid = sysjob_to_jobid_pdb(pdb,
    3727           0 :                                                             queue[j].sysjob);
    3728           0 :                                 if (jobid == (uint32_t)-1) {
    3729           0 :                                         DEBUG(2, ("ignoring untracked job %d\n",
    3730             :                                                   queue[j].sysjob));
    3731           0 :                                         continue;
    3732             :                                 }
    3733             :                                 /* FIXME check return value */
    3734           0 :                                 construct_notify_jobs_info(p->msg_ctx,
    3735           0 :                                                            &queue[j], info,
    3736             :                                                            pinfo2, snum,
    3737             :                                                            &option_type,
    3738             :                                                            jobid,
    3739             :                                                            mem_ctx);
    3740             :                         }
    3741             : 
    3742           0 :                         SAFE_FREE(queue);
    3743           0 :                         break;
    3744             :                 }
    3745             :         }
    3746             : 
    3747             :         /*
    3748             :          * Debugging information, don't delete.
    3749             :          */
    3750             :         /*
    3751             :         DEBUG(1,("dumping the NOTIFY_INFO\n"));
    3752             :         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
    3753             :         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
    3754             : 
    3755             :         for (i=0; i<info->count; i++) {
    3756             :                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
    3757             :                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
    3758             :                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
    3759             :         }
    3760             :         */
    3761             : 
    3762           0 :         talloc_free(pinfo2);
    3763           0 :         result = WERR_OK;
    3764           0 : err_pdb_drop:
    3765           0 :         release_print_db(pdb);
    3766           0 :         return result;
    3767             : }
    3768             : 
    3769             : /****************************************************************
    3770             :  _spoolss_RouterRefreshPrinterChangeNotify
    3771             : ****************************************************************/
    3772             : 
    3773           4 : WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
    3774             :                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
    3775             : {
    3776           0 :         struct spoolss_NotifyInfo *info;
    3777             : 
    3778           4 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    3779           4 :         WERROR result = WERR_INVALID_HANDLE;
    3780             : 
    3781             :         /* we always have a spoolss_NotifyInfo struct */
    3782           4 :         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
    3783           4 :         if (!info) {
    3784           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3785           0 :                 goto done;
    3786             :         }
    3787             : 
    3788           4 :         *r->out.info = info;
    3789             : 
    3790           4 :         if (!Printer) {
    3791           0 :                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
    3792             :                         "Invalid handle (%s:%u:%u).\n",
    3793             :                         OUR_HANDLE(r->in.handle)));
    3794           0 :                 goto done;
    3795             :         }
    3796             : 
    3797           4 :         DEBUG(4,("Printer type %x\n",Printer->printer_type));
    3798             : 
    3799             :         /*
    3800             :          *      We are now using the change value, and
    3801             :          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
    3802             :          *      I don't have a global notification system, I'm sending back all the
    3803             :          *      information even when _NOTHING_ has changed.
    3804             :          */
    3805             : 
    3806             :         /* We need to keep track of the change value to send back in
    3807             :            RRPCN replies otherwise our updates are ignored. */
    3808             : 
    3809           4 :         Printer->notify.fnpcn = true;
    3810             : 
    3811           4 :         if (Printer->notify.cli_chan != NULL &&
    3812           4 :             Printer->notify.cli_chan->active_connections > 0) {
    3813           4 :                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
    3814             :                         "Saving change value in request [%x]\n",
    3815             :                         r->in.change_low));
    3816           4 :                 Printer->notify.change = r->in.change_low;
    3817             :         }
    3818             : 
    3819             :         /* just ignore the spoolss_NotifyOption */
    3820             : 
    3821           4 :         switch (Printer->printer_type) {
    3822           4 :                 case SPLHND_SERVER:
    3823           4 :                         result = printserver_notify_info(p, r->in.handle,
    3824             :                                                          info, p->mem_ctx);
    3825           4 :                         break;
    3826             : 
    3827           0 :                 case SPLHND_PRINTER:
    3828           0 :                         result = printer_notify_info(p, r->in.handle,
    3829             :                                                      info, p->mem_ctx);
    3830           0 :                         break;
    3831             :         }
    3832             : 
    3833           4 :         Printer->notify.fnpcn = false;
    3834             : 
    3835           4 : done:
    3836           4 :         return result;
    3837             : }
    3838             : 
    3839             : /********************************************************************
    3840             :  ********************************************************************/
    3841             : 
    3842        4076 : static WERROR create_printername(TALLOC_CTX *mem_ctx,
    3843             :                                  const char *servername,
    3844             :                                  const char *printername,
    3845             :                                  const char **printername_p)
    3846             : {
    3847             :         /* FIXME: add lp_force_printername() */
    3848             : 
    3849        4076 :         if (servername == NULL) {
    3850        1732 :                 *printername_p = talloc_strdup(mem_ctx, printername);
    3851        1732 :                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
    3852        1732 :                 return WERR_OK;
    3853             :         }
    3854             : 
    3855        2344 :         if (servername[0] == '\\' && servername[1] == '\\') {
    3856        2344 :                 servername += 2;
    3857             :         }
    3858             : 
    3859        2344 :         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
    3860        2344 :         W_ERROR_HAVE_NO_MEMORY(*printername_p);
    3861             : 
    3862        2344 :         return WERR_OK;
    3863             : }
    3864             : 
    3865             : /********************************************************************
    3866             :  ********************************************************************/
    3867             : 
    3868        2936 : static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
    3869             :                                           const char *printername)
    3870             : {
    3871        2936 :         if (dm == NULL) {
    3872          94 :                 return;
    3873             :         }
    3874             : 
    3875        2842 :         dm->devicename = talloc_strndup(dm, printername,
    3876        2842 :                                         MIN(strlen(printername), 31));
    3877             : }
    3878             : 
    3879             : /********************************************************************
    3880             :  * construct_printer_info_0
    3881             :  * fill a printer_info_0 struct
    3882             :  ********************************************************************/
    3883             : 
    3884         276 : static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
    3885             :                                       const struct auth_session_info *session_info,
    3886             :                                       struct messaging_context *msg_ctx,
    3887             :                                       struct spoolss_PrinterInfo2 *info2,
    3888             :                                       const char *servername,
    3889             :                                       struct spoolss_PrinterInfo0 *r,
    3890             :                                       int snum)
    3891             : {
    3892           0 :         int count;
    3893           0 :         struct printer_session_counter *session_counter;
    3894           0 :         struct timeval setuptime;
    3895           0 :         print_status_struct status;
    3896           0 :         WERROR result;
    3897           0 :         int os_major, os_minor, os_build;
    3898           0 :         const char *architecture;
    3899           0 :         uint32_t processor_architecture, processor_type;
    3900             : 
    3901         276 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    3902         276 :         if (!W_ERROR_IS_OK(result)) {
    3903           0 :                 return result;
    3904             :         }
    3905             : 
    3906         276 :         if (servername) {
    3907         140 :                 r->servername = talloc_strdup(mem_ctx, servername);
    3908         140 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    3909             :         } else {
    3910         136 :                 r->servername = NULL;
    3911             :         }
    3912             : 
    3913         276 :         count = print_queue_length(msg_ctx, snum, &status);
    3914             : 
    3915             :         /* check if we already have a counter for this printer */
    3916         660 :         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
    3917         620 :                 if (session_counter->snum == snum)
    3918         236 :                         break;
    3919             :         }
    3920             : 
    3921             :         /* it's the first time, add it to the list */
    3922         276 :         if (session_counter == NULL) {
    3923          40 :                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
    3924          40 :                 W_ERROR_HAVE_NO_MEMORY(session_counter);
    3925          40 :                 session_counter->snum                = snum;
    3926          40 :                 session_counter->counter     = 0;
    3927          40 :                 DLIST_ADD(counter_list, session_counter);
    3928             :         }
    3929             : 
    3930             :         /* increment it */
    3931         276 :         session_counter->counter++;
    3932             : 
    3933         276 :         r->cjobs                     = count;
    3934         276 :         r->total_jobs                        = 0;
    3935         276 :         r->total_bytes                       = 0;
    3936             : 
    3937         276 :         get_startup_time(&setuptime);
    3938         276 :         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
    3939             : 
    3940             :         /* JFM:
    3941             :          * the global_counter should be stored in a TDB as it's common to all the clients
    3942             :          * and should be zeroed on samba startup
    3943             :          */
    3944         276 :         r->global_counter            = session_counter->counter;
    3945         276 :         r->total_pages                       = 0;
    3946             : 
    3947             :         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
    3948         276 :         os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
    3949             :                                "spoolss", "os_major",
    3950             :                                GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
    3951         276 :         os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
    3952             :                                "spoolss", "os_minor",
    3953             :                                GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
    3954         276 :         os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
    3955             :                                "spoolss", "os_build",
    3956             :                                GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
    3957             : 
    3958         276 :         SCVAL(&r->version, 0, os_major);
    3959         276 :         SCVAL(&r->version, 1, os_minor);
    3960         276 :         SSVAL(&r->version, 2, os_build);
    3961             : 
    3962         276 :         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    3963             :                                             "spoolss",
    3964             :                                             "architecture",
    3965             :                                             GLOBAL_SPOOLSS_ARCHITECTURE);
    3966             : 
    3967         276 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
    3968         276 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_AMD64;
    3969         276 :                 processor_type          = PROCESSOR_AMD_X8664;
    3970           0 :         } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
    3971           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_ARM64;
    3972           0 :                 processor_type          = PROCESSOR_ARM820;
    3973             :         } else {
    3974           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_INTEL;
    3975           0 :                 processor_type          = PROCESSOR_INTEL_PENTIUM;
    3976             :         }
    3977             : 
    3978         276 :         r->free_build                        = SPOOLSS_RELEASE_BUILD;
    3979         276 :         r->spooling                  = 0;
    3980         276 :         r->max_spooling                      = 0;
    3981         276 :         r->session_counter           = session_counter->counter;
    3982         276 :         r->num_error_out_of_paper    = 0x0;
    3983         276 :         r->num_error_not_ready               = 0x0;          /* number of print failure */
    3984         276 :         r->job_error                 = 0x0;
    3985         276 :         r->number_of_processors              = 0x1;
    3986         276 :         r->processor_type            = processor_type;
    3987         276 :         r->high_part_total_bytes     = 0x0;
    3988             : 
    3989             :         /* ChangeID in milliseconds*/
    3990         276 :         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
    3991             :                                     info2->sharename, &r->change_id);
    3992             : 
    3993         276 :         r->last_error                        = WERR_OK;
    3994         276 :         r->status                    = nt_printq_status(status.status);
    3995         276 :         r->enumerate_network_printers        = 0x0;
    3996         276 :         r->c_setprinter                      = 0x0;
    3997         276 :         r->processor_architecture    = processor_architecture;
    3998         276 :         r->processor_level           = 0x6;          /* 6  ???*/
    3999         276 :         r->ref_ic                    = 0;
    4000         276 :         r->reserved2                 = 0;
    4001         276 :         r->reserved3                 = 0;
    4002             : 
    4003         276 :         return WERR_OK;
    4004             : }
    4005             : 
    4006             : 
    4007             : /********************************************************************
    4008             :  * construct_printer_info1
    4009             :  * fill a spoolss_PrinterInfo1 struct
    4010             : ********************************************************************/
    4011             : 
    4012         528 : static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
    4013             :                                       const struct spoolss_PrinterInfo2 *info2,
    4014             :                                       uint32_t flags,
    4015             :                                       const char *servername,
    4016             :                                       struct spoolss_PrinterInfo1 *r,
    4017             :                                       int snum)
    4018             : {
    4019           0 :         const struct loadparm_substitution *lp_sub =
    4020         528 :                 loadparm_s3_global_substitution();
    4021           0 :         WERROR result;
    4022             : 
    4023         528 :         r->flags             = flags;
    4024             : 
    4025         528 :         if (info2->comment == NULL || info2->comment[0] == '\0') {
    4026         388 :                 r->comment   = lp_comment(mem_ctx, lp_sub, snum);
    4027             :         } else {
    4028         140 :                 r->comment   = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
    4029             :         }
    4030         528 :         W_ERROR_HAVE_NO_MEMORY(r->comment);
    4031             : 
    4032         528 :         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
    4033         528 :         if (!W_ERROR_IS_OK(result)) {
    4034           0 :                 return result;
    4035             :         }
    4036             : 
    4037        1056 :         r->description               = talloc_asprintf(mem_ctx, "%s,%s,%s",
    4038             :                                                   r->name,
    4039         528 :                                                   info2->drivername,
    4040             :                                                   r->comment);
    4041         528 :         W_ERROR_HAVE_NO_MEMORY(r->description);
    4042             : 
    4043         528 :         return WERR_OK;
    4044             : }
    4045             : 
    4046             : /********************************************************************
    4047             :  * construct_printer_info2
    4048             :  * fill a spoolss_PrinterInfo2 struct
    4049             : ********************************************************************/
    4050             : 
    4051        1272 : static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
    4052             :                                       struct messaging_context *msg_ctx,
    4053             :                                       const struct spoolss_PrinterInfo2 *info2,
    4054             :                                       const char *servername,
    4055             :                                       struct spoolss_PrinterInfo2 *r,
    4056             :                                       int snum)
    4057             : {
    4058           0 :         const struct loadparm_substitution *lp_sub =
    4059        1272 :                 loadparm_s3_global_substitution();
    4060           0 :         int count;
    4061           0 :         print_status_struct status;
    4062           0 :         WERROR result;
    4063             : 
    4064        1272 :         count = print_queue_length(msg_ctx, snum, &status);
    4065             : 
    4066        1272 :         if (servername) {
    4067         572 :                 r->servername                = talloc_strdup(mem_ctx, servername);
    4068         572 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    4069             :         } else {
    4070         700 :                 r->servername                = NULL;
    4071             :         }
    4072             : 
    4073        1272 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4074        1272 :         if (!W_ERROR_IS_OK(result)) {
    4075           0 :                 return result;
    4076             :         }
    4077             : 
    4078        1272 :         r->sharename         = lp_servicename(mem_ctx, lp_sub, snum);
    4079        1272 :         W_ERROR_HAVE_NO_MEMORY(r->sharename);
    4080        1272 :         r->portname          = talloc_strdup(mem_ctx, info2->portname);
    4081        1272 :         W_ERROR_HAVE_NO_MEMORY(r->portname);
    4082        1272 :         r->drivername                = talloc_strdup(mem_ctx, info2->drivername);
    4083        1272 :         W_ERROR_HAVE_NO_MEMORY(r->drivername);
    4084             : 
    4085        1272 :         if (info2->comment[0] == '\0') {
    4086         876 :                 r->comment   = lp_comment(mem_ctx, lp_sub, snum);
    4087             :         } else {
    4088         396 :                 r->comment   = talloc_strdup(mem_ctx, info2->comment);
    4089             :         }
    4090        1272 :         W_ERROR_HAVE_NO_MEMORY(r->comment);
    4091             : 
    4092        1272 :         r->location  = talloc_strdup(mem_ctx, info2->location);
    4093        1272 :         if (info2->location[0] == '\0') {
    4094        1192 :                 const char *loc = NULL;
    4095           0 :                 NTSTATUS nt_status;
    4096             : 
    4097        1192 :                 nt_status = printer_list_get_printer(mem_ctx,
    4098        1192 :                                                      info2->sharename,
    4099             :                                                      NULL,
    4100             :                                                      &loc,
    4101             :                                                      NULL);
    4102        1192 :                 if (NT_STATUS_IS_OK(nt_status)) {
    4103           0 :                         if (loc != NULL) {
    4104           0 :                                 r->location = talloc_strdup(mem_ctx, loc);
    4105             :                         }
    4106             :                 }
    4107             :         }
    4108        1272 :         W_ERROR_HAVE_NO_MEMORY(r->location);
    4109             : 
    4110        1272 :         r->sepfile           = talloc_strdup(mem_ctx, info2->sepfile);
    4111        1272 :         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
    4112        1272 :         r->printprocessor    = talloc_strdup(mem_ctx, info2->printprocessor);
    4113        1272 :         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
    4114        1272 :         r->datatype          = talloc_strdup(mem_ctx, info2->datatype);
    4115        1272 :         W_ERROR_HAVE_NO_MEMORY(r->datatype);
    4116        1272 :         r->parameters                = talloc_strdup(mem_ctx, info2->parameters);
    4117        1272 :         W_ERROR_HAVE_NO_MEMORY(r->parameters);
    4118             : 
    4119        1272 :         r->attributes                = info2->attributes;
    4120             : 
    4121        1272 :         r->priority          = info2->priority;
    4122        1272 :         r->defaultpriority   = info2->defaultpriority;
    4123        1272 :         r->starttime         = info2->starttime;
    4124        1272 :         r->untiltime         = info2->untiltime;
    4125        1272 :         r->status            = nt_printq_status(status.status);
    4126        1272 :         r->cjobs             = count;
    4127        1272 :         r->averageppm                = info2->averageppm;
    4128             : 
    4129        1272 :         if (info2->devmode != NULL) {
    4130        1186 :                 result = copy_devicemode(mem_ctx,
    4131        1186 :                                          info2->devmode,
    4132             :                                          &r->devmode);
    4133        1186 :                 if (!W_ERROR_IS_OK(result)) {
    4134           0 :                         return result;
    4135             :                 }
    4136          86 :         } else if (lp_default_devmode(snum)) {
    4137           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    4138           0 :                                                         info2->printername,
    4139             :                                                         &r->devmode);
    4140           0 :                 if (!W_ERROR_IS_OK(result)) {
    4141           0 :                         return result;
    4142             :                 }
    4143             :         } else {
    4144          86 :                 r->devmode = NULL;
    4145          86 :                 DEBUG(8,("Returning NULL Devicemode!\n"));
    4146             :         }
    4147             : 
    4148        1272 :         compose_devicemode_devicename(r->devmode, r->printername);
    4149             : 
    4150        1272 :         r->secdesc = NULL;
    4151             : 
    4152        1272 :         if (info2->secdesc != NULL) {
    4153             :                 /* don't use talloc_steal() here unless you do a deep steal of all
    4154             :                    the SEC_DESC members */
    4155             : 
    4156        1272 :                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
    4157        1272 :                 if (r->secdesc == NULL) {
    4158           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    4159             :                 }
    4160             :         }
    4161             : 
    4162        1272 :         return WERR_OK;
    4163             : }
    4164             : 
    4165             : /********************************************************************
    4166             :  * construct_printer_info3
    4167             :  * fill a spoolss_PrinterInfo3 struct
    4168             :  ********************************************************************/
    4169             : 
    4170         144 : static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
    4171             :                                       const struct spoolss_PrinterInfo2 *info2,
    4172             :                                       const char *servername,
    4173             :                                       struct spoolss_PrinterInfo3 *r,
    4174             :                                       int snum)
    4175             : {
    4176             :         /* These are the components of the SD we are returning. */
    4177             : 
    4178         144 :         if (info2->secdesc != NULL) {
    4179             :                 /* don't use talloc_steal() here unless you do a deep steal of all
    4180             :                    the SEC_DESC members */
    4181             : 
    4182         144 :                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
    4183         144 :                 if (r->secdesc == NULL) {
    4184           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    4185             :                 }
    4186             :         }
    4187             : 
    4188         144 :         return WERR_OK;
    4189             : }
    4190             : 
    4191             : /********************************************************************
    4192             :  * construct_printer_info4
    4193             :  * fill a spoolss_PrinterInfo4 struct
    4194             :  ********************************************************************/
    4195             : 
    4196         168 : static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
    4197             :                                       const struct spoolss_PrinterInfo2 *info2,
    4198             :                                       const char *servername,
    4199             :                                       struct spoolss_PrinterInfo4 *r,
    4200             :                                       int snum)
    4201             : {
    4202           0 :         WERROR result;
    4203             : 
    4204         168 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4205         168 :         if (!W_ERROR_IS_OK(result)) {
    4206           0 :                 return result;
    4207             :         }
    4208             : 
    4209         168 :         if (servername) {
    4210           8 :                 r->servername        = talloc_strdup(mem_ctx, servername);
    4211           8 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    4212             :         } else {
    4213         160 :                 r->servername = NULL;
    4214             :         }
    4215             : 
    4216         168 :         r->attributes        = info2->attributes;
    4217             : 
    4218         168 :         return WERR_OK;
    4219             : }
    4220             : 
    4221             : /********************************************************************
    4222             :  * construct_printer_info5
    4223             :  * fill a spoolss_PrinterInfo5 struct
    4224             :  ********************************************************************/
    4225             : 
    4226         168 : static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
    4227             :                                       const struct spoolss_PrinterInfo2 *info2,
    4228             :                                       const char *servername,
    4229             :                                       struct spoolss_PrinterInfo5 *r,
    4230             :                                       int snum)
    4231             : {
    4232           0 :         WERROR result;
    4233             : 
    4234         168 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4235         168 :         if (!W_ERROR_IS_OK(result)) {
    4236           0 :                 return result;
    4237             :         }
    4238             : 
    4239         168 :         r->portname  = talloc_strdup(mem_ctx, info2->portname);
    4240         168 :         W_ERROR_HAVE_NO_MEMORY(r->portname);
    4241             : 
    4242         168 :         r->attributes        = info2->attributes;
    4243             : 
    4244             :         /*
    4245             :          * These two are not used by NT+ according to MSDN. However the values
    4246             :          * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
    4247             :          */
    4248         168 :         r->device_not_selected_timeout               = 0xafc8; /* 45 sec */
    4249         168 :         r->transmission_retry_timeout                = 0xafc8; /* 45 sec */
    4250             : 
    4251         168 :         return WERR_OK;
    4252             : }
    4253             : 
    4254             : /********************************************************************
    4255             :  * construct_printer_info_6
    4256             :  * fill a spoolss_PrinterInfo6 struct
    4257             :  ********************************************************************/
    4258             : 
    4259          88 : static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
    4260             :                                       struct messaging_context *msg_ctx,
    4261             :                                       const struct spoolss_PrinterInfo2 *info2,
    4262             :                                       const char *servername,
    4263             :                                       struct spoolss_PrinterInfo6 *r,
    4264             :                                       int snum)
    4265             : {
    4266           0 :         print_status_struct status;
    4267             : 
    4268          88 :         print_queue_length(msg_ctx, snum, &status);
    4269             : 
    4270          88 :         r->status = nt_printq_status(status.status);
    4271             : 
    4272          88 :         return WERR_OK;
    4273             : }
    4274             : 
    4275             : /********************************************************************
    4276             :  * construct_printer_info7
    4277             :  * fill a spoolss_PrinterInfo7 struct
    4278             :  ********************************************************************/
    4279             : 
    4280         112 : static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
    4281             :                                       struct messaging_context *msg_ctx,
    4282             :                                       const char *servername,
    4283             :                                       struct spoolss_PrinterInfo7 *r,
    4284             :                                       int snum)
    4285             : {
    4286           0 :         const struct loadparm_substitution *lp_sub =
    4287         112 :                 loadparm_s3_global_substitution();
    4288           0 :         const struct auth_session_info *session_info;
    4289         112 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    4290           0 :         char *printer;
    4291           0 :         WERROR werr;
    4292         112 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    4293         112 :         if (tmp_ctx == NULL) {
    4294           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4295             :         }
    4296             : 
    4297         112 :         session_info = get_session_info_system();
    4298         112 :         SMB_ASSERT(session_info != NULL);
    4299             : 
    4300         112 :         printer = lp_servicename(tmp_ctx, lp_sub, snum);
    4301         112 :         if (printer == NULL) {
    4302           0 :                 DEBUG(0, ("invalid printer snum %d\n", snum));
    4303           0 :                 werr = WERR_INVALID_PARAMETER;
    4304           0 :                 goto out_tmp_free;
    4305             :         }
    4306             : 
    4307         112 :         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
    4308             :                                  servername, printer, &pinfo2)) {
    4309           0 :                 struct GUID guid;
    4310           0 :                 char *guidstr;
    4311           0 :                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
    4312             :                                            printer, &guid);
    4313           0 :                 if (!W_ERROR_IS_OK(werr)) {
    4314             :                         /*
    4315             :                          * If we do not have a GUID entry in the registry, then
    4316             :                          * try to retrieve it from AD and store it now.
    4317             :                          */
    4318           0 :                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
    4319             :                                                         &guid);
    4320           0 :                         if (!W_ERROR_IS_OK(werr)) {
    4321           0 :                                 DBG_NOTICE("Failed to retrieve GUID for "
    4322             :                                            "printer [%s] from AD - %s\n",
    4323             :                                            printer,
    4324             :                                            win_errstr(werr));
    4325           0 :                                 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
    4326             :                                         /*
    4327             :                                          * If we did not find it in AD, then it
    4328             :                                          * is unpublished and we should reflect
    4329             :                                          * this in the registry and return
    4330             :                                          * success.
    4331             :                                          */
    4332           0 :                                         DBG_WARNING("Unpublish printer [%s]\n",
    4333             :                                                     pinfo2->sharename);
    4334           0 :                                         nt_printer_publish(tmp_ctx,
    4335             :                                                            session_info,
    4336             :                                                            msg_ctx,
    4337             :                                                            pinfo2,
    4338             :                                                            DSPRINT_UNPUBLISH);
    4339           0 :                                         r->guid = talloc_strdup(mem_ctx, "");
    4340           0 :                                         r->action = DSPRINT_UNPUBLISH;
    4341             : 
    4342           0 :                                         if (r->guid == NULL) {
    4343           0 :                                                 werr = WERR_NOT_ENOUGH_MEMORY;
    4344             :                                         } else {
    4345           0 :                                                 werr = WERR_OK;
    4346             :                                         }
    4347             :                                 }
    4348           0 :                                 goto out_tmp_free;
    4349             :                         }
    4350             : 
    4351           0 :                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
    4352           0 :                         if (!W_ERROR_IS_OK(werr)) {
    4353           0 :                                 DEBUG(3, ("failed to store printer %s guid\n",
    4354             :                                           printer));
    4355             :                         }
    4356             :                 }
    4357             : 
    4358             :                 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
    4359           0 :                 guidstr = GUID_string2(mem_ctx, &guid);
    4360           0 :                 if (guidstr == NULL) {
    4361           0 :                         werr = WERR_NOT_ENOUGH_MEMORY;
    4362           0 :                         goto out_tmp_free;
    4363             :                 }
    4364             :                 /* Convert GUID string to uppercase otherwise printers
    4365             :                  * are pruned */
    4366           0 :                 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
    4367           0 :                 r->action = DSPRINT_PUBLISH;
    4368             : 
    4369           0 :                 TALLOC_FREE(guidstr);
    4370             :         } else {
    4371         112 :                 r->guid = talloc_strdup(mem_ctx, "");
    4372         112 :                 r->action = DSPRINT_UNPUBLISH;
    4373             :         }
    4374         112 :         if (r->guid == NULL) {
    4375           0 :                 werr = WERR_NOT_ENOUGH_MEMORY;
    4376           0 :                 goto out_tmp_free;
    4377             :         }
    4378             : 
    4379         112 :         werr = WERR_OK;
    4380         112 : out_tmp_free:
    4381         112 :         talloc_free(tmp_ctx);
    4382         112 :         return werr;
    4383             : }
    4384             : 
    4385             : /********************************************************************
    4386             :  * construct_printer_info8
    4387             :  * fill a spoolss_PrinterInfo8 struct
    4388             :  ********************************************************************/
    4389             : 
    4390        1664 : static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
    4391             :                                       const struct spoolss_PrinterInfo2 *info2,
    4392             :                                       const char *servername,
    4393             :                                       struct spoolss_DeviceModeInfo *r,
    4394             :                                       int snum)
    4395             : {
    4396           0 :         WERROR result;
    4397           0 :         const char *printername;
    4398             : 
    4399        1664 :         result = create_printername(mem_ctx, servername, info2->printername, &printername);
    4400        1664 :         if (!W_ERROR_IS_OK(result)) {
    4401           0 :                 return result;
    4402             :         }
    4403             : 
    4404        1664 :         if (info2->devmode != NULL) {
    4405        1656 :                 result = copy_devicemode(mem_ctx,
    4406        1656 :                                          info2->devmode,
    4407             :                                          &r->devmode);
    4408        1656 :                 if (!W_ERROR_IS_OK(result)) {
    4409           0 :                         return result;
    4410             :                 }
    4411           8 :         } else if (lp_default_devmode(snum)) {
    4412           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    4413           0 :                                                         info2->printername,
    4414             :                                                         &r->devmode);
    4415           0 :                 if (!W_ERROR_IS_OK(result)) {
    4416           0 :                         return result;
    4417             :                 }
    4418             :         } else {
    4419           8 :                 r->devmode = NULL;
    4420           8 :                 DEBUG(8,("Returning NULL Devicemode!\n"));
    4421             :         }
    4422             : 
    4423        1664 :         compose_devicemode_devicename(r->devmode, printername);
    4424             : 
    4425        1664 :         return WERR_OK;
    4426             : }
    4427             : 
    4428             : /********************************************************************
    4429             :  Spoolss_enumprinters.
    4430             : ********************************************************************/
    4431             : 
    4432         180 : static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
    4433             :                                            const struct auth_session_info *session_info,
    4434             :                                            struct messaging_context *msg_ctx,
    4435             :                                            const char *servername,
    4436             :                                            uint32_t level,
    4437             :                                            uint32_t flags,
    4438             :                                            union spoolss_PrinterInfo **info_p,
    4439             :                                            uint32_t *count_p)
    4440             : {
    4441           0 :         int snum;
    4442           0 :         int n_services;
    4443         180 :         union spoolss_PrinterInfo *info = NULL;
    4444         180 :         uint32_t count = 0;
    4445         180 :         WERROR result = WERR_OK;
    4446         180 :         struct dcerpc_binding_handle *b = NULL;
    4447         180 :         TALLOC_CTX *tmp_ctx = NULL;
    4448             : 
    4449         180 :         tmp_ctx = talloc_new(mem_ctx);
    4450         180 :         if (!tmp_ctx) {
    4451           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4452             :         }
    4453             : 
    4454             :         /*
    4455             :          * printer shares are updated on client enumeration. The background
    4456             :          * printer process updates printer_list.tdb at regular intervals.
    4457             :          */
    4458         180 :         become_root();
    4459         180 :         delete_and_reload_printers();
    4460         180 :         unbecome_root();
    4461             : 
    4462         180 :         n_services = lp_numservices();
    4463         180 :         *count_p = 0;
    4464         180 :         *info_p = NULL;
    4465             : 
    4466       12230 :         for (snum = 0; snum < n_services; snum++) {
    4467             : 
    4468           0 :                 const char *printer;
    4469           0 :                 struct spoolss_PrinterInfo2 *info2;
    4470             : 
    4471       12050 :                 if (!snum_is_shared_printer(snum)) {
    4472       11070 :                         continue;
    4473             :                 }
    4474             : 
    4475         980 :                 printer = lp_const_servicename(snum);
    4476             : 
    4477         980 :                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
    4478             :                         printer, snum));
    4479             : 
    4480         980 :                 if (b == NULL) {
    4481         180 :                         result = winreg_printer_binding_handle(tmp_ctx,
    4482             :                                                                session_info,
    4483             :                                                                msg_ctx,
    4484             :                                                                &b);
    4485         180 :                         if (!W_ERROR_IS_OK(result)) {
    4486           0 :                                 goto out;
    4487             :                         }
    4488             :                 }
    4489             : 
    4490         980 :                 result = winreg_create_printer(tmp_ctx, b,
    4491             :                                                printer);
    4492         980 :                 if (!W_ERROR_IS_OK(result)) {
    4493           0 :                         goto out;
    4494             :                 }
    4495             : 
    4496         980 :                 info = talloc_realloc(tmp_ctx, info,
    4497             :                                             union spoolss_PrinterInfo,
    4498             :                                             count + 1);
    4499         980 :                 if (!info) {
    4500           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    4501           0 :                         goto out;
    4502             :                 }
    4503             : 
    4504         980 :                 result = winreg_get_printer(tmp_ctx, b,
    4505             :                                             printer, &info2);
    4506         980 :                 if (!W_ERROR_IS_OK(result)) {
    4507           0 :                         goto out;
    4508             :                 }
    4509             : 
    4510         980 :                 switch (level) {
    4511          40 :                 case 0:
    4512          40 :                         result = construct_printer_info0(info, session_info,
    4513             :                                                          msg_ctx, info2,
    4514             :                                                          servername,
    4515          40 :                                                          &info[count].info0, snum);
    4516          40 :                         break;
    4517         440 :                 case 1:
    4518         440 :                         result = construct_printer_info1(info, info2, flags,
    4519             :                                                          servername,
    4520         440 :                                                          &info[count].info1, snum);
    4521         440 :                         break;
    4522         340 :                 case 2:
    4523         340 :                         result = construct_printer_info2(info, msg_ctx, info2,
    4524             :                                                          servername,
    4525         340 :                                                          &info[count].info2, snum);
    4526         340 :                         break;
    4527          80 :                 case 4:
    4528          80 :                         result = construct_printer_info4(info, info2,
    4529             :                                                          servername,
    4530          80 :                                                          &info[count].info4, snum);
    4531          80 :                         break;
    4532          80 :                 case 5:
    4533          80 :                         result = construct_printer_info5(info, info2,
    4534             :                                                          servername,
    4535          80 :                                                          &info[count].info5, snum);
    4536          80 :                         break;
    4537             : 
    4538           0 :                 default:
    4539           0 :                         result = WERR_INVALID_LEVEL;
    4540           0 :                         goto out;
    4541             :                 }
    4542             : 
    4543         980 :                 if (!W_ERROR_IS_OK(result)) {
    4544           0 :                         goto out;
    4545             :                 }
    4546             : 
    4547         980 :                 count++;
    4548             :         }
    4549             : 
    4550         180 : out:
    4551         180 :         if (W_ERROR_IS_OK(result)) {
    4552         180 :                 *info_p = talloc_move(mem_ctx, &info);
    4553         180 :                 *count_p = count;
    4554             :         }
    4555             : 
    4556         180 :         talloc_free(tmp_ctx);
    4557             : 
    4558         180 :         return result;
    4559             : }
    4560             : 
    4561             : /********************************************************************
    4562             :  * handle enumeration of printers at level 0
    4563             :  ********************************************************************/
    4564             : 
    4565           8 : static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
    4566             :                                   const struct auth_session_info *session_info,
    4567             :                                   struct messaging_context *msg_ctx,
    4568             :                                   uint32_t flags,
    4569             :                                   const char *servername,
    4570             :                                   union spoolss_PrinterInfo **info,
    4571             :                                   uint32_t *count)
    4572             : {
    4573           8 :         DEBUG(4,("enum_all_printers_info_0\n"));
    4574             : 
    4575           8 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4576             :                                             servername, 0, flags, info, count);
    4577             : }
    4578             : 
    4579             : 
    4580             : /********************************************************************
    4581             : ********************************************************************/
    4582             : 
    4583          72 : static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
    4584             :                                        const struct auth_session_info *session_info,
    4585             :                                        struct messaging_context *msg_ctx,
    4586             :                                        const char *servername,
    4587             :                                        uint32_t flags,
    4588             :                                        union spoolss_PrinterInfo **info,
    4589             :                                        uint32_t *count)
    4590             : {
    4591          72 :         DEBUG(4,("enum_all_printers_info_1\n"));
    4592             : 
    4593          72 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4594             :                                             servername, 1, flags, info, count);
    4595             : }
    4596             : 
    4597             : /********************************************************************
    4598             :  enum_all_printers_info_1_local.
    4599             : *********************************************************************/
    4600             : 
    4601          72 : static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
    4602             :                                              const struct auth_session_info *session_info,
    4603             :                                              struct messaging_context *msg_ctx,
    4604             :                                              const char *servername,
    4605             :                                              union spoolss_PrinterInfo **info,
    4606             :                                              uint32_t *count)
    4607             : {
    4608          72 :         DEBUG(4,("enum_all_printers_info_1_local\n"));
    4609             : 
    4610          72 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4611             :                                         servername, PRINTER_ENUM_ICON8, info, count);
    4612             : }
    4613             : 
    4614             : /********************************************************************
    4615             :  enum_all_printers_info_1_name.
    4616             : *********************************************************************/
    4617             : 
    4618           0 : static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
    4619             :                                             const struct auth_session_info *session_info,
    4620             :                                             struct messaging_context *msg_ctx,
    4621             :                                             const char *servername,
    4622             :                                             union spoolss_PrinterInfo **info,
    4623             :                                             uint32_t *count)
    4624             : {
    4625           0 :         const char *s = servername;
    4626             : 
    4627           0 :         DEBUG(4,("enum_all_printers_info_1_name\n"));
    4628             : 
    4629           0 :         if (servername != NULL &&
    4630           0 :             (servername[0] == '\\') && (servername[1] == '\\')) {
    4631           0 :                 s = servername + 2;
    4632             :         }
    4633             : 
    4634           0 :         if (!is_myname_or_ipaddr(s)) {
    4635           0 :                 return WERR_INVALID_NAME;
    4636             :         }
    4637             : 
    4638           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4639             :                                         servername, PRINTER_ENUM_ICON8, info, count);
    4640             : }
    4641             : 
    4642             : /********************************************************************
    4643             :  enum_all_printers_info_1_network.
    4644             : *********************************************************************/
    4645             : 
    4646           0 : static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
    4647             :                                                const struct auth_session_info *session_info,
    4648             :                                                struct messaging_context *msg_ctx,
    4649             :                                                const char *servername,
    4650             :                                                union spoolss_PrinterInfo **info,
    4651             :                                                uint32_t *count)
    4652             : {
    4653           0 :         const char *s = servername;
    4654             : 
    4655           0 :         DEBUG(4,("enum_all_printers_info_1_network\n"));
    4656             : 
    4657             :         /* If we respond to a enum_printers level 1 on our name with flags
    4658             :            set to PRINTER_ENUM_REMOTE with a list of printers then these
    4659             :            printers incorrectly appear in the APW browse list.
    4660             :            Specifically the printers for the server appear at the workgroup
    4661             :            level where all the other servers in the domain are
    4662             :            listed. Windows responds to this call with a
    4663             :            WERR_CAN_NOT_COMPLETE so we should do the same. */
    4664             : 
    4665           0 :         if (servername != NULL &&
    4666           0 :             (servername[0] == '\\') && (servername[1] == '\\')) {
    4667           0 :                  s = servername + 2;
    4668             :         }
    4669             : 
    4670           0 :         if (is_myname_or_ipaddr(s)) {
    4671           0 :                  return WERR_CAN_NOT_COMPLETE;
    4672             :         }
    4673             : 
    4674           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4675             :                                         servername, PRINTER_ENUM_NAME, info, count);
    4676             : }
    4677             : 
    4678             : /********************************************************************
    4679             :  * api_spoolss_enumprinters
    4680             :  *
    4681             :  * called from api_spoolss_enumprinters (see this to understand)
    4682             :  ********************************************************************/
    4683             : 
    4684          68 : static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
    4685             :                                        const struct auth_session_info *session_info,
    4686             :                                        struct messaging_context *msg_ctx,
    4687             :                                        const char *servername,
    4688             :                                        union spoolss_PrinterInfo **info,
    4689             :                                        uint32_t *count)
    4690             : {
    4691          68 :         DEBUG(4,("enum_all_printers_info_2\n"));
    4692             : 
    4693          68 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4694             :                                             servername, 2, 0, info, count);
    4695             : }
    4696             : 
    4697             : /********************************************************************
    4698             :  * handle enumeration of printers at level 1
    4699             :  ********************************************************************/
    4700             : 
    4701          72 : static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
    4702             :                                   const struct auth_session_info *session_info,
    4703             :                                   struct messaging_context *msg_ctx,
    4704             :                                   uint32_t flags,
    4705             :                                   const char *servername,
    4706             :                                   union spoolss_PrinterInfo **info,
    4707             :                                   uint32_t *count)
    4708             : {
    4709             :         /* Not all the flags are equals */
    4710             : 
    4711          72 :         if (flags & PRINTER_ENUM_LOCAL) {
    4712          72 :                 return enum_all_printers_info_1_local(mem_ctx, session_info,
    4713             :                                                       msg_ctx, servername, info, count);
    4714             :         }
    4715             : 
    4716           0 :         if (flags & PRINTER_ENUM_NAME) {
    4717           0 :                 return enum_all_printers_info_1_name(mem_ctx, session_info,
    4718             :                                                      msg_ctx, servername, info,
    4719             :                                                      count);
    4720             :         }
    4721             : 
    4722           0 :         if (flags & PRINTER_ENUM_NETWORK) {
    4723           0 :                 return enum_all_printers_info_1_network(mem_ctx, session_info,
    4724             :                                                         msg_ctx, servername, info,
    4725             :                                                         count);
    4726             :         }
    4727             : 
    4728           0 :         return WERR_OK; /* NT4sp5 does that */
    4729             : }
    4730             : 
    4731             : /********************************************************************
    4732             :  * handle enumeration of printers at level 2
    4733             :  ********************************************************************/
    4734             : 
    4735          68 : static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
    4736             :                                   const struct auth_session_info *session_info,
    4737             :                                   struct messaging_context *msg_ctx,
    4738             :                                   uint32_t flags,
    4739             :                                   const char *servername,
    4740             :                                   union spoolss_PrinterInfo **info,
    4741             :                                   uint32_t *count)
    4742             : {
    4743          68 :         if (flags & PRINTER_ENUM_LOCAL) {
    4744             : 
    4745          52 :                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
    4746             :                                                 servername,
    4747             :                                                 info, count);
    4748             :         }
    4749             : 
    4750          16 :         if (flags & PRINTER_ENUM_NAME) {
    4751          16 :                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
    4752           0 :                         return WERR_INVALID_NAME;
    4753             :                 }
    4754             : 
    4755          16 :                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
    4756             :                                                 servername,
    4757             :                                                 info, count);
    4758             :         }
    4759             : 
    4760           0 :         if (flags & PRINTER_ENUM_REMOTE) {
    4761           0 :                 return WERR_INVALID_LEVEL;
    4762             :         }
    4763             : 
    4764           0 :         return WERR_OK;
    4765             : }
    4766             : 
    4767             : /********************************************************************
    4768             :  * handle enumeration of printers at level 4
    4769             :  ********************************************************************/
    4770             : 
    4771          16 : static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
    4772             :                                   const struct auth_session_info *session_info,
    4773             :                                   struct messaging_context *msg_ctx,
    4774             :                                   uint32_t flags,
    4775             :                                   const char *servername,
    4776             :                                   union spoolss_PrinterInfo **info,
    4777             :                                   uint32_t *count)
    4778             : {
    4779          16 :         DEBUG(4,("enum_all_printers_info_4\n"));
    4780             : 
    4781          16 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4782             :                                             servername, 4, flags, info, count);
    4783             : }
    4784             : 
    4785             : 
    4786             : /********************************************************************
    4787             :  * handle enumeration of printers at level 5
    4788             :  ********************************************************************/
    4789             : 
    4790          16 : static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
    4791             :                                   const struct auth_session_info *session_info,
    4792             :                                   struct messaging_context *msg_ctx,
    4793             :                                   uint32_t flags,
    4794             :                                   const char *servername,
    4795             :                                   union spoolss_PrinterInfo **info,
    4796             :                                   uint32_t *count)
    4797             : {
    4798          16 :         DEBUG(4,("enum_all_printers_info_5\n"));
    4799             : 
    4800          16 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4801             :                                             servername, 5, flags, info, count);
    4802             : }
    4803             : 
    4804             : /****************************************************************
    4805             :  _spoolss_EnumPrinters
    4806             : ****************************************************************/
    4807             : 
    4808         180 : WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
    4809             :                              struct spoolss_EnumPrinters *r)
    4810             : {
    4811         180 :         const struct auth_session_info *session_info = get_session_info_system();
    4812           0 :         WERROR result;
    4813             : 
    4814             :         /* that's an [in out] buffer */
    4815             : 
    4816         180 :         if (!r->in.buffer && (r->in.offered != 0)) {
    4817           0 :                 return WERR_INVALID_PARAMETER;
    4818             :         }
    4819             : 
    4820         180 :         DEBUG(4,("_spoolss_EnumPrinters\n"));
    4821             : 
    4822         180 :         *r->out.needed = 0;
    4823         180 :         *r->out.count = 0;
    4824         180 :         *r->out.info = NULL;
    4825             : 
    4826             :         /*
    4827             :          * Level 1:
    4828             :          *          flags==PRINTER_ENUM_NAME
    4829             :          *           if name=="" then enumerates all printers
    4830             :          *           if name!="" then enumerate the printer
    4831             :          *          flags==PRINTER_ENUM_REMOTE
    4832             :          *          name is NULL, enumerate printers
    4833             :          * Level 2: name!="" enumerates printers, name can't be NULL
    4834             :          * Level 3: doesn't exist
    4835             :          * Level 4: does a local registry lookup
    4836             :          * Level 5: same as Level 2
    4837             :          */
    4838             : 
    4839         180 :         if (r->in.server && r->in.server[0] == '\0') {
    4840          80 :                 r->in.server = NULL;
    4841             :         }
    4842             : 
    4843         180 :         switch (r->in.level) {
    4844           8 :         case 0:
    4845           8 :                 result = enumprinters_level0(p->mem_ctx, session_info,
    4846             :                                              p->msg_ctx, r->in.flags,
    4847             :                                              r->in.server,
    4848             :                                              r->out.info, r->out.count);
    4849           8 :                 break;
    4850          72 :         case 1:
    4851          72 :                 result = enumprinters_level1(p->mem_ctx, session_info,
    4852             :                                              p->msg_ctx, r->in.flags,
    4853             :                                              r->in.server,
    4854             :                                              r->out.info, r->out.count);
    4855          72 :                 break;
    4856          68 :         case 2:
    4857          68 :                 result = enumprinters_level2(p->mem_ctx, session_info,
    4858             :                                              p->msg_ctx, r->in.flags,
    4859             :                                              r->in.server,
    4860             :                                              r->out.info, r->out.count);
    4861          68 :                 break;
    4862          16 :         case 4:
    4863          16 :                 result = enumprinters_level4(p->mem_ctx, session_info,
    4864             :                                              p->msg_ctx, r->in.flags,
    4865             :                                              r->in.server,
    4866             :                                              r->out.info, r->out.count);
    4867          16 :                 break;
    4868          16 :         case 5:
    4869          16 :                 result = enumprinters_level5(p->mem_ctx, session_info,
    4870             :                                              p->msg_ctx, r->in.flags,
    4871             :                                              r->in.server,
    4872             :                                              r->out.info, r->out.count);
    4873          16 :                 break;
    4874           0 :         default:
    4875           0 :                 return WERR_INVALID_LEVEL;
    4876             :         }
    4877             : 
    4878         180 :         if (!W_ERROR_IS_OK(result)) {
    4879           0 :                 return result;
    4880             :         }
    4881             : 
    4882         180 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    4883             :                                                      spoolss_EnumPrinters,
    4884             :                                                      *r->out.info, r->in.level,
    4885             :                                                      *r->out.count);
    4886         180 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    4887         180 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    4888             : 
    4889         180 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    4890             : }
    4891             : 
    4892             : /****************************************************************
    4893             :  _spoolss_GetPrinter
    4894             : ****************************************************************/
    4895             : 
    4896        3512 : WERROR _spoolss_GetPrinter(struct pipes_struct *p,
    4897             :                            struct spoolss_GetPrinter *r)
    4898             : {
    4899        3512 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    4900        3512 :         struct spoolss_PrinterInfo2 *info2 = NULL;
    4901        3512 :         WERROR result = WERR_OK;
    4902           0 :         int snum;
    4903             : 
    4904             :         /* that's an [in out] buffer */
    4905             : 
    4906        3512 :         if (!r->in.buffer && (r->in.offered != 0)) {
    4907           0 :                 result = WERR_INVALID_PARAMETER;
    4908           0 :                 goto err_info_free;
    4909             :         }
    4910             : 
    4911        3512 :         *r->out.needed = 0;
    4912             : 
    4913        3512 :         if (Printer == NULL) {
    4914           0 :                 result = WERR_INVALID_HANDLE;
    4915           0 :                 goto err_info_free;
    4916             :         }
    4917             : 
    4918        3512 :         if (Printer->printer_type == SPLHND_SERVER) {
    4919             : 
    4920           0 :                 struct dcerpc_binding_handle *b;
    4921             : 
    4922          72 :                 if (r->in.level != 3) {
    4923          32 :                         result = WERR_INVALID_LEVEL;
    4924          32 :                         goto err_info_free;
    4925             :                 }
    4926             : 
    4927          40 :                 result = winreg_printer_binding_handle(p->mem_ctx,
    4928             :                                                        get_session_info_system(),
    4929             :                                                        p->msg_ctx,
    4930             :                                                        &b);
    4931          40 :                 if (!W_ERROR_IS_OK(result)) {
    4932           0 :                         goto err_info_free;
    4933             :                 }
    4934             : 
    4935          40 :                 result = winreg_get_printserver_secdesc(p->mem_ctx,
    4936             :                                                         b,
    4937          40 :                                                         &r->out.info->info3.secdesc);
    4938          40 :                 if (!W_ERROR_IS_OK(result)) {
    4939           0 :                         goto err_info_free;
    4940             :                 }
    4941             : 
    4942          40 :                 goto done;
    4943             :         }
    4944             : 
    4945        3440 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    4946           0 :                 result = WERR_INVALID_HANDLE;
    4947           0 :                 goto err_info_free;
    4948             :         }
    4949             : 
    4950        3440 :         result = winreg_get_printer_internal(p->mem_ctx,
    4951             :                                     get_session_info_system(),
    4952             :                                     p->msg_ctx,
    4953             :                                     lp_const_servicename(snum),
    4954             :                                     &info2);
    4955        3440 :         if (!W_ERROR_IS_OK(result)) {
    4956           0 :                 goto err_info_free;
    4957             :         }
    4958             : 
    4959        3440 :         switch (r->in.level) {
    4960         236 :         case 0:
    4961         236 :                 result = construct_printer_info0(p->mem_ctx,
    4962             :                                                  get_session_info_system(),
    4963             :                                                  p->msg_ctx,
    4964             :                                                  info2,
    4965             :                                                  Printer->servername,
    4966         236 :                                                  &r->out.info->info0,
    4967             :                                                  snum);
    4968         236 :                 break;
    4969          88 :         case 1:
    4970          88 :                 result = construct_printer_info1(p->mem_ctx, info2,
    4971             :                                                  PRINTER_ENUM_ICON8,
    4972             :                                                  Printer->servername,
    4973          88 :                                                  &r->out.info->info1, snum);
    4974          88 :                 break;
    4975         932 :         case 2:
    4976         932 :                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
    4977             :                                                  Printer->servername,
    4978         932 :                                                  &r->out.info->info2, snum);
    4979         932 :                 break;
    4980         144 :         case 3:
    4981         144 :                 result = construct_printer_info3(p->mem_ctx, info2,
    4982             :                                                  Printer->servername,
    4983         144 :                                                  &r->out.info->info3, snum);
    4984         144 :                 break;
    4985          88 :         case 4:
    4986          88 :                 result = construct_printer_info4(p->mem_ctx, info2,
    4987             :                                                  Printer->servername,
    4988          88 :                                                  &r->out.info->info4, snum);
    4989          88 :                 break;
    4990          88 :         case 5:
    4991          88 :                 result = construct_printer_info5(p->mem_ctx, info2,
    4992             :                                                  Printer->servername,
    4993          88 :                                                  &r->out.info->info5, snum);
    4994          88 :                 break;
    4995          88 :         case 6:
    4996          88 :                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
    4997             :                                                  Printer->servername,
    4998          88 :                                                  &r->out.info->info6, snum);
    4999          88 :                 break;
    5000         112 :         case 7:
    5001         112 :                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
    5002             :                                                  Printer->servername,
    5003         112 :                                                  &r->out.info->info7, snum);
    5004         112 :                 break;
    5005        1664 :         case 8:
    5006        1664 :                 result = construct_printer_info8(p->mem_ctx, info2,
    5007             :                                                  Printer->servername,
    5008        1664 :                                                  &r->out.info->info8, snum);
    5009        1664 :                 break;
    5010           0 :         default:
    5011           0 :                 result = WERR_INVALID_LEVEL;
    5012           0 :                 break;
    5013             :         }
    5014        3440 :         TALLOC_FREE(info2);
    5015             : 
    5016        3440 :         if (!W_ERROR_IS_OK(result)) {
    5017           0 :                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
    5018             :                           r->in.level, win_errstr(result)));
    5019           0 :                 goto err_info_free;
    5020             :         }
    5021        3440 :  done:
    5022        3480 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
    5023             :                                                r->out.info, r->in.level);
    5024        3480 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    5025             : 
    5026        3480 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    5027             : 
    5028          32 : err_info_free:
    5029          32 :         TALLOC_FREE(r->out.info);
    5030          32 :         return result;
    5031             : }
    5032             : 
    5033             : /********************************************************************
    5034             :  ********************************************************************/
    5035             : 
    5036             : #define FILL_DRIVER_STRING(mem_ctx, in, out) \
    5037             :         do { \
    5038             :                 if (in && strlen(in)) { \
    5039             :                         out = talloc_strdup(mem_ctx, in); \
    5040             :                 } else { \
    5041             :                         out = talloc_strdup(mem_ctx, ""); \
    5042             :                 } \
    5043             :                 W_ERROR_HAVE_NO_MEMORY(out); \
    5044             :         } while (0);
    5045             : 
    5046             : #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
    5047             :         do { \
    5048             :                 if (in && strlen(in)) { \
    5049             :                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
    5050             :                 } else { \
    5051             :                         out = talloc_strdup(mem_ctx, ""); \
    5052             :                 } \
    5053             :                 W_ERROR_HAVE_NO_MEMORY(out); \
    5054             :         } while (0);
    5055             : 
    5056           0 : static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
    5057             :                                                   const char **string_array,
    5058             :                                                   const char ***presult,
    5059             :                                                   const char *cservername,
    5060             :                                                   const char *arch,
    5061             :                                                   int version)
    5062             : {
    5063           0 :         size_t i;
    5064           0 :         size_t num_strings = 0;
    5065           0 :         const char **array = NULL;
    5066             : 
    5067           0 :         if (string_array == NULL) {
    5068           0 :                 return WERR_INVALID_PARAMETER;
    5069             :         }
    5070             : 
    5071           0 :         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
    5072           0 :                 const char *str = NULL;
    5073             : 
    5074           0 :                 if (cservername == NULL || arch == NULL) {
    5075           0 :                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
    5076             :                 } else {
    5077           0 :                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
    5078             :                 }
    5079             : 
    5080           0 :                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
    5081           0 :                         TALLOC_FREE(array);
    5082           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    5083             :                 }
    5084             :         }
    5085             : 
    5086           0 :         if (i > 0) {
    5087           0 :                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
    5088             :                              &array, &num_strings);
    5089             :         }
    5090             : 
    5091           0 :         if (presult != NULL) {
    5092           0 :                 *presult = array;
    5093             :         } else {
    5094           0 :                 talloc_free(array);
    5095             :         }
    5096             : 
    5097           0 :         return WERR_OK;
    5098             : }
    5099             : 
    5100             : /********************************************************************
    5101             :  * fill a spoolss_DriverInfo1 struct
    5102             :  ********************************************************************/
    5103             : 
    5104           0 : static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
    5105             :                                         struct spoolss_DriverInfo1 *r,
    5106             :                                         const struct spoolss_DriverInfo8 *driver,
    5107             :                                         const char *servername)
    5108             : {
    5109           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5110           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5111             : 
    5112           0 :         return WERR_OK;
    5113             : }
    5114             : 
    5115             : /********************************************************************
    5116             :  * fill a spoolss_DriverInfo2 struct
    5117             :  ********************************************************************/
    5118             : 
    5119           0 : static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
    5120             :                                         struct spoolss_DriverInfo2 *r,
    5121             :                                         const struct spoolss_DriverInfo8 *driver,
    5122             :                                         const char *servername)
    5123             : 
    5124             : {
    5125           0 :         const char *cservername = canon_servername(servername);
    5126             : 
    5127           0 :         r->version           = driver->version;
    5128             : 
    5129           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5130           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5131           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5132           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5133             : 
    5134           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5135             :                                driver->architecture,
    5136             :                                driver->version,
    5137             :                                driver->driver_path,
    5138           0 :                                r->driver_path);
    5139             : 
    5140           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5141             :                                driver->architecture,
    5142             :                                driver->version,
    5143             :                                driver->data_file,
    5144           0 :                                r->data_file);
    5145             : 
    5146           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5147             :                                driver->architecture,
    5148             :                                driver->version,
    5149             :                                driver->config_file,
    5150           0 :                                r->config_file);
    5151             : 
    5152           0 :         return WERR_OK;
    5153             : }
    5154             : 
    5155             : /********************************************************************
    5156             :  * fill a spoolss_DriverInfo3 struct
    5157             :  ********************************************************************/
    5158             : 
    5159           0 : static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
    5160             :                                         struct spoolss_DriverInfo3 *r,
    5161             :                                         const struct spoolss_DriverInfo8 *driver,
    5162             :                                         const char *servername)
    5163             : {
    5164           0 :         const char *cservername = canon_servername(servername);
    5165             : 
    5166           0 :         r->version           = driver->version;
    5167             : 
    5168           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5169           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5170           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5171           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5172             : 
    5173           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5174             :                                driver->architecture,
    5175             :                                driver->version,
    5176             :                                driver->driver_path,
    5177           0 :                                r->driver_path);
    5178             : 
    5179           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5180             :                                driver->architecture,
    5181             :                                driver->version,
    5182             :                                driver->data_file,
    5183           0 :                                r->data_file);
    5184             : 
    5185           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5186             :                                driver->architecture,
    5187             :                                driver->version,
    5188             :                                driver->config_file,
    5189           0 :                                r->config_file);
    5190             : 
    5191           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5192             :                                driver->architecture,
    5193             :                                driver->version,
    5194             :                                driver->help_file,
    5195           0 :                                r->help_file);
    5196             : 
    5197           0 :         FILL_DRIVER_STRING(mem_ctx,
    5198             :                            driver->monitor_name,
    5199           0 :                            r->monitor_name);
    5200             : 
    5201           0 :         FILL_DRIVER_STRING(mem_ctx,
    5202             :                            driver->default_datatype,
    5203           0 :                            r->default_datatype);
    5204             : 
    5205           0 :         return string_array_from_driver_info(mem_ctx,
    5206           0 :                                              driver->dependent_files,
    5207             :                                              &r->dependent_files,
    5208             :                                              cservername,
    5209           0 :                                              driver->architecture,
    5210           0 :                                              driver->version);
    5211             : }
    5212             : 
    5213             : /********************************************************************
    5214             :  * fill a spoolss_DriverInfo4 struct
    5215             :  ********************************************************************/
    5216             : 
    5217           0 : static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
    5218             :                                         struct spoolss_DriverInfo4 *r,
    5219             :                                         const struct spoolss_DriverInfo8 *driver,
    5220             :                                         const char *servername)
    5221             : {
    5222           0 :         const char *cservername = canon_servername(servername);
    5223           0 :         WERROR result;
    5224             : 
    5225           0 :         r->version           = driver->version;
    5226             : 
    5227           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5228           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5229           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5230           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5231             : 
    5232           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5233             :                                driver->architecture,
    5234             :                                driver->version,
    5235             :                                driver->driver_path,
    5236           0 :                                r->driver_path);
    5237             : 
    5238           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5239             :                                driver->architecture,
    5240             :                                driver->version,
    5241             :                                driver->data_file,
    5242           0 :                                r->data_file);
    5243             : 
    5244           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5245             :                                driver->architecture,
    5246             :                                driver->version,
    5247             :                                driver->config_file,
    5248           0 :                                r->config_file);
    5249             : 
    5250           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5251             :                                driver->architecture,
    5252             :                                driver->version,
    5253             :                                driver->help_file,
    5254           0 :                                r->help_file);
    5255             : 
    5256           0 :         result = string_array_from_driver_info(mem_ctx,
    5257           0 :                                                driver->dependent_files,
    5258             :                                                &r->dependent_files,
    5259             :                                                cservername,
    5260           0 :                                                driver->architecture,
    5261           0 :                                                driver->version);
    5262           0 :         if (!W_ERROR_IS_OK(result)) {
    5263           0 :                 return result;
    5264             :         }
    5265             : 
    5266           0 :         FILL_DRIVER_STRING(mem_ctx,
    5267             :                            driver->monitor_name,
    5268           0 :                            r->monitor_name);
    5269             : 
    5270           0 :         FILL_DRIVER_STRING(mem_ctx,
    5271             :                            driver->default_datatype,
    5272           0 :                            r->default_datatype);
    5273             : 
    5274             : 
    5275           0 :         result = string_array_from_driver_info(mem_ctx,
    5276           0 :                                                driver->previous_names,
    5277             :                                                &r->previous_names,
    5278             :                                                NULL, NULL, 0);
    5279             : 
    5280           0 :         return result;
    5281             : }
    5282             : 
    5283             : /********************************************************************
    5284             :  * fill a spoolss_DriverInfo5 struct
    5285             :  ********************************************************************/
    5286             : 
    5287           0 : static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
    5288             :                                         struct spoolss_DriverInfo5 *r,
    5289             :                                         const struct spoolss_DriverInfo8 *driver,
    5290             :                                         const char *servername)
    5291             : {
    5292           0 :         const char *cservername = canon_servername(servername);
    5293             : 
    5294           0 :         r->version           = driver->version;
    5295             : 
    5296           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5297           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5298           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5299           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5300             : 
    5301           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5302             :                                driver->architecture,
    5303             :                                driver->version,
    5304             :                                driver->driver_path,
    5305           0 :                                r->driver_path);
    5306             : 
    5307           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5308             :                                driver->architecture,
    5309             :                                driver->version,
    5310             :                                driver->data_file,
    5311           0 :                                r->data_file);
    5312             : 
    5313           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5314             :                                driver->architecture,
    5315             :                                driver->version,
    5316             :                                driver->config_file,
    5317           0 :                                r->config_file);
    5318             : 
    5319           0 :         r->driver_attributes = 0;
    5320           0 :         r->config_version    = 0;
    5321           0 :         r->driver_version    = 0;
    5322             : 
    5323           0 :         return WERR_OK;
    5324             : }
    5325             : /********************************************************************
    5326             :  * fill a spoolss_DriverInfo6 struct
    5327             :  ********************************************************************/
    5328             : 
    5329           0 : static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
    5330             :                                         struct spoolss_DriverInfo6 *r,
    5331             :                                         const struct spoolss_DriverInfo8 *driver,
    5332             :                                         const char *servername)
    5333             : {
    5334           0 :         const char *cservername = canon_servername(servername);
    5335           0 :         WERROR result;
    5336             : 
    5337           0 :         r->version           = driver->version;
    5338             : 
    5339           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5340           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5341           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5342           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5343             : 
    5344           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5345             :                                driver->architecture,
    5346             :                                driver->version,
    5347             :                                driver->driver_path,
    5348           0 :                                r->driver_path);
    5349             : 
    5350           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5351             :                                driver->architecture,
    5352             :                                driver->version,
    5353             :                                driver->data_file,
    5354           0 :                                r->data_file);
    5355             : 
    5356           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5357             :                                driver->architecture,
    5358             :                                driver->version,
    5359             :                                driver->config_file,
    5360           0 :                                r->config_file);
    5361             : 
    5362           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5363             :                                driver->architecture,
    5364             :                                driver->version,
    5365             :                                driver->help_file,
    5366           0 :                                r->help_file);
    5367             : 
    5368           0 :         FILL_DRIVER_STRING(mem_ctx,
    5369             :                            driver->monitor_name,
    5370           0 :                            r->monitor_name);
    5371             : 
    5372           0 :         FILL_DRIVER_STRING(mem_ctx,
    5373             :                            driver->default_datatype,
    5374           0 :                            r->default_datatype);
    5375             : 
    5376           0 :         result = string_array_from_driver_info(mem_ctx,
    5377           0 :                                                driver->dependent_files,
    5378             :                                                &r->dependent_files,
    5379             :                                                cservername,
    5380           0 :                                                driver->architecture,
    5381           0 :                                                driver->version);
    5382           0 :         if (!W_ERROR_IS_OK(result)) {
    5383           0 :                 return result;
    5384             :         }
    5385             : 
    5386           0 :         result = string_array_from_driver_info(mem_ctx,
    5387           0 :                                                driver->previous_names,
    5388             :                                                &r->previous_names,
    5389             :                                                NULL, NULL, 0);
    5390           0 :         if (!W_ERROR_IS_OK(result)) {
    5391           0 :                 return result;
    5392             :         }
    5393             : 
    5394           0 :         r->driver_date               = driver->driver_date;
    5395           0 :         r->driver_version    = driver->driver_version;
    5396             : 
    5397           0 :         FILL_DRIVER_STRING(mem_ctx,
    5398             :                            driver->manufacturer_name,
    5399           0 :                            r->manufacturer_name);
    5400           0 :         FILL_DRIVER_STRING(mem_ctx,
    5401             :                            driver->manufacturer_url,
    5402           0 :                            r->manufacturer_url);
    5403           0 :         FILL_DRIVER_STRING(mem_ctx,
    5404             :                            driver->hardware_id,
    5405           0 :                            r->hardware_id);
    5406           0 :         FILL_DRIVER_STRING(mem_ctx,
    5407             :                            driver->provider,
    5408           0 :                            r->provider);
    5409             : 
    5410           0 :         return WERR_OK;
    5411             : }
    5412             : 
    5413             : /********************************************************************
    5414             :  * fill a spoolss_DriverInfo8 struct
    5415             :  ********************************************************************/
    5416             : 
    5417           0 : static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
    5418             :                                         struct spoolss_DriverInfo8 *r,
    5419             :                                         const struct spoolss_DriverInfo8 *driver,
    5420             :                                         const char *servername)
    5421             : {
    5422           0 :         const char *cservername = canon_servername(servername);
    5423           0 :         WERROR result;
    5424             : 
    5425           0 :         r->version           = driver->version;
    5426             : 
    5427           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5428           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5429           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5430           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5431             : 
    5432           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5433             :                                driver->architecture,
    5434             :                                driver->version,
    5435             :                                driver->driver_path,
    5436           0 :                                r->driver_path);
    5437             : 
    5438           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5439             :                                driver->architecture,
    5440             :                                driver->version,
    5441             :                                driver->data_file,
    5442           0 :                                r->data_file);
    5443             : 
    5444           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5445             :                                driver->architecture,
    5446             :                                driver->version,
    5447             :                                driver->config_file,
    5448           0 :                                r->config_file);
    5449             : 
    5450           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5451             :                                driver->architecture,
    5452             :                                driver->version,
    5453             :                                driver->help_file,
    5454           0 :                                r->help_file);
    5455             : 
    5456           0 :         FILL_DRIVER_STRING(mem_ctx,
    5457             :                            driver->monitor_name,
    5458           0 :                            r->monitor_name);
    5459             : 
    5460           0 :         FILL_DRIVER_STRING(mem_ctx,
    5461             :                            driver->default_datatype,
    5462           0 :                            r->default_datatype);
    5463             : 
    5464           0 :         result = string_array_from_driver_info(mem_ctx,
    5465           0 :                                                driver->dependent_files,
    5466             :                                                &r->dependent_files,
    5467             :                                                cservername,
    5468           0 :                                                driver->architecture,
    5469           0 :                                                driver->version);
    5470           0 :         if (!W_ERROR_IS_OK(result)) {
    5471           0 :                 return result;
    5472             :         }
    5473             : 
    5474           0 :         result = string_array_from_driver_info(mem_ctx,
    5475           0 :                                                driver->previous_names,
    5476             :                                                &r->previous_names,
    5477             :                                                NULL, NULL, 0);
    5478           0 :         if (!W_ERROR_IS_OK(result)) {
    5479           0 :                 return result;
    5480             :         }
    5481             : 
    5482           0 :         r->driver_date               = driver->driver_date;
    5483           0 :         r->driver_version    = driver->driver_version;
    5484             : 
    5485           0 :         FILL_DRIVER_STRING(mem_ctx,
    5486             :                            driver->manufacturer_name,
    5487           0 :                            r->manufacturer_name);
    5488           0 :         FILL_DRIVER_STRING(mem_ctx,
    5489             :                            driver->manufacturer_url,
    5490           0 :                            r->manufacturer_url);
    5491           0 :         FILL_DRIVER_STRING(mem_ctx,
    5492             :                            driver->hardware_id,
    5493           0 :                            r->hardware_id);
    5494           0 :         FILL_DRIVER_STRING(mem_ctx,
    5495             :                            driver->provider,
    5496           0 :                            r->provider);
    5497             : 
    5498           0 :         FILL_DRIVER_STRING(mem_ctx,
    5499             :                            driver->print_processor,
    5500           0 :                            r->print_processor);
    5501           0 :         FILL_DRIVER_STRING(mem_ctx,
    5502             :                            driver->vendor_setup,
    5503           0 :                            r->vendor_setup);
    5504             : 
    5505           0 :         result = string_array_from_driver_info(mem_ctx,
    5506           0 :                                                driver->color_profiles,
    5507             :                                                &r->color_profiles,
    5508             :                                                NULL, NULL, 0);
    5509           0 :         if (!W_ERROR_IS_OK(result)) {
    5510           0 :                 return result;
    5511             :         }
    5512             : 
    5513           0 :         FILL_DRIVER_STRING(mem_ctx,
    5514             :                            driver->inf_path,
    5515           0 :                            r->inf_path);
    5516             : 
    5517           0 :         r->printer_driver_attributes = driver->printer_driver_attributes;
    5518             : 
    5519           0 :         result = string_array_from_driver_info(mem_ctx,
    5520           0 :                                                driver->core_driver_dependencies,
    5521             :                                                &r->core_driver_dependencies,
    5522             :                                                NULL, NULL, 0);
    5523           0 :         if (!W_ERROR_IS_OK(result)) {
    5524           0 :                 return result;
    5525             :         }
    5526             : 
    5527           0 :         r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
    5528           0 :         r->min_inbox_driver_ver_version      = driver->min_inbox_driver_ver_version;
    5529             : 
    5530           0 :         return WERR_OK;
    5531             : }
    5532             : 
    5533             : #if 0 /* disabled until marshalling issues are resolved - gd */
    5534             : /********************************************************************
    5535             :  ********************************************************************/
    5536             : 
    5537             : static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
    5538             :                                           struct spoolss_DriverFileInfo *r,
    5539             :                                           const char *cservername,
    5540             :                                           const char *file_name,
    5541             :                                           enum spoolss_DriverFileType file_type,
    5542             :                                           uint32_t file_version)
    5543             : {
    5544             :         r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
    5545             :                                           cservername, file_name);
    5546             :         W_ERROR_HAVE_NO_MEMORY(r->file_name);
    5547             :         r->file_type = file_type;
    5548             :         r->file_version      = file_version;
    5549             : 
    5550             :         return WERR_OK;
    5551             : }
    5552             : 
    5553             : /********************************************************************
    5554             :  ********************************************************************/
    5555             : 
    5556             : static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
    5557             :                                                  const struct spoolss_DriverInfo8 *driver,
    5558             :                                                  const char *cservername,
    5559             :                                                  struct spoolss_DriverFileInfo **info_p,
    5560             :                                                  uint32_t *count_p)
    5561             : {
    5562             :         struct spoolss_DriverFileInfo *info = NULL;
    5563             :         uint32_t count = 0;
    5564             :         WERROR result;
    5565             :         uint32_t i;
    5566             : 
    5567             :         *info_p = NULL;
    5568             :         *count_p = 0;
    5569             : 
    5570             :         if (strlen(driver->driver_path)) {
    5571             :                 info = talloc_realloc(mem_ctx, info,
    5572             :                                             struct spoolss_DriverFileInfo,
    5573             :                                             count + 1);
    5574             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5575             :                 result = fill_spoolss_DriverFileInfo(info,
    5576             :                                                      &info[count],
    5577             :                                                      cservername,
    5578             :                                                      driver->driver_path,
    5579             :                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
    5580             :                                                      0);
    5581             :                 W_ERROR_NOT_OK_RETURN(result);
    5582             :                 count++;
    5583             :         }
    5584             : 
    5585             :         if (strlen(driver->config_file)) {
    5586             :                 info = talloc_realloc(mem_ctx, info,
    5587             :                                             struct spoolss_DriverFileInfo,
    5588             :                                             count + 1);
    5589             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5590             :                 result = fill_spoolss_DriverFileInfo(info,
    5591             :                                                      &info[count],
    5592             :                                                      cservername,
    5593             :                                                      driver->config_file,
    5594             :                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
    5595             :                                                      0);
    5596             :                 W_ERROR_NOT_OK_RETURN(result);
    5597             :                 count++;
    5598             :         }
    5599             : 
    5600             :         if (strlen(driver->data_file)) {
    5601             :                 info = talloc_realloc(mem_ctx, info,
    5602             :                                             struct spoolss_DriverFileInfo,
    5603             :                                             count + 1);
    5604             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5605             :                 result = fill_spoolss_DriverFileInfo(info,
    5606             :                                                      &info[count],
    5607             :                                                      cservername,
    5608             :                                                      driver->data_file,
    5609             :                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
    5610             :                                                      0);
    5611             :                 W_ERROR_NOT_OK_RETURN(result);
    5612             :                 count++;
    5613             :         }
    5614             : 
    5615             :         if (strlen(driver->help_file)) {
    5616             :                 info = talloc_realloc(mem_ctx, info,
    5617             :                                             struct spoolss_DriverFileInfo,
    5618             :                                             count + 1);
    5619             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5620             :                 result = fill_spoolss_DriverFileInfo(info,
    5621             :                                                      &info[count],
    5622             :                                                      cservername,
    5623             :                                                      driver->help_file,
    5624             :                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
    5625             :                                                      0);
    5626             :                 W_ERROR_NOT_OK_RETURN(result);
    5627             :                 count++;
    5628             :         }
    5629             : 
    5630             :         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
    5631             :                 info = talloc_realloc(mem_ctx, info,
    5632             :                                             struct spoolss_DriverFileInfo,
    5633             :                                             count + 1);
    5634             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5635             :                 result = fill_spoolss_DriverFileInfo(info,
    5636             :                                                      &info[count],
    5637             :                                                      cservername,
    5638             :                                                      driver->dependent_files[i],
    5639             :                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
    5640             :                                                      0);
    5641             :                 W_ERROR_NOT_OK_RETURN(result);
    5642             :                 count++;
    5643             :         }
    5644             : 
    5645             :         *info_p = info;
    5646             :         *count_p = count;
    5647             : 
    5648             :         return WERR_OK;
    5649             : }
    5650             : 
    5651             : /********************************************************************
    5652             :  * fill a spoolss_DriverInfo101 struct
    5653             :  ********************************************************************/
    5654             : 
    5655             : static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
    5656             :                                           struct spoolss_DriverInfo101 *r,
    5657             :                                           const struct spoolss_DriverInfo8 *driver,
    5658             :                                           const char *servername)
    5659             : {
    5660             :         const char *cservername = canon_servername(servername);
    5661             :         WERROR result;
    5662             : 
    5663             :         r->version           = driver->version;
    5664             : 
    5665             :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5666             :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5667             :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5668             :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5669             : 
    5670             :         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
    5671             :                                                     cservername,
    5672             :                                                     &r->file_info,
    5673             :                                                     &r->file_count);
    5674             :         if (!W_ERROR_IS_OK(result)) {
    5675             :                 return result;
    5676             :         }
    5677             : 
    5678             :         FILL_DRIVER_STRING(mem_ctx,
    5679             :                            driver->monitor_name,
    5680             :                            r->monitor_name);
    5681             : 
    5682             :         FILL_DRIVER_STRING(mem_ctx,
    5683             :                            driver->default_datatype,
    5684             :                            r->default_datatype);
    5685             : 
    5686             :         result = string_array_from_driver_info(mem_ctx,
    5687             :                                                driver->previous_names,
    5688             :                                                &r->previous_names,
    5689             :                                                NULL, NULL, 0);
    5690             :         if (!W_ERROR_IS_OK(result)) {
    5691             :                 return result;
    5692             :         }
    5693             : 
    5694             :         r->driver_date               = driver->driver_date;
    5695             :         r->driver_version    = driver->driver_version;
    5696             : 
    5697             :         FILL_DRIVER_STRING(mem_ctx,
    5698             :                            driver->manufacturer_name,
    5699             :                            r->manufacturer_name);
    5700             :         FILL_DRIVER_STRING(mem_ctx,
    5701             :                            driver->manufacturer_url,
    5702             :                            r->manufacturer_url);
    5703             :         FILL_DRIVER_STRING(mem_ctx,
    5704             :                            driver->hardware_id,
    5705             :                            r->hardware_id);
    5706             :         FILL_DRIVER_STRING(mem_ctx,
    5707             :                            driver->provider,
    5708             :                            r->provider);
    5709             : 
    5710             :         return WERR_OK;
    5711             : }
    5712             : #endif
    5713             : /********************************************************************
    5714             :  ********************************************************************/
    5715             : 
    5716           4 : static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
    5717             :                                                   const struct auth_session_info *session_info,
    5718             :                                                   struct messaging_context *msg_ctx,
    5719             :                                                   uint32_t level,
    5720             :                                                   union spoolss_DriverInfo *r,
    5721             :                                                   int snum,
    5722             :                                                   const char *servername,
    5723             :                                                   const char *architecture,
    5724             :                                                   uint32_t version)
    5725             : {
    5726           4 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    5727           0 :         struct spoolss_DriverInfo8 *driver;
    5728           0 :         WERROR result;
    5729           0 :         struct dcerpc_binding_handle *b;
    5730           4 :         TALLOC_CTX *tmp_ctx = NULL;
    5731             : 
    5732           4 :         if (level == 101) {
    5733           4 :                 return WERR_INVALID_LEVEL;
    5734             :         }
    5735             : 
    5736           0 :         tmp_ctx = talloc_new(mem_ctx);
    5737           0 :         if (!tmp_ctx) {
    5738           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    5739             :         }
    5740             : 
    5741           0 :         result = winreg_printer_binding_handle(tmp_ctx,
    5742             :                                                session_info,
    5743             :                                                msg_ctx,
    5744             :                                                &b);
    5745           0 :         if (!W_ERROR_IS_OK(result)) {
    5746           0 :                 goto done;
    5747             :         }
    5748             : 
    5749           0 :         result = winreg_get_printer(tmp_ctx, b,
    5750             :                                     lp_const_servicename(snum),
    5751             :                                     &pinfo2);
    5752           0 :         if (!W_ERROR_IS_OK(result)) {
    5753           0 :                 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
    5754             :                         lp_const_servicename(snum), win_errstr(result));
    5755           0 :                 result = WERR_INVALID_PRINTER_NAME;
    5756           0 :                 goto done;
    5757             :         }
    5758             : 
    5759           0 :         if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
    5760           0 :                 result = WERR_UNKNOWN_PRINTER_DRIVER;
    5761           0 :                 goto done;
    5762             :         }
    5763             : 
    5764           0 :         DBG_INFO("Construct printer driver [%s] for [%s]\n",
    5765             :                  pinfo2->drivername,
    5766             :                  pinfo2->sharename);
    5767             : 
    5768           0 :         result = winreg_get_driver(tmp_ctx, b,
    5769             :                                    architecture,
    5770           0 :                                    pinfo2->drivername, version, &driver);
    5771             : 
    5772           0 :         DBG_INFO("winreg_get_driver() status: %s\n",
    5773             :                  win_errstr(result));
    5774             : 
    5775           0 :         if (!W_ERROR_IS_OK(result)) {
    5776             :                 /*
    5777             :                  * Is this a W2k client ?
    5778             :                  */
    5779             : 
    5780           0 :                 if (version < 3) {
    5781           0 :                         result = WERR_UNKNOWN_PRINTER_DRIVER;
    5782           0 :                         goto done;
    5783             :                 }
    5784             : 
    5785             :                 /* Yes - try again with a WinNT driver. */
    5786           0 :                 version = 2;
    5787           0 :                 result = winreg_get_driver(tmp_ctx, b,
    5788             :                                            architecture,
    5789           0 :                                            pinfo2->drivername,
    5790             :                                            version, &driver);
    5791           0 :                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
    5792             :                         win_errstr(result)));
    5793           0 :                 if (!W_ERROR_IS_OK(result)) {
    5794           0 :                         result = WERR_UNKNOWN_PRINTER_DRIVER;
    5795           0 :                         goto done;
    5796             :                 }
    5797             :         }
    5798             : 
    5799             :         /* these are allocated on mem_ctx and not tmp_ctx because they are
    5800             :          * the 'return value' and need to outlive this call */
    5801           0 :         switch (level) {
    5802           0 :         case 1:
    5803           0 :                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
    5804           0 :                 break;
    5805           0 :         case 2:
    5806           0 :                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
    5807           0 :                 break;
    5808           0 :         case 3:
    5809           0 :                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
    5810           0 :                 break;
    5811           0 :         case 4:
    5812           0 :                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
    5813           0 :                 break;
    5814           0 :         case 5:
    5815           0 :                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
    5816           0 :                 break;
    5817           0 :         case 6:
    5818           0 :                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
    5819           0 :                 break;
    5820           0 :         case 8:
    5821           0 :                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
    5822           0 :                 break;
    5823             : #if 0 /* disabled until marshalling issues are resolved - gd */
    5824             :         case 101:
    5825             :                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
    5826             :                 break;
    5827             : #endif
    5828           0 :         default:
    5829           0 :                 result = WERR_INVALID_LEVEL;
    5830           0 :                 break;
    5831             :         }
    5832             : 
    5833           0 : done:
    5834           0 :         talloc_free(tmp_ctx);
    5835           0 :         return result;
    5836             : }
    5837             : 
    5838             : /****************************************************************
    5839             :  _spoolss_GetPrinterDriver2
    5840             : ****************************************************************/
    5841             : 
    5842           4 : WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
    5843             :                                   struct spoolss_GetPrinterDriver2 *r)
    5844             : {
    5845           0 :         struct printer_handle *printer;
    5846           0 :         WERROR result;
    5847           4 :         uint32_t version = r->in.client_major_version;
    5848             : 
    5849           0 :         int snum;
    5850             : 
    5851             :         /* that's an [in out] buffer */
    5852             : 
    5853           4 :         if (!r->in.buffer && (r->in.offered != 0)) {
    5854           0 :                 result = WERR_INVALID_PARAMETER;
    5855           0 :                 goto err_info_free;
    5856             :         }
    5857             : 
    5858           4 :         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
    5859             : 
    5860           4 :         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
    5861           0 :                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
    5862           0 :                 result = WERR_INVALID_PRINTER_NAME;
    5863           0 :                 goto err_info_free;
    5864             :         }
    5865             : 
    5866           4 :         *r->out.needed = 0;
    5867           4 :         *r->out.server_major_version = 0;
    5868           4 :         *r->out.server_minor_version = 0;
    5869             : 
    5870           4 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    5871           0 :                 result = WERR_INVALID_HANDLE;
    5872           0 :                 goto err_info_free;
    5873             :         }
    5874             : 
    5875           4 :         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
    5876           0 :                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
    5877             :                         "downgrading to v3\n"));
    5878           0 :                 version = SPOOLSS_DRIVER_VERSION_200X;
    5879             :         }
    5880             : 
    5881           4 :         result = construct_printer_driver_info_level(p->mem_ctx,
    5882             :                                                      get_session_info_system(),
    5883             :                                                      p->msg_ctx,
    5884             :                                                      r->in.level, r->out.info,
    5885             :                                                      snum, printer->servername,
    5886             :                                                      r->in.architecture,
    5887             :                                                      version);
    5888           4 :         if (!W_ERROR_IS_OK(result)) {
    5889           4 :                 goto err_info_free;
    5890             :         }
    5891             : 
    5892           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
    5893             :                                                r->out.info, r->in.level);
    5894           0 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    5895             : 
    5896           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    5897             : 
    5898           4 : err_info_free:
    5899           4 :         TALLOC_FREE(r->out.info);
    5900           4 :         return result;
    5901             : }
    5902             : 
    5903             : 
    5904             : /****************************************************************
    5905             :  _spoolss_StartPagePrinter
    5906             : ****************************************************************/
    5907             : 
    5908        1920 : WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
    5909             :                                  struct spoolss_StartPagePrinter *r)
    5910             : {
    5911        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5912             : 
    5913        1920 :         if (!Printer) {
    5914           0 :                 DEBUG(3,("_spoolss_StartPagePrinter: "
    5915             :                         "Error in startpageprinter printer handle\n"));
    5916           0 :                 return WERR_INVALID_HANDLE;
    5917             :         }
    5918             : 
    5919        1920 :         Printer->page_started = true;
    5920        1920 :         return WERR_OK;
    5921             : }
    5922             : 
    5923             : /****************************************************************
    5924             :  _spoolss_EndPagePrinter
    5925             : ****************************************************************/
    5926             : 
    5927        1920 : WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
    5928             :                                struct spoolss_EndPagePrinter *r)
    5929             : {
    5930           0 :         int snum;
    5931             : 
    5932        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5933             : 
    5934        1920 :         if (!Printer) {
    5935           0 :                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
    5936             :                         OUR_HANDLE(r->in.handle)));
    5937           0 :                 return WERR_INVALID_HANDLE;
    5938             :         }
    5939             : 
    5940        1920 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    5941           0 :                 return WERR_INVALID_HANDLE;
    5942             : 
    5943        1920 :         Printer->page_started = false;
    5944        1920 :         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
    5945             : 
    5946        1920 :         return WERR_OK;
    5947             : }
    5948             : 
    5949             : /****************************************************************
    5950             :  _spoolss_StartDocPrinter
    5951             : ****************************************************************/
    5952             : 
    5953         668 : WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
    5954             :                                 struct spoolss_StartDocPrinter *r)
    5955             : {
    5956         668 :         struct dcesrv_call_state *dce_call = p->dce_call;
    5957         668 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    5958           0 :         const struct tsocket_address *remote_address =
    5959         668 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    5960           0 :         struct auth_session_info *session_info =
    5961         668 :                 dcesrv_call_session_info(dce_call);
    5962           0 :         struct spoolss_DocumentInfo1 *info_1;
    5963           0 :         int snum;
    5964         668 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5965           0 :         WERROR werr;
    5966           0 :         char *rhost;
    5967           0 :         int rc;
    5968             : 
    5969         668 :         if (!Printer) {
    5970           0 :                 DEBUG(2,("_spoolss_StartDocPrinter: "
    5971             :                         "Invalid handle (%s:%u:%u)\n",
    5972             :                         OUR_HANDLE(r->in.handle)));
    5973           0 :                 return WERR_INVALID_HANDLE;
    5974             :         }
    5975             : 
    5976         668 :         if (Printer->jobid) {
    5977           0 :                 DEBUG(2, ("_spoolss_StartDocPrinter: "
    5978             :                           "StartDocPrinter called twice! "
    5979             :                           "(existing jobid = %d)\n", Printer->jobid));
    5980           0 :                 return WERR_INVALID_HANDLE;
    5981             :         }
    5982             : 
    5983         668 :         if (r->in.info_ctr->level != 1) {
    5984           0 :                 return WERR_INVALID_LEVEL;
    5985             :         }
    5986             : 
    5987         668 :         info_1 = r->in.info_ctr->info.info1;
    5988             : 
    5989             :         /*
    5990             :          * a nice thing with NT is it doesn't listen to what you tell it.
    5991             :          * when asked to send _only_ RAW data, it tries to send data
    5992             :          * in EMF format.
    5993             :          *
    5994             :          * So I add checks like in NT Server ...
    5995             :          */
    5996             : 
    5997         668 :         if (info_1->datatype) {
    5998             :                 /*
    5999             :                  * The v4 driver model used in Windows 8 declares print jobs
    6000             :                  * intended to bypass the XPS processing layer by setting
    6001             :                  * datatype to "XPS_PASS" instead of "RAW".
    6002             :                  */
    6003         668 :                 if ((strcmp(info_1->datatype, "RAW") != 0)
    6004         224 :                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
    6005           0 :                         *r->out.job_id = 0;
    6006           0 :                         return WERR_INVALID_DATATYPE;
    6007             :                 }
    6008             :         }
    6009             : 
    6010             :         /* get the share number of the printer */
    6011         668 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    6012           0 :                 return WERR_INVALID_HANDLE;
    6013             :         }
    6014             : 
    6015         668 :         rc = get_remote_hostname(remote_address,
    6016             :                                  &rhost,
    6017             :                                  p->mem_ctx);
    6018         668 :         if (rc < 0) {
    6019           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6020             :         }
    6021         668 :         if (strequal(rhost,"UNKNOWN")) {
    6022         668 :                 rhost = tsocket_address_inet_addr_string(remote_address,
    6023             :                                                          p->mem_ctx);
    6024         668 :                 if (rhost == NULL) {
    6025           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    6026             :                 }
    6027             :         }
    6028             : 
    6029         668 :         werr = print_job_start(session_info,
    6030             :                                p->msg_ctx,
    6031             :                                rhost,
    6032             :                                snum,
    6033             :                                info_1->document_name,
    6034             :                                info_1->output_file,
    6035             :                                Printer->devmode,
    6036             :                                &Printer->jobid);
    6037             : 
    6038             :         /* An error occurred in print_job_start() so return an appropriate
    6039             :            NT error code. */
    6040             : 
    6041         668 :         if (!W_ERROR_IS_OK(werr)) {
    6042           0 :                 return werr;
    6043             :         }
    6044             : 
    6045         668 :         Printer->document_started = true;
    6046         668 :         *r->out.job_id = Printer->jobid;
    6047             : 
    6048         668 :         return WERR_OK;
    6049             : }
    6050             : 
    6051             : /****************************************************************
    6052             :  _spoolss_EndDocPrinter
    6053             : ****************************************************************/
    6054             : 
    6055         668 : WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
    6056             :                               struct spoolss_EndDocPrinter *r)
    6057             : {
    6058         668 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6059           0 :         NTSTATUS status;
    6060           0 :         int snum;
    6061             : 
    6062         668 :         if (!Printer) {
    6063           0 :                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
    6064             :                         OUR_HANDLE(r->in.handle)));
    6065           0 :                 return WERR_INVALID_HANDLE;
    6066             :         }
    6067             : 
    6068         668 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    6069           0 :                 return WERR_INVALID_HANDLE;
    6070             :         }
    6071             : 
    6072         668 :         Printer->document_started = false;
    6073         668 :         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
    6074         668 :         if (!NT_STATUS_IS_OK(status)) {
    6075         292 :                 DEBUG(2, ("_spoolss_EndDocPrinter: "
    6076             :                           "print_job_end failed [%s]\n",
    6077             :                           nt_errstr(status)));
    6078             :         }
    6079             : 
    6080         668 :         Printer->jobid = 0;
    6081         668 :         return ntstatus_to_werror(status);
    6082             : }
    6083             : 
    6084             : /****************************************************************
    6085             :  _spoolss_WritePrinter
    6086             : ****************************************************************/
    6087             : 
    6088        1920 : WERROR _spoolss_WritePrinter(struct pipes_struct *p,
    6089             :                              struct spoolss_WritePrinter *r)
    6090             : {
    6091           0 :         ssize_t buffer_written;
    6092           0 :         int snum;
    6093        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6094             : 
    6095        1920 :         if (!Printer) {
    6096           0 :                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
    6097             :                         OUR_HANDLE(r->in.handle)));
    6098           0 :                 *r->out.num_written = r->in._data_size;
    6099           0 :                 return WERR_INVALID_HANDLE;
    6100             :         }
    6101             : 
    6102        1920 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    6103           0 :                 return WERR_INVALID_HANDLE;
    6104             : 
    6105             :         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
    6106        1920 :         buffer_written = print_job_write(global_event_context(),p->msg_ctx,
    6107             :                                                    snum, Printer->jobid,
    6108        1920 :                                                    (const char *)r->in.data.data,
    6109        1920 :                                                    (size_t)r->in._data_size);
    6110        1920 :         if (buffer_written == (ssize_t)-1) {
    6111           0 :                 *r->out.num_written = 0;
    6112           0 :                 if (errno == ENOSPC)
    6113           0 :                         return WERR_NO_SPOOL_SPACE;
    6114             :                 else
    6115           0 :                         return WERR_ACCESS_DENIED;
    6116             :         }
    6117             : 
    6118        1920 :         *r->out.num_written = r->in._data_size;
    6119             : 
    6120        1920 :         return WERR_OK;
    6121             : }
    6122             : 
    6123             : /********************************************************************
    6124             :  * api_spoolss_getprinter
    6125             :  * called from the spoolss dispatcher
    6126             :  *
    6127             :  ********************************************************************/
    6128             : 
    6129         104 : static WERROR control_printer(struct policy_handle *handle, uint32_t command,
    6130             :                               struct pipes_struct *p)
    6131             : {
    6132         104 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6133           0 :         struct auth_session_info *session_info =
    6134         104 :                 dcesrv_call_session_info(dce_call);
    6135           0 :         int snum;
    6136         104 :         WERROR errcode = WERR_INVALID_FUNCTION;
    6137         104 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6138             : 
    6139         104 :         if (!Printer) {
    6140           0 :                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
    6141             :                         OUR_HANDLE(handle)));
    6142           0 :                 return WERR_INVALID_HANDLE;
    6143             :         }
    6144             : 
    6145         104 :         if (!get_printer_snum(p, handle, &snum, NULL))
    6146           0 :                 return WERR_INVALID_HANDLE;
    6147             : 
    6148         104 :         switch (command) {
    6149          52 :         case SPOOLSS_PRINTER_CONTROL_PAUSE:
    6150          52 :                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
    6151          52 :                 break;
    6152          40 :         case SPOOLSS_PRINTER_CONTROL_RESUME:
    6153             :         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
    6154          40 :                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
    6155          40 :                 break;
    6156          12 :         case SPOOLSS_PRINTER_CONTROL_PURGE:
    6157          12 :                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
    6158          12 :                 break;
    6159           0 :         default:
    6160           0 :                 return WERR_INVALID_LEVEL;
    6161             :         }
    6162             : 
    6163         104 :         return errcode;
    6164             : }
    6165             : 
    6166             : 
    6167             : /****************************************************************
    6168             :  _spoolss_AbortPrinter
    6169             :  * From MSDN: "Deletes printer's spool file if printer is configured
    6170             :  * for spooling"
    6171             : ****************************************************************/
    6172             : 
    6173           0 : WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
    6174             :                              struct spoolss_AbortPrinter *r)
    6175             : {
    6176           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6177           0 :         struct auth_session_info *session_info =
    6178           0 :                 dcesrv_call_session_info(dce_call);
    6179           0 :         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6180           0 :         int             snum;
    6181           0 :         WERROR          errcode = WERR_OK;
    6182             : 
    6183           0 :         if (!Printer) {
    6184           0 :                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
    6185             :                         OUR_HANDLE(r->in.handle)));
    6186           0 :                 return WERR_INVALID_HANDLE;
    6187             :         }
    6188             : 
    6189           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    6190           0 :                 return WERR_INVALID_HANDLE;
    6191             : 
    6192           0 :         if (!Printer->document_started) {
    6193           0 :                 return WERR_SPL_NO_STARTDOC;
    6194             :         }
    6195             : 
    6196           0 :         errcode = print_job_delete(session_info,
    6197             :                                    p->msg_ctx,
    6198             :                                    snum,
    6199             :                                    Printer->jobid);
    6200             : 
    6201           0 :         return errcode;
    6202             : }
    6203             : 
    6204             : /********************************************************************
    6205             :  * called by spoolss_api_setprinter
    6206             :  * when updating a printer description
    6207             :  ********************************************************************/
    6208             : 
    6209         120 : static WERROR update_printer_sec(struct policy_handle *handle,
    6210             :                                  struct pipes_struct *p,
    6211             :                                  struct sec_desc_buf *secdesc_ctr)
    6212             : {
    6213         120 :         struct spoolss_security_descriptor *new_secdesc = NULL;
    6214         120 :         struct spoolss_security_descriptor *old_secdesc = NULL;
    6215         120 :         const char *printer = NULL;
    6216           0 :         WERROR result;
    6217         120 :         int snum = -1;
    6218         120 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6219           0 :         struct dcerpc_binding_handle *b;
    6220         120 :         TALLOC_CTX *tmp_ctx = NULL;
    6221         120 :         bool ok = false;
    6222             : 
    6223         120 :         if (!Printer) {
    6224           0 :                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
    6225             :                          OUR_HANDLE(handle)));
    6226             : 
    6227           0 :                 result = WERR_INVALID_HANDLE;
    6228           0 :                 goto done;
    6229             :         }
    6230             : 
    6231         120 :         if (secdesc_ctr == NULL) {
    6232           0 :                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
    6233           0 :                 result = WERR_INVALID_PARAMETER;
    6234           0 :                 goto done;
    6235             :         }
    6236             : 
    6237         120 :         switch (Printer->printer_type) {
    6238           8 :         case SPLHND_SERVER:
    6239           8 :                 break;
    6240         112 :         case SPLHND_PRINTER:
    6241         112 :                 if (!get_printer_snum(p, handle, &snum, NULL)) {
    6242           0 :                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
    6243             :                                  OUR_HANDLE(handle)));
    6244           0 :                         result = WERR_INVALID_HANDLE;
    6245           0 :                         goto done;
    6246             :                 }
    6247         112 :                 printer = lp_const_servicename(snum);
    6248         112 :                 break;
    6249           0 :         default:
    6250           0 :                 break;
    6251             :         }
    6252             : 
    6253             :         /* Check the user has permissions to change the security
    6254             :            descriptor.  By experimentation with two NT machines, the user
    6255             :            requires Full Access to the printer to change security
    6256             :            information. */
    6257             : 
    6258         120 :         switch (Printer->printer_type) {
    6259           8 :         case SPLHND_SERVER:
    6260           8 :                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
    6261           8 :                 break;
    6262         112 :         case SPLHND_PRINTER:
    6263         112 :                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
    6264         112 :                 break;
    6265           0 :         default:
    6266           0 :                 break;
    6267             :         }
    6268             : 
    6269         120 :         if (!ok) {
    6270           0 :                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
    6271             :                         "(access_granted: 0x%08x)\n", Printer->access_granted));
    6272           0 :                 result = WERR_ACCESS_DENIED;
    6273           0 :                 goto done;
    6274             :         }
    6275             : 
    6276         120 :         tmp_ctx = talloc_new(p->mem_ctx);
    6277         120 :         if (!tmp_ctx) {
    6278           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6279             :         }
    6280             : 
    6281         120 :         result = winreg_printer_binding_handle(tmp_ctx,
    6282             :                                                get_session_info_system(),
    6283             :                                                p->msg_ctx,
    6284             :                                                &b);
    6285         120 :         if (!W_ERROR_IS_OK(result)) {
    6286           0 :                 goto done;
    6287             :         }
    6288             : 
    6289             :         /* NT seems to like setting the security descriptor even though
    6290             :            nothing may have actually changed. */
    6291             : 
    6292         120 :         if (printer != NULL) {
    6293         112 :                 result = winreg_get_printer_secdesc(tmp_ctx, b,
    6294             :                                                     printer,
    6295             :                                                     &old_secdesc);
    6296             :         } else {
    6297           8 :                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
    6298             :                                                         &old_secdesc);
    6299             :         }
    6300         120 :         if (!W_ERROR_IS_OK(result)) {
    6301           0 :                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
    6302           0 :                 result = WERR_INVALID_HANDLE;
    6303           0 :                 goto done;
    6304             :         }
    6305             : 
    6306         120 :         if (DEBUGLEVEL >= 10) {
    6307           0 :                 struct dom_sid_buf buf;
    6308           0 :                 struct security_acl *the_acl;
    6309           0 :                 int i;
    6310             : 
    6311           0 :                 the_acl = old_secdesc->dacl;
    6312           0 :                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
    6313             :                            printer, the_acl->num_aces));
    6314             : 
    6315           0 :                 for (i = 0; i < the_acl->num_aces; i++) {
    6316           0 :                         DEBUG(10, ("%s 0x%08x\n",
    6317             :                                    dom_sid_str_buf(
    6318             :                                            &the_acl->aces[i].trustee,
    6319             :                                            &buf),
    6320             :                                   the_acl->aces[i].access_mask));
    6321             :                 }
    6322             : 
    6323           0 :                 the_acl = secdesc_ctr->sd->dacl;
    6324             : 
    6325           0 :                 if (the_acl) {
    6326           0 :                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
    6327             :                                    printer, the_acl->num_aces));
    6328             : 
    6329           0 :                         for (i = 0; i < the_acl->num_aces; i++) {
    6330           0 :                                 DEBUG(10, ("%s 0x%08x\n",
    6331             :                                            dom_sid_str_buf(
    6332             :                                                    &the_acl->aces[i].trustee,
    6333             :                                                    &buf),
    6334             :                                            the_acl->aces[i].access_mask));
    6335             :                         }
    6336             :                 } else {
    6337           0 :                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
    6338             :                 }
    6339             :         }
    6340             : 
    6341         120 :         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
    6342         120 :         if (new_secdesc == NULL) {
    6343           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    6344           0 :                 goto done;
    6345             :         }
    6346             : 
    6347         120 :         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
    6348          56 :                 result = WERR_OK;
    6349          56 :                 goto done;
    6350             :         }
    6351             : 
    6352          64 :         if (printer != NULL) {
    6353          56 :                 result = winreg_set_printer_secdesc(tmp_ctx, b,
    6354             :                                                     printer,
    6355             :                                                     new_secdesc);
    6356             :         } else {
    6357           8 :                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
    6358             :                                                         new_secdesc);
    6359             :         }
    6360             : 
    6361         120 : done:
    6362         120 :         talloc_free(tmp_ctx);
    6363         120 :         return result;
    6364             : }
    6365             : 
    6366             : /********************************************************************
    6367             :  Canonicalize printer info from a client
    6368             :  ********************************************************************/
    6369             : 
    6370         100 : static bool check_printer_ok(TALLOC_CTX *mem_ctx,
    6371             :                              struct spoolss_SetPrinterInfo2 *info2,
    6372             :                              int snum)
    6373             : {
    6374           0 :         fstring printername;
    6375           0 :         const char *p;
    6376             : 
    6377         100 :         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
    6378             :                 "portname=%s drivername=%s comment=%s location=%s\n",
    6379             :                 info2->servername, info2->printername, info2->sharename,
    6380             :                 info2->portname, info2->drivername, info2->comment,
    6381             :                 info2->location));
    6382             : 
    6383             :         /* we force some elements to "correct" values */
    6384         100 :         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
    6385         100 :         if (info2->servername == NULL) {
    6386           0 :                 return false;
    6387             :         }
    6388         100 :         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
    6389         100 :         if (info2->sharename == NULL) {
    6390           0 :                 return false;
    6391             :         }
    6392             : 
    6393             :         /* check to see if we allow printername != sharename */
    6394         100 :         if (lp_force_printername(snum)) {
    6395           0 :                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
    6396             :                                         lp_netbios_name(), info2->sharename);
    6397             :         } else {
    6398             :                 /* make sure printername is in \\server\printername format */
    6399         100 :                 fstrcpy(printername, info2->printername);
    6400         100 :                 p = printername;
    6401         100 :                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
    6402          56 :                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
    6403          56 :                                 p++;
    6404             :                 }
    6405             : 
    6406         100 :                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
    6407             :                                         lp_netbios_name(), p);
    6408             :         }
    6409         100 :         if (info2->printername == NULL) {
    6410           0 :                 return false;
    6411             :         }
    6412             : 
    6413         100 :         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
    6414         100 :         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
    6415             : 
    6416         100 :         return true;
    6417             : }
    6418             : 
    6419             : /****************************************************************************
    6420             : ****************************************************************************/
    6421             : 
    6422           0 : static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
    6423             : {
    6424           0 :         const struct loadparm_substitution *lp_sub =
    6425           0 :                 loadparm_s3_global_substitution();
    6426           0 :         char *cmd = lp_addport_command(talloc_tos(), lp_sub);
    6427           0 :         char *command = NULL;
    6428           0 :         int ret;
    6429           0 :         bool is_print_op = false;
    6430             : 
    6431           0 :         if ( !*cmd ) {
    6432           0 :                 return WERR_ACCESS_DENIED;
    6433             :         }
    6434             : 
    6435           0 :         command = talloc_asprintf(ctx,
    6436             :                         "%s \"%s\" \"%s\"", cmd, portname, uri );
    6437           0 :         if (!command) {
    6438           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6439             :         }
    6440             : 
    6441           0 :         if ( token )
    6442           0 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
    6443             : 
    6444           0 :         DEBUG(10,("Running [%s]\n", command));
    6445             : 
    6446             :         /********* BEGIN SePrintOperatorPrivilege **********/
    6447             : 
    6448           0 :         if ( is_print_op )
    6449           0 :                 become_root();
    6450             : 
    6451           0 :         ret = smbrun(command, NULL, NULL);
    6452             : 
    6453           0 :         if ( is_print_op )
    6454           0 :                 unbecome_root();
    6455             : 
    6456             :         /********* END SePrintOperatorPrivilege **********/
    6457             : 
    6458           0 :         DEBUGADD(10,("returned [%d]\n", ret));
    6459             : 
    6460           0 :         TALLOC_FREE(command);
    6461             : 
    6462           0 :         if ( ret != 0 ) {
    6463           0 :                 return WERR_ACCESS_DENIED;
    6464             :         }
    6465             : 
    6466           0 :         return WERR_OK;
    6467             : }
    6468             : 
    6469             : /****************************************************************************
    6470             : ****************************************************************************/
    6471             : 
    6472        4902 : static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
    6473             :                                    int snum)
    6474             : {
    6475             :         /*
    6476             :          * As we do not know if we are embedded in the file server process
    6477             :          * or not, we have to pretend that all shares are in use.
    6478             :          */
    6479        4902 :         return true;
    6480             : }
    6481             : 
    6482          66 : static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
    6483             :                              struct spoolss_SetPrinterInfo2 *info2,
    6484             :                              const char *remote_machine,
    6485             :                              struct messaging_context *msg_ctx)
    6486             : {
    6487           0 :         const struct loadparm_substitution *lp_sub =
    6488          66 :                 loadparm_s3_global_substitution();
    6489          66 :         char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
    6490           0 :         char **qlines;
    6491          66 :         char *command = NULL;
    6492           0 :         int numlines;
    6493           0 :         int ret;
    6494           0 :         int fd;
    6495          66 :         bool is_print_op = false;
    6496             : 
    6497          66 :         if (!remote_machine) {
    6498           0 :                 return false;
    6499             :         }
    6500             : 
    6501          66 :         command = talloc_asprintf(ctx,
    6502             :                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
    6503             :                         cmd, info2->printername, info2->sharename,
    6504             :                         info2->portname, info2->drivername,
    6505             :                         info2->location, info2->comment, remote_machine);
    6506          66 :         if (!command) {
    6507           0 :                 return false;
    6508             :         }
    6509             : 
    6510          66 :         if ( token )
    6511          66 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
    6512             : 
    6513          66 :         DEBUG(10,("Running [%s]\n", command));
    6514             : 
    6515             :         /********* BEGIN SePrintOperatorPrivilege **********/
    6516             : 
    6517          66 :         if ( is_print_op )
    6518           0 :                 become_root();
    6519             : 
    6520          66 :         ret = smbrun(command, &fd, NULL);
    6521          66 :         if (ret == 0) {
    6522             :                 /* Tell everyone we updated smb.conf. */
    6523          66 :                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
    6524             :         }
    6525             : 
    6526          66 :         if ( is_print_op )
    6527           0 :                 unbecome_root();
    6528             : 
    6529             :         /********* END SePrintOperatorPrivilege **********/
    6530             : 
    6531          66 :         DEBUGADD(10,("returned [%d]\n", ret));
    6532             : 
    6533          66 :         TALLOC_FREE(command);
    6534             : 
    6535          66 :         if ( ret != 0 ) {
    6536           0 :                 if (fd != -1)
    6537           0 :                         close(fd);
    6538           0 :                 return false;
    6539             :         }
    6540             : 
    6541             :         /* reload our services immediately */
    6542          66 :         become_root();
    6543          66 :         reload_services(NULL, spoolss_conn_snum_used, false);
    6544          66 :         unbecome_root();
    6545             : 
    6546          66 :         numlines = 0;
    6547             :         /* Get lines and convert them back to dos-codepage */
    6548          66 :         qlines = fd_lines_load(fd, &numlines, 0, NULL);
    6549          66 :         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
    6550          66 :         close(fd);
    6551             : 
    6552             :         /* Set the portname to what the script says the portname should be. */
    6553             :         /* but don't require anything to be return from the script exit a good error code */
    6554             : 
    6555          66 :         if (numlines) {
    6556             :                 /* Set the portname to what the script says the portname should be. */
    6557           0 :                 info2->portname = talloc_strdup(ctx, qlines[0]);
    6558           0 :                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
    6559             :         }
    6560             : 
    6561          66 :         TALLOC_FREE(qlines);
    6562          66 :         return true;
    6563             : }
    6564             : 
    6565         100 : static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
    6566             :                                const struct auth_session_info *session_info,
    6567             :                                struct messaging_context *msg_ctx,
    6568             :                                int snum,
    6569             :                                struct spoolss_SetPrinterInfo2 *printer,
    6570             :                                struct spoolss_PrinterInfo2 *old_printer)
    6571             : {
    6572         100 :         bool force_update = (old_printer == NULL);
    6573           0 :         const char *dnsdomname;
    6574           0 :         const char *longname;
    6575           0 :         const char *uncname;
    6576           0 :         const char *spooling;
    6577           0 :         DATA_BLOB buffer;
    6578         100 :         WERROR result = WERR_OK;
    6579           0 :         struct dcerpc_binding_handle *b;
    6580           0 :         TALLOC_CTX *tmp_ctx;
    6581           0 :         bool ok;
    6582             : 
    6583         100 :         tmp_ctx = talloc_new(mem_ctx);
    6584         100 :         if (!tmp_ctx) {
    6585           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6586             :         }
    6587             : 
    6588         100 :         result = winreg_printer_binding_handle(tmp_ctx,
    6589             :                                                session_info,
    6590             :                                                msg_ctx,
    6591             :                                                &b);
    6592         100 :         if (!W_ERROR_IS_OK(result)) {
    6593           0 :                 goto done;
    6594             :         }
    6595             : 
    6596         100 :         if (printer->drivername != NULL &&
    6597          84 :             (force_update ||
    6598          84 :              !strequal(printer->drivername, old_printer->drivername))) {
    6599          24 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
    6600          24 :                 if (!ok) {
    6601           0 :                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
    6602           0 :                         result = WERR_INVALID_DATA;
    6603           0 :                         goto done;
    6604             :                 }
    6605          24 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6606             :                                           printer->sharename,
    6607             :                                           SPOOL_DSSPOOLER_KEY,
    6608             :                                           SPOOL_REG_DRIVERNAME,
    6609             :                                           REG_SZ,
    6610             :                                           buffer.data,
    6611          24 :                                           buffer.length);
    6612          24 :                 if (!W_ERROR_IS_OK(result)) {
    6613           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
    6614           0 :                         goto done;
    6615             :                 }
    6616             : 
    6617          24 :                 if (!force_update) {
    6618           8 :                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
    6619             :                                 printer->drivername));
    6620             : 
    6621           8 :                         notify_printer_driver(global_event_context(), msg_ctx,
    6622           8 :                                               snum, printer->drivername ?
    6623             :                                               printer->drivername : "");
    6624             :                 }
    6625             :         }
    6626             : 
    6627         100 :         if (printer->comment != NULL &&
    6628          84 :             (force_update ||
    6629          84 :              !strequal(printer->comment, old_printer->comment))) {
    6630          34 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
    6631          34 :                 if (!ok) {
    6632           0 :                         DEBUG(0, ("comment data corrupted\n"));
    6633           0 :                         result = WERR_INVALID_DATA;
    6634           0 :                         goto done;
    6635             :                 }
    6636          34 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6637             :                                           printer->sharename,
    6638             :                                           SPOOL_DSSPOOLER_KEY,
    6639             :                                           SPOOL_REG_DESCRIPTION,
    6640             :                                           REG_SZ,
    6641             :                                           buffer.data,
    6642          34 :                                           buffer.length);
    6643          34 :                 if (!W_ERROR_IS_OK(result)) {
    6644           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
    6645           0 :                         goto done;
    6646             :                 }
    6647             : 
    6648          34 :                 if (!force_update) {
    6649          34 :                         notify_printer_comment(global_event_context(), msg_ctx,
    6650          34 :                                                snum, printer->comment ?
    6651             :                                                printer->comment : "");
    6652             :                 }
    6653             :         }
    6654             : 
    6655         100 :         if (printer->sharename != NULL &&
    6656          84 :             (force_update ||
    6657          84 :              !strequal(printer->sharename, old_printer->sharename))) {
    6658          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
    6659          16 :                 if (!ok) {
    6660           0 :                         DEBUG(0, ("sharename data corrupted\n"));
    6661           0 :                         result = WERR_INVALID_DATA;
    6662           0 :                         goto done;
    6663             :                 }
    6664          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6665             :                                           printer->sharename,
    6666             :                                           SPOOL_DSSPOOLER_KEY,
    6667             :                                           SPOOL_REG_PRINTSHARENAME,
    6668             :                                           REG_SZ,
    6669             :                                           buffer.data,
    6670          16 :                                           buffer.length);
    6671          16 :                 if (!W_ERROR_IS_OK(result)) {
    6672           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
    6673           0 :                         goto done;
    6674             :                 }
    6675             : 
    6676          16 :                 if (!force_update) {
    6677           0 :                         notify_printer_sharename(global_event_context(),
    6678             :                                                  msg_ctx,
    6679           0 :                                                  snum, printer->sharename ?
    6680             :                                                  printer->sharename : "");
    6681             :                 }
    6682             : 
    6683             :                 /* name change, purge any cache entries for the old */
    6684          16 :                 prune_printername_cache();
    6685             :         }
    6686             : 
    6687         100 :         if (printer->printername != NULL &&
    6688          84 :             (force_update ||
    6689          84 :              !strequal(printer->printername, old_printer->printername))) {
    6690           0 :                 const char *p;
    6691             : 
    6692         100 :                 p = strrchr(printer->printername, '\\' );
    6693         100 :                 if (p != NULL) {
    6694         100 :                         p++;
    6695             :                 } else {
    6696           0 :                         p = printer->printername;
    6697             :                 }
    6698             : 
    6699         100 :                 ok = push_reg_sz(tmp_ctx, &buffer, p);
    6700         100 :                 if (!ok) {
    6701           0 :                         DEBUG(0, ("printername data corrupted\n"));
    6702           0 :                         result = WERR_INVALID_DATA;
    6703           0 :                         goto done;
    6704             :                 }
    6705         100 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6706             :                                           printer->sharename,
    6707             :                                           SPOOL_DSSPOOLER_KEY,
    6708             :                                           SPOOL_REG_PRINTERNAME,
    6709             :                                           REG_SZ,
    6710             :                                           buffer.data,
    6711         100 :                                           buffer.length);
    6712         100 :                 if (!W_ERROR_IS_OK(result)) {
    6713           0 :                         DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
    6714           0 :                         goto done;
    6715             :                 }
    6716             : 
    6717         100 :                 if (!force_update) {
    6718          84 :                         notify_printer_printername(global_event_context(),
    6719             :                                                    msg_ctx, snum, p ? p : "");
    6720             :                 }
    6721             : 
    6722             :                 /* name change, purge any cache entries for the old */
    6723         100 :                 prune_printername_cache();
    6724             :         }
    6725             : 
    6726         100 :         if (printer->portname != NULL &&
    6727          84 :             (force_update ||
    6728          84 :              !strequal(printer->portname, old_printer->portname))) {
    6729          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
    6730          16 :                 if (!ok) {
    6731           0 :                         DEBUG(0, ("portname data corrupted\n"));
    6732           0 :                         result = WERR_INVALID_DATA;
    6733           0 :                         goto done;
    6734             :                 }
    6735          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6736             :                                           printer->sharename,
    6737             :                                           SPOOL_DSSPOOLER_KEY,
    6738             :                                           SPOOL_REG_PORTNAME,
    6739             :                                           REG_SZ,
    6740             :                                           buffer.data,
    6741          16 :                                           buffer.length);
    6742          16 :                 if (!W_ERROR_IS_OK(result)) {
    6743           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
    6744           0 :                         goto done;
    6745             :                 }
    6746             : 
    6747          16 :                 if (!force_update) {
    6748           0 :                         notify_printer_port(global_event_context(),
    6749           0 :                                             msg_ctx, snum, printer->portname ?
    6750             :                                             printer->portname : "");
    6751             :                 }
    6752             :         }
    6753             : 
    6754         100 :         if (printer->location != NULL &&
    6755          84 :             (force_update ||
    6756          84 :              !strequal(printer->location, old_printer->location))) {
    6757           8 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
    6758           8 :                 if (!ok) {
    6759           0 :                         DEBUG(0, ("location data corrupted\n"));
    6760           0 :                         result = WERR_INVALID_DATA;
    6761           0 :                         goto done;
    6762             :                 }
    6763           8 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6764             :                                           printer->sharename,
    6765             :                                           SPOOL_DSSPOOLER_KEY,
    6766             :                                           SPOOL_REG_LOCATION,
    6767             :                                           REG_SZ,
    6768             :                                           buffer.data,
    6769           8 :                                           buffer.length);
    6770           8 :                 if (!W_ERROR_IS_OK(result)) {
    6771           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
    6772           0 :                         goto done;
    6773             :                 }
    6774             : 
    6775           8 :                 if (!force_update) {
    6776           8 :                         notify_printer_location(global_event_context(),
    6777             :                                                 msg_ctx, snum,
    6778           8 :                                                 printer->location ?
    6779             :                                                 printer->location : "");
    6780             :                 }
    6781             :         }
    6782             : 
    6783         100 :         if (printer->sepfile != NULL &&
    6784          84 :             (force_update ||
    6785          84 :              !strequal(printer->sepfile, old_printer->sepfile))) {
    6786           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
    6787           0 :                 if (!ok) {
    6788           0 :                         DEBUG(0, ("sepfile data corrupted\n"));
    6789           0 :                         result = WERR_INVALID_DATA;
    6790           0 :                         goto done;
    6791             :                 }
    6792           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6793             :                                           printer->sharename,
    6794             :                                           SPOOL_DSSPOOLER_KEY,
    6795             :                                           SPOOL_REG_PRINTSEPARATORFILE,
    6796             :                                           REG_SZ,
    6797             :                                           buffer.data,
    6798           0 :                                           buffer.length);
    6799           0 :                 if (!W_ERROR_IS_OK(result)) {
    6800           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
    6801           0 :                         goto done;
    6802             :                 }
    6803             : 
    6804           0 :                 if (!force_update) {
    6805           0 :                         notify_printer_sepfile(global_event_context(),
    6806             :                                                msg_ctx, snum,
    6807           0 :                                                printer->sepfile ?
    6808             :                                                printer->sepfile : "");
    6809             :                 }
    6810             :         }
    6811             : 
    6812         100 :         if (printer->starttime != 0 &&
    6813           0 :             (force_update ||
    6814           0 :              printer->starttime != old_printer->starttime)) {
    6815           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6816           0 :                 SIVAL(buffer.data, 0, printer->starttime);
    6817           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6818             :                                           printer->sharename,
    6819             :                                           SPOOL_DSSPOOLER_KEY,
    6820             :                                           SPOOL_REG_PRINTSTARTTIME,
    6821             :                                           REG_DWORD,
    6822             :                                           buffer.data,
    6823           0 :                                           buffer.length);
    6824           0 :                 if (!W_ERROR_IS_OK(result)) {
    6825           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
    6826           0 :                         goto done;
    6827             :                 }
    6828             :         }
    6829             : 
    6830         100 :         if (printer->untiltime != 0 &&
    6831           0 :             (force_update ||
    6832           0 :              printer->untiltime != old_printer->untiltime)) {
    6833           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6834           0 :                 SIVAL(buffer.data, 0, printer->untiltime);
    6835           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6836             :                                           printer->sharename,
    6837             :                                           SPOOL_DSSPOOLER_KEY,
    6838             :                                           SPOOL_REG_PRINTENDTIME,
    6839             :                                           REG_DWORD,
    6840             :                                           buffer.data,
    6841           0 :                                           buffer.length);
    6842           0 :                 if (!W_ERROR_IS_OK(result)) {
    6843           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6844           0 :                         goto done;
    6845             :                 }
    6846             :         }
    6847             : 
    6848         100 :         if (force_update || printer->priority != old_printer->priority) {
    6849          16 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6850          16 :                 SIVAL(buffer.data, 0, printer->priority);
    6851          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6852             :                                           printer->sharename,
    6853             :                                           SPOOL_DSSPOOLER_KEY,
    6854             :                                           SPOOL_REG_PRIORITY,
    6855             :                                           REG_DWORD,
    6856             :                                           buffer.data,
    6857          16 :                                           buffer.length);
    6858          16 :                 if (!W_ERROR_IS_OK(result)) {
    6859           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6860           0 :                         goto done;
    6861             :                 }
    6862             :         }
    6863             : 
    6864         100 :         if (force_update || printer->attributes != old_printer->attributes) {
    6865          16 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6866          16 :                 SIVAL(buffer.data, 0, (printer->attributes &
    6867             :                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
    6868          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6869             :                                           printer->sharename,
    6870             :                                           SPOOL_DSSPOOLER_KEY,
    6871             :                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
    6872             :                                           REG_DWORD,
    6873             :                                           buffer.data,
    6874          16 :                                           buffer.length);
    6875          16 :                 if (!W_ERROR_IS_OK(result)) {
    6876           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6877           0 :                         goto done;
    6878             :                 }
    6879             : 
    6880          16 :                 switch (printer->attributes & 0x3) {
    6881          16 :                         case 0:
    6882          16 :                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
    6883          16 :                                 break;
    6884           0 :                         case 1:
    6885           0 :                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
    6886           0 :                                 break;
    6887           0 :                         case 2:
    6888           0 :                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
    6889           0 :                                 break;
    6890           0 :                         default:
    6891           0 :                                 spooling = "unknown";
    6892             :                 }
    6893          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
    6894          16 :                 if (!ok) {
    6895           0 :                         DEBUG(0, ("printSpooling data corrupted\n"));
    6896           0 :                         result = WERR_INVALID_DATA;
    6897           0 :                         goto done;
    6898             :                 }
    6899          16 :                 winreg_set_printer_dataex(tmp_ctx, b,
    6900             :                                           printer->sharename,
    6901             :                                           SPOOL_DSSPOOLER_KEY,
    6902             :                                           SPOOL_REG_PRINTSPOOLING,
    6903             :                                           REG_SZ,
    6904             :                                           buffer.data,
    6905          16 :                                           buffer.length);
    6906             :         }
    6907             : 
    6908         100 :         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
    6909         100 :         if (!ok) {
    6910           0 :                 DEBUG(0, ("shortServerName data corrupted\n"));
    6911           0 :                 result = WERR_INVALID_DATA;
    6912           0 :                 goto done;
    6913             :         }
    6914         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6915             :                                   printer->sharename,
    6916             :                                   SPOOL_DSSPOOLER_KEY,
    6917             :                                   SPOOL_REG_SHORTSERVERNAME,
    6918             :                                   REG_SZ,
    6919             :                                   buffer.data,
    6920         100 :                                   buffer.length);
    6921         100 :         if (!W_ERROR_IS_OK(result)) {
    6922           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
    6923           0 :                 goto done;
    6924             :         }
    6925             : 
    6926         100 :         dnsdomname = get_mydnsfullname();
    6927         100 :         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
    6928         100 :                 longname = talloc_strdup(tmp_ctx, dnsdomname);
    6929             :         } else {
    6930           0 :                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
    6931             :         }
    6932         100 :         if (longname == NULL) {
    6933           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    6934           0 :                 goto done;
    6935             :         }
    6936             : 
    6937         100 :         ok = push_reg_sz(tmp_ctx, &buffer, longname);
    6938         100 :         if (!ok) {
    6939           0 :                 DEBUG(0, ("longname data corrupted\n"));
    6940           0 :                 result = WERR_INVALID_DATA;
    6941           0 :                 goto done;
    6942             :         }
    6943         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6944             :                                            printer->sharename,
    6945             :                                            SPOOL_DSSPOOLER_KEY,
    6946             :                                            SPOOL_REG_SERVERNAME,
    6947             :                                            REG_SZ,
    6948             :                                            buffer.data,
    6949         100 :                                            buffer.length);
    6950         100 :         if (!W_ERROR_IS_OK(result)) {
    6951           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
    6952           0 :                 goto done;
    6953             :         }
    6954             : 
    6955         100 :         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
    6956             :                                   lp_netbios_name(), printer->sharename);
    6957         100 :         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
    6958         100 :         if (!ok) {
    6959           0 :                 DEBUG(0, ("uncName data corrupted\n"));
    6960           0 :                 result = WERR_INVALID_DATA;
    6961           0 :                 goto done;
    6962             :         }
    6963         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6964             :                                   printer->sharename,
    6965             :                                   SPOOL_DSSPOOLER_KEY,
    6966             :                                   SPOOL_REG_UNCNAME,
    6967             :                                   REG_SZ,
    6968             :                                   buffer.data,
    6969         100 :                                   buffer.length);
    6970         100 :         if (!W_ERROR_IS_OK(result)) {
    6971           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
    6972           0 :                 goto done;
    6973             :         }
    6974             : 
    6975         100 : done:
    6976         100 :         talloc_free(tmp_ctx);
    6977         100 :         return result;
    6978             : }
    6979             : 
    6980             : /********************************************************************
    6981             :  * Called by spoolss_api_setprinter
    6982             :  * when updating a printer description.
    6983             :  ********************************************************************/
    6984             : 
    6985          84 : static WERROR update_printer(struct pipes_struct *p,
    6986             :                              struct policy_handle *handle,
    6987             :                              struct spoolss_SetPrinterInfoCtr *info_ctr,
    6988             :                              struct spoolss_DeviceMode *devmode)
    6989             : {
    6990          84 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6991          84 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    6992           0 :         const struct tsocket_address *remote_address =
    6993          84 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    6994           0 :         struct auth_session_info *session_info =
    6995          84 :                 dcesrv_call_session_info(dce_call);
    6996          84 :         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
    6997          84 :         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
    6998           0 :         struct spoolss_PrinterInfo2 *old_printer;
    6999          84 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    7000           0 :         const struct loadparm_substitution *lp_sub =
    7001          84 :                 loadparm_s3_global_substitution();
    7002           0 :         int snum;
    7003          84 :         WERROR result = WERR_OK;
    7004           0 :         TALLOC_CTX *tmp_ctx;
    7005           0 :         struct dcerpc_binding_handle *b;
    7006             : 
    7007          84 :         DEBUG(8,("update_printer\n"));
    7008             : 
    7009          84 :         tmp_ctx = talloc_new(p->mem_ctx);
    7010          84 :         if (tmp_ctx == NULL) {
    7011           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    7012             :         }
    7013             : 
    7014          84 :         if (!Printer) {
    7015           0 :                 result = WERR_INVALID_HANDLE;
    7016           0 :                 goto done;
    7017             :         }
    7018             : 
    7019          84 :         if (!get_printer_snum(p, handle, &snum, NULL)) {
    7020           0 :                 result = WERR_INVALID_HANDLE;
    7021           0 :                 goto done;
    7022             :         }
    7023             : 
    7024          84 :         result = winreg_printer_binding_handle(tmp_ctx,
    7025             :                                                get_session_info_system(),
    7026             :                                                p->msg_ctx,
    7027             :                                                &b);
    7028          84 :         if (!W_ERROR_IS_OK(result)) {
    7029           0 :                 goto done;
    7030             :         }
    7031             : 
    7032          84 :         result = winreg_get_printer(tmp_ctx, b,
    7033             :                                     lp_const_servicename(snum),
    7034             :                                     &old_printer);
    7035          84 :         if (!W_ERROR_IS_OK(result)) {
    7036           0 :                 result = WERR_INVALID_HANDLE;
    7037           0 :                 goto done;
    7038             :         }
    7039             : 
    7040             :         /* Do sanity check on the requested changes for Samba */
    7041          84 :         if (!check_printer_ok(tmp_ctx, printer, snum)) {
    7042           0 :                 result = WERR_INVALID_PARAMETER;
    7043           0 :                 goto done;
    7044             :         }
    7045             : 
    7046             :         /* FIXME!!! If the driver has changed we really should verify that
    7047             :            it is installed before doing much else   --jerry */
    7048             : 
    7049             :         /* Check calling user has permission to update printer description */
    7050          84 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
    7051           0 :                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
    7052           0 :                 result = WERR_ACCESS_DENIED;
    7053           0 :                 goto done;
    7054             :         }
    7055             : 
    7056             :         /* Call addprinter hook */
    7057             :         /* Check changes to see if this is really needed */
    7058             : 
    7059          84 :         if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
    7060          84 :                         (!strequal(printer->drivername, old_printer->drivername) ||
    7061          76 :                          !strequal(printer->comment, old_printer->comment) ||
    7062          42 :                          !strequal(printer->portname, old_printer->portname) ||
    7063          42 :                          !strequal(printer->location, old_printer->location)) )
    7064             :         {
    7065           0 :                 char *raddr;
    7066             : 
    7067          50 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    7068             :                                                          p->mem_ctx);
    7069          50 :                 if (raddr == NULL) {
    7070           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    7071           0 :                         goto done;
    7072             :                 }
    7073             : 
    7074             :                 /* add_printer_hook() will call reload_services() */
    7075          50 :                 if (!add_printer_hook(tmp_ctx, session_info->security_token,
    7076             :                                       printer, raddr,
    7077             :                                       p->msg_ctx)) {
    7078           0 :                         result = WERR_ACCESS_DENIED;
    7079           0 :                         goto done;
    7080             :                 }
    7081             :         }
    7082             : 
    7083          84 :         result = update_dsspooler(tmp_ctx,
    7084             :                                   get_session_info_system(),
    7085             :                                   p->msg_ctx,
    7086             :                                   snum,
    7087             :                                   printer,
    7088             :                                   old_printer);
    7089          84 :         if (!W_ERROR_IS_OK(result)) {
    7090           0 :                 goto done;
    7091             :         }
    7092             : 
    7093          84 :         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
    7094             : 
    7095          84 :         if (devmode == NULL) {
    7096          76 :                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
    7097             :         }
    7098          84 :         result = winreg_update_printer(tmp_ctx, b,
    7099             :                                        printer->sharename,
    7100             :                                        printer_mask,
    7101             :                                        printer,
    7102             :                                        devmode,
    7103             :                                        NULL);
    7104             : 
    7105          84 : done:
    7106          84 :         talloc_free(tmp_ctx);
    7107             : 
    7108          84 :         return result;
    7109             : }
    7110             : 
    7111             : /****************************************************************************
    7112             : ****************************************************************************/
    7113           8 : static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
    7114             :                                            struct policy_handle *handle,
    7115             :                                            struct spoolss_SetPrinterInfo7 *info7)
    7116             : {
    7117             : #ifdef HAVE_ADS
    7118           0 :         const struct loadparm_substitution *lp_sub =
    7119           6 :                 loadparm_s3_global_substitution();
    7120           6 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    7121           0 :         WERROR result;
    7122           0 :         int snum;
    7123           0 :         struct printer_handle *Printer;
    7124             : 
    7125           6 :         if ( lp_security() != SEC_ADS ) {
    7126           6 :                 return WERR_INVALID_LEVEL;
    7127             :         }
    7128             : 
    7129           0 :         Printer = find_printer_index_by_hnd(p, handle);
    7130             : 
    7131           0 :         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
    7132             : 
    7133           0 :         if (!Printer)
    7134           0 :                 return WERR_INVALID_HANDLE;
    7135             : 
    7136           0 :         if (!get_printer_snum(p, handle, &snum, NULL))
    7137           0 :                 return WERR_INVALID_HANDLE;
    7138             : 
    7139           0 :         result = winreg_get_printer_internal(p->mem_ctx,
    7140             :                                     get_session_info_system(),
    7141             :                                     p->msg_ctx,
    7142           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum),
    7143             :                                     &pinfo2);
    7144           0 :         if (!W_ERROR_IS_OK(result)) {
    7145           0 :                 return WERR_INVALID_HANDLE;
    7146             :         }
    7147             : 
    7148           0 :         nt_printer_publish(pinfo2,
    7149             :                            get_session_info_system(),
    7150             :                            p->msg_ctx,
    7151             :                            pinfo2,
    7152           0 :                            info7->action);
    7153             : 
    7154           0 :         TALLOC_FREE(pinfo2);
    7155           0 :         return WERR_OK;
    7156             : #else
    7157           2 :         return WERR_INVALID_LEVEL;
    7158             : #endif
    7159             : }
    7160             : 
    7161             : /********************************************************************
    7162             :  ********************************************************************/
    7163             : 
    7164         296 : static WERROR update_printer_devmode(struct pipes_struct *p,
    7165             :                                      struct policy_handle *handle,
    7166             :                                      struct spoolss_DeviceMode *devmode)
    7167             : {
    7168           0 :         int snum;
    7169         296 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    7170         296 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
    7171             : 
    7172         296 :         DEBUG(8,("update_printer_devmode\n"));
    7173             : 
    7174         296 :         if (!Printer) {
    7175           0 :                 return WERR_INVALID_HANDLE;
    7176             :         }
    7177             : 
    7178         296 :         if (!get_printer_snum(p, handle, &snum, NULL)) {
    7179           0 :                 return WERR_INVALID_HANDLE;
    7180             :         }
    7181             : 
    7182             :         /* Check calling user has permission to update printer description */
    7183         296 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
    7184           0 :                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
    7185           0 :                 return WERR_ACCESS_DENIED;
    7186             :         }
    7187             : 
    7188         296 :         return winreg_update_printer_internal(p->mem_ctx,
    7189             :                                      get_session_info_system(),
    7190             :                                      p->msg_ctx,
    7191             :                                      lp_const_servicename(snum),
    7192             :                                      info2_mask,
    7193             :                                      NULL,
    7194             :                                      devmode,
    7195             :                                      NULL);
    7196             : }
    7197             : 
    7198             : 
    7199             : /****************************************************************
    7200             :  _spoolss_SetPrinter
    7201             : ****************************************************************/
    7202             : 
    7203         584 : WERROR _spoolss_SetPrinter(struct pipes_struct *p,
    7204             :                            struct spoolss_SetPrinter *r)
    7205             : {
    7206           0 :         WERROR result;
    7207             : 
    7208         584 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    7209             : 
    7210         584 :         if (!Printer) {
    7211           0 :                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
    7212             :                         OUR_HANDLE(r->in.handle)));
    7213           0 :                 return WERR_INVALID_HANDLE;
    7214             :         }
    7215             : 
    7216             :         /* check the level */
    7217         584 :         switch (r->in.info_ctr->level) {
    7218         104 :                 case 0:
    7219         104 :                         return control_printer(r->in.handle, r->in.command, p);
    7220          84 :                 case 2:
    7221          84 :                         result = update_printer(p, r->in.handle,
    7222             :                                                 r->in.info_ctr,
    7223          84 :                                                 r->in.devmode_ctr->devmode);
    7224          84 :                         if (!W_ERROR_IS_OK(result))
    7225           0 :                                 return result;
    7226          84 :                         if (r->in.secdesc_ctr->sd)
    7227          28 :                                 result = update_printer_sec(r->in.handle, p,
    7228             :                                                             r->in.secdesc_ctr);
    7229          84 :                         return result;
    7230          92 :                 case 3:
    7231          92 :                         return update_printer_sec(r->in.handle, p,
    7232             :                                                   r->in.secdesc_ctr);
    7233           0 :                 case 4: {
    7234           0 :                         struct spoolss_PrinterInfo2 *old_printer;
    7235           0 :                         struct spoolss_SetPrinterInfo2 *set_old_printer;
    7236           0 :                         struct spoolss_SetPrinterInfoCtr *info_ctr;
    7237           0 :                         struct dcerpc_binding_handle *b;
    7238           0 :                         int snum;
    7239           0 :                         TALLOC_CTX *tmp_ctx;
    7240             : 
    7241           0 :                         tmp_ctx = talloc_new(p->mem_ctx);
    7242           0 :                         if (tmp_ctx == NULL) {
    7243           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7244             :                         }
    7245             : 
    7246           0 :                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7247           0 :                                 TALLOC_FREE(tmp_ctx);
    7248           0 :                                 return WERR_INVALID_HANDLE;
    7249             :                         }
    7250             : 
    7251           0 :                         result = winreg_printer_binding_handle(tmp_ctx,
    7252             :                                                                get_session_info_system(),
    7253             :                                                                p->msg_ctx,
    7254             :                                                                &b);
    7255           0 :                         if (!W_ERROR_IS_OK(result)) {
    7256           0 :                                 TALLOC_FREE(tmp_ctx);
    7257           0 :                                 return result;
    7258             :                         }
    7259             : 
    7260           0 :                         result = winreg_get_printer(tmp_ctx, b,
    7261             :                                                     lp_const_servicename(snum),
    7262             :                                                     &old_printer);
    7263           0 :                         if (!W_ERROR_IS_OK(result)) {
    7264           0 :                                 TALLOC_FREE(tmp_ctx);
    7265           0 :                                 return WERR_INVALID_HANDLE;
    7266             :                         }
    7267             : 
    7268           0 :                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
    7269           0 :                         if (old_printer->servername == NULL) {
    7270           0 :                                 TALLOC_FREE(tmp_ctx);
    7271           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7272             :                         }
    7273             : 
    7274           0 :                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
    7275           0 :                         if (old_printer->printername == NULL) {
    7276           0 :                                 TALLOC_FREE(tmp_ctx);
    7277           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7278             :                         }
    7279             : 
    7280           0 :                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
    7281             : 
    7282           0 :                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
    7283           0 :                         if (set_old_printer == NULL) {
    7284           0 :                                 TALLOC_FREE(tmp_ctx);
    7285           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7286             :                         }
    7287             : 
    7288           0 :                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
    7289             : 
    7290           0 :                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
    7291           0 :                         if (info_ctr == NULL) {
    7292           0 :                                 TALLOC_FREE(tmp_ctx);
    7293           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7294             :                         }
    7295             : 
    7296           0 :                         info_ctr->level = 2;
    7297           0 :                         info_ctr->info.info2 = set_old_printer;
    7298             : 
    7299           0 :                         result = update_printer(p, r->in.handle,
    7300             :                                                 info_ctr,
    7301           0 :                                                 r->in.devmode_ctr->devmode);
    7302             : 
    7303           0 :                         if (!W_ERROR_IS_OK(result)) {
    7304           0 :                                 TALLOC_FREE(tmp_ctx);
    7305           0 :                                 return result;
    7306             :                         }
    7307             : 
    7308           0 :                         if (r->in.secdesc_ctr->sd) {
    7309           0 :                                 result = update_printer_sec(r->in.handle, p,
    7310             :                                                             r->in.secdesc_ctr);
    7311             :                         }
    7312             : 
    7313           0 :                         TALLOC_FREE(tmp_ctx);
    7314           0 :                         return result;
    7315             :                 }
    7316           8 :                 case 7:
    7317           8 :                         return publish_or_unpublish_printer(p, r->in.handle,
    7318           8 :                                                             r->in.info_ctr->info.info7);
    7319         296 :                 case 8:
    7320         296 :                         return update_printer_devmode(p, r->in.handle,
    7321         296 :                                                       r->in.devmode_ctr->devmode);
    7322           0 :                 default:
    7323           0 :                         return WERR_INVALID_LEVEL;
    7324             :         }
    7325             : }
    7326             : 
    7327             : /****************************************************************
    7328             :  _spoolss_FindClosePrinterNotify
    7329             : ****************************************************************/
    7330             : 
    7331           0 : WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
    7332             :                                        struct spoolss_FindClosePrinterNotify *r)
    7333             : {
    7334           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    7335             : 
    7336           0 :         if (!Printer) {
    7337           0 :                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
    7338             :                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
    7339           0 :                 return WERR_INVALID_HANDLE;
    7340             :         }
    7341             : 
    7342           0 :         if (Printer->notify.cli_chan != NULL &&
    7343           0 :             Printer->notify.cli_chan->active_connections > 0) {
    7344           0 :                 int snum = -1;
    7345             : 
    7346           0 :                 if (Printer->printer_type == SPLHND_PRINTER) {
    7347           0 :                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7348           0 :                                 return WERR_INVALID_HANDLE;
    7349             :                         }
    7350             :                 }
    7351             : 
    7352           0 :                 srv_spoolss_replycloseprinter(snum, Printer);
    7353             :         }
    7354             : 
    7355           0 :         Printer->notify.flags=0;
    7356           0 :         Printer->notify.options=0;
    7357           0 :         Printer->notify.localmachine[0]='\0';
    7358           0 :         Printer->notify.printerlocal=0;
    7359           0 :         TALLOC_FREE(Printer->notify.option);
    7360             : 
    7361           0 :         return WERR_OK;
    7362             : }
    7363             : 
    7364             : /****************************************************************
    7365             :  _spoolss_AddJob
    7366             : ****************************************************************/
    7367             : 
    7368          16 : WERROR _spoolss_AddJob(struct pipes_struct *p,
    7369             :                        struct spoolss_AddJob *r)
    7370             : {
    7371          16 :         if (!r->in.buffer && (r->in.offered != 0)) {
    7372           0 :                 return WERR_INVALID_PARAMETER;
    7373             :         }
    7374             : 
    7375             :         /* this is what a NT server returns for AddJob. AddJob must fail on
    7376             :          * non-local printers */
    7377             : 
    7378          16 :         if (r->in.level != 1) {
    7379           8 :                 return WERR_INVALID_LEVEL;
    7380             :         }
    7381             : 
    7382           8 :         return WERR_INVALID_PARAMETER;
    7383             : }
    7384             : 
    7385             : /****************************************************************************
    7386             : fill_job_info1
    7387             : ****************************************************************************/
    7388             : 
    7389         320 : static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
    7390             :                              struct spoolss_JobInfo1 *r,
    7391             :                              const print_queue_struct *queue,
    7392             :                              uint32_t jobid,
    7393             :                              int position, int snum,
    7394             :                              struct spoolss_PrinterInfo2 *pinfo2)
    7395             : {
    7396           0 :         const struct loadparm_substitution *lp_sub =
    7397         320 :                 loadparm_s3_global_substitution();
    7398           0 :         struct tm *t;
    7399             : 
    7400         320 :         t = gmtime(&queue->time);
    7401             : 
    7402         320 :         r->job_id            = jobid;
    7403             : 
    7404         320 :         r->printer_name              = lp_servicename(mem_ctx, lp_sub, snum);
    7405         320 :         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
    7406         320 :         r->server_name               = talloc_strdup(mem_ctx, pinfo2->servername);
    7407         320 :         W_ERROR_HAVE_NO_MEMORY(r->server_name);
    7408         320 :         r->user_name         = talloc_strdup(mem_ctx, queue->fs_user);
    7409         320 :         W_ERROR_HAVE_NO_MEMORY(r->user_name);
    7410         320 :         r->document_name     = talloc_strdup(mem_ctx, queue->fs_file);
    7411         320 :         W_ERROR_HAVE_NO_MEMORY(r->document_name);
    7412         320 :         r->data_type         = talloc_strdup(mem_ctx, "RAW");
    7413         320 :         W_ERROR_HAVE_NO_MEMORY(r->data_type);
    7414         320 :         r->text_status               = talloc_strdup(mem_ctx, "");
    7415         320 :         W_ERROR_HAVE_NO_MEMORY(r->text_status);
    7416             : 
    7417         320 :         r->status            = nt_printj_status(queue->status);
    7418         320 :         r->priority          = queue->priority;
    7419         320 :         r->position          = position;
    7420         320 :         r->total_pages               = queue->page_count;
    7421         320 :         r->pages_printed     = 0; /* ??? */
    7422             : 
    7423         320 :         init_systemtime(&r->submitted, t);
    7424             : 
    7425         320 :         return WERR_OK;
    7426             : }
    7427             : 
    7428             : /****************************************************************************
    7429             : fill_job_info2
    7430             : ****************************************************************************/
    7431             : 
    7432          72 : static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
    7433             :                              struct spoolss_JobInfo2 *r,
    7434             :                              const print_queue_struct *queue,
    7435             :                              uint32_t jobid,
    7436             :                              int position, int snum,
    7437             :                              struct spoolss_PrinterInfo2 *pinfo2,
    7438             :                              struct spoolss_DeviceMode *devmode)
    7439             : {
    7440           0 :         const struct loadparm_substitution *lp_sub =
    7441          72 :                 loadparm_s3_global_substitution();
    7442           0 :         struct tm *t;
    7443             : 
    7444          72 :         t = gmtime(&queue->time);
    7445             : 
    7446          72 :         r->job_id            = jobid;
    7447             : 
    7448          72 :         r->printer_name              = lp_servicename(mem_ctx, lp_sub, snum);
    7449          72 :         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
    7450          72 :         r->server_name               = talloc_strdup(mem_ctx, pinfo2->servername);
    7451          72 :         W_ERROR_HAVE_NO_MEMORY(r->server_name);
    7452          72 :         r->user_name         = talloc_strdup(mem_ctx, queue->fs_user);
    7453          72 :         W_ERROR_HAVE_NO_MEMORY(r->user_name);
    7454          72 :         r->document_name     = talloc_strdup(mem_ctx, queue->fs_file);
    7455          72 :         W_ERROR_HAVE_NO_MEMORY(r->document_name);
    7456          72 :         r->notify_name               = talloc_strdup(mem_ctx, queue->fs_user);
    7457          72 :         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
    7458          72 :         r->data_type         = talloc_strdup(mem_ctx, "RAW");
    7459          72 :         W_ERROR_HAVE_NO_MEMORY(r->data_type);
    7460          72 :         r->print_processor   = talloc_strdup(mem_ctx, "winprint");
    7461          72 :         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
    7462          72 :         r->parameters                = talloc_strdup(mem_ctx, "");
    7463          72 :         W_ERROR_HAVE_NO_MEMORY(r->parameters);
    7464          72 :         r->driver_name               = talloc_strdup(mem_ctx, pinfo2->drivername);
    7465          72 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    7466             : 
    7467          72 :         r->devmode           = devmode;
    7468             : 
    7469          72 :         r->text_status               = talloc_strdup(mem_ctx, "");
    7470          72 :         W_ERROR_HAVE_NO_MEMORY(r->text_status);
    7471             : 
    7472          72 :         r->secdesc           = NULL;
    7473             : 
    7474          72 :         r->status            = nt_printj_status(queue->status);
    7475          72 :         r->priority          = queue->priority;
    7476          72 :         r->position          = position;
    7477          72 :         r->start_time                = 0;
    7478          72 :         r->until_time                = 0;
    7479          72 :         r->total_pages               = queue->page_count;
    7480          72 :         r->size                      = queue->size;
    7481          72 :         init_systemtime(&r->submitted, t);
    7482          72 :         r->time                      = 0;
    7483          72 :         r->pages_printed     = 0; /* ??? */
    7484             : 
    7485          72 :         return WERR_OK;
    7486             : }
    7487             : 
    7488             : /****************************************************************************
    7489             :  Enumjobs at level 1.
    7490             : ****************************************************************************/
    7491             : 
    7492          24 : static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
    7493             :                               const print_queue_struct *queue,
    7494             :                               uint32_t num_queues, int snum,
    7495             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7496             :                               union spoolss_JobInfo **info_p,
    7497             :                               uint32_t *count)
    7498             : {
    7499           0 :         union spoolss_JobInfo *info;
    7500           0 :         int i;
    7501          24 :         WERROR result = WERR_OK;
    7502           0 :         uint32_t num_filled;
    7503           0 :         struct tdb_print_db *pdb;
    7504             : 
    7505          24 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7506          24 :         if (info == NULL) {
    7507           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7508           0 :                 goto err_out;
    7509             :         }
    7510             : 
    7511          24 :         pdb = get_print_db_byname(pinfo2->sharename);
    7512          24 :         if (pdb == NULL) {
    7513           0 :                 result = WERR_INVALID_PARAMETER;
    7514           0 :                 goto err_info_free;
    7515             :         }
    7516             : 
    7517          24 :         num_filled = 0;
    7518         216 :         for (i = 0; i < num_queues; i++) {
    7519         192 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7520         192 :                 if (jobid == (uint32_t)-1) {
    7521           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7522           0 :                         continue;
    7523             :                 }
    7524             : 
    7525         192 :                 result = fill_job_info1(info,
    7526         192 :                                         &info[num_filled].info1,
    7527         192 :                                         &queue[i],
    7528             :                                         jobid,
    7529             :                                         i,
    7530             :                                         snum,
    7531             :                                         pinfo2);
    7532         192 :                 if (!W_ERROR_IS_OK(result)) {
    7533           0 :                         goto err_pdb_drop;
    7534             :                 }
    7535             : 
    7536         192 :                 num_filled++;
    7537             :         }
    7538             : 
    7539          24 :         release_print_db(pdb);
    7540          24 :         *info_p = info;
    7541          24 :         *count = num_filled;
    7542             : 
    7543          24 :         return WERR_OK;
    7544             : 
    7545           0 : err_pdb_drop:
    7546           0 :         release_print_db(pdb);
    7547           0 : err_info_free:
    7548           0 :         TALLOC_FREE(info);
    7549           0 : err_out:
    7550           0 :         *count = 0;
    7551           0 :         return result;
    7552             : }
    7553             : 
    7554             : /****************************************************************************
    7555             :  Enumjobs at level 2.
    7556             : ****************************************************************************/
    7557             : 
    7558          16 : static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
    7559             :                               const print_queue_struct *queue,
    7560             :                               uint32_t num_queues, int snum,
    7561             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7562             :                               union spoolss_JobInfo **info_p,
    7563             :                               uint32_t *count)
    7564             : {
    7565           0 :         union spoolss_JobInfo *info;
    7566           0 :         int i;
    7567          16 :         WERROR result = WERR_OK;
    7568           0 :         uint32_t num_filled;
    7569           0 :         struct tdb_print_db *pdb;
    7570             : 
    7571          16 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7572          16 :         if (info == NULL) {
    7573           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7574           0 :                 goto err_out;
    7575             :         }
    7576             : 
    7577          16 :         pdb = get_print_db_byname(pinfo2->sharename);
    7578          16 :         if (pdb == NULL) {
    7579           0 :                 result = WERR_INVALID_PARAMETER;
    7580           0 :                 goto err_info_free;
    7581             :         }
    7582             : 
    7583          16 :         num_filled = 0;
    7584          88 :         for (i = 0; i< num_queues; i++) {
    7585           0 :                 struct spoolss_DeviceMode *devmode;
    7586          72 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7587          72 :                 if (jobid == (uint32_t)-1) {
    7588           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7589           0 :                         continue;
    7590             :                 }
    7591             : 
    7592          72 :                 result = spoolss_create_default_devmode(info,
    7593             :                                                         pinfo2->printername,
    7594             :                                                         &devmode);
    7595          72 :                 if (!W_ERROR_IS_OK(result)) {
    7596           0 :                         DEBUG(3, ("Can't proceed w/o a devmode!\n"));
    7597           0 :                         goto err_pdb_drop;
    7598             :                 }
    7599             : 
    7600          72 :                 result = fill_job_info2(info,
    7601          72 :                                         &info[num_filled].info2,
    7602          72 :                                         &queue[i],
    7603             :                                         jobid,
    7604             :                                         i,
    7605             :                                         snum,
    7606             :                                         pinfo2,
    7607             :                                         devmode);
    7608          72 :                 if (!W_ERROR_IS_OK(result)) {
    7609           0 :                         goto err_pdb_drop;
    7610             :                 }
    7611          72 :                 num_filled++;
    7612             :         }
    7613             : 
    7614          16 :         release_print_db(pdb);
    7615          16 :         *info_p = info;
    7616          16 :         *count = num_filled;
    7617             : 
    7618          16 :         return WERR_OK;
    7619             : 
    7620           0 : err_pdb_drop:
    7621           0 :         release_print_db(pdb);
    7622           0 : err_info_free:
    7623           0 :         TALLOC_FREE(info);
    7624           0 : err_out:
    7625           0 :         *count = 0;
    7626           0 :         return result;
    7627             : }
    7628             : 
    7629             : /****************************************************************************
    7630             :  Enumjobs at level 3.
    7631             : ****************************************************************************/
    7632             : 
    7633           0 : static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
    7634             :                               const print_queue_struct *queue,
    7635             :                               uint32_t num_queues, int snum,
    7636             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7637             :                               union spoolss_JobInfo **info_p,
    7638             :                               uint32_t *count)
    7639             : {
    7640           0 :         union spoolss_JobInfo *info;
    7641           0 :         int i;
    7642           0 :         WERROR result = WERR_OK;
    7643           0 :         uint32_t num_filled;
    7644           0 :         struct tdb_print_db *pdb;
    7645             : 
    7646           0 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7647           0 :         if (info == NULL) {
    7648           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7649           0 :                 goto err_out;
    7650             :         }
    7651             : 
    7652           0 :         pdb = get_print_db_byname(pinfo2->sharename);
    7653           0 :         if (pdb == NULL) {
    7654           0 :                 result = WERR_INVALID_PARAMETER;
    7655           0 :                 goto err_info_free;
    7656             :         }
    7657             : 
    7658           0 :         num_filled = 0;
    7659           0 :         for (i = 0; i < num_queues; i++) {
    7660           0 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7661           0 :                 if (jobid == (uint32_t)-1) {
    7662           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7663           0 :                         continue;
    7664             :                 }
    7665             : 
    7666           0 :                 info[num_filled].info3.job_id = jobid;
    7667             :                 /* next_job_id is overwritten on next iteration */
    7668           0 :                 info[num_filled].info3.next_job_id = 0;
    7669           0 :                 info[num_filled].info3.reserved = 0;
    7670             : 
    7671           0 :                 if (num_filled > 0) {
    7672           0 :                         info[num_filled - 1].info3.next_job_id = jobid;
    7673             :                 }
    7674           0 :                 num_filled++;
    7675             :         }
    7676             : 
    7677           0 :         release_print_db(pdb);
    7678           0 :         *info_p = info;
    7679           0 :         *count = num_filled;
    7680             : 
    7681           0 :         return WERR_OK;
    7682             : 
    7683           0 : err_info_free:
    7684           0 :         TALLOC_FREE(info);
    7685           0 : err_out:
    7686           0 :         *count = 0;
    7687           0 :         return result;
    7688             : }
    7689             : 
    7690             : /****************************************************************
    7691             :  _spoolss_EnumJobs
    7692             : ****************************************************************/
    7693             : 
    7694          98 : WERROR _spoolss_EnumJobs(struct pipes_struct *p,
    7695             :                          struct spoolss_EnumJobs *r)
    7696             : {
    7697           0 :         WERROR result;
    7698          98 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    7699           0 :         int snum;
    7700           0 :         print_status_struct prt_status;
    7701          98 :         print_queue_struct *queue = NULL;
    7702           0 :         uint32_t count;
    7703             : 
    7704             :         /* that's an [in out] buffer */
    7705             : 
    7706          98 :         if (!r->in.buffer && (r->in.offered != 0)) {
    7707           0 :                 return WERR_INVALID_PARAMETER;
    7708             :         }
    7709             : 
    7710          98 :         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
    7711          12 :                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
    7712          12 :                 return WERR_INVALID_LEVEL;
    7713             :         }
    7714             : 
    7715          86 :         DEBUG(4,("_spoolss_EnumJobs\n"));
    7716             : 
    7717          86 :         *r->out.needed = 0;
    7718          86 :         *r->out.count = 0;
    7719          86 :         *r->out.info = NULL;
    7720             : 
    7721             :         /* lookup the printer snum and tdb entry */
    7722             : 
    7723          86 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7724           0 :                 return WERR_INVALID_HANDLE;
    7725             :         }
    7726             : 
    7727          86 :         result = winreg_get_printer_internal(p->mem_ctx,
    7728             :                                     get_session_info_system(),
    7729             :                                     p->msg_ctx,
    7730             :                                     lp_const_servicename(snum),
    7731             :                                     &pinfo2);
    7732          86 :         if (!W_ERROR_IS_OK(result)) {
    7733           0 :                 return result;
    7734             :         }
    7735             : 
    7736          86 :         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
    7737          86 :         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
    7738             :                 count, prt_status.status, prt_status.message));
    7739             : 
    7740          86 :         if (count == 0) {
    7741          46 :                 SAFE_FREE(queue);
    7742          46 :                 TALLOC_FREE(pinfo2);
    7743          46 :                 return WERR_OK;
    7744             :         }
    7745             : 
    7746          40 :         switch (r->in.level) {
    7747          24 :         case 1:
    7748          24 :                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
    7749             :                                          pinfo2, r->out.info, r->out.count);
    7750          24 :                 break;
    7751          16 :         case 2:
    7752          16 :                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
    7753             :                                          pinfo2, r->out.info, r->out.count);
    7754          16 :                 break;
    7755           0 :         case 3:
    7756           0 :                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
    7757             :                                          pinfo2, r->out.info, r->out.count);
    7758           0 :                 break;
    7759           0 :         default:
    7760           0 :                 SMB_ASSERT(false);      /* level checked on entry */
    7761             :                 break;
    7762             :         }
    7763             : 
    7764          40 :         SAFE_FREE(queue);
    7765          40 :         TALLOC_FREE(pinfo2);
    7766             : 
    7767          40 :         if (!W_ERROR_IS_OK(result)) {
    7768           0 :                 return result;
    7769             :         }
    7770             : 
    7771          40 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    7772             :                                                      spoolss_EnumJobs,
    7773             :                                                      *r->out.info, r->in.level,
    7774             :                                                      *r->out.count);
    7775          40 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    7776          40 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    7777             : 
    7778          40 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    7779             : }
    7780             : 
    7781             : /****************************************************************
    7782             :  _spoolss_ScheduleJob
    7783             : ****************************************************************/
    7784             : 
    7785           0 : WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
    7786             :                             struct spoolss_ScheduleJob *r)
    7787             : {
    7788           0 :         return WERR_OK;
    7789             : }
    7790             : 
    7791             : /****************************************************************
    7792             : ****************************************************************/
    7793             : 
    7794          32 : static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
    7795             :                                struct messaging_context *msg_ctx,
    7796             :                                const char *printer_name,
    7797             :                                uint32_t job_id,
    7798             :                                struct spoolss_SetJobInfo1 *r)
    7799             : {
    7800           0 :         char *old_doc_name;
    7801             : 
    7802          32 :         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
    7803           0 :                 return WERR_INVALID_HANDLE;
    7804             :         }
    7805             : 
    7806          32 :         if (strequal(old_doc_name, r->document_name)) {
    7807           0 :                 return WERR_OK;
    7808             :         }
    7809             : 
    7810          32 :         if (!print_job_set_name(global_event_context(), msg_ctx,
    7811             :                                 printer_name, job_id, r->document_name)) {
    7812           0 :                 return WERR_INVALID_HANDLE;
    7813             :         }
    7814             : 
    7815          32 :         return WERR_OK;
    7816             : }
    7817             : 
    7818             : /****************************************************************
    7819             :  _spoolss_SetJob
    7820             : ****************************************************************/
    7821             : 
    7822         640 : WERROR _spoolss_SetJob(struct pipes_struct *p,
    7823             :                        struct spoolss_SetJob *r)
    7824             : {
    7825         640 :         struct dcesrv_call_state *dce_call = p->dce_call;
    7826           0 :         struct auth_session_info *session_info =
    7827         640 :                 dcesrv_call_session_info(dce_call);
    7828           0 :         int snum;
    7829         640 :         WERROR errcode = WERR_INVALID_FUNCTION;
    7830             : 
    7831         640 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7832           0 :                 return WERR_INVALID_HANDLE;
    7833             :         }
    7834             : 
    7835         640 :         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
    7836         238 :                 return WERR_INVALID_PRINTER_NAME;
    7837             :         }
    7838             : 
    7839         402 :         switch (r->in.command) {
    7840         306 :         case SPOOLSS_JOB_CONTROL_CANCEL:
    7841             :         case SPOOLSS_JOB_CONTROL_DELETE:
    7842         306 :                 errcode = print_job_delete(session_info, p->msg_ctx,
    7843             :                                            snum, r->in.job_id);
    7844         306 :                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
    7845         306 :                         errcode = WERR_OK;
    7846             :                 }
    7847         306 :                 break;
    7848          32 :         case SPOOLSS_JOB_CONTROL_PAUSE:
    7849          32 :                 errcode = print_job_pause(session_info, p->msg_ctx,
    7850             :                                           snum, r->in.job_id);
    7851          32 :                 break;
    7852          32 :         case SPOOLSS_JOB_CONTROL_RESTART:
    7853             :         case SPOOLSS_JOB_CONTROL_RESUME:
    7854          32 :                 errcode = print_job_resume(session_info, p->msg_ctx,
    7855             :                                            snum, r->in.job_id);
    7856          32 :                 break;
    7857          32 :         case SPOOLSS_JOB_CONTROL_NOOP:
    7858          32 :                 errcode = WERR_OK;
    7859          32 :                 break;
    7860           0 :         default:
    7861           0 :                 return WERR_INVALID_LEVEL;
    7862             :         }
    7863             : 
    7864         402 :         if (!W_ERROR_IS_OK(errcode)) {
    7865           0 :                 return errcode;
    7866             :         }
    7867             : 
    7868         402 :         if (r->in.ctr == NULL) {
    7869         370 :                 return errcode;
    7870             :         }
    7871             : 
    7872          32 :         switch (r->in.ctr->level) {
    7873          32 :         case 1:
    7874          32 :                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
    7875             :                                            lp_const_servicename(snum),
    7876             :                                            r->in.job_id,
    7877          32 :                                            r->in.ctr->info.info1);
    7878          32 :                 break;
    7879           0 :         case 2:
    7880             :         case 3:
    7881             :         case 4:
    7882             :         default:
    7883           0 :                 return WERR_INVALID_LEVEL;
    7884             :         }
    7885             : 
    7886          32 :         return errcode;
    7887             : }
    7888             : 
    7889             : /****************************************************************************
    7890             :  Enumerates all printer drivers by level and architecture.
    7891             : ****************************************************************************/
    7892             : 
    7893         460 : static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
    7894             :                                                        const struct auth_session_info *session_info,
    7895             :                                                        struct messaging_context *msg_ctx,
    7896             :                                                        const char *servername,
    7897             :                                                        const char *architecture,
    7898             :                                                        uint32_t level,
    7899             :                                                        union spoolss_DriverInfo **info_p,
    7900             :                                                        uint32_t *count_p)
    7901             : {
    7902           0 :         int i;
    7903           0 :         uint32_t version;
    7904           0 :         struct spoolss_DriverInfo8 *driver;
    7905         460 :         union spoolss_DriverInfo *info = NULL;
    7906         460 :         uint32_t count = 0;
    7907         460 :         WERROR result = WERR_OK;
    7908           0 :         uint32_t num_drivers;
    7909           0 :         const char **drivers;
    7910           0 :         struct dcerpc_binding_handle *b;
    7911         460 :         TALLOC_CTX *tmp_ctx = NULL;
    7912             : 
    7913         460 :         *count_p = 0;
    7914         460 :         *info_p = NULL;
    7915             : 
    7916         460 :         tmp_ctx = talloc_new(mem_ctx);
    7917         460 :         if (!tmp_ctx) {
    7918           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    7919             :         }
    7920             : 
    7921         460 :         result = winreg_printer_binding_handle(tmp_ctx,
    7922             :                                                session_info,
    7923             :                                                msg_ctx,
    7924             :                                                &b);
    7925         460 :         if (!W_ERROR_IS_OK(result)) {
    7926           0 :                 goto out;
    7927             :         }
    7928             : 
    7929        2300 :         for (version=0; version<DRIVER_MAX_VERSION; version++) {
    7930        1840 :                 result = winreg_get_driver_list(tmp_ctx, b,
    7931             :                                                 architecture, version,
    7932             :                                                 &num_drivers, &drivers);
    7933        1840 :                 if (!W_ERROR_IS_OK(result)) {
    7934           0 :                         goto out;
    7935             :                 }
    7936        1840 :                 DEBUG(4, ("we have:[%d] drivers in environment"
    7937             :                           " [%s] and version [%d]\n",
    7938             :                           num_drivers, architecture, version));
    7939             : 
    7940        1840 :                 if (num_drivers != 0) {
    7941           0 :                         info = talloc_realloc(tmp_ctx, info,
    7942             :                                                     union spoolss_DriverInfo,
    7943             :                                                     count + num_drivers);
    7944           0 :                         if (!info) {
    7945           0 :                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
    7946             :                                         "failed to enlarge driver info buffer!\n"));
    7947           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
    7948           0 :                                 goto out;
    7949             :                         }
    7950             :                 }
    7951             : 
    7952        1840 :                 for (i = 0; i < num_drivers; i++) {
    7953           0 :                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
    7954             : 
    7955           0 :                         result = winreg_get_driver(tmp_ctx, b,
    7956           0 :                                                    architecture, drivers[i],
    7957             :                                                    version, &driver);
    7958           0 :                         if (!W_ERROR_IS_OK(result)) {
    7959           0 :                                 goto out;
    7960             :                         }
    7961             : 
    7962           0 :                         switch (level) {
    7963           0 :                         case 1:
    7964           0 :                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
    7965             :                                                                    driver, servername);
    7966           0 :                                 break;
    7967           0 :                         case 2:
    7968           0 :                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
    7969             :                                                                    driver, servername);
    7970           0 :                                 break;
    7971           0 :                         case 3:
    7972           0 :                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
    7973             :                                                                    driver, servername);
    7974           0 :                                 break;
    7975           0 :                         case 4:
    7976           0 :                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
    7977             :                                                                    driver, servername);
    7978           0 :                                 break;
    7979           0 :                         case 5:
    7980           0 :                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
    7981             :                                                                    driver, servername);
    7982           0 :                                 break;
    7983           0 :                         case 6:
    7984           0 :                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
    7985             :                                                                    driver, servername);
    7986           0 :                                 break;
    7987           0 :                         case 8:
    7988           0 :                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
    7989             :                                                                    driver, servername);
    7990           0 :                                 break;
    7991           0 :                         default:
    7992           0 :                                 result = WERR_INVALID_LEVEL;
    7993           0 :                                 break;
    7994             :                         }
    7995             : 
    7996           0 :                         TALLOC_FREE(driver);
    7997             : 
    7998           0 :                         if (!W_ERROR_IS_OK(result)) {
    7999           0 :                                 goto out;
    8000             :                         }
    8001             :                 }
    8002             : 
    8003        1840 :                 count += num_drivers;
    8004        1840 :                 TALLOC_FREE(drivers);
    8005             :         }
    8006             : 
    8007         460 : out:
    8008         460 :         if (W_ERROR_IS_OK(result)) {
    8009         460 :                 *info_p = talloc_move(mem_ctx, &info);
    8010         460 :                 *count_p = count;
    8011             :         }
    8012             : 
    8013         460 :         talloc_free(tmp_ctx);
    8014         460 :         return result;
    8015             : }
    8016             : 
    8017             : /****************************************************************************
    8018             :  Enumerates all printer drivers by level.
    8019             : ****************************************************************************/
    8020             : 
    8021         108 : static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
    8022             :                                        const struct auth_session_info *session_info,
    8023             :                                        struct messaging_context *msg_ctx,
    8024             :                                        const char *servername,
    8025             :                                        const char *architecture,
    8026             :                                        uint32_t level,
    8027             :                                        union spoolss_DriverInfo **info_p,
    8028             :                                        uint32_t *count_p)
    8029             : {
    8030           0 :         uint32_t a,i;
    8031         108 :         WERROR result = WERR_OK;
    8032             : 
    8033         108 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
    8034             : 
    8035         440 :                 for (a=0; archi_table[a].long_archi != NULL; a++) {
    8036             : 
    8037         396 :                         union spoolss_DriverInfo *info = NULL;
    8038         396 :                         uint32_t count = 0;
    8039             : 
    8040         396 :                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
    8041             :                                                                           session_info,
    8042             :                                                                           msg_ctx,
    8043             :                                                                           servername,
    8044         396 :                                                                           archi_table[a].long_archi,
    8045             :                                                                           level,
    8046             :                                                                           &info,
    8047             :                                                                           &count);
    8048         396 :                         if (!W_ERROR_IS_OK(result)) {
    8049           0 :                                 continue;
    8050             :                         }
    8051             : 
    8052         396 :                         for (i=0; i < count; i++) {
    8053           0 :                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
    8054             :                                              info[i], info_p, count_p);
    8055             :                         }
    8056             :                 }
    8057             : 
    8058          44 :                 return result;
    8059             :         }
    8060             : 
    8061          64 :         return enumprinterdrivers_level_by_architecture(mem_ctx,
    8062             :                                                         session_info,
    8063             :                                                         msg_ctx,
    8064             :                                                         servername,
    8065             :                                                         architecture,
    8066             :                                                         level,
    8067             :                                                         info_p,
    8068             :                                                         count_p);
    8069             : }
    8070             : 
    8071             : /****************************************************************
    8072             :  _spoolss_EnumPrinterDrivers
    8073             : ****************************************************************/
    8074             : 
    8075         108 : WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
    8076             :                                    struct spoolss_EnumPrinterDrivers *r)
    8077             : {
    8078           0 :         const char *cservername;
    8079           0 :         WERROR result;
    8080             : 
    8081             :         /* that's an [in out] buffer */
    8082             : 
    8083         108 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8084           0 :                 return WERR_INVALID_PARAMETER;
    8085             :         }
    8086             : 
    8087         108 :         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
    8088             : 
    8089         108 :         *r->out.needed = 0;
    8090         108 :         *r->out.count = 0;
    8091         108 :         *r->out.info = NULL;
    8092             : 
    8093         108 :         cservername = canon_servername(r->in.server);
    8094             : 
    8095         108 :         if (!is_myname_or_ipaddr(cservername)) {
    8096           0 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    8097             :         }
    8098             : 
    8099         108 :         result = enumprinterdrivers_level(p->mem_ctx,
    8100             :                                           get_session_info_system(),
    8101             :                                           p->msg_ctx,
    8102             :                                           cservername,
    8103             :                                           r->in.environment,
    8104             :                                           r->in.level,
    8105             :                                           r->out.info,
    8106             :                                           r->out.count);
    8107         108 :         if (!W_ERROR_IS_OK(result)) {
    8108           0 :                 return result;
    8109             :         }
    8110             : 
    8111         108 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8112             :                                                      spoolss_EnumPrinterDrivers,
    8113             :                                                      *r->out.info, r->in.level,
    8114             :                                                      *r->out.count);
    8115         108 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8116         108 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8117             : 
    8118         108 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8119             : }
    8120             : 
    8121             : /****************************************************************
    8122             :  _spoolss_EnumForms
    8123             : ****************************************************************/
    8124             : 
    8125         560 : WERROR _spoolss_EnumForms(struct pipes_struct *p,
    8126             :                           struct spoolss_EnumForms *r)
    8127             : {
    8128           0 :         WERROR result;
    8129             : 
    8130         560 :         *r->out.count = 0;
    8131         560 :         *r->out.needed = 0;
    8132         560 :         *r->out.info = NULL;
    8133             : 
    8134             :         /* that's an [in out] buffer */
    8135             : 
    8136         560 :         if (!r->in.buffer && (r->in.offered != 0) ) {
    8137           0 :                 return WERR_INVALID_PARAMETER;
    8138             :         }
    8139             : 
    8140         560 :         DEBUG(4,("_spoolss_EnumForms\n"));
    8141         560 :         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
    8142         560 :         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
    8143             : 
    8144         560 :         switch (r->in.level) {
    8145         536 :         case 1:
    8146         536 :                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
    8147             :                                                    get_session_info_system(),
    8148             :                                                    p->msg_ctx,
    8149             :                                                    r->out.count,
    8150             :                                                    r->out.info);
    8151         536 :                 break;
    8152          24 :         default:
    8153          24 :                 result = WERR_INVALID_LEVEL;
    8154          24 :                 break;
    8155             :         }
    8156             : 
    8157         560 :         if (!W_ERROR_IS_OK(result)) {
    8158          24 :                 return result;
    8159             :         }
    8160             : 
    8161         536 :         if (*r->out.count == 0) {
    8162           0 :                 return WERR_NO_MORE_ITEMS;
    8163             :         }
    8164             : 
    8165         536 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8166             :                                                      spoolss_EnumForms,
    8167             :                                                      *r->out.info, r->in.level,
    8168             :                                                      *r->out.count);
    8169         536 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8170         536 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8171             : 
    8172         536 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8173             : }
    8174             : 
    8175             : /****************************************************************
    8176             :  _spoolss_GetForm
    8177             : ****************************************************************/
    8178             : 
    8179        5040 : WERROR _spoolss_GetForm(struct pipes_struct *p,
    8180             :                         struct spoolss_GetForm *r)
    8181             : {
    8182           0 :         WERROR result;
    8183             : 
    8184             :         /* that's an [in out] buffer */
    8185             : 
    8186        5040 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8187           0 :                 TALLOC_FREE(r->out.info);
    8188           0 :                 return WERR_INVALID_PARAMETER;
    8189             :         }
    8190             : 
    8191        5040 :         DEBUG(4,("_spoolss_GetForm\n"));
    8192        5040 :         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
    8193        5040 :         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
    8194             : 
    8195        5040 :         switch (r->in.level) {
    8196        5040 :         case 1:
    8197        5040 :                 result = winreg_printer_getform1_internal(p->mem_ctx,
    8198             :                                                  get_session_info_system(),
    8199             :                                                  p->msg_ctx,
    8200             :                                                  r->in.form_name,
    8201        5040 :                                                  &r->out.info->info1);
    8202        5040 :                 break;
    8203           0 :         default:
    8204           0 :                 result = WERR_INVALID_LEVEL;
    8205           0 :                 break;
    8206             :         }
    8207             : 
    8208        5040 :         if (!W_ERROR_IS_OK(result)) {
    8209           0 :                 TALLOC_FREE(r->out.info);
    8210           0 :                 return result;
    8211             :         }
    8212             : 
    8213        5040 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
    8214             :                                                r->out.info, r->in.level);
    8215        5040 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    8216             : 
    8217        5040 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8218             : }
    8219             : 
    8220             : /****************************************************************************
    8221             : ****************************************************************************/
    8222             : 
    8223           8 : static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
    8224             :                           struct spoolss_PortInfo1 *r,
    8225             :                           const char *name)
    8226             : {
    8227           8 :         r->port_name = talloc_strdup(mem_ctx, name);
    8228           8 :         W_ERROR_HAVE_NO_MEMORY(r->port_name);
    8229             : 
    8230           8 :         return WERR_OK;
    8231             : }
    8232             : 
    8233             : /****************************************************************************
    8234             :  TODO: This probably needs distinguish between TCP/IP and Local ports
    8235             :  somehow.
    8236             : ****************************************************************************/
    8237             : 
    8238          16 : static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
    8239             :                           struct spoolss_PortInfo2 *r,
    8240             :                           const char *name)
    8241             : {
    8242          16 :         r->port_name = talloc_strdup(mem_ctx, name);
    8243          16 :         W_ERROR_HAVE_NO_MEMORY(r->port_name);
    8244             : 
    8245          16 :         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
    8246          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    8247             : 
    8248          16 :         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
    8249          16 :         W_ERROR_HAVE_NO_MEMORY(r->description);
    8250             : 
    8251          16 :         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
    8252          16 :         r->reserved = 0;
    8253             : 
    8254          16 :         return WERR_OK;
    8255             : }
    8256             : 
    8257             : 
    8258             : /****************************************************************************
    8259             :  wrapper around the enum ports command
    8260             : ****************************************************************************/
    8261             : 
    8262          24 : static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
    8263             : {
    8264           0 :         const struct loadparm_substitution *lp_sub =
    8265          24 :                 loadparm_s3_global_substitution();
    8266          24 :         char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
    8267          24 :         char **qlines = NULL;
    8268          24 :         char *command = NULL;
    8269           0 :         int numlines;
    8270           0 :         int ret;
    8271           0 :         int fd;
    8272             : 
    8273          24 :         *count = 0;
    8274          24 :         *lines = NULL;
    8275             : 
    8276             :         /* if no hook then just fill in the default port */
    8277             : 
    8278          24 :         if ( !*cmd ) {
    8279          24 :                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
    8280           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8281             :                 }
    8282          24 :                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
    8283           0 :                         TALLOC_FREE(qlines);
    8284           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8285             :                 }
    8286          24 :                 qlines[1] = NULL;
    8287          24 :                 numlines = 1;
    8288             :         }
    8289             :         else {
    8290             :                 /* we have a valid enumport command */
    8291             : 
    8292           0 :                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
    8293           0 :                 if (!command) {
    8294           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8295             :                 }
    8296             : 
    8297           0 :                 DEBUG(10,("Running [%s]\n", command));
    8298           0 :                 ret = smbrun(command, &fd, NULL);
    8299           0 :                 DEBUG(10,("Returned [%d]\n", ret));
    8300           0 :                 TALLOC_FREE(command);
    8301           0 :                 if (ret != 0) {
    8302           0 :                         if (fd != -1) {
    8303           0 :                                 close(fd);
    8304             :                         }
    8305           0 :                         return WERR_ACCESS_DENIED;
    8306             :                 }
    8307             : 
    8308           0 :                 numlines = 0;
    8309           0 :                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
    8310           0 :                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
    8311           0 :                 close(fd);
    8312             :         }
    8313             : 
    8314          24 :         *count = numlines;
    8315          24 :         *lines = qlines;
    8316             : 
    8317          24 :         return WERR_OK;
    8318             : }
    8319             : 
    8320             : /****************************************************************************
    8321             :  enumports level 1.
    8322             : ****************************************************************************/
    8323             : 
    8324           8 : static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
    8325             :                                 union spoolss_PortInfo **info_p,
    8326             :                                 uint32_t *count)
    8327             : {
    8328           8 :         union spoolss_PortInfo *info = NULL;
    8329           8 :         int i=0;
    8330           8 :         WERROR result = WERR_OK;
    8331           8 :         char **qlines = NULL;
    8332           8 :         int numlines = 0;
    8333             : 
    8334           8 :         result = enumports_hook(talloc_tos(), &numlines, &qlines );
    8335           8 :         if (!W_ERROR_IS_OK(result)) {
    8336           0 :                 goto out;
    8337             :         }
    8338             : 
    8339           8 :         if (numlines) {
    8340           8 :                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
    8341           8 :                 if (!info) {
    8342           0 :                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
    8343           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    8344           0 :                         goto out;
    8345             :                 }
    8346             : 
    8347          16 :                 for (i=0; i<numlines; i++) {
    8348           8 :                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
    8349           8 :                         result = fill_port_1(info, &info[i].info1, qlines[i]);
    8350           8 :                         if (!W_ERROR_IS_OK(result)) {
    8351           0 :                                 goto out;
    8352             :                         }
    8353             :                 }
    8354             :         }
    8355           8 :         TALLOC_FREE(qlines);
    8356             : 
    8357           0 : out:
    8358           8 :         if (!W_ERROR_IS_OK(result)) {
    8359           0 :                 TALLOC_FREE(info);
    8360           0 :                 TALLOC_FREE(qlines);
    8361           0 :                 *count = 0;
    8362           0 :                 *info_p = NULL;
    8363           0 :                 return result;
    8364             :         }
    8365             : 
    8366           8 :         *info_p = info;
    8367           8 :         *count = numlines;
    8368             : 
    8369           8 :         return WERR_OK;
    8370             : }
    8371             : 
    8372             : /****************************************************************************
    8373             :  enumports level 2.
    8374             : ****************************************************************************/
    8375             : 
    8376          16 : static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
    8377             :                                 union spoolss_PortInfo **info_p,
    8378             :                                 uint32_t *count)
    8379             : {
    8380          16 :         union spoolss_PortInfo *info = NULL;
    8381          16 :         int i=0;
    8382          16 :         WERROR result = WERR_OK;
    8383          16 :         char **qlines = NULL;
    8384          16 :         int numlines = 0;
    8385             : 
    8386          16 :         result = enumports_hook(talloc_tos(), &numlines, &qlines );
    8387          16 :         if (!W_ERROR_IS_OK(result)) {
    8388           0 :                 goto out;
    8389             :         }
    8390             : 
    8391          16 :         if (numlines) {
    8392          16 :                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
    8393          16 :                 if (!info) {
    8394           0 :                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
    8395           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    8396           0 :                         goto out;
    8397             :                 }
    8398             : 
    8399          32 :                 for (i=0; i<numlines; i++) {
    8400          16 :                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
    8401          16 :                         result = fill_port_2(info, &info[i].info2, qlines[i]);
    8402          16 :                         if (!W_ERROR_IS_OK(result)) {
    8403           0 :                                 goto out;
    8404             :                         }
    8405             :                 }
    8406             :         }
    8407          16 :         TALLOC_FREE(qlines);
    8408             : 
    8409           0 : out:
    8410          16 :         if (!W_ERROR_IS_OK(result)) {
    8411           0 :                 TALLOC_FREE(info);
    8412           0 :                 TALLOC_FREE(qlines);
    8413           0 :                 *count = 0;
    8414           0 :                 *info_p = NULL;
    8415           0 :                 return result;
    8416             :         }
    8417             : 
    8418          16 :         *info_p = info;
    8419          16 :         *count = numlines;
    8420             : 
    8421          16 :         return WERR_OK;
    8422             : }
    8423             : 
    8424             : /****************************************************************
    8425             :  _spoolss_EnumPorts
    8426             : ****************************************************************/
    8427             : 
    8428          24 : WERROR _spoolss_EnumPorts(struct pipes_struct *p,
    8429             :                           struct spoolss_EnumPorts *r)
    8430             : {
    8431           0 :         WERROR result;
    8432             : 
    8433             :         /* that's an [in out] buffer */
    8434             : 
    8435          24 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8436           0 :                 return WERR_INVALID_PARAMETER;
    8437             :         }
    8438             : 
    8439          24 :         DEBUG(4,("_spoolss_EnumPorts\n"));
    8440             : 
    8441          24 :         *r->out.count = 0;
    8442          24 :         *r->out.needed = 0;
    8443          24 :         *r->out.info = NULL;
    8444             : 
    8445          24 :         switch (r->in.level) {
    8446           8 :         case 1:
    8447           8 :                 result = enumports_level_1(p->mem_ctx, r->out.info,
    8448             :                                            r->out.count);
    8449           8 :                 break;
    8450          16 :         case 2:
    8451          16 :                 result = enumports_level_2(p->mem_ctx, r->out.info,
    8452             :                                            r->out.count);
    8453          16 :                 break;
    8454           0 :         default:
    8455           0 :                 return WERR_INVALID_LEVEL;
    8456             :         }
    8457             : 
    8458          24 :         if (!W_ERROR_IS_OK(result)) {
    8459           0 :                 return result;
    8460             :         }
    8461             : 
    8462          24 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8463             :                                                      spoolss_EnumPorts,
    8464             :                                                      *r->out.info, r->in.level,
    8465             :                                                      *r->out.count);
    8466          24 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8467          24 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8468             : 
    8469          24 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8470             : }
    8471             : 
    8472             : /****************************************************************************
    8473             : ****************************************************************************/
    8474             : 
    8475          96 : static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
    8476             :                                            const char *server,
    8477             :                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
    8478             :                                            struct spoolss_DeviceMode *devmode,
    8479             :                                            struct security_descriptor *secdesc,
    8480             :                                            struct spoolss_UserLevelCtr *user_ctr,
    8481             :                                            struct policy_handle *handle)
    8482             : {
    8483          96 :         struct dcesrv_call_state *dce_call = p->dce_call;
    8484          96 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    8485           0 :         const struct tsocket_address *remote_address =
    8486          96 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    8487           0 :         struct auth_session_info *session_info =
    8488          96 :                 dcesrv_call_session_info(dce_call);
    8489          96 :         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
    8490          96 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
    8491           0 :         const struct loadparm_substitution *lp_sub =
    8492          96 :                 loadparm_s3_global_substitution();
    8493           0 :         int     snum;
    8494          96 :         WERROR err = WERR_OK;
    8495             : 
    8496             :         /* samba does not have a concept of local, non-shared printers yet, so
    8497             :          * make sure we always setup sharename - gd */
    8498          96 :         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
    8499          96 :             (info2->printername != NULL && info2->printername[0] != '\0')) {
    8500          80 :                 DEBUG(5, ("spoolss_addprinterex_level_2: "
    8501             :                         "no sharename has been set, setting printername %s as sharename\n",
    8502             :                         info2->printername));
    8503          80 :                 info2->sharename = info2->printername;
    8504             :         }
    8505             : 
    8506             :         /* check to see if the printer already exists */
    8507          96 :         if ((snum = print_queue_snum(info2->sharename)) != -1) {
    8508          16 :                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
    8509             :                         info2->sharename));
    8510          16 :                 return WERR_PRINTER_ALREADY_EXISTS;
    8511             :         }
    8512             : 
    8513          80 :         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
    8514          80 :                 if ((snum = print_queue_snum(info2->printername)) != -1) {
    8515           0 :                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
    8516             :                                 info2->printername));
    8517           0 :                         return WERR_PRINTER_ALREADY_EXISTS;
    8518             :                 }
    8519             :         }
    8520             : 
    8521             :         /* validate printer info struct */
    8522          80 :         if (!info2->printername || strlen(info2->printername) == 0) {
    8523          16 :                 return WERR_INVALID_PRINTER_NAME;
    8524             :         }
    8525          64 :         if (!info2->portname || strlen(info2->portname) == 0) {
    8526          16 :                 return WERR_UNKNOWN_PORT;
    8527             :         }
    8528          48 :         if (!info2->drivername || strlen(info2->drivername) == 0) {
    8529          16 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    8530             :         }
    8531          32 :         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
    8532          16 :                 return WERR_UNKNOWN_PRINTPROCESSOR;
    8533             :         }
    8534             : 
    8535             :         /* FIXME!!!  smbd should check to see if the driver is installed before
    8536             :            trying to add a printer like this  --jerry */
    8537             : 
    8538          16 :         if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
    8539           0 :                 char *raddr;
    8540             : 
    8541          16 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    8542             :                                                          p->mem_ctx);
    8543          16 :                 if (raddr == NULL) {
    8544           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8545             :                 }
    8546             : 
    8547          16 :                 if ( !add_printer_hook(p->mem_ctx, session_info->security_token,
    8548             :                                        info2, raddr,
    8549             :                                        p->msg_ctx) ) {
    8550           0 :                         return WERR_ACCESS_DENIED;
    8551             :                 }
    8552             :         } else {
    8553           0 :                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
    8554             :                         "smb.conf parameter \"addprinter command\" is defined. This "
    8555             :                         "parameter must exist for this call to succeed\n",
    8556             :                         info2->sharename ));
    8557             :         }
    8558             : 
    8559          16 :         if ((snum = print_queue_snum(info2->sharename)) == -1) {
    8560           0 :                 return WERR_ACCESS_DENIED;
    8561             :         }
    8562             : 
    8563             :         /* you must be a printer admin to add a new printer */
    8564          16 :         if (!W_ERROR_IS_OK(print_access_check(session_info,
    8565             :                                               p->msg_ctx,
    8566             :                                               snum,
    8567             :                                               PRINTER_ACCESS_ADMINISTER))) {
    8568           0 :                 return WERR_ACCESS_DENIED;
    8569             :         }
    8570             : 
    8571             :         /*
    8572             :          * Do sanity check on the requested changes for Samba.
    8573             :          */
    8574             : 
    8575          16 :         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
    8576           0 :                 return WERR_INVALID_PARAMETER;
    8577             :         }
    8578             : 
    8579          16 :         if (devmode == NULL) {
    8580          16 :                 info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
    8581             :         }
    8582             : 
    8583          16 :         err = update_dsspooler(p->mem_ctx,
    8584             :                                get_session_info_system(),
    8585             :                                p->msg_ctx,
    8586             :                                0,
    8587             :                                info2,
    8588             :                                NULL);
    8589          16 :         if (!W_ERROR_IS_OK(err)) {
    8590           0 :                 return err;
    8591             :         }
    8592             : 
    8593          16 :         err = winreg_update_printer_internal(p->mem_ctx,
    8594             :                                     get_session_info_system(),
    8595             :                                     p->msg_ctx,
    8596             :                                     info2->sharename,
    8597             :                                     info2_mask,
    8598             :                                     info2,
    8599             :                                     devmode,
    8600             :                                     secdesc);
    8601          16 :         if (!W_ERROR_IS_OK(err)) {
    8602           0 :                 return err;
    8603             :         }
    8604             : 
    8605          16 :         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
    8606          16 :         if (!W_ERROR_IS_OK(err)) {
    8607             :                 /* Handle open failed - remove addition. */
    8608           0 :                 ZERO_STRUCTP(handle);
    8609           0 :                 return err;
    8610             :         }
    8611             : 
    8612          16 :         return WERR_OK;
    8613             : }
    8614             : 
    8615             : /****************************************************************
    8616             :  _spoolss_AddPrinterEx
    8617             : ****************************************************************/
    8618             : 
    8619          96 : WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
    8620             :                              struct spoolss_AddPrinterEx *r)
    8621             : {
    8622          96 :         switch (r->in.info_ctr->level) {
    8623           0 :         case 1:
    8624             :                 /* we don't handle yet */
    8625             :                 /* but I know what to do ... */
    8626           0 :                 return WERR_INVALID_LEVEL;
    8627          96 :         case 2:
    8628          96 :                 return spoolss_addprinterex_level_2(p, r->in.server,
    8629             :                                                     r->in.info_ctr,
    8630          96 :                                                     r->in.devmode_ctr->devmode,
    8631          96 :                                                     r->in.secdesc_ctr->sd,
    8632             :                                                     r->in.userlevel_ctr,
    8633             :                                                     r->out.handle);
    8634           0 :         default:
    8635           0 :                 return WERR_INVALID_LEVEL;
    8636             :         }
    8637             : }
    8638             : 
    8639             : /****************************************************************
    8640             :  _spoolss_AddPrinter
    8641             : ****************************************************************/
    8642             : 
    8643          72 : WERROR _spoolss_AddPrinter(struct pipes_struct *p,
    8644             :                            struct spoolss_AddPrinter *r)
    8645             : {
    8646           0 :         struct spoolss_AddPrinterEx a;
    8647           0 :         struct spoolss_UserLevelCtr userlevel_ctr;
    8648             : 
    8649          72 :         ZERO_STRUCT(userlevel_ctr);
    8650             : 
    8651          72 :         userlevel_ctr.level = 1;
    8652             : 
    8653          72 :         a.in.server             = r->in.server;
    8654          72 :         a.in.info_ctr           = r->in.info_ctr;
    8655          72 :         a.in.devmode_ctr        = r->in.devmode_ctr;
    8656          72 :         a.in.secdesc_ctr        = r->in.secdesc_ctr;
    8657          72 :         a.in.userlevel_ctr      = &userlevel_ctr;
    8658          72 :         a.out.handle            = r->out.handle;
    8659             : 
    8660          72 :         return _spoolss_AddPrinterEx(p, &a);
    8661             : }
    8662             : 
    8663             : /****************************************************************
    8664             :  _spoolss_AddPrinterDriverEx
    8665             : ****************************************************************/
    8666             : 
    8667           0 : WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
    8668             :                                    struct spoolss_AddPrinterDriverEx *r)
    8669             : {
    8670           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    8671           0 :         struct auth_session_info *session_info =
    8672           0 :                 dcesrv_call_session_info(dce_call);
    8673           0 :         WERROR err = WERR_OK;
    8674           0 :         const char *driver_name = NULL;
    8675           0 :         const char *driver_directory = NULL;
    8676           0 :         uint32_t version;
    8677             : 
    8678             :         /*
    8679             :          * we only support the semantics of AddPrinterDriver()
    8680             :          * i.e. only copy files that are newer than existing ones
    8681             :          */
    8682             : 
    8683           0 :         if (r->in.flags == 0) {
    8684           0 :                 return WERR_INVALID_PARAMETER;
    8685             :         }
    8686             : 
    8687           0 :         if (!(r->in.flags & APD_COPY_ALL_FILES) &&
    8688           0 :             !(r->in.flags & APD_COPY_NEW_FILES)) {
    8689           0 :                 return WERR_ACCESS_DENIED;
    8690             :         }
    8691             : 
    8692             :         /* FIXME */
    8693           0 :         if (r->in.info_ctr->level != 3 &&
    8694           0 :             r->in.info_ctr->level != 6 &&
    8695           0 :             r->in.info_ctr->level != 8) {
    8696           0 :                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
    8697             :                         r->in.info_ctr->level));
    8698           0 :                 return WERR_INVALID_LEVEL;
    8699             :         }
    8700             : 
    8701           0 :         DEBUG(5,("Cleaning driver's information\n"));
    8702           0 :         err = clean_up_driver_struct(p->mem_ctx,
    8703             :                                      session_info,
    8704           0 :                                      r->in.info_ctr,
    8705             :                                      r->in.flags,
    8706             :                                      &driver_directory);
    8707           0 :         if (!W_ERROR_IS_OK(err)) {
    8708           0 :                 DBG_ERR("clean_up_driver_struct failed - %s\n",
    8709             :                         win_errstr(err));
    8710           0 :                 goto done;
    8711             :         }
    8712             : 
    8713           0 :         DEBUG(5,("Moving driver to final destination\n"));
    8714           0 :         err = move_driver_to_download_area(session_info,
    8715           0 :                                            r->in.info_ctr,
    8716             :                                            driver_directory);
    8717           0 :         if (!W_ERROR_IS_OK(err)) {
    8718           0 :                 DBG_ERR("move_driver_to_download_area failed - %s\n",
    8719             :                         win_errstr(err));
    8720           0 :                 goto done;
    8721             :         }
    8722             : 
    8723           0 :         err = winreg_add_driver_internal(p->mem_ctx,
    8724             :                                 get_session_info_system(),
    8725             :                                 p->msg_ctx,
    8726             :                                 r->in.info_ctr,
    8727             :                                 &driver_name,
    8728             :                                 &version);
    8729           0 :         if (!W_ERROR_IS_OK(err)) {
    8730           0 :                 DBG_ERR("winreg_add_driver_internal failed - %s\n",
    8731             :                         win_errstr(err));
    8732           0 :                 goto done;
    8733             :         }
    8734             : 
    8735             :         /*
    8736             :          * I think this is where the DrvUpgradePrinter() hook would be
    8737             :          * be called in a driver's interface DLL on a Windows NT 4.0/2k
    8738             :          * server.  Right now, we just need to send ourselves a message
    8739             :          * to update each printer bound to this driver.   --jerry
    8740             :          */
    8741             : 
    8742           0 :         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
    8743           0 :                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
    8744             :                         __func__, driver_name));
    8745             :         }
    8746             : 
    8747           0 : done:
    8748           0 :         return err;
    8749             : }
    8750             : 
    8751             : /****************************************************************
    8752             :  _spoolss_AddPrinterDriver
    8753             : ****************************************************************/
    8754             : 
    8755           0 : WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
    8756             :                                  struct spoolss_AddPrinterDriver *r)
    8757             : {
    8758           0 :         struct spoolss_AddPrinterDriverEx a;
    8759             : 
    8760           0 :         switch (r->in.info_ctr->level) {
    8761           0 :         case 2:
    8762             :         case 3:
    8763             :         case 4:
    8764             :         case 5:
    8765           0 :                 break;
    8766           0 :         default:
    8767           0 :                 return WERR_INVALID_LEVEL;
    8768             :         }
    8769             : 
    8770           0 :         a.in.servername         = r->in.servername;
    8771           0 :         a.in.info_ctr           = r->in.info_ctr;
    8772           0 :         a.in.flags              = APD_COPY_NEW_FILES;
    8773             : 
    8774           0 :         return _spoolss_AddPrinterDriverEx(p, &a);
    8775             : }
    8776             : 
    8777             : /****************************************************************************
    8778             : ****************************************************************************/
    8779             : 
    8780             : struct _spoolss_paths {
    8781             :         int type;
    8782             :         const char *share;
    8783             :         const char *dir;
    8784             : };
    8785             : 
    8786             : enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
    8787             : 
    8788             : static const struct _spoolss_paths spoolss_paths[]= {
    8789             :         { SPOOLSS_DRIVER_PATH,          "print$",     "DRIVERS" },
    8790             :         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",   "PRTPROCS" }
    8791             : };
    8792             : 
    8793         208 : static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
    8794             :                                           const char *servername,
    8795             :                                           const char *environment,
    8796             :                                           int component,
    8797             :                                           char **path)
    8798             : {
    8799         208 :         const char *pservername = NULL;
    8800           0 :         const char *long_archi;
    8801           0 :         const char *short_archi;
    8802             : 
    8803         208 :         *path = NULL;
    8804             : 
    8805             :         /* environment may be empty */
    8806         208 :         if (environment && strlen(environment)) {
    8807         208 :                 long_archi = environment;
    8808             :         } else {
    8809           0 :                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    8810             :                                                   "spoolss", "architecture",
    8811             :                                                   GLOBAL_SPOOLSS_ARCHITECTURE);
    8812             :         }
    8813             : 
    8814             :         /* servername may be empty */
    8815         208 :         if (servername && strlen(servername)) {
    8816         144 :                 pservername = canon_servername(servername);
    8817             : 
    8818         144 :                 if (!is_myname_or_ipaddr(pservername)) {
    8819           0 :                         return WERR_INVALID_PARAMETER;
    8820             :                 }
    8821             :         }
    8822             : 
    8823         208 :         if (!(short_archi = get_short_archi(long_archi))) {
    8824           0 :                 return WERR_INVALID_ENVIRONMENT;
    8825             :         }
    8826             : 
    8827         208 :         switch (component) {
    8828         208 :         case SPOOLSS_PRTPROCS_PATH:
    8829             :         case SPOOLSS_DRIVER_PATH:
    8830         208 :                 if (pservername) {
    8831         144 :                         *path = talloc_asprintf(mem_ctx,
    8832             :                                         "\\\\%s\\%s\\%s",
    8833             :                                         pservername,
    8834         144 :                                         spoolss_paths[component].share,
    8835             :                                         short_archi);
    8836             :                 } else {
    8837          64 :                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
    8838             :                                         SPOOLSS_DEFAULT_SERVER_PATH,
    8839          64 :                                         spoolss_paths[component].dir,
    8840             :                                         short_archi);
    8841             :                 }
    8842         208 :                 break;
    8843           0 :         default:
    8844           0 :                 return WERR_INVALID_PARAMETER;
    8845             :         }
    8846             : 
    8847         208 :         if (!*path) {
    8848           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    8849             :         }
    8850             : 
    8851         208 :         return WERR_OK;
    8852             : }
    8853             : 
    8854             : /****************************************************************************
    8855             : ****************************************************************************/
    8856             : 
    8857         168 : static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
    8858             :                                           const char *servername,
    8859             :                                           const char *environment,
    8860             :                                           struct spoolss_DriverDirectoryInfo1 *r)
    8861             : {
    8862           0 :         WERROR werr;
    8863         168 :         char *path = NULL;
    8864             : 
    8865         168 :         werr = compose_spoolss_server_path(mem_ctx,
    8866             :                                            servername,
    8867             :                                            environment,
    8868             :                                            SPOOLSS_DRIVER_PATH,
    8869             :                                            &path);
    8870         168 :         if (!W_ERROR_IS_OK(werr)) {
    8871           0 :                 return werr;
    8872             :         }
    8873             : 
    8874         168 :         DEBUG(4,("printer driver directory: [%s]\n", path));
    8875             : 
    8876         168 :         r->directory_name = path;
    8877             : 
    8878         168 :         return WERR_OK;
    8879             : }
    8880             : 
    8881             : /****************************************************************
    8882             :  _spoolss_GetPrinterDriverDirectory
    8883             : ****************************************************************/
    8884             : 
    8885         168 : WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
    8886             :                                           struct spoolss_GetPrinterDriverDirectory *r)
    8887             : {
    8888           0 :         WERROR werror;
    8889             : 
    8890             :         /* that's an [in out] buffer */
    8891             : 
    8892         168 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8893           0 :                 TALLOC_FREE(r->out.info);
    8894           0 :                 return WERR_INVALID_PARAMETER;
    8895             :         }
    8896             : 
    8897         168 :         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
    8898             :                 r->in.level));
    8899             : 
    8900         168 :         *r->out.needed = 0;
    8901             : 
    8902             :         /* r->in.level is ignored */
    8903             : 
    8904         168 :         werror = getprinterdriverdir_level_1(p->mem_ctx,
    8905             :                                              r->in.server,
    8906             :                                              r->in.environment,
    8907         168 :                                              &r->out.info->info1);
    8908         168 :         if (!W_ERROR_IS_OK(werror)) {
    8909           0 :                 TALLOC_FREE(r->out.info);
    8910           0 :                 return werror;
    8911             :         }
    8912             : 
    8913         168 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
    8914             :                                                r->out.info, r->in.level);
    8915         168 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    8916             : 
    8917         168 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8918             : }
    8919             : 
    8920             : /****************************************************************
    8921             :  _spoolss_EnumPrinterData
    8922             : ****************************************************************/
    8923             : 
    8924         152 : WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
    8925             :                                 struct spoolss_EnumPrinterData *r)
    8926             : {
    8927           0 :         WERROR result;
    8928           0 :         struct spoolss_EnumPrinterDataEx r2;
    8929           0 :         uint32_t count;
    8930         152 :         struct spoolss_PrinterEnumValues *info, *val = NULL;
    8931           0 :         uint32_t needed;
    8932             : 
    8933         152 :         r2.in.handle    = r->in.handle;
    8934         152 :         r2.in.key_name  = "PrinterDriverData";
    8935         152 :         r2.in.offered   = 0;
    8936         152 :         r2.out.count    = &count;
    8937         152 :         r2.out.info     = &info;
    8938         152 :         r2.out.needed   = &needed;
    8939             : 
    8940         152 :         result = _spoolss_EnumPrinterDataEx(p, &r2);
    8941         152 :         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
    8942         112 :                 r2.in.offered = needed;
    8943         112 :                 result = _spoolss_EnumPrinterDataEx(p, &r2);
    8944             :         }
    8945         152 :         if (!W_ERROR_IS_OK(result)) {
    8946           0 :                 return result;
    8947             :         }
    8948             : 
    8949             :         /*
    8950             :          * The NT machine wants to know the biggest size of value and data
    8951             :          *
    8952             :          * cf: MSDN EnumPrinterData remark section
    8953             :          */
    8954             : 
    8955         152 :         if (!r->in.value_offered && !r->in.data_offered) {
    8956          48 :                 uint32_t biggest_valuesize = 0;
    8957          48 :                 uint32_t biggest_datasize = 0;
    8958           0 :                 int i, name_length;
    8959             : 
    8960          48 :                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
    8961             : 
    8962         132 :                 for (i=0; i<count; i++) {
    8963             : 
    8964          84 :                         name_length = strlen(info[i].value_name);
    8965          84 :                         if (strlen(info[i].value_name) > biggest_valuesize) {
    8966          28 :                                 biggest_valuesize = name_length;
    8967             :                         }
    8968             : 
    8969          84 :                         if (info[i].data_length > biggest_datasize) {
    8970          28 :                                 biggest_datasize = info[i].data_length;
    8971             :                         }
    8972             : 
    8973          84 :                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
    8974             :                                 biggest_datasize));
    8975             :                 }
    8976             : 
    8977             :                 /* the value is an UNICODE string but real_value_size is the length
    8978             :                    in bytes including the trailing 0 */
    8979             : 
    8980          48 :                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
    8981          48 :                 *r->out.data_needed  = biggest_datasize;
    8982             : 
    8983          48 :                 DEBUG(6,("final values: [%d], [%d]\n",
    8984             :                         *r->out.value_needed, *r->out.data_needed));
    8985             : 
    8986          48 :                 return WERR_OK;
    8987             :         }
    8988             : 
    8989         104 :         if (r->in.enum_index < count) {
    8990          84 :                 val = &info[r->in.enum_index];
    8991             :         }
    8992             : 
    8993         104 :         if (val == NULL) {
    8994             :                 /* out_value should default to "" or else NT4 has
    8995             :                    problems unmarshalling the response */
    8996             : 
    8997          20 :                 if (r->in.value_offered) {
    8998          20 :                         *r->out.value_needed = 1;
    8999          20 :                         r->out.value_name = talloc_strdup(r, "");
    9000          20 :                         if (!r->out.value_name) {
    9001           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    9002             :                         }
    9003             :                 } else {
    9004           0 :                         r->out.value_name = NULL;
    9005           0 :                         *r->out.value_needed = 0;
    9006             :                 }
    9007             : 
    9008             :                 /* the data is counted in bytes */
    9009             : 
    9010          20 :                 *r->out.data_needed = r->in.data_offered;
    9011             : 
    9012          20 :                 result = WERR_NO_MORE_ITEMS;
    9013             :         } else {
    9014             :                 /*
    9015             :                  * the value is:
    9016             :                  * - counted in bytes in the request
    9017             :                  * - counted in UNICODE chars in the max reply
    9018             :                  * - counted in bytes in the real size
    9019             :                  *
    9020             :                  * take a pause *before* coding not *during* coding
    9021             :                  */
    9022             : 
    9023             :                 /* name */
    9024          84 :                 if (r->in.value_offered) {
    9025          84 :                         r->out.value_name = talloc_strdup(r, val->value_name);
    9026          84 :                         if (!r->out.value_name) {
    9027           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    9028             :                         }
    9029          84 :                         *r->out.value_needed = val->value_name_len;
    9030             :                 } else {
    9031           0 :                         r->out.value_name = NULL;
    9032           0 :                         *r->out.value_needed = 0;
    9033             :                 }
    9034             : 
    9035             :                 /* type */
    9036             : 
    9037          84 :                 *r->out.type = val->type;
    9038             : 
    9039             :                 /* data - counted in bytes */
    9040             : 
    9041             :                 /*
    9042             :                  * See the section "Dynamically Typed Query Parameters"
    9043             :                  * in MS-RPRN.
    9044             :                  */
    9045             : 
    9046          84 :                 if (r->out.data && val->data && val->data->data &&
    9047          84 :                                 val->data_length && r->in.data_offered) {
    9048          84 :                         memcpy(r->out.data, val->data->data,
    9049          84 :                                 MIN(val->data_length,r->in.data_offered));
    9050             :                 }
    9051             : 
    9052          84 :                 *r->out.data_needed = val->data_length;
    9053             : 
    9054          84 :                 result = WERR_OK;
    9055             :         }
    9056             : 
    9057         104 :         return result;
    9058             : }
    9059             : 
    9060             : /****************************************************************
    9061             :  _spoolss_SetPrinterData
    9062             : ****************************************************************/
    9063             : 
    9064         168 : WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
    9065             :                                struct spoolss_SetPrinterData *r)
    9066             : {
    9067           0 :         struct spoolss_SetPrinterDataEx r2;
    9068             : 
    9069         168 :         r2.in.handle            = r->in.handle;
    9070         168 :         r2.in.key_name          = "PrinterDriverData";
    9071         168 :         r2.in.value_name        = r->in.value_name;
    9072         168 :         r2.in.type              = r->in.type;
    9073         168 :         r2.in.data              = r->in.data;
    9074         168 :         r2.in.offered           = r->in.offered;
    9075             : 
    9076         168 :         return _spoolss_SetPrinterDataEx(p, &r2);
    9077             : }
    9078             : 
    9079             : /****************************************************************
    9080             :  _spoolss_ResetPrinter
    9081             : ****************************************************************/
    9082             : 
    9083           0 : WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
    9084             :                              struct spoolss_ResetPrinter *r)
    9085             : {
    9086           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9087           0 :         int             snum;
    9088             : 
    9089           0 :         DEBUG(5,("_spoolss_ResetPrinter\n"));
    9090             : 
    9091             :         /*
    9092             :          * All we do is to check to see if the handle and queue is valid.
    9093             :          * This call really doesn't mean anything to us because we only
    9094             :          * support RAW printing.   --jerry
    9095             :          */
    9096             : 
    9097           0 :         if (!Printer) {
    9098           0 :                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
    9099             :                         OUR_HANDLE(r->in.handle)));
    9100           0 :                 return WERR_INVALID_HANDLE;
    9101             :         }
    9102             : 
    9103           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    9104           0 :                 return WERR_INVALID_HANDLE;
    9105             : 
    9106             : 
    9107             :         /* blindly return success */
    9108           0 :         return WERR_OK;
    9109             : }
    9110             : 
    9111             : /****************************************************************
    9112             :  _spoolss_DeletePrinterData
    9113             : ****************************************************************/
    9114             : 
    9115         168 : WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
    9116             :                                   struct spoolss_DeletePrinterData *r)
    9117             : {
    9118           0 :         struct spoolss_DeletePrinterDataEx r2;
    9119             : 
    9120         168 :         r2.in.handle            = r->in.handle;
    9121         168 :         r2.in.key_name          = "PrinterDriverData";
    9122         168 :         r2.in.value_name        = r->in.value_name;
    9123             : 
    9124         168 :         return _spoolss_DeletePrinterDataEx(p, &r2);
    9125             : }
    9126             : 
    9127             : /****************************************************************
    9128             :  _spoolss_AddForm
    9129             : ****************************************************************/
    9130             : 
    9131         576 : WERROR _spoolss_AddForm(struct pipes_struct *p,
    9132             :                         struct spoolss_AddForm *r)
    9133             : {
    9134         576 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9135           0 :         struct auth_session_info *session_info =
    9136         576 :                 dcesrv_call_session_info(dce_call);
    9137           0 :         struct spoolss_AddFormInfo1 *form;
    9138         576 :         int snum = -1;
    9139         576 :         WERROR status = WERR_OK;
    9140         576 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9141           0 :         struct dcerpc_binding_handle *b;
    9142         576 :         TALLOC_CTX *tmp_ctx = NULL;
    9143             : 
    9144         576 :         DEBUG(5,("_spoolss_AddForm\n"));
    9145             : 
    9146         576 :         if (!Printer) {
    9147           0 :                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
    9148             :                         OUR_HANDLE(r->in.handle)));
    9149           0 :                 return WERR_INVALID_HANDLE;
    9150             :         }
    9151             : 
    9152             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    9153             :            and not a printer admin, then fail */
    9154             : 
    9155         576 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9156           0 :             !security_token_has_privilege(session_info->security_token,
    9157             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    9158           0 :                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
    9159           0 :                 return WERR_ACCESS_DENIED;
    9160             :         }
    9161             : 
    9162         576 :         if (r->in.info_ctr->level != 1) {
    9163           0 :                 return WERR_INVALID_LEVEL;
    9164             :         }
    9165             : 
    9166         576 :         form = r->in.info_ctr->info.info1;
    9167         576 :         if (!form) {
    9168           0 :                 return WERR_INVALID_PARAMETER;
    9169             :         }
    9170             : 
    9171         576 :         switch (form->flags) {
    9172         480 :         case SPOOLSS_FORM_USER:
    9173             :         case SPOOLSS_FORM_BUILTIN:
    9174             :         case SPOOLSS_FORM_PRINTER:
    9175         480 :                 break;
    9176          96 :         default:
    9177          96 :                 return WERR_INVALID_PARAMETER;
    9178             :         }
    9179             : 
    9180         480 :         tmp_ctx = talloc_new(p->mem_ctx);
    9181         480 :         if (!tmp_ctx) {
    9182           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9183             :         }
    9184             : 
    9185         480 :         status = winreg_printer_binding_handle(tmp_ctx,
    9186             :                                                get_session_info_system(),
    9187             :                                                p->msg_ctx,
    9188             :                                                &b);
    9189         480 :         if (!W_ERROR_IS_OK(status)) {
    9190           0 :                 goto done;
    9191             :         }
    9192             : 
    9193         480 :         status = winreg_printer_addform1(tmp_ctx, b, form);
    9194         480 :         if (!W_ERROR_IS_OK(status)) {
    9195         384 :                 goto done;
    9196             :         }
    9197             : 
    9198             :         /*
    9199             :          * ChangeID must always be set if this is a printer
    9200             :          */
    9201          96 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9202          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9203           0 :                         status = WERR_INVALID_HANDLE;
    9204           0 :                         goto done;
    9205             :                 }
    9206             : 
    9207          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9208             :                                                         lp_const_servicename(snum));
    9209             :         }
    9210             : 
    9211          16 : done:
    9212         480 :         talloc_free(tmp_ctx);
    9213         480 :         return status;
    9214             : }
    9215             : 
    9216             : /****************************************************************
    9217             :  _spoolss_DeleteForm
    9218             : ****************************************************************/
    9219             : 
    9220         384 : WERROR _spoolss_DeleteForm(struct pipes_struct *p,
    9221             :                            struct spoolss_DeleteForm *r)
    9222             : {
    9223         384 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9224           0 :         struct auth_session_info *session_info =
    9225         384 :                 dcesrv_call_session_info(dce_call);
    9226         384 :         const char *form_name = r->in.form_name;
    9227         384 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9228         384 :         int snum = -1;
    9229         384 :         WERROR status = WERR_OK;
    9230           0 :         struct dcerpc_binding_handle *b;
    9231         384 :         TALLOC_CTX *tmp_ctx = NULL;
    9232             : 
    9233         384 :         DEBUG(5,("_spoolss_DeleteForm\n"));
    9234             : 
    9235         384 :         if (!Printer) {
    9236           0 :                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
    9237             :                         OUR_HANDLE(r->in.handle)));
    9238           0 :                 return WERR_INVALID_HANDLE;
    9239             :         }
    9240             : 
    9241         384 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9242           0 :             !security_token_has_privilege(session_info->security_token,
    9243             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    9244           0 :                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
    9245           0 :                 return WERR_ACCESS_DENIED;
    9246             :         }
    9247             : 
    9248         384 :         tmp_ctx = talloc_new(p->mem_ctx);
    9249         384 :         if (!tmp_ctx) {
    9250           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9251             :         }
    9252             : 
    9253         384 :         status = winreg_printer_binding_handle(tmp_ctx,
    9254             :                                                get_session_info_system(),
    9255             :                                                p->msg_ctx,
    9256             :                                                &b);
    9257         384 :         if (!W_ERROR_IS_OK(status)) {
    9258           0 :                 goto done;
    9259             :         }
    9260             : 
    9261         384 :         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
    9262         384 :         if (!W_ERROR_IS_OK(status)) {
    9263         288 :                 goto done;
    9264             :         }
    9265             : 
    9266             :         /*
    9267             :          * ChangeID must always be set if this is a printer
    9268             :          */
    9269          96 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9270          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9271           0 :                         status = WERR_INVALID_HANDLE;
    9272           0 :                         goto done;
    9273             :                 }
    9274             : 
    9275          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9276             :                                                         lp_const_servicename(snum));
    9277             :         }
    9278             : 
    9279          16 : done:
    9280         384 :         talloc_free(tmp_ctx);
    9281         384 :         return status;
    9282             : }
    9283             : 
    9284             : /****************************************************************
    9285             :  _spoolss_SetForm
    9286             : ****************************************************************/
    9287             : 
    9288          80 : WERROR _spoolss_SetForm(struct pipes_struct *p,
    9289             :                         struct spoolss_SetForm *r)
    9290             : {
    9291          80 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9292           0 :         struct auth_session_info *session_info =
    9293          80 :                 dcesrv_call_session_info(dce_call);
    9294           0 :         struct spoolss_AddFormInfo1 *form;
    9295          80 :         const char *form_name = r->in.form_name;
    9296          80 :         int snum = -1;
    9297          80 :         WERROR status = WERR_OK;
    9298           0 :         struct dcerpc_binding_handle *b;
    9299          80 :         TALLOC_CTX *tmp_ctx = NULL;
    9300             : 
    9301          80 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9302             : 
    9303          80 :         DEBUG(5,("_spoolss_SetForm\n"));
    9304             : 
    9305          80 :         if (!Printer) {
    9306           0 :                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
    9307             :                         OUR_HANDLE(r->in.handle)));
    9308           0 :                 return WERR_INVALID_HANDLE;
    9309             :         }
    9310             : 
    9311             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    9312             :            and not a printer admin, then fail */
    9313             : 
    9314          80 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9315           0 :              !security_token_has_privilege(session_info->security_token,
    9316             :                                            SEC_PRIV_PRINT_OPERATOR)) {
    9317           0 :                 DEBUG(2,("_spoolss_SetForm: denied by insufficient permissions.\n"));
    9318           0 :                 return WERR_ACCESS_DENIED;
    9319             :         }
    9320             : 
    9321          80 :         if (r->in.info_ctr->level != 1) {
    9322           0 :                 return WERR_INVALID_LEVEL;
    9323             :         }
    9324             : 
    9325          80 :         form = r->in.info_ctr->info.info1;
    9326          80 :         if (!form) {
    9327           0 :                 return WERR_INVALID_PARAMETER;
    9328             :         }
    9329             : 
    9330          80 :         tmp_ctx = talloc_new(p->mem_ctx);
    9331          80 :         if (!tmp_ctx) {
    9332           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9333             :         }
    9334             : 
    9335          80 :         status = winreg_printer_binding_handle(tmp_ctx,
    9336             :                                                get_session_info_system(),
    9337             :                                                p->msg_ctx,
    9338             :                                                &b);
    9339          80 :         if (!W_ERROR_IS_OK(status)) {
    9340           0 :                 goto done;
    9341             :         }
    9342             : 
    9343          80 :         status = winreg_printer_setform1(tmp_ctx, b,
    9344             :                                          form_name,
    9345             :                                          form);
    9346          80 :         if (!W_ERROR_IS_OK(status)) {
    9347           0 :                 goto done;
    9348             :         }
    9349             : 
    9350             :         /*
    9351             :          * ChangeID must always be set if this is a printer
    9352             :          */
    9353          80 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9354          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9355           0 :                         status = WERR_INVALID_HANDLE;
    9356           0 :                         goto done;
    9357             :                 }
    9358             : 
    9359          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9360             :                                                         lp_const_servicename(snum));
    9361             :         }
    9362             : 
    9363           0 : done:
    9364          80 :         talloc_free(tmp_ctx);
    9365          80 :         return status;
    9366             : }
    9367             : 
    9368             : /****************************************************************************
    9369             :  fill_print_processor1
    9370             : ****************************************************************************/
    9371             : 
    9372          24 : static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
    9373             :                                     struct spoolss_PrintProcessorInfo1 *r,
    9374             :                                     const char *print_processor_name)
    9375             : {
    9376          24 :         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
    9377          24 :         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
    9378             : 
    9379          24 :         return WERR_OK;
    9380             : }
    9381             : 
    9382             : /****************************************************************************
    9383             :  enumprintprocessors level 1.
    9384             : ****************************************************************************/
    9385             : 
    9386          24 : static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
    9387             :                                           union spoolss_PrintProcessorInfo **info_p,
    9388             :                                           uint32_t *count)
    9389             : {
    9390           0 :         union spoolss_PrintProcessorInfo *info;
    9391           0 :         WERROR result;
    9392             : 
    9393          24 :         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
    9394          24 :         W_ERROR_HAVE_NO_MEMORY(info);
    9395             : 
    9396          24 :         *count = 1;
    9397             : 
    9398          24 :         result = fill_print_processor1(info, &info[0].info1, "winprint");
    9399          24 :         if (!W_ERROR_IS_OK(result)) {
    9400           0 :                 goto out;
    9401             :         }
    9402             : 
    9403          24 :  out:
    9404          24 :         if (!W_ERROR_IS_OK(result)) {
    9405           0 :                 TALLOC_FREE(info);
    9406           0 :                 *count = 0;
    9407           0 :                 return result;
    9408             :         }
    9409             : 
    9410          24 :         *info_p = info;
    9411             : 
    9412          24 :         return WERR_OK;
    9413             : }
    9414             : 
    9415             : /****************************************************************
    9416             :  _spoolss_EnumPrintProcessors
    9417             : ****************************************************************/
    9418             : 
    9419          48 : WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
    9420             :                                     struct spoolss_EnumPrintProcessors *r)
    9421             : {
    9422           0 :         WERROR result;
    9423             : 
    9424             :         /* that's an [in out] buffer */
    9425             : 
    9426          48 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9427           0 :                 return WERR_INVALID_PARAMETER;
    9428             :         }
    9429             : 
    9430          48 :         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
    9431             : 
    9432             :         /*
    9433             :          * Enumerate the print processors ...
    9434             :          *
    9435             :          * Just reply with "winprint", to keep NT happy
    9436             :          * and I can use my nice printer checker.
    9437             :          */
    9438             : 
    9439          48 :         *r->out.count = 0;
    9440          48 :         *r->out.needed = 0;
    9441          48 :         *r->out.info = NULL;
    9442             : 
    9443          48 :         if (!get_short_archi(r->in.environment)) {
    9444           4 :                 return WERR_INVALID_ENVIRONMENT;
    9445             :         }
    9446             : 
    9447          44 :         switch (r->in.level) {
    9448          24 :         case 1:
    9449          24 :                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
    9450             :                                                      r->out.count);
    9451          24 :                 break;
    9452          20 :         default:
    9453          20 :                 return WERR_INVALID_LEVEL;
    9454             :         }
    9455             : 
    9456          24 :         if (!W_ERROR_IS_OK(result)) {
    9457           0 :                 return result;
    9458             :         }
    9459             : 
    9460          24 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9461             :                                                      spoolss_EnumPrintProcessors,
    9462             :                                                      *r->out.info, r->in.level,
    9463             :                                                      *r->out.count);
    9464          24 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9465          24 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9466             : 
    9467          24 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9468             : }
    9469             : 
    9470             : /****************************************************************************
    9471             :  fill_printprocdatatype1
    9472             : ****************************************************************************/
    9473             : 
    9474          16 : static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
    9475             :                                       struct spoolss_PrintProcDataTypesInfo1 *r,
    9476             :                                       const char *name_array)
    9477             : {
    9478          16 :         r->name_array = talloc_strdup(mem_ctx, name_array);
    9479          16 :         W_ERROR_HAVE_NO_MEMORY(r->name_array);
    9480             : 
    9481          16 :         return WERR_OK;
    9482             : }
    9483             : 
    9484             : /****************************************************************************
    9485             :  enumprintprocdatatypes level 1.
    9486             : ****************************************************************************/
    9487             : 
    9488          16 : static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
    9489             :                                              union spoolss_PrintProcDataTypesInfo **info_p,
    9490             :                                              uint32_t *count)
    9491             : {
    9492           0 :         WERROR result;
    9493           0 :         union spoolss_PrintProcDataTypesInfo *info;
    9494             : 
    9495          16 :         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
    9496          16 :         W_ERROR_HAVE_NO_MEMORY(info);
    9497             : 
    9498          16 :         *count = 1;
    9499             : 
    9500          16 :         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
    9501          16 :         if (!W_ERROR_IS_OK(result)) {
    9502           0 :                 goto out;
    9503             :         }
    9504             : 
    9505          16 :  out:
    9506          16 :         if (!W_ERROR_IS_OK(result)) {
    9507           0 :                 TALLOC_FREE(info);
    9508           0 :                 *count = 0;
    9509           0 :                 return result;
    9510             :         }
    9511             : 
    9512          16 :         *info_p = info;
    9513             : 
    9514          16 :         return WERR_OK;
    9515             : }
    9516             : 
    9517             : /****************************************************************
    9518             :  _spoolss_EnumPrintProcessorDataTypes
    9519             : ****************************************************************/
    9520             : 
    9521          44 : WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
    9522             :                                             struct spoolss_EnumPrintProcessorDataTypes *r)
    9523             : {
    9524           0 :         WERROR result;
    9525             : 
    9526             :         /* that's an [in out] buffer */
    9527             : 
    9528          44 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9529           0 :                 return WERR_INVALID_PARAMETER;
    9530             :         }
    9531             : 
    9532          44 :         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
    9533             : 
    9534          44 :         *r->out.count = 0;
    9535          44 :         *r->out.needed = 0;
    9536          44 :         *r->out.info = NULL;
    9537             : 
    9538          44 :         if (r->in.print_processor_name == NULL ||
    9539          40 :             !strequal(r->in.print_processor_name, "winprint")) {
    9540           8 :                 return WERR_UNKNOWN_PRINTPROCESSOR;
    9541             :         }
    9542             : 
    9543          36 :         switch (r->in.level) {
    9544          16 :         case 1:
    9545          16 :                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
    9546             :                                                         r->out.count);
    9547          16 :                 break;
    9548          20 :         default:
    9549          20 :                 return WERR_INVALID_LEVEL;
    9550             :         }
    9551             : 
    9552          16 :         if (!W_ERROR_IS_OK(result)) {
    9553           0 :                 return result;
    9554             :         }
    9555             : 
    9556          16 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9557             :                                                      spoolss_EnumPrintProcessorDataTypes,
    9558             :                                                      *r->out.info, r->in.level,
    9559             :                                                      *r->out.count);
    9560          16 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9561          16 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9562             : 
    9563          16 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9564             : }
    9565             : 
    9566             : /****************************************************************************
    9567             :  fill_monitor_1
    9568             : ****************************************************************************/
    9569             : 
    9570          16 : static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
    9571             :                              struct spoolss_MonitorInfo1 *r,
    9572             :                              const char *monitor_name)
    9573             : {
    9574          16 :         r->monitor_name                      = talloc_strdup(mem_ctx, monitor_name);
    9575          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    9576             : 
    9577          16 :         return WERR_OK;
    9578             : }
    9579             : 
    9580             : /****************************************************************************
    9581             :  fill_monitor_2
    9582             : ****************************************************************************/
    9583             : 
    9584          16 : static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
    9585             :                              struct spoolss_MonitorInfo2 *r,
    9586             :                              const char *monitor_name,
    9587             :                              const char *environment,
    9588             :                              const char *dll_name)
    9589             : {
    9590          16 :         r->monitor_name                      = talloc_strdup(mem_ctx, monitor_name);
    9591          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    9592          16 :         r->environment                       = talloc_strdup(mem_ctx, environment);
    9593          16 :         W_ERROR_HAVE_NO_MEMORY(r->environment);
    9594          16 :         r->dll_name                  = talloc_strdup(mem_ctx, dll_name);
    9595          16 :         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
    9596             : 
    9597          16 :         return WERR_OK;
    9598             : }
    9599             : 
    9600             : /****************************************************************************
    9601             :  enumprintmonitors level 1.
    9602             : ****************************************************************************/
    9603             : 
    9604           8 : static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
    9605             :                                         union spoolss_MonitorInfo **info_p,
    9606             :                                         uint32_t *count)
    9607             : {
    9608           0 :         union spoolss_MonitorInfo *info;
    9609           8 :         WERROR result = WERR_OK;
    9610             : 
    9611           8 :         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
    9612           8 :         W_ERROR_HAVE_NO_MEMORY(info);
    9613             : 
    9614           8 :         *count = 2;
    9615             : 
    9616           8 :         result = fill_monitor_1(info, &info[0].info1,
    9617             :                                 SPL_LOCAL_PORT);
    9618           8 :         if (!W_ERROR_IS_OK(result)) {
    9619           0 :                 goto out;
    9620             :         }
    9621             : 
    9622           8 :         result = fill_monitor_1(info, &info[1].info1,
    9623             :                                 SPL_TCPIP_PORT);
    9624           8 :         if (!W_ERROR_IS_OK(result)) {
    9625           0 :                 goto out;
    9626             :         }
    9627             : 
    9628           8 : out:
    9629           8 :         if (!W_ERROR_IS_OK(result)) {
    9630           0 :                 TALLOC_FREE(info);
    9631           0 :                 *count = 0;
    9632           0 :                 return result;
    9633             :         }
    9634             : 
    9635           8 :         *info_p = info;
    9636             : 
    9637           8 :         return WERR_OK;
    9638             : }
    9639             : 
    9640             : /****************************************************************************
    9641             :  enumprintmonitors level 2.
    9642             : ****************************************************************************/
    9643             : 
    9644           8 : static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
    9645             :                                         union spoolss_MonitorInfo **info_p,
    9646             :                                         uint32_t *count)
    9647             : {
    9648           0 :         union spoolss_MonitorInfo *info;
    9649           8 :         WERROR result = WERR_OK;
    9650           0 :         const char *architecture;
    9651             : 
    9652           8 :         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
    9653           8 :         W_ERROR_HAVE_NO_MEMORY(info);
    9654             : 
    9655           8 :         *count = 2;
    9656             : 
    9657           8 :         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    9658             :                                             "spoolss",
    9659             :                                             "architecture",
    9660             :                                             GLOBAL_SPOOLSS_ARCHITECTURE);
    9661             : 
    9662           8 :         result = fill_monitor_2(info, &info[0].info2,
    9663             :                                 SPL_LOCAL_PORT,
    9664             :                                 architecture,
    9665             :                                 "localmon.dll");
    9666           8 :         if (!W_ERROR_IS_OK(result)) {
    9667           0 :                 goto out;
    9668             :         }
    9669             : 
    9670           8 :         result = fill_monitor_2(info, &info[1].info2,
    9671             :                                 SPL_TCPIP_PORT,
    9672             :                                 architecture,
    9673             :                                 "tcpmon.dll");
    9674           8 :         if (!W_ERROR_IS_OK(result)) {
    9675           0 :                 goto out;
    9676             :         }
    9677             : 
    9678           8 : out:
    9679           8 :         if (!W_ERROR_IS_OK(result)) {
    9680           0 :                 TALLOC_FREE(info);
    9681           0 :                 *count = 0;
    9682           0 :                 return result;
    9683             :         }
    9684             : 
    9685           8 :         *info_p = info;
    9686             : 
    9687           8 :         return WERR_OK;
    9688             : }
    9689             : 
    9690             : /****************************************************************
    9691             :  _spoolss_EnumMonitors
    9692             : ****************************************************************/
    9693             : 
    9694          16 : WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
    9695             :                              struct spoolss_EnumMonitors *r)
    9696             : {
    9697           0 :         WERROR result;
    9698             : 
    9699             :         /* that's an [in out] buffer */
    9700             : 
    9701          16 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9702           0 :                 return WERR_INVALID_PARAMETER;
    9703             :         }
    9704             : 
    9705          16 :         DEBUG(5,("_spoolss_EnumMonitors\n"));
    9706             : 
    9707             :         /*
    9708             :          * Enumerate the print monitors ...
    9709             :          *
    9710             :          * Just reply with "Local Port", to keep NT happy
    9711             :          * and I can use my nice printer checker.
    9712             :          */
    9713             : 
    9714          16 :         *r->out.count = 0;
    9715          16 :         *r->out.needed = 0;
    9716          16 :         *r->out.info = NULL;
    9717             : 
    9718          16 :         switch (r->in.level) {
    9719           8 :         case 1:
    9720           8 :                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
    9721             :                                                    r->out.count);
    9722           8 :                 break;
    9723           8 :         case 2:
    9724           8 :                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
    9725             :                                                    r->out.count);
    9726           8 :                 break;
    9727           0 :         default:
    9728           0 :                 return WERR_INVALID_LEVEL;
    9729             :         }
    9730             : 
    9731          16 :         if (!W_ERROR_IS_OK(result)) {
    9732           0 :                 return result;
    9733             :         }
    9734             : 
    9735          16 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9736             :                                                      spoolss_EnumMonitors,
    9737             :                                                      *r->out.info, r->in.level,
    9738             :                                                      *r->out.count);
    9739          16 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9740          16 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9741             : 
    9742          16 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9743             : }
    9744             : 
    9745             : /****************************************************************************
    9746             : ****************************************************************************/
    9747             : 
    9748         128 : static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
    9749             :                              const print_queue_struct *queue,
    9750             :                              int count, int snum,
    9751             :                              struct spoolss_PrinterInfo2 *pinfo2,
    9752             :                              uint32_t jobid,
    9753             :                              int sysjob,
    9754             :                              struct spoolss_JobInfo1 *r)
    9755             : {
    9756         128 :         int i = 0;
    9757         128 :         bool found = false;
    9758             : 
    9759         576 :         for (i=0; i<count; i++) {
    9760         576 :                 if (queue[i].sysjob == sysjob) {
    9761         128 :                         found = true;
    9762         128 :                         break;
    9763             :                 }
    9764             :         }
    9765             : 
    9766         128 :         if (found == false) {
    9767             :                 /* NT treats not found as bad param... yet another bad choice */
    9768           0 :                 return WERR_INVALID_PARAMETER;
    9769             :         }
    9770             : 
    9771         128 :         return fill_job_info1(mem_ctx,
    9772             :                               r,
    9773         128 :                               &queue[i],
    9774             :                               jobid,
    9775             :                               i,
    9776             :                               snum,
    9777             :                               pinfo2);
    9778             : }
    9779             : 
    9780             : /****************************************************************************
    9781             : ****************************************************************************/
    9782             : 
    9783           0 : static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
    9784             :                              const print_queue_struct *queue,
    9785             :                              int count, int snum,
    9786             :                              struct spoolss_PrinterInfo2 *pinfo2,
    9787             :                              uint32_t jobid,
    9788             :                              int sysjob,
    9789             :                              struct spoolss_JobInfo2 *r)
    9790             : {
    9791           0 :         int i = 0;
    9792           0 :         bool found = false;
    9793           0 :         struct spoolss_DeviceMode *devmode;
    9794           0 :         WERROR result;
    9795             : 
    9796           0 :         for (i=0; i<count; i++) {
    9797           0 :                 if (queue[i].sysjob == sysjob) {
    9798           0 :                         found = true;
    9799           0 :                         break;
    9800             :                 }
    9801             :         }
    9802             : 
    9803           0 :         if (found == false) {
    9804             :                 /* NT treats not found as bad param... yet another bad
    9805             :                    choice */
    9806           0 :                 return WERR_INVALID_PARAMETER;
    9807             :         }
    9808             : 
    9809             :         /*
    9810             :          * if the print job does not have a DEVMODE associated with it,
    9811             :          * just use the one for the printer. A NULL devicemode is not
    9812             :          *  a failure condition
    9813             :          */
    9814             : 
    9815           0 :         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
    9816           0 :         if (!devmode) {
    9817           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    9818             :                                                 pinfo2->printername,
    9819             :                                                 &devmode);
    9820           0 :                 if (!W_ERROR_IS_OK(result)) {
    9821           0 :                         DEBUG(3, ("Can't proceed w/o a devmode!\n"));
    9822           0 :                         return result;
    9823             :                 }
    9824             :         }
    9825             : 
    9826           0 :         return fill_job_info2(mem_ctx,
    9827             :                               r,
    9828           0 :                               &queue[i],
    9829             :                               jobid,
    9830             :                               i,
    9831             :                               snum,
    9832             :                               pinfo2,
    9833             :                               devmode);
    9834             : }
    9835             : 
    9836             : /****************************************************************
    9837             :  _spoolss_GetJob
    9838             : ****************************************************************/
    9839             : 
    9840        2048 : WERROR _spoolss_GetJob(struct pipes_struct *p,
    9841             :                        struct spoolss_GetJob *r)
    9842             : {
    9843        2048 :         WERROR result = WERR_OK;
    9844        2048 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    9845           0 :         const char *svc_name;
    9846           0 :         int sysjob;
    9847           0 :         int snum;
    9848           0 :         int count;
    9849           0 :         struct tdb_print_db *pdb;
    9850        2048 :         print_queue_struct      *queue = NULL;
    9851           0 :         print_status_struct prt_status;
    9852             : 
    9853             :         /* that's an [in out] buffer */
    9854             : 
    9855        2048 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9856           0 :                 result = WERR_INVALID_PARAMETER;
    9857           0 :                 goto err_jinfo_free;
    9858             :         }
    9859             : 
    9860        2048 :         DEBUG(5,("_spoolss_GetJob\n"));
    9861             : 
    9862        2048 :         *r->out.needed = 0;
    9863             : 
    9864        2048 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9865           0 :                 result = WERR_INVALID_HANDLE;
    9866           0 :                 goto err_jinfo_free;
    9867             :         }
    9868             : 
    9869        2048 :         svc_name = lp_const_servicename(snum);
    9870        2048 :         if (svc_name == NULL) {
    9871           0 :                 result = WERR_INVALID_PARAMETER;
    9872           0 :                 goto err_jinfo_free;
    9873             :         }
    9874             : 
    9875        2048 :         result = winreg_get_printer_internal(p->mem_ctx,
    9876             :                                     get_session_info_system(),
    9877             :                                     p->msg_ctx,
    9878             :                                     svc_name,
    9879             :                                     &pinfo2);
    9880        2048 :         if (!W_ERROR_IS_OK(result)) {
    9881           0 :                 goto err_jinfo_free;
    9882             :         }
    9883             : 
    9884        2048 :         pdb = get_print_db_byname(svc_name);
    9885        2048 :         if (pdb == NULL) {
    9886           0 :                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
    9887           0 :                 result = WERR_INVALID_PARAMETER;
    9888           0 :                 goto err_pinfo_free;
    9889             :         }
    9890             : 
    9891        2048 :         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
    9892        2048 :         release_print_db(pdb);
    9893        2048 :         if (sysjob == -1) {
    9894        1920 :                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
    9895        1920 :                 result = WERR_INVALID_PARAMETER;
    9896        1920 :                 goto err_pinfo_free;
    9897             :         }
    9898             : 
    9899         128 :         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
    9900             : 
    9901         128 :         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
    9902             :                      count, prt_status.status, prt_status.message));
    9903             : 
    9904         128 :         switch (r->in.level) {
    9905         128 :         case 1:
    9906         128 :                 result = getjob_level_1(p->mem_ctx,
    9907             :                                         queue, count, snum, pinfo2,
    9908             :                                         r->in.job_id, sysjob,
    9909         128 :                                         &r->out.info->info1);
    9910         128 :                 break;
    9911           0 :         case 2:
    9912           0 :                 result = getjob_level_2(p->mem_ctx,
    9913             :                                         queue, count, snum, pinfo2,
    9914             :                                         r->in.job_id, sysjob,
    9915           0 :                                         &r->out.info->info2);
    9916           0 :                 break;
    9917           0 :         default:
    9918           0 :                 result = WERR_INVALID_LEVEL;
    9919           0 :                 break;
    9920             :         }
    9921             : 
    9922         128 :         SAFE_FREE(queue);
    9923         128 :         TALLOC_FREE(pinfo2);
    9924             : 
    9925         128 :         if (!W_ERROR_IS_OK(result)) {
    9926           0 :                 goto err_jinfo_free;
    9927             :         }
    9928             : 
    9929         128 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
    9930             :                                                                                    r->in.level);
    9931         128 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    9932             : 
    9933         128 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9934             : 
    9935        1920 : err_pinfo_free:
    9936        1920 :         TALLOC_FREE(pinfo2);
    9937           0 : err_jinfo_free:
    9938        1920 :         TALLOC_FREE(r->out.info);
    9939        1920 :         return result;
    9940             : }
    9941             : 
    9942             : /****************************************************************
    9943             :  _spoolss_GetPrinterDataEx
    9944             : ****************************************************************/
    9945             : 
    9946        3180 : WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
    9947             :                                  struct spoolss_GetPrinterDataEx *r)
    9948             : {
    9949             : 
    9950        3180 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9951           0 :         const char *printer;
    9952        3180 :         int                     snum = 0;
    9953        3180 :         WERROR result = WERR_OK;
    9954           0 :         DATA_BLOB blob;
    9955        3180 :         enum winreg_Type val_type = REG_NONE;
    9956        3180 :         uint8_t *val_data = NULL;
    9957        3180 :         uint32_t val_size = 0;
    9958           0 :         struct dcerpc_binding_handle *b;
    9959           0 :         TALLOC_CTX *tmp_ctx;
    9960             : 
    9961        3180 :         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
    9962             : 
    9963        3180 :         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
    9964             :                 r->in.key_name, r->in.value_name));
    9965             : 
    9966             :         /* in case of problem, return some default values */
    9967             : 
    9968        3180 :         *r->out.needed       = 0;
    9969        3180 :         *r->out.type = REG_NONE;
    9970             : 
    9971        3180 :         tmp_ctx = talloc_new(p->mem_ctx);
    9972        3180 :         if (!tmp_ctx) {
    9973           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9974             :         }
    9975             : 
    9976        3180 :         if (!Printer) {
    9977           0 :                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
    9978             :                         OUR_HANDLE(r->in.handle)));
    9979           0 :                 result = WERR_INVALID_HANDLE;
    9980           0 :                 goto done;
    9981             :         }
    9982             : 
    9983             :         /* Is the handle to a printer or to the server? */
    9984             : 
    9985        3180 :         if (Printer->printer_type == SPLHND_SERVER) {
    9986             : 
    9987           0 :                 union spoolss_PrinterData data;
    9988             : 
    9989         404 :                 result = getprinterdata_printer_server(tmp_ctx,
    9990             :                                                        r->in.value_name,
    9991             :                                                        r->out.type,
    9992             :                                                        &data);
    9993         404 :                 if (!W_ERROR_IS_OK(result)) {
    9994           4 :                         goto done;
    9995             :                 }
    9996             : 
    9997         400 :                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
    9998         400 :                                                   *r->out.type, &data);
    9999         400 :                 if (!W_ERROR_IS_OK(result)) {
   10000           0 :                         goto done;
   10001             :                 }
   10002             : 
   10003         400 :                 *r->out.needed = blob.length;
   10004             : 
   10005         400 :                 if (r->in.offered >= *r->out.needed) {
   10006         204 :                         memcpy(r->out.data, blob.data, blob.length);
   10007             :                 }
   10008             : 
   10009         400 :                 result = WERR_OK;
   10010         400 :                 goto done;
   10011             :         }
   10012             : 
   10013             :         /* check to see if the keyname is valid */
   10014        2776 :         if (!strlen(r->in.key_name)) {
   10015           0 :                 result = WERR_INVALID_PARAMETER;
   10016           0 :                 goto done;
   10017             :         }
   10018             : 
   10019        2776 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10020           0 :                 result = WERR_INVALID_HANDLE;
   10021           0 :                 goto done;
   10022             :         }
   10023        2776 :         printer = lp_const_servicename(snum);
   10024             : 
   10025        2776 :         result = winreg_printer_binding_handle(tmp_ctx,
   10026             :                                                get_session_info_system(),
   10027             :                                                p->msg_ctx,
   10028             :                                                &b);
   10029        2776 :         if (!W_ERROR_IS_OK(result)) {
   10030           0 :                 goto done;
   10031             :         }
   10032             : 
   10033             :         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
   10034        3076 :         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
   10035         300 :             strequal(r->in.value_name, "ChangeId")) {
   10036         128 :                 *r->out.type = REG_DWORD;
   10037         128 :                 *r->out.needed = 4;
   10038         128 :                 if (r->in.offered >= *r->out.needed) {
   10039          64 :                         uint32_t changeid = 0;
   10040             : 
   10041          64 :                         result = winreg_printer_get_changeid(tmp_ctx, b,
   10042             :                                                              printer,
   10043             :                                                              &changeid);
   10044          64 :                         if (!W_ERROR_IS_OK(result)) {
   10045           0 :                                 goto done;
   10046             :                         }
   10047             : 
   10048          64 :                         SIVAL(r->out.data, 0, changeid);
   10049          64 :                         result = WERR_OK;
   10050             :                 }
   10051         128 :                 goto done;
   10052             :         }
   10053             : 
   10054        2648 :         result = winreg_get_printer_dataex(tmp_ctx, b,
   10055             :                                            printer,
   10056             :                                            r->in.key_name,
   10057             :                                            r->in.value_name,
   10058             :                                            &val_type,
   10059             :                                            &val_data,
   10060             :                                            &val_size);
   10061        2648 :         if (!W_ERROR_IS_OK(result)) {
   10062           4 :                 goto done;
   10063             :         }
   10064             : 
   10065        2644 :         *r->out.needed = val_size;
   10066        2644 :         *r->out.type = val_type;
   10067             : 
   10068        2644 :         if (r->in.offered >= *r->out.needed) {
   10069        1340 :                 memcpy(r->out.data, val_data, val_size);
   10070             :         }
   10071             : 
   10072        1304 : done:
   10073             :         /* NOTE: do not replace type when returning WERR_MORE_DATA */
   10074             : 
   10075        3180 :         if (W_ERROR_IS_OK(result)) {
   10076        3172 :                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
   10077             :         }
   10078             : 
   10079        3180 :         talloc_free(tmp_ctx);
   10080        3180 :         return result;
   10081             : }
   10082             : 
   10083             : /****************************************************************
   10084             :  _spoolss_SetPrinterDataEx
   10085             : ****************************************************************/
   10086             : 
   10087        1368 : WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
   10088             :                                  struct spoolss_SetPrinterDataEx *r)
   10089             : {
   10090           0 :         const struct loadparm_substitution *lp_sub =
   10091        1368 :                 loadparm_s3_global_substitution();
   10092        1368 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
   10093        1368 :         int                     snum = 0;
   10094        1368 :         WERROR                  result = WERR_OK;
   10095        1368 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10096           0 :         char                    *oid_string;
   10097           0 :         struct dcerpc_binding_handle *b;
   10098           0 :         TALLOC_CTX *tmp_ctx;
   10099             : 
   10100        1368 :         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
   10101             : 
   10102             :         /* From MSDN documentation of SetPrinterDataEx: pass request to
   10103             :            SetPrinterData if key is "PrinterDriverData" */
   10104             : 
   10105        1368 :         if (!Printer) {
   10106           0 :                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
   10107             :                         OUR_HANDLE(r->in.handle)));
   10108           0 :                 return WERR_INVALID_HANDLE;
   10109             :         }
   10110             : 
   10111        1368 :         if (Printer->printer_type == SPLHND_SERVER) {
   10112           0 :                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
   10113             :                         "Not implemented for server handles yet\n"));
   10114           0 :                 return WERR_INVALID_PARAMETER;
   10115             :         }
   10116             : 
   10117        1368 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10118           0 :                 return WERR_INVALID_HANDLE;
   10119             :         }
   10120             : 
   10121             :         /*
   10122             :          * Access check : NT returns "access denied" if you make a
   10123             :          * SetPrinterData call without the necessary privilege.
   10124             :          * we were originally returning OK if nothing changed
   10125             :          * which made Win2k issue **a lot** of SetPrinterData
   10126             :          * when connecting to a printer  --jerry
   10127             :          */
   10128             : 
   10129        1368 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10130           0 :                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
   10131             :                         "change denied by handle access permissions\n"));
   10132           0 :                 return WERR_ACCESS_DENIED;
   10133             :         }
   10134             : 
   10135        1368 :         tmp_ctx = talloc_new(p->mem_ctx);
   10136        1368 :         if (!tmp_ctx) {
   10137           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10138             :         }
   10139             : 
   10140        1368 :         result = winreg_printer_binding_handle(tmp_ctx,
   10141             :                                                get_session_info_system(),
   10142             :                                                p->msg_ctx,
   10143             :                                                &b);
   10144        1368 :         if (!W_ERROR_IS_OK(result)) {
   10145           0 :                 goto done;
   10146             :         }
   10147             : 
   10148        1368 :         result = winreg_get_printer(tmp_ctx, b,
   10149        1368 :                                     lp_servicename(talloc_tos(), lp_sub, snum),
   10150             :                                     &pinfo2);
   10151        1368 :         if (!W_ERROR_IS_OK(result)) {
   10152           0 :                 goto done;
   10153             :         }
   10154             : 
   10155             :         /* check for OID in valuename */
   10156             : 
   10157        1368 :         oid_string = strchr(r->in.value_name, ',');
   10158        1368 :         if (oid_string) {
   10159           0 :                 *oid_string = '\0';
   10160           0 :                 oid_string++;
   10161             :         }
   10162             : 
   10163             :         /* save the registry data */
   10164             : 
   10165        1368 :         result = winreg_set_printer_dataex(tmp_ctx, b,
   10166        1368 :                                            pinfo2->sharename,
   10167             :                                            r->in.key_name,
   10168             :                                            r->in.value_name,
   10169             :                                            r->in.type,
   10170             :                                            r->in.data,
   10171             :                                            r->in.offered);
   10172             : 
   10173        1368 :         if (W_ERROR_IS_OK(result)) {
   10174             :                 /* save the OID if one was specified */
   10175        1368 :                 if (oid_string) {
   10176           0 :                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
   10177             :                                 r->in.key_name, SPOOL_OID_KEY);
   10178           0 :                         if (!str) {
   10179           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
   10180           0 :                                 goto done;
   10181             :                         }
   10182             : 
   10183             :                         /*
   10184             :                          * I'm not checking the status here on purpose.  Don't know
   10185             :                          * if this is right, but I'm returning the status from the
   10186             :                          * previous set_printer_dataex() call.  I have no idea if
   10187             :                          * this is right.    --jerry
   10188             :                          */
   10189           0 :                         winreg_set_printer_dataex(tmp_ctx, b,
   10190           0 :                                                   pinfo2->sharename,
   10191             :                                                   str,
   10192             :                                                   r->in.value_name,
   10193             :                                                   REG_SZ,
   10194             :                                                   (uint8_t *) oid_string,
   10195           0 :                                                   strlen(oid_string) + 1);
   10196             :                 }
   10197             : 
   10198        1368 :                 result = winreg_printer_update_changeid(tmp_ctx, b,
   10199             :                                                         lp_const_servicename(snum));
   10200             : 
   10201             :         }
   10202             : 
   10203           0 : done:
   10204        1368 :         talloc_free(tmp_ctx);
   10205        1368 :         return result;
   10206             : }
   10207             : 
   10208             : /****************************************************************
   10209             :  _spoolss_DeletePrinterDataEx
   10210             : ****************************************************************/
   10211             : 
   10212        1368 : WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
   10213             :                                     struct spoolss_DeletePrinterDataEx *r)
   10214             : {
   10215           0 :         const char *printer;
   10216        1368 :         int             snum=0;
   10217        1368 :         WERROR          status = WERR_OK;
   10218        1368 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10219             : 
   10220        1368 :         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
   10221             : 
   10222        1368 :         if (!Printer) {
   10223           0 :                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
   10224             :                         "Invalid handle (%s:%u:%u).\n",
   10225             :                         OUR_HANDLE(r->in.handle)));
   10226           0 :                 return WERR_INVALID_HANDLE;
   10227             :         }
   10228             : 
   10229        1368 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10230           0 :                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
   10231             :                         "printer properties change denied by handle\n"));
   10232           0 :                 return WERR_ACCESS_DENIED;
   10233             :         }
   10234             : 
   10235        1368 :         if (!r->in.value_name || !r->in.key_name) {
   10236           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10237             :         }
   10238             : 
   10239        1368 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10240           0 :                 return WERR_INVALID_HANDLE;
   10241             :         }
   10242        1368 :         printer = lp_const_servicename(snum);
   10243             : 
   10244        1368 :         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
   10245             :                                               get_session_info_system(),
   10246             :                                               p->msg_ctx,
   10247             :                                               printer,
   10248             :                                               r->in.key_name,
   10249             :                                               r->in.value_name);
   10250        1368 :         if (W_ERROR_IS_OK(status)) {
   10251        1368 :                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
   10252             :                                                         get_session_info_system(),
   10253             :                                                         p->msg_ctx,
   10254             :                                                         printer);
   10255             :         }
   10256             : 
   10257        1368 :         return status;
   10258             : }
   10259             : 
   10260             : /****************************************************************
   10261             :  _spoolss_EnumPrinterKey
   10262             : ****************************************************************/
   10263             : 
   10264        3384 : WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
   10265             :                                struct spoolss_EnumPrinterKey *r)
   10266             : {
   10267           0 :         uint32_t        num_keys;
   10268        3384 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10269        3384 :         int             snum = 0;
   10270        3384 :         WERROR          result = WERR_FILE_NOT_FOUND;
   10271        3384 :         const char **array = NULL;
   10272           0 :         DATA_BLOB blob;
   10273             : 
   10274        3384 :         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
   10275             : 
   10276        3384 :         if (!Printer) {
   10277           0 :                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
   10278             :                         OUR_HANDLE(r->in.handle)));
   10279           0 :                 return WERR_INVALID_HANDLE;
   10280             :         }
   10281             : 
   10282        3384 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10283           0 :                 return WERR_INVALID_HANDLE;
   10284             :         }
   10285             : 
   10286        3384 :         result = winreg_enum_printer_key_internal(p->mem_ctx,
   10287             :                                          get_session_info_system(),
   10288             :                                          p->msg_ctx,
   10289             :                                          lp_const_servicename(snum),
   10290             :                                          r->in.key_name,
   10291             :                                          &num_keys,
   10292             :                                          &array);
   10293        3384 :         if (!W_ERROR_IS_OK(result)) {
   10294           0 :                 goto done;
   10295             :         }
   10296             : 
   10297        3384 :         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
   10298           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
   10299           0 :                 goto done;
   10300             :         }
   10301             : 
   10302        3384 :         *r->out._ndr_size = r->in.offered / 2;
   10303        3384 :         *r->out.needed = blob.length;
   10304             : 
   10305        3384 :         if (r->in.offered < *r->out.needed) {
   10306        1304 :                 result = WERR_MORE_DATA;
   10307             :         } else {
   10308        2080 :                 result = WERR_OK;
   10309        2080 :                 r->out.key_buffer->string_array = array;
   10310             :         }
   10311             : 
   10312        3384 :  done:
   10313        3384 :         if (!W_ERROR_IS_OK(result)) {
   10314        1304 :                 TALLOC_FREE(array);
   10315        1304 :                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
   10316           0 :                         *r->out.needed = 0;
   10317             :                 }
   10318             :         }
   10319             : 
   10320        3384 :         return result;
   10321             : }
   10322             : 
   10323             : /****************************************************************
   10324             :  _spoolss_DeletePrinterKey
   10325             : ****************************************************************/
   10326             : 
   10327         216 : WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
   10328             :                                  struct spoolss_DeletePrinterKey *r)
   10329             : {
   10330         216 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10331         216 :         int                     snum=0;
   10332           0 :         WERROR                  status;
   10333           0 :         const char *printer;
   10334           0 :         struct dcerpc_binding_handle *b;
   10335           0 :         TALLOC_CTX *tmp_ctx;
   10336             : 
   10337         216 :         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
   10338             : 
   10339         216 :         if (!Printer) {
   10340           0 :                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
   10341             :                         OUR_HANDLE(r->in.handle)));
   10342           0 :                 return WERR_INVALID_HANDLE;
   10343             :         }
   10344             : 
   10345             :         /* if keyname == NULL, return error */
   10346         216 :         if ( !r->in.key_name )
   10347           0 :                 return WERR_INVALID_PARAMETER;
   10348             : 
   10349         216 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10350           0 :                 return WERR_INVALID_HANDLE;
   10351             :         }
   10352             : 
   10353         216 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10354           0 :                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
   10355             :                         "printer properties change denied by handle\n"));
   10356           0 :                 return WERR_ACCESS_DENIED;
   10357             :         }
   10358             : 
   10359         216 :         printer = lp_const_servicename(snum);
   10360             : 
   10361         216 :         tmp_ctx = talloc_new(p->mem_ctx);
   10362         216 :         if (!tmp_ctx) {
   10363           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10364             :         }
   10365             : 
   10366         216 :         status = winreg_printer_binding_handle(tmp_ctx,
   10367             :                                                get_session_info_system(),
   10368             :                                                p->msg_ctx,
   10369             :                                                &b);
   10370         216 :         if (!W_ERROR_IS_OK(status)) {
   10371           0 :                 goto done;
   10372             :         }
   10373             : 
   10374             :         /* delete the key and all subkeys */
   10375         216 :         status = winreg_delete_printer_key(tmp_ctx, b,
   10376             :                                            printer,
   10377             :                                            r->in.key_name);
   10378         216 :         if (W_ERROR_IS_OK(status)) {
   10379         216 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
   10380             :                                                         printer);
   10381             :         }
   10382             : 
   10383           0 : done:
   10384         216 :         talloc_free(tmp_ctx);
   10385         216 :         return status;
   10386             : }
   10387             : 
   10388             : /****************************************************************
   10389             :  _spoolss_EnumPrinterDataEx
   10390             : ****************************************************************/
   10391             : 
   10392        2860 : WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
   10393             :                                   struct spoolss_EnumPrinterDataEx *r)
   10394             : {
   10395        2860 :         uint32_t        count = 0;
   10396        2860 :         struct spoolss_PrinterEnumValues *info = NULL;
   10397        2860 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10398           0 :         int             snum;
   10399           0 :         WERROR          result;
   10400             : 
   10401        2860 :         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
   10402             : 
   10403        2860 :         *r->out.count = 0;
   10404        2860 :         *r->out.needed = 0;
   10405        2860 :         *r->out.info = NULL;
   10406             : 
   10407        2860 :         if (!Printer) {
   10408           0 :                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
   10409             :                         OUR_HANDLE(r->in.handle)));
   10410           0 :                 return WERR_INVALID_HANDLE;
   10411             :         }
   10412             : 
   10413             :         /*
   10414             :          * first check for a keyname of NULL or "".  Win2k seems to send
   10415             :          * this a lot and we should send back WERR_INVALID_PARAMETER
   10416             :          * no need to spend time looking up the printer in this case.
   10417             :          * --jerry
   10418             :          */
   10419             : 
   10420        2860 :         if (!strlen(r->in.key_name)) {
   10421           4 :                 result = WERR_INVALID_PARAMETER;
   10422           4 :                 goto done;
   10423             :         }
   10424             : 
   10425        2856 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10426           0 :                 return WERR_INVALID_HANDLE;
   10427             :         }
   10428             : 
   10429             :         /* now look for a match on the key name */
   10430        2856 :         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
   10431             :                                             get_session_info_system(),
   10432             :                                             p->msg_ctx,
   10433             :                                             lp_const_servicename(snum),
   10434             :                                             r->in.key_name,
   10435             :                                             &count,
   10436             :                                             &info);
   10437        2856 :         if (!W_ERROR_IS_OK(result)) {
   10438           0 :                 goto done;
   10439             :         }
   10440             : 
   10441        2856 :         *r->out.count        = count;
   10442        2856 :         *r->out.info = info;
   10443             : 
   10444        2860 :  done:
   10445        2860 :         if (!W_ERROR_IS_OK(result)) {
   10446           4 :                 return result;
   10447             :         }
   10448             : 
   10449        2856 :         *r->out.needed       = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
   10450             :                                                spoolss_EnumPrinterDataEx,
   10451             :                                                *r->out.info,
   10452             :                                                *r->out.count);
   10453        2856 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
   10454        2856 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
   10455             : 
   10456        2856 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
   10457             : }
   10458             : 
   10459             : /****************************************************************************
   10460             : ****************************************************************************/
   10461             : 
   10462          40 : static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
   10463             :                                                  const char *servername,
   10464             :                                                  const char *environment,
   10465             :                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
   10466             : {
   10467           0 :         WERROR werr;
   10468          40 :         char *path = NULL;
   10469             : 
   10470          40 :         werr = compose_spoolss_server_path(mem_ctx,
   10471             :                                            servername,
   10472             :                                            environment,
   10473             :                                            SPOOLSS_PRTPROCS_PATH,
   10474             :                                            &path);
   10475          40 :         if (!W_ERROR_IS_OK(werr)) {
   10476           0 :                 return werr;
   10477             :         }
   10478             : 
   10479          40 :         DEBUG(4,("print processor directory: [%s]\n", path));
   10480             : 
   10481          40 :         r->directory_name = path;
   10482             : 
   10483          40 :         return WERR_OK;
   10484             : }
   10485             : 
   10486             : /****************************************************************
   10487             :  _spoolss_GetPrintProcessorDirectory
   10488             : ****************************************************************/
   10489             : 
   10490          40 : WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
   10491             :                                            struct spoolss_GetPrintProcessorDirectory *r)
   10492             : {
   10493           0 :         WERROR result;
   10494          40 :         char *prnproc_share = NULL;
   10495          40 :         bool prnproc_share_exists = false;
   10496           0 :         int snum;
   10497             : 
   10498             :         /* that's an [in out] buffer */
   10499             : 
   10500          40 :         if (!r->in.buffer && (r->in.offered != 0)) {
   10501           0 :                 result = WERR_INVALID_PARAMETER;
   10502           0 :                 goto err_info_free;
   10503             :         }
   10504             : 
   10505          40 :         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
   10506             :                 r->in.level));
   10507             : 
   10508          40 :         *r->out.needed = 0;
   10509             : 
   10510             :         /* r->in.level is ignored */
   10511             : 
   10512             :         /* We always should reply with a local print processor directory so that
   10513             :          * users are not forced to have a [prnproc$] share on the Samba spoolss
   10514             :          * server, if users decide to do so, lets announce it though - Guenther */
   10515             : 
   10516          40 :         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
   10517          40 :         if (!prnproc_share) {
   10518           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
   10519           0 :                 goto err_info_free;
   10520             :         }
   10521          40 :         if (snum != -1) {
   10522           0 :                 prnproc_share_exists = true;
   10523             :         }
   10524             : 
   10525          40 :         result = getprintprocessordirectory_level_1(p->mem_ctx,
   10526             :                                                     prnproc_share_exists ? r->in.server : NULL,
   10527             :                                                     r->in.environment,
   10528          40 :                                                     &r->out.info->info1);
   10529          40 :         if (!W_ERROR_IS_OK(result)) {
   10530           0 :                 goto err_info_free;
   10531             :         }
   10532             : 
   10533          40 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
   10534             :                                                                                    r->out.info, r->in.level);
   10535          40 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
   10536             : 
   10537          40 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
   10538             : 
   10539           0 : err_info_free:
   10540           0 :         TALLOC_FREE(r->out.info);
   10541           0 :         return result;
   10542             : }
   10543             : 
   10544             : /*******************************************************************
   10545             :  ********************************************************************/
   10546             : 
   10547           0 : static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
   10548             :                                const char *dllname)
   10549             : {
   10550           0 :         enum ndr_err_code ndr_err;
   10551           0 :         struct spoolss_MonitorUi ui;
   10552             : 
   10553           0 :         ui.dll_name = dllname;
   10554             : 
   10555           0 :         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
   10556             :                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
   10557           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10558           0 :                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
   10559             :         }
   10560           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10561             : }
   10562             : 
   10563             : /*******************************************************************
   10564             :  Streams the monitor UI DLL name in UNICODE
   10565             : *******************************************************************/
   10566             : 
   10567           0 : static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
   10568             :                                struct security_token *token, DATA_BLOB *in,
   10569             :                                DATA_BLOB *out, uint32_t *needed)
   10570             : {
   10571           0 :         const char *dllname = "tcpmonui.dll";
   10572             : 
   10573           0 :         *needed = (strlen(dllname)+1) * 2;
   10574             : 
   10575           0 :         if (out->length < *needed) {
   10576           0 :                 return WERR_INSUFFICIENT_BUFFER;
   10577             :         }
   10578             : 
   10579           0 :         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
   10580           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10581             :         }
   10582             : 
   10583           0 :         return WERR_OK;
   10584             : }
   10585             : 
   10586             : /*******************************************************************
   10587             :  ********************************************************************/
   10588             : 
   10589           0 : static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
   10590             :                              struct spoolss_PortData1 *port1,
   10591             :                              const DATA_BLOB *buf)
   10592             : {
   10593           0 :         enum ndr_err_code ndr_err;
   10594           0 :         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
   10595             :                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
   10596           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10597           0 :                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
   10598             :         }
   10599           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10600             : }
   10601             : 
   10602             : /*******************************************************************
   10603             :  ********************************************************************/
   10604             : 
   10605           0 : static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
   10606             :                              struct spoolss_PortData2 *port2,
   10607             :                              const DATA_BLOB *buf)
   10608             : {
   10609           0 :         enum ndr_err_code ndr_err;
   10610           0 :         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
   10611             :                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
   10612           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10613           0 :                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
   10614             :         }
   10615           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10616             : }
   10617             : 
   10618             : /*******************************************************************
   10619             :  Create a new TCP/IP port
   10620             : *******************************************************************/
   10621             : 
   10622           0 : static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
   10623             :                              struct security_token *token, DATA_BLOB *in,
   10624             :                              DATA_BLOB *out, uint32_t *needed)
   10625             : {
   10626           0 :         struct spoolss_PortData1 port1;
   10627           0 :         struct spoolss_PortData2 port2;
   10628           0 :         char *device_uri = NULL;
   10629           0 :         uint32_t version;
   10630             : 
   10631           0 :         const char *portname;
   10632           0 :         const char *hostaddress;
   10633           0 :         const char *queue;
   10634           0 :         uint32_t port_number;
   10635           0 :         uint32_t protocol;
   10636             : 
   10637             :         /* peek for spoolss_PortData version */
   10638             : 
   10639           0 :         if (!in || (in->length < (128 + 4))) {
   10640           0 :                 return WERR_GEN_FAILURE;
   10641             :         }
   10642             : 
   10643           0 :         version = IVAL(in->data, 128);
   10644             : 
   10645           0 :         switch (version) {
   10646           0 :                 case 1:
   10647           0 :                         ZERO_STRUCT(port1);
   10648             : 
   10649           0 :                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
   10650           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
   10651             :                         }
   10652             : 
   10653           0 :                         portname        = port1.portname;
   10654           0 :                         hostaddress     = port1.hostaddress;
   10655           0 :                         queue           = port1.queue;
   10656           0 :                         protocol        = port1.protocol;
   10657           0 :                         port_number     = port1.port_number;
   10658             : 
   10659           0 :                         break;
   10660           0 :                 case 2:
   10661           0 :                         ZERO_STRUCT(port2);
   10662             : 
   10663           0 :                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
   10664           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
   10665             :                         }
   10666             : 
   10667           0 :                         portname        = port2.portname;
   10668           0 :                         hostaddress     = port2.hostaddress;
   10669           0 :                         queue           = port2.queue;
   10670           0 :                         protocol        = port2.protocol;
   10671           0 :                         port_number     = port2.port_number;
   10672             : 
   10673           0 :                         break;
   10674           0 :                 default:
   10675           0 :                         DEBUG(1,("xcvtcp_addport: "
   10676             :                                 "unknown version of port_data: %d\n", version));
   10677           0 :                         return WERR_UNKNOWN_PORT;
   10678             :         }
   10679             : 
   10680             :         /* create the device URI and call the add_port_hook() */
   10681             : 
   10682           0 :         switch (protocol) {
   10683           0 :         case PROTOCOL_RAWTCP_TYPE:
   10684           0 :                 device_uri = talloc_asprintf(mem_ctx,
   10685             :                                 "socket://%s:%d/", hostaddress,
   10686             :                                 port_number);
   10687           0 :                 break;
   10688             : 
   10689           0 :         case PROTOCOL_LPR_TYPE:
   10690           0 :                 device_uri = talloc_asprintf(mem_ctx,
   10691             :                         "lpr://%s/%s", hostaddress, queue );
   10692           0 :                 break;
   10693             : 
   10694           0 :         default:
   10695           0 :                 return WERR_UNKNOWN_PORT;
   10696             :         }
   10697             : 
   10698           0 :         if (!device_uri) {
   10699           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10700             :         }
   10701             : 
   10702           0 :         return add_port_hook(mem_ctx, token, portname, device_uri);
   10703             : }
   10704             : 
   10705             : /*******************************************************************
   10706             : *******************************************************************/
   10707             : 
   10708             : struct xcv_api_table xcvtcp_cmds[] = {
   10709             :         { "MonitorUI",        xcvtcp_monitorui },
   10710             :         { "AddPort",  xcvtcp_addport},
   10711             :         { NULL,         NULL }
   10712             : };
   10713             : 
   10714           0 : static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
   10715             :                                      struct security_token *token, const char *command,
   10716             :                                      DATA_BLOB *inbuf,
   10717             :                                      DATA_BLOB *outbuf,
   10718             :                                      uint32_t *needed )
   10719             : {
   10720           0 :         int i;
   10721             : 
   10722           0 :         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
   10723             : 
   10724           0 :         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
   10725           0 :                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
   10726           0 :                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
   10727             :         }
   10728             : 
   10729           0 :         return WERR_INVALID_FUNCTION;
   10730             : }
   10731             : 
   10732             : /*******************************************************************
   10733             : *******************************************************************/
   10734             : #if 0   /* don't support management using the "Local Port" monitor */
   10735             : 
   10736             : static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
   10737             :                                  struct security_token *token, DATA_BLOB *in,
   10738             :                                  DATA_BLOB *out, uint32_t *needed)
   10739             : {
   10740             :         const char *dllname = "localui.dll";
   10741             : 
   10742             :         *needed = (strlen(dllname)+1) * 2;
   10743             : 
   10744             :         if (out->length < *needed) {
   10745             :                 return WERR_INSUFFICIENT_BUFFER;
   10746             :         }
   10747             : 
   10748             :         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
   10749             :                 return WERR_NOT_ENOUGH_MEMORY;
   10750             :         }
   10751             : 
   10752             :         return WERR_OK;
   10753             : }
   10754             : 
   10755             : /*******************************************************************
   10756             : *******************************************************************/
   10757             : 
   10758             : struct xcv_api_table xcvlocal_cmds[] = {
   10759             :         { "MonitorUI",        xcvlocal_monitorui },
   10760             :         { NULL,         NULL }
   10761             : };
   10762             : #else
   10763             : struct xcv_api_table xcvlocal_cmds[] = {
   10764             :         { NULL,         NULL }
   10765             : };
   10766             : #endif
   10767             : 
   10768             : 
   10769             : 
   10770             : /*******************************************************************
   10771             : *******************************************************************/
   10772             : 
   10773           0 : static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
   10774             :                                        struct security_token *token, const char *command,
   10775             :                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
   10776             :                                        uint32_t *needed)
   10777             : {
   10778           0 :         int i;
   10779             : 
   10780           0 :         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
   10781             : 
   10782           0 :         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
   10783           0 :                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
   10784           0 :                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
   10785             :         }
   10786           0 :         return WERR_INVALID_FUNCTION;
   10787             : }
   10788             : 
   10789             : /****************************************************************
   10790             :  _spoolss_XcvData
   10791             : ****************************************************************/
   10792             : 
   10793           0 : WERROR _spoolss_XcvData(struct pipes_struct *p,
   10794             :                         struct spoolss_XcvData *r)
   10795             : {
   10796           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
   10797           0 :         struct auth_session_info *session_info =
   10798           0 :                 dcesrv_call_session_info(dce_call);
   10799           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10800           0 :         DATA_BLOB out_data = data_blob_null;
   10801           0 :         WERROR werror;
   10802             : 
   10803           0 :         if (!Printer) {
   10804           0 :                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
   10805             :                         OUR_HANDLE(r->in.handle)));
   10806           0 :                 return WERR_INVALID_HANDLE;
   10807             :         }
   10808             : 
   10809             :         /* Has to be a handle to the TCP/IP port monitor */
   10810             : 
   10811           0 :         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
   10812           0 :                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
   10813           0 :                 return WERR_INVALID_HANDLE;
   10814             :         }
   10815             : 
   10816             :         /* requires administrative access to the server */
   10817             : 
   10818           0 :         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
   10819           0 :                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
   10820           0 :                 return WERR_ACCESS_DENIED;
   10821             :         }
   10822             : 
   10823             :         /* Allocate the outgoing buffer */
   10824             : 
   10825           0 :         if (r->in.out_data_size) {
   10826           0 :                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
   10827           0 :                 if (out_data.data == NULL) {
   10828           0 :                         return WERR_NOT_ENOUGH_MEMORY;
   10829             :                 }
   10830             :         }
   10831             : 
   10832           0 :         switch ( Printer->printer_type ) {
   10833           0 :         case SPLHND_PORTMON_TCP:
   10834           0 :                 werror = process_xcvtcp_command(p->mem_ctx,
   10835             :                                                 session_info->security_token,
   10836             :                                                 r->in.function_name,
   10837             :                                                 &r->in.in_data, &out_data,
   10838             :                                                 r->out.needed);
   10839           0 :                 break;
   10840           0 :         case SPLHND_PORTMON_LOCAL:
   10841           0 :                 werror = process_xcvlocal_command(p->mem_ctx,
   10842             :                                                   session_info->security_token,
   10843             :                                                   r->in.function_name,
   10844             :                                                   &r->in.in_data, &out_data,
   10845             :                                                   r->out.needed);
   10846           0 :                 break;
   10847           0 :         default:
   10848           0 :                 werror = WERR_INVALID_PRINT_MONITOR;
   10849             :         }
   10850             : 
   10851           0 :         if (!W_ERROR_IS_OK(werror)) {
   10852           0 :                 return werror;
   10853             :         }
   10854             : 
   10855           0 :         *r->out.status_code = 0;
   10856             : 
   10857           0 :         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
   10858           0 :                 memcpy(r->out.out_data, out_data.data,
   10859           0 :                         MIN(r->in.out_data_size, out_data.length));
   10860             :         }
   10861             : 
   10862           0 :         return WERR_OK;
   10863             : }
   10864             : 
   10865             : /****************************************************************
   10866             :  _spoolss_AddPrintProcessor
   10867             : ****************************************************************/
   10868             : 
   10869           4 : WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
   10870             :                                   struct spoolss_AddPrintProcessor *r)
   10871             : {
   10872             :         /* for now, just indicate success and ignore the add.  We'll
   10873             :            automatically set the winprint processor for printer
   10874             :            entries later.  Used to debug the LexMark Optra S 1855 PCL
   10875             :            driver --jerry */
   10876             : 
   10877           4 :         return WERR_OK;
   10878             : }
   10879             : 
   10880             : /****************************************************************
   10881             :  _spoolss_AddPort
   10882             : ****************************************************************/
   10883             : 
   10884           4 : WERROR _spoolss_AddPort(struct pipes_struct *p,
   10885             :                         struct spoolss_AddPort *r)
   10886             : {
   10887             :         /* do what w2k3 does */
   10888             : 
   10889           4 :         return WERR_NOT_SUPPORTED;
   10890             : }
   10891             : 
   10892             : /****************************************************************
   10893             :  _spoolss_GetPrinterDriver
   10894             : ****************************************************************/
   10895             : 
   10896           0 : WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
   10897             :                                  struct spoolss_GetPrinterDriver *r)
   10898             : {
   10899           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10900           0 :         return WERR_NOT_SUPPORTED;
   10901             : }
   10902             : 
   10903             : /****************************************************************
   10904             :  _spoolss_ReadPrinter
   10905             : ****************************************************************/
   10906             : 
   10907           0 : WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
   10908             :                             struct spoolss_ReadPrinter *r)
   10909             : {
   10910           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10911           0 :         return WERR_NOT_SUPPORTED;
   10912             : }
   10913             : 
   10914             : /****************************************************************
   10915             :  _spoolss_WaitForPrinterChange
   10916             : ****************************************************************/
   10917             : 
   10918           0 : WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
   10919             :                                      struct spoolss_WaitForPrinterChange *r)
   10920             : {
   10921           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10922           0 :         return WERR_NOT_SUPPORTED;
   10923             : }
   10924             : 
   10925             : /****************************************************************
   10926             :  _spoolss_ConfigurePort
   10927             : ****************************************************************/
   10928             : 
   10929           0 : WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
   10930             :                               struct spoolss_ConfigurePort *r)
   10931             : {
   10932           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10933           0 :         return WERR_NOT_SUPPORTED;
   10934             : }
   10935             : 
   10936             : /****************************************************************
   10937             :  _spoolss_DeletePort
   10938             : ****************************************************************/
   10939             : 
   10940           0 : WERROR _spoolss_DeletePort(struct pipes_struct *p,
   10941             :                            struct spoolss_DeletePort *r)
   10942             : {
   10943           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10944           0 :         return WERR_NOT_SUPPORTED;
   10945             : }
   10946             : 
   10947             : /****************************************************************
   10948             :  _spoolss_CreatePrinterIC
   10949             : ****************************************************************/
   10950             : 
   10951           0 : WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
   10952             :                                 struct spoolss_CreatePrinterIC *r)
   10953             : {
   10954           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10955           0 :         return WERR_NOT_SUPPORTED;
   10956             : }
   10957             : 
   10958             : /****************************************************************
   10959             :  _spoolss_PlayGDIScriptOnPrinterIC
   10960             : ****************************************************************/
   10961             : 
   10962           0 : WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
   10963             :                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
   10964             : {
   10965           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10966           0 :         return WERR_NOT_SUPPORTED;
   10967             : }
   10968             : 
   10969             : /****************************************************************
   10970             :  _spoolss_DeletePrinterIC
   10971             : ****************************************************************/
   10972             : 
   10973           0 : WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
   10974             :                                 struct spoolss_DeletePrinterIC *r)
   10975             : {
   10976           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10977           0 :         return WERR_NOT_SUPPORTED;
   10978             : }
   10979             : 
   10980             : /****************************************************************
   10981             :  _spoolss_AddPrinterConnection
   10982             : ****************************************************************/
   10983             : 
   10984           0 : WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
   10985             :                                      struct spoolss_AddPrinterConnection *r)
   10986             : {
   10987           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10988           0 :         return WERR_NOT_SUPPORTED;
   10989             : }
   10990             : 
   10991             : /****************************************************************
   10992             :  _spoolss_DeletePrinterConnection
   10993             : ****************************************************************/
   10994             : 
   10995           0 : WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
   10996             :                                         struct spoolss_DeletePrinterConnection *r)
   10997             : {
   10998           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10999           0 :         return WERR_NOT_SUPPORTED;
   11000             : }
   11001             : 
   11002             : /****************************************************************
   11003             :  _spoolss_PrinterMessageBox
   11004             : ****************************************************************/
   11005             : 
   11006           0 : WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
   11007             :                                   struct spoolss_PrinterMessageBox *r)
   11008             : {
   11009           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11010           0 :         return WERR_NOT_SUPPORTED;
   11011             : }
   11012             : 
   11013             : /****************************************************************
   11014             :  _spoolss_AddMonitor
   11015             : ****************************************************************/
   11016             : 
   11017           0 : WERROR _spoolss_AddMonitor(struct pipes_struct *p,
   11018             :                            struct spoolss_AddMonitor *r)
   11019             : {
   11020           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11021           0 :         return WERR_NOT_SUPPORTED;
   11022             : }
   11023             : 
   11024             : /****************************************************************
   11025             :  _spoolss_DeleteMonitor
   11026             : ****************************************************************/
   11027             : 
   11028           0 : WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
   11029             :                               struct spoolss_DeleteMonitor *r)
   11030             : {
   11031           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11032           0 :         return WERR_NOT_SUPPORTED;
   11033             : }
   11034             : 
   11035             : /****************************************************************
   11036             :  _spoolss_DeletePrintProcessor
   11037             : ****************************************************************/
   11038             : 
   11039           0 : WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
   11040             :                                      struct spoolss_DeletePrintProcessor *r)
   11041             : {
   11042           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11043           0 :         return WERR_NOT_SUPPORTED;
   11044             : }
   11045             : 
   11046             : /****************************************************************
   11047             :  _spoolss_AddPrintProvidor
   11048             : ****************************************************************/
   11049             : 
   11050           0 : WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
   11051             :                                  struct spoolss_AddPrintProvidor *r)
   11052             : {
   11053           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11054           0 :         return WERR_NOT_SUPPORTED;
   11055             : }
   11056             : 
   11057             : /****************************************************************
   11058             :  _spoolss_DeletePrintProvidor
   11059             : ****************************************************************/
   11060             : 
   11061           0 : WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
   11062             :                                     struct spoolss_DeletePrintProvidor *r)
   11063             : {
   11064           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11065           0 :         return WERR_NOT_SUPPORTED;
   11066             : }
   11067             : 
   11068             : /****************************************************************
   11069             :  _spoolss_FindFirstPrinterChangeNotification
   11070             : ****************************************************************/
   11071             : 
   11072           0 : WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
   11073             :                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
   11074             : {
   11075           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11076           0 :         return WERR_NOT_SUPPORTED;
   11077             : }
   11078             : 
   11079             : /****************************************************************
   11080             :  _spoolss_FindNextPrinterChangeNotification
   11081             : ****************************************************************/
   11082             : 
   11083           0 : WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
   11084             :                                                   struct spoolss_FindNextPrinterChangeNotification *r)
   11085             : {
   11086           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11087           0 :         return WERR_NOT_SUPPORTED;
   11088             : }
   11089             : 
   11090             : /****************************************************************
   11091             :  _spoolss_RouterFindFirstPrinterChangeNotificationOld
   11092             : ****************************************************************/
   11093             : 
   11094           0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
   11095             :                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
   11096             : {
   11097           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11098           0 :         return WERR_NOT_SUPPORTED;
   11099             : }
   11100             : 
   11101             : /****************************************************************
   11102             :  _spoolss_ReplyOpenPrinter
   11103             : ****************************************************************/
   11104             : 
   11105           0 : WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
   11106             :                                  struct spoolss_ReplyOpenPrinter *r)
   11107             : {
   11108           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11109           0 :         return WERR_NOT_SUPPORTED;
   11110             : }
   11111             : 
   11112             : /****************************************************************
   11113             :  _spoolss_RouterReplyPrinter
   11114             : ****************************************************************/
   11115             : 
   11116           0 : WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
   11117             :                                    struct spoolss_RouterReplyPrinter *r)
   11118             : {
   11119           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11120           0 :         return WERR_NOT_SUPPORTED;
   11121             : }
   11122             : 
   11123             : /****************************************************************
   11124             :  _spoolss_ReplyClosePrinter
   11125             : ****************************************************************/
   11126             : 
   11127           0 : WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
   11128             :                                   struct spoolss_ReplyClosePrinter *r)
   11129             : {
   11130           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11131           0 :         return WERR_NOT_SUPPORTED;
   11132             : }
   11133             : 
   11134             : /****************************************************************
   11135             :  _spoolss_AddPortEx
   11136             : ****************************************************************/
   11137             : 
   11138           0 : WERROR _spoolss_AddPortEx(struct pipes_struct *p,
   11139             :                           struct spoolss_AddPortEx *r)
   11140             : {
   11141           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11142           0 :         return WERR_NOT_SUPPORTED;
   11143             : }
   11144             : 
   11145             : /****************************************************************
   11146             :  _spoolss_RouterFindFirstPrinterChangeNotification
   11147             : ****************************************************************/
   11148             : 
   11149           0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
   11150             :                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
   11151             : {
   11152           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11153           0 :         return WERR_NOT_SUPPORTED;
   11154             : }
   11155             : 
   11156             : /****************************************************************
   11157             :  _spoolss_SpoolerInit
   11158             : ****************************************************************/
   11159             : 
   11160           0 : WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
   11161             :                             struct spoolss_SpoolerInit *r)
   11162             : {
   11163           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11164           0 :         return WERR_NOT_SUPPORTED;
   11165             : }
   11166             : 
   11167             : /****************************************************************
   11168             :  _spoolss_ResetPrinterEx
   11169             : ****************************************************************/
   11170             : 
   11171           0 : WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
   11172             :                                struct spoolss_ResetPrinterEx *r)
   11173             : {
   11174           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11175           0 :         return WERR_NOT_SUPPORTED;
   11176             : }
   11177             : 
   11178             : /****************************************************************
   11179             :  _spoolss_RouterReplyPrinterEx
   11180             : ****************************************************************/
   11181             : 
   11182           0 : WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
   11183             :                                      struct spoolss_RouterReplyPrinterEx *r)
   11184             : {
   11185           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11186           0 :         return WERR_NOT_SUPPORTED;
   11187             : }
   11188             : 
   11189             : /****************************************************************
   11190             :  _spoolss_44
   11191             : ****************************************************************/
   11192             : 
   11193           0 : WERROR _spoolss_44(struct pipes_struct *p,
   11194             :                    struct spoolss_44 *r)
   11195             : {
   11196           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11197           0 :         return WERR_NOT_SUPPORTED;
   11198             : }
   11199             : 
   11200             : /****************************************************************
   11201             :  _spoolss_SetPort
   11202             : ****************************************************************/
   11203             : 
   11204           0 : WERROR _spoolss_SetPort(struct pipes_struct *p,
   11205             :                         struct spoolss_SetPort *r)
   11206             : {
   11207           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11208           0 :         return WERR_NOT_SUPPORTED;
   11209             : }
   11210             : 
   11211             : /****************************************************************
   11212             :  _spoolss_4a
   11213             : ****************************************************************/
   11214             : 
   11215           0 : WERROR _spoolss_4a(struct pipes_struct *p,
   11216             :                    struct spoolss_4a *r)
   11217             : {
   11218           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11219           0 :         return WERR_NOT_SUPPORTED;
   11220             : }
   11221             : 
   11222             : /****************************************************************
   11223             :  _spoolss_4b
   11224             : ****************************************************************/
   11225             : 
   11226           0 : WERROR _spoolss_4b(struct pipes_struct *p,
   11227             :                    struct spoolss_4b *r)
   11228             : {
   11229           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11230           0 :         return WERR_NOT_SUPPORTED;
   11231             : }
   11232             : 
   11233             : /****************************************************************
   11234             :  _spoolss_4c
   11235             : ****************************************************************/
   11236             : 
   11237           0 : WERROR _spoolss_4c(struct pipes_struct *p,
   11238             :                    struct spoolss_4c *r)
   11239             : {
   11240           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11241           0 :         return WERR_NOT_SUPPORTED;
   11242             : }
   11243             : 
   11244             : /****************************************************************
   11245             :  _spoolss_53
   11246             : ****************************************************************/
   11247             : 
   11248           0 : WERROR _spoolss_53(struct pipes_struct *p,
   11249             :                    struct spoolss_53 *r)
   11250             : {
   11251           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11252           0 :         return WERR_NOT_SUPPORTED;
   11253             : }
   11254             : 
   11255             : /****************************************************************
   11256             :  _spoolss_AddPerMachineConnection
   11257             : ****************************************************************/
   11258             : 
   11259           4 : WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
   11260             :                                         struct spoolss_AddPerMachineConnection *r)
   11261             : {
   11262           4 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11263           4 :         return WERR_NOT_SUPPORTED;
   11264             : }
   11265             : 
   11266             : /****************************************************************
   11267             :  _spoolss_DeletePerMachineConnection
   11268             : ****************************************************************/
   11269             : 
   11270           0 : WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
   11271             :                                            struct spoolss_DeletePerMachineConnection *r)
   11272             : {
   11273           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11274           0 :         return WERR_NOT_SUPPORTED;
   11275             : }
   11276             : 
   11277             : /****************************************************************
   11278             :  _spoolss_EnumPerMachineConnections
   11279             : ****************************************************************/
   11280             : 
   11281           0 : WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
   11282             :                                           struct spoolss_EnumPerMachineConnections *r)
   11283             : {
   11284           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11285           0 :         return WERR_NOT_SUPPORTED;
   11286             : }
   11287             : 
   11288             : /****************************************************************
   11289             :  _spoolss_5a
   11290             : ****************************************************************/
   11291             : 
   11292           0 : WERROR _spoolss_5a(struct pipes_struct *p,
   11293             :                    struct spoolss_5a *r)
   11294             : {
   11295           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11296           0 :         return WERR_NOT_SUPPORTED;
   11297             : }
   11298             : 
   11299             : /****************************************************************
   11300             :  _spoolss_5b
   11301             : ****************************************************************/
   11302             : 
   11303           0 : WERROR _spoolss_5b(struct pipes_struct *p,
   11304             :                    struct spoolss_5b *r)
   11305             : {
   11306           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11307           0 :         return WERR_NOT_SUPPORTED;
   11308             : }
   11309             : 
   11310             : /****************************************************************
   11311             :  _spoolss_5c
   11312             : ****************************************************************/
   11313             : 
   11314           0 : WERROR _spoolss_5c(struct pipes_struct *p,
   11315             :                    struct spoolss_5c *r)
   11316             : {
   11317           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11318           0 :         return WERR_NOT_SUPPORTED;
   11319             : }
   11320             : 
   11321             : /****************************************************************
   11322             :  _spoolss_5d
   11323             : ****************************************************************/
   11324             : 
   11325           0 : WERROR _spoolss_5d(struct pipes_struct *p,
   11326             :                    struct spoolss_5d *r)
   11327             : {
   11328           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11329           0 :         return WERR_NOT_SUPPORTED;
   11330             : }
   11331             : 
   11332             : /****************************************************************
   11333             :  _spoolss_5e
   11334             : ****************************************************************/
   11335             : 
   11336           0 : WERROR _spoolss_5e(struct pipes_struct *p,
   11337             :                    struct spoolss_5e *r)
   11338             : {
   11339           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11340           0 :         return WERR_NOT_SUPPORTED;
   11341             : }
   11342             : 
   11343             : /****************************************************************
   11344             :  _spoolss_5f
   11345             : ****************************************************************/
   11346             : 
   11347           0 : WERROR _spoolss_5f(struct pipes_struct *p,
   11348             :                    struct spoolss_5f *r)
   11349             : {
   11350           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11351           0 :         return WERR_NOT_SUPPORTED;
   11352             : }
   11353             : 
   11354             : /****************************************************************
   11355             :  _spoolss_60
   11356             : ****************************************************************/
   11357             : 
   11358           0 : WERROR _spoolss_60(struct pipes_struct *p,
   11359             :                    struct spoolss_60 *r)
   11360             : {
   11361           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11362           0 :         return WERR_NOT_SUPPORTED;
   11363             : }
   11364             : 
   11365             : /****************************************************************
   11366             :  _spoolss_SendRecvBidiData
   11367             : ****************************************************************/
   11368             : 
   11369           0 : WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
   11370             :                                  struct spoolss_SendRecvBidiData *r)
   11371             : {
   11372           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11373           0 :         return WERR_NOT_SUPPORTED;
   11374             : }
   11375             : 
   11376             : /****************************************************************
   11377             :  _spoolss_62
   11378             : ****************************************************************/
   11379             : 
   11380           0 : WERROR _spoolss_62(struct pipes_struct *p,
   11381             :                    struct spoolss_62 *r)
   11382             : {
   11383           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11384           0 :         return WERR_NOT_SUPPORTED;
   11385             : }
   11386             : 
   11387             : /****************************************************************
   11388             :  _spoolss_63
   11389             : ****************************************************************/
   11390             : 
   11391           0 : WERROR _spoolss_63(struct pipes_struct *p,
   11392             :                    struct spoolss_63 *r)
   11393             : {
   11394           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11395           0 :         return WERR_NOT_SUPPORTED;
   11396             : }
   11397             : 
   11398             : /****************************************************************
   11399             :  _spoolss_64
   11400             : ****************************************************************/
   11401             : 
   11402           0 : WERROR _spoolss_64(struct pipes_struct *p,
   11403             :                    struct spoolss_64 *r)
   11404             : {
   11405           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11406           0 :         return WERR_NOT_SUPPORTED;
   11407             : }
   11408             : 
   11409             : /****************************************************************
   11410             :  _spoolss_65
   11411             : ****************************************************************/
   11412             : 
   11413           0 : WERROR _spoolss_65(struct pipes_struct *p,
   11414             :                    struct spoolss_65 *r)
   11415             : {
   11416           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11417           0 :         return WERR_NOT_SUPPORTED;
   11418             : }
   11419             : 
   11420             : /****************************************************************
   11421             :  _spoolss_GetCorePrinterDrivers
   11422             : ****************************************************************/
   11423             : 
   11424           8 : HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
   11425             :                                        struct spoolss_GetCorePrinterDrivers *r)
   11426             : {
   11427           8 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11428           8 :         return HRES_ERROR_NOT_SUPPORTED;
   11429             : }
   11430             : 
   11431             : /****************************************************************
   11432             :  _spoolss_67
   11433             : ****************************************************************/
   11434             : 
   11435           0 : WERROR _spoolss_67(struct pipes_struct *p,
   11436             :                    struct spoolss_67 *r)
   11437             : {
   11438           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11439           0 :         return WERR_NOT_SUPPORTED;
   11440             : }
   11441             : 
   11442             : /****************************************************************
   11443             :  _spoolss_GetPrinterDriverPackagePath
   11444             : ****************************************************************/
   11445             : 
   11446           4 : HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
   11447             :                                              struct spoolss_GetPrinterDriverPackagePath *r)
   11448             : {
   11449           4 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11450           4 :         return HRES_ERROR_NOT_SUPPORTED;
   11451             : }
   11452             : 
   11453             : /****************************************************************
   11454             :  _spoolss_69
   11455             : ****************************************************************/
   11456             : 
   11457           0 : WERROR _spoolss_69(struct pipes_struct *p,
   11458             :                    struct spoolss_69 *r)
   11459             : {
   11460           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11461           0 :         return WERR_NOT_SUPPORTED;
   11462             : }
   11463             : 
   11464             : /****************************************************************
   11465             :  _spoolss_6a
   11466             : ****************************************************************/
   11467             : 
   11468           0 : WERROR _spoolss_6a(struct pipes_struct *p,
   11469             :                    struct spoolss_6a *r)
   11470             : {
   11471           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11472           0 :         return WERR_NOT_SUPPORTED;
   11473             : }
   11474             : 
   11475             : /****************************************************************
   11476             :  _spoolss_6b
   11477             : ****************************************************************/
   11478             : 
   11479           0 : WERROR _spoolss_6b(struct pipes_struct *p,
   11480             :                    struct spoolss_6b *r)
   11481             : {
   11482           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11483           0 :         return WERR_NOT_SUPPORTED;
   11484             : }
   11485             : 
   11486             : /****************************************************************
   11487             :  _spoolss_6c
   11488             : ****************************************************************/
   11489             : 
   11490           0 : WERROR _spoolss_6c(struct pipes_struct *p,
   11491             :                    struct spoolss_6c *r)
   11492             : {
   11493           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11494           0 :         return WERR_NOT_SUPPORTED;
   11495             : }
   11496             : 
   11497             : /****************************************************************
   11498             :  _spoolss_6d
   11499             : ****************************************************************/
   11500             : 
   11501           0 : WERROR _spoolss_6d(struct pipes_struct *p,
   11502             :                    struct spoolss_6d *r)
   11503             : {
   11504           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11505           0 :         return WERR_NOT_SUPPORTED;
   11506             : }
   11507             : 
   11508             : /****************************************************************
   11509             :  _spoolss_GetJobNamedPropertyValue
   11510             : ****************************************************************/
   11511             : 
   11512           0 : WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
   11513             :                                          struct spoolss_GetJobNamedPropertyValue *r)
   11514             : {
   11515           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11516           0 :         return WERR_NOT_SUPPORTED;
   11517             : }
   11518             : 
   11519             : /****************************************************************
   11520             :  _spoolss_SetJobNamedProperty
   11521             : ****************************************************************/
   11522             : 
   11523           0 : WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
   11524             :                                     struct spoolss_SetJobNamedProperty *r)
   11525             : {
   11526           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11527           0 :         return WERR_NOT_SUPPORTED;
   11528             : }
   11529             : 
   11530             : /****************************************************************
   11531             :  _spoolss_DeleteJobNamedProperty
   11532             : ****************************************************************/
   11533             : 
   11534           0 : WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
   11535             :                                        struct spoolss_DeleteJobNamedProperty *r)
   11536             : {
   11537           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11538           0 :         return WERR_NOT_SUPPORTED;
   11539             : }
   11540             : 
   11541             : /****************************************************************
   11542             :  _spoolss_EnumJobNamedProperties
   11543             : ****************************************************************/
   11544             : 
   11545           0 : WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
   11546             :                                        struct spoolss_EnumJobNamedProperties *r)
   11547             : {
   11548           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11549           0 :         return WERR_NOT_SUPPORTED;
   11550             : }
   11551             : 
   11552             : /****************************************************************
   11553             :  _spoolss_72
   11554             : ****************************************************************/
   11555             : 
   11556           0 : WERROR _spoolss_72(struct pipes_struct *p,
   11557             :                    struct spoolss_72 *r)
   11558             : {
   11559           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11560           0 :         return WERR_NOT_SUPPORTED;
   11561             : }
   11562             : 
   11563             : /****************************************************************
   11564             :  _spoolss_73
   11565             : ****************************************************************/
   11566             : 
   11567           0 : WERROR _spoolss_73(struct pipes_struct *p,
   11568             :                    struct spoolss_73 *r)
   11569             : {
   11570           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11571           0 :         return WERR_NOT_SUPPORTED;
   11572             : }
   11573             : 
   11574             : /****************************************************************
   11575             :  _spoolss_RpcLogJobInfoForBranchOffice
   11576             : ****************************************************************/
   11577             : 
   11578           8 : WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
   11579             :                                           struct spoolss_LogJobInfoForBranchOffice *r)
   11580             : {
   11581           8 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11582           8 :         return WERR_NOT_SUPPORTED;
   11583             : }
   11584             : 
   11585             : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
   11586             :                 const struct dcesrv_endpoint_server *ep_server);
   11587             : 
   11588             : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
   11589             :                 const struct dcesrv_endpoint_server *ep_server);
   11590             : 
   11591             : #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
   11592             :         spoolss_init_server
   11593             : 
   11594             : #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
   11595             :         spoolss_shutdown_server
   11596             : 
   11597          28 : static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
   11598             :                 const struct dcesrv_endpoint_server *ep_server)
   11599             : {
   11600          28 :         struct messaging_context *msg_ctx = global_messaging_context();
   11601           0 :         bool ok;
   11602             : 
   11603             :         /*
   11604             :          * Migrate the printers first.
   11605             :          */
   11606          28 :         ok = nt_printing_tdb_migrate(msg_ctx);
   11607          28 :         if (!ok) {
   11608           0 :                 return NT_STATUS_UNSUCCESSFUL;
   11609             :         }
   11610             : 
   11611          28 :         return spoolss__op_init_server(dce_ctx, ep_server);
   11612             : }
   11613             : 
   11614          28 : static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
   11615             :                 const struct dcesrv_endpoint_server *ep_server)
   11616             : {
   11617          28 :         srv_spoolss_cleanup();
   11618             : 
   11619          28 :         return spoolss__op_shutdown_server(dce_ctx, ep_server);
   11620             : }
   11621             : 
   11622             : /* include the generated boilerplate */
   11623             : #include "librpc/gen_ndr/ndr_spoolss_scompat.c"

Generated by: LCOV version 1.14