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 98b443d9 Lines: 2245 4837 46.4 %
Date: 2024-05-31 13:13:24 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         386 : static int nt_printj_status(int v)
     167             : {
     168         386 :         switch (v) {
     169         386 :         case LPQ_QUEUED:
     170         386 :                 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         220 :         case LPQ_PAUSED:
     201         220 :                 return PRINTER_STATUS_PAUSED;
     202        1416 :         case LPQ_QUEUED:
     203             :         case LPQ_SPOOLING:
     204             :         case LPQ_PRINTING:
     205        1416 :                 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       52175 : static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
     317             :                                                         struct policy_handle *hnd)
     318             : {
     319       52175 :         struct printer_handle *find_printer = NULL;
     320           0 :         NTSTATUS status;
     321             : 
     322       52175 :         find_printer = find_policy_by_hnd(p,
     323             :                                           hnd,
     324             :                                           DCESRV_HANDLE_ANY,
     325             :                                           struct printer_handle,
     326           0 :                                           &status);
     327       52175 :         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       52175 :         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       24717 : static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
     469             :                              int *number, struct share_params **params)
     470             : {
     471       24717 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     472             : 
     473       24717 :         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       24717 :         switch (Printer->printer_type) {
     480       24717 :                 case SPLHND_PRINTER:
     481       24717 :                         DEBUG(4,("short name:%s\n", Printer->sharename));
     482       24717 :                         *number = print_queue_snum(Printer->sharename);
     483       24717 :                         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(NULL,
    2495             :                                         pp_cli,
    2496             :                                         lp_netbios_name(),
    2497             :                                         remote_machine,
    2498             :                                         &rm_addr,
    2499             :                                         0,
    2500             :                                         "IPC$",
    2501             :                                         "IPC",
    2502             :                                         anon_creds,
    2503             :                                         CLI_FULL_CONNECTION_IPC);
    2504           2 :         TALLOC_FREE(anon_creds);
    2505           2 :         if ( !NT_STATUS_IS_OK( ret ) ) {
    2506           0 :                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
    2507             :                         remote_machine ));
    2508           0 :                 return false;
    2509             :         }
    2510             : 
    2511           2 :         if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
    2512           0 :                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
    2513           0 :                 cli_shutdown(*pp_cli);
    2514           0 :                 return false;
    2515             :         }
    2516             : 
    2517             :         /*
    2518             :          * Ok - we have an anonymous connection to the IPC$ share.
    2519             :          * Now start the NT Domain stuff :-).
    2520             :          */
    2521             : 
    2522           2 :         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
    2523           2 :         if (!NT_STATUS_IS_OK(ret)) {
    2524           0 :                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
    2525             :                         remote_machine, nt_errstr(ret)));
    2526           0 :                 cli_shutdown(*pp_cli);
    2527           0 :                 return false;
    2528             :         }
    2529             : 
    2530           2 :         return true;
    2531             : }
    2532             : 
    2533             : /***************************************************************************
    2534             :  Connect to the client.
    2535             : ****************************************************************************/
    2536             : 
    2537           2 : static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
    2538             :                                         uint32_t localprinter,
    2539             :                                         enum winreg_Type type,
    2540             :                                         struct policy_handle *handle,
    2541             :                                         struct notify_back_channel **_chan,
    2542             :                                         struct sockaddr_storage *client_ss,
    2543             :                                         struct messaging_context *msg_ctx)
    2544             : {
    2545           0 :         WERROR result;
    2546           0 :         NTSTATUS status;
    2547           0 :         struct notify_back_channel *chan;
    2548             : 
    2549           2 :         for (chan = back_channels; chan; chan = chan->next) {
    2550           0 :                 if (memcmp(&chan->client_address, client_ss,
    2551             :                            sizeof(struct sockaddr_storage)) == 0) {
    2552           0 :                         break;
    2553             :                 }
    2554             :         }
    2555             : 
    2556             :         /*
    2557             :          * If it's the first connection, contact the client
    2558             :          * and connect to the IPC$ share anonymously
    2559             :          */
    2560           2 :         if (!chan) {
    2561           0 :                 fstring unix_printer;
    2562             : 
    2563             :                 /* the +2 is to strip the leading 2 backslashes */
    2564           2 :                 fstrcpy(unix_printer, printer + 2);
    2565             : 
    2566           2 :                 chan = talloc_zero(NULL, struct notify_back_channel);
    2567           2 :                 if (!chan) {
    2568           0 :                         return false;
    2569             :                 }
    2570           2 :                 chan->client_address = *client_ss;
    2571             : 
    2572           2 :                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
    2573           0 :                         TALLOC_FREE(chan);
    2574           0 :                         return false;
    2575             :                 }
    2576             : 
    2577           2 :                 DLIST_ADD(back_channels, chan);
    2578             : 
    2579           2 :                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
    2580             :                                    receive_notify2_message_list);
    2581             :         }
    2582             : 
    2583           2 :         if (chan->cli_pipe == NULL ||
    2584           2 :             chan->cli_pipe->binding_handle == NULL) {
    2585           0 :                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
    2586             :                         "NULL %s for printer %s\n",
    2587             :                         chan->cli_pipe == NULL ?
    2588             :                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
    2589             :                         printer));
    2590           0 :                 return false;
    2591             :         }
    2592             : 
    2593             :         /*
    2594             :          * Tell the specific printing tdb we want messages for this printer
    2595             :          * by registering our PID.
    2596             :          */
    2597             : 
    2598           2 :         if (!print_notify_register_pid(snum)) {
    2599           0 :                 DEBUG(0, ("Failed to register our pid for printer %s\n",
    2600             :                           printer));
    2601             :         }
    2602             : 
    2603           2 :         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
    2604             :                                                  talloc_tos(),
    2605             :                                                  printer,
    2606             :                                                  localprinter,
    2607             :                                                  type,
    2608             :                                                  0,
    2609             :                                                  NULL,
    2610             :                                                  handle,
    2611             :                                                  &result);
    2612           2 :         if (!NT_STATUS_IS_OK(status)) {
    2613           0 :                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
    2614           0 :                 result = ntstatus_to_werror(status);
    2615           2 :         } else if (!W_ERROR_IS_OK(result)) {
    2616           0 :                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
    2617             :         }
    2618             : 
    2619           2 :         chan->active_connections++;
    2620           2 :         *_chan = chan;
    2621             : 
    2622           2 :         return (W_ERROR_IS_OK(result));
    2623             : }
    2624             : 
    2625             : /****************************************************************
    2626             :  ****************************************************************/
    2627             : 
    2628           2 : static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
    2629             :                                                              const struct spoolss_NotifyOption *r)
    2630             : {
    2631           0 :         struct spoolss_NotifyOption *option;
    2632           0 :         uint32_t i,k;
    2633             : 
    2634           2 :         if (!r) {
    2635           0 :                 return NULL;
    2636             :         }
    2637             : 
    2638           2 :         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
    2639           2 :         if (!option) {
    2640           0 :                 return NULL;
    2641             :         }
    2642             : 
    2643           2 :         *option = *r;
    2644             : 
    2645           2 :         if (!option->count) {
    2646           0 :                 return option;
    2647             :         }
    2648             : 
    2649           2 :         option->types = talloc_zero_array(option,
    2650             :                 struct spoolss_NotifyOptionType, option->count);
    2651           2 :         if (!option->types) {
    2652           0 :                 talloc_free(option);
    2653           0 :                 return NULL;
    2654             :         }
    2655             : 
    2656           6 :         for (i=0; i < option->count; i++) {
    2657           4 :                 option->types[i] = r->types[i];
    2658             : 
    2659           4 :                 if (option->types[i].count) {
    2660           4 :                         option->types[i].fields = talloc_zero_array(option,
    2661             :                                 union spoolss_Field, option->types[i].count);
    2662           4 :                         if (!option->types[i].fields) {
    2663           0 :                                 talloc_free(option);
    2664           0 :                                 return NULL;
    2665             :                         }
    2666           8 :                         for (k=0; k<option->types[i].count; k++) {
    2667           4 :                                 option->types[i].fields[k] =
    2668           4 :                                         r->types[i].fields[k];
    2669             :                         }
    2670             :                 }
    2671             :         }
    2672             : 
    2673           2 :         return option;
    2674             : }
    2675             : 
    2676             : /****************************************************************
    2677             :  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
    2678             :  *
    2679             :  * before replying OK: status=0 a rpc call is made to the workstation
    2680             :  * asking ReplyOpenPrinter
    2681             :  *
    2682             :  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
    2683             :  * called from api_spoolss_rffpcnex
    2684             : ****************************************************************/
    2685             : 
    2686           2 : WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
    2687             :                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
    2688             : {
    2689           2 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2690           2 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    2691           0 :         const struct tsocket_address *remote_address =
    2692           2 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    2693           2 :         int snum = -1;
    2694           2 :         struct spoolss_NotifyOption *option = r->in.notify_options;
    2695           0 :         struct sockaddr_storage client_ss;
    2696           0 :         ssize_t client_len;
    2697             : 
    2698             :         /* store the notify value in the printer struct */
    2699             : 
    2700           2 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    2701             : 
    2702           2 :         if (!Printer) {
    2703           0 :                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2704             :                         "Invalid handle (%s:%u:%u).\n",
    2705             :                         OUR_HANDLE(r->in.handle)));
    2706           0 :                 return WERR_INVALID_HANDLE;
    2707             :         }
    2708             : 
    2709           2 :         Printer->notify.flags                = r->in.flags;
    2710           2 :         Printer->notify.options              = r->in.options;
    2711           2 :         Printer->notify.printerlocal = r->in.printer_local;
    2712           2 :         Printer->notify.msg_ctx              = p->msg_ctx;
    2713             : 
    2714           2 :         TALLOC_FREE(Printer->notify.option);
    2715           2 :         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
    2716             : 
    2717           2 :         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
    2718             : 
    2719             :         /* Connect to the client machine and send a ReplyOpenPrinter */
    2720             : 
    2721           2 :         if ( Printer->printer_type == SPLHND_SERVER)
    2722           2 :                 snum = -1;
    2723           0 :         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
    2724           0 :                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
    2725           0 :                 return WERR_INVALID_HANDLE;
    2726             : 
    2727           2 :         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2728             :                   "remote_address is %s\n",
    2729             :                   tsocket_address_string(remote_address, p->mem_ctx)));
    2730             : 
    2731           2 :         if (!lp_print_notify_backchannel(snum)) {
    2732           0 :                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2733             :                         "backchannel disabled\n"));
    2734           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
    2735             :         }
    2736             : 
    2737           2 :         client_len = tsocket_address_bsd_sockaddr(remote_address,
    2738             :                                                   (struct sockaddr *) &client_ss,
    2739             :                                                   sizeof(struct sockaddr_storage));
    2740           2 :         if (client_len < 0) {
    2741           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2742             :         }
    2743             : 
    2744           2 :         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
    2745             :                                         Printer->notify.printerlocal, REG_SZ,
    2746             :                                         &Printer->notify.cli_hnd,
    2747             :                                         &Printer->notify.cli_chan,
    2748             :                                         &client_ss, p->msg_ctx)) {
    2749           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
    2750             :         }
    2751             : 
    2752           2 :         return WERR_OK;
    2753             : }
    2754             : 
    2755             : /*******************************************************************
    2756             :  * fill a notify_info_data with the servername
    2757             :  ********************************************************************/
    2758             : 
    2759           0 : static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
    2760             :                                        int snum,
    2761             :                                        struct spoolss_Notify *data,
    2762             :                                        print_queue_struct *queue,
    2763             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    2764             :                                        TALLOC_CTX *mem_ctx)
    2765             : {
    2766           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
    2767           0 : }
    2768             : 
    2769             : /*******************************************************************
    2770             :  * fill a notify_info_data with the printername (not including the servername).
    2771             :  ********************************************************************/
    2772             : 
    2773           0 : static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
    2774             :                                         int snum,
    2775             :                                         struct spoolss_Notify *data,
    2776             :                                         print_queue_struct *queue,
    2777             :                                         struct spoolss_PrinterInfo2 *pinfo2,
    2778             :                                         TALLOC_CTX *mem_ctx)
    2779             : {
    2780             :         /* the notify name should not contain the \\server\ part */
    2781           0 :         const char *p = strrchr(pinfo2->printername, '\\');
    2782             : 
    2783           0 :         if (!p) {
    2784           0 :                 p = pinfo2->printername;
    2785             :         } else {
    2786           0 :                 p++;
    2787             :         }
    2788             : 
    2789           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    2790           0 : }
    2791             : 
    2792             : /*******************************************************************
    2793             :  * fill a notify_info_data with the servicename
    2794             :  ********************************************************************/
    2795             : 
    2796           0 : static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
    2797             :                                       int snum,
    2798             :                                       struct spoolss_Notify *data,
    2799             :                                       print_queue_struct *queue,
    2800             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2801             :                                       TALLOC_CTX *mem_ctx)
    2802             : {
    2803           0 :         const struct loadparm_substitution *lp_sub =
    2804           0 :                 loadparm_s3_global_substitution();
    2805             : 
    2806           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
    2807           0 : }
    2808             : 
    2809             : /*******************************************************************
    2810             :  * fill a notify_info_data with the port name
    2811             :  ********************************************************************/
    2812             : 
    2813           0 : static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
    2814             :                                      int snum,
    2815             :                                      struct spoolss_Notify *data,
    2816             :                                      print_queue_struct *queue,
    2817             :                                      struct spoolss_PrinterInfo2 *pinfo2,
    2818             :                                      TALLOC_CTX *mem_ctx)
    2819             : {
    2820           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
    2821           0 : }
    2822             : 
    2823             : /*******************************************************************
    2824             :  * fill a notify_info_data with the printername
    2825             :  * but it doesn't exist, have to see what to do
    2826             :  ********************************************************************/
    2827             : 
    2828           0 : static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
    2829             :                                        int snum,
    2830             :                                        struct spoolss_Notify *data,
    2831             :                                        print_queue_struct *queue,
    2832             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    2833             :                                        TALLOC_CTX *mem_ctx)
    2834             : {
    2835           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
    2836           0 : }
    2837             : 
    2838             : /*******************************************************************
    2839             :  * fill a notify_info_data with the comment
    2840             :  ********************************************************************/
    2841             : 
    2842           0 : static void spoolss_notify_comment(struct messaging_context *msg_ctx,
    2843             :                                    int snum,
    2844             :                                    struct spoolss_Notify *data,
    2845             :                                    print_queue_struct *queue,
    2846             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2847             :                                    TALLOC_CTX *mem_ctx)
    2848             : {
    2849           0 :         const struct loadparm_substitution *lp_sub =
    2850           0 :                 loadparm_s3_global_substitution();
    2851           0 :         const char *p;
    2852             : 
    2853           0 :         if (*pinfo2->comment == '\0') {
    2854           0 :                 p = lp_comment(talloc_tos(), lp_sub, snum);
    2855             :         } else {
    2856           0 :                 p = pinfo2->comment;
    2857             :         }
    2858             : 
    2859           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    2860           0 : }
    2861             : 
    2862             : /*******************************************************************
    2863             :  * fill a notify_info_data with the comment
    2864             :  * location = "Room 1, floor 2, building 3"
    2865             :  ********************************************************************/
    2866             : 
    2867           0 : static void spoolss_notify_location(struct messaging_context *msg_ctx,
    2868             :                                     int snum,
    2869             :                                     struct spoolss_Notify *data,
    2870             :                                     print_queue_struct *queue,
    2871             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2872             :                                     TALLOC_CTX *mem_ctx)
    2873             : {
    2874           0 :         const char *loc = pinfo2->location;
    2875           0 :         NTSTATUS status;
    2876             : 
    2877           0 :         status = printer_list_get_printer(mem_ctx,
    2878             :                                           pinfo2->sharename,
    2879             :                                           NULL,
    2880             :                                           &loc,
    2881             :                                           NULL);
    2882           0 :         if (NT_STATUS_IS_OK(status)) {
    2883           0 :                 if (loc == NULL) {
    2884           0 :                         loc = pinfo2->location;
    2885             :                 }
    2886             :         }
    2887             : 
    2888           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
    2889           0 : }
    2890             : 
    2891             : /*******************************************************************
    2892             :  * fill a notify_info_data with the device mode
    2893             :  * jfm:xxxx don't to it for know but that's a real problem !!!
    2894             :  ********************************************************************/
    2895             : 
    2896           0 : static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
    2897             :                                    int snum,
    2898             :                                    struct spoolss_Notify *data,
    2899             :                                    print_queue_struct *queue,
    2900             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2901             :                                    TALLOC_CTX *mem_ctx)
    2902             : {
    2903             :         /* for a dummy implementation we have to zero the fields */
    2904           0 :         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
    2905           0 : }
    2906             : 
    2907             : /*******************************************************************
    2908             :  * fill a notify_info_data with the separator file name
    2909             :  ********************************************************************/
    2910             : 
    2911           0 : static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
    2912             :                                    int snum,
    2913             :                                    struct spoolss_Notify *data,
    2914             :                                    print_queue_struct *queue,
    2915             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2916             :                                    TALLOC_CTX *mem_ctx)
    2917             : {
    2918           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
    2919           0 : }
    2920             : 
    2921             : /*******************************************************************
    2922             :  * fill a notify_info_data with the print processor
    2923             :  * jfm:xxxx return always winprint to indicate we don't do anything to it
    2924             :  ********************************************************************/
    2925             : 
    2926           0 : static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
    2927             :                                            int snum,
    2928             :                                            struct spoolss_Notify *data,
    2929             :                                            print_queue_struct *queue,
    2930             :                                            struct spoolss_PrinterInfo2 *pinfo2,
    2931             :                                            TALLOC_CTX *mem_ctx)
    2932             : {
    2933           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
    2934           0 : }
    2935             : 
    2936             : /*******************************************************************
    2937             :  * fill a notify_info_data with the print processor options
    2938             :  * jfm:xxxx send an empty string
    2939             :  ********************************************************************/
    2940             : 
    2941           0 : static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
    2942             :                                       int snum,
    2943             :                                       struct spoolss_Notify *data,
    2944             :                                       print_queue_struct *queue,
    2945             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2946             :                                       TALLOC_CTX *mem_ctx)
    2947             : {
    2948           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
    2949           0 : }
    2950             : 
    2951             : /*******************************************************************
    2952             :  * fill a notify_info_data with the data type
    2953             :  * jfm:xxxx always send RAW as data type
    2954             :  ********************************************************************/
    2955             : 
    2956           0 : static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
    2957             :                                     int snum,
    2958             :                                     struct spoolss_Notify *data,
    2959             :                                     print_queue_struct *queue,
    2960             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2961             :                                     TALLOC_CTX *mem_ctx)
    2962             : {
    2963           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
    2964           0 : }
    2965             : 
    2966             : /*******************************************************************
    2967             :  * fill a notify_info_data with the security descriptor
    2968             :  * jfm:xxxx send an null pointer to say no security desc
    2969             :  * have to implement security before !
    2970             :  ********************************************************************/
    2971             : 
    2972           0 : static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
    2973             :                                          int snum,
    2974             :                                          struct spoolss_Notify *data,
    2975             :                                          print_queue_struct *queue,
    2976             :                                          struct spoolss_PrinterInfo2 *pinfo2,
    2977             :                                          TALLOC_CTX *mem_ctx)
    2978             : {
    2979           0 :         if (pinfo2->secdesc == NULL) {
    2980           0 :                 data->data.sd.sd = NULL;
    2981             :         } else {
    2982           0 :                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
    2983           0 :                                                             pinfo2->secdesc);
    2984             :         }
    2985           0 :         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
    2986             :                                                              0);
    2987           0 : }
    2988             : 
    2989             : /*******************************************************************
    2990             :  * fill a notify_info_data with the attributes
    2991             :  * jfm:xxxx a samba printer is always shared
    2992             :  ********************************************************************/
    2993             : 
    2994           0 : static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
    2995             :                                       int snum,
    2996             :                                       struct spoolss_Notify *data,
    2997             :                                       print_queue_struct *queue,
    2998             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2999             :                                       TALLOC_CTX *mem_ctx)
    3000             : {
    3001           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
    3002           0 : }
    3003             : 
    3004             : /*******************************************************************
    3005             :  * fill a notify_info_data with the priority
    3006             :  ********************************************************************/
    3007             : 
    3008           0 : static void spoolss_notify_priority(struct messaging_context *msg_ctx,
    3009             :                                     int snum,
    3010             :                                     struct spoolss_Notify *data,
    3011             :                                     print_queue_struct *queue,
    3012             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3013             :                                     TALLOC_CTX *mem_ctx)
    3014             : {
    3015           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
    3016           0 : }
    3017             : 
    3018             : /*******************************************************************
    3019             :  * fill a notify_info_data with the default priority
    3020             :  ********************************************************************/
    3021             : 
    3022           0 : static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
    3023             :                                             int snum,
    3024             :                                             struct spoolss_Notify *data,
    3025             :                                             print_queue_struct *queue,
    3026             :                                             struct spoolss_PrinterInfo2 *pinfo2,
    3027             :                                             TALLOC_CTX *mem_ctx)
    3028             : {
    3029           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
    3030           0 : }
    3031             : 
    3032             : /*******************************************************************
    3033             :  * fill a notify_info_data with the start time
    3034             :  ********************************************************************/
    3035             : 
    3036           0 : static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
    3037             :                                       int snum,
    3038             :                                       struct spoolss_Notify *data,
    3039             :                                       print_queue_struct *queue,
    3040             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3041             :                                       TALLOC_CTX *mem_ctx)
    3042             : {
    3043           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
    3044           0 : }
    3045             : 
    3046             : /*******************************************************************
    3047             :  * fill a notify_info_data with the until time
    3048             :  ********************************************************************/
    3049             : 
    3050           0 : static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
    3051             :                                       int snum,
    3052             :                                       struct spoolss_Notify *data,
    3053             :                                       print_queue_struct *queue,
    3054             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3055             :                                       TALLOC_CTX *mem_ctx)
    3056             : {
    3057           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
    3058           0 : }
    3059             : 
    3060             : /*******************************************************************
    3061             :  * fill a notify_info_data with the status
    3062             :  ********************************************************************/
    3063             : 
    3064           0 : static void spoolss_notify_status(struct messaging_context *msg_ctx,
    3065             :                                   int snum,
    3066             :                                   struct spoolss_Notify *data,
    3067             :                                   print_queue_struct *queue,
    3068             :                                   struct spoolss_PrinterInfo2 *pinfo2,
    3069             :                                   TALLOC_CTX *mem_ctx)
    3070             : {
    3071           0 :         print_status_struct status;
    3072             : 
    3073           0 :         print_queue_length(msg_ctx, snum, &status);
    3074           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
    3075           0 : }
    3076             : 
    3077             : /*******************************************************************
    3078             :  * fill a notify_info_data with the number of jobs queued
    3079             :  ********************************************************************/
    3080             : 
    3081           0 : static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
    3082             :                                  int snum,
    3083             :                                  struct spoolss_Notify *data,
    3084             :                                  print_queue_struct *queue,
    3085             :                                  struct spoolss_PrinterInfo2 *pinfo2,
    3086             :                                  TALLOC_CTX *mem_ctx)
    3087             : {
    3088           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
    3089           0 :                 data, print_queue_length(msg_ctx, snum, NULL));
    3090           0 : }
    3091             : 
    3092             : /*******************************************************************
    3093             :  * fill a notify_info_data with the average ppm
    3094             :  ********************************************************************/
    3095             : 
    3096           0 : static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
    3097             :                                        int snum,
    3098             :                                        struct spoolss_Notify *data,
    3099             :                                        print_queue_struct *queue,
    3100             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    3101             :                                        TALLOC_CTX *mem_ctx)
    3102             : {
    3103             :         /* always respond 8 pages per minutes */
    3104             :         /* a little hard ! */
    3105           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
    3106           0 : }
    3107             : 
    3108             : /*******************************************************************
    3109             :  * fill a notify_info_data with username
    3110             :  ********************************************************************/
    3111             : 
    3112           0 : static void spoolss_notify_username(struct messaging_context *msg_ctx,
    3113             :                                     int snum,
    3114             :                                     struct spoolss_Notify *data,
    3115             :                                     print_queue_struct *queue,
    3116             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3117             :                                     TALLOC_CTX *mem_ctx)
    3118             : {
    3119           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
    3120           0 : }
    3121             : 
    3122             : /*******************************************************************
    3123             :  * fill a notify_info_data with job status
    3124             :  ********************************************************************/
    3125             : 
    3126           0 : static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
    3127             :                                       int snum,
    3128             :                                       struct spoolss_Notify *data,
    3129             :                                       print_queue_struct *queue,
    3130             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3131             :                                       TALLOC_CTX *mem_ctx)
    3132             : {
    3133           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
    3134           0 : }
    3135             : 
    3136             : /*******************************************************************
    3137             :  * fill a notify_info_data with job name
    3138             :  ********************************************************************/
    3139             : 
    3140           0 : static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
    3141             :                                     int snum,
    3142             :                                     struct spoolss_Notify *data,
    3143             :                                     print_queue_struct *queue,
    3144             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3145             :                                     TALLOC_CTX *mem_ctx)
    3146             : {
    3147           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
    3148           0 : }
    3149             : 
    3150             : /*******************************************************************
    3151             :  * fill a notify_info_data with job status
    3152             :  ********************************************************************/
    3153             : 
    3154           0 : static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
    3155             :                                              int snum,
    3156             :                                              struct spoolss_Notify *data,
    3157             :                                              print_queue_struct *queue,
    3158             :                                              struct spoolss_PrinterInfo2 *pinfo2,
    3159             :                                              TALLOC_CTX *mem_ctx)
    3160             : {
    3161             :         /*
    3162             :          * Now we're returning job status codes we just return a "" here. JRA.
    3163             :          */
    3164             : 
    3165           0 :         const char *p = "";
    3166             : 
    3167             : #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
    3168             :         p = "unknown";
    3169             : 
    3170             :         switch (queue->status) {
    3171             :         case LPQ_QUEUED:
    3172             :                 p = "Queued";
    3173             :                 break;
    3174             :         case LPQ_PAUSED:
    3175             :                 p = "";    /* NT provides the paused string */
    3176             :                 break;
    3177             :         case LPQ_SPOOLING:
    3178             :                 p = "Spooling";
    3179             :                 break;
    3180             :         case LPQ_PRINTING:
    3181             :                 p = "Printing";
    3182             :                 break;
    3183             :         }
    3184             : #endif /* NO LONGER NEEDED. */
    3185             : 
    3186           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    3187           0 : }
    3188             : 
    3189             : /*******************************************************************
    3190             :  * fill a notify_info_data with job time
    3191             :  ********************************************************************/
    3192             : 
    3193           0 : static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
    3194             :                                     int snum,
    3195             :                                     struct spoolss_Notify *data,
    3196             :                                     print_queue_struct *queue,
    3197             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3198             :                                     TALLOC_CTX *mem_ctx)
    3199             : {
    3200           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
    3201           0 : }
    3202             : 
    3203             : /*******************************************************************
    3204             :  * fill a notify_info_data with job size
    3205             :  ********************************************************************/
    3206             : 
    3207           0 : static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
    3208             :                                     int snum,
    3209             :                                     struct spoolss_Notify *data,
    3210             :                                     print_queue_struct *queue,
    3211             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3212             :                                     TALLOC_CTX *mem_ctx)
    3213             : {
    3214           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
    3215           0 : }
    3216             : 
    3217             : /*******************************************************************
    3218             :  * fill a notify_info_data with page info
    3219             :  ********************************************************************/
    3220           0 : static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
    3221             :                                        int snum,
    3222             :                                 struct spoolss_Notify *data,
    3223             :                                 print_queue_struct *queue,
    3224             :                                 struct spoolss_PrinterInfo2 *pinfo2,
    3225             :                                 TALLOC_CTX *mem_ctx)
    3226             : {
    3227           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
    3228           0 : }
    3229             : 
    3230             : /*******************************************************************
    3231             :  * fill a notify_info_data with pages printed info.
    3232             :  ********************************************************************/
    3233           0 : static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
    3234             :                                          int snum,
    3235             :                                 struct spoolss_Notify *data,
    3236             :                                 print_queue_struct *queue,
    3237             :                                 struct spoolss_PrinterInfo2 *pinfo2,
    3238             :                                 TALLOC_CTX *mem_ctx)
    3239             : {
    3240             :         /* Add code when back-end tracks this */
    3241           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
    3242           0 : }
    3243             : 
    3244             : /*******************************************************************
    3245             :  Fill a notify_info_data with job position.
    3246             :  ********************************************************************/
    3247             : 
    3248           0 : static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
    3249             :                                         int snum,
    3250             :                                         struct spoolss_Notify *data,
    3251             :                                         print_queue_struct *queue,
    3252             :                                         struct spoolss_PrinterInfo2 *pinfo2,
    3253             :                                         TALLOC_CTX *mem_ctx)
    3254             : {
    3255           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
    3256           0 : }
    3257             : 
    3258             : /*******************************************************************
    3259             :  Fill a notify_info_data with submitted time.
    3260             :  ********************************************************************/
    3261             : 
    3262           0 : static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
    3263             :                                           int snum,
    3264             :                                           struct spoolss_Notify *data,
    3265             :                                           print_queue_struct *queue,
    3266             :                                           struct spoolss_PrinterInfo2 *pinfo2,
    3267             :                                           TALLOC_CTX *mem_ctx)
    3268             : {
    3269           0 :         data->data.string.string = NULL;
    3270           0 :         data->data.string.size = 0;
    3271             : 
    3272           0 :         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
    3273             :                                &data->data.string.string,
    3274             :                                &data->data.string.size);
    3275             : 
    3276           0 : }
    3277             : 
    3278             : struct s_notify_info_data_table
    3279             : {
    3280             :         enum spoolss_NotifyType type;
    3281             :         uint16_t field;
    3282             :         const char *name;
    3283             :         enum spoolss_NotifyTable variable_type;
    3284             :         void (*fn) (struct messaging_context *msg_ctx,
    3285             :                     int snum, struct spoolss_Notify *data,
    3286             :                     print_queue_struct *queue,
    3287             :                     struct spoolss_PrinterInfo2 *pinfo2,
    3288             :                     TALLOC_CTX *mem_ctx);
    3289             : };
    3290             : 
    3291             : /* A table describing the various print notification constants and
    3292             :    whether the notification data is a pointer to a variable sized
    3293             :    buffer, a one value uint32_t or a two value uint32_t. */
    3294             : 
    3295             : static const struct s_notify_info_data_table notify_info_data_table[] =
    3296             : {
    3297             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
    3298             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
    3299             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
    3300             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
    3301             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
    3302             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
    3303             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
    3304             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
    3305             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
    3306             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
    3307             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
    3308             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
    3309             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
    3310             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
    3311             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
    3312             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
    3313             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
    3314             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
    3315             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
    3316             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
    3317             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
    3318             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
    3319             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
    3320             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
    3321             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
    3322             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
    3323             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
    3324             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
    3325             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
    3326             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
    3327             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
    3328             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
    3329             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
    3330             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
    3331             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
    3332             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
    3333             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
    3334             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
    3335             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
    3336             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
    3337             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
    3338             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
    3339             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
    3340             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
    3341             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
    3342             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
    3343             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
    3344             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
    3345             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
    3346             : };
    3347             : 
    3348             : /*******************************************************************
    3349             :  Return the variable_type of info_data structure.
    3350             : ********************************************************************/
    3351             : 
    3352           0 : static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
    3353             :                                                                   uint16_t field)
    3354             : {
    3355           0 :         int i=0;
    3356             : 
    3357           0 :         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
    3358           0 :                 if ( (notify_info_data_table[i].type == type) &&
    3359           0 :                      (notify_info_data_table[i].field == field) ) {
    3360           0 :                         return notify_info_data_table[i].variable_type;
    3361             :                 }
    3362             :         }
    3363             : 
    3364           0 :         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
    3365             : 
    3366           0 :         return (enum spoolss_NotifyTable) 0;
    3367             : }
    3368             : 
    3369             : /****************************************************************************
    3370             : ****************************************************************************/
    3371             : 
    3372           0 : static bool search_notify(enum spoolss_NotifyType type,
    3373             :                           uint16_t field,
    3374             :                           int *value)
    3375             : {
    3376           0 :         int i;
    3377             : 
    3378           0 :         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
    3379           0 :                 if (notify_info_data_table[i].type == type &&
    3380           0 :                     notify_info_data_table[i].field == field &&
    3381           0 :                     notify_info_data_table[i].fn != NULL) {
    3382           0 :                         *value = i;
    3383           0 :                         return true;
    3384             :                 }
    3385             :         }
    3386             : 
    3387           0 :         return false;
    3388             : }
    3389             : 
    3390             : /****************************************************************************
    3391             : ****************************************************************************/
    3392             : 
    3393           0 : static void construct_info_data(struct spoolss_Notify *info_data,
    3394             :                                 enum spoolss_NotifyType type,
    3395             :                                 uint16_t field, int id)
    3396             : {
    3397           0 :         info_data->type                      = type;
    3398           0 :         info_data->field.field               = field;
    3399           0 :         info_data->variable_type     = variable_type_of_notify_info_data(type, field);
    3400           0 :         info_data->job_id            = id;
    3401           0 : }
    3402             : 
    3403             : /*******************************************************************
    3404             :  *
    3405             :  * fill a notify_info struct with info asked
    3406             :  *
    3407             :  ********************************************************************/
    3408             : 
    3409           0 : static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
    3410             :                                           struct printer_handle *print_hnd,
    3411             :                                           struct spoolss_NotifyInfo *info,
    3412             :                                           struct spoolss_PrinterInfo2 *pinfo2,
    3413             :                                           int snum,
    3414             :                                           const struct spoolss_NotifyOptionType *option_type,
    3415             :                                           uint32_t id,
    3416             :                                           TALLOC_CTX *mem_ctx)
    3417             : {
    3418           0 :         const struct loadparm_substitution *lp_sub =
    3419           0 :                 loadparm_s3_global_substitution();
    3420           0 :         int field_num,j;
    3421           0 :         enum spoolss_NotifyType type;
    3422           0 :         uint16_t field;
    3423             : 
    3424           0 :         struct spoolss_Notify *current_data;
    3425             : 
    3426           0 :         type = option_type->type;
    3427             : 
    3428           0 :         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
    3429             :                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
    3430             :                 option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
    3431             : 
    3432           0 :         for(field_num=0; field_num < option_type->count; field_num++) {
    3433           0 :                 field = option_type->fields[field_num].field;
    3434             : 
    3435           0 :                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
    3436             : 
    3437           0 :                 if (!search_notify(type, field, &j) )
    3438           0 :                         continue;
    3439             : 
    3440           0 :                 info->notifies = talloc_realloc(info, info->notifies,
    3441             :                                                       struct spoolss_Notify,
    3442             :                                                       info->count + 1);
    3443           0 :                 if (info->notifies == NULL) {
    3444           0 :                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
    3445           0 :                         return false;
    3446             :                 }
    3447             : 
    3448           0 :                 current_data = &info->notifies[info->count];
    3449             : 
    3450           0 :                 construct_info_data(current_data, type, field, id);
    3451             : 
    3452           0 :                 DEBUG(10, ("construct_notify_printer_info: "
    3453             :                            "calling [%s]  snum=%d  printername=[%s])\n",
    3454             :                            notify_info_data_table[j].name, snum,
    3455             :                            pinfo2->printername));
    3456             : 
    3457           0 :                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
    3458             :                                              NULL, pinfo2, mem_ctx);
    3459             : 
    3460           0 :                 info->count++;
    3461             :         }
    3462             : 
    3463           0 :         return true;
    3464             : }
    3465             : 
    3466             : /*******************************************************************
    3467             :  *
    3468             :  * fill a notify_info struct with info asked
    3469             :  *
    3470             :  ********************************************************************/
    3471             : 
    3472           0 : static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
    3473             :                                        print_queue_struct *queue,
    3474             :                                        struct spoolss_NotifyInfo *info,
    3475             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    3476             :                                        int snum,
    3477             :                                        const struct spoolss_NotifyOptionType *option_type,
    3478             :                                        uint32_t id,
    3479             :                                        TALLOC_CTX *mem_ctx)
    3480             : {
    3481           0 :         int field_num,j;
    3482           0 :         enum spoolss_NotifyType type;
    3483           0 :         uint16_t field;
    3484           0 :         struct spoolss_Notify *current_data;
    3485             : 
    3486           0 :         DEBUG(4,("construct_notify_jobs_info\n"));
    3487             : 
    3488           0 :         type = option_type->type;
    3489             : 
    3490           0 :         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
    3491             :                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
    3492             :                 option_type->count));
    3493             : 
    3494           0 :         for(field_num=0; field_num<option_type->count; field_num++) {
    3495           0 :                 field = option_type->fields[field_num].field;
    3496             : 
    3497           0 :                 if (!search_notify(type, field, &j) )
    3498           0 :                         continue;
    3499             : 
    3500           0 :                 info->notifies = talloc_realloc(info, info->notifies,
    3501             :                                                       struct spoolss_Notify,
    3502             :                                                       info->count + 1);
    3503           0 :                 if (info->notifies == NULL) {
    3504           0 :                         DEBUG(2,("construct_notify_jobs_info: failed to enlarge buffer info->data!\n"));
    3505           0 :                         return false;
    3506             :                 }
    3507             : 
    3508           0 :                 current_data=&(info->notifies[info->count]);
    3509             : 
    3510           0 :                 construct_info_data(current_data, type, field, id);
    3511           0 :                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
    3512             :                                              queue, pinfo2, mem_ctx);
    3513           0 :                 info->count++;
    3514             :         }
    3515             : 
    3516           0 :         return true;
    3517             : }
    3518             : 
    3519             : /*
    3520             :  * JFM: The enumeration is not that simple, it's even non obvious.
    3521             :  *
    3522             :  * let's take an example: I want to monitor the PRINTER SERVER for
    3523             :  * the printer's name and the number of jobs currently queued.
    3524             :  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
    3525             :  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
    3526             :  *
    3527             :  * I have 3 printers on the back of my server.
    3528             :  *
    3529             :  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
    3530             :  * structures.
    3531             :  *   Number     Data                    Id
    3532             :  *      1       printer 1 name          1
    3533             :  *      2       printer 1 cjob          1
    3534             :  *      3       printer 2 name          2
    3535             :  *      4       printer 2 cjob          2
    3536             :  *      5       printer 3 name          3
    3537             :  *      6       printer 3 name          3
    3538             :  *
    3539             :  * that's the print server case, the printer case is even worse.
    3540             :  */
    3541             : 
    3542             : /*******************************************************************
    3543             :  *
    3544             :  * enumerate all printers on the printserver
    3545             :  * fill a notify_info struct with info asked
    3546             :  *
    3547             :  ********************************************************************/
    3548             : 
    3549           4 : static WERROR printserver_notify_info(struct pipes_struct *p,
    3550             :                                       struct policy_handle *hnd,
    3551             :                                       struct spoolss_NotifyInfo *info,
    3552             :                                       TALLOC_CTX *mem_ctx)
    3553             : {
    3554           0 :         const struct loadparm_substitution *lp_sub =
    3555           4 :                 loadparm_s3_global_substitution();
    3556           0 :         int snum;
    3557           4 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
    3558           4 :         int n_services=lp_numservices();
    3559           0 :         int i;
    3560           0 :         struct spoolss_NotifyOption *option;
    3561           0 :         struct spoolss_NotifyOptionType option_type;
    3562           4 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    3563           0 :         WERROR result;
    3564             : 
    3565           4 :         DEBUG(4,("printserver_notify_info\n"));
    3566             : 
    3567           4 :         if (!Printer)
    3568           0 :                 return WERR_INVALID_HANDLE;
    3569             : 
    3570           4 :         option = Printer->notify.option;
    3571             : 
    3572           4 :         info->version        = 2;
    3573           4 :         info->notifies       = NULL;
    3574           4 :         info->count  = 0;
    3575             : 
    3576             :         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
    3577             :            sending a ffpcn() request first */
    3578             : 
    3579           4 :         if ( !option )
    3580           0 :                 return WERR_INVALID_HANDLE;
    3581             : 
    3582          12 :         for (i=0; i<option->count; i++) {
    3583           8 :                 option_type = option->types[i];
    3584             : 
    3585           8 :                 if (option_type.type != PRINTER_NOTIFY_TYPE)
    3586           4 :                         continue;
    3587             : 
    3588         492 :                 for (snum = 0; snum < n_services; snum++) {
    3589         488 :                         if (!lp_browseable(snum) ||
    3590         488 :                             !lp_snum_ok(snum) ||
    3591         488 :                             !lp_printable(snum)) {
    3592         468 :                                 continue; /* skip */
    3593             :                         }
    3594             : 
    3595             :                         /* Maybe we should use the SYSTEM session_info here... */
    3596          20 :                         result = winreg_get_printer_internal(mem_ctx,
    3597             :                                                     get_session_info_system(),
    3598             :                                                     p->msg_ctx,
    3599          20 :                                                     lp_servicename(talloc_tos(), lp_sub, snum),
    3600             :                                                     &pinfo2);
    3601          20 :                         if (!W_ERROR_IS_OK(result)) {
    3602          20 :                                 DEBUG(4, ("printserver_notify_info: "
    3603             :                                           "Failed to get printer [%s]\n",
    3604             :                                           lp_servicename(talloc_tos(), lp_sub, snum)));
    3605          20 :                                 continue;
    3606             :                         }
    3607             : 
    3608             : 
    3609           0 :                         construct_notify_printer_info(p->msg_ctx,
    3610             :                                                       Printer, info,
    3611             :                                                       pinfo2, snum,
    3612             :                                                       &option_type, snum,
    3613             :                                                       mem_ctx);
    3614             : 
    3615           0 :                         TALLOC_FREE(pinfo2);
    3616             :                 }
    3617             :         }
    3618             : 
    3619             : #if 0
    3620             :         /*
    3621             :          * Debugging information, don't delete.
    3622             :          */
    3623             : 
    3624             :         DEBUG(1,("dumping the NOTIFY_INFO\n"));
    3625             :         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
    3626             :         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
    3627             : 
    3628             :         for (i=0; i<info->count; i++) {
    3629             :                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
    3630             :                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
    3631             :                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
    3632             :         }
    3633             : #endif
    3634             : 
    3635           4 :         return WERR_OK;
    3636             : }
    3637             : 
    3638             : /*******************************************************************
    3639             :  *
    3640             :  * fill a notify_info struct with info asked
    3641             :  *
    3642             :  ********************************************************************/
    3643             : 
    3644           0 : static WERROR printer_notify_info(struct pipes_struct *p,
    3645             :                                   struct policy_handle *hnd,
    3646             :                                   struct spoolss_NotifyInfo *info,
    3647             :                                   TALLOC_CTX *mem_ctx)
    3648             : {
    3649           0 :         const struct loadparm_substitution *lp_sub =
    3650           0 :                 loadparm_s3_global_substitution();
    3651           0 :         int snum;
    3652           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
    3653           0 :         int i;
    3654           0 :         uint32_t id;
    3655           0 :         struct spoolss_NotifyOption *option;
    3656           0 :         struct spoolss_NotifyOptionType option_type;
    3657           0 :         int count,j;
    3658           0 :         print_queue_struct *queue=NULL;
    3659           0 :         print_status_struct status;
    3660           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    3661           0 :         WERROR result;
    3662           0 :         struct tdb_print_db *pdb;
    3663             : 
    3664           0 :         DEBUG(4,("printer_notify_info\n"));
    3665             : 
    3666           0 :         if (!Printer)
    3667           0 :                 return WERR_INVALID_HANDLE;
    3668             : 
    3669           0 :         option = Printer->notify.option;
    3670           0 :         id = 0x0;
    3671             : 
    3672           0 :         info->version        = 2;
    3673           0 :         info->notifies       = NULL;
    3674           0 :         info->count  = 0;
    3675             : 
    3676             :         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
    3677             :            sending a ffpcn() request first */
    3678             : 
    3679           0 :         if ( !option )
    3680           0 :                 return WERR_INVALID_HANDLE;
    3681             : 
    3682           0 :         if (!get_printer_snum(p, hnd, &snum, NULL)) {
    3683           0 :                 return WERR_INVALID_HANDLE;
    3684             :         }
    3685             : 
    3686           0 :         pdb = get_print_db_byname(Printer->sharename);
    3687           0 :         if (pdb == NULL) {
    3688           0 :                 return WERR_INVALID_HANDLE;
    3689             :         }
    3690             : 
    3691             :         /* Maybe we should use the SYSTEM session_info here... */
    3692           0 :         result = winreg_get_printer_internal(mem_ctx,
    3693             :                                     get_session_info_system(),
    3694             :                                     p->msg_ctx,
    3695           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
    3696           0 :         if (!W_ERROR_IS_OK(result)) {
    3697           0 :                 result = WERR_INVALID_HANDLE;
    3698           0 :                 goto err_pdb_drop;
    3699             :         }
    3700             : 
    3701             :         /*
    3702             :          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
    3703             :          * correct servername.
    3704             :          */
    3705           0 :         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
    3706           0 :         if (pinfo2->servername == NULL) {
    3707           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3708           0 :                 goto err_pdb_drop;
    3709             :         }
    3710             : 
    3711           0 :         for (i = 0; i < option->count; i++) {
    3712           0 :                 option_type = option->types[i];
    3713             : 
    3714           0 :                 switch (option_type.type) {
    3715           0 :                 case PRINTER_NOTIFY_TYPE:
    3716           0 :                         if (construct_notify_printer_info(p->msg_ctx,
    3717             :                                                           Printer, info,
    3718             :                                                           pinfo2, snum,
    3719             :                                                           &option_type, id,
    3720             :                                                           mem_ctx)) {
    3721           0 :                                 id--;
    3722             :                         }
    3723           0 :                         break;
    3724             : 
    3725           0 :                 case JOB_NOTIFY_TYPE:
    3726             : 
    3727           0 :                         count = print_queue_status(p->msg_ctx, snum, &queue,
    3728             :                                                    &status);
    3729             : 
    3730           0 :                         for (j = 0; j < count; j++) {
    3731           0 :                                 uint32_t jobid;
    3732           0 :                                 jobid = sysjob_to_jobid_pdb(pdb,
    3733           0 :                                                             queue[j].sysjob);
    3734           0 :                                 if (jobid == (uint32_t)-1) {
    3735           0 :                                         DEBUG(2, ("ignoring untracked job %d\n",
    3736             :                                                   queue[j].sysjob));
    3737           0 :                                         continue;
    3738             :                                 }
    3739             :                                 /* FIXME check return value */
    3740           0 :                                 construct_notify_jobs_info(p->msg_ctx,
    3741           0 :                                                            &queue[j], info,
    3742             :                                                            pinfo2, snum,
    3743             :                                                            &option_type,
    3744             :                                                            jobid,
    3745             :                                                            mem_ctx);
    3746             :                         }
    3747             : 
    3748           0 :                         SAFE_FREE(queue);
    3749           0 :                         break;
    3750             :                 }
    3751             :         }
    3752             : 
    3753             :         /*
    3754             :          * Debugging information, don't delete.
    3755             :          */
    3756             :         /*
    3757             :         DEBUG(1,("dumping the NOTIFY_INFO\n"));
    3758             :         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
    3759             :         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
    3760             : 
    3761             :         for (i=0; i<info->count; i++) {
    3762             :                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
    3763             :                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
    3764             :                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
    3765             :         }
    3766             :         */
    3767             : 
    3768           0 :         talloc_free(pinfo2);
    3769           0 :         result = WERR_OK;
    3770           0 : err_pdb_drop:
    3771           0 :         release_print_db(pdb);
    3772           0 :         return result;
    3773             : }
    3774             : 
    3775             : /****************************************************************
    3776             :  _spoolss_RouterRefreshPrinterChangeNotify
    3777             : ****************************************************************/
    3778             : 
    3779           4 : WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
    3780             :                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
    3781             : {
    3782           0 :         struct spoolss_NotifyInfo *info;
    3783             : 
    3784           4 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    3785           4 :         WERROR result = WERR_INVALID_HANDLE;
    3786             : 
    3787             :         /* we always have a spoolss_NotifyInfo struct */
    3788           4 :         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
    3789           4 :         if (!info) {
    3790           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3791           0 :                 goto done;
    3792             :         }
    3793             : 
    3794           4 :         *r->out.info = info;
    3795             : 
    3796           4 :         if (!Printer) {
    3797           0 :                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
    3798             :                         "Invalid handle (%s:%u:%u).\n",
    3799             :                         OUR_HANDLE(r->in.handle)));
    3800           0 :                 goto done;
    3801             :         }
    3802             : 
    3803           4 :         DEBUG(4,("Printer type %x\n",Printer->printer_type));
    3804             : 
    3805             :         /*
    3806             :          *      We are now using the change value, and
    3807             :          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
    3808             :          *      I don't have a global notification system, I'm sending back all the
    3809             :          *      information even when _NOTHING_ has changed.
    3810             :          */
    3811             : 
    3812             :         /* We need to keep track of the change value to send back in
    3813             :            RRPCN replies otherwise our updates are ignored. */
    3814             : 
    3815           4 :         Printer->notify.fnpcn = true;
    3816             : 
    3817           4 :         if (Printer->notify.cli_chan != NULL &&
    3818           4 :             Printer->notify.cli_chan->active_connections > 0) {
    3819           4 :                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
    3820             :                         "Saving change value in request [%x]\n",
    3821             :                         r->in.change_low));
    3822           4 :                 Printer->notify.change = r->in.change_low;
    3823             :         }
    3824             : 
    3825             :         /* just ignore the spoolss_NotifyOption */
    3826             : 
    3827           4 :         switch (Printer->printer_type) {
    3828           4 :                 case SPLHND_SERVER:
    3829           4 :                         result = printserver_notify_info(p, r->in.handle,
    3830             :                                                          info, p->mem_ctx);
    3831           4 :                         break;
    3832             : 
    3833           0 :                 case SPLHND_PRINTER:
    3834           0 :                         result = printer_notify_info(p, r->in.handle,
    3835             :                                                      info, p->mem_ctx);
    3836           0 :                         break;
    3837             :         }
    3838             : 
    3839           4 :         Printer->notify.fnpcn = false;
    3840             : 
    3841           4 : done:
    3842           4 :         return result;
    3843             : }
    3844             : 
    3845             : /********************************************************************
    3846             :  ********************************************************************/
    3847             : 
    3848        4076 : static WERROR create_printername(TALLOC_CTX *mem_ctx,
    3849             :                                  const char *servername,
    3850             :                                  const char *printername,
    3851             :                                  const char **printername_p)
    3852             : {
    3853             :         /* FIXME: add lp_force_printername() */
    3854             : 
    3855        4076 :         if (servername == NULL) {
    3856        1732 :                 *printername_p = talloc_strdup(mem_ctx, printername);
    3857        1732 :                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
    3858        1732 :                 return WERR_OK;
    3859             :         }
    3860             : 
    3861        2344 :         if (servername[0] == '\\' && servername[1] == '\\') {
    3862        2344 :                 servername += 2;
    3863             :         }
    3864             : 
    3865        2344 :         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
    3866        2344 :         W_ERROR_HAVE_NO_MEMORY(*printername_p);
    3867             : 
    3868        2344 :         return WERR_OK;
    3869             : }
    3870             : 
    3871             : /********************************************************************
    3872             :  ********************************************************************/
    3873             : 
    3874        2936 : static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
    3875             :                                           const char *printername)
    3876             : {
    3877        2936 :         if (dm == NULL) {
    3878          94 :                 return;
    3879             :         }
    3880             : 
    3881        2842 :         dm->devicename = talloc_strndup(dm, printername,
    3882        2842 :                                         MIN(strlen(printername), 31));
    3883             : }
    3884             : 
    3885             : /********************************************************************
    3886             :  * construct_printer_info_0
    3887             :  * fill a printer_info_0 struct
    3888             :  ********************************************************************/
    3889             : 
    3890         276 : static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
    3891             :                                       const struct auth_session_info *session_info,
    3892             :                                       struct messaging_context *msg_ctx,
    3893             :                                       struct spoolss_PrinterInfo2 *info2,
    3894             :                                       const char *servername,
    3895             :                                       struct spoolss_PrinterInfo0 *r,
    3896             :                                       int snum)
    3897             : {
    3898           0 :         int count;
    3899           0 :         struct printer_session_counter *session_counter;
    3900           0 :         struct timeval setuptime;
    3901           0 :         print_status_struct status;
    3902           0 :         WERROR result;
    3903           0 :         int os_major, os_minor, os_build;
    3904           0 :         const char *architecture;
    3905           0 :         uint32_t processor_architecture, processor_type;
    3906             : 
    3907         276 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    3908         276 :         if (!W_ERROR_IS_OK(result)) {
    3909           0 :                 return result;
    3910             :         }
    3911             : 
    3912         276 :         if (servername) {
    3913         140 :                 r->servername = talloc_strdup(mem_ctx, servername);
    3914         140 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    3915             :         } else {
    3916         136 :                 r->servername = NULL;
    3917             :         }
    3918             : 
    3919         276 :         count = print_queue_length(msg_ctx, snum, &status);
    3920             : 
    3921             :         /* check if we already have a counter for this printer */
    3922         660 :         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
    3923         620 :                 if (session_counter->snum == snum)
    3924         236 :                         break;
    3925             :         }
    3926             : 
    3927             :         /* it's the first time, add it to the list */
    3928         276 :         if (session_counter == NULL) {
    3929          40 :                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
    3930          40 :                 W_ERROR_HAVE_NO_MEMORY(session_counter);
    3931          40 :                 session_counter->snum                = snum;
    3932          40 :                 session_counter->counter     = 0;
    3933          40 :                 DLIST_ADD(counter_list, session_counter);
    3934             :         }
    3935             : 
    3936             :         /* increment it */
    3937         276 :         session_counter->counter++;
    3938             : 
    3939         276 :         r->cjobs                     = count;
    3940         276 :         r->total_jobs                        = 0;
    3941         276 :         r->total_bytes                       = 0;
    3942             : 
    3943         276 :         get_startup_time(&setuptime);
    3944         276 :         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
    3945             : 
    3946             :         /* JFM:
    3947             :          * the global_counter should be stored in a TDB as it's common to all the clients
    3948             :          * and should be zeroed on samba startup
    3949             :          */
    3950         276 :         r->global_counter            = session_counter->counter;
    3951         276 :         r->total_pages                       = 0;
    3952             : 
    3953             :         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
    3954         276 :         os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
    3955             :                                "spoolss", "os_major",
    3956             :                                GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
    3957         276 :         os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
    3958             :                                "spoolss", "os_minor",
    3959             :                                GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
    3960         276 :         os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
    3961             :                                "spoolss", "os_build",
    3962             :                                GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
    3963             : 
    3964         276 :         SCVAL(&r->version, 0, os_major);
    3965         276 :         SCVAL(&r->version, 1, os_minor);
    3966         276 :         SSVAL(&r->version, 2, os_build);
    3967             : 
    3968         276 :         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    3969             :                                             "spoolss",
    3970             :                                             "architecture",
    3971             :                                             GLOBAL_SPOOLSS_ARCHITECTURE);
    3972             : 
    3973         276 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
    3974         276 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_AMD64;
    3975         276 :                 processor_type          = PROCESSOR_AMD_X8664;
    3976           0 :         } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
    3977           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_ARM64;
    3978           0 :                 processor_type          = PROCESSOR_ARM820;
    3979             :         } else {
    3980           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_INTEL;
    3981           0 :                 processor_type          = PROCESSOR_INTEL_PENTIUM;
    3982             :         }
    3983             : 
    3984         276 :         r->free_build                        = SPOOLSS_RELEASE_BUILD;
    3985         276 :         r->spooling                  = 0;
    3986         276 :         r->max_spooling                      = 0;
    3987         276 :         r->session_counter           = session_counter->counter;
    3988         276 :         r->num_error_out_of_paper    = 0x0;
    3989         276 :         r->num_error_not_ready               = 0x0;          /* number of print failure */
    3990         276 :         r->job_error                 = 0x0;
    3991         276 :         r->number_of_processors              = 0x1;
    3992         276 :         r->processor_type            = processor_type;
    3993         276 :         r->high_part_total_bytes     = 0x0;
    3994             : 
    3995             :         /* ChangeID in milliseconds*/
    3996         276 :         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
    3997             :                                     info2->sharename, &r->change_id);
    3998             : 
    3999         276 :         r->last_error                        = WERR_OK;
    4000         276 :         r->status                    = nt_printq_status(status.status);
    4001         276 :         r->enumerate_network_printers        = 0x0;
    4002         276 :         r->c_setprinter                      = 0x0;
    4003         276 :         r->processor_architecture    = processor_architecture;
    4004         276 :         r->processor_level           = 0x6;          /* 6  ???*/
    4005         276 :         r->ref_ic                    = 0;
    4006         276 :         r->reserved2                 = 0;
    4007         276 :         r->reserved3                 = 0;
    4008             : 
    4009         276 :         return WERR_OK;
    4010             : }
    4011             : 
    4012             : 
    4013             : /********************************************************************
    4014             :  * construct_printer_info1
    4015             :  * fill a spoolss_PrinterInfo1 struct
    4016             : ********************************************************************/
    4017             : 
    4018         528 : static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
    4019             :                                       const struct spoolss_PrinterInfo2 *info2,
    4020             :                                       uint32_t flags,
    4021             :                                       const char *servername,
    4022             :                                       struct spoolss_PrinterInfo1 *r,
    4023             :                                       int snum)
    4024             : {
    4025           0 :         const struct loadparm_substitution *lp_sub =
    4026         528 :                 loadparm_s3_global_substitution();
    4027           0 :         WERROR result;
    4028             : 
    4029         528 :         r->flags             = flags;
    4030             : 
    4031         528 :         if (info2->comment == NULL || info2->comment[0] == '\0') {
    4032         388 :                 r->comment   = lp_comment(mem_ctx, lp_sub, snum);
    4033             :         } else {
    4034         140 :                 r->comment   = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
    4035             :         }
    4036         528 :         W_ERROR_HAVE_NO_MEMORY(r->comment);
    4037             : 
    4038         528 :         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
    4039         528 :         if (!W_ERROR_IS_OK(result)) {
    4040           0 :                 return result;
    4041             :         }
    4042             : 
    4043        1056 :         r->description               = talloc_asprintf(mem_ctx, "%s,%s,%s",
    4044             :                                                   r->name,
    4045         528 :                                                   info2->drivername,
    4046             :                                                   r->comment);
    4047         528 :         W_ERROR_HAVE_NO_MEMORY(r->description);
    4048             : 
    4049         528 :         return WERR_OK;
    4050             : }
    4051             : 
    4052             : /********************************************************************
    4053             :  * construct_printer_info2
    4054             :  * fill a spoolss_PrinterInfo2 struct
    4055             : ********************************************************************/
    4056             : 
    4057        1272 : static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
    4058             :                                       struct messaging_context *msg_ctx,
    4059             :                                       const struct spoolss_PrinterInfo2 *info2,
    4060             :                                       const char *servername,
    4061             :                                       struct spoolss_PrinterInfo2 *r,
    4062             :                                       int snum)
    4063             : {
    4064           0 :         const struct loadparm_substitution *lp_sub =
    4065        1272 :                 loadparm_s3_global_substitution();
    4066           0 :         int count;
    4067           0 :         print_status_struct status;
    4068           0 :         WERROR result;
    4069             : 
    4070        1272 :         count = print_queue_length(msg_ctx, snum, &status);
    4071             : 
    4072        1272 :         if (servername) {
    4073         572 :                 r->servername                = talloc_strdup(mem_ctx, servername);
    4074         572 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    4075             :         } else {
    4076         700 :                 r->servername                = NULL;
    4077             :         }
    4078             : 
    4079        1272 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4080        1272 :         if (!W_ERROR_IS_OK(result)) {
    4081           0 :                 return result;
    4082             :         }
    4083             : 
    4084        1272 :         r->sharename         = lp_servicename(mem_ctx, lp_sub, snum);
    4085        1272 :         W_ERROR_HAVE_NO_MEMORY(r->sharename);
    4086        1272 :         r->portname          = talloc_strdup(mem_ctx, info2->portname);
    4087        1272 :         W_ERROR_HAVE_NO_MEMORY(r->portname);
    4088        1272 :         r->drivername                = talloc_strdup(mem_ctx, info2->drivername);
    4089        1272 :         W_ERROR_HAVE_NO_MEMORY(r->drivername);
    4090             : 
    4091        1272 :         if (info2->comment[0] == '\0') {
    4092         876 :                 r->comment   = lp_comment(mem_ctx, lp_sub, snum);
    4093             :         } else {
    4094         396 :                 r->comment   = talloc_strdup(mem_ctx, info2->comment);
    4095             :         }
    4096        1272 :         W_ERROR_HAVE_NO_MEMORY(r->comment);
    4097             : 
    4098        1272 :         r->location  = talloc_strdup(mem_ctx, info2->location);
    4099        1272 :         if (info2->location[0] == '\0') {
    4100        1192 :                 const char *loc = NULL;
    4101           0 :                 NTSTATUS nt_status;
    4102             : 
    4103        1192 :                 nt_status = printer_list_get_printer(mem_ctx,
    4104        1192 :                                                      info2->sharename,
    4105             :                                                      NULL,
    4106             :                                                      &loc,
    4107             :                                                      NULL);
    4108        1192 :                 if (NT_STATUS_IS_OK(nt_status)) {
    4109           0 :                         if (loc != NULL) {
    4110           0 :                                 r->location = talloc_strdup(mem_ctx, loc);
    4111             :                         }
    4112             :                 }
    4113             :         }
    4114        1272 :         W_ERROR_HAVE_NO_MEMORY(r->location);
    4115             : 
    4116        1272 :         r->sepfile           = talloc_strdup(mem_ctx, info2->sepfile);
    4117        1272 :         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
    4118        1272 :         r->printprocessor    = talloc_strdup(mem_ctx, info2->printprocessor);
    4119        1272 :         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
    4120        1272 :         r->datatype          = talloc_strdup(mem_ctx, info2->datatype);
    4121        1272 :         W_ERROR_HAVE_NO_MEMORY(r->datatype);
    4122        1272 :         r->parameters                = talloc_strdup(mem_ctx, info2->parameters);
    4123        1272 :         W_ERROR_HAVE_NO_MEMORY(r->parameters);
    4124             : 
    4125        1272 :         r->attributes                = info2->attributes;
    4126             : 
    4127        1272 :         r->priority          = info2->priority;
    4128        1272 :         r->defaultpriority   = info2->defaultpriority;
    4129        1272 :         r->starttime         = info2->starttime;
    4130        1272 :         r->untiltime         = info2->untiltime;
    4131        1272 :         r->status            = nt_printq_status(status.status);
    4132        1272 :         r->cjobs             = count;
    4133        1272 :         r->averageppm                = info2->averageppm;
    4134             : 
    4135        1272 :         if (info2->devmode != NULL) {
    4136        1186 :                 result = copy_devicemode(mem_ctx,
    4137        1186 :                                          info2->devmode,
    4138             :                                          &r->devmode);
    4139        1186 :                 if (!W_ERROR_IS_OK(result)) {
    4140           0 :                         return result;
    4141             :                 }
    4142          86 :         } else if (lp_default_devmode(snum)) {
    4143           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    4144           0 :                                                         info2->printername,
    4145             :                                                         &r->devmode);
    4146           0 :                 if (!W_ERROR_IS_OK(result)) {
    4147           0 :                         return result;
    4148             :                 }
    4149             :         } else {
    4150          86 :                 r->devmode = NULL;
    4151          86 :                 DEBUG(8,("Returning NULL Devicemode!\n"));
    4152             :         }
    4153             : 
    4154        1272 :         compose_devicemode_devicename(r->devmode, r->printername);
    4155             : 
    4156        1272 :         r->secdesc = NULL;
    4157             : 
    4158        1272 :         if (info2->secdesc != NULL) {
    4159             :                 /* don't use talloc_steal() here unless you do a deep steal of all
    4160             :                    the SEC_DESC members */
    4161             : 
    4162        1272 :                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
    4163        1272 :                 if (r->secdesc == NULL) {
    4164           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    4165             :                 }
    4166             :         }
    4167             : 
    4168        1272 :         return WERR_OK;
    4169             : }
    4170             : 
    4171             : /********************************************************************
    4172             :  * construct_printer_info3
    4173             :  * fill a spoolss_PrinterInfo3 struct
    4174             :  ********************************************************************/
    4175             : 
    4176         144 : static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
    4177             :                                       const struct spoolss_PrinterInfo2 *info2,
    4178             :                                       const char *servername,
    4179             :                                       struct spoolss_PrinterInfo3 *r,
    4180             :                                       int snum)
    4181             : {
    4182             :         /* These are the components of the SD we are returning. */
    4183             : 
    4184         144 :         if (info2->secdesc != NULL) {
    4185             :                 /* don't use talloc_steal() here unless you do a deep steal of all
    4186             :                    the SEC_DESC members */
    4187             : 
    4188         144 :                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
    4189         144 :                 if (r->secdesc == NULL) {
    4190           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    4191             :                 }
    4192             :         }
    4193             : 
    4194         144 :         return WERR_OK;
    4195             : }
    4196             : 
    4197             : /********************************************************************
    4198             :  * construct_printer_info4
    4199             :  * fill a spoolss_PrinterInfo4 struct
    4200             :  ********************************************************************/
    4201             : 
    4202         168 : static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
    4203             :                                       const struct spoolss_PrinterInfo2 *info2,
    4204             :                                       const char *servername,
    4205             :                                       struct spoolss_PrinterInfo4 *r,
    4206             :                                       int snum)
    4207             : {
    4208           0 :         WERROR result;
    4209             : 
    4210         168 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4211         168 :         if (!W_ERROR_IS_OK(result)) {
    4212           0 :                 return result;
    4213             :         }
    4214             : 
    4215         168 :         if (servername) {
    4216           8 :                 r->servername        = talloc_strdup(mem_ctx, servername);
    4217           8 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    4218             :         } else {
    4219         160 :                 r->servername = NULL;
    4220             :         }
    4221             : 
    4222         168 :         r->attributes        = info2->attributes;
    4223             : 
    4224         168 :         return WERR_OK;
    4225             : }
    4226             : 
    4227             : /********************************************************************
    4228             :  * construct_printer_info5
    4229             :  * fill a spoolss_PrinterInfo5 struct
    4230             :  ********************************************************************/
    4231             : 
    4232         168 : static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
    4233             :                                       const struct spoolss_PrinterInfo2 *info2,
    4234             :                                       const char *servername,
    4235             :                                       struct spoolss_PrinterInfo5 *r,
    4236             :                                       int snum)
    4237             : {
    4238           0 :         WERROR result;
    4239             : 
    4240         168 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4241         168 :         if (!W_ERROR_IS_OK(result)) {
    4242           0 :                 return result;
    4243             :         }
    4244             : 
    4245         168 :         r->portname  = talloc_strdup(mem_ctx, info2->portname);
    4246         168 :         W_ERROR_HAVE_NO_MEMORY(r->portname);
    4247             : 
    4248         168 :         r->attributes        = info2->attributes;
    4249             : 
    4250             :         /*
    4251             :          * These two are not used by NT+ according to MSDN. However the values
    4252             :          * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
    4253             :          */
    4254         168 :         r->device_not_selected_timeout               = 0xafc8; /* 45 sec */
    4255         168 :         r->transmission_retry_timeout                = 0xafc8; /* 45 sec */
    4256             : 
    4257         168 :         return WERR_OK;
    4258             : }
    4259             : 
    4260             : /********************************************************************
    4261             :  * construct_printer_info_6
    4262             :  * fill a spoolss_PrinterInfo6 struct
    4263             :  ********************************************************************/
    4264             : 
    4265          88 : static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
    4266             :                                       struct messaging_context *msg_ctx,
    4267             :                                       const struct spoolss_PrinterInfo2 *info2,
    4268             :                                       const char *servername,
    4269             :                                       struct spoolss_PrinterInfo6 *r,
    4270             :                                       int snum)
    4271             : {
    4272           0 :         print_status_struct status;
    4273             : 
    4274          88 :         print_queue_length(msg_ctx, snum, &status);
    4275             : 
    4276          88 :         r->status = nt_printq_status(status.status);
    4277             : 
    4278          88 :         return WERR_OK;
    4279             : }
    4280             : 
    4281             : /********************************************************************
    4282             :  * construct_printer_info7
    4283             :  * fill a spoolss_PrinterInfo7 struct
    4284             :  ********************************************************************/
    4285             : 
    4286         112 : static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
    4287             :                                       struct messaging_context *msg_ctx,
    4288             :                                       const char *servername,
    4289             :                                       struct spoolss_PrinterInfo7 *r,
    4290             :                                       int snum)
    4291             : {
    4292           0 :         const struct loadparm_substitution *lp_sub =
    4293         112 :                 loadparm_s3_global_substitution();
    4294           0 :         const struct auth_session_info *session_info;
    4295         112 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    4296           0 :         char *printer;
    4297           0 :         WERROR werr;
    4298         112 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    4299         112 :         if (tmp_ctx == NULL) {
    4300           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4301             :         }
    4302             : 
    4303         112 :         session_info = get_session_info_system();
    4304         112 :         SMB_ASSERT(session_info != NULL);
    4305             : 
    4306         112 :         printer = lp_servicename(tmp_ctx, lp_sub, snum);
    4307         112 :         if (printer == NULL) {
    4308           0 :                 DEBUG(0, ("invalid printer snum %d\n", snum));
    4309           0 :                 werr = WERR_INVALID_PARAMETER;
    4310           0 :                 goto out_tmp_free;
    4311             :         }
    4312             : 
    4313         112 :         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
    4314             :                                  servername, printer, &pinfo2)) {
    4315           0 :                 struct GUID guid;
    4316           0 :                 char *guidstr;
    4317           0 :                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
    4318             :                                            printer, &guid);
    4319           0 :                 if (!W_ERROR_IS_OK(werr)) {
    4320             :                         /*
    4321             :                          * If we do not have a GUID entry in the registry, then
    4322             :                          * try to retrieve it from AD and store it now.
    4323             :                          */
    4324           0 :                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
    4325             :                                                         &guid);
    4326           0 :                         if (!W_ERROR_IS_OK(werr)) {
    4327           0 :                                 DBG_NOTICE("Failed to retrieve GUID for "
    4328             :                                            "printer [%s] from AD - %s\n",
    4329             :                                            printer,
    4330             :                                            win_errstr(werr));
    4331           0 :                                 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
    4332             :                                         /*
    4333             :                                          * If we did not find it in AD, then it
    4334             :                                          * is unpublished and we should reflect
    4335             :                                          * this in the registry and return
    4336             :                                          * success.
    4337             :                                          */
    4338           0 :                                         DBG_WARNING("Unpublish printer [%s]\n",
    4339             :                                                     pinfo2->sharename);
    4340           0 :                                         nt_printer_publish(tmp_ctx,
    4341             :                                                            session_info,
    4342             :                                                            msg_ctx,
    4343             :                                                            pinfo2,
    4344             :                                                            DSPRINT_UNPUBLISH);
    4345           0 :                                         r->guid = talloc_strdup(mem_ctx, "");
    4346           0 :                                         r->action = DSPRINT_UNPUBLISH;
    4347             : 
    4348           0 :                                         if (r->guid == NULL) {
    4349           0 :                                                 werr = WERR_NOT_ENOUGH_MEMORY;
    4350             :                                         } else {
    4351           0 :                                                 werr = WERR_OK;
    4352             :                                         }
    4353             :                                 }
    4354           0 :                                 goto out_tmp_free;
    4355             :                         }
    4356             : 
    4357           0 :                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
    4358           0 :                         if (!W_ERROR_IS_OK(werr)) {
    4359           0 :                                 DEBUG(3, ("failed to store printer %s guid\n",
    4360             :                                           printer));
    4361             :                         }
    4362             :                 }
    4363             : 
    4364             :                 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
    4365           0 :                 guidstr = GUID_string2(mem_ctx, &guid);
    4366           0 :                 if (guidstr == NULL) {
    4367           0 :                         werr = WERR_NOT_ENOUGH_MEMORY;
    4368           0 :                         goto out_tmp_free;
    4369             :                 }
    4370             :                 /* Convert GUID string to uppercase otherwise printers
    4371             :                  * are pruned */
    4372           0 :                 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
    4373           0 :                 r->action = DSPRINT_PUBLISH;
    4374             : 
    4375           0 :                 TALLOC_FREE(guidstr);
    4376             :         } else {
    4377         112 :                 r->guid = talloc_strdup(mem_ctx, "");
    4378         112 :                 r->action = DSPRINT_UNPUBLISH;
    4379             :         }
    4380         112 :         if (r->guid == NULL) {
    4381           0 :                 werr = WERR_NOT_ENOUGH_MEMORY;
    4382           0 :                 goto out_tmp_free;
    4383             :         }
    4384             : 
    4385         112 :         werr = WERR_OK;
    4386         112 : out_tmp_free:
    4387         112 :         talloc_free(tmp_ctx);
    4388         112 :         return werr;
    4389             : }
    4390             : 
    4391             : /********************************************************************
    4392             :  * construct_printer_info8
    4393             :  * fill a spoolss_PrinterInfo8 struct
    4394             :  ********************************************************************/
    4395             : 
    4396        1664 : static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
    4397             :                                       const struct spoolss_PrinterInfo2 *info2,
    4398             :                                       const char *servername,
    4399             :                                       struct spoolss_DeviceModeInfo *r,
    4400             :                                       int snum)
    4401             : {
    4402           0 :         WERROR result;
    4403           0 :         const char *printername;
    4404             : 
    4405        1664 :         result = create_printername(mem_ctx, servername, info2->printername, &printername);
    4406        1664 :         if (!W_ERROR_IS_OK(result)) {
    4407           0 :                 return result;
    4408             :         }
    4409             : 
    4410        1664 :         if (info2->devmode != NULL) {
    4411        1656 :                 result = copy_devicemode(mem_ctx,
    4412        1656 :                                          info2->devmode,
    4413             :                                          &r->devmode);
    4414        1656 :                 if (!W_ERROR_IS_OK(result)) {
    4415           0 :                         return result;
    4416             :                 }
    4417           8 :         } else if (lp_default_devmode(snum)) {
    4418           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    4419           0 :                                                         info2->printername,
    4420             :                                                         &r->devmode);
    4421           0 :                 if (!W_ERROR_IS_OK(result)) {
    4422           0 :                         return result;
    4423             :                 }
    4424             :         } else {
    4425           8 :                 r->devmode = NULL;
    4426           8 :                 DEBUG(8,("Returning NULL Devicemode!\n"));
    4427             :         }
    4428             : 
    4429        1664 :         compose_devicemode_devicename(r->devmode, printername);
    4430             : 
    4431        1664 :         return WERR_OK;
    4432             : }
    4433             : 
    4434             : /********************************************************************
    4435             :  Spoolss_enumprinters.
    4436             : ********************************************************************/
    4437             : 
    4438         180 : static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
    4439             :                                            const struct auth_session_info *session_info,
    4440             :                                            struct messaging_context *msg_ctx,
    4441             :                                            const char *servername,
    4442             :                                            uint32_t level,
    4443             :                                            uint32_t flags,
    4444             :                                            union spoolss_PrinterInfo **info_p,
    4445             :                                            uint32_t *count_p)
    4446             : {
    4447           0 :         int snum;
    4448           0 :         int n_services;
    4449         180 :         union spoolss_PrinterInfo *info = NULL;
    4450         180 :         uint32_t count = 0;
    4451         180 :         WERROR result = WERR_OK;
    4452         180 :         struct dcerpc_binding_handle *b = NULL;
    4453         180 :         TALLOC_CTX *tmp_ctx = NULL;
    4454             : 
    4455         180 :         tmp_ctx = talloc_new(mem_ctx);
    4456         180 :         if (!tmp_ctx) {
    4457           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4458             :         }
    4459             : 
    4460             :         /*
    4461             :          * printer shares are updated on client enumeration. The background
    4462             :          * printer process updates printer_list.tdb at regular intervals.
    4463             :          */
    4464         180 :         become_root();
    4465         180 :         delete_and_reload_printers();
    4466         180 :         unbecome_root();
    4467             : 
    4468         180 :         n_services = lp_numservices();
    4469         180 :         *count_p = 0;
    4470         180 :         *info_p = NULL;
    4471             : 
    4472       12230 :         for (snum = 0; snum < n_services; snum++) {
    4473             : 
    4474           0 :                 const char *printer;
    4475           0 :                 struct spoolss_PrinterInfo2 *info2;
    4476             : 
    4477       12050 :                 if (!snum_is_shared_printer(snum)) {
    4478       11070 :                         continue;
    4479             :                 }
    4480             : 
    4481         980 :                 printer = lp_const_servicename(snum);
    4482             : 
    4483         980 :                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
    4484             :                         printer, snum));
    4485             : 
    4486         980 :                 if (b == NULL) {
    4487         180 :                         result = winreg_printer_binding_handle(tmp_ctx,
    4488             :                                                                session_info,
    4489             :                                                                msg_ctx,
    4490             :                                                                &b);
    4491         180 :                         if (!W_ERROR_IS_OK(result)) {
    4492           0 :                                 goto out;
    4493             :                         }
    4494             :                 }
    4495             : 
    4496         980 :                 result = winreg_create_printer(tmp_ctx, b,
    4497             :                                                printer);
    4498         980 :                 if (!W_ERROR_IS_OK(result)) {
    4499           0 :                         goto out;
    4500             :                 }
    4501             : 
    4502         980 :                 info = talloc_realloc(tmp_ctx, info,
    4503             :                                             union spoolss_PrinterInfo,
    4504             :                                             count + 1);
    4505         980 :                 if (!info) {
    4506           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    4507           0 :                         goto out;
    4508             :                 }
    4509             : 
    4510         980 :                 result = winreg_get_printer(tmp_ctx, b,
    4511             :                                             printer, &info2);
    4512         980 :                 if (!W_ERROR_IS_OK(result)) {
    4513           0 :                         goto out;
    4514             :                 }
    4515             : 
    4516         980 :                 switch (level) {
    4517          40 :                 case 0:
    4518          40 :                         result = construct_printer_info0(info, session_info,
    4519             :                                                          msg_ctx, info2,
    4520             :                                                          servername,
    4521          40 :                                                          &info[count].info0, snum);
    4522          40 :                         break;
    4523         440 :                 case 1:
    4524         440 :                         result = construct_printer_info1(info, info2, flags,
    4525             :                                                          servername,
    4526         440 :                                                          &info[count].info1, snum);
    4527         440 :                         break;
    4528         340 :                 case 2:
    4529         340 :                         result = construct_printer_info2(info, msg_ctx, info2,
    4530             :                                                          servername,
    4531         340 :                                                          &info[count].info2, snum);
    4532         340 :                         break;
    4533          80 :                 case 4:
    4534          80 :                         result = construct_printer_info4(info, info2,
    4535             :                                                          servername,
    4536          80 :                                                          &info[count].info4, snum);
    4537          80 :                         break;
    4538          80 :                 case 5:
    4539          80 :                         result = construct_printer_info5(info, info2,
    4540             :                                                          servername,
    4541          80 :                                                          &info[count].info5, snum);
    4542          80 :                         break;
    4543             : 
    4544           0 :                 default:
    4545           0 :                         result = WERR_INVALID_LEVEL;
    4546           0 :                         goto out;
    4547             :                 }
    4548             : 
    4549         980 :                 if (!W_ERROR_IS_OK(result)) {
    4550           0 :                         goto out;
    4551             :                 }
    4552             : 
    4553         980 :                 count++;
    4554             :         }
    4555             : 
    4556         180 : out:
    4557         180 :         if (W_ERROR_IS_OK(result)) {
    4558         180 :                 *info_p = talloc_move(mem_ctx, &info);
    4559         180 :                 *count_p = count;
    4560             :         }
    4561             : 
    4562         180 :         talloc_free(tmp_ctx);
    4563             : 
    4564         180 :         return result;
    4565             : }
    4566             : 
    4567             : /********************************************************************
    4568             :  * handle enumeration of printers at level 0
    4569             :  ********************************************************************/
    4570             : 
    4571           8 : static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
    4572             :                                   const struct auth_session_info *session_info,
    4573             :                                   struct messaging_context *msg_ctx,
    4574             :                                   uint32_t flags,
    4575             :                                   const char *servername,
    4576             :                                   union spoolss_PrinterInfo **info,
    4577             :                                   uint32_t *count)
    4578             : {
    4579           8 :         DEBUG(4,("enum_all_printers_info_0\n"));
    4580             : 
    4581           8 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4582             :                                             servername, 0, flags, info, count);
    4583             : }
    4584             : 
    4585             : 
    4586             : /********************************************************************
    4587             : ********************************************************************/
    4588             : 
    4589          72 : static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
    4590             :                                        const struct auth_session_info *session_info,
    4591             :                                        struct messaging_context *msg_ctx,
    4592             :                                        const char *servername,
    4593             :                                        uint32_t flags,
    4594             :                                        union spoolss_PrinterInfo **info,
    4595             :                                        uint32_t *count)
    4596             : {
    4597          72 :         DEBUG(4,("enum_all_printers_info_1\n"));
    4598             : 
    4599          72 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4600             :                                             servername, 1, flags, info, count);
    4601             : }
    4602             : 
    4603             : /********************************************************************
    4604             :  enum_all_printers_info_1_local.
    4605             : *********************************************************************/
    4606             : 
    4607          72 : static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
    4608             :                                              const struct auth_session_info *session_info,
    4609             :                                              struct messaging_context *msg_ctx,
    4610             :                                              const char *servername,
    4611             :                                              union spoolss_PrinterInfo **info,
    4612             :                                              uint32_t *count)
    4613             : {
    4614          72 :         DEBUG(4,("enum_all_printers_info_1_local\n"));
    4615             : 
    4616          72 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4617             :                                         servername, PRINTER_ENUM_ICON8, info, count);
    4618             : }
    4619             : 
    4620             : /********************************************************************
    4621             :  enum_all_printers_info_1_name.
    4622             : *********************************************************************/
    4623             : 
    4624           0 : static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
    4625             :                                             const struct auth_session_info *session_info,
    4626             :                                             struct messaging_context *msg_ctx,
    4627             :                                             const char *servername,
    4628             :                                             union spoolss_PrinterInfo **info,
    4629             :                                             uint32_t *count)
    4630             : {
    4631           0 :         const char *s = servername;
    4632             : 
    4633           0 :         DEBUG(4,("enum_all_printers_info_1_name\n"));
    4634             : 
    4635           0 :         if (servername != NULL &&
    4636           0 :             (servername[0] == '\\') && (servername[1] == '\\')) {
    4637           0 :                 s = servername + 2;
    4638             :         }
    4639             : 
    4640           0 :         if (!is_myname_or_ipaddr(s)) {
    4641           0 :                 return WERR_INVALID_NAME;
    4642             :         }
    4643             : 
    4644           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4645             :                                         servername, PRINTER_ENUM_ICON8, info, count);
    4646             : }
    4647             : 
    4648             : /********************************************************************
    4649             :  enum_all_printers_info_1_network.
    4650             : *********************************************************************/
    4651             : 
    4652           0 : static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
    4653             :                                                const struct auth_session_info *session_info,
    4654             :                                                struct messaging_context *msg_ctx,
    4655             :                                                const char *servername,
    4656             :                                                union spoolss_PrinterInfo **info,
    4657             :                                                uint32_t *count)
    4658             : {
    4659           0 :         const char *s = servername;
    4660             : 
    4661           0 :         DEBUG(4,("enum_all_printers_info_1_network\n"));
    4662             : 
    4663             :         /* If we respond to a enum_printers level 1 on our name with flags
    4664             :            set to PRINTER_ENUM_REMOTE with a list of printers then these
    4665             :            printers incorrectly appear in the APW browse list.
    4666             :            Specifically the printers for the server appear at the workgroup
    4667             :            level where all the other servers in the domain are
    4668             :            listed. Windows responds to this call with a
    4669             :            WERR_CAN_NOT_COMPLETE so we should do the same. */
    4670             : 
    4671           0 :         if (servername != NULL &&
    4672           0 :             (servername[0] == '\\') && (servername[1] == '\\')) {
    4673           0 :                  s = servername + 2;
    4674             :         }
    4675             : 
    4676           0 :         if (is_myname_or_ipaddr(s)) {
    4677           0 :                  return WERR_CAN_NOT_COMPLETE;
    4678             :         }
    4679             : 
    4680           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4681             :                                         servername, PRINTER_ENUM_NAME, info, count);
    4682             : }
    4683             : 
    4684             : /********************************************************************
    4685             :  * api_spoolss_enumprinters
    4686             :  *
    4687             :  * called from api_spoolss_enumprinters (see this to understand)
    4688             :  ********************************************************************/
    4689             : 
    4690          68 : static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
    4691             :                                        const struct auth_session_info *session_info,
    4692             :                                        struct messaging_context *msg_ctx,
    4693             :                                        const char *servername,
    4694             :                                        union spoolss_PrinterInfo **info,
    4695             :                                        uint32_t *count)
    4696             : {
    4697          68 :         DEBUG(4,("enum_all_printers_info_2\n"));
    4698             : 
    4699          68 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4700             :                                             servername, 2, 0, info, count);
    4701             : }
    4702             : 
    4703             : /********************************************************************
    4704             :  * handle enumeration of printers at level 1
    4705             :  ********************************************************************/
    4706             : 
    4707          72 : static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
    4708             :                                   const struct auth_session_info *session_info,
    4709             :                                   struct messaging_context *msg_ctx,
    4710             :                                   uint32_t flags,
    4711             :                                   const char *servername,
    4712             :                                   union spoolss_PrinterInfo **info,
    4713             :                                   uint32_t *count)
    4714             : {
    4715             :         /* Not all the flags are equals */
    4716             : 
    4717          72 :         if (flags & PRINTER_ENUM_LOCAL) {
    4718          72 :                 return enum_all_printers_info_1_local(mem_ctx, session_info,
    4719             :                                                       msg_ctx, servername, info, count);
    4720             :         }
    4721             : 
    4722           0 :         if (flags & PRINTER_ENUM_NAME) {
    4723           0 :                 return enum_all_printers_info_1_name(mem_ctx, session_info,
    4724             :                                                      msg_ctx, servername, info,
    4725             :                                                      count);
    4726             :         }
    4727             : 
    4728           0 :         if (flags & PRINTER_ENUM_NETWORK) {
    4729           0 :                 return enum_all_printers_info_1_network(mem_ctx, session_info,
    4730             :                                                         msg_ctx, servername, info,
    4731             :                                                         count);
    4732             :         }
    4733             : 
    4734           0 :         return WERR_OK; /* NT4sp5 does that */
    4735             : }
    4736             : 
    4737             : /********************************************************************
    4738             :  * handle enumeration of printers at level 2
    4739             :  ********************************************************************/
    4740             : 
    4741          68 : static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
    4742             :                                   const struct auth_session_info *session_info,
    4743             :                                   struct messaging_context *msg_ctx,
    4744             :                                   uint32_t flags,
    4745             :                                   const char *servername,
    4746             :                                   union spoolss_PrinterInfo **info,
    4747             :                                   uint32_t *count)
    4748             : {
    4749          68 :         if (flags & PRINTER_ENUM_LOCAL) {
    4750             : 
    4751          52 :                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
    4752             :                                                 servername,
    4753             :                                                 info, count);
    4754             :         }
    4755             : 
    4756          16 :         if (flags & PRINTER_ENUM_NAME) {
    4757          16 :                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
    4758           0 :                         return WERR_INVALID_NAME;
    4759             :                 }
    4760             : 
    4761          16 :                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
    4762             :                                                 servername,
    4763             :                                                 info, count);
    4764             :         }
    4765             : 
    4766           0 :         if (flags & PRINTER_ENUM_REMOTE) {
    4767           0 :                 return WERR_INVALID_LEVEL;
    4768             :         }
    4769             : 
    4770           0 :         return WERR_OK;
    4771             : }
    4772             : 
    4773             : /********************************************************************
    4774             :  * handle enumeration of printers at level 4
    4775             :  ********************************************************************/
    4776             : 
    4777          16 : static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
    4778             :                                   const struct auth_session_info *session_info,
    4779             :                                   struct messaging_context *msg_ctx,
    4780             :                                   uint32_t flags,
    4781             :                                   const char *servername,
    4782             :                                   union spoolss_PrinterInfo **info,
    4783             :                                   uint32_t *count)
    4784             : {
    4785          16 :         DEBUG(4,("enum_all_printers_info_4\n"));
    4786             : 
    4787          16 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4788             :                                             servername, 4, flags, info, count);
    4789             : }
    4790             : 
    4791             : 
    4792             : /********************************************************************
    4793             :  * handle enumeration of printers at level 5
    4794             :  ********************************************************************/
    4795             : 
    4796          16 : static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
    4797             :                                   const struct auth_session_info *session_info,
    4798             :                                   struct messaging_context *msg_ctx,
    4799             :                                   uint32_t flags,
    4800             :                                   const char *servername,
    4801             :                                   union spoolss_PrinterInfo **info,
    4802             :                                   uint32_t *count)
    4803             : {
    4804          16 :         DEBUG(4,("enum_all_printers_info_5\n"));
    4805             : 
    4806          16 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4807             :                                             servername, 5, flags, info, count);
    4808             : }
    4809             : 
    4810             : /****************************************************************
    4811             :  _spoolss_EnumPrinters
    4812             : ****************************************************************/
    4813             : 
    4814         180 : WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
    4815             :                              struct spoolss_EnumPrinters *r)
    4816             : {
    4817         180 :         const struct auth_session_info *session_info = get_session_info_system();
    4818           0 :         WERROR result;
    4819             : 
    4820             :         /* that's an [in out] buffer */
    4821             : 
    4822         180 :         if (!r->in.buffer && (r->in.offered != 0)) {
    4823           0 :                 return WERR_INVALID_PARAMETER;
    4824             :         }
    4825             : 
    4826         180 :         DEBUG(4,("_spoolss_EnumPrinters\n"));
    4827             : 
    4828         180 :         *r->out.needed = 0;
    4829         180 :         *r->out.count = 0;
    4830         180 :         *r->out.info = NULL;
    4831             : 
    4832             :         /*
    4833             :          * Level 1:
    4834             :          *          flags==PRINTER_ENUM_NAME
    4835             :          *           if name=="" then enumerates all printers
    4836             :          *           if name!="" then enumerate the printer
    4837             :          *          flags==PRINTER_ENUM_REMOTE
    4838             :          *          name is NULL, enumerate printers
    4839             :          * Level 2: name!="" enumerates printers, name can't be NULL
    4840             :          * Level 3: doesn't exist
    4841             :          * Level 4: does a local registry lookup
    4842             :          * Level 5: same as Level 2
    4843             :          */
    4844             : 
    4845         180 :         if (r->in.server && r->in.server[0] == '\0') {
    4846          80 :                 r->in.server = NULL;
    4847             :         }
    4848             : 
    4849         180 :         switch (r->in.level) {
    4850           8 :         case 0:
    4851           8 :                 result = enumprinters_level0(p->mem_ctx, session_info,
    4852             :                                              p->msg_ctx, r->in.flags,
    4853             :                                              r->in.server,
    4854             :                                              r->out.info, r->out.count);
    4855           8 :                 break;
    4856          72 :         case 1:
    4857          72 :                 result = enumprinters_level1(p->mem_ctx, session_info,
    4858             :                                              p->msg_ctx, r->in.flags,
    4859             :                                              r->in.server,
    4860             :                                              r->out.info, r->out.count);
    4861          72 :                 break;
    4862          68 :         case 2:
    4863          68 :                 result = enumprinters_level2(p->mem_ctx, session_info,
    4864             :                                              p->msg_ctx, r->in.flags,
    4865             :                                              r->in.server,
    4866             :                                              r->out.info, r->out.count);
    4867          68 :                 break;
    4868          16 :         case 4:
    4869          16 :                 result = enumprinters_level4(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          16 :         case 5:
    4875          16 :                 result = enumprinters_level5(p->mem_ctx, session_info,
    4876             :                                              p->msg_ctx, r->in.flags,
    4877             :                                              r->in.server,
    4878             :                                              r->out.info, r->out.count);
    4879          16 :                 break;
    4880           0 :         default:
    4881           0 :                 return WERR_INVALID_LEVEL;
    4882             :         }
    4883             : 
    4884         180 :         if (!W_ERROR_IS_OK(result)) {
    4885           0 :                 return result;
    4886             :         }
    4887             : 
    4888         180 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    4889             :                                                      spoolss_EnumPrinters,
    4890             :                                                      *r->out.info, r->in.level,
    4891             :                                                      *r->out.count);
    4892         180 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    4893         180 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    4894             : 
    4895         180 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    4896             : }
    4897             : 
    4898             : /****************************************************************
    4899             :  _spoolss_GetPrinter
    4900             : ****************************************************************/
    4901             : 
    4902        3512 : WERROR _spoolss_GetPrinter(struct pipes_struct *p,
    4903             :                            struct spoolss_GetPrinter *r)
    4904             : {
    4905        3512 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    4906        3512 :         struct spoolss_PrinterInfo2 *info2 = NULL;
    4907        3512 :         WERROR result = WERR_OK;
    4908           0 :         int snum;
    4909             : 
    4910             :         /* that's an [in out] buffer */
    4911             : 
    4912        3512 :         if (!r->in.buffer && (r->in.offered != 0)) {
    4913           0 :                 result = WERR_INVALID_PARAMETER;
    4914           0 :                 goto err_info_free;
    4915             :         }
    4916             : 
    4917        3512 :         *r->out.needed = 0;
    4918             : 
    4919        3512 :         if (Printer == NULL) {
    4920           0 :                 result = WERR_INVALID_HANDLE;
    4921           0 :                 goto err_info_free;
    4922             :         }
    4923             : 
    4924        3512 :         if (Printer->printer_type == SPLHND_SERVER) {
    4925             : 
    4926           0 :                 struct dcerpc_binding_handle *b;
    4927             : 
    4928          72 :                 if (r->in.level != 3) {
    4929          32 :                         result = WERR_INVALID_LEVEL;
    4930          32 :                         goto err_info_free;
    4931             :                 }
    4932             : 
    4933          40 :                 result = winreg_printer_binding_handle(p->mem_ctx,
    4934             :                                                        get_session_info_system(),
    4935             :                                                        p->msg_ctx,
    4936             :                                                        &b);
    4937          40 :                 if (!W_ERROR_IS_OK(result)) {
    4938           0 :                         goto err_info_free;
    4939             :                 }
    4940             : 
    4941          40 :                 result = winreg_get_printserver_secdesc(p->mem_ctx,
    4942             :                                                         b,
    4943          40 :                                                         &r->out.info->info3.secdesc);
    4944          40 :                 if (!W_ERROR_IS_OK(result)) {
    4945           0 :                         goto err_info_free;
    4946             :                 }
    4947             : 
    4948          40 :                 goto done;
    4949             :         }
    4950             : 
    4951        3440 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    4952           0 :                 result = WERR_INVALID_HANDLE;
    4953           0 :                 goto err_info_free;
    4954             :         }
    4955             : 
    4956        3440 :         result = winreg_get_printer_internal(p->mem_ctx,
    4957             :                                     get_session_info_system(),
    4958             :                                     p->msg_ctx,
    4959             :                                     lp_const_servicename(snum),
    4960             :                                     &info2);
    4961        3440 :         if (!W_ERROR_IS_OK(result)) {
    4962           0 :                 goto err_info_free;
    4963             :         }
    4964             : 
    4965        3440 :         switch (r->in.level) {
    4966         236 :         case 0:
    4967         236 :                 result = construct_printer_info0(p->mem_ctx,
    4968             :                                                  get_session_info_system(),
    4969             :                                                  p->msg_ctx,
    4970             :                                                  info2,
    4971             :                                                  Printer->servername,
    4972         236 :                                                  &r->out.info->info0,
    4973             :                                                  snum);
    4974         236 :                 break;
    4975          88 :         case 1:
    4976          88 :                 result = construct_printer_info1(p->mem_ctx, info2,
    4977             :                                                  PRINTER_ENUM_ICON8,
    4978             :                                                  Printer->servername,
    4979          88 :                                                  &r->out.info->info1, snum);
    4980          88 :                 break;
    4981         932 :         case 2:
    4982         932 :                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
    4983             :                                                  Printer->servername,
    4984         932 :                                                  &r->out.info->info2, snum);
    4985         932 :                 break;
    4986         144 :         case 3:
    4987         144 :                 result = construct_printer_info3(p->mem_ctx, info2,
    4988             :                                                  Printer->servername,
    4989         144 :                                                  &r->out.info->info3, snum);
    4990         144 :                 break;
    4991          88 :         case 4:
    4992          88 :                 result = construct_printer_info4(p->mem_ctx, info2,
    4993             :                                                  Printer->servername,
    4994          88 :                                                  &r->out.info->info4, snum);
    4995          88 :                 break;
    4996          88 :         case 5:
    4997          88 :                 result = construct_printer_info5(p->mem_ctx, info2,
    4998             :                                                  Printer->servername,
    4999          88 :                                                  &r->out.info->info5, snum);
    5000          88 :                 break;
    5001          88 :         case 6:
    5002          88 :                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
    5003             :                                                  Printer->servername,
    5004          88 :                                                  &r->out.info->info6, snum);
    5005          88 :                 break;
    5006         112 :         case 7:
    5007         112 :                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
    5008             :                                                  Printer->servername,
    5009         112 :                                                  &r->out.info->info7, snum);
    5010         112 :                 break;
    5011        1664 :         case 8:
    5012        1664 :                 result = construct_printer_info8(p->mem_ctx, info2,
    5013             :                                                  Printer->servername,
    5014        1664 :                                                  &r->out.info->info8, snum);
    5015        1664 :                 break;
    5016           0 :         default:
    5017           0 :                 result = WERR_INVALID_LEVEL;
    5018           0 :                 break;
    5019             :         }
    5020        3440 :         TALLOC_FREE(info2);
    5021             : 
    5022        3440 :         if (!W_ERROR_IS_OK(result)) {
    5023           0 :                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
    5024             :                           r->in.level, win_errstr(result)));
    5025           0 :                 goto err_info_free;
    5026             :         }
    5027        3440 :  done:
    5028        3480 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
    5029             :                                                r->out.info, r->in.level);
    5030        3480 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    5031             : 
    5032        3480 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    5033             : 
    5034          32 : err_info_free:
    5035          32 :         TALLOC_FREE(r->out.info);
    5036          32 :         return result;
    5037             : }
    5038             : 
    5039             : /********************************************************************
    5040             :  ********************************************************************/
    5041             : 
    5042             : #define FILL_DRIVER_STRING(mem_ctx, in, out) \
    5043             :         do { \
    5044             :                 if (in && strlen(in)) { \
    5045             :                         out = talloc_strdup(mem_ctx, in); \
    5046             :                 } else { \
    5047             :                         out = talloc_strdup(mem_ctx, ""); \
    5048             :                 } \
    5049             :                 W_ERROR_HAVE_NO_MEMORY(out); \
    5050             :         } while (0);
    5051             : 
    5052             : #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
    5053             :         do { \
    5054             :                 if (in && strlen(in)) { \
    5055             :                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
    5056             :                 } else { \
    5057             :                         out = talloc_strdup(mem_ctx, ""); \
    5058             :                 } \
    5059             :                 W_ERROR_HAVE_NO_MEMORY(out); \
    5060             :         } while (0);
    5061             : 
    5062           0 : static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
    5063             :                                                   const char **string_array,
    5064             :                                                   const char ***presult,
    5065             :                                                   const char *cservername,
    5066             :                                                   const char *arch,
    5067             :                                                   int version)
    5068             : {
    5069           0 :         size_t i;
    5070           0 :         size_t num_strings = 0;
    5071           0 :         const char **array = NULL;
    5072             : 
    5073           0 :         if (string_array == NULL) {
    5074           0 :                 return WERR_INVALID_PARAMETER;
    5075             :         }
    5076             : 
    5077           0 :         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
    5078           0 :                 const char *str = NULL;
    5079             : 
    5080           0 :                 if (cservername == NULL || arch == NULL) {
    5081           0 :                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
    5082             :                 } else {
    5083           0 :                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
    5084             :                 }
    5085             : 
    5086           0 :                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
    5087           0 :                         TALLOC_FREE(array);
    5088           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    5089             :                 }
    5090             :         }
    5091             : 
    5092           0 :         if (i > 0) {
    5093           0 :                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
    5094             :                              &array, &num_strings);
    5095             :         }
    5096             : 
    5097           0 :         if (presult != NULL) {
    5098           0 :                 *presult = array;
    5099             :         } else {
    5100           0 :                 talloc_free(array);
    5101             :         }
    5102             : 
    5103           0 :         return WERR_OK;
    5104             : }
    5105             : 
    5106             : /********************************************************************
    5107             :  * fill a spoolss_DriverInfo1 struct
    5108             :  ********************************************************************/
    5109             : 
    5110           0 : static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
    5111             :                                         struct spoolss_DriverInfo1 *r,
    5112             :                                         const struct spoolss_DriverInfo8 *driver,
    5113             :                                         const char *servername)
    5114             : {
    5115           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5116           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5117             : 
    5118           0 :         return WERR_OK;
    5119             : }
    5120             : 
    5121             : /********************************************************************
    5122             :  * fill a spoolss_DriverInfo2 struct
    5123             :  ********************************************************************/
    5124             : 
    5125           0 : static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
    5126             :                                         struct spoolss_DriverInfo2 *r,
    5127             :                                         const struct spoolss_DriverInfo8 *driver,
    5128             :                                         const char *servername)
    5129             : 
    5130             : {
    5131           0 :         const char *cservername = canon_servername(servername);
    5132             : 
    5133           0 :         r->version           = driver->version;
    5134             : 
    5135           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5136           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5137           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5138           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5139             : 
    5140           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5141             :                                driver->architecture,
    5142             :                                driver->version,
    5143             :                                driver->driver_path,
    5144           0 :                                r->driver_path);
    5145             : 
    5146           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5147             :                                driver->architecture,
    5148             :                                driver->version,
    5149             :                                driver->data_file,
    5150           0 :                                r->data_file);
    5151             : 
    5152           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5153             :                                driver->architecture,
    5154             :                                driver->version,
    5155             :                                driver->config_file,
    5156           0 :                                r->config_file);
    5157             : 
    5158           0 :         return WERR_OK;
    5159             : }
    5160             : 
    5161             : /********************************************************************
    5162             :  * fill a spoolss_DriverInfo3 struct
    5163             :  ********************************************************************/
    5164             : 
    5165           0 : static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
    5166             :                                         struct spoolss_DriverInfo3 *r,
    5167             :                                         const struct spoolss_DriverInfo8 *driver,
    5168             :                                         const char *servername)
    5169             : {
    5170           0 :         const char *cservername = canon_servername(servername);
    5171             : 
    5172           0 :         r->version           = driver->version;
    5173             : 
    5174           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5175           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5176           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5177           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5178             : 
    5179           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5180             :                                driver->architecture,
    5181             :                                driver->version,
    5182             :                                driver->driver_path,
    5183           0 :                                r->driver_path);
    5184             : 
    5185           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5186             :                                driver->architecture,
    5187             :                                driver->version,
    5188             :                                driver->data_file,
    5189           0 :                                r->data_file);
    5190             : 
    5191           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5192             :                                driver->architecture,
    5193             :                                driver->version,
    5194             :                                driver->config_file,
    5195           0 :                                r->config_file);
    5196             : 
    5197           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5198             :                                driver->architecture,
    5199             :                                driver->version,
    5200             :                                driver->help_file,
    5201           0 :                                r->help_file);
    5202             : 
    5203           0 :         FILL_DRIVER_STRING(mem_ctx,
    5204             :                            driver->monitor_name,
    5205           0 :                            r->monitor_name);
    5206             : 
    5207           0 :         FILL_DRIVER_STRING(mem_ctx,
    5208             :                            driver->default_datatype,
    5209           0 :                            r->default_datatype);
    5210             : 
    5211           0 :         return string_array_from_driver_info(mem_ctx,
    5212           0 :                                              driver->dependent_files,
    5213             :                                              &r->dependent_files,
    5214             :                                              cservername,
    5215           0 :                                              driver->architecture,
    5216           0 :                                              driver->version);
    5217             : }
    5218             : 
    5219             : /********************************************************************
    5220             :  * fill a spoolss_DriverInfo4 struct
    5221             :  ********************************************************************/
    5222             : 
    5223           0 : static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
    5224             :                                         struct spoolss_DriverInfo4 *r,
    5225             :                                         const struct spoolss_DriverInfo8 *driver,
    5226             :                                         const char *servername)
    5227             : {
    5228           0 :         const char *cservername = canon_servername(servername);
    5229           0 :         WERROR result;
    5230             : 
    5231           0 :         r->version           = driver->version;
    5232             : 
    5233           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5234           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5235           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5236           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5237             : 
    5238           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5239             :                                driver->architecture,
    5240             :                                driver->version,
    5241             :                                driver->driver_path,
    5242           0 :                                r->driver_path);
    5243             : 
    5244           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5245             :                                driver->architecture,
    5246             :                                driver->version,
    5247             :                                driver->data_file,
    5248           0 :                                r->data_file);
    5249             : 
    5250           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5251             :                                driver->architecture,
    5252             :                                driver->version,
    5253             :                                driver->config_file,
    5254           0 :                                r->config_file);
    5255             : 
    5256           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5257             :                                driver->architecture,
    5258             :                                driver->version,
    5259             :                                driver->help_file,
    5260           0 :                                r->help_file);
    5261             : 
    5262           0 :         result = string_array_from_driver_info(mem_ctx,
    5263           0 :                                                driver->dependent_files,
    5264             :                                                &r->dependent_files,
    5265             :                                                cservername,
    5266           0 :                                                driver->architecture,
    5267           0 :                                                driver->version);
    5268           0 :         if (!W_ERROR_IS_OK(result)) {
    5269           0 :                 return result;
    5270             :         }
    5271             : 
    5272           0 :         FILL_DRIVER_STRING(mem_ctx,
    5273             :                            driver->monitor_name,
    5274           0 :                            r->monitor_name);
    5275             : 
    5276           0 :         FILL_DRIVER_STRING(mem_ctx,
    5277             :                            driver->default_datatype,
    5278           0 :                            r->default_datatype);
    5279             : 
    5280             : 
    5281           0 :         result = string_array_from_driver_info(mem_ctx,
    5282           0 :                                                driver->previous_names,
    5283             :                                                &r->previous_names,
    5284             :                                                NULL, NULL, 0);
    5285             : 
    5286           0 :         return result;
    5287             : }
    5288             : 
    5289             : /********************************************************************
    5290             :  * fill a spoolss_DriverInfo5 struct
    5291             :  ********************************************************************/
    5292             : 
    5293           0 : static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
    5294             :                                         struct spoolss_DriverInfo5 *r,
    5295             :                                         const struct spoolss_DriverInfo8 *driver,
    5296             :                                         const char *servername)
    5297             : {
    5298           0 :         const char *cservername = canon_servername(servername);
    5299             : 
    5300           0 :         r->version           = driver->version;
    5301             : 
    5302           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5303           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5304           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5305           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5306             : 
    5307           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5308             :                                driver->architecture,
    5309             :                                driver->version,
    5310             :                                driver->driver_path,
    5311           0 :                                r->driver_path);
    5312             : 
    5313           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5314             :                                driver->architecture,
    5315             :                                driver->version,
    5316             :                                driver->data_file,
    5317           0 :                                r->data_file);
    5318             : 
    5319           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5320             :                                driver->architecture,
    5321             :                                driver->version,
    5322             :                                driver->config_file,
    5323           0 :                                r->config_file);
    5324             : 
    5325           0 :         r->driver_attributes = 0;
    5326           0 :         r->config_version    = 0;
    5327           0 :         r->driver_version    = 0;
    5328             : 
    5329           0 :         return WERR_OK;
    5330             : }
    5331             : /********************************************************************
    5332             :  * fill a spoolss_DriverInfo6 struct
    5333             :  ********************************************************************/
    5334             : 
    5335           0 : static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
    5336             :                                         struct spoolss_DriverInfo6 *r,
    5337             :                                         const struct spoolss_DriverInfo8 *driver,
    5338             :                                         const char *servername)
    5339             : {
    5340           0 :         const char *cservername = canon_servername(servername);
    5341           0 :         WERROR result;
    5342             : 
    5343           0 :         r->version           = driver->version;
    5344             : 
    5345           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5346           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5347           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5348           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5349             : 
    5350           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5351             :                                driver->architecture,
    5352             :                                driver->version,
    5353             :                                driver->driver_path,
    5354           0 :                                r->driver_path);
    5355             : 
    5356           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5357             :                                driver->architecture,
    5358             :                                driver->version,
    5359             :                                driver->data_file,
    5360           0 :                                r->data_file);
    5361             : 
    5362           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5363             :                                driver->architecture,
    5364             :                                driver->version,
    5365             :                                driver->config_file,
    5366           0 :                                r->config_file);
    5367             : 
    5368           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5369             :                                driver->architecture,
    5370             :                                driver->version,
    5371             :                                driver->help_file,
    5372           0 :                                r->help_file);
    5373             : 
    5374           0 :         FILL_DRIVER_STRING(mem_ctx,
    5375             :                            driver->monitor_name,
    5376           0 :                            r->monitor_name);
    5377             : 
    5378           0 :         FILL_DRIVER_STRING(mem_ctx,
    5379             :                            driver->default_datatype,
    5380           0 :                            r->default_datatype);
    5381             : 
    5382           0 :         result = string_array_from_driver_info(mem_ctx,
    5383           0 :                                                driver->dependent_files,
    5384             :                                                &r->dependent_files,
    5385             :                                                cservername,
    5386           0 :                                                driver->architecture,
    5387           0 :                                                driver->version);
    5388           0 :         if (!W_ERROR_IS_OK(result)) {
    5389           0 :                 return result;
    5390             :         }
    5391             : 
    5392           0 :         result = string_array_from_driver_info(mem_ctx,
    5393           0 :                                                driver->previous_names,
    5394             :                                                &r->previous_names,
    5395             :                                                NULL, NULL, 0);
    5396           0 :         if (!W_ERROR_IS_OK(result)) {
    5397           0 :                 return result;
    5398             :         }
    5399             : 
    5400           0 :         r->driver_date               = driver->driver_date;
    5401           0 :         r->driver_version    = driver->driver_version;
    5402             : 
    5403           0 :         FILL_DRIVER_STRING(mem_ctx,
    5404             :                            driver->manufacturer_name,
    5405           0 :                            r->manufacturer_name);
    5406           0 :         FILL_DRIVER_STRING(mem_ctx,
    5407             :                            driver->manufacturer_url,
    5408           0 :                            r->manufacturer_url);
    5409           0 :         FILL_DRIVER_STRING(mem_ctx,
    5410             :                            driver->hardware_id,
    5411           0 :                            r->hardware_id);
    5412           0 :         FILL_DRIVER_STRING(mem_ctx,
    5413             :                            driver->provider,
    5414           0 :                            r->provider);
    5415             : 
    5416           0 :         return WERR_OK;
    5417             : }
    5418             : 
    5419             : /********************************************************************
    5420             :  * fill a spoolss_DriverInfo8 struct
    5421             :  ********************************************************************/
    5422             : 
    5423           0 : static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
    5424             :                                         struct spoolss_DriverInfo8 *r,
    5425             :                                         const struct spoolss_DriverInfo8 *driver,
    5426             :                                         const char *servername)
    5427             : {
    5428           0 :         const char *cservername = canon_servername(servername);
    5429           0 :         WERROR result;
    5430             : 
    5431           0 :         r->version           = driver->version;
    5432             : 
    5433           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5434           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5435           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5436           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5437             : 
    5438           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5439             :                                driver->architecture,
    5440             :                                driver->version,
    5441             :                                driver->driver_path,
    5442           0 :                                r->driver_path);
    5443             : 
    5444           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5445             :                                driver->architecture,
    5446             :                                driver->version,
    5447             :                                driver->data_file,
    5448           0 :                                r->data_file);
    5449             : 
    5450           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5451             :                                driver->architecture,
    5452             :                                driver->version,
    5453             :                                driver->config_file,
    5454           0 :                                r->config_file);
    5455             : 
    5456           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5457             :                                driver->architecture,
    5458             :                                driver->version,
    5459             :                                driver->help_file,
    5460           0 :                                r->help_file);
    5461             : 
    5462           0 :         FILL_DRIVER_STRING(mem_ctx,
    5463             :                            driver->monitor_name,
    5464           0 :                            r->monitor_name);
    5465             : 
    5466           0 :         FILL_DRIVER_STRING(mem_ctx,
    5467             :                            driver->default_datatype,
    5468           0 :                            r->default_datatype);
    5469             : 
    5470           0 :         result = string_array_from_driver_info(mem_ctx,
    5471           0 :                                                driver->dependent_files,
    5472             :                                                &r->dependent_files,
    5473             :                                                cservername,
    5474           0 :                                                driver->architecture,
    5475           0 :                                                driver->version);
    5476           0 :         if (!W_ERROR_IS_OK(result)) {
    5477           0 :                 return result;
    5478             :         }
    5479             : 
    5480           0 :         result = string_array_from_driver_info(mem_ctx,
    5481           0 :                                                driver->previous_names,
    5482             :                                                &r->previous_names,
    5483             :                                                NULL, NULL, 0);
    5484           0 :         if (!W_ERROR_IS_OK(result)) {
    5485           0 :                 return result;
    5486             :         }
    5487             : 
    5488           0 :         r->driver_date               = driver->driver_date;
    5489           0 :         r->driver_version    = driver->driver_version;
    5490             : 
    5491           0 :         FILL_DRIVER_STRING(mem_ctx,
    5492             :                            driver->manufacturer_name,
    5493           0 :                            r->manufacturer_name);
    5494           0 :         FILL_DRIVER_STRING(mem_ctx,
    5495             :                            driver->manufacturer_url,
    5496           0 :                            r->manufacturer_url);
    5497           0 :         FILL_DRIVER_STRING(mem_ctx,
    5498             :                            driver->hardware_id,
    5499           0 :                            r->hardware_id);
    5500           0 :         FILL_DRIVER_STRING(mem_ctx,
    5501             :                            driver->provider,
    5502           0 :                            r->provider);
    5503             : 
    5504           0 :         FILL_DRIVER_STRING(mem_ctx,
    5505             :                            driver->print_processor,
    5506           0 :                            r->print_processor);
    5507           0 :         FILL_DRIVER_STRING(mem_ctx,
    5508             :                            driver->vendor_setup,
    5509           0 :                            r->vendor_setup);
    5510             : 
    5511           0 :         result = string_array_from_driver_info(mem_ctx,
    5512           0 :                                                driver->color_profiles,
    5513             :                                                &r->color_profiles,
    5514             :                                                NULL, NULL, 0);
    5515           0 :         if (!W_ERROR_IS_OK(result)) {
    5516           0 :                 return result;
    5517             :         }
    5518             : 
    5519           0 :         FILL_DRIVER_STRING(mem_ctx,
    5520             :                            driver->inf_path,
    5521           0 :                            r->inf_path);
    5522             : 
    5523           0 :         r->printer_driver_attributes = driver->printer_driver_attributes;
    5524             : 
    5525           0 :         result = string_array_from_driver_info(mem_ctx,
    5526           0 :                                                driver->core_driver_dependencies,
    5527             :                                                &r->core_driver_dependencies,
    5528             :                                                NULL, NULL, 0);
    5529           0 :         if (!W_ERROR_IS_OK(result)) {
    5530           0 :                 return result;
    5531             :         }
    5532             : 
    5533           0 :         r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
    5534           0 :         r->min_inbox_driver_ver_version      = driver->min_inbox_driver_ver_version;
    5535             : 
    5536           0 :         return WERR_OK;
    5537             : }
    5538             : 
    5539             : #if 0 /* disabled until marshalling issues are resolved - gd */
    5540             : /********************************************************************
    5541             :  ********************************************************************/
    5542             : 
    5543             : static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
    5544             :                                           struct spoolss_DriverFileInfo *r,
    5545             :                                           const char *cservername,
    5546             :                                           const char *file_name,
    5547             :                                           enum spoolss_DriverFileType file_type,
    5548             :                                           uint32_t file_version)
    5549             : {
    5550             :         r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
    5551             :                                           cservername, file_name);
    5552             :         W_ERROR_HAVE_NO_MEMORY(r->file_name);
    5553             :         r->file_type = file_type;
    5554             :         r->file_version      = file_version;
    5555             : 
    5556             :         return WERR_OK;
    5557             : }
    5558             : 
    5559             : /********************************************************************
    5560             :  ********************************************************************/
    5561             : 
    5562             : static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
    5563             :                                                  const struct spoolss_DriverInfo8 *driver,
    5564             :                                                  const char *cservername,
    5565             :                                                  struct spoolss_DriverFileInfo **info_p,
    5566             :                                                  uint32_t *count_p)
    5567             : {
    5568             :         struct spoolss_DriverFileInfo *info = NULL;
    5569             :         uint32_t count = 0;
    5570             :         WERROR result;
    5571             :         uint32_t i;
    5572             : 
    5573             :         *info_p = NULL;
    5574             :         *count_p = 0;
    5575             : 
    5576             :         if (strlen(driver->driver_path)) {
    5577             :                 info = talloc_realloc(mem_ctx, info,
    5578             :                                             struct spoolss_DriverFileInfo,
    5579             :                                             count + 1);
    5580             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5581             :                 result = fill_spoolss_DriverFileInfo(info,
    5582             :                                                      &info[count],
    5583             :                                                      cservername,
    5584             :                                                      driver->driver_path,
    5585             :                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
    5586             :                                                      0);
    5587             :                 W_ERROR_NOT_OK_RETURN(result);
    5588             :                 count++;
    5589             :         }
    5590             : 
    5591             :         if (strlen(driver->config_file)) {
    5592             :                 info = talloc_realloc(mem_ctx, info,
    5593             :                                             struct spoolss_DriverFileInfo,
    5594             :                                             count + 1);
    5595             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5596             :                 result = fill_spoolss_DriverFileInfo(info,
    5597             :                                                      &info[count],
    5598             :                                                      cservername,
    5599             :                                                      driver->config_file,
    5600             :                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
    5601             :                                                      0);
    5602             :                 W_ERROR_NOT_OK_RETURN(result);
    5603             :                 count++;
    5604             :         }
    5605             : 
    5606             :         if (strlen(driver->data_file)) {
    5607             :                 info = talloc_realloc(mem_ctx, info,
    5608             :                                             struct spoolss_DriverFileInfo,
    5609             :                                             count + 1);
    5610             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5611             :                 result = fill_spoolss_DriverFileInfo(info,
    5612             :                                                      &info[count],
    5613             :                                                      cservername,
    5614             :                                                      driver->data_file,
    5615             :                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
    5616             :                                                      0);
    5617             :                 W_ERROR_NOT_OK_RETURN(result);
    5618             :                 count++;
    5619             :         }
    5620             : 
    5621             :         if (strlen(driver->help_file)) {
    5622             :                 info = talloc_realloc(mem_ctx, info,
    5623             :                                             struct spoolss_DriverFileInfo,
    5624             :                                             count + 1);
    5625             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5626             :                 result = fill_spoolss_DriverFileInfo(info,
    5627             :                                                      &info[count],
    5628             :                                                      cservername,
    5629             :                                                      driver->help_file,
    5630             :                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
    5631             :                                                      0);
    5632             :                 W_ERROR_NOT_OK_RETURN(result);
    5633             :                 count++;
    5634             :         }
    5635             : 
    5636             :         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
    5637             :                 info = talloc_realloc(mem_ctx, info,
    5638             :                                             struct spoolss_DriverFileInfo,
    5639             :                                             count + 1);
    5640             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5641             :                 result = fill_spoolss_DriverFileInfo(info,
    5642             :                                                      &info[count],
    5643             :                                                      cservername,
    5644             :                                                      driver->dependent_files[i],
    5645             :                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
    5646             :                                                      0);
    5647             :                 W_ERROR_NOT_OK_RETURN(result);
    5648             :                 count++;
    5649             :         }
    5650             : 
    5651             :         *info_p = info;
    5652             :         *count_p = count;
    5653             : 
    5654             :         return WERR_OK;
    5655             : }
    5656             : 
    5657             : /********************************************************************
    5658             :  * fill a spoolss_DriverInfo101 struct
    5659             :  ********************************************************************/
    5660             : 
    5661             : static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
    5662             :                                           struct spoolss_DriverInfo101 *r,
    5663             :                                           const struct spoolss_DriverInfo8 *driver,
    5664             :                                           const char *servername)
    5665             : {
    5666             :         const char *cservername = canon_servername(servername);
    5667             :         WERROR result;
    5668             : 
    5669             :         r->version           = driver->version;
    5670             : 
    5671             :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5672             :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5673             :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5674             :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5675             : 
    5676             :         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
    5677             :                                                     cservername,
    5678             :                                                     &r->file_info,
    5679             :                                                     &r->file_count);
    5680             :         if (!W_ERROR_IS_OK(result)) {
    5681             :                 return result;
    5682             :         }
    5683             : 
    5684             :         FILL_DRIVER_STRING(mem_ctx,
    5685             :                            driver->monitor_name,
    5686             :                            r->monitor_name);
    5687             : 
    5688             :         FILL_DRIVER_STRING(mem_ctx,
    5689             :                            driver->default_datatype,
    5690             :                            r->default_datatype);
    5691             : 
    5692             :         result = string_array_from_driver_info(mem_ctx,
    5693             :                                                driver->previous_names,
    5694             :                                                &r->previous_names,
    5695             :                                                NULL, NULL, 0);
    5696             :         if (!W_ERROR_IS_OK(result)) {
    5697             :                 return result;
    5698             :         }
    5699             : 
    5700             :         r->driver_date               = driver->driver_date;
    5701             :         r->driver_version    = driver->driver_version;
    5702             : 
    5703             :         FILL_DRIVER_STRING(mem_ctx,
    5704             :                            driver->manufacturer_name,
    5705             :                            r->manufacturer_name);
    5706             :         FILL_DRIVER_STRING(mem_ctx,
    5707             :                            driver->manufacturer_url,
    5708             :                            r->manufacturer_url);
    5709             :         FILL_DRIVER_STRING(mem_ctx,
    5710             :                            driver->hardware_id,
    5711             :                            r->hardware_id);
    5712             :         FILL_DRIVER_STRING(mem_ctx,
    5713             :                            driver->provider,
    5714             :                            r->provider);
    5715             : 
    5716             :         return WERR_OK;
    5717             : }
    5718             : #endif
    5719             : /********************************************************************
    5720             :  ********************************************************************/
    5721             : 
    5722           4 : static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
    5723             :                                                   const struct auth_session_info *session_info,
    5724             :                                                   struct messaging_context *msg_ctx,
    5725             :                                                   uint32_t level,
    5726             :                                                   union spoolss_DriverInfo *r,
    5727             :                                                   int snum,
    5728             :                                                   const char *servername,
    5729             :                                                   const char *architecture,
    5730             :                                                   uint32_t version)
    5731             : {
    5732           4 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    5733           0 :         struct spoolss_DriverInfo8 *driver;
    5734           0 :         WERROR result;
    5735           0 :         struct dcerpc_binding_handle *b;
    5736           4 :         TALLOC_CTX *tmp_ctx = NULL;
    5737             : 
    5738           4 :         if (level == 101) {
    5739           4 :                 return WERR_INVALID_LEVEL;
    5740             :         }
    5741             : 
    5742           0 :         tmp_ctx = talloc_new(mem_ctx);
    5743           0 :         if (!tmp_ctx) {
    5744           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    5745             :         }
    5746             : 
    5747           0 :         result = winreg_printer_binding_handle(tmp_ctx,
    5748             :                                                session_info,
    5749             :                                                msg_ctx,
    5750             :                                                &b);
    5751           0 :         if (!W_ERROR_IS_OK(result)) {
    5752           0 :                 goto done;
    5753             :         }
    5754             : 
    5755           0 :         result = winreg_get_printer(tmp_ctx, b,
    5756             :                                     lp_const_servicename(snum),
    5757             :                                     &pinfo2);
    5758           0 :         if (!W_ERROR_IS_OK(result)) {
    5759           0 :                 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
    5760             :                         lp_const_servicename(snum), win_errstr(result));
    5761           0 :                 result = WERR_INVALID_PRINTER_NAME;
    5762           0 :                 goto done;
    5763             :         }
    5764             : 
    5765           0 :         if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
    5766           0 :                 result = WERR_UNKNOWN_PRINTER_DRIVER;
    5767           0 :                 goto done;
    5768             :         }
    5769             : 
    5770           0 :         DBG_INFO("Construct printer driver [%s] for [%s]\n",
    5771             :                  pinfo2->drivername,
    5772             :                  pinfo2->sharename);
    5773             : 
    5774           0 :         result = winreg_get_driver(tmp_ctx, b,
    5775             :                                    architecture,
    5776           0 :                                    pinfo2->drivername, version, &driver);
    5777             : 
    5778           0 :         DBG_INFO("winreg_get_driver() status: %s\n",
    5779             :                  win_errstr(result));
    5780             : 
    5781           0 :         if (!W_ERROR_IS_OK(result)) {
    5782             :                 /*
    5783             :                  * Is this a W2k client ?
    5784             :                  */
    5785             : 
    5786           0 :                 if (version < 3) {
    5787           0 :                         result = WERR_UNKNOWN_PRINTER_DRIVER;
    5788           0 :                         goto done;
    5789             :                 }
    5790             : 
    5791             :                 /* Yes - try again with a WinNT driver. */
    5792           0 :                 version = 2;
    5793           0 :                 result = winreg_get_driver(tmp_ctx, b,
    5794             :                                            architecture,
    5795           0 :                                            pinfo2->drivername,
    5796             :                                            version, &driver);
    5797           0 :                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
    5798             :                         win_errstr(result)));
    5799           0 :                 if (!W_ERROR_IS_OK(result)) {
    5800           0 :                         result = WERR_UNKNOWN_PRINTER_DRIVER;
    5801           0 :                         goto done;
    5802             :                 }
    5803             :         }
    5804             : 
    5805             :         /* these are allocated on mem_ctx and not tmp_ctx because they are
    5806             :          * the 'return value' and need to outlive this call */
    5807           0 :         switch (level) {
    5808           0 :         case 1:
    5809           0 :                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
    5810           0 :                 break;
    5811           0 :         case 2:
    5812           0 :                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
    5813           0 :                 break;
    5814           0 :         case 3:
    5815           0 :                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
    5816           0 :                 break;
    5817           0 :         case 4:
    5818           0 :                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
    5819           0 :                 break;
    5820           0 :         case 5:
    5821           0 :                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
    5822           0 :                 break;
    5823           0 :         case 6:
    5824           0 :                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
    5825           0 :                 break;
    5826           0 :         case 8:
    5827           0 :                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
    5828           0 :                 break;
    5829             : #if 0 /* disabled until marshalling issues are resolved - gd */
    5830             :         case 101:
    5831             :                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
    5832             :                 break;
    5833             : #endif
    5834           0 :         default:
    5835           0 :                 result = WERR_INVALID_LEVEL;
    5836           0 :                 break;
    5837             :         }
    5838             : 
    5839           0 : done:
    5840           0 :         talloc_free(tmp_ctx);
    5841           0 :         return result;
    5842             : }
    5843             : 
    5844             : /****************************************************************
    5845             :  _spoolss_GetPrinterDriver2
    5846             : ****************************************************************/
    5847             : 
    5848           4 : WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
    5849             :                                   struct spoolss_GetPrinterDriver2 *r)
    5850             : {
    5851           0 :         struct printer_handle *printer;
    5852           0 :         WERROR result;
    5853           4 :         uint32_t version = r->in.client_major_version;
    5854             : 
    5855           0 :         int snum;
    5856             : 
    5857             :         /* that's an [in out] buffer */
    5858             : 
    5859           4 :         if (!r->in.buffer && (r->in.offered != 0)) {
    5860           0 :                 result = WERR_INVALID_PARAMETER;
    5861           0 :                 goto err_info_free;
    5862             :         }
    5863             : 
    5864           4 :         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
    5865             : 
    5866           4 :         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
    5867           0 :                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
    5868           0 :                 result = WERR_INVALID_PRINTER_NAME;
    5869           0 :                 goto err_info_free;
    5870             :         }
    5871             : 
    5872           4 :         *r->out.needed = 0;
    5873           4 :         *r->out.server_major_version = 0;
    5874           4 :         *r->out.server_minor_version = 0;
    5875             : 
    5876           4 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    5877           0 :                 result = WERR_INVALID_HANDLE;
    5878           0 :                 goto err_info_free;
    5879             :         }
    5880             : 
    5881           4 :         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
    5882           0 :                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
    5883             :                         "downgrading to v3\n"));
    5884           0 :                 version = SPOOLSS_DRIVER_VERSION_200X;
    5885             :         }
    5886             : 
    5887           4 :         result = construct_printer_driver_info_level(p->mem_ctx,
    5888             :                                                      get_session_info_system(),
    5889             :                                                      p->msg_ctx,
    5890             :                                                      r->in.level, r->out.info,
    5891             :                                                      snum, printer->servername,
    5892             :                                                      r->in.architecture,
    5893             :                                                      version);
    5894           4 :         if (!W_ERROR_IS_OK(result)) {
    5895           4 :                 goto err_info_free;
    5896             :         }
    5897             : 
    5898           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
    5899             :                                                r->out.info, r->in.level);
    5900           0 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    5901             : 
    5902           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    5903             : 
    5904           4 : err_info_free:
    5905           4 :         TALLOC_FREE(r->out.info);
    5906           4 :         return result;
    5907             : }
    5908             : 
    5909             : 
    5910             : /****************************************************************
    5911             :  _spoolss_StartPagePrinter
    5912             : ****************************************************************/
    5913             : 
    5914        1920 : WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
    5915             :                                  struct spoolss_StartPagePrinter *r)
    5916             : {
    5917        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5918             : 
    5919        1920 :         if (!Printer) {
    5920           0 :                 DEBUG(3,("_spoolss_StartPagePrinter: "
    5921             :                         "Error in startpageprinter printer handle\n"));
    5922           0 :                 return WERR_INVALID_HANDLE;
    5923             :         }
    5924             : 
    5925        1920 :         Printer->page_started = true;
    5926        1920 :         return WERR_OK;
    5927             : }
    5928             : 
    5929             : /****************************************************************
    5930             :  _spoolss_EndPagePrinter
    5931             : ****************************************************************/
    5932             : 
    5933        1920 : WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
    5934             :                                struct spoolss_EndPagePrinter *r)
    5935             : {
    5936           0 :         int snum;
    5937             : 
    5938        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5939             : 
    5940        1920 :         if (!Printer) {
    5941           0 :                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
    5942             :                         OUR_HANDLE(r->in.handle)));
    5943           0 :                 return WERR_INVALID_HANDLE;
    5944             :         }
    5945             : 
    5946        1920 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    5947           0 :                 return WERR_INVALID_HANDLE;
    5948             : 
    5949        1920 :         Printer->page_started = false;
    5950        1920 :         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
    5951             : 
    5952        1920 :         return WERR_OK;
    5953             : }
    5954             : 
    5955             : /****************************************************************
    5956             :  _spoolss_StartDocPrinter
    5957             : ****************************************************************/
    5958             : 
    5959         668 : WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
    5960             :                                 struct spoolss_StartDocPrinter *r)
    5961             : {
    5962         668 :         struct dcesrv_call_state *dce_call = p->dce_call;
    5963         668 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    5964           0 :         const struct tsocket_address *remote_address =
    5965         668 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    5966           0 :         struct auth_session_info *session_info =
    5967         668 :                 dcesrv_call_session_info(dce_call);
    5968           0 :         struct spoolss_DocumentInfo1 *info_1;
    5969           0 :         int snum;
    5970         668 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5971           0 :         WERROR werr;
    5972           0 :         char *rhost;
    5973           0 :         int rc;
    5974             : 
    5975         668 :         if (!Printer) {
    5976           0 :                 DEBUG(2,("_spoolss_StartDocPrinter: "
    5977             :                         "Invalid handle (%s:%u:%u)\n",
    5978             :                         OUR_HANDLE(r->in.handle)));
    5979           0 :                 return WERR_INVALID_HANDLE;
    5980             :         }
    5981             : 
    5982         668 :         if (Printer->jobid) {
    5983           0 :                 DEBUG(2, ("_spoolss_StartDocPrinter: "
    5984             :                           "StartDocPrinter called twice! "
    5985             :                           "(existing jobid = %d)\n", Printer->jobid));
    5986           0 :                 return WERR_INVALID_HANDLE;
    5987             :         }
    5988             : 
    5989         668 :         if (r->in.info_ctr->level != 1) {
    5990           0 :                 return WERR_INVALID_LEVEL;
    5991             :         }
    5992             : 
    5993         668 :         info_1 = r->in.info_ctr->info.info1;
    5994             : 
    5995             :         /*
    5996             :          * a nice thing with NT is it doesn't listen to what you tell it.
    5997             :          * when asked to send _only_ RAW data, it tries to send data
    5998             :          * in EMF format.
    5999             :          *
    6000             :          * So I add checks like in NT Server ...
    6001             :          */
    6002             : 
    6003         668 :         if (info_1->datatype) {
    6004             :                 /*
    6005             :                  * The v4 driver model used in Windows 8 declares print jobs
    6006             :                  * intended to bypass the XPS processing layer by setting
    6007             :                  * datatype to "XPS_PASS" instead of "RAW".
    6008             :                  */
    6009         668 :                 if ((strcmp(info_1->datatype, "RAW") != 0)
    6010         224 :                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
    6011           0 :                         *r->out.job_id = 0;
    6012           0 :                         return WERR_INVALID_DATATYPE;
    6013             :                 }
    6014             :         }
    6015             : 
    6016             :         /* get the share number of the printer */
    6017         668 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    6018           0 :                 return WERR_INVALID_HANDLE;
    6019             :         }
    6020             : 
    6021         668 :         rc = get_remote_hostname(remote_address,
    6022             :                                  &rhost,
    6023             :                                  p->mem_ctx);
    6024         668 :         if (rc < 0) {
    6025           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6026             :         }
    6027         668 :         if (strequal(rhost,"UNKNOWN")) {
    6028         668 :                 rhost = tsocket_address_inet_addr_string(remote_address,
    6029             :                                                          p->mem_ctx);
    6030         668 :                 if (rhost == NULL) {
    6031           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    6032             :                 }
    6033             :         }
    6034             : 
    6035         668 :         werr = print_job_start(session_info,
    6036             :                                p->msg_ctx,
    6037             :                                rhost,
    6038             :                                snum,
    6039             :                                info_1->document_name,
    6040             :                                info_1->output_file,
    6041             :                                Printer->devmode,
    6042             :                                &Printer->jobid);
    6043             : 
    6044             :         /* An error occurred in print_job_start() so return an appropriate
    6045             :            NT error code. */
    6046             : 
    6047         668 :         if (!W_ERROR_IS_OK(werr)) {
    6048           0 :                 return werr;
    6049             :         }
    6050             : 
    6051         668 :         Printer->document_started = true;
    6052         668 :         *r->out.job_id = Printer->jobid;
    6053             : 
    6054         668 :         return WERR_OK;
    6055             : }
    6056             : 
    6057             : /****************************************************************
    6058             :  _spoolss_EndDocPrinter
    6059             : ****************************************************************/
    6060             : 
    6061         668 : WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
    6062             :                               struct spoolss_EndDocPrinter *r)
    6063             : {
    6064         668 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6065           0 :         NTSTATUS status;
    6066           0 :         int snum;
    6067             : 
    6068         668 :         if (!Printer) {
    6069           0 :                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
    6070             :                         OUR_HANDLE(r->in.handle)));
    6071           0 :                 return WERR_INVALID_HANDLE;
    6072             :         }
    6073             : 
    6074         668 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    6075           0 :                 return WERR_INVALID_HANDLE;
    6076             :         }
    6077             : 
    6078         668 :         Printer->document_started = false;
    6079         668 :         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
    6080         668 :         if (!NT_STATUS_IS_OK(status)) {
    6081         292 :                 DEBUG(2, ("_spoolss_EndDocPrinter: "
    6082             :                           "print_job_end failed [%s]\n",
    6083             :                           nt_errstr(status)));
    6084             :         }
    6085             : 
    6086         668 :         Printer->jobid = 0;
    6087         668 :         return ntstatus_to_werror(status);
    6088             : }
    6089             : 
    6090             : /****************************************************************
    6091             :  _spoolss_WritePrinter
    6092             : ****************************************************************/
    6093             : 
    6094        1920 : WERROR _spoolss_WritePrinter(struct pipes_struct *p,
    6095             :                              struct spoolss_WritePrinter *r)
    6096             : {
    6097           0 :         ssize_t buffer_written;
    6098           0 :         int snum;
    6099        1920 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6100             : 
    6101        1920 :         if (!Printer) {
    6102           0 :                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
    6103             :                         OUR_HANDLE(r->in.handle)));
    6104           0 :                 *r->out.num_written = r->in._data_size;
    6105           0 :                 return WERR_INVALID_HANDLE;
    6106             :         }
    6107             : 
    6108        1920 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    6109           0 :                 return WERR_INVALID_HANDLE;
    6110             : 
    6111             :         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
    6112        1920 :         buffer_written = print_job_write(global_event_context(),p->msg_ctx,
    6113             :                                                    snum, Printer->jobid,
    6114        1920 :                                                    (const char *)r->in.data.data,
    6115        1920 :                                                    (size_t)r->in._data_size);
    6116        1920 :         if (buffer_written == (ssize_t)-1) {
    6117           0 :                 *r->out.num_written = 0;
    6118           0 :                 if (errno == ENOSPC)
    6119           0 :                         return WERR_NO_SPOOL_SPACE;
    6120             :                 else
    6121           0 :                         return WERR_ACCESS_DENIED;
    6122             :         }
    6123             : 
    6124        1920 :         *r->out.num_written = r->in._data_size;
    6125             : 
    6126        1920 :         return WERR_OK;
    6127             : }
    6128             : 
    6129             : /********************************************************************
    6130             :  * api_spoolss_getprinter
    6131             :  * called from the spoolss dispatcher
    6132             :  *
    6133             :  ********************************************************************/
    6134             : 
    6135         104 : static WERROR control_printer(struct policy_handle *handle, uint32_t command,
    6136             :                               struct pipes_struct *p)
    6137             : {
    6138         104 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6139           0 :         struct auth_session_info *session_info =
    6140         104 :                 dcesrv_call_session_info(dce_call);
    6141           0 :         int snum;
    6142         104 :         WERROR errcode = WERR_INVALID_FUNCTION;
    6143         104 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6144             : 
    6145         104 :         if (!Printer) {
    6146           0 :                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
    6147             :                         OUR_HANDLE(handle)));
    6148           0 :                 return WERR_INVALID_HANDLE;
    6149             :         }
    6150             : 
    6151         104 :         if (!get_printer_snum(p, handle, &snum, NULL))
    6152           0 :                 return WERR_INVALID_HANDLE;
    6153             : 
    6154         104 :         switch (command) {
    6155          52 :         case SPOOLSS_PRINTER_CONTROL_PAUSE:
    6156          52 :                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
    6157          52 :                 break;
    6158          40 :         case SPOOLSS_PRINTER_CONTROL_RESUME:
    6159             :         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
    6160          40 :                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
    6161          40 :                 break;
    6162          12 :         case SPOOLSS_PRINTER_CONTROL_PURGE:
    6163          12 :                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
    6164          12 :                 break;
    6165           0 :         default:
    6166           0 :                 return WERR_INVALID_LEVEL;
    6167             :         }
    6168             : 
    6169         104 :         return errcode;
    6170             : }
    6171             : 
    6172             : 
    6173             : /****************************************************************
    6174             :  _spoolss_AbortPrinter
    6175             :  * From MSDN: "Deletes printer's spool file if printer is configured
    6176             :  * for spooling"
    6177             : ****************************************************************/
    6178             : 
    6179           0 : WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
    6180             :                              struct spoolss_AbortPrinter *r)
    6181             : {
    6182           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6183           0 :         struct auth_session_info *session_info =
    6184           0 :                 dcesrv_call_session_info(dce_call);
    6185           0 :         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6186           0 :         int             snum;
    6187           0 :         WERROR          errcode = WERR_OK;
    6188             : 
    6189           0 :         if (!Printer) {
    6190           0 :                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
    6191             :                         OUR_HANDLE(r->in.handle)));
    6192           0 :                 return WERR_INVALID_HANDLE;
    6193             :         }
    6194             : 
    6195           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    6196           0 :                 return WERR_INVALID_HANDLE;
    6197             : 
    6198           0 :         if (!Printer->document_started) {
    6199           0 :                 return WERR_SPL_NO_STARTDOC;
    6200             :         }
    6201             : 
    6202           0 :         errcode = print_job_delete(session_info,
    6203             :                                    p->msg_ctx,
    6204             :                                    snum,
    6205             :                                    Printer->jobid);
    6206             : 
    6207           0 :         return errcode;
    6208             : }
    6209             : 
    6210             : /********************************************************************
    6211             :  * called by spoolss_api_setprinter
    6212             :  * when updating a printer description
    6213             :  ********************************************************************/
    6214             : 
    6215         120 : static WERROR update_printer_sec(struct policy_handle *handle,
    6216             :                                  struct pipes_struct *p,
    6217             :                                  struct sec_desc_buf *secdesc_ctr)
    6218             : {
    6219         120 :         struct spoolss_security_descriptor *new_secdesc = NULL;
    6220         120 :         struct spoolss_security_descriptor *old_secdesc = NULL;
    6221         120 :         const char *printer = NULL;
    6222           0 :         WERROR result;
    6223         120 :         int snum = -1;
    6224         120 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6225           0 :         struct dcerpc_binding_handle *b;
    6226         120 :         TALLOC_CTX *tmp_ctx = NULL;
    6227         120 :         bool ok = false;
    6228             : 
    6229         120 :         if (!Printer) {
    6230           0 :                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
    6231             :                          OUR_HANDLE(handle)));
    6232             : 
    6233           0 :                 result = WERR_INVALID_HANDLE;
    6234           0 :                 goto done;
    6235             :         }
    6236             : 
    6237         120 :         if (secdesc_ctr == NULL) {
    6238           0 :                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
    6239           0 :                 result = WERR_INVALID_PARAMETER;
    6240           0 :                 goto done;
    6241             :         }
    6242             : 
    6243         120 :         switch (Printer->printer_type) {
    6244           8 :         case SPLHND_SERVER:
    6245           8 :                 break;
    6246         112 :         case SPLHND_PRINTER:
    6247         112 :                 if (!get_printer_snum(p, handle, &snum, NULL)) {
    6248           0 :                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
    6249             :                                  OUR_HANDLE(handle)));
    6250           0 :                         result = WERR_INVALID_HANDLE;
    6251           0 :                         goto done;
    6252             :                 }
    6253         112 :                 printer = lp_const_servicename(snum);
    6254         112 :                 break;
    6255           0 :         default:
    6256           0 :                 break;
    6257             :         }
    6258             : 
    6259             :         /* Check the user has permissions to change the security
    6260             :            descriptor.  By experimentation with two NT machines, the user
    6261             :            requires Full Access to the printer to change security
    6262             :            information. */
    6263             : 
    6264         120 :         switch (Printer->printer_type) {
    6265           8 :         case SPLHND_SERVER:
    6266           8 :                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
    6267           8 :                 break;
    6268         112 :         case SPLHND_PRINTER:
    6269         112 :                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
    6270         112 :                 break;
    6271           0 :         default:
    6272           0 :                 break;
    6273             :         }
    6274             : 
    6275         120 :         if (!ok) {
    6276           0 :                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
    6277             :                         "(access_granted: 0x%08x)\n", Printer->access_granted));
    6278           0 :                 result = WERR_ACCESS_DENIED;
    6279           0 :                 goto done;
    6280             :         }
    6281             : 
    6282         120 :         tmp_ctx = talloc_new(p->mem_ctx);
    6283         120 :         if (!tmp_ctx) {
    6284           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6285             :         }
    6286             : 
    6287         120 :         result = winreg_printer_binding_handle(tmp_ctx,
    6288             :                                                get_session_info_system(),
    6289             :                                                p->msg_ctx,
    6290             :                                                &b);
    6291         120 :         if (!W_ERROR_IS_OK(result)) {
    6292           0 :                 goto done;
    6293             :         }
    6294             : 
    6295             :         /* NT seems to like setting the security descriptor even though
    6296             :            nothing may have actually changed. */
    6297             : 
    6298         120 :         if (printer != NULL) {
    6299         112 :                 result = winreg_get_printer_secdesc(tmp_ctx, b,
    6300             :                                                     printer,
    6301             :                                                     &old_secdesc);
    6302             :         } else {
    6303           8 :                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
    6304             :                                                         &old_secdesc);
    6305             :         }
    6306         120 :         if (!W_ERROR_IS_OK(result)) {
    6307           0 :                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
    6308           0 :                 result = WERR_INVALID_HANDLE;
    6309           0 :                 goto done;
    6310             :         }
    6311             : 
    6312         120 :         if (DEBUGLEVEL >= 10) {
    6313           0 :                 struct dom_sid_buf buf;
    6314           0 :                 struct security_acl *the_acl;
    6315           0 :                 int i;
    6316             : 
    6317           0 :                 the_acl = old_secdesc->dacl;
    6318           0 :                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
    6319             :                            printer, the_acl->num_aces));
    6320             : 
    6321           0 :                 for (i = 0; i < the_acl->num_aces; i++) {
    6322           0 :                         DEBUG(10, ("%s 0x%08x\n",
    6323             :                                    dom_sid_str_buf(
    6324             :                                            &the_acl->aces[i].trustee,
    6325             :                                            &buf),
    6326             :                                   the_acl->aces[i].access_mask));
    6327             :                 }
    6328             : 
    6329           0 :                 the_acl = secdesc_ctr->sd->dacl;
    6330             : 
    6331           0 :                 if (the_acl) {
    6332           0 :                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
    6333             :                                    printer, the_acl->num_aces));
    6334             : 
    6335           0 :                         for (i = 0; i < the_acl->num_aces; i++) {
    6336           0 :                                 DEBUG(10, ("%s 0x%08x\n",
    6337             :                                            dom_sid_str_buf(
    6338             :                                                    &the_acl->aces[i].trustee,
    6339             :                                                    &buf),
    6340             :                                            the_acl->aces[i].access_mask));
    6341             :                         }
    6342             :                 } else {
    6343           0 :                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
    6344             :                 }
    6345             :         }
    6346             : 
    6347         120 :         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
    6348         120 :         if (new_secdesc == NULL) {
    6349           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    6350           0 :                 goto done;
    6351             :         }
    6352             : 
    6353         120 :         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
    6354          56 :                 result = WERR_OK;
    6355          56 :                 goto done;
    6356             :         }
    6357             : 
    6358          64 :         if (printer != NULL) {
    6359          56 :                 result = winreg_set_printer_secdesc(tmp_ctx, b,
    6360             :                                                     printer,
    6361             :                                                     new_secdesc);
    6362             :         } else {
    6363           8 :                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
    6364             :                                                         new_secdesc);
    6365             :         }
    6366             : 
    6367         120 : done:
    6368         120 :         talloc_free(tmp_ctx);
    6369         120 :         return result;
    6370             : }
    6371             : 
    6372             : /********************************************************************
    6373             :  Canonicalize printer info from a client
    6374             :  ********************************************************************/
    6375             : 
    6376         100 : static bool check_printer_ok(TALLOC_CTX *mem_ctx,
    6377             :                              struct spoolss_SetPrinterInfo2 *info2,
    6378             :                              int snum)
    6379             : {
    6380           0 :         fstring printername;
    6381           0 :         const char *p;
    6382             : 
    6383         100 :         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
    6384             :                 "portname=%s drivername=%s comment=%s location=%s\n",
    6385             :                 info2->servername, info2->printername, info2->sharename,
    6386             :                 info2->portname, info2->drivername, info2->comment,
    6387             :                 info2->location));
    6388             : 
    6389             :         /* we force some elements to "correct" values */
    6390         100 :         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
    6391         100 :         if (info2->servername == NULL) {
    6392           0 :                 return false;
    6393             :         }
    6394         100 :         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
    6395         100 :         if (info2->sharename == NULL) {
    6396           0 :                 return false;
    6397             :         }
    6398             : 
    6399             :         /* check to see if we allow printername != sharename */
    6400         100 :         if (lp_force_printername(snum)) {
    6401           0 :                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
    6402             :                                         lp_netbios_name(), info2->sharename);
    6403             :         } else {
    6404             :                 /* make sure printername is in \\server\printername format */
    6405         100 :                 fstrcpy(printername, info2->printername);
    6406         100 :                 p = printername;
    6407         100 :                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
    6408          56 :                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
    6409          56 :                                 p++;
    6410             :                 }
    6411             : 
    6412         100 :                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
    6413             :                                         lp_netbios_name(), p);
    6414             :         }
    6415         100 :         if (info2->printername == NULL) {
    6416           0 :                 return false;
    6417             :         }
    6418             : 
    6419         100 :         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
    6420         100 :         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
    6421             : 
    6422         100 :         return true;
    6423             : }
    6424             : 
    6425             : /****************************************************************************
    6426             : ****************************************************************************/
    6427             : 
    6428           0 : static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
    6429             : {
    6430           0 :         const struct loadparm_substitution *lp_sub =
    6431           0 :                 loadparm_s3_global_substitution();
    6432           0 :         char *cmd = lp_addport_command(talloc_tos(), lp_sub);
    6433           0 :         char *command = NULL;
    6434           0 :         int ret;
    6435           0 :         bool is_print_op = false;
    6436             : 
    6437           0 :         if ( !*cmd ) {
    6438           0 :                 return WERR_ACCESS_DENIED;
    6439             :         }
    6440             : 
    6441           0 :         command = talloc_asprintf(ctx,
    6442             :                         "%s \"%s\" \"%s\"", cmd, portname, uri );
    6443           0 :         if (!command) {
    6444           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6445             :         }
    6446             : 
    6447           0 :         if ( token )
    6448           0 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
    6449             : 
    6450           0 :         DEBUG(10,("Running [%s]\n", command));
    6451             : 
    6452             :         /********* BEGIN SePrintOperatorPrivilege **********/
    6453             : 
    6454           0 :         if ( is_print_op )
    6455           0 :                 become_root();
    6456             : 
    6457           0 :         ret = smbrun(command, NULL, NULL);
    6458             : 
    6459           0 :         if ( is_print_op )
    6460           0 :                 unbecome_root();
    6461             : 
    6462             :         /********* END SePrintOperatorPrivilege **********/
    6463             : 
    6464           0 :         DEBUGADD(10,("returned [%d]\n", ret));
    6465             : 
    6466           0 :         TALLOC_FREE(command);
    6467             : 
    6468           0 :         if ( ret != 0 ) {
    6469           0 :                 return WERR_ACCESS_DENIED;
    6470             :         }
    6471             : 
    6472           0 :         return WERR_OK;
    6473             : }
    6474             : 
    6475             : /****************************************************************************
    6476             : ****************************************************************************/
    6477             : 
    6478        4902 : static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
    6479             :                                    int snum)
    6480             : {
    6481             :         /*
    6482             :          * As we do not know if we are embedded in the file server process
    6483             :          * or not, we have to pretend that all shares are in use.
    6484             :          */
    6485        4902 :         return true;
    6486             : }
    6487             : 
    6488          66 : static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
    6489             :                              struct spoolss_SetPrinterInfo2 *info2,
    6490             :                              const char *remote_machine,
    6491             :                              struct messaging_context *msg_ctx)
    6492             : {
    6493           0 :         const struct loadparm_substitution *lp_sub =
    6494          66 :                 loadparm_s3_global_substitution();
    6495          66 :         char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
    6496           0 :         char **qlines;
    6497          66 :         char *command = NULL;
    6498           0 :         int numlines;
    6499           0 :         int ret;
    6500           0 :         int fd;
    6501          66 :         bool is_print_op = false;
    6502             : 
    6503          66 :         if (!remote_machine) {
    6504           0 :                 return false;
    6505             :         }
    6506             : 
    6507          66 :         command = talloc_asprintf(ctx,
    6508             :                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
    6509             :                         cmd, info2->printername, info2->sharename,
    6510             :                         info2->portname, info2->drivername,
    6511             :                         info2->location, info2->comment, remote_machine);
    6512          66 :         if (!command) {
    6513           0 :                 return false;
    6514             :         }
    6515             : 
    6516          66 :         if ( token )
    6517          66 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
    6518             : 
    6519          66 :         DEBUG(10,("Running [%s]\n", command));
    6520             : 
    6521             :         /********* BEGIN SePrintOperatorPrivilege **********/
    6522             : 
    6523          66 :         if ( is_print_op )
    6524           0 :                 become_root();
    6525             : 
    6526          66 :         ret = smbrun(command, &fd, NULL);
    6527          66 :         if (ret == 0) {
    6528             :                 /* Tell everyone we updated smb.conf. */
    6529          66 :                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
    6530             :         }
    6531             : 
    6532          66 :         if ( is_print_op )
    6533           0 :                 unbecome_root();
    6534             : 
    6535             :         /********* END SePrintOperatorPrivilege **********/
    6536             : 
    6537          66 :         DEBUGADD(10,("returned [%d]\n", ret));
    6538             : 
    6539          66 :         TALLOC_FREE(command);
    6540             : 
    6541          66 :         if ( ret != 0 ) {
    6542           0 :                 if (fd != -1)
    6543           0 :                         close(fd);
    6544           0 :                 return false;
    6545             :         }
    6546             : 
    6547             :         /* reload our services immediately */
    6548          66 :         become_root();
    6549          66 :         reload_services(NULL, spoolss_conn_snum_used, false);
    6550          66 :         unbecome_root();
    6551             : 
    6552          66 :         numlines = 0;
    6553             :         /* Get lines and convert them back to dos-codepage */
    6554          66 :         qlines = fd_lines_load(fd, &numlines, 0, NULL);
    6555          66 :         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
    6556          66 :         close(fd);
    6557             : 
    6558             :         /* Set the portname to what the script says the portname should be. */
    6559             :         /* but don't require anything to be return from the script exit a good error code */
    6560             : 
    6561          66 :         if (numlines) {
    6562             :                 /* Set the portname to what the script says the portname should be. */
    6563           0 :                 info2->portname = talloc_strdup(ctx, qlines[0]);
    6564           0 :                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
    6565             :         }
    6566             : 
    6567          66 :         TALLOC_FREE(qlines);
    6568          66 :         return true;
    6569             : }
    6570             : 
    6571         100 : static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
    6572             :                                const struct auth_session_info *session_info,
    6573             :                                struct messaging_context *msg_ctx,
    6574             :                                int snum,
    6575             :                                struct spoolss_SetPrinterInfo2 *printer,
    6576             :                                struct spoolss_PrinterInfo2 *old_printer)
    6577             : {
    6578         100 :         bool force_update = (old_printer == NULL);
    6579           0 :         const char *dnsdomname;
    6580           0 :         const char *longname;
    6581           0 :         const char *uncname;
    6582           0 :         const char *spooling;
    6583           0 :         DATA_BLOB buffer;
    6584         100 :         WERROR result = WERR_OK;
    6585           0 :         struct dcerpc_binding_handle *b;
    6586           0 :         TALLOC_CTX *tmp_ctx;
    6587           0 :         bool ok;
    6588             : 
    6589         100 :         tmp_ctx = talloc_new(mem_ctx);
    6590         100 :         if (!tmp_ctx) {
    6591           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6592             :         }
    6593             : 
    6594         100 :         result = winreg_printer_binding_handle(tmp_ctx,
    6595             :                                                session_info,
    6596             :                                                msg_ctx,
    6597             :                                                &b);
    6598         100 :         if (!W_ERROR_IS_OK(result)) {
    6599           0 :                 goto done;
    6600             :         }
    6601             : 
    6602         100 :         if (printer->drivername != NULL &&
    6603          84 :             (force_update ||
    6604          84 :              !strequal(printer->drivername, old_printer->drivername))) {
    6605          24 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
    6606          24 :                 if (!ok) {
    6607           0 :                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
    6608           0 :                         result = WERR_INVALID_DATA;
    6609           0 :                         goto done;
    6610             :                 }
    6611          24 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6612             :                                           printer->sharename,
    6613             :                                           SPOOL_DSSPOOLER_KEY,
    6614             :                                           SPOOL_REG_DRIVERNAME,
    6615             :                                           REG_SZ,
    6616             :                                           buffer.data,
    6617          24 :                                           buffer.length);
    6618          24 :                 if (!W_ERROR_IS_OK(result)) {
    6619           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
    6620           0 :                         goto done;
    6621             :                 }
    6622             : 
    6623          24 :                 if (!force_update) {
    6624           8 :                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
    6625             :                                 printer->drivername));
    6626             : 
    6627           8 :                         notify_printer_driver(global_event_context(), msg_ctx,
    6628           8 :                                               snum, printer->drivername ?
    6629             :                                               printer->drivername : "");
    6630             :                 }
    6631             :         }
    6632             : 
    6633         100 :         if (printer->comment != NULL &&
    6634          84 :             (force_update ||
    6635          84 :              !strequal(printer->comment, old_printer->comment))) {
    6636          34 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
    6637          34 :                 if (!ok) {
    6638           0 :                         DEBUG(0, ("comment data corrupted\n"));
    6639           0 :                         result = WERR_INVALID_DATA;
    6640           0 :                         goto done;
    6641             :                 }
    6642          34 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6643             :                                           printer->sharename,
    6644             :                                           SPOOL_DSSPOOLER_KEY,
    6645             :                                           SPOOL_REG_DESCRIPTION,
    6646             :                                           REG_SZ,
    6647             :                                           buffer.data,
    6648          34 :                                           buffer.length);
    6649          34 :                 if (!W_ERROR_IS_OK(result)) {
    6650           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
    6651           0 :                         goto done;
    6652             :                 }
    6653             : 
    6654          34 :                 if (!force_update) {
    6655          34 :                         notify_printer_comment(global_event_context(), msg_ctx,
    6656          34 :                                                snum, printer->comment ?
    6657             :                                                printer->comment : "");
    6658             :                 }
    6659             :         }
    6660             : 
    6661         100 :         if (printer->sharename != NULL &&
    6662          84 :             (force_update ||
    6663          84 :              !strequal(printer->sharename, old_printer->sharename))) {
    6664          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
    6665          16 :                 if (!ok) {
    6666           0 :                         DEBUG(0, ("sharename data corrupted\n"));
    6667           0 :                         result = WERR_INVALID_DATA;
    6668           0 :                         goto done;
    6669             :                 }
    6670          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6671             :                                           printer->sharename,
    6672             :                                           SPOOL_DSSPOOLER_KEY,
    6673             :                                           SPOOL_REG_PRINTSHARENAME,
    6674             :                                           REG_SZ,
    6675             :                                           buffer.data,
    6676          16 :                                           buffer.length);
    6677          16 :                 if (!W_ERROR_IS_OK(result)) {
    6678           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
    6679           0 :                         goto done;
    6680             :                 }
    6681             : 
    6682          16 :                 if (!force_update) {
    6683           0 :                         notify_printer_sharename(global_event_context(),
    6684             :                                                  msg_ctx,
    6685           0 :                                                  snum, printer->sharename ?
    6686             :                                                  printer->sharename : "");
    6687             :                 }
    6688             : 
    6689             :                 /* name change, purge any cache entries for the old */
    6690          16 :                 prune_printername_cache();
    6691             :         }
    6692             : 
    6693         100 :         if (printer->printername != NULL &&
    6694          84 :             (force_update ||
    6695          84 :              !strequal(printer->printername, old_printer->printername))) {
    6696           0 :                 const char *p;
    6697             : 
    6698         100 :                 p = strrchr(printer->printername, '\\' );
    6699         100 :                 if (p != NULL) {
    6700         100 :                         p++;
    6701             :                 } else {
    6702           0 :                         p = printer->printername;
    6703             :                 }
    6704             : 
    6705         100 :                 ok = push_reg_sz(tmp_ctx, &buffer, p);
    6706         100 :                 if (!ok) {
    6707           0 :                         DEBUG(0, ("printername data corrupted\n"));
    6708           0 :                         result = WERR_INVALID_DATA;
    6709           0 :                         goto done;
    6710             :                 }
    6711         100 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6712             :                                           printer->sharename,
    6713             :                                           SPOOL_DSSPOOLER_KEY,
    6714             :                                           SPOOL_REG_PRINTERNAME,
    6715             :                                           REG_SZ,
    6716             :                                           buffer.data,
    6717         100 :                                           buffer.length);
    6718         100 :                 if (!W_ERROR_IS_OK(result)) {
    6719           0 :                         DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
    6720           0 :                         goto done;
    6721             :                 }
    6722             : 
    6723         100 :                 if (!force_update) {
    6724          84 :                         notify_printer_printername(global_event_context(),
    6725             :                                                    msg_ctx, snum, p ? p : "");
    6726             :                 }
    6727             : 
    6728             :                 /* name change, purge any cache entries for the old */
    6729         100 :                 prune_printername_cache();
    6730             :         }
    6731             : 
    6732         100 :         if (printer->portname != NULL &&
    6733          84 :             (force_update ||
    6734          84 :              !strequal(printer->portname, old_printer->portname))) {
    6735          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
    6736          16 :                 if (!ok) {
    6737           0 :                         DEBUG(0, ("portname data corrupted\n"));
    6738           0 :                         result = WERR_INVALID_DATA;
    6739           0 :                         goto done;
    6740             :                 }
    6741          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6742             :                                           printer->sharename,
    6743             :                                           SPOOL_DSSPOOLER_KEY,
    6744             :                                           SPOOL_REG_PORTNAME,
    6745             :                                           REG_SZ,
    6746             :                                           buffer.data,
    6747          16 :                                           buffer.length);
    6748          16 :                 if (!W_ERROR_IS_OK(result)) {
    6749           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
    6750           0 :                         goto done;
    6751             :                 }
    6752             : 
    6753          16 :                 if (!force_update) {
    6754           0 :                         notify_printer_port(global_event_context(),
    6755           0 :                                             msg_ctx, snum, printer->portname ?
    6756             :                                             printer->portname : "");
    6757             :                 }
    6758             :         }
    6759             : 
    6760         100 :         if (printer->location != NULL &&
    6761          84 :             (force_update ||
    6762          84 :              !strequal(printer->location, old_printer->location))) {
    6763           8 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
    6764           8 :                 if (!ok) {
    6765           0 :                         DEBUG(0, ("location data corrupted\n"));
    6766           0 :                         result = WERR_INVALID_DATA;
    6767           0 :                         goto done;
    6768             :                 }
    6769           8 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6770             :                                           printer->sharename,
    6771             :                                           SPOOL_DSSPOOLER_KEY,
    6772             :                                           SPOOL_REG_LOCATION,
    6773             :                                           REG_SZ,
    6774             :                                           buffer.data,
    6775           8 :                                           buffer.length);
    6776           8 :                 if (!W_ERROR_IS_OK(result)) {
    6777           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
    6778           0 :                         goto done;
    6779             :                 }
    6780             : 
    6781           8 :                 if (!force_update) {
    6782           8 :                         notify_printer_location(global_event_context(),
    6783             :                                                 msg_ctx, snum,
    6784           8 :                                                 printer->location ?
    6785             :                                                 printer->location : "");
    6786             :                 }
    6787             :         }
    6788             : 
    6789         100 :         if (printer->sepfile != NULL &&
    6790          84 :             (force_update ||
    6791          84 :              !strequal(printer->sepfile, old_printer->sepfile))) {
    6792           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
    6793           0 :                 if (!ok) {
    6794           0 :                         DEBUG(0, ("sepfile data corrupted\n"));
    6795           0 :                         result = WERR_INVALID_DATA;
    6796           0 :                         goto done;
    6797             :                 }
    6798           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6799             :                                           printer->sharename,
    6800             :                                           SPOOL_DSSPOOLER_KEY,
    6801             :                                           SPOOL_REG_PRINTSEPARATORFILE,
    6802             :                                           REG_SZ,
    6803             :                                           buffer.data,
    6804           0 :                                           buffer.length);
    6805           0 :                 if (!W_ERROR_IS_OK(result)) {
    6806           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
    6807           0 :                         goto done;
    6808             :                 }
    6809             : 
    6810           0 :                 if (!force_update) {
    6811           0 :                         notify_printer_sepfile(global_event_context(),
    6812             :                                                msg_ctx, snum,
    6813           0 :                                                printer->sepfile ?
    6814             :                                                printer->sepfile : "");
    6815             :                 }
    6816             :         }
    6817             : 
    6818         100 :         if (printer->starttime != 0 &&
    6819           0 :             (force_update ||
    6820           0 :              printer->starttime != old_printer->starttime)) {
    6821           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6822           0 :                 SIVAL(buffer.data, 0, printer->starttime);
    6823           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6824             :                                           printer->sharename,
    6825             :                                           SPOOL_DSSPOOLER_KEY,
    6826             :                                           SPOOL_REG_PRINTSTARTTIME,
    6827             :                                           REG_DWORD,
    6828             :                                           buffer.data,
    6829           0 :                                           buffer.length);
    6830           0 :                 if (!W_ERROR_IS_OK(result)) {
    6831           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
    6832           0 :                         goto done;
    6833             :                 }
    6834             :         }
    6835             : 
    6836         100 :         if (printer->untiltime != 0 &&
    6837           0 :             (force_update ||
    6838           0 :              printer->untiltime != old_printer->untiltime)) {
    6839           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6840           0 :                 SIVAL(buffer.data, 0, printer->untiltime);
    6841           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6842             :                                           printer->sharename,
    6843             :                                           SPOOL_DSSPOOLER_KEY,
    6844             :                                           SPOOL_REG_PRINTENDTIME,
    6845             :                                           REG_DWORD,
    6846             :                                           buffer.data,
    6847           0 :                                           buffer.length);
    6848           0 :                 if (!W_ERROR_IS_OK(result)) {
    6849           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6850           0 :                         goto done;
    6851             :                 }
    6852             :         }
    6853             : 
    6854         100 :         if (force_update || printer->priority != old_printer->priority) {
    6855          16 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6856          16 :                 SIVAL(buffer.data, 0, printer->priority);
    6857          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6858             :                                           printer->sharename,
    6859             :                                           SPOOL_DSSPOOLER_KEY,
    6860             :                                           SPOOL_REG_PRIORITY,
    6861             :                                           REG_DWORD,
    6862             :                                           buffer.data,
    6863          16 :                                           buffer.length);
    6864          16 :                 if (!W_ERROR_IS_OK(result)) {
    6865           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6866           0 :                         goto done;
    6867             :                 }
    6868             :         }
    6869             : 
    6870         100 :         if (force_update || printer->attributes != old_printer->attributes) {
    6871          16 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6872          16 :                 SIVAL(buffer.data, 0, (printer->attributes &
    6873             :                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
    6874          16 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6875             :                                           printer->sharename,
    6876             :                                           SPOOL_DSSPOOLER_KEY,
    6877             :                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
    6878             :                                           REG_DWORD,
    6879             :                                           buffer.data,
    6880          16 :                                           buffer.length);
    6881          16 :                 if (!W_ERROR_IS_OK(result)) {
    6882           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6883           0 :                         goto done;
    6884             :                 }
    6885             : 
    6886          16 :                 switch (printer->attributes & 0x3) {
    6887          16 :                         case 0:
    6888          16 :                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
    6889          16 :                                 break;
    6890           0 :                         case 1:
    6891           0 :                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
    6892           0 :                                 break;
    6893           0 :                         case 2:
    6894           0 :                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
    6895           0 :                                 break;
    6896           0 :                         default:
    6897           0 :                                 spooling = "unknown";
    6898             :                 }
    6899          16 :                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
    6900          16 :                 if (!ok) {
    6901           0 :                         DEBUG(0, ("printSpooling data corrupted\n"));
    6902           0 :                         result = WERR_INVALID_DATA;
    6903           0 :                         goto done;
    6904             :                 }
    6905          16 :                 winreg_set_printer_dataex(tmp_ctx, b,
    6906             :                                           printer->sharename,
    6907             :                                           SPOOL_DSSPOOLER_KEY,
    6908             :                                           SPOOL_REG_PRINTSPOOLING,
    6909             :                                           REG_SZ,
    6910             :                                           buffer.data,
    6911          16 :                                           buffer.length);
    6912             :         }
    6913             : 
    6914         100 :         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
    6915         100 :         if (!ok) {
    6916           0 :                 DEBUG(0, ("shortServerName data corrupted\n"));
    6917           0 :                 result = WERR_INVALID_DATA;
    6918           0 :                 goto done;
    6919             :         }
    6920         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6921             :                                   printer->sharename,
    6922             :                                   SPOOL_DSSPOOLER_KEY,
    6923             :                                   SPOOL_REG_SHORTSERVERNAME,
    6924             :                                   REG_SZ,
    6925             :                                   buffer.data,
    6926         100 :                                   buffer.length);
    6927         100 :         if (!W_ERROR_IS_OK(result)) {
    6928           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
    6929           0 :                 goto done;
    6930             :         }
    6931             : 
    6932         100 :         dnsdomname = get_mydnsfullname();
    6933         100 :         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
    6934         100 :                 longname = talloc_strdup(tmp_ctx, dnsdomname);
    6935             :         } else {
    6936           0 :                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
    6937             :         }
    6938         100 :         if (longname == NULL) {
    6939           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    6940           0 :                 goto done;
    6941             :         }
    6942             : 
    6943         100 :         ok = push_reg_sz(tmp_ctx, &buffer, longname);
    6944         100 :         if (!ok) {
    6945           0 :                 DEBUG(0, ("longname data corrupted\n"));
    6946           0 :                 result = WERR_INVALID_DATA;
    6947           0 :                 goto done;
    6948             :         }
    6949         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6950             :                                            printer->sharename,
    6951             :                                            SPOOL_DSSPOOLER_KEY,
    6952             :                                            SPOOL_REG_SERVERNAME,
    6953             :                                            REG_SZ,
    6954             :                                            buffer.data,
    6955         100 :                                            buffer.length);
    6956         100 :         if (!W_ERROR_IS_OK(result)) {
    6957           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
    6958           0 :                 goto done;
    6959             :         }
    6960             : 
    6961         100 :         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
    6962             :                                   lp_netbios_name(), printer->sharename);
    6963         100 :         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
    6964         100 :         if (!ok) {
    6965           0 :                 DEBUG(0, ("uncName data corrupted\n"));
    6966           0 :                 result = WERR_INVALID_DATA;
    6967           0 :                 goto done;
    6968             :         }
    6969         100 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6970             :                                   printer->sharename,
    6971             :                                   SPOOL_DSSPOOLER_KEY,
    6972             :                                   SPOOL_REG_UNCNAME,
    6973             :                                   REG_SZ,
    6974             :                                   buffer.data,
    6975         100 :                                   buffer.length);
    6976         100 :         if (!W_ERROR_IS_OK(result)) {
    6977           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
    6978           0 :                 goto done;
    6979             :         }
    6980             : 
    6981         100 : done:
    6982         100 :         talloc_free(tmp_ctx);
    6983         100 :         return result;
    6984             : }
    6985             : 
    6986             : /********************************************************************
    6987             :  * Called by spoolss_api_setprinter
    6988             :  * when updating a printer description.
    6989             :  ********************************************************************/
    6990             : 
    6991          84 : static WERROR update_printer(struct pipes_struct *p,
    6992             :                              struct policy_handle *handle,
    6993             :                              struct spoolss_SetPrinterInfoCtr *info_ctr,
    6994             :                              struct spoolss_DeviceMode *devmode)
    6995             : {
    6996          84 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6997          84 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    6998           0 :         const struct tsocket_address *remote_address =
    6999          84 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    7000           0 :         struct auth_session_info *session_info =
    7001          84 :                 dcesrv_call_session_info(dce_call);
    7002          84 :         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
    7003          84 :         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
    7004           0 :         struct spoolss_PrinterInfo2 *old_printer;
    7005          84 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    7006           0 :         const struct loadparm_substitution *lp_sub =
    7007          84 :                 loadparm_s3_global_substitution();
    7008           0 :         int snum;
    7009          84 :         WERROR result = WERR_OK;
    7010           0 :         TALLOC_CTX *tmp_ctx;
    7011           0 :         struct dcerpc_binding_handle *b;
    7012             : 
    7013          84 :         DEBUG(8,("update_printer\n"));
    7014             : 
    7015          84 :         tmp_ctx = talloc_new(p->mem_ctx);
    7016          84 :         if (tmp_ctx == NULL) {
    7017           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    7018             :         }
    7019             : 
    7020          84 :         if (!Printer) {
    7021           0 :                 result = WERR_INVALID_HANDLE;
    7022           0 :                 goto done;
    7023             :         }
    7024             : 
    7025          84 :         if (!get_printer_snum(p, handle, &snum, NULL)) {
    7026           0 :                 result = WERR_INVALID_HANDLE;
    7027           0 :                 goto done;
    7028             :         }
    7029             : 
    7030          84 :         result = winreg_printer_binding_handle(tmp_ctx,
    7031             :                                                get_session_info_system(),
    7032             :                                                p->msg_ctx,
    7033             :                                                &b);
    7034          84 :         if (!W_ERROR_IS_OK(result)) {
    7035           0 :                 goto done;
    7036             :         }
    7037             : 
    7038          84 :         result = winreg_get_printer(tmp_ctx, b,
    7039             :                                     lp_const_servicename(snum),
    7040             :                                     &old_printer);
    7041          84 :         if (!W_ERROR_IS_OK(result)) {
    7042           0 :                 result = WERR_INVALID_HANDLE;
    7043           0 :                 goto done;
    7044             :         }
    7045             : 
    7046             :         /* Do sanity check on the requested changes for Samba */
    7047          84 :         if (!check_printer_ok(tmp_ctx, printer, snum)) {
    7048           0 :                 result = WERR_INVALID_PARAMETER;
    7049           0 :                 goto done;
    7050             :         }
    7051             : 
    7052             :         /* FIXME!!! If the driver has changed we really should verify that
    7053             :            it is installed before doing much else   --jerry */
    7054             : 
    7055             :         /* Check calling user has permission to update printer description */
    7056          84 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
    7057           0 :                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
    7058           0 :                 result = WERR_ACCESS_DENIED;
    7059           0 :                 goto done;
    7060             :         }
    7061             : 
    7062             :         /* Call addprinter hook */
    7063             :         /* Check changes to see if this is really needed */
    7064             : 
    7065          84 :         if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
    7066          84 :                         (!strequal(printer->drivername, old_printer->drivername) ||
    7067          76 :                          !strequal(printer->comment, old_printer->comment) ||
    7068          42 :                          !strequal(printer->portname, old_printer->portname) ||
    7069          42 :                          !strequal(printer->location, old_printer->location)) )
    7070             :         {
    7071           0 :                 char *raddr;
    7072             : 
    7073          50 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    7074             :                                                          p->mem_ctx);
    7075          50 :                 if (raddr == NULL) {
    7076           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    7077           0 :                         goto done;
    7078             :                 }
    7079             : 
    7080             :                 /* add_printer_hook() will call reload_services() */
    7081          50 :                 if (!add_printer_hook(tmp_ctx, session_info->security_token,
    7082             :                                       printer, raddr,
    7083             :                                       p->msg_ctx)) {
    7084           0 :                         result = WERR_ACCESS_DENIED;
    7085           0 :                         goto done;
    7086             :                 }
    7087             :         }
    7088             : 
    7089          84 :         result = update_dsspooler(tmp_ctx,
    7090             :                                   get_session_info_system(),
    7091             :                                   p->msg_ctx,
    7092             :                                   snum,
    7093             :                                   printer,
    7094             :                                   old_printer);
    7095          84 :         if (!W_ERROR_IS_OK(result)) {
    7096           0 :                 goto done;
    7097             :         }
    7098             : 
    7099          84 :         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
    7100             : 
    7101          84 :         if (devmode == NULL) {
    7102          76 :                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
    7103             :         }
    7104          84 :         result = winreg_update_printer(tmp_ctx, b,
    7105             :                                        printer->sharename,
    7106             :                                        printer_mask,
    7107             :                                        printer,
    7108             :                                        devmode,
    7109             :                                        NULL);
    7110             : 
    7111          84 : done:
    7112          84 :         talloc_free(tmp_ctx);
    7113             : 
    7114          84 :         return result;
    7115             : }
    7116             : 
    7117             : /****************************************************************************
    7118             : ****************************************************************************/
    7119           8 : static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
    7120             :                                            struct policy_handle *handle,
    7121             :                                            struct spoolss_SetPrinterInfo7 *info7)
    7122             : {
    7123             : #ifdef HAVE_ADS
    7124           0 :         const struct loadparm_substitution *lp_sub =
    7125           6 :                 loadparm_s3_global_substitution();
    7126           6 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    7127           0 :         WERROR result;
    7128           0 :         int snum;
    7129           0 :         struct printer_handle *Printer;
    7130             : 
    7131           6 :         if ( lp_security() != SEC_ADS ) {
    7132           6 :                 return WERR_INVALID_LEVEL;
    7133             :         }
    7134             : 
    7135           0 :         Printer = find_printer_index_by_hnd(p, handle);
    7136             : 
    7137           0 :         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
    7138             : 
    7139           0 :         if (!Printer)
    7140           0 :                 return WERR_INVALID_HANDLE;
    7141             : 
    7142           0 :         if (!get_printer_snum(p, handle, &snum, NULL))
    7143           0 :                 return WERR_INVALID_HANDLE;
    7144             : 
    7145           0 :         result = winreg_get_printer_internal(p->mem_ctx,
    7146             :                                     get_session_info_system(),
    7147             :                                     p->msg_ctx,
    7148           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum),
    7149             :                                     &pinfo2);
    7150           0 :         if (!W_ERROR_IS_OK(result)) {
    7151           0 :                 return WERR_INVALID_HANDLE;
    7152             :         }
    7153             : 
    7154           0 :         nt_printer_publish(pinfo2,
    7155             :                            get_session_info_system(),
    7156             :                            p->msg_ctx,
    7157             :                            pinfo2,
    7158           0 :                            info7->action);
    7159             : 
    7160           0 :         TALLOC_FREE(pinfo2);
    7161           0 :         return WERR_OK;
    7162             : #else
    7163           2 :         return WERR_INVALID_LEVEL;
    7164             : #endif
    7165             : }
    7166             : 
    7167             : /********************************************************************
    7168             :  ********************************************************************/
    7169             : 
    7170         296 : static WERROR update_printer_devmode(struct pipes_struct *p,
    7171             :                                      struct policy_handle *handle,
    7172             :                                      struct spoolss_DeviceMode *devmode)
    7173             : {
    7174           0 :         int snum;
    7175         296 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    7176         296 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
    7177             : 
    7178         296 :         DEBUG(8,("update_printer_devmode\n"));
    7179             : 
    7180         296 :         if (!Printer) {
    7181           0 :                 return WERR_INVALID_HANDLE;
    7182             :         }
    7183             : 
    7184         296 :         if (!get_printer_snum(p, handle, &snum, NULL)) {
    7185           0 :                 return WERR_INVALID_HANDLE;
    7186             :         }
    7187             : 
    7188             :         /* Check calling user has permission to update printer description */
    7189         296 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
    7190           0 :                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
    7191           0 :                 return WERR_ACCESS_DENIED;
    7192             :         }
    7193             : 
    7194         296 :         return winreg_update_printer_internal(p->mem_ctx,
    7195             :                                      get_session_info_system(),
    7196             :                                      p->msg_ctx,
    7197             :                                      lp_const_servicename(snum),
    7198             :                                      info2_mask,
    7199             :                                      NULL,
    7200             :                                      devmode,
    7201             :                                      NULL);
    7202             : }
    7203             : 
    7204             : 
    7205             : /****************************************************************
    7206             :  _spoolss_SetPrinter
    7207             : ****************************************************************/
    7208             : 
    7209         584 : WERROR _spoolss_SetPrinter(struct pipes_struct *p,
    7210             :                            struct spoolss_SetPrinter *r)
    7211             : {
    7212           0 :         WERROR result;
    7213             : 
    7214         584 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    7215             : 
    7216         584 :         if (!Printer) {
    7217           0 :                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
    7218             :                         OUR_HANDLE(r->in.handle)));
    7219           0 :                 return WERR_INVALID_HANDLE;
    7220             :         }
    7221             : 
    7222             :         /* check the level */
    7223         584 :         switch (r->in.info_ctr->level) {
    7224         104 :                 case 0:
    7225         104 :                         return control_printer(r->in.handle, r->in.command, p);
    7226          84 :                 case 2:
    7227          84 :                         result = update_printer(p, r->in.handle,
    7228             :                                                 r->in.info_ctr,
    7229          84 :                                                 r->in.devmode_ctr->devmode);
    7230          84 :                         if (!W_ERROR_IS_OK(result))
    7231           0 :                                 return result;
    7232          84 :                         if (r->in.secdesc_ctr->sd)
    7233          28 :                                 result = update_printer_sec(r->in.handle, p,
    7234             :                                                             r->in.secdesc_ctr);
    7235          84 :                         return result;
    7236          92 :                 case 3:
    7237          92 :                         return update_printer_sec(r->in.handle, p,
    7238             :                                                   r->in.secdesc_ctr);
    7239           0 :                 case 4: {
    7240           0 :                         struct spoolss_PrinterInfo2 *old_printer;
    7241           0 :                         struct spoolss_SetPrinterInfo2 *set_old_printer;
    7242           0 :                         struct spoolss_SetPrinterInfoCtr *info_ctr;
    7243           0 :                         struct dcerpc_binding_handle *b;
    7244           0 :                         int snum;
    7245           0 :                         TALLOC_CTX *tmp_ctx;
    7246             : 
    7247           0 :                         tmp_ctx = talloc_new(p->mem_ctx);
    7248           0 :                         if (tmp_ctx == NULL) {
    7249           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7250             :                         }
    7251             : 
    7252           0 :                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7253           0 :                                 TALLOC_FREE(tmp_ctx);
    7254           0 :                                 return WERR_INVALID_HANDLE;
    7255             :                         }
    7256             : 
    7257           0 :                         result = winreg_printer_binding_handle(tmp_ctx,
    7258             :                                                                get_session_info_system(),
    7259             :                                                                p->msg_ctx,
    7260             :                                                                &b);
    7261           0 :                         if (!W_ERROR_IS_OK(result)) {
    7262           0 :                                 TALLOC_FREE(tmp_ctx);
    7263           0 :                                 return result;
    7264             :                         }
    7265             : 
    7266           0 :                         result = winreg_get_printer(tmp_ctx, b,
    7267             :                                                     lp_const_servicename(snum),
    7268             :                                                     &old_printer);
    7269           0 :                         if (!W_ERROR_IS_OK(result)) {
    7270           0 :                                 TALLOC_FREE(tmp_ctx);
    7271           0 :                                 return WERR_INVALID_HANDLE;
    7272             :                         }
    7273             : 
    7274           0 :                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
    7275           0 :                         if (old_printer->servername == NULL) {
    7276           0 :                                 TALLOC_FREE(tmp_ctx);
    7277           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7278             :                         }
    7279             : 
    7280           0 :                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
    7281           0 :                         if (old_printer->printername == NULL) {
    7282           0 :                                 TALLOC_FREE(tmp_ctx);
    7283           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7284             :                         }
    7285             : 
    7286           0 :                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
    7287             : 
    7288           0 :                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
    7289           0 :                         if (set_old_printer == NULL) {
    7290           0 :                                 TALLOC_FREE(tmp_ctx);
    7291           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7292             :                         }
    7293             : 
    7294           0 :                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
    7295             : 
    7296           0 :                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
    7297           0 :                         if (info_ctr == NULL) {
    7298           0 :                                 TALLOC_FREE(tmp_ctx);
    7299           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7300             :                         }
    7301             : 
    7302           0 :                         info_ctr->level = 2;
    7303           0 :                         info_ctr->info.info2 = set_old_printer;
    7304             : 
    7305           0 :                         result = update_printer(p, r->in.handle,
    7306             :                                                 info_ctr,
    7307           0 :                                                 r->in.devmode_ctr->devmode);
    7308             : 
    7309           0 :                         if (!W_ERROR_IS_OK(result)) {
    7310           0 :                                 TALLOC_FREE(tmp_ctx);
    7311           0 :                                 return result;
    7312             :                         }
    7313             : 
    7314           0 :                         if (r->in.secdesc_ctr->sd) {
    7315           0 :                                 result = update_printer_sec(r->in.handle, p,
    7316             :                                                             r->in.secdesc_ctr);
    7317             :                         }
    7318             : 
    7319           0 :                         TALLOC_FREE(tmp_ctx);
    7320           0 :                         return result;
    7321             :                 }
    7322           8 :                 case 7:
    7323           8 :                         return publish_or_unpublish_printer(p, r->in.handle,
    7324           8 :                                                             r->in.info_ctr->info.info7);
    7325         296 :                 case 8:
    7326         296 :                         return update_printer_devmode(p, r->in.handle,
    7327         296 :                                                       r->in.devmode_ctr->devmode);
    7328           0 :                 default:
    7329           0 :                         return WERR_INVALID_LEVEL;
    7330             :         }
    7331             : }
    7332             : 
    7333             : /****************************************************************
    7334             :  _spoolss_FindClosePrinterNotify
    7335             : ****************************************************************/
    7336             : 
    7337           0 : WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
    7338             :                                        struct spoolss_FindClosePrinterNotify *r)
    7339             : {
    7340           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    7341             : 
    7342           0 :         if (!Printer) {
    7343           0 :                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
    7344             :                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
    7345           0 :                 return WERR_INVALID_HANDLE;
    7346             :         }
    7347             : 
    7348           0 :         if (Printer->notify.cli_chan != NULL &&
    7349           0 :             Printer->notify.cli_chan->active_connections > 0) {
    7350           0 :                 int snum = -1;
    7351             : 
    7352           0 :                 if (Printer->printer_type == SPLHND_PRINTER) {
    7353           0 :                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7354           0 :                                 return WERR_INVALID_HANDLE;
    7355             :                         }
    7356             :                 }
    7357             : 
    7358           0 :                 srv_spoolss_replycloseprinter(snum, Printer);
    7359             :         }
    7360             : 
    7361           0 :         Printer->notify.flags=0;
    7362           0 :         Printer->notify.options=0;
    7363           0 :         Printer->notify.localmachine[0]='\0';
    7364           0 :         Printer->notify.printerlocal=0;
    7365           0 :         TALLOC_FREE(Printer->notify.option);
    7366             : 
    7367           0 :         return WERR_OK;
    7368             : }
    7369             : 
    7370             : /****************************************************************
    7371             :  _spoolss_AddJob
    7372             : ****************************************************************/
    7373             : 
    7374          16 : WERROR _spoolss_AddJob(struct pipes_struct *p,
    7375             :                        struct spoolss_AddJob *r)
    7376             : {
    7377          16 :         if (!r->in.buffer && (r->in.offered != 0)) {
    7378           0 :                 return WERR_INVALID_PARAMETER;
    7379             :         }
    7380             : 
    7381             :         /* this is what a NT server returns for AddJob. AddJob must fail on
    7382             :          * non-local printers */
    7383             : 
    7384          16 :         if (r->in.level != 1) {
    7385           8 :                 return WERR_INVALID_LEVEL;
    7386             :         }
    7387             : 
    7388           8 :         return WERR_INVALID_PARAMETER;
    7389             : }
    7390             : 
    7391             : /****************************************************************************
    7392             : fill_job_info1
    7393             : ****************************************************************************/
    7394             : 
    7395         320 : static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
    7396             :                              struct spoolss_JobInfo1 *r,
    7397             :                              const print_queue_struct *queue,
    7398             :                              uint32_t jobid,
    7399             :                              int position, int snum,
    7400             :                              struct spoolss_PrinterInfo2 *pinfo2)
    7401             : {
    7402           0 :         const struct loadparm_substitution *lp_sub =
    7403         320 :                 loadparm_s3_global_substitution();
    7404           0 :         struct tm *t;
    7405             : 
    7406         320 :         t = gmtime(&queue->time);
    7407             : 
    7408         320 :         r->job_id            = jobid;
    7409             : 
    7410         320 :         r->printer_name              = lp_servicename(mem_ctx, lp_sub, snum);
    7411         320 :         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
    7412         320 :         r->server_name               = talloc_strdup(mem_ctx, pinfo2->servername);
    7413         320 :         W_ERROR_HAVE_NO_MEMORY(r->server_name);
    7414         320 :         r->user_name         = talloc_strdup(mem_ctx, queue->fs_user);
    7415         320 :         W_ERROR_HAVE_NO_MEMORY(r->user_name);
    7416         320 :         r->document_name     = talloc_strdup(mem_ctx, queue->fs_file);
    7417         320 :         W_ERROR_HAVE_NO_MEMORY(r->document_name);
    7418         320 :         r->data_type         = talloc_strdup(mem_ctx, "RAW");
    7419         320 :         W_ERROR_HAVE_NO_MEMORY(r->data_type);
    7420         320 :         r->text_status               = talloc_strdup(mem_ctx, "");
    7421         320 :         W_ERROR_HAVE_NO_MEMORY(r->text_status);
    7422             : 
    7423         320 :         r->status            = nt_printj_status(queue->status);
    7424         320 :         r->priority          = queue->priority;
    7425         320 :         r->position          = position;
    7426         320 :         r->total_pages               = queue->page_count;
    7427         320 :         r->pages_printed     = 0; /* ??? */
    7428             : 
    7429         320 :         init_systemtime(&r->submitted, t);
    7430             : 
    7431         320 :         return WERR_OK;
    7432             : }
    7433             : 
    7434             : /****************************************************************************
    7435             : fill_job_info2
    7436             : ****************************************************************************/
    7437             : 
    7438          66 : static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
    7439             :                              struct spoolss_JobInfo2 *r,
    7440             :                              const print_queue_struct *queue,
    7441             :                              uint32_t jobid,
    7442             :                              int position, int snum,
    7443             :                              struct spoolss_PrinterInfo2 *pinfo2,
    7444             :                              struct spoolss_DeviceMode *devmode)
    7445             : {
    7446           0 :         const struct loadparm_substitution *lp_sub =
    7447          66 :                 loadparm_s3_global_substitution();
    7448           0 :         struct tm *t;
    7449             : 
    7450          66 :         t = gmtime(&queue->time);
    7451             : 
    7452          66 :         r->job_id            = jobid;
    7453             : 
    7454          66 :         r->printer_name              = lp_servicename(mem_ctx, lp_sub, snum);
    7455          66 :         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
    7456          66 :         r->server_name               = talloc_strdup(mem_ctx, pinfo2->servername);
    7457          66 :         W_ERROR_HAVE_NO_MEMORY(r->server_name);
    7458          66 :         r->user_name         = talloc_strdup(mem_ctx, queue->fs_user);
    7459          66 :         W_ERROR_HAVE_NO_MEMORY(r->user_name);
    7460          66 :         r->document_name     = talloc_strdup(mem_ctx, queue->fs_file);
    7461          66 :         W_ERROR_HAVE_NO_MEMORY(r->document_name);
    7462          66 :         r->notify_name               = talloc_strdup(mem_ctx, queue->fs_user);
    7463          66 :         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
    7464          66 :         r->data_type         = talloc_strdup(mem_ctx, "RAW");
    7465          66 :         W_ERROR_HAVE_NO_MEMORY(r->data_type);
    7466          66 :         r->print_processor   = talloc_strdup(mem_ctx, "winprint");
    7467          66 :         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
    7468          66 :         r->parameters                = talloc_strdup(mem_ctx, "");
    7469          66 :         W_ERROR_HAVE_NO_MEMORY(r->parameters);
    7470          66 :         r->driver_name               = talloc_strdup(mem_ctx, pinfo2->drivername);
    7471          66 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    7472             : 
    7473          66 :         r->devmode           = devmode;
    7474             : 
    7475          66 :         r->text_status               = talloc_strdup(mem_ctx, "");
    7476          66 :         W_ERROR_HAVE_NO_MEMORY(r->text_status);
    7477             : 
    7478          66 :         r->secdesc           = NULL;
    7479             : 
    7480          66 :         r->status            = nt_printj_status(queue->status);
    7481          66 :         r->priority          = queue->priority;
    7482          66 :         r->position          = position;
    7483          66 :         r->start_time                = 0;
    7484          66 :         r->until_time                = 0;
    7485          66 :         r->total_pages               = queue->page_count;
    7486          66 :         r->size                      = queue->size;
    7487          66 :         init_systemtime(&r->submitted, t);
    7488          66 :         r->time                      = 0;
    7489          66 :         r->pages_printed     = 0; /* ??? */
    7490             : 
    7491          66 :         return WERR_OK;
    7492             : }
    7493             : 
    7494             : /****************************************************************************
    7495             :  Enumjobs at level 1.
    7496             : ****************************************************************************/
    7497             : 
    7498          24 : static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
    7499             :                               const print_queue_struct *queue,
    7500             :                               uint32_t num_queues, int snum,
    7501             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7502             :                               union spoolss_JobInfo **info_p,
    7503             :                               uint32_t *count)
    7504             : {
    7505           0 :         union spoolss_JobInfo *info;
    7506           0 :         int i;
    7507          24 :         WERROR result = WERR_OK;
    7508           0 :         uint32_t num_filled;
    7509           0 :         struct tdb_print_db *pdb;
    7510             : 
    7511          24 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7512          24 :         if (info == NULL) {
    7513           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7514           0 :                 goto err_out;
    7515             :         }
    7516             : 
    7517          24 :         pdb = get_print_db_byname(pinfo2->sharename);
    7518          24 :         if (pdb == NULL) {
    7519           0 :                 result = WERR_INVALID_PARAMETER;
    7520           0 :                 goto err_info_free;
    7521             :         }
    7522             : 
    7523          24 :         num_filled = 0;
    7524         216 :         for (i = 0; i < num_queues; i++) {
    7525         192 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7526         192 :                 if (jobid == (uint32_t)-1) {
    7527           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7528           0 :                         continue;
    7529             :                 }
    7530             : 
    7531         192 :                 result = fill_job_info1(info,
    7532         192 :                                         &info[num_filled].info1,
    7533         192 :                                         &queue[i],
    7534             :                                         jobid,
    7535             :                                         i,
    7536             :                                         snum,
    7537             :                                         pinfo2);
    7538         192 :                 if (!W_ERROR_IS_OK(result)) {
    7539           0 :                         goto err_pdb_drop;
    7540             :                 }
    7541             : 
    7542         192 :                 num_filled++;
    7543             :         }
    7544             : 
    7545          24 :         release_print_db(pdb);
    7546          24 :         *info_p = info;
    7547          24 :         *count = num_filled;
    7548             : 
    7549          24 :         return WERR_OK;
    7550             : 
    7551           0 : err_pdb_drop:
    7552           0 :         release_print_db(pdb);
    7553           0 : err_info_free:
    7554           0 :         TALLOC_FREE(info);
    7555           0 : err_out:
    7556           0 :         *count = 0;
    7557           0 :         return result;
    7558             : }
    7559             : 
    7560             : /****************************************************************************
    7561             :  Enumjobs at level 2.
    7562             : ****************************************************************************/
    7563             : 
    7564          10 : static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
    7565             :                               const print_queue_struct *queue,
    7566             :                               uint32_t num_queues, int snum,
    7567             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7568             :                               union spoolss_JobInfo **info_p,
    7569             :                               uint32_t *count)
    7570             : {
    7571           0 :         union spoolss_JobInfo *info;
    7572           0 :         int i;
    7573          10 :         WERROR result = WERR_OK;
    7574           0 :         uint32_t num_filled;
    7575           0 :         struct tdb_print_db *pdb;
    7576             : 
    7577          10 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7578          10 :         if (info == NULL) {
    7579           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7580           0 :                 goto err_out;
    7581             :         }
    7582             : 
    7583          10 :         pdb = get_print_db_byname(pinfo2->sharename);
    7584          10 :         if (pdb == NULL) {
    7585           0 :                 result = WERR_INVALID_PARAMETER;
    7586           0 :                 goto err_info_free;
    7587             :         }
    7588             : 
    7589          10 :         num_filled = 0;
    7590          76 :         for (i = 0; i< num_queues; i++) {
    7591           0 :                 struct spoolss_DeviceMode *devmode;
    7592          66 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7593          66 :                 if (jobid == (uint32_t)-1) {
    7594           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7595           0 :                         continue;
    7596             :                 }
    7597             : 
    7598          66 :                 result = spoolss_create_default_devmode(info,
    7599             :                                                         pinfo2->printername,
    7600             :                                                         &devmode);
    7601          66 :                 if (!W_ERROR_IS_OK(result)) {
    7602           0 :                         DEBUG(3, ("Can't proceed w/o a devmode!\n"));
    7603           0 :                         goto err_pdb_drop;
    7604             :                 }
    7605             : 
    7606          66 :                 result = fill_job_info2(info,
    7607          66 :                                         &info[num_filled].info2,
    7608          66 :                                         &queue[i],
    7609             :                                         jobid,
    7610             :                                         i,
    7611             :                                         snum,
    7612             :                                         pinfo2,
    7613             :                                         devmode);
    7614          66 :                 if (!W_ERROR_IS_OK(result)) {
    7615           0 :                         goto err_pdb_drop;
    7616             :                 }
    7617          66 :                 num_filled++;
    7618             :         }
    7619             : 
    7620          10 :         release_print_db(pdb);
    7621          10 :         *info_p = info;
    7622          10 :         *count = num_filled;
    7623             : 
    7624          10 :         return WERR_OK;
    7625             : 
    7626           0 : err_pdb_drop:
    7627           0 :         release_print_db(pdb);
    7628           0 : err_info_free:
    7629           0 :         TALLOC_FREE(info);
    7630           0 : err_out:
    7631           0 :         *count = 0;
    7632           0 :         return result;
    7633             : }
    7634             : 
    7635             : /****************************************************************************
    7636             :  Enumjobs at level 3.
    7637             : ****************************************************************************/
    7638             : 
    7639           0 : static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
    7640             :                               const print_queue_struct *queue,
    7641             :                               uint32_t num_queues, int snum,
    7642             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7643             :                               union spoolss_JobInfo **info_p,
    7644             :                               uint32_t *count)
    7645             : {
    7646           0 :         union spoolss_JobInfo *info;
    7647           0 :         int i;
    7648           0 :         WERROR result = WERR_OK;
    7649           0 :         uint32_t num_filled;
    7650           0 :         struct tdb_print_db *pdb;
    7651             : 
    7652           0 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7653           0 :         if (info == NULL) {
    7654           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7655           0 :                 goto err_out;
    7656             :         }
    7657             : 
    7658           0 :         pdb = get_print_db_byname(pinfo2->sharename);
    7659           0 :         if (pdb == NULL) {
    7660           0 :                 result = WERR_INVALID_PARAMETER;
    7661           0 :                 goto err_info_free;
    7662             :         }
    7663             : 
    7664           0 :         num_filled = 0;
    7665           0 :         for (i = 0; i < num_queues; i++) {
    7666           0 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7667           0 :                 if (jobid == (uint32_t)-1) {
    7668           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7669           0 :                         continue;
    7670             :                 }
    7671             : 
    7672           0 :                 info[num_filled].info3.job_id = jobid;
    7673             :                 /* next_job_id is overwritten on next iteration */
    7674           0 :                 info[num_filled].info3.next_job_id = 0;
    7675           0 :                 info[num_filled].info3.reserved = 0;
    7676             : 
    7677           0 :                 if (num_filled > 0) {
    7678           0 :                         info[num_filled - 1].info3.next_job_id = jobid;
    7679             :                 }
    7680           0 :                 num_filled++;
    7681             :         }
    7682             : 
    7683           0 :         release_print_db(pdb);
    7684           0 :         *info_p = info;
    7685           0 :         *count = num_filled;
    7686             : 
    7687           0 :         return WERR_OK;
    7688             : 
    7689           0 : err_info_free:
    7690           0 :         TALLOC_FREE(info);
    7691           0 : err_out:
    7692           0 :         *count = 0;
    7693           0 :         return result;
    7694             : }
    7695             : 
    7696             : /****************************************************************
    7697             :  _spoolss_EnumJobs
    7698             : ****************************************************************/
    7699             : 
    7700          95 : WERROR _spoolss_EnumJobs(struct pipes_struct *p,
    7701             :                          struct spoolss_EnumJobs *r)
    7702             : {
    7703           0 :         WERROR result;
    7704          95 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    7705           0 :         int snum;
    7706           0 :         print_status_struct prt_status;
    7707          95 :         print_queue_struct *queue = NULL;
    7708           0 :         uint32_t count;
    7709             : 
    7710             :         /* that's an [in out] buffer */
    7711             : 
    7712          95 :         if (!r->in.buffer && (r->in.offered != 0)) {
    7713           0 :                 return WERR_INVALID_PARAMETER;
    7714             :         }
    7715             : 
    7716          95 :         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
    7717          12 :                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
    7718          12 :                 return WERR_INVALID_LEVEL;
    7719             :         }
    7720             : 
    7721          83 :         DEBUG(4,("_spoolss_EnumJobs\n"));
    7722             : 
    7723          83 :         *r->out.needed = 0;
    7724          83 :         *r->out.count = 0;
    7725          83 :         *r->out.info = NULL;
    7726             : 
    7727             :         /* lookup the printer snum and tdb entry */
    7728             : 
    7729          83 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7730           0 :                 return WERR_INVALID_HANDLE;
    7731             :         }
    7732             : 
    7733          83 :         result = winreg_get_printer_internal(p->mem_ctx,
    7734             :                                     get_session_info_system(),
    7735             :                                     p->msg_ctx,
    7736             :                                     lp_const_servicename(snum),
    7737             :                                     &pinfo2);
    7738          83 :         if (!W_ERROR_IS_OK(result)) {
    7739           0 :                 return result;
    7740             :         }
    7741             : 
    7742          83 :         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
    7743          83 :         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
    7744             :                 count, prt_status.status, prt_status.message));
    7745             : 
    7746          83 :         if (count == 0) {
    7747          49 :                 SAFE_FREE(queue);
    7748          49 :                 TALLOC_FREE(pinfo2);
    7749          49 :                 return WERR_OK;
    7750             :         }
    7751             : 
    7752          34 :         switch (r->in.level) {
    7753          24 :         case 1:
    7754          24 :                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
    7755             :                                          pinfo2, r->out.info, r->out.count);
    7756          24 :                 break;
    7757          10 :         case 2:
    7758          10 :                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
    7759             :                                          pinfo2, r->out.info, r->out.count);
    7760          10 :                 break;
    7761           0 :         case 3:
    7762           0 :                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
    7763             :                                          pinfo2, r->out.info, r->out.count);
    7764           0 :                 break;
    7765           0 :         default:
    7766           0 :                 SMB_ASSERT(false);      /* level checked on entry */
    7767             :                 break;
    7768             :         }
    7769             : 
    7770          34 :         SAFE_FREE(queue);
    7771          34 :         TALLOC_FREE(pinfo2);
    7772             : 
    7773          34 :         if (!W_ERROR_IS_OK(result)) {
    7774           0 :                 return result;
    7775             :         }
    7776             : 
    7777          34 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    7778             :                                                      spoolss_EnumJobs,
    7779             :                                                      *r->out.info, r->in.level,
    7780             :                                                      *r->out.count);
    7781          34 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    7782          34 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    7783             : 
    7784          34 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    7785             : }
    7786             : 
    7787             : /****************************************************************
    7788             :  _spoolss_ScheduleJob
    7789             : ****************************************************************/
    7790             : 
    7791           0 : WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
    7792             :                             struct spoolss_ScheduleJob *r)
    7793             : {
    7794           0 :         return WERR_OK;
    7795             : }
    7796             : 
    7797             : /****************************************************************
    7798             : ****************************************************************/
    7799             : 
    7800          32 : static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
    7801             :                                struct messaging_context *msg_ctx,
    7802             :                                const char *printer_name,
    7803             :                                uint32_t job_id,
    7804             :                                struct spoolss_SetJobInfo1 *r)
    7805             : {
    7806           0 :         char *old_doc_name;
    7807             : 
    7808          32 :         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
    7809           0 :                 return WERR_INVALID_HANDLE;
    7810             :         }
    7811             : 
    7812          32 :         if (strequal(old_doc_name, r->document_name)) {
    7813           0 :                 return WERR_OK;
    7814             :         }
    7815             : 
    7816          32 :         if (!print_job_set_name(global_event_context(), msg_ctx,
    7817             :                                 printer_name, job_id, r->document_name)) {
    7818           0 :                 return WERR_INVALID_HANDLE;
    7819             :         }
    7820             : 
    7821          32 :         return WERR_OK;
    7822             : }
    7823             : 
    7824             : /****************************************************************
    7825             :  _spoolss_SetJob
    7826             : ****************************************************************/
    7827             : 
    7828         640 : WERROR _spoolss_SetJob(struct pipes_struct *p,
    7829             :                        struct spoolss_SetJob *r)
    7830             : {
    7831         640 :         struct dcesrv_call_state *dce_call = p->dce_call;
    7832           0 :         struct auth_session_info *session_info =
    7833         640 :                 dcesrv_call_session_info(dce_call);
    7834           0 :         int snum;
    7835         640 :         WERROR errcode = WERR_INVALID_FUNCTION;
    7836             : 
    7837         640 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7838           0 :                 return WERR_INVALID_HANDLE;
    7839             :         }
    7840             : 
    7841         640 :         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
    7842         244 :                 return WERR_INVALID_PRINTER_NAME;
    7843             :         }
    7844             : 
    7845         396 :         switch (r->in.command) {
    7846         300 :         case SPOOLSS_JOB_CONTROL_CANCEL:
    7847             :         case SPOOLSS_JOB_CONTROL_DELETE:
    7848         300 :                 errcode = print_job_delete(session_info, p->msg_ctx,
    7849             :                                            snum, r->in.job_id);
    7850         300 :                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
    7851         300 :                         errcode = WERR_OK;
    7852             :                 }
    7853         300 :                 break;
    7854          32 :         case SPOOLSS_JOB_CONTROL_PAUSE:
    7855          32 :                 errcode = print_job_pause(session_info, p->msg_ctx,
    7856             :                                           snum, r->in.job_id);
    7857          32 :                 break;
    7858          32 :         case SPOOLSS_JOB_CONTROL_RESTART:
    7859             :         case SPOOLSS_JOB_CONTROL_RESUME:
    7860          32 :                 errcode = print_job_resume(session_info, p->msg_ctx,
    7861             :                                            snum, r->in.job_id);
    7862          32 :                 break;
    7863          32 :         case SPOOLSS_JOB_CONTROL_NOOP:
    7864          32 :                 errcode = WERR_OK;
    7865          32 :                 break;
    7866           0 :         default:
    7867           0 :                 return WERR_INVALID_LEVEL;
    7868             :         }
    7869             : 
    7870         396 :         if (!W_ERROR_IS_OK(errcode)) {
    7871           0 :                 return errcode;
    7872             :         }
    7873             : 
    7874         396 :         if (r->in.ctr == NULL) {
    7875         364 :                 return errcode;
    7876             :         }
    7877             : 
    7878          32 :         switch (r->in.ctr->level) {
    7879          32 :         case 1:
    7880          32 :                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
    7881             :                                            lp_const_servicename(snum),
    7882             :                                            r->in.job_id,
    7883          32 :                                            r->in.ctr->info.info1);
    7884          32 :                 break;
    7885           0 :         case 2:
    7886             :         case 3:
    7887             :         case 4:
    7888             :         default:
    7889           0 :                 return WERR_INVALID_LEVEL;
    7890             :         }
    7891             : 
    7892          32 :         return errcode;
    7893             : }
    7894             : 
    7895             : /****************************************************************************
    7896             :  Enumerates all printer drivers by level and architecture.
    7897             : ****************************************************************************/
    7898             : 
    7899         460 : static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
    7900             :                                                        const struct auth_session_info *session_info,
    7901             :                                                        struct messaging_context *msg_ctx,
    7902             :                                                        const char *servername,
    7903             :                                                        const char *architecture,
    7904             :                                                        uint32_t level,
    7905             :                                                        union spoolss_DriverInfo **info_p,
    7906             :                                                        uint32_t *count_p)
    7907             : {
    7908           0 :         int i;
    7909           0 :         uint32_t version;
    7910           0 :         struct spoolss_DriverInfo8 *driver;
    7911         460 :         union spoolss_DriverInfo *info = NULL;
    7912         460 :         uint32_t count = 0;
    7913         460 :         WERROR result = WERR_OK;
    7914           0 :         uint32_t num_drivers;
    7915           0 :         const char **drivers;
    7916           0 :         struct dcerpc_binding_handle *b;
    7917         460 :         TALLOC_CTX *tmp_ctx = NULL;
    7918             : 
    7919         460 :         *count_p = 0;
    7920         460 :         *info_p = NULL;
    7921             : 
    7922         460 :         tmp_ctx = talloc_new(mem_ctx);
    7923         460 :         if (!tmp_ctx) {
    7924           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    7925             :         }
    7926             : 
    7927         460 :         result = winreg_printer_binding_handle(tmp_ctx,
    7928             :                                                session_info,
    7929             :                                                msg_ctx,
    7930             :                                                &b);
    7931         460 :         if (!W_ERROR_IS_OK(result)) {
    7932           0 :                 goto out;
    7933             :         }
    7934             : 
    7935        2300 :         for (version=0; version<DRIVER_MAX_VERSION; version++) {
    7936        1840 :                 result = winreg_get_driver_list(tmp_ctx, b,
    7937             :                                                 architecture, version,
    7938             :                                                 &num_drivers, &drivers);
    7939        1840 :                 if (!W_ERROR_IS_OK(result)) {
    7940           0 :                         goto out;
    7941             :                 }
    7942        1840 :                 DEBUG(4, ("we have:[%d] drivers in environment"
    7943             :                           " [%s] and version [%d]\n",
    7944             :                           num_drivers, architecture, version));
    7945             : 
    7946        1840 :                 if (num_drivers != 0) {
    7947           0 :                         info = talloc_realloc(tmp_ctx, info,
    7948             :                                                     union spoolss_DriverInfo,
    7949             :                                                     count + num_drivers);
    7950           0 :                         if (!info) {
    7951           0 :                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
    7952             :                                         "failed to enlarge driver info buffer!\n"));
    7953           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
    7954           0 :                                 goto out;
    7955             :                         }
    7956             :                 }
    7957             : 
    7958        1840 :                 for (i = 0; i < num_drivers; i++) {
    7959           0 :                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
    7960             : 
    7961           0 :                         result = winreg_get_driver(tmp_ctx, b,
    7962           0 :                                                    architecture, drivers[i],
    7963             :                                                    version, &driver);
    7964           0 :                         if (!W_ERROR_IS_OK(result)) {
    7965           0 :                                 goto out;
    7966             :                         }
    7967             : 
    7968           0 :                         switch (level) {
    7969           0 :                         case 1:
    7970           0 :                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
    7971             :                                                                    driver, servername);
    7972           0 :                                 break;
    7973           0 :                         case 2:
    7974           0 :                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
    7975             :                                                                    driver, servername);
    7976           0 :                                 break;
    7977           0 :                         case 3:
    7978           0 :                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
    7979             :                                                                    driver, servername);
    7980           0 :                                 break;
    7981           0 :                         case 4:
    7982           0 :                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
    7983             :                                                                    driver, servername);
    7984           0 :                                 break;
    7985           0 :                         case 5:
    7986           0 :                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
    7987             :                                                                    driver, servername);
    7988           0 :                                 break;
    7989           0 :                         case 6:
    7990           0 :                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
    7991             :                                                                    driver, servername);
    7992           0 :                                 break;
    7993           0 :                         case 8:
    7994           0 :                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
    7995             :                                                                    driver, servername);
    7996           0 :                                 break;
    7997           0 :                         default:
    7998           0 :                                 result = WERR_INVALID_LEVEL;
    7999           0 :                                 break;
    8000             :                         }
    8001             : 
    8002           0 :                         TALLOC_FREE(driver);
    8003             : 
    8004           0 :                         if (!W_ERROR_IS_OK(result)) {
    8005           0 :                                 goto out;
    8006             :                         }
    8007             :                 }
    8008             : 
    8009        1840 :                 count += num_drivers;
    8010        1840 :                 TALLOC_FREE(drivers);
    8011             :         }
    8012             : 
    8013         460 : out:
    8014         460 :         if (W_ERROR_IS_OK(result)) {
    8015         460 :                 *info_p = talloc_move(mem_ctx, &info);
    8016         460 :                 *count_p = count;
    8017             :         }
    8018             : 
    8019         460 :         talloc_free(tmp_ctx);
    8020         460 :         return result;
    8021             : }
    8022             : 
    8023             : /****************************************************************************
    8024             :  Enumerates all printer drivers by level.
    8025             : ****************************************************************************/
    8026             : 
    8027         108 : static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
    8028             :                                        const struct auth_session_info *session_info,
    8029             :                                        struct messaging_context *msg_ctx,
    8030             :                                        const char *servername,
    8031             :                                        const char *architecture,
    8032             :                                        uint32_t level,
    8033             :                                        union spoolss_DriverInfo **info_p,
    8034             :                                        uint32_t *count_p)
    8035             : {
    8036           0 :         uint32_t a,i;
    8037         108 :         WERROR result = WERR_OK;
    8038             : 
    8039         108 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
    8040             : 
    8041         440 :                 for (a=0; archi_table[a].long_archi != NULL; a++) {
    8042             : 
    8043         396 :                         union spoolss_DriverInfo *info = NULL;
    8044         396 :                         uint32_t count = 0;
    8045             : 
    8046         396 :                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
    8047             :                                                                           session_info,
    8048             :                                                                           msg_ctx,
    8049             :                                                                           servername,
    8050         396 :                                                                           archi_table[a].long_archi,
    8051             :                                                                           level,
    8052             :                                                                           &info,
    8053             :                                                                           &count);
    8054         396 :                         if (!W_ERROR_IS_OK(result)) {
    8055           0 :                                 continue;
    8056             :                         }
    8057             : 
    8058         396 :                         for (i=0; i < count; i++) {
    8059           0 :                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
    8060             :                                              info[i], info_p, count_p);
    8061             :                         }
    8062             :                 }
    8063             : 
    8064          44 :                 return result;
    8065             :         }
    8066             : 
    8067          64 :         return enumprinterdrivers_level_by_architecture(mem_ctx,
    8068             :                                                         session_info,
    8069             :                                                         msg_ctx,
    8070             :                                                         servername,
    8071             :                                                         architecture,
    8072             :                                                         level,
    8073             :                                                         info_p,
    8074             :                                                         count_p);
    8075             : }
    8076             : 
    8077             : /****************************************************************
    8078             :  _spoolss_EnumPrinterDrivers
    8079             : ****************************************************************/
    8080             : 
    8081         108 : WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
    8082             :                                    struct spoolss_EnumPrinterDrivers *r)
    8083             : {
    8084           0 :         const char *cservername;
    8085           0 :         WERROR result;
    8086             : 
    8087             :         /* that's an [in out] buffer */
    8088             : 
    8089         108 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8090           0 :                 return WERR_INVALID_PARAMETER;
    8091             :         }
    8092             : 
    8093         108 :         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
    8094             : 
    8095         108 :         *r->out.needed = 0;
    8096         108 :         *r->out.count = 0;
    8097         108 :         *r->out.info = NULL;
    8098             : 
    8099         108 :         cservername = canon_servername(r->in.server);
    8100             : 
    8101         108 :         if (!is_myname_or_ipaddr(cservername)) {
    8102           0 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    8103             :         }
    8104             : 
    8105         108 :         result = enumprinterdrivers_level(p->mem_ctx,
    8106             :                                           get_session_info_system(),
    8107             :                                           p->msg_ctx,
    8108             :                                           cservername,
    8109             :                                           r->in.environment,
    8110             :                                           r->in.level,
    8111             :                                           r->out.info,
    8112             :                                           r->out.count);
    8113         108 :         if (!W_ERROR_IS_OK(result)) {
    8114           0 :                 return result;
    8115             :         }
    8116             : 
    8117         108 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8118             :                                                      spoolss_EnumPrinterDrivers,
    8119             :                                                      *r->out.info, r->in.level,
    8120             :                                                      *r->out.count);
    8121         108 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8122         108 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8123             : 
    8124         108 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8125             : }
    8126             : 
    8127             : /****************************************************************
    8128             :  _spoolss_EnumForms
    8129             : ****************************************************************/
    8130             : 
    8131         560 : WERROR _spoolss_EnumForms(struct pipes_struct *p,
    8132             :                           struct spoolss_EnumForms *r)
    8133             : {
    8134           0 :         WERROR result;
    8135             : 
    8136         560 :         *r->out.count = 0;
    8137         560 :         *r->out.needed = 0;
    8138         560 :         *r->out.info = NULL;
    8139             : 
    8140             :         /* that's an [in out] buffer */
    8141             : 
    8142         560 :         if (!r->in.buffer && (r->in.offered != 0) ) {
    8143           0 :                 return WERR_INVALID_PARAMETER;
    8144             :         }
    8145             : 
    8146         560 :         DEBUG(4,("_spoolss_EnumForms\n"));
    8147         560 :         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
    8148         560 :         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
    8149             : 
    8150         560 :         switch (r->in.level) {
    8151         536 :         case 1:
    8152         536 :                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
    8153             :                                                    get_session_info_system(),
    8154             :                                                    p->msg_ctx,
    8155             :                                                    r->out.count,
    8156             :                                                    r->out.info);
    8157         536 :                 break;
    8158          24 :         default:
    8159          24 :                 result = WERR_INVALID_LEVEL;
    8160          24 :                 break;
    8161             :         }
    8162             : 
    8163         560 :         if (!W_ERROR_IS_OK(result)) {
    8164          24 :                 return result;
    8165             :         }
    8166             : 
    8167         536 :         if (*r->out.count == 0) {
    8168           0 :                 return WERR_NO_MORE_ITEMS;
    8169             :         }
    8170             : 
    8171         536 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8172             :                                                      spoolss_EnumForms,
    8173             :                                                      *r->out.info, r->in.level,
    8174             :                                                      *r->out.count);
    8175         536 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8176         536 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8177             : 
    8178         536 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8179             : }
    8180             : 
    8181             : /****************************************************************
    8182             :  _spoolss_GetForm
    8183             : ****************************************************************/
    8184             : 
    8185        5040 : WERROR _spoolss_GetForm(struct pipes_struct *p,
    8186             :                         struct spoolss_GetForm *r)
    8187             : {
    8188           0 :         WERROR result;
    8189             : 
    8190             :         /* that's an [in out] buffer */
    8191             : 
    8192        5040 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8193           0 :                 TALLOC_FREE(r->out.info);
    8194           0 :                 return WERR_INVALID_PARAMETER;
    8195             :         }
    8196             : 
    8197        5040 :         DEBUG(4,("_spoolss_GetForm\n"));
    8198        5040 :         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
    8199        5040 :         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
    8200             : 
    8201        5040 :         switch (r->in.level) {
    8202        5040 :         case 1:
    8203        5040 :                 result = winreg_printer_getform1_internal(p->mem_ctx,
    8204             :                                                  get_session_info_system(),
    8205             :                                                  p->msg_ctx,
    8206             :                                                  r->in.form_name,
    8207        5040 :                                                  &r->out.info->info1);
    8208        5040 :                 break;
    8209           0 :         default:
    8210           0 :                 result = WERR_INVALID_LEVEL;
    8211           0 :                 break;
    8212             :         }
    8213             : 
    8214        5040 :         if (!W_ERROR_IS_OK(result)) {
    8215           0 :                 TALLOC_FREE(r->out.info);
    8216           0 :                 return result;
    8217             :         }
    8218             : 
    8219        5040 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
    8220             :                                                r->out.info, r->in.level);
    8221        5040 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    8222             : 
    8223        5040 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8224             : }
    8225             : 
    8226             : /****************************************************************************
    8227             : ****************************************************************************/
    8228             : 
    8229           8 : static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
    8230             :                           struct spoolss_PortInfo1 *r,
    8231             :                           const char *name)
    8232             : {
    8233           8 :         r->port_name = talloc_strdup(mem_ctx, name);
    8234           8 :         W_ERROR_HAVE_NO_MEMORY(r->port_name);
    8235             : 
    8236           8 :         return WERR_OK;
    8237             : }
    8238             : 
    8239             : /****************************************************************************
    8240             :  TODO: This probably needs distinguish between TCP/IP and Local ports
    8241             :  somehow.
    8242             : ****************************************************************************/
    8243             : 
    8244          16 : static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
    8245             :                           struct spoolss_PortInfo2 *r,
    8246             :                           const char *name)
    8247             : {
    8248          16 :         r->port_name = talloc_strdup(mem_ctx, name);
    8249          16 :         W_ERROR_HAVE_NO_MEMORY(r->port_name);
    8250             : 
    8251          16 :         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
    8252          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    8253             : 
    8254          16 :         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
    8255          16 :         W_ERROR_HAVE_NO_MEMORY(r->description);
    8256             : 
    8257          16 :         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
    8258          16 :         r->reserved = 0;
    8259             : 
    8260          16 :         return WERR_OK;
    8261             : }
    8262             : 
    8263             : 
    8264             : /****************************************************************************
    8265             :  wrapper around the enum ports command
    8266             : ****************************************************************************/
    8267             : 
    8268          24 : static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
    8269             : {
    8270           0 :         const struct loadparm_substitution *lp_sub =
    8271          24 :                 loadparm_s3_global_substitution();
    8272          24 :         char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
    8273          24 :         char **qlines = NULL;
    8274          24 :         char *command = NULL;
    8275           0 :         int numlines;
    8276           0 :         int ret;
    8277           0 :         int fd;
    8278             : 
    8279          24 :         *count = 0;
    8280          24 :         *lines = NULL;
    8281             : 
    8282             :         /* if no hook then just fill in the default port */
    8283             : 
    8284          24 :         if ( !*cmd ) {
    8285          24 :                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
    8286           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8287             :                 }
    8288          24 :                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
    8289           0 :                         TALLOC_FREE(qlines);
    8290           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8291             :                 }
    8292          24 :                 qlines[1] = NULL;
    8293          24 :                 numlines = 1;
    8294             :         }
    8295             :         else {
    8296             :                 /* we have a valid enumport command */
    8297             : 
    8298           0 :                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
    8299           0 :                 if (!command) {
    8300           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8301             :                 }
    8302             : 
    8303           0 :                 DEBUG(10,("Running [%s]\n", command));
    8304           0 :                 ret = smbrun(command, &fd, NULL);
    8305           0 :                 DEBUG(10,("Returned [%d]\n", ret));
    8306           0 :                 TALLOC_FREE(command);
    8307           0 :                 if (ret != 0) {
    8308           0 :                         if (fd != -1) {
    8309           0 :                                 close(fd);
    8310             :                         }
    8311           0 :                         return WERR_ACCESS_DENIED;
    8312             :                 }
    8313             : 
    8314           0 :                 numlines = 0;
    8315           0 :                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
    8316           0 :                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
    8317           0 :                 close(fd);
    8318             :         }
    8319             : 
    8320          24 :         *count = numlines;
    8321          24 :         *lines = qlines;
    8322             : 
    8323          24 :         return WERR_OK;
    8324             : }
    8325             : 
    8326             : /****************************************************************************
    8327             :  enumports level 1.
    8328             : ****************************************************************************/
    8329             : 
    8330           8 : static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
    8331             :                                 union spoolss_PortInfo **info_p,
    8332             :                                 uint32_t *count)
    8333             : {
    8334           8 :         union spoolss_PortInfo *info = NULL;
    8335           8 :         int i=0;
    8336           8 :         WERROR result = WERR_OK;
    8337           8 :         char **qlines = NULL;
    8338           8 :         int numlines = 0;
    8339             : 
    8340           8 :         result = enumports_hook(talloc_tos(), &numlines, &qlines );
    8341           8 :         if (!W_ERROR_IS_OK(result)) {
    8342           0 :                 goto out;
    8343             :         }
    8344             : 
    8345           8 :         if (numlines) {
    8346           8 :                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
    8347           8 :                 if (!info) {
    8348           0 :                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
    8349           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    8350           0 :                         goto out;
    8351             :                 }
    8352             : 
    8353          16 :                 for (i=0; i<numlines; i++) {
    8354           8 :                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
    8355           8 :                         result = fill_port_1(info, &info[i].info1, qlines[i]);
    8356           8 :                         if (!W_ERROR_IS_OK(result)) {
    8357           0 :                                 goto out;
    8358             :                         }
    8359             :                 }
    8360             :         }
    8361           8 :         TALLOC_FREE(qlines);
    8362             : 
    8363           0 : out:
    8364           8 :         if (!W_ERROR_IS_OK(result)) {
    8365           0 :                 TALLOC_FREE(info);
    8366           0 :                 TALLOC_FREE(qlines);
    8367           0 :                 *count = 0;
    8368           0 :                 *info_p = NULL;
    8369           0 :                 return result;
    8370             :         }
    8371             : 
    8372           8 :         *info_p = info;
    8373           8 :         *count = numlines;
    8374             : 
    8375           8 :         return WERR_OK;
    8376             : }
    8377             : 
    8378             : /****************************************************************************
    8379             :  enumports level 2.
    8380             : ****************************************************************************/
    8381             : 
    8382          16 : static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
    8383             :                                 union spoolss_PortInfo **info_p,
    8384             :                                 uint32_t *count)
    8385             : {
    8386          16 :         union spoolss_PortInfo *info = NULL;
    8387          16 :         int i=0;
    8388          16 :         WERROR result = WERR_OK;
    8389          16 :         char **qlines = NULL;
    8390          16 :         int numlines = 0;
    8391             : 
    8392          16 :         result = enumports_hook(talloc_tos(), &numlines, &qlines );
    8393          16 :         if (!W_ERROR_IS_OK(result)) {
    8394           0 :                 goto out;
    8395             :         }
    8396             : 
    8397          16 :         if (numlines) {
    8398          16 :                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
    8399          16 :                 if (!info) {
    8400           0 :                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
    8401           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    8402           0 :                         goto out;
    8403             :                 }
    8404             : 
    8405          32 :                 for (i=0; i<numlines; i++) {
    8406          16 :                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
    8407          16 :                         result = fill_port_2(info, &info[i].info2, qlines[i]);
    8408          16 :                         if (!W_ERROR_IS_OK(result)) {
    8409           0 :                                 goto out;
    8410             :                         }
    8411             :                 }
    8412             :         }
    8413          16 :         TALLOC_FREE(qlines);
    8414             : 
    8415           0 : out:
    8416          16 :         if (!W_ERROR_IS_OK(result)) {
    8417           0 :                 TALLOC_FREE(info);
    8418           0 :                 TALLOC_FREE(qlines);
    8419           0 :                 *count = 0;
    8420           0 :                 *info_p = NULL;
    8421           0 :                 return result;
    8422             :         }
    8423             : 
    8424          16 :         *info_p = info;
    8425          16 :         *count = numlines;
    8426             : 
    8427          16 :         return WERR_OK;
    8428             : }
    8429             : 
    8430             : /****************************************************************
    8431             :  _spoolss_EnumPorts
    8432             : ****************************************************************/
    8433             : 
    8434          24 : WERROR _spoolss_EnumPorts(struct pipes_struct *p,
    8435             :                           struct spoolss_EnumPorts *r)
    8436             : {
    8437           0 :         WERROR result;
    8438             : 
    8439             :         /* that's an [in out] buffer */
    8440             : 
    8441          24 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8442           0 :                 return WERR_INVALID_PARAMETER;
    8443             :         }
    8444             : 
    8445          24 :         DEBUG(4,("_spoolss_EnumPorts\n"));
    8446             : 
    8447          24 :         *r->out.count = 0;
    8448          24 :         *r->out.needed = 0;
    8449          24 :         *r->out.info = NULL;
    8450             : 
    8451          24 :         switch (r->in.level) {
    8452           8 :         case 1:
    8453           8 :                 result = enumports_level_1(p->mem_ctx, r->out.info,
    8454             :                                            r->out.count);
    8455           8 :                 break;
    8456          16 :         case 2:
    8457          16 :                 result = enumports_level_2(p->mem_ctx, r->out.info,
    8458             :                                            r->out.count);
    8459          16 :                 break;
    8460           0 :         default:
    8461           0 :                 return WERR_INVALID_LEVEL;
    8462             :         }
    8463             : 
    8464          24 :         if (!W_ERROR_IS_OK(result)) {
    8465           0 :                 return result;
    8466             :         }
    8467             : 
    8468          24 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8469             :                                                      spoolss_EnumPorts,
    8470             :                                                      *r->out.info, r->in.level,
    8471             :                                                      *r->out.count);
    8472          24 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8473          24 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8474             : 
    8475          24 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8476             : }
    8477             : 
    8478             : /****************************************************************************
    8479             : ****************************************************************************/
    8480             : 
    8481          96 : static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
    8482             :                                            const char *server,
    8483             :                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
    8484             :                                            struct spoolss_DeviceMode *devmode,
    8485             :                                            struct security_descriptor *secdesc,
    8486             :                                            struct spoolss_UserLevelCtr *user_ctr,
    8487             :                                            struct policy_handle *handle)
    8488             : {
    8489          96 :         struct dcesrv_call_state *dce_call = p->dce_call;
    8490          96 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    8491           0 :         const struct tsocket_address *remote_address =
    8492          96 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    8493           0 :         struct auth_session_info *session_info =
    8494          96 :                 dcesrv_call_session_info(dce_call);
    8495          96 :         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
    8496          96 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
    8497           0 :         const struct loadparm_substitution *lp_sub =
    8498          96 :                 loadparm_s3_global_substitution();
    8499           0 :         int     snum;
    8500          96 :         WERROR err = WERR_OK;
    8501             : 
    8502             :         /* samba does not have a concept of local, non-shared printers yet, so
    8503             :          * make sure we always setup sharename - gd */
    8504          96 :         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
    8505          96 :             (info2->printername != NULL && info2->printername[0] != '\0')) {
    8506          80 :                 DEBUG(5, ("spoolss_addprinterex_level_2: "
    8507             :                         "no sharename has been set, setting printername %s as sharename\n",
    8508             :                         info2->printername));
    8509          80 :                 info2->sharename = info2->printername;
    8510             :         }
    8511             : 
    8512             :         /* check to see if the printer already exists */
    8513          96 :         if ((snum = print_queue_snum(info2->sharename)) != -1) {
    8514          16 :                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
    8515             :                         info2->sharename));
    8516          16 :                 return WERR_PRINTER_ALREADY_EXISTS;
    8517             :         }
    8518             : 
    8519          80 :         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
    8520          80 :                 if ((snum = print_queue_snum(info2->printername)) != -1) {
    8521           0 :                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
    8522             :                                 info2->printername));
    8523           0 :                         return WERR_PRINTER_ALREADY_EXISTS;
    8524             :                 }
    8525             :         }
    8526             : 
    8527             :         /* validate printer info struct */
    8528          80 :         if (!info2->printername || strlen(info2->printername) == 0) {
    8529          16 :                 return WERR_INVALID_PRINTER_NAME;
    8530             :         }
    8531          64 :         if (!info2->portname || strlen(info2->portname) == 0) {
    8532          16 :                 return WERR_UNKNOWN_PORT;
    8533             :         }
    8534          48 :         if (!info2->drivername || strlen(info2->drivername) == 0) {
    8535          16 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    8536             :         }
    8537          32 :         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
    8538          16 :                 return WERR_UNKNOWN_PRINTPROCESSOR;
    8539             :         }
    8540             : 
    8541             :         /* FIXME!!!  smbd should check to see if the driver is installed before
    8542             :            trying to add a printer like this  --jerry */
    8543             : 
    8544          16 :         if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
    8545           0 :                 char *raddr;
    8546             : 
    8547          16 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    8548             :                                                          p->mem_ctx);
    8549          16 :                 if (raddr == NULL) {
    8550           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8551             :                 }
    8552             : 
    8553          16 :                 if ( !add_printer_hook(p->mem_ctx, session_info->security_token,
    8554             :                                        info2, raddr,
    8555             :                                        p->msg_ctx) ) {
    8556           0 :                         return WERR_ACCESS_DENIED;
    8557             :                 }
    8558             :         } else {
    8559           0 :                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
    8560             :                         "smb.conf parameter \"addprinter command\" is defined. This "
    8561             :                         "parameter must exist for this call to succeed\n",
    8562             :                         info2->sharename ));
    8563             :         }
    8564             : 
    8565          16 :         if ((snum = print_queue_snum(info2->sharename)) == -1) {
    8566           0 :                 return WERR_ACCESS_DENIED;
    8567             :         }
    8568             : 
    8569             :         /* you must be a printer admin to add a new printer */
    8570          16 :         if (!W_ERROR_IS_OK(print_access_check(session_info,
    8571             :                                               p->msg_ctx,
    8572             :                                               snum,
    8573             :                                               PRINTER_ACCESS_ADMINISTER))) {
    8574           0 :                 return WERR_ACCESS_DENIED;
    8575             :         }
    8576             : 
    8577             :         /*
    8578             :          * Do sanity check on the requested changes for Samba.
    8579             :          */
    8580             : 
    8581          16 :         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
    8582           0 :                 return WERR_INVALID_PARAMETER;
    8583             :         }
    8584             : 
    8585          16 :         if (devmode == NULL) {
    8586          16 :                 info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
    8587             :         }
    8588             : 
    8589          16 :         err = update_dsspooler(p->mem_ctx,
    8590             :                                get_session_info_system(),
    8591             :                                p->msg_ctx,
    8592             :                                0,
    8593             :                                info2,
    8594             :                                NULL);
    8595          16 :         if (!W_ERROR_IS_OK(err)) {
    8596           0 :                 return err;
    8597             :         }
    8598             : 
    8599          16 :         err = winreg_update_printer_internal(p->mem_ctx,
    8600             :                                     get_session_info_system(),
    8601             :                                     p->msg_ctx,
    8602             :                                     info2->sharename,
    8603             :                                     info2_mask,
    8604             :                                     info2,
    8605             :                                     devmode,
    8606             :                                     secdesc);
    8607          16 :         if (!W_ERROR_IS_OK(err)) {
    8608           0 :                 return err;
    8609             :         }
    8610             : 
    8611          16 :         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
    8612          16 :         if (!W_ERROR_IS_OK(err)) {
    8613             :                 /* Handle open failed - remove addition. */
    8614           0 :                 ZERO_STRUCTP(handle);
    8615           0 :                 return err;
    8616             :         }
    8617             : 
    8618          16 :         return WERR_OK;
    8619             : }
    8620             : 
    8621             : /****************************************************************
    8622             :  _spoolss_AddPrinterEx
    8623             : ****************************************************************/
    8624             : 
    8625          96 : WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
    8626             :                              struct spoolss_AddPrinterEx *r)
    8627             : {
    8628          96 :         switch (r->in.info_ctr->level) {
    8629           0 :         case 1:
    8630             :                 /* we don't handle yet */
    8631             :                 /* but I know what to do ... */
    8632           0 :                 return WERR_INVALID_LEVEL;
    8633          96 :         case 2:
    8634          96 :                 return spoolss_addprinterex_level_2(p, r->in.server,
    8635             :                                                     r->in.info_ctr,
    8636          96 :                                                     r->in.devmode_ctr->devmode,
    8637          96 :                                                     r->in.secdesc_ctr->sd,
    8638             :                                                     r->in.userlevel_ctr,
    8639             :                                                     r->out.handle);
    8640           0 :         default:
    8641           0 :                 return WERR_INVALID_LEVEL;
    8642             :         }
    8643             : }
    8644             : 
    8645             : /****************************************************************
    8646             :  _spoolss_AddPrinter
    8647             : ****************************************************************/
    8648             : 
    8649          72 : WERROR _spoolss_AddPrinter(struct pipes_struct *p,
    8650             :                            struct spoolss_AddPrinter *r)
    8651             : {
    8652           0 :         struct spoolss_AddPrinterEx a;
    8653           0 :         struct spoolss_UserLevelCtr userlevel_ctr;
    8654             : 
    8655          72 :         ZERO_STRUCT(userlevel_ctr);
    8656             : 
    8657          72 :         userlevel_ctr.level = 1;
    8658             : 
    8659          72 :         a.in.server             = r->in.server;
    8660          72 :         a.in.info_ctr           = r->in.info_ctr;
    8661          72 :         a.in.devmode_ctr        = r->in.devmode_ctr;
    8662          72 :         a.in.secdesc_ctr        = r->in.secdesc_ctr;
    8663          72 :         a.in.userlevel_ctr      = &userlevel_ctr;
    8664          72 :         a.out.handle            = r->out.handle;
    8665             : 
    8666          72 :         return _spoolss_AddPrinterEx(p, &a);
    8667             : }
    8668             : 
    8669             : /****************************************************************
    8670             :  _spoolss_AddPrinterDriverEx
    8671             : ****************************************************************/
    8672             : 
    8673           0 : WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
    8674             :                                    struct spoolss_AddPrinterDriverEx *r)
    8675             : {
    8676           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    8677           0 :         struct auth_session_info *session_info =
    8678           0 :                 dcesrv_call_session_info(dce_call);
    8679           0 :         WERROR err = WERR_OK;
    8680           0 :         const char *driver_name = NULL;
    8681           0 :         const char *driver_directory = NULL;
    8682           0 :         uint32_t version;
    8683             : 
    8684             :         /*
    8685             :          * we only support the semantics of AddPrinterDriver()
    8686             :          * i.e. only copy files that are newer than existing ones
    8687             :          */
    8688             : 
    8689           0 :         if (r->in.flags == 0) {
    8690           0 :                 return WERR_INVALID_PARAMETER;
    8691             :         }
    8692             : 
    8693           0 :         if (!(r->in.flags & APD_COPY_ALL_FILES) &&
    8694           0 :             !(r->in.flags & APD_COPY_NEW_FILES)) {
    8695           0 :                 return WERR_ACCESS_DENIED;
    8696             :         }
    8697             : 
    8698             :         /* FIXME */
    8699           0 :         if (r->in.info_ctr->level != 3 &&
    8700           0 :             r->in.info_ctr->level != 6 &&
    8701           0 :             r->in.info_ctr->level != 8) {
    8702           0 :                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
    8703             :                         r->in.info_ctr->level));
    8704           0 :                 return WERR_INVALID_LEVEL;
    8705             :         }
    8706             : 
    8707           0 :         DEBUG(5,("Cleaning driver's information\n"));
    8708           0 :         err = clean_up_driver_struct(p->mem_ctx,
    8709             :                                      session_info,
    8710           0 :                                      r->in.info_ctr,
    8711             :                                      r->in.flags,
    8712             :                                      &driver_directory);
    8713           0 :         if (!W_ERROR_IS_OK(err)) {
    8714           0 :                 DBG_ERR("clean_up_driver_struct failed - %s\n",
    8715             :                         win_errstr(err));
    8716           0 :                 goto done;
    8717             :         }
    8718             : 
    8719           0 :         DEBUG(5,("Moving driver to final destination\n"));
    8720           0 :         err = move_driver_to_download_area(session_info,
    8721           0 :                                            r->in.info_ctr,
    8722             :                                            driver_directory);
    8723           0 :         if (!W_ERROR_IS_OK(err)) {
    8724           0 :                 DBG_ERR("move_driver_to_download_area failed - %s\n",
    8725             :                         win_errstr(err));
    8726           0 :                 goto done;
    8727             :         }
    8728             : 
    8729           0 :         err = winreg_add_driver_internal(p->mem_ctx,
    8730             :                                 get_session_info_system(),
    8731             :                                 p->msg_ctx,
    8732             :                                 r->in.info_ctr,
    8733             :                                 &driver_name,
    8734             :                                 &version);
    8735           0 :         if (!W_ERROR_IS_OK(err)) {
    8736           0 :                 DBG_ERR("winreg_add_driver_internal failed - %s\n",
    8737             :                         win_errstr(err));
    8738           0 :                 goto done;
    8739             :         }
    8740             : 
    8741             :         /*
    8742             :          * I think this is where the DrvUpgradePrinter() hook would be
    8743             :          * be called in a driver's interface DLL on a Windows NT 4.0/2k
    8744             :          * server.  Right now, we just need to send ourselves a message
    8745             :          * to update each printer bound to this driver.   --jerry
    8746             :          */
    8747             : 
    8748           0 :         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
    8749           0 :                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
    8750             :                         __func__, driver_name));
    8751             :         }
    8752             : 
    8753           0 : done:
    8754           0 :         return err;
    8755             : }
    8756             : 
    8757             : /****************************************************************
    8758             :  _spoolss_AddPrinterDriver
    8759             : ****************************************************************/
    8760             : 
    8761           0 : WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
    8762             :                                  struct spoolss_AddPrinterDriver *r)
    8763             : {
    8764           0 :         struct spoolss_AddPrinterDriverEx a;
    8765             : 
    8766           0 :         switch (r->in.info_ctr->level) {
    8767           0 :         case 2:
    8768             :         case 3:
    8769             :         case 4:
    8770             :         case 5:
    8771           0 :                 break;
    8772           0 :         default:
    8773           0 :                 return WERR_INVALID_LEVEL;
    8774             :         }
    8775             : 
    8776           0 :         a.in.servername         = r->in.servername;
    8777           0 :         a.in.info_ctr           = r->in.info_ctr;
    8778           0 :         a.in.flags              = APD_COPY_NEW_FILES;
    8779             : 
    8780           0 :         return _spoolss_AddPrinterDriverEx(p, &a);
    8781             : }
    8782             : 
    8783             : /****************************************************************************
    8784             : ****************************************************************************/
    8785             : 
    8786             : struct _spoolss_paths {
    8787             :         int type;
    8788             :         const char *share;
    8789             :         const char *dir;
    8790             : };
    8791             : 
    8792             : enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
    8793             : 
    8794             : static const struct _spoolss_paths spoolss_paths[]= {
    8795             :         { SPOOLSS_DRIVER_PATH,          "print$",     "DRIVERS" },
    8796             :         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",   "PRTPROCS" }
    8797             : };
    8798             : 
    8799         208 : static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
    8800             :                                           const char *servername,
    8801             :                                           const char *environment,
    8802             :                                           int component,
    8803             :                                           char **path)
    8804             : {
    8805         208 :         const char *pservername = NULL;
    8806           0 :         const char *long_archi;
    8807           0 :         const char *short_archi;
    8808             : 
    8809         208 :         *path = NULL;
    8810             : 
    8811             :         /* environment may be empty */
    8812         208 :         if (environment && strlen(environment)) {
    8813         208 :                 long_archi = environment;
    8814             :         } else {
    8815           0 :                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    8816             :                                                   "spoolss", "architecture",
    8817             :                                                   GLOBAL_SPOOLSS_ARCHITECTURE);
    8818             :         }
    8819             : 
    8820             :         /* servername may be empty */
    8821         208 :         if (servername && strlen(servername)) {
    8822         144 :                 pservername = canon_servername(servername);
    8823             : 
    8824         144 :                 if (!is_myname_or_ipaddr(pservername)) {
    8825           0 :                         return WERR_INVALID_PARAMETER;
    8826             :                 }
    8827             :         }
    8828             : 
    8829         208 :         if (!(short_archi = get_short_archi(long_archi))) {
    8830           0 :                 return WERR_INVALID_ENVIRONMENT;
    8831             :         }
    8832             : 
    8833         208 :         switch (component) {
    8834         208 :         case SPOOLSS_PRTPROCS_PATH:
    8835             :         case SPOOLSS_DRIVER_PATH:
    8836         208 :                 if (pservername) {
    8837         144 :                         *path = talloc_asprintf(mem_ctx,
    8838             :                                         "\\\\%s\\%s\\%s",
    8839             :                                         pservername,
    8840         144 :                                         spoolss_paths[component].share,
    8841             :                                         short_archi);
    8842             :                 } else {
    8843          64 :                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
    8844             :                                         SPOOLSS_DEFAULT_SERVER_PATH,
    8845          64 :                                         spoolss_paths[component].dir,
    8846             :                                         short_archi);
    8847             :                 }
    8848         208 :                 break;
    8849           0 :         default:
    8850           0 :                 return WERR_INVALID_PARAMETER;
    8851             :         }
    8852             : 
    8853         208 :         if (!*path) {
    8854           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    8855             :         }
    8856             : 
    8857         208 :         return WERR_OK;
    8858             : }
    8859             : 
    8860             : /****************************************************************************
    8861             : ****************************************************************************/
    8862             : 
    8863         168 : static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
    8864             :                                           const char *servername,
    8865             :                                           const char *environment,
    8866             :                                           struct spoolss_DriverDirectoryInfo1 *r)
    8867             : {
    8868           0 :         WERROR werr;
    8869         168 :         char *path = NULL;
    8870             : 
    8871         168 :         werr = compose_spoolss_server_path(mem_ctx,
    8872             :                                            servername,
    8873             :                                            environment,
    8874             :                                            SPOOLSS_DRIVER_PATH,
    8875             :                                            &path);
    8876         168 :         if (!W_ERROR_IS_OK(werr)) {
    8877           0 :                 return werr;
    8878             :         }
    8879             : 
    8880         168 :         DEBUG(4,("printer driver directory: [%s]\n", path));
    8881             : 
    8882         168 :         r->directory_name = path;
    8883             : 
    8884         168 :         return WERR_OK;
    8885             : }
    8886             : 
    8887             : /****************************************************************
    8888             :  _spoolss_GetPrinterDriverDirectory
    8889             : ****************************************************************/
    8890             : 
    8891         168 : WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
    8892             :                                           struct spoolss_GetPrinterDriverDirectory *r)
    8893             : {
    8894           0 :         WERROR werror;
    8895             : 
    8896             :         /* that's an [in out] buffer */
    8897             : 
    8898         168 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8899           0 :                 TALLOC_FREE(r->out.info);
    8900           0 :                 return WERR_INVALID_PARAMETER;
    8901             :         }
    8902             : 
    8903         168 :         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
    8904             :                 r->in.level));
    8905             : 
    8906         168 :         *r->out.needed = 0;
    8907             : 
    8908             :         /* r->in.level is ignored */
    8909             : 
    8910         168 :         werror = getprinterdriverdir_level_1(p->mem_ctx,
    8911             :                                              r->in.server,
    8912             :                                              r->in.environment,
    8913         168 :                                              &r->out.info->info1);
    8914         168 :         if (!W_ERROR_IS_OK(werror)) {
    8915           0 :                 TALLOC_FREE(r->out.info);
    8916           0 :                 return werror;
    8917             :         }
    8918             : 
    8919         168 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
    8920             :                                                r->out.info, r->in.level);
    8921         168 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    8922             : 
    8923         168 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8924             : }
    8925             : 
    8926             : /****************************************************************
    8927             :  _spoolss_EnumPrinterData
    8928             : ****************************************************************/
    8929             : 
    8930         152 : WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
    8931             :                                 struct spoolss_EnumPrinterData *r)
    8932             : {
    8933           0 :         WERROR result;
    8934           0 :         struct spoolss_EnumPrinterDataEx r2;
    8935           0 :         uint32_t count;
    8936         152 :         struct spoolss_PrinterEnumValues *info, *val = NULL;
    8937           0 :         uint32_t needed;
    8938             : 
    8939         152 :         r2.in.handle    = r->in.handle;
    8940         152 :         r2.in.key_name  = "PrinterDriverData";
    8941         152 :         r2.in.offered   = 0;
    8942         152 :         r2.out.count    = &count;
    8943         152 :         r2.out.info     = &info;
    8944         152 :         r2.out.needed   = &needed;
    8945             : 
    8946         152 :         result = _spoolss_EnumPrinterDataEx(p, &r2);
    8947         152 :         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
    8948         112 :                 r2.in.offered = needed;
    8949         112 :                 result = _spoolss_EnumPrinterDataEx(p, &r2);
    8950             :         }
    8951         152 :         if (!W_ERROR_IS_OK(result)) {
    8952           0 :                 return result;
    8953             :         }
    8954             : 
    8955             :         /*
    8956             :          * The NT machine wants to know the biggest size of value and data
    8957             :          *
    8958             :          * cf: MSDN EnumPrinterData remark section
    8959             :          */
    8960             : 
    8961         152 :         if (!r->in.value_offered && !r->in.data_offered) {
    8962          48 :                 uint32_t biggest_valuesize = 0;
    8963          48 :                 uint32_t biggest_datasize = 0;
    8964           0 :                 int i, name_length;
    8965             : 
    8966          48 :                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
    8967             : 
    8968         132 :                 for (i=0; i<count; i++) {
    8969             : 
    8970          84 :                         name_length = strlen(info[i].value_name);
    8971          84 :                         if (strlen(info[i].value_name) > biggest_valuesize) {
    8972          28 :                                 biggest_valuesize = name_length;
    8973             :                         }
    8974             : 
    8975          84 :                         if (info[i].data_length > biggest_datasize) {
    8976          28 :                                 biggest_datasize = info[i].data_length;
    8977             :                         }
    8978             : 
    8979          84 :                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
    8980             :                                 biggest_datasize));
    8981             :                 }
    8982             : 
    8983             :                 /* the value is an UNICODE string but real_value_size is the length
    8984             :                    in bytes including the trailing 0 */
    8985             : 
    8986          48 :                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
    8987          48 :                 *r->out.data_needed  = biggest_datasize;
    8988             : 
    8989          48 :                 DEBUG(6,("final values: [%d], [%d]\n",
    8990             :                         *r->out.value_needed, *r->out.data_needed));
    8991             : 
    8992          48 :                 return WERR_OK;
    8993             :         }
    8994             : 
    8995         104 :         if (r->in.enum_index < count) {
    8996          84 :                 val = &info[r->in.enum_index];
    8997             :         }
    8998             : 
    8999         104 :         if (val == NULL) {
    9000             :                 /* out_value should default to "" or else NT4 has
    9001             :                    problems unmarshalling the response */
    9002             : 
    9003          20 :                 if (r->in.value_offered) {
    9004          20 :                         *r->out.value_needed = 1;
    9005          20 :                         r->out.value_name = talloc_strdup(r, "");
    9006          20 :                         if (!r->out.value_name) {
    9007           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    9008             :                         }
    9009             :                 } else {
    9010           0 :                         r->out.value_name = NULL;
    9011           0 :                         *r->out.value_needed = 0;
    9012             :                 }
    9013             : 
    9014             :                 /* the data is counted in bytes */
    9015             : 
    9016          20 :                 *r->out.data_needed = r->in.data_offered;
    9017             : 
    9018          20 :                 result = WERR_NO_MORE_ITEMS;
    9019             :         } else {
    9020             :                 /*
    9021             :                  * the value is:
    9022             :                  * - counted in bytes in the request
    9023             :                  * - counted in UNICODE chars in the max reply
    9024             :                  * - counted in bytes in the real size
    9025             :                  *
    9026             :                  * take a pause *before* coding not *during* coding
    9027             :                  */
    9028             : 
    9029             :                 /* name */
    9030          84 :                 if (r->in.value_offered) {
    9031          84 :                         r->out.value_name = talloc_strdup(r, val->value_name);
    9032          84 :                         if (!r->out.value_name) {
    9033           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    9034             :                         }
    9035          84 :                         *r->out.value_needed = val->value_name_len;
    9036             :                 } else {
    9037           0 :                         r->out.value_name = NULL;
    9038           0 :                         *r->out.value_needed = 0;
    9039             :                 }
    9040             : 
    9041             :                 /* type */
    9042             : 
    9043          84 :                 *r->out.type = val->type;
    9044             : 
    9045             :                 /* data - counted in bytes */
    9046             : 
    9047             :                 /*
    9048             :                  * See the section "Dynamically Typed Query Parameters"
    9049             :                  * in MS-RPRN.
    9050             :                  */
    9051             : 
    9052          84 :                 if (r->out.data && val->data && val->data->data &&
    9053          84 :                                 val->data_length && r->in.data_offered) {
    9054          84 :                         memcpy(r->out.data, val->data->data,
    9055          84 :                                 MIN(val->data_length,r->in.data_offered));
    9056             :                 }
    9057             : 
    9058          84 :                 *r->out.data_needed = val->data_length;
    9059             : 
    9060          84 :                 result = WERR_OK;
    9061             :         }
    9062             : 
    9063         104 :         return result;
    9064             : }
    9065             : 
    9066             : /****************************************************************
    9067             :  _spoolss_SetPrinterData
    9068             : ****************************************************************/
    9069             : 
    9070         168 : WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
    9071             :                                struct spoolss_SetPrinterData *r)
    9072             : {
    9073           0 :         struct spoolss_SetPrinterDataEx r2;
    9074             : 
    9075         168 :         r2.in.handle            = r->in.handle;
    9076         168 :         r2.in.key_name          = "PrinterDriverData";
    9077         168 :         r2.in.value_name        = r->in.value_name;
    9078         168 :         r2.in.type              = r->in.type;
    9079         168 :         r2.in.data              = r->in.data;
    9080         168 :         r2.in.offered           = r->in.offered;
    9081             : 
    9082         168 :         return _spoolss_SetPrinterDataEx(p, &r2);
    9083             : }
    9084             : 
    9085             : /****************************************************************
    9086             :  _spoolss_ResetPrinter
    9087             : ****************************************************************/
    9088             : 
    9089           0 : WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
    9090             :                              struct spoolss_ResetPrinter *r)
    9091             : {
    9092           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9093           0 :         int             snum;
    9094             : 
    9095           0 :         DEBUG(5,("_spoolss_ResetPrinter\n"));
    9096             : 
    9097             :         /*
    9098             :          * All we do is to check to see if the handle and queue is valid.
    9099             :          * This call really doesn't mean anything to us because we only
    9100             :          * support RAW printing.   --jerry
    9101             :          */
    9102             : 
    9103           0 :         if (!Printer) {
    9104           0 :                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
    9105             :                         OUR_HANDLE(r->in.handle)));
    9106           0 :                 return WERR_INVALID_HANDLE;
    9107             :         }
    9108             : 
    9109           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    9110           0 :                 return WERR_INVALID_HANDLE;
    9111             : 
    9112             : 
    9113             :         /* blindly return success */
    9114           0 :         return WERR_OK;
    9115             : }
    9116             : 
    9117             : /****************************************************************
    9118             :  _spoolss_DeletePrinterData
    9119             : ****************************************************************/
    9120             : 
    9121         168 : WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
    9122             :                                   struct spoolss_DeletePrinterData *r)
    9123             : {
    9124           0 :         struct spoolss_DeletePrinterDataEx r2;
    9125             : 
    9126         168 :         r2.in.handle            = r->in.handle;
    9127         168 :         r2.in.key_name          = "PrinterDriverData";
    9128         168 :         r2.in.value_name        = r->in.value_name;
    9129             : 
    9130         168 :         return _spoolss_DeletePrinterDataEx(p, &r2);
    9131             : }
    9132             : 
    9133             : /****************************************************************
    9134             :  _spoolss_AddForm
    9135             : ****************************************************************/
    9136             : 
    9137         576 : WERROR _spoolss_AddForm(struct pipes_struct *p,
    9138             :                         struct spoolss_AddForm *r)
    9139             : {
    9140         576 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9141           0 :         struct auth_session_info *session_info =
    9142         576 :                 dcesrv_call_session_info(dce_call);
    9143           0 :         struct spoolss_AddFormInfo1 *form;
    9144         576 :         int snum = -1;
    9145         576 :         WERROR status = WERR_OK;
    9146         576 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9147           0 :         struct dcerpc_binding_handle *b;
    9148         576 :         TALLOC_CTX *tmp_ctx = NULL;
    9149             : 
    9150         576 :         DEBUG(5,("_spoolss_AddForm\n"));
    9151             : 
    9152         576 :         if (!Printer) {
    9153           0 :                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
    9154             :                         OUR_HANDLE(r->in.handle)));
    9155           0 :                 return WERR_INVALID_HANDLE;
    9156             :         }
    9157             : 
    9158             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    9159             :            and not a printer admin, then fail */
    9160             : 
    9161         576 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9162           0 :             !security_token_has_privilege(session_info->security_token,
    9163             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    9164           0 :                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
    9165           0 :                 return WERR_ACCESS_DENIED;
    9166             :         }
    9167             : 
    9168         576 :         if (r->in.info_ctr->level != 1) {
    9169           0 :                 return WERR_INVALID_LEVEL;
    9170             :         }
    9171             : 
    9172         576 :         form = r->in.info_ctr->info.info1;
    9173         576 :         if (!form) {
    9174           0 :                 return WERR_INVALID_PARAMETER;
    9175             :         }
    9176             : 
    9177         576 :         switch (form->flags) {
    9178         480 :         case SPOOLSS_FORM_USER:
    9179             :         case SPOOLSS_FORM_BUILTIN:
    9180             :         case SPOOLSS_FORM_PRINTER:
    9181         480 :                 break;
    9182          96 :         default:
    9183          96 :                 return WERR_INVALID_PARAMETER;
    9184             :         }
    9185             : 
    9186         480 :         tmp_ctx = talloc_new(p->mem_ctx);
    9187         480 :         if (!tmp_ctx) {
    9188           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9189             :         }
    9190             : 
    9191         480 :         status = winreg_printer_binding_handle(tmp_ctx,
    9192             :                                                get_session_info_system(),
    9193             :                                                p->msg_ctx,
    9194             :                                                &b);
    9195         480 :         if (!W_ERROR_IS_OK(status)) {
    9196           0 :                 goto done;
    9197             :         }
    9198             : 
    9199         480 :         status = winreg_printer_addform1(tmp_ctx, b, form);
    9200         480 :         if (!W_ERROR_IS_OK(status)) {
    9201         384 :                 goto done;
    9202             :         }
    9203             : 
    9204             :         /*
    9205             :          * ChangeID must always be set if this is a printer
    9206             :          */
    9207          96 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9208          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9209           0 :                         status = WERR_INVALID_HANDLE;
    9210           0 :                         goto done;
    9211             :                 }
    9212             : 
    9213          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9214             :                                                         lp_const_servicename(snum));
    9215             :         }
    9216             : 
    9217          16 : done:
    9218         480 :         talloc_free(tmp_ctx);
    9219         480 :         return status;
    9220             : }
    9221             : 
    9222             : /****************************************************************
    9223             :  _spoolss_DeleteForm
    9224             : ****************************************************************/
    9225             : 
    9226         384 : WERROR _spoolss_DeleteForm(struct pipes_struct *p,
    9227             :                            struct spoolss_DeleteForm *r)
    9228             : {
    9229         384 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9230           0 :         struct auth_session_info *session_info =
    9231         384 :                 dcesrv_call_session_info(dce_call);
    9232         384 :         const char *form_name = r->in.form_name;
    9233         384 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9234         384 :         int snum = -1;
    9235         384 :         WERROR status = WERR_OK;
    9236           0 :         struct dcerpc_binding_handle *b;
    9237         384 :         TALLOC_CTX *tmp_ctx = NULL;
    9238             : 
    9239         384 :         DEBUG(5,("_spoolss_DeleteForm\n"));
    9240             : 
    9241         384 :         if (!Printer) {
    9242           0 :                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
    9243             :                         OUR_HANDLE(r->in.handle)));
    9244           0 :                 return WERR_INVALID_HANDLE;
    9245             :         }
    9246             : 
    9247         384 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9248           0 :             !security_token_has_privilege(session_info->security_token,
    9249             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    9250           0 :                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
    9251           0 :                 return WERR_ACCESS_DENIED;
    9252             :         }
    9253             : 
    9254         384 :         tmp_ctx = talloc_new(p->mem_ctx);
    9255         384 :         if (!tmp_ctx) {
    9256           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9257             :         }
    9258             : 
    9259         384 :         status = winreg_printer_binding_handle(tmp_ctx,
    9260             :                                                get_session_info_system(),
    9261             :                                                p->msg_ctx,
    9262             :                                                &b);
    9263         384 :         if (!W_ERROR_IS_OK(status)) {
    9264           0 :                 goto done;
    9265             :         }
    9266             : 
    9267         384 :         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
    9268         384 :         if (!W_ERROR_IS_OK(status)) {
    9269         288 :                 goto done;
    9270             :         }
    9271             : 
    9272             :         /*
    9273             :          * ChangeID must always be set if this is a printer
    9274             :          */
    9275          96 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9276          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9277           0 :                         status = WERR_INVALID_HANDLE;
    9278           0 :                         goto done;
    9279             :                 }
    9280             : 
    9281          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9282             :                                                         lp_const_servicename(snum));
    9283             :         }
    9284             : 
    9285          16 : done:
    9286         384 :         talloc_free(tmp_ctx);
    9287         384 :         return status;
    9288             : }
    9289             : 
    9290             : /****************************************************************
    9291             :  _spoolss_SetForm
    9292             : ****************************************************************/
    9293             : 
    9294          80 : WERROR _spoolss_SetForm(struct pipes_struct *p,
    9295             :                         struct spoolss_SetForm *r)
    9296             : {
    9297          80 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9298           0 :         struct auth_session_info *session_info =
    9299          80 :                 dcesrv_call_session_info(dce_call);
    9300           0 :         struct spoolss_AddFormInfo1 *form;
    9301          80 :         const char *form_name = r->in.form_name;
    9302          80 :         int snum = -1;
    9303          80 :         WERROR status = WERR_OK;
    9304           0 :         struct dcerpc_binding_handle *b;
    9305          80 :         TALLOC_CTX *tmp_ctx = NULL;
    9306             : 
    9307          80 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9308             : 
    9309          80 :         DEBUG(5,("_spoolss_SetForm\n"));
    9310             : 
    9311          80 :         if (!Printer) {
    9312           0 :                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
    9313             :                         OUR_HANDLE(r->in.handle)));
    9314           0 :                 return WERR_INVALID_HANDLE;
    9315             :         }
    9316             : 
    9317             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    9318             :            and not a printer admin, then fail */
    9319             : 
    9320          80 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9321           0 :              !security_token_has_privilege(session_info->security_token,
    9322             :                                            SEC_PRIV_PRINT_OPERATOR)) {
    9323           0 :                 DEBUG(2,("_spoolss_SetForm: denied by insufficient permissions.\n"));
    9324           0 :                 return WERR_ACCESS_DENIED;
    9325             :         }
    9326             : 
    9327          80 :         if (r->in.info_ctr->level != 1) {
    9328           0 :                 return WERR_INVALID_LEVEL;
    9329             :         }
    9330             : 
    9331          80 :         form = r->in.info_ctr->info.info1;
    9332          80 :         if (!form) {
    9333           0 :                 return WERR_INVALID_PARAMETER;
    9334             :         }
    9335             : 
    9336          80 :         tmp_ctx = talloc_new(p->mem_ctx);
    9337          80 :         if (!tmp_ctx) {
    9338           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9339             :         }
    9340             : 
    9341          80 :         status = winreg_printer_binding_handle(tmp_ctx,
    9342             :                                                get_session_info_system(),
    9343             :                                                p->msg_ctx,
    9344             :                                                &b);
    9345          80 :         if (!W_ERROR_IS_OK(status)) {
    9346           0 :                 goto done;
    9347             :         }
    9348             : 
    9349          80 :         status = winreg_printer_setform1(tmp_ctx, b,
    9350             :                                          form_name,
    9351             :                                          form);
    9352          80 :         if (!W_ERROR_IS_OK(status)) {
    9353           0 :                 goto done;
    9354             :         }
    9355             : 
    9356             :         /*
    9357             :          * ChangeID must always be set if this is a printer
    9358             :          */
    9359          80 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9360          80 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9361           0 :                         status = WERR_INVALID_HANDLE;
    9362           0 :                         goto done;
    9363             :                 }
    9364             : 
    9365          80 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9366             :                                                         lp_const_servicename(snum));
    9367             :         }
    9368             : 
    9369           0 : done:
    9370          80 :         talloc_free(tmp_ctx);
    9371          80 :         return status;
    9372             : }
    9373             : 
    9374             : /****************************************************************************
    9375             :  fill_print_processor1
    9376             : ****************************************************************************/
    9377             : 
    9378          24 : static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
    9379             :                                     struct spoolss_PrintProcessorInfo1 *r,
    9380             :                                     const char *print_processor_name)
    9381             : {
    9382          24 :         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
    9383          24 :         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
    9384             : 
    9385          24 :         return WERR_OK;
    9386             : }
    9387             : 
    9388             : /****************************************************************************
    9389             :  enumprintprocessors level 1.
    9390             : ****************************************************************************/
    9391             : 
    9392          24 : static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
    9393             :                                           union spoolss_PrintProcessorInfo **info_p,
    9394             :                                           uint32_t *count)
    9395             : {
    9396           0 :         union spoolss_PrintProcessorInfo *info;
    9397           0 :         WERROR result;
    9398             : 
    9399          24 :         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
    9400          24 :         W_ERROR_HAVE_NO_MEMORY(info);
    9401             : 
    9402          24 :         *count = 1;
    9403             : 
    9404          24 :         result = fill_print_processor1(info, &info[0].info1, "winprint");
    9405          24 :         if (!W_ERROR_IS_OK(result)) {
    9406           0 :                 goto out;
    9407             :         }
    9408             : 
    9409          24 :  out:
    9410          24 :         if (!W_ERROR_IS_OK(result)) {
    9411           0 :                 TALLOC_FREE(info);
    9412           0 :                 *count = 0;
    9413           0 :                 return result;
    9414             :         }
    9415             : 
    9416          24 :         *info_p = info;
    9417             : 
    9418          24 :         return WERR_OK;
    9419             : }
    9420             : 
    9421             : /****************************************************************
    9422             :  _spoolss_EnumPrintProcessors
    9423             : ****************************************************************/
    9424             : 
    9425          48 : WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
    9426             :                                     struct spoolss_EnumPrintProcessors *r)
    9427             : {
    9428           0 :         WERROR result;
    9429             : 
    9430             :         /* that's an [in out] buffer */
    9431             : 
    9432          48 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9433           0 :                 return WERR_INVALID_PARAMETER;
    9434             :         }
    9435             : 
    9436          48 :         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
    9437             : 
    9438             :         /*
    9439             :          * Enumerate the print processors ...
    9440             :          *
    9441             :          * Just reply with "winprint", to keep NT happy
    9442             :          * and I can use my nice printer checker.
    9443             :          */
    9444             : 
    9445          48 :         *r->out.count = 0;
    9446          48 :         *r->out.needed = 0;
    9447          48 :         *r->out.info = NULL;
    9448             : 
    9449          48 :         if (!get_short_archi(r->in.environment)) {
    9450           4 :                 return WERR_INVALID_ENVIRONMENT;
    9451             :         }
    9452             : 
    9453          44 :         switch (r->in.level) {
    9454          24 :         case 1:
    9455          24 :                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
    9456             :                                                      r->out.count);
    9457          24 :                 break;
    9458          20 :         default:
    9459          20 :                 return WERR_INVALID_LEVEL;
    9460             :         }
    9461             : 
    9462          24 :         if (!W_ERROR_IS_OK(result)) {
    9463           0 :                 return result;
    9464             :         }
    9465             : 
    9466          24 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9467             :                                                      spoolss_EnumPrintProcessors,
    9468             :                                                      *r->out.info, r->in.level,
    9469             :                                                      *r->out.count);
    9470          24 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9471          24 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9472             : 
    9473          24 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9474             : }
    9475             : 
    9476             : /****************************************************************************
    9477             :  fill_printprocdatatype1
    9478             : ****************************************************************************/
    9479             : 
    9480          16 : static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
    9481             :                                       struct spoolss_PrintProcDataTypesInfo1 *r,
    9482             :                                       const char *name_array)
    9483             : {
    9484          16 :         r->name_array = talloc_strdup(mem_ctx, name_array);
    9485          16 :         W_ERROR_HAVE_NO_MEMORY(r->name_array);
    9486             : 
    9487          16 :         return WERR_OK;
    9488             : }
    9489             : 
    9490             : /****************************************************************************
    9491             :  enumprintprocdatatypes level 1.
    9492             : ****************************************************************************/
    9493             : 
    9494          16 : static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
    9495             :                                              union spoolss_PrintProcDataTypesInfo **info_p,
    9496             :                                              uint32_t *count)
    9497             : {
    9498           0 :         WERROR result;
    9499           0 :         union spoolss_PrintProcDataTypesInfo *info;
    9500             : 
    9501          16 :         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
    9502          16 :         W_ERROR_HAVE_NO_MEMORY(info);
    9503             : 
    9504          16 :         *count = 1;
    9505             : 
    9506          16 :         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
    9507          16 :         if (!W_ERROR_IS_OK(result)) {
    9508           0 :                 goto out;
    9509             :         }
    9510             : 
    9511          16 :  out:
    9512          16 :         if (!W_ERROR_IS_OK(result)) {
    9513           0 :                 TALLOC_FREE(info);
    9514           0 :                 *count = 0;
    9515           0 :                 return result;
    9516             :         }
    9517             : 
    9518          16 :         *info_p = info;
    9519             : 
    9520          16 :         return WERR_OK;
    9521             : }
    9522             : 
    9523             : /****************************************************************
    9524             :  _spoolss_EnumPrintProcessorDataTypes
    9525             : ****************************************************************/
    9526             : 
    9527          44 : WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
    9528             :                                             struct spoolss_EnumPrintProcessorDataTypes *r)
    9529             : {
    9530           0 :         WERROR result;
    9531             : 
    9532             :         /* that's an [in out] buffer */
    9533             : 
    9534          44 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9535           0 :                 return WERR_INVALID_PARAMETER;
    9536             :         }
    9537             : 
    9538          44 :         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
    9539             : 
    9540          44 :         *r->out.count = 0;
    9541          44 :         *r->out.needed = 0;
    9542          44 :         *r->out.info = NULL;
    9543             : 
    9544          44 :         if (r->in.print_processor_name == NULL ||
    9545          40 :             !strequal(r->in.print_processor_name, "winprint")) {
    9546           8 :                 return WERR_UNKNOWN_PRINTPROCESSOR;
    9547             :         }
    9548             : 
    9549          36 :         switch (r->in.level) {
    9550          16 :         case 1:
    9551          16 :                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
    9552             :                                                         r->out.count);
    9553          16 :                 break;
    9554          20 :         default:
    9555          20 :                 return WERR_INVALID_LEVEL;
    9556             :         }
    9557             : 
    9558          16 :         if (!W_ERROR_IS_OK(result)) {
    9559           0 :                 return result;
    9560             :         }
    9561             : 
    9562          16 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9563             :                                                      spoolss_EnumPrintProcessorDataTypes,
    9564             :                                                      *r->out.info, r->in.level,
    9565             :                                                      *r->out.count);
    9566          16 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9567          16 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9568             : 
    9569          16 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9570             : }
    9571             : 
    9572             : /****************************************************************************
    9573             :  fill_monitor_1
    9574             : ****************************************************************************/
    9575             : 
    9576          16 : static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
    9577             :                              struct spoolss_MonitorInfo1 *r,
    9578             :                              const char *monitor_name)
    9579             : {
    9580          16 :         r->monitor_name                      = talloc_strdup(mem_ctx, monitor_name);
    9581          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    9582             : 
    9583          16 :         return WERR_OK;
    9584             : }
    9585             : 
    9586             : /****************************************************************************
    9587             :  fill_monitor_2
    9588             : ****************************************************************************/
    9589             : 
    9590          16 : static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
    9591             :                              struct spoolss_MonitorInfo2 *r,
    9592             :                              const char *monitor_name,
    9593             :                              const char *environment,
    9594             :                              const char *dll_name)
    9595             : {
    9596          16 :         r->monitor_name                      = talloc_strdup(mem_ctx, monitor_name);
    9597          16 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    9598          16 :         r->environment                       = talloc_strdup(mem_ctx, environment);
    9599          16 :         W_ERROR_HAVE_NO_MEMORY(r->environment);
    9600          16 :         r->dll_name                  = talloc_strdup(mem_ctx, dll_name);
    9601          16 :         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
    9602             : 
    9603          16 :         return WERR_OK;
    9604             : }
    9605             : 
    9606             : /****************************************************************************
    9607             :  enumprintmonitors level 1.
    9608             : ****************************************************************************/
    9609             : 
    9610           8 : static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
    9611             :                                         union spoolss_MonitorInfo **info_p,
    9612             :                                         uint32_t *count)
    9613             : {
    9614           0 :         union spoolss_MonitorInfo *info;
    9615           8 :         WERROR result = WERR_OK;
    9616             : 
    9617           8 :         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
    9618           8 :         W_ERROR_HAVE_NO_MEMORY(info);
    9619             : 
    9620           8 :         *count = 2;
    9621             : 
    9622           8 :         result = fill_monitor_1(info, &info[0].info1,
    9623             :                                 SPL_LOCAL_PORT);
    9624           8 :         if (!W_ERROR_IS_OK(result)) {
    9625           0 :                 goto out;
    9626             :         }
    9627             : 
    9628           8 :         result = fill_monitor_1(info, &info[1].info1,
    9629             :                                 SPL_TCPIP_PORT);
    9630           8 :         if (!W_ERROR_IS_OK(result)) {
    9631           0 :                 goto out;
    9632             :         }
    9633             : 
    9634           8 : out:
    9635           8 :         if (!W_ERROR_IS_OK(result)) {
    9636           0 :                 TALLOC_FREE(info);
    9637           0 :                 *count = 0;
    9638           0 :                 return result;
    9639             :         }
    9640             : 
    9641           8 :         *info_p = info;
    9642             : 
    9643           8 :         return WERR_OK;
    9644             : }
    9645             : 
    9646             : /****************************************************************************
    9647             :  enumprintmonitors level 2.
    9648             : ****************************************************************************/
    9649             : 
    9650           8 : static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
    9651             :                                         union spoolss_MonitorInfo **info_p,
    9652             :                                         uint32_t *count)
    9653             : {
    9654           0 :         union spoolss_MonitorInfo *info;
    9655           8 :         WERROR result = WERR_OK;
    9656           0 :         const char *architecture;
    9657             : 
    9658           8 :         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
    9659           8 :         W_ERROR_HAVE_NO_MEMORY(info);
    9660             : 
    9661           8 :         *count = 2;
    9662             : 
    9663           8 :         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    9664             :                                             "spoolss",
    9665             :                                             "architecture",
    9666             :                                             GLOBAL_SPOOLSS_ARCHITECTURE);
    9667             : 
    9668           8 :         result = fill_monitor_2(info, &info[0].info2,
    9669             :                                 SPL_LOCAL_PORT,
    9670             :                                 architecture,
    9671             :                                 "localmon.dll");
    9672           8 :         if (!W_ERROR_IS_OK(result)) {
    9673           0 :                 goto out;
    9674             :         }
    9675             : 
    9676           8 :         result = fill_monitor_2(info, &info[1].info2,
    9677             :                                 SPL_TCPIP_PORT,
    9678             :                                 architecture,
    9679             :                                 "tcpmon.dll");
    9680           8 :         if (!W_ERROR_IS_OK(result)) {
    9681           0 :                 goto out;
    9682             :         }
    9683             : 
    9684           8 : out:
    9685           8 :         if (!W_ERROR_IS_OK(result)) {
    9686           0 :                 TALLOC_FREE(info);
    9687           0 :                 *count = 0;
    9688           0 :                 return result;
    9689             :         }
    9690             : 
    9691           8 :         *info_p = info;
    9692             : 
    9693           8 :         return WERR_OK;
    9694             : }
    9695             : 
    9696             : /****************************************************************
    9697             :  _spoolss_EnumMonitors
    9698             : ****************************************************************/
    9699             : 
    9700          16 : WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
    9701             :                              struct spoolss_EnumMonitors *r)
    9702             : {
    9703           0 :         WERROR result;
    9704             : 
    9705             :         /* that's an [in out] buffer */
    9706             : 
    9707          16 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9708           0 :                 return WERR_INVALID_PARAMETER;
    9709             :         }
    9710             : 
    9711          16 :         DEBUG(5,("_spoolss_EnumMonitors\n"));
    9712             : 
    9713             :         /*
    9714             :          * Enumerate the print monitors ...
    9715             :          *
    9716             :          * Just reply with "Local Port", to keep NT happy
    9717             :          * and I can use my nice printer checker.
    9718             :          */
    9719             : 
    9720          16 :         *r->out.count = 0;
    9721          16 :         *r->out.needed = 0;
    9722          16 :         *r->out.info = NULL;
    9723             : 
    9724          16 :         switch (r->in.level) {
    9725           8 :         case 1:
    9726           8 :                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
    9727             :                                                    r->out.count);
    9728           8 :                 break;
    9729           8 :         case 2:
    9730           8 :                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
    9731             :                                                    r->out.count);
    9732           8 :                 break;
    9733           0 :         default:
    9734           0 :                 return WERR_INVALID_LEVEL;
    9735             :         }
    9736             : 
    9737          16 :         if (!W_ERROR_IS_OK(result)) {
    9738           0 :                 return result;
    9739             :         }
    9740             : 
    9741          16 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9742             :                                                      spoolss_EnumMonitors,
    9743             :                                                      *r->out.info, r->in.level,
    9744             :                                                      *r->out.count);
    9745          16 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9746          16 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9747             : 
    9748          16 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9749             : }
    9750             : 
    9751             : /****************************************************************************
    9752             : ****************************************************************************/
    9753             : 
    9754         128 : static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
    9755             :                              const print_queue_struct *queue,
    9756             :                              int count, int snum,
    9757             :                              struct spoolss_PrinterInfo2 *pinfo2,
    9758             :                              uint32_t jobid,
    9759             :                              int sysjob,
    9760             :                              struct spoolss_JobInfo1 *r)
    9761             : {
    9762         128 :         int i = 0;
    9763         128 :         bool found = false;
    9764             : 
    9765         576 :         for (i=0; i<count; i++) {
    9766         576 :                 if (queue[i].sysjob == sysjob) {
    9767         128 :                         found = true;
    9768         128 :                         break;
    9769             :                 }
    9770             :         }
    9771             : 
    9772         128 :         if (found == false) {
    9773             :                 /* NT treats not found as bad param... yet another bad choice */
    9774           0 :                 return WERR_INVALID_PARAMETER;
    9775             :         }
    9776             : 
    9777         128 :         return fill_job_info1(mem_ctx,
    9778             :                               r,
    9779         128 :                               &queue[i],
    9780             :                               jobid,
    9781             :                               i,
    9782             :                               snum,
    9783             :                               pinfo2);
    9784             : }
    9785             : 
    9786             : /****************************************************************************
    9787             : ****************************************************************************/
    9788             : 
    9789           0 : static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
    9790             :                              const print_queue_struct *queue,
    9791             :                              int count, int snum,
    9792             :                              struct spoolss_PrinterInfo2 *pinfo2,
    9793             :                              uint32_t jobid,
    9794             :                              int sysjob,
    9795             :                              struct spoolss_JobInfo2 *r)
    9796             : {
    9797           0 :         int i = 0;
    9798           0 :         bool found = false;
    9799           0 :         struct spoolss_DeviceMode *devmode;
    9800           0 :         WERROR result;
    9801             : 
    9802           0 :         for (i=0; i<count; i++) {
    9803           0 :                 if (queue[i].sysjob == sysjob) {
    9804           0 :                         found = true;
    9805           0 :                         break;
    9806             :                 }
    9807             :         }
    9808             : 
    9809           0 :         if (found == false) {
    9810             :                 /* NT treats not found as bad param... yet another bad
    9811             :                    choice */
    9812           0 :                 return WERR_INVALID_PARAMETER;
    9813             :         }
    9814             : 
    9815             :         /*
    9816             :          * if the print job does not have a DEVMODE associated with it,
    9817             :          * just use the one for the printer. A NULL devicemode is not
    9818             :          *  a failure condition
    9819             :          */
    9820             : 
    9821           0 :         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
    9822           0 :         if (!devmode) {
    9823           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    9824             :                                                 pinfo2->printername,
    9825             :                                                 &devmode);
    9826           0 :                 if (!W_ERROR_IS_OK(result)) {
    9827           0 :                         DEBUG(3, ("Can't proceed w/o a devmode!\n"));
    9828           0 :                         return result;
    9829             :                 }
    9830             :         }
    9831             : 
    9832           0 :         return fill_job_info2(mem_ctx,
    9833             :                               r,
    9834           0 :                               &queue[i],
    9835             :                               jobid,
    9836             :                               i,
    9837             :                               snum,
    9838             :                               pinfo2,
    9839             :                               devmode);
    9840             : }
    9841             : 
    9842             : /****************************************************************
    9843             :  _spoolss_GetJob
    9844             : ****************************************************************/
    9845             : 
    9846        2048 : WERROR _spoolss_GetJob(struct pipes_struct *p,
    9847             :                        struct spoolss_GetJob *r)
    9848             : {
    9849        2048 :         WERROR result = WERR_OK;
    9850        2048 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    9851           0 :         const char *svc_name;
    9852           0 :         int sysjob;
    9853           0 :         int snum;
    9854           0 :         int count;
    9855           0 :         struct tdb_print_db *pdb;
    9856        2048 :         print_queue_struct      *queue = NULL;
    9857           0 :         print_status_struct prt_status;
    9858             : 
    9859             :         /* that's an [in out] buffer */
    9860             : 
    9861        2048 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9862           0 :                 result = WERR_INVALID_PARAMETER;
    9863           0 :                 goto err_jinfo_free;
    9864             :         }
    9865             : 
    9866        2048 :         DEBUG(5,("_spoolss_GetJob\n"));
    9867             : 
    9868        2048 :         *r->out.needed = 0;
    9869             : 
    9870        2048 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9871           0 :                 result = WERR_INVALID_HANDLE;
    9872           0 :                 goto err_jinfo_free;
    9873             :         }
    9874             : 
    9875        2048 :         svc_name = lp_const_servicename(snum);
    9876        2048 :         if (svc_name == NULL) {
    9877           0 :                 result = WERR_INVALID_PARAMETER;
    9878           0 :                 goto err_jinfo_free;
    9879             :         }
    9880             : 
    9881        2048 :         result = winreg_get_printer_internal(p->mem_ctx,
    9882             :                                     get_session_info_system(),
    9883             :                                     p->msg_ctx,
    9884             :                                     svc_name,
    9885             :                                     &pinfo2);
    9886        2048 :         if (!W_ERROR_IS_OK(result)) {
    9887           0 :                 goto err_jinfo_free;
    9888             :         }
    9889             : 
    9890        2048 :         pdb = get_print_db_byname(svc_name);
    9891        2048 :         if (pdb == NULL) {
    9892           0 :                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
    9893           0 :                 result = WERR_INVALID_PARAMETER;
    9894           0 :                 goto err_pinfo_free;
    9895             :         }
    9896             : 
    9897        2048 :         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
    9898        2048 :         release_print_db(pdb);
    9899        2048 :         if (sysjob == -1) {
    9900        1920 :                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
    9901        1920 :                 result = WERR_INVALID_PARAMETER;
    9902        1920 :                 goto err_pinfo_free;
    9903             :         }
    9904             : 
    9905         128 :         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
    9906             : 
    9907         128 :         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
    9908             :                      count, prt_status.status, prt_status.message));
    9909             : 
    9910         128 :         switch (r->in.level) {
    9911         128 :         case 1:
    9912         128 :                 result = getjob_level_1(p->mem_ctx,
    9913             :                                         queue, count, snum, pinfo2,
    9914             :                                         r->in.job_id, sysjob,
    9915         128 :                                         &r->out.info->info1);
    9916         128 :                 break;
    9917           0 :         case 2:
    9918           0 :                 result = getjob_level_2(p->mem_ctx,
    9919             :                                         queue, count, snum, pinfo2,
    9920             :                                         r->in.job_id, sysjob,
    9921           0 :                                         &r->out.info->info2);
    9922           0 :                 break;
    9923           0 :         default:
    9924           0 :                 result = WERR_INVALID_LEVEL;
    9925           0 :                 break;
    9926             :         }
    9927             : 
    9928         128 :         SAFE_FREE(queue);
    9929         128 :         TALLOC_FREE(pinfo2);
    9930             : 
    9931         128 :         if (!W_ERROR_IS_OK(result)) {
    9932           0 :                 goto err_jinfo_free;
    9933             :         }
    9934             : 
    9935         128 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
    9936             :                                                                                    r->in.level);
    9937         128 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    9938             : 
    9939         128 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9940             : 
    9941        1920 : err_pinfo_free:
    9942        1920 :         TALLOC_FREE(pinfo2);
    9943           0 : err_jinfo_free:
    9944        1920 :         TALLOC_FREE(r->out.info);
    9945        1920 :         return result;
    9946             : }
    9947             : 
    9948             : /****************************************************************
    9949             :  _spoolss_GetPrinterDataEx
    9950             : ****************************************************************/
    9951             : 
    9952        3180 : WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
    9953             :                                  struct spoolss_GetPrinterDataEx *r)
    9954             : {
    9955             : 
    9956        3180 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9957           0 :         const char *printer;
    9958        3180 :         int                     snum = 0;
    9959        3180 :         WERROR result = WERR_OK;
    9960           0 :         DATA_BLOB blob;
    9961        3180 :         enum winreg_Type val_type = REG_NONE;
    9962        3180 :         uint8_t *val_data = NULL;
    9963        3180 :         uint32_t val_size = 0;
    9964           0 :         struct dcerpc_binding_handle *b;
    9965           0 :         TALLOC_CTX *tmp_ctx;
    9966             : 
    9967        3180 :         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
    9968             : 
    9969        3180 :         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
    9970             :                 r->in.key_name, r->in.value_name));
    9971             : 
    9972             :         /* in case of problem, return some default values */
    9973             : 
    9974        3180 :         *r->out.needed       = 0;
    9975        3180 :         *r->out.type = REG_NONE;
    9976             : 
    9977        3180 :         tmp_ctx = talloc_new(p->mem_ctx);
    9978        3180 :         if (!tmp_ctx) {
    9979           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9980             :         }
    9981             : 
    9982        3180 :         if (!Printer) {
    9983           0 :                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
    9984             :                         OUR_HANDLE(r->in.handle)));
    9985           0 :                 result = WERR_INVALID_HANDLE;
    9986           0 :                 goto done;
    9987             :         }
    9988             : 
    9989             :         /* Is the handle to a printer or to the server? */
    9990             : 
    9991        3180 :         if (Printer->printer_type == SPLHND_SERVER) {
    9992             : 
    9993           0 :                 union spoolss_PrinterData data;
    9994             : 
    9995         404 :                 result = getprinterdata_printer_server(tmp_ctx,
    9996             :                                                        r->in.value_name,
    9997             :                                                        r->out.type,
    9998             :                                                        &data);
    9999         404 :                 if (!W_ERROR_IS_OK(result)) {
   10000           4 :                         goto done;
   10001             :                 }
   10002             : 
   10003         400 :                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
   10004         400 :                                                   *r->out.type, &data);
   10005         400 :                 if (!W_ERROR_IS_OK(result)) {
   10006           0 :                         goto done;
   10007             :                 }
   10008             : 
   10009         400 :                 *r->out.needed = blob.length;
   10010             : 
   10011         400 :                 if (r->in.offered >= *r->out.needed) {
   10012         204 :                         memcpy(r->out.data, blob.data, blob.length);
   10013             :                 }
   10014             : 
   10015         400 :                 result = WERR_OK;
   10016         400 :                 goto done;
   10017             :         }
   10018             : 
   10019             :         /* check to see if the keyname is valid */
   10020        2776 :         if (!strlen(r->in.key_name)) {
   10021           0 :                 result = WERR_INVALID_PARAMETER;
   10022           0 :                 goto done;
   10023             :         }
   10024             : 
   10025        2776 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10026           0 :                 result = WERR_INVALID_HANDLE;
   10027           0 :                 goto done;
   10028             :         }
   10029        2776 :         printer = lp_const_servicename(snum);
   10030             : 
   10031        2776 :         result = winreg_printer_binding_handle(tmp_ctx,
   10032             :                                                get_session_info_system(),
   10033             :                                                p->msg_ctx,
   10034             :                                                &b);
   10035        2776 :         if (!W_ERROR_IS_OK(result)) {
   10036           0 :                 goto done;
   10037             :         }
   10038             : 
   10039             :         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
   10040        3076 :         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
   10041         300 :             strequal(r->in.value_name, "ChangeId")) {
   10042         128 :                 *r->out.type = REG_DWORD;
   10043         128 :                 *r->out.needed = 4;
   10044         128 :                 if (r->in.offered >= *r->out.needed) {
   10045          64 :                         uint32_t changeid = 0;
   10046             : 
   10047          64 :                         result = winreg_printer_get_changeid(tmp_ctx, b,
   10048             :                                                              printer,
   10049             :                                                              &changeid);
   10050          64 :                         if (!W_ERROR_IS_OK(result)) {
   10051           0 :                                 goto done;
   10052             :                         }
   10053             : 
   10054          64 :                         SIVAL(r->out.data, 0, changeid);
   10055          64 :                         result = WERR_OK;
   10056             :                 }
   10057         128 :                 goto done;
   10058             :         }
   10059             : 
   10060        2648 :         result = winreg_get_printer_dataex(tmp_ctx, b,
   10061             :                                            printer,
   10062             :                                            r->in.key_name,
   10063             :                                            r->in.value_name,
   10064             :                                            &val_type,
   10065             :                                            &val_data,
   10066             :                                            &val_size);
   10067        2648 :         if (!W_ERROR_IS_OK(result)) {
   10068           4 :                 goto done;
   10069             :         }
   10070             : 
   10071        2644 :         *r->out.needed = val_size;
   10072        2644 :         *r->out.type = val_type;
   10073             : 
   10074        2644 :         if (r->in.offered >= *r->out.needed) {
   10075        1340 :                 memcpy(r->out.data, val_data, val_size);
   10076             :         }
   10077             : 
   10078        1304 : done:
   10079             :         /* NOTE: do not replace type when returning WERR_MORE_DATA */
   10080             : 
   10081        3180 :         if (W_ERROR_IS_OK(result)) {
   10082        3172 :                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
   10083             :         }
   10084             : 
   10085        3180 :         talloc_free(tmp_ctx);
   10086        3180 :         return result;
   10087             : }
   10088             : 
   10089             : /****************************************************************
   10090             :  _spoolss_SetPrinterDataEx
   10091             : ****************************************************************/
   10092             : 
   10093        1368 : WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
   10094             :                                  struct spoolss_SetPrinterDataEx *r)
   10095             : {
   10096           0 :         const struct loadparm_substitution *lp_sub =
   10097        1368 :                 loadparm_s3_global_substitution();
   10098        1368 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
   10099        1368 :         int                     snum = 0;
   10100        1368 :         WERROR                  result = WERR_OK;
   10101        1368 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10102           0 :         char                    *oid_string;
   10103           0 :         struct dcerpc_binding_handle *b;
   10104           0 :         TALLOC_CTX *tmp_ctx;
   10105             : 
   10106        1368 :         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
   10107             : 
   10108             :         /* From MSDN documentation of SetPrinterDataEx: pass request to
   10109             :            SetPrinterData if key is "PrinterDriverData" */
   10110             : 
   10111        1368 :         if (!Printer) {
   10112           0 :                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
   10113             :                         OUR_HANDLE(r->in.handle)));
   10114           0 :                 return WERR_INVALID_HANDLE;
   10115             :         }
   10116             : 
   10117        1368 :         if (Printer->printer_type == SPLHND_SERVER) {
   10118           0 :                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
   10119             :                         "Not implemented for server handles yet\n"));
   10120           0 :                 return WERR_INVALID_PARAMETER;
   10121             :         }
   10122             : 
   10123        1368 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10124           0 :                 return WERR_INVALID_HANDLE;
   10125             :         }
   10126             : 
   10127             :         /*
   10128             :          * Access check : NT returns "access denied" if you make a
   10129             :          * SetPrinterData call without the necessary privilege.
   10130             :          * we were originally returning OK if nothing changed
   10131             :          * which made Win2k issue **a lot** of SetPrinterData
   10132             :          * when connecting to a printer  --jerry
   10133             :          */
   10134             : 
   10135        1368 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10136           0 :                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
   10137             :                         "change denied by handle access permissions\n"));
   10138           0 :                 return WERR_ACCESS_DENIED;
   10139             :         }
   10140             : 
   10141        1368 :         tmp_ctx = talloc_new(p->mem_ctx);
   10142        1368 :         if (!tmp_ctx) {
   10143           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10144             :         }
   10145             : 
   10146        1368 :         result = winreg_printer_binding_handle(tmp_ctx,
   10147             :                                                get_session_info_system(),
   10148             :                                                p->msg_ctx,
   10149             :                                                &b);
   10150        1368 :         if (!W_ERROR_IS_OK(result)) {
   10151           0 :                 goto done;
   10152             :         }
   10153             : 
   10154        1368 :         result = winreg_get_printer(tmp_ctx, b,
   10155        1368 :                                     lp_servicename(talloc_tos(), lp_sub, snum),
   10156             :                                     &pinfo2);
   10157        1368 :         if (!W_ERROR_IS_OK(result)) {
   10158           0 :                 goto done;
   10159             :         }
   10160             : 
   10161             :         /* check for OID in valuename */
   10162             : 
   10163        1368 :         oid_string = strchr(r->in.value_name, ',');
   10164        1368 :         if (oid_string) {
   10165           0 :                 *oid_string = '\0';
   10166           0 :                 oid_string++;
   10167             :         }
   10168             : 
   10169             :         /* save the registry data */
   10170             : 
   10171        1368 :         result = winreg_set_printer_dataex(tmp_ctx, b,
   10172        1368 :                                            pinfo2->sharename,
   10173             :                                            r->in.key_name,
   10174             :                                            r->in.value_name,
   10175             :                                            r->in.type,
   10176             :                                            r->in.data,
   10177             :                                            r->in.offered);
   10178             : 
   10179        1368 :         if (W_ERROR_IS_OK(result)) {
   10180             :                 /* save the OID if one was specified */
   10181        1368 :                 if (oid_string) {
   10182           0 :                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
   10183             :                                 r->in.key_name, SPOOL_OID_KEY);
   10184           0 :                         if (!str) {
   10185           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
   10186           0 :                                 goto done;
   10187             :                         }
   10188             : 
   10189             :                         /*
   10190             :                          * I'm not checking the status here on purpose.  Don't know
   10191             :                          * if this is right, but I'm returning the status from the
   10192             :                          * previous set_printer_dataex() call.  I have no idea if
   10193             :                          * this is right.    --jerry
   10194             :                          */
   10195           0 :                         winreg_set_printer_dataex(tmp_ctx, b,
   10196           0 :                                                   pinfo2->sharename,
   10197             :                                                   str,
   10198             :                                                   r->in.value_name,
   10199             :                                                   REG_SZ,
   10200             :                                                   (uint8_t *) oid_string,
   10201           0 :                                                   strlen(oid_string) + 1);
   10202             :                 }
   10203             : 
   10204        1368 :                 result = winreg_printer_update_changeid(tmp_ctx, b,
   10205             :                                                         lp_const_servicename(snum));
   10206             : 
   10207             :         }
   10208             : 
   10209           0 : done:
   10210        1368 :         talloc_free(tmp_ctx);
   10211        1368 :         return result;
   10212             : }
   10213             : 
   10214             : /****************************************************************
   10215             :  _spoolss_DeletePrinterDataEx
   10216             : ****************************************************************/
   10217             : 
   10218        1368 : WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
   10219             :                                     struct spoolss_DeletePrinterDataEx *r)
   10220             : {
   10221           0 :         const char *printer;
   10222        1368 :         int             snum=0;
   10223        1368 :         WERROR          status = WERR_OK;
   10224        1368 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10225             : 
   10226        1368 :         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
   10227             : 
   10228        1368 :         if (!Printer) {
   10229           0 :                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
   10230             :                         "Invalid handle (%s:%u:%u).\n",
   10231             :                         OUR_HANDLE(r->in.handle)));
   10232           0 :                 return WERR_INVALID_HANDLE;
   10233             :         }
   10234             : 
   10235        1368 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10236           0 :                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
   10237             :                         "printer properties change denied by handle\n"));
   10238           0 :                 return WERR_ACCESS_DENIED;
   10239             :         }
   10240             : 
   10241        1368 :         if (!r->in.value_name || !r->in.key_name) {
   10242           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10243             :         }
   10244             : 
   10245        1368 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10246           0 :                 return WERR_INVALID_HANDLE;
   10247             :         }
   10248        1368 :         printer = lp_const_servicename(snum);
   10249             : 
   10250        1368 :         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
   10251             :                                               get_session_info_system(),
   10252             :                                               p->msg_ctx,
   10253             :                                               printer,
   10254             :                                               r->in.key_name,
   10255             :                                               r->in.value_name);
   10256        1368 :         if (W_ERROR_IS_OK(status)) {
   10257        1368 :                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
   10258             :                                                         get_session_info_system(),
   10259             :                                                         p->msg_ctx,
   10260             :                                                         printer);
   10261             :         }
   10262             : 
   10263        1368 :         return status;
   10264             : }
   10265             : 
   10266             : /****************************************************************
   10267             :  _spoolss_EnumPrinterKey
   10268             : ****************************************************************/
   10269             : 
   10270        3384 : WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
   10271             :                                struct spoolss_EnumPrinterKey *r)
   10272             : {
   10273           0 :         uint32_t        num_keys;
   10274        3384 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10275        3384 :         int             snum = 0;
   10276        3384 :         WERROR          result = WERR_FILE_NOT_FOUND;
   10277        3384 :         const char **array = NULL;
   10278           0 :         DATA_BLOB blob;
   10279             : 
   10280        3384 :         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
   10281             : 
   10282        3384 :         if (!Printer) {
   10283           0 :                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
   10284             :                         OUR_HANDLE(r->in.handle)));
   10285           0 :                 return WERR_INVALID_HANDLE;
   10286             :         }
   10287             : 
   10288        3384 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10289           0 :                 return WERR_INVALID_HANDLE;
   10290             :         }
   10291             : 
   10292        3384 :         result = winreg_enum_printer_key_internal(p->mem_ctx,
   10293             :                                          get_session_info_system(),
   10294             :                                          p->msg_ctx,
   10295             :                                          lp_const_servicename(snum),
   10296             :                                          r->in.key_name,
   10297             :                                          &num_keys,
   10298             :                                          &array);
   10299        3384 :         if (!W_ERROR_IS_OK(result)) {
   10300           0 :                 goto done;
   10301             :         }
   10302             : 
   10303        3384 :         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
   10304           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
   10305           0 :                 goto done;
   10306             :         }
   10307             : 
   10308        3384 :         *r->out._ndr_size = r->in.offered / 2;
   10309        3384 :         *r->out.needed = blob.length;
   10310             : 
   10311        3384 :         if (r->in.offered < *r->out.needed) {
   10312        1304 :                 result = WERR_MORE_DATA;
   10313             :         } else {
   10314        2080 :                 result = WERR_OK;
   10315        2080 :                 r->out.key_buffer->string_array = array;
   10316             :         }
   10317             : 
   10318        3384 :  done:
   10319        3384 :         if (!W_ERROR_IS_OK(result)) {
   10320        1304 :                 TALLOC_FREE(array);
   10321        1304 :                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
   10322           0 :                         *r->out.needed = 0;
   10323             :                 }
   10324             :         }
   10325             : 
   10326        3384 :         return result;
   10327             : }
   10328             : 
   10329             : /****************************************************************
   10330             :  _spoolss_DeletePrinterKey
   10331             : ****************************************************************/
   10332             : 
   10333         216 : WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
   10334             :                                  struct spoolss_DeletePrinterKey *r)
   10335             : {
   10336         216 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10337         216 :         int                     snum=0;
   10338           0 :         WERROR                  status;
   10339           0 :         const char *printer;
   10340           0 :         struct dcerpc_binding_handle *b;
   10341           0 :         TALLOC_CTX *tmp_ctx;
   10342             : 
   10343         216 :         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
   10344             : 
   10345         216 :         if (!Printer) {
   10346           0 :                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
   10347             :                         OUR_HANDLE(r->in.handle)));
   10348           0 :                 return WERR_INVALID_HANDLE;
   10349             :         }
   10350             : 
   10351             :         /* if keyname == NULL, return error */
   10352         216 :         if ( !r->in.key_name )
   10353           0 :                 return WERR_INVALID_PARAMETER;
   10354             : 
   10355         216 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10356           0 :                 return WERR_INVALID_HANDLE;
   10357             :         }
   10358             : 
   10359         216 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10360           0 :                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
   10361             :                         "printer properties change denied by handle\n"));
   10362           0 :                 return WERR_ACCESS_DENIED;
   10363             :         }
   10364             : 
   10365         216 :         printer = lp_const_servicename(snum);
   10366             : 
   10367         216 :         tmp_ctx = talloc_new(p->mem_ctx);
   10368         216 :         if (!tmp_ctx) {
   10369           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10370             :         }
   10371             : 
   10372         216 :         status = winreg_printer_binding_handle(tmp_ctx,
   10373             :                                                get_session_info_system(),
   10374             :                                                p->msg_ctx,
   10375             :                                                &b);
   10376         216 :         if (!W_ERROR_IS_OK(status)) {
   10377           0 :                 goto done;
   10378             :         }
   10379             : 
   10380             :         /* delete the key and all subkeys */
   10381         216 :         status = winreg_delete_printer_key(tmp_ctx, b,
   10382             :                                            printer,
   10383             :                                            r->in.key_name);
   10384         216 :         if (W_ERROR_IS_OK(status)) {
   10385         216 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
   10386             :                                                         printer);
   10387             :         }
   10388             : 
   10389           0 : done:
   10390         216 :         talloc_free(tmp_ctx);
   10391         216 :         return status;
   10392             : }
   10393             : 
   10394             : /****************************************************************
   10395             :  _spoolss_EnumPrinterDataEx
   10396             : ****************************************************************/
   10397             : 
   10398        2860 : WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
   10399             :                                   struct spoolss_EnumPrinterDataEx *r)
   10400             : {
   10401        2860 :         uint32_t        count = 0;
   10402        2860 :         struct spoolss_PrinterEnumValues *info = NULL;
   10403        2860 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10404           0 :         int             snum;
   10405           0 :         WERROR          result;
   10406             : 
   10407        2860 :         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
   10408             : 
   10409        2860 :         *r->out.count = 0;
   10410        2860 :         *r->out.needed = 0;
   10411        2860 :         *r->out.info = NULL;
   10412             : 
   10413        2860 :         if (!Printer) {
   10414           0 :                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
   10415             :                         OUR_HANDLE(r->in.handle)));
   10416           0 :                 return WERR_INVALID_HANDLE;
   10417             :         }
   10418             : 
   10419             :         /*
   10420             :          * first check for a keyname of NULL or "".  Win2k seems to send
   10421             :          * this a lot and we should send back WERR_INVALID_PARAMETER
   10422             :          * no need to spend time looking up the printer in this case.
   10423             :          * --jerry
   10424             :          */
   10425             : 
   10426        2860 :         if (!strlen(r->in.key_name)) {
   10427           4 :                 result = WERR_INVALID_PARAMETER;
   10428           4 :                 goto done;
   10429             :         }
   10430             : 
   10431        2856 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10432           0 :                 return WERR_INVALID_HANDLE;
   10433             :         }
   10434             : 
   10435             :         /* now look for a match on the key name */
   10436        2856 :         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
   10437             :                                             get_session_info_system(),
   10438             :                                             p->msg_ctx,
   10439             :                                             lp_const_servicename(snum),
   10440             :                                             r->in.key_name,
   10441             :                                             &count,
   10442             :                                             &info);
   10443        2856 :         if (!W_ERROR_IS_OK(result)) {
   10444           0 :                 goto done;
   10445             :         }
   10446             : 
   10447        2856 :         *r->out.count        = count;
   10448        2856 :         *r->out.info = info;
   10449             : 
   10450        2860 :  done:
   10451        2860 :         if (!W_ERROR_IS_OK(result)) {
   10452           4 :                 return result;
   10453             :         }
   10454             : 
   10455        2856 :         *r->out.needed       = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
   10456             :                                                spoolss_EnumPrinterDataEx,
   10457             :                                                *r->out.info,
   10458             :                                                *r->out.count);
   10459        2856 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
   10460        2856 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
   10461             : 
   10462        2856 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
   10463             : }
   10464             : 
   10465             : /****************************************************************************
   10466             : ****************************************************************************/
   10467             : 
   10468          40 : static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
   10469             :                                                  const char *servername,
   10470             :                                                  const char *environment,
   10471             :                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
   10472             : {
   10473           0 :         WERROR werr;
   10474          40 :         char *path = NULL;
   10475             : 
   10476          40 :         werr = compose_spoolss_server_path(mem_ctx,
   10477             :                                            servername,
   10478             :                                            environment,
   10479             :                                            SPOOLSS_PRTPROCS_PATH,
   10480             :                                            &path);
   10481          40 :         if (!W_ERROR_IS_OK(werr)) {
   10482           0 :                 return werr;
   10483             :         }
   10484             : 
   10485          40 :         DEBUG(4,("print processor directory: [%s]\n", path));
   10486             : 
   10487          40 :         r->directory_name = path;
   10488             : 
   10489          40 :         return WERR_OK;
   10490             : }
   10491             : 
   10492             : /****************************************************************
   10493             :  _spoolss_GetPrintProcessorDirectory
   10494             : ****************************************************************/
   10495             : 
   10496          40 : WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
   10497             :                                            struct spoolss_GetPrintProcessorDirectory *r)
   10498             : {
   10499           0 :         WERROR result;
   10500          40 :         char *prnproc_share = NULL;
   10501          40 :         bool prnproc_share_exists = false;
   10502           0 :         int snum;
   10503             : 
   10504             :         /* that's an [in out] buffer */
   10505             : 
   10506          40 :         if (!r->in.buffer && (r->in.offered != 0)) {
   10507           0 :                 result = WERR_INVALID_PARAMETER;
   10508           0 :                 goto err_info_free;
   10509             :         }
   10510             : 
   10511          40 :         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
   10512             :                 r->in.level));
   10513             : 
   10514          40 :         *r->out.needed = 0;
   10515             : 
   10516             :         /* r->in.level is ignored */
   10517             : 
   10518             :         /* We always should reply with a local print processor directory so that
   10519             :          * users are not forced to have a [prnproc$] share on the Samba spoolss
   10520             :          * server, if users decide to do so, lets announce it though - Guenther */
   10521             : 
   10522          40 :         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
   10523          40 :         if (!prnproc_share) {
   10524           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
   10525           0 :                 goto err_info_free;
   10526             :         }
   10527          40 :         if (snum != -1) {
   10528           0 :                 prnproc_share_exists = true;
   10529             :         }
   10530             : 
   10531          40 :         result = getprintprocessordirectory_level_1(p->mem_ctx,
   10532             :                                                     prnproc_share_exists ? r->in.server : NULL,
   10533             :                                                     r->in.environment,
   10534          40 :                                                     &r->out.info->info1);
   10535          40 :         if (!W_ERROR_IS_OK(result)) {
   10536           0 :                 goto err_info_free;
   10537             :         }
   10538             : 
   10539          40 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
   10540             :                                                                                    r->out.info, r->in.level);
   10541          40 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
   10542             : 
   10543          40 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
   10544             : 
   10545           0 : err_info_free:
   10546           0 :         TALLOC_FREE(r->out.info);
   10547           0 :         return result;
   10548             : }
   10549             : 
   10550             : /*******************************************************************
   10551             :  ********************************************************************/
   10552             : 
   10553           0 : static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
   10554             :                                const char *dllname)
   10555             : {
   10556           0 :         enum ndr_err_code ndr_err;
   10557           0 :         struct spoolss_MonitorUi ui;
   10558             : 
   10559           0 :         ui.dll_name = dllname;
   10560             : 
   10561           0 :         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
   10562             :                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
   10563           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10564           0 :                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
   10565             :         }
   10566           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10567             : }
   10568             : 
   10569             : /*******************************************************************
   10570             :  Streams the monitor UI DLL name in UNICODE
   10571             : *******************************************************************/
   10572             : 
   10573           0 : static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
   10574             :                                struct security_token *token, DATA_BLOB *in,
   10575             :                                DATA_BLOB *out, uint32_t *needed)
   10576             : {
   10577           0 :         const char *dllname = "tcpmonui.dll";
   10578             : 
   10579           0 :         *needed = (strlen(dllname)+1) * 2;
   10580             : 
   10581           0 :         if (out->length < *needed) {
   10582           0 :                 return WERR_INSUFFICIENT_BUFFER;
   10583             :         }
   10584             : 
   10585           0 :         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
   10586           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10587             :         }
   10588             : 
   10589           0 :         return WERR_OK;
   10590             : }
   10591             : 
   10592             : /*******************************************************************
   10593             :  ********************************************************************/
   10594             : 
   10595           0 : static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
   10596             :                              struct spoolss_PortData1 *port1,
   10597             :                              const DATA_BLOB *buf)
   10598             : {
   10599           0 :         enum ndr_err_code ndr_err;
   10600           0 :         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
   10601             :                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
   10602           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10603           0 :                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
   10604             :         }
   10605           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10606             : }
   10607             : 
   10608             : /*******************************************************************
   10609             :  ********************************************************************/
   10610             : 
   10611           0 : static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
   10612             :                              struct spoolss_PortData2 *port2,
   10613             :                              const DATA_BLOB *buf)
   10614             : {
   10615           0 :         enum ndr_err_code ndr_err;
   10616           0 :         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
   10617             :                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
   10618           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10619           0 :                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
   10620             :         }
   10621           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10622             : }
   10623             : 
   10624             : /*******************************************************************
   10625             :  Create a new TCP/IP port
   10626             : *******************************************************************/
   10627             : 
   10628           0 : static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
   10629             :                              struct security_token *token, DATA_BLOB *in,
   10630             :                              DATA_BLOB *out, uint32_t *needed)
   10631             : {
   10632           0 :         struct spoolss_PortData1 port1;
   10633           0 :         struct spoolss_PortData2 port2;
   10634           0 :         char *device_uri = NULL;
   10635           0 :         uint32_t version;
   10636             : 
   10637           0 :         const char *portname;
   10638           0 :         const char *hostaddress;
   10639           0 :         const char *queue;
   10640           0 :         uint32_t port_number;
   10641           0 :         uint32_t protocol;
   10642             : 
   10643             :         /* peek for spoolss_PortData version */
   10644             : 
   10645           0 :         if (!in || (in->length < (128 + 4))) {
   10646           0 :                 return WERR_GEN_FAILURE;
   10647             :         }
   10648             : 
   10649           0 :         version = IVAL(in->data, 128);
   10650             : 
   10651           0 :         switch (version) {
   10652           0 :                 case 1:
   10653           0 :                         ZERO_STRUCT(port1);
   10654             : 
   10655           0 :                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
   10656           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
   10657             :                         }
   10658             : 
   10659           0 :                         portname        = port1.portname;
   10660           0 :                         hostaddress     = port1.hostaddress;
   10661           0 :                         queue           = port1.queue;
   10662           0 :                         protocol        = port1.protocol;
   10663           0 :                         port_number     = port1.port_number;
   10664             : 
   10665           0 :                         break;
   10666           0 :                 case 2:
   10667           0 :                         ZERO_STRUCT(port2);
   10668             : 
   10669           0 :                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
   10670           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
   10671             :                         }
   10672             : 
   10673           0 :                         portname        = port2.portname;
   10674           0 :                         hostaddress     = port2.hostaddress;
   10675           0 :                         queue           = port2.queue;
   10676           0 :                         protocol        = port2.protocol;
   10677           0 :                         port_number     = port2.port_number;
   10678             : 
   10679           0 :                         break;
   10680           0 :                 default:
   10681           0 :                         DEBUG(1,("xcvtcp_addport: "
   10682             :                                 "unknown version of port_data: %d\n", version));
   10683           0 :                         return WERR_UNKNOWN_PORT;
   10684             :         }
   10685             : 
   10686             :         /* create the device URI and call the add_port_hook() */
   10687             : 
   10688           0 :         switch (protocol) {
   10689           0 :         case PROTOCOL_RAWTCP_TYPE:
   10690           0 :                 device_uri = talloc_asprintf(mem_ctx,
   10691             :                                 "socket://%s:%d/", hostaddress,
   10692             :                                 port_number);
   10693           0 :                 break;
   10694             : 
   10695           0 :         case PROTOCOL_LPR_TYPE:
   10696           0 :                 device_uri = talloc_asprintf(mem_ctx,
   10697             :                         "lpr://%s/%s", hostaddress, queue );
   10698           0 :                 break;
   10699             : 
   10700           0 :         default:
   10701           0 :                 return WERR_UNKNOWN_PORT;
   10702             :         }
   10703             : 
   10704           0 :         if (!device_uri) {
   10705           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10706             :         }
   10707             : 
   10708           0 :         return add_port_hook(mem_ctx, token, portname, device_uri);
   10709             : }
   10710             : 
   10711             : /*******************************************************************
   10712             : *******************************************************************/
   10713             : 
   10714             : struct xcv_api_table xcvtcp_cmds[] = {
   10715             :         { "MonitorUI",        xcvtcp_monitorui },
   10716             :         { "AddPort",  xcvtcp_addport},
   10717             :         { NULL,         NULL }
   10718             : };
   10719             : 
   10720           0 : static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
   10721             :                                      struct security_token *token, const char *command,
   10722             :                                      DATA_BLOB *inbuf,
   10723             :                                      DATA_BLOB *outbuf,
   10724             :                                      uint32_t *needed )
   10725             : {
   10726           0 :         int i;
   10727             : 
   10728           0 :         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
   10729             : 
   10730           0 :         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
   10731           0 :                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
   10732           0 :                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
   10733             :         }
   10734             : 
   10735           0 :         return WERR_INVALID_FUNCTION;
   10736             : }
   10737             : 
   10738             : /*******************************************************************
   10739             : *******************************************************************/
   10740             : #if 0   /* don't support management using the "Local Port" monitor */
   10741             : 
   10742             : static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
   10743             :                                  struct security_token *token, DATA_BLOB *in,
   10744             :                                  DATA_BLOB *out, uint32_t *needed)
   10745             : {
   10746             :         const char *dllname = "localui.dll";
   10747             : 
   10748             :         *needed = (strlen(dllname)+1) * 2;
   10749             : 
   10750             :         if (out->length < *needed) {
   10751             :                 return WERR_INSUFFICIENT_BUFFER;
   10752             :         }
   10753             : 
   10754             :         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
   10755             :                 return WERR_NOT_ENOUGH_MEMORY;
   10756             :         }
   10757             : 
   10758             :         return WERR_OK;
   10759             : }
   10760             : 
   10761             : /*******************************************************************
   10762             : *******************************************************************/
   10763             : 
   10764             : struct xcv_api_table xcvlocal_cmds[] = {
   10765             :         { "MonitorUI",        xcvlocal_monitorui },
   10766             :         { NULL,         NULL }
   10767             : };
   10768             : #else
   10769             : struct xcv_api_table xcvlocal_cmds[] = {
   10770             :         { NULL,         NULL }
   10771             : };
   10772             : #endif
   10773             : 
   10774             : 
   10775             : 
   10776             : /*******************************************************************
   10777             : *******************************************************************/
   10778             : 
   10779           0 : static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
   10780             :                                        struct security_token *token, const char *command,
   10781             :                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
   10782             :                                        uint32_t *needed)
   10783             : {
   10784           0 :         int i;
   10785             : 
   10786           0 :         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
   10787             : 
   10788           0 :         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
   10789           0 :                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
   10790           0 :                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
   10791             :         }
   10792           0 :         return WERR_INVALID_FUNCTION;
   10793             : }
   10794             : 
   10795             : /****************************************************************
   10796             :  _spoolss_XcvData
   10797             : ****************************************************************/
   10798             : 
   10799           0 : WERROR _spoolss_XcvData(struct pipes_struct *p,
   10800             :                         struct spoolss_XcvData *r)
   10801             : {
   10802           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
   10803           0 :         struct auth_session_info *session_info =
   10804           0 :                 dcesrv_call_session_info(dce_call);
   10805           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10806           0 :         DATA_BLOB out_data = data_blob_null;
   10807           0 :         WERROR werror;
   10808             : 
   10809           0 :         if (!Printer) {
   10810           0 :                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
   10811             :                         OUR_HANDLE(r->in.handle)));
   10812           0 :                 return WERR_INVALID_HANDLE;
   10813             :         }
   10814             : 
   10815             :         /* Has to be a handle to the TCP/IP port monitor */
   10816             : 
   10817           0 :         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
   10818           0 :                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
   10819           0 :                 return WERR_INVALID_HANDLE;
   10820             :         }
   10821             : 
   10822             :         /* requires administrative access to the server */
   10823             : 
   10824           0 :         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
   10825           0 :                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
   10826           0 :                 return WERR_ACCESS_DENIED;
   10827             :         }
   10828             : 
   10829             :         /* Allocate the outgoing buffer */
   10830             : 
   10831           0 :         if (r->in.out_data_size) {
   10832           0 :                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
   10833           0 :                 if (out_data.data == NULL) {
   10834           0 :                         return WERR_NOT_ENOUGH_MEMORY;
   10835             :                 }
   10836             :         }
   10837             : 
   10838           0 :         switch ( Printer->printer_type ) {
   10839           0 :         case SPLHND_PORTMON_TCP:
   10840           0 :                 werror = process_xcvtcp_command(p->mem_ctx,
   10841             :                                                 session_info->security_token,
   10842             :                                                 r->in.function_name,
   10843             :                                                 &r->in.in_data, &out_data,
   10844             :                                                 r->out.needed);
   10845           0 :                 break;
   10846           0 :         case SPLHND_PORTMON_LOCAL:
   10847           0 :                 werror = process_xcvlocal_command(p->mem_ctx,
   10848             :                                                   session_info->security_token,
   10849             :                                                   r->in.function_name,
   10850             :                                                   &r->in.in_data, &out_data,
   10851             :                                                   r->out.needed);
   10852           0 :                 break;
   10853           0 :         default:
   10854           0 :                 werror = WERR_INVALID_PRINT_MONITOR;
   10855             :         }
   10856             : 
   10857           0 :         if (!W_ERROR_IS_OK(werror)) {
   10858           0 :                 return werror;
   10859             :         }
   10860             : 
   10861           0 :         *r->out.status_code = 0;
   10862             : 
   10863           0 :         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
   10864           0 :                 memcpy(r->out.out_data, out_data.data,
   10865           0 :                         MIN(r->in.out_data_size, out_data.length));
   10866             :         }
   10867             : 
   10868           0 :         return WERR_OK;
   10869             : }
   10870             : 
   10871             : /****************************************************************
   10872             :  _spoolss_AddPrintProcessor
   10873             : ****************************************************************/
   10874             : 
   10875           4 : WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
   10876             :                                   struct spoolss_AddPrintProcessor *r)
   10877             : {
   10878             :         /* for now, just indicate success and ignore the add.  We'll
   10879             :            automatically set the winprint processor for printer
   10880             :            entries later.  Used to debug the LexMark Optra S 1855 PCL
   10881             :            driver --jerry */
   10882             : 
   10883           4 :         return WERR_OK;
   10884             : }
   10885             : 
   10886             : /****************************************************************
   10887             :  _spoolss_AddPort
   10888             : ****************************************************************/
   10889             : 
   10890           4 : WERROR _spoolss_AddPort(struct pipes_struct *p,
   10891             :                         struct spoolss_AddPort *r)
   10892             : {
   10893             :         /* do what w2k3 does */
   10894             : 
   10895           4 :         return WERR_NOT_SUPPORTED;
   10896             : }
   10897             : 
   10898             : /****************************************************************
   10899             :  _spoolss_GetPrinterDriver
   10900             : ****************************************************************/
   10901             : 
   10902           0 : WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
   10903             :                                  struct spoolss_GetPrinterDriver *r)
   10904             : {
   10905           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10906           0 :         return WERR_NOT_SUPPORTED;
   10907             : }
   10908             : 
   10909             : /****************************************************************
   10910             :  _spoolss_ReadPrinter
   10911             : ****************************************************************/
   10912             : 
   10913           0 : WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
   10914             :                             struct spoolss_ReadPrinter *r)
   10915             : {
   10916           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10917           0 :         return WERR_NOT_SUPPORTED;
   10918             : }
   10919             : 
   10920             : /****************************************************************
   10921             :  _spoolss_WaitForPrinterChange
   10922             : ****************************************************************/
   10923             : 
   10924           0 : WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
   10925             :                                      struct spoolss_WaitForPrinterChange *r)
   10926             : {
   10927           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10928           0 :         return WERR_NOT_SUPPORTED;
   10929             : }
   10930             : 
   10931             : /****************************************************************
   10932             :  _spoolss_ConfigurePort
   10933             : ****************************************************************/
   10934             : 
   10935           0 : WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
   10936             :                               struct spoolss_ConfigurePort *r)
   10937             : {
   10938           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10939           0 :         return WERR_NOT_SUPPORTED;
   10940             : }
   10941             : 
   10942             : /****************************************************************
   10943             :  _spoolss_DeletePort
   10944             : ****************************************************************/
   10945             : 
   10946           0 : WERROR _spoolss_DeletePort(struct pipes_struct *p,
   10947             :                            struct spoolss_DeletePort *r)
   10948             : {
   10949           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10950           0 :         return WERR_NOT_SUPPORTED;
   10951             : }
   10952             : 
   10953             : /****************************************************************
   10954             :  _spoolss_CreatePrinterIC
   10955             : ****************************************************************/
   10956             : 
   10957           0 : WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
   10958             :                                 struct spoolss_CreatePrinterIC *r)
   10959             : {
   10960           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10961           0 :         return WERR_NOT_SUPPORTED;
   10962             : }
   10963             : 
   10964             : /****************************************************************
   10965             :  _spoolss_PlayGDIScriptOnPrinterIC
   10966             : ****************************************************************/
   10967             : 
   10968           0 : WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
   10969             :                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
   10970             : {
   10971           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10972           0 :         return WERR_NOT_SUPPORTED;
   10973             : }
   10974             : 
   10975             : /****************************************************************
   10976             :  _spoolss_DeletePrinterIC
   10977             : ****************************************************************/
   10978             : 
   10979           0 : WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
   10980             :                                 struct spoolss_DeletePrinterIC *r)
   10981             : {
   10982           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10983           0 :         return WERR_NOT_SUPPORTED;
   10984             : }
   10985             : 
   10986             : /****************************************************************
   10987             :  _spoolss_AddPrinterConnection
   10988             : ****************************************************************/
   10989             : 
   10990           0 : WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
   10991             :                                      struct spoolss_AddPrinterConnection *r)
   10992             : {
   10993           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10994           0 :         return WERR_NOT_SUPPORTED;
   10995             : }
   10996             : 
   10997             : /****************************************************************
   10998             :  _spoolss_DeletePrinterConnection
   10999             : ****************************************************************/
   11000             : 
   11001           0 : WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
   11002             :                                         struct spoolss_DeletePrinterConnection *r)
   11003             : {
   11004           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11005           0 :         return WERR_NOT_SUPPORTED;
   11006             : }
   11007             : 
   11008             : /****************************************************************
   11009             :  _spoolss_PrinterMessageBox
   11010             : ****************************************************************/
   11011             : 
   11012           0 : WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
   11013             :                                   struct spoolss_PrinterMessageBox *r)
   11014             : {
   11015           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11016           0 :         return WERR_NOT_SUPPORTED;
   11017             : }
   11018             : 
   11019             : /****************************************************************
   11020             :  _spoolss_AddMonitor
   11021             : ****************************************************************/
   11022             : 
   11023           0 : WERROR _spoolss_AddMonitor(struct pipes_struct *p,
   11024             :                            struct spoolss_AddMonitor *r)
   11025             : {
   11026           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11027           0 :         return WERR_NOT_SUPPORTED;
   11028             : }
   11029             : 
   11030             : /****************************************************************
   11031             :  _spoolss_DeleteMonitor
   11032             : ****************************************************************/
   11033             : 
   11034           0 : WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
   11035             :                               struct spoolss_DeleteMonitor *r)
   11036             : {
   11037           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11038           0 :         return WERR_NOT_SUPPORTED;
   11039             : }
   11040             : 
   11041             : /****************************************************************
   11042             :  _spoolss_DeletePrintProcessor
   11043             : ****************************************************************/
   11044             : 
   11045           0 : WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
   11046             :                                      struct spoolss_DeletePrintProcessor *r)
   11047             : {
   11048           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11049           0 :         return WERR_NOT_SUPPORTED;
   11050             : }
   11051             : 
   11052             : /****************************************************************
   11053             :  _spoolss_AddPrintProvidor
   11054             : ****************************************************************/
   11055             : 
   11056           0 : WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
   11057             :                                  struct spoolss_AddPrintProvidor *r)
   11058             : {
   11059           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11060           0 :         return WERR_NOT_SUPPORTED;
   11061             : }
   11062             : 
   11063             : /****************************************************************
   11064             :  _spoolss_DeletePrintProvidor
   11065             : ****************************************************************/
   11066             : 
   11067           0 : WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
   11068             :                                     struct spoolss_DeletePrintProvidor *r)
   11069             : {
   11070           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11071           0 :         return WERR_NOT_SUPPORTED;
   11072             : }
   11073             : 
   11074             : /****************************************************************
   11075             :  _spoolss_FindFirstPrinterChangeNotification
   11076             : ****************************************************************/
   11077             : 
   11078           0 : WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
   11079             :                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
   11080             : {
   11081           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11082           0 :         return WERR_NOT_SUPPORTED;
   11083             : }
   11084             : 
   11085             : /****************************************************************
   11086             :  _spoolss_FindNextPrinterChangeNotification
   11087             : ****************************************************************/
   11088             : 
   11089           0 : WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
   11090             :                                                   struct spoolss_FindNextPrinterChangeNotification *r)
   11091             : {
   11092           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11093           0 :         return WERR_NOT_SUPPORTED;
   11094             : }
   11095             : 
   11096             : /****************************************************************
   11097             :  _spoolss_RouterFindFirstPrinterChangeNotificationOld
   11098             : ****************************************************************/
   11099             : 
   11100           0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
   11101             :                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
   11102             : {
   11103           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11104           0 :         return WERR_NOT_SUPPORTED;
   11105             : }
   11106             : 
   11107             : /****************************************************************
   11108             :  _spoolss_ReplyOpenPrinter
   11109             : ****************************************************************/
   11110             : 
   11111           0 : WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
   11112             :                                  struct spoolss_ReplyOpenPrinter *r)
   11113             : {
   11114           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11115           0 :         return WERR_NOT_SUPPORTED;
   11116             : }
   11117             : 
   11118             : /****************************************************************
   11119             :  _spoolss_RouterReplyPrinter
   11120             : ****************************************************************/
   11121             : 
   11122           0 : WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
   11123             :                                    struct spoolss_RouterReplyPrinter *r)
   11124             : {
   11125           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11126           0 :         return WERR_NOT_SUPPORTED;
   11127             : }
   11128             : 
   11129             : /****************************************************************
   11130             :  _spoolss_ReplyClosePrinter
   11131             : ****************************************************************/
   11132             : 
   11133           0 : WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
   11134             :                                   struct spoolss_ReplyClosePrinter *r)
   11135             : {
   11136           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11137           0 :         return WERR_NOT_SUPPORTED;
   11138             : }
   11139             : 
   11140             : /****************************************************************
   11141             :  _spoolss_AddPortEx
   11142             : ****************************************************************/
   11143             : 
   11144           0 : WERROR _spoolss_AddPortEx(struct pipes_struct *p,
   11145             :                           struct spoolss_AddPortEx *r)
   11146             : {
   11147           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11148           0 :         return WERR_NOT_SUPPORTED;
   11149             : }
   11150             : 
   11151             : /****************************************************************
   11152             :  _spoolss_RouterFindFirstPrinterChangeNotification
   11153             : ****************************************************************/
   11154             : 
   11155           0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
   11156             :                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
   11157             : {
   11158           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11159           0 :         return WERR_NOT_SUPPORTED;
   11160             : }
   11161             : 
   11162             : /****************************************************************
   11163             :  _spoolss_SpoolerInit
   11164             : ****************************************************************/
   11165             : 
   11166           0 : WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
   11167             :                             struct spoolss_SpoolerInit *r)
   11168             : {
   11169           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11170           0 :         return WERR_NOT_SUPPORTED;
   11171             : }
   11172             : 
   11173             : /****************************************************************
   11174             :  _spoolss_ResetPrinterEx
   11175             : ****************************************************************/
   11176             : 
   11177           0 : WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
   11178             :                                struct spoolss_ResetPrinterEx *r)
   11179             : {
   11180           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11181           0 :         return WERR_NOT_SUPPORTED;
   11182             : }
   11183             : 
   11184             : /****************************************************************
   11185             :  _spoolss_RouterReplyPrinterEx
   11186             : ****************************************************************/
   11187             : 
   11188           0 : WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
   11189             :                                      struct spoolss_RouterReplyPrinterEx *r)
   11190             : {
   11191           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11192           0 :         return WERR_NOT_SUPPORTED;
   11193             : }
   11194             : 
   11195             : /****************************************************************
   11196             :  _spoolss_44
   11197             : ****************************************************************/
   11198             : 
   11199           0 : WERROR _spoolss_44(struct pipes_struct *p,
   11200             :                    struct spoolss_44 *r)
   11201             : {
   11202           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11203           0 :         return WERR_NOT_SUPPORTED;
   11204             : }
   11205             : 
   11206             : /****************************************************************
   11207             :  _spoolss_SetPort
   11208             : ****************************************************************/
   11209             : 
   11210           0 : WERROR _spoolss_SetPort(struct pipes_struct *p,
   11211             :                         struct spoolss_SetPort *r)
   11212             : {
   11213           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11214           0 :         return WERR_NOT_SUPPORTED;
   11215             : }
   11216             : 
   11217             : /****************************************************************
   11218             :  _spoolss_4a
   11219             : ****************************************************************/
   11220             : 
   11221           0 : WERROR _spoolss_4a(struct pipes_struct *p,
   11222             :                    struct spoolss_4a *r)
   11223             : {
   11224           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11225           0 :         return WERR_NOT_SUPPORTED;
   11226             : }
   11227             : 
   11228             : /****************************************************************
   11229             :  _spoolss_4b
   11230             : ****************************************************************/
   11231             : 
   11232           0 : WERROR _spoolss_4b(struct pipes_struct *p,
   11233             :                    struct spoolss_4b *r)
   11234             : {
   11235           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11236           0 :         return WERR_NOT_SUPPORTED;
   11237             : }
   11238             : 
   11239             : /****************************************************************
   11240             :  _spoolss_4c
   11241             : ****************************************************************/
   11242             : 
   11243           0 : WERROR _spoolss_4c(struct pipes_struct *p,
   11244             :                    struct spoolss_4c *r)
   11245             : {
   11246           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11247           0 :         return WERR_NOT_SUPPORTED;
   11248             : }
   11249             : 
   11250             : /****************************************************************
   11251             :  _spoolss_53
   11252             : ****************************************************************/
   11253             : 
   11254           0 : WERROR _spoolss_53(struct pipes_struct *p,
   11255             :                    struct spoolss_53 *r)
   11256             : {
   11257           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11258           0 :         return WERR_NOT_SUPPORTED;
   11259             : }
   11260             : 
   11261             : /****************************************************************
   11262             :  _spoolss_AddPerMachineConnection
   11263             : ****************************************************************/
   11264             : 
   11265           4 : WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
   11266             :                                         struct spoolss_AddPerMachineConnection *r)
   11267             : {
   11268           4 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11269           4 :         return WERR_NOT_SUPPORTED;
   11270             : }
   11271             : 
   11272             : /****************************************************************
   11273             :  _spoolss_DeletePerMachineConnection
   11274             : ****************************************************************/
   11275             : 
   11276           0 : WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
   11277             :                                            struct spoolss_DeletePerMachineConnection *r)
   11278             : {
   11279           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11280           0 :         return WERR_NOT_SUPPORTED;
   11281             : }
   11282             : 
   11283             : /****************************************************************
   11284             :  _spoolss_EnumPerMachineConnections
   11285             : ****************************************************************/
   11286             : 
   11287           0 : WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
   11288             :                                           struct spoolss_EnumPerMachineConnections *r)
   11289             : {
   11290           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11291           0 :         return WERR_NOT_SUPPORTED;
   11292             : }
   11293             : 
   11294             : /****************************************************************
   11295             :  _spoolss_5a
   11296             : ****************************************************************/
   11297             : 
   11298           0 : WERROR _spoolss_5a(struct pipes_struct *p,
   11299             :                    struct spoolss_5a *r)
   11300             : {
   11301           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11302           0 :         return WERR_NOT_SUPPORTED;
   11303             : }
   11304             : 
   11305             : /****************************************************************
   11306             :  _spoolss_5b
   11307             : ****************************************************************/
   11308             : 
   11309           0 : WERROR _spoolss_5b(struct pipes_struct *p,
   11310             :                    struct spoolss_5b *r)
   11311             : {
   11312           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11313           0 :         return WERR_NOT_SUPPORTED;
   11314             : }
   11315             : 
   11316             : /****************************************************************
   11317             :  _spoolss_5c
   11318             : ****************************************************************/
   11319             : 
   11320           0 : WERROR _spoolss_5c(struct pipes_struct *p,
   11321             :                    struct spoolss_5c *r)
   11322             : {
   11323           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11324           0 :         return WERR_NOT_SUPPORTED;
   11325             : }
   11326             : 
   11327             : /****************************************************************
   11328             :  _spoolss_5d
   11329             : ****************************************************************/
   11330             : 
   11331           0 : WERROR _spoolss_5d(struct pipes_struct *p,
   11332             :                    struct spoolss_5d *r)
   11333             : {
   11334           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11335           0 :         return WERR_NOT_SUPPORTED;
   11336             : }
   11337             : 
   11338             : /****************************************************************
   11339             :  _spoolss_5e
   11340             : ****************************************************************/
   11341             : 
   11342           0 : WERROR _spoolss_5e(struct pipes_struct *p,
   11343             :                    struct spoolss_5e *r)
   11344             : {
   11345           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11346           0 :         return WERR_NOT_SUPPORTED;
   11347             : }
   11348             : 
   11349             : /****************************************************************
   11350             :  _spoolss_5f
   11351             : ****************************************************************/
   11352             : 
   11353           0 : WERROR _spoolss_5f(struct pipes_struct *p,
   11354             :                    struct spoolss_5f *r)
   11355             : {
   11356           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11357           0 :         return WERR_NOT_SUPPORTED;
   11358             : }
   11359             : 
   11360             : /****************************************************************
   11361             :  _spoolss_60
   11362             : ****************************************************************/
   11363             : 
   11364           0 : WERROR _spoolss_60(struct pipes_struct *p,
   11365             :                    struct spoolss_60 *r)
   11366             : {
   11367           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11368           0 :         return WERR_NOT_SUPPORTED;
   11369             : }
   11370             : 
   11371             : /****************************************************************
   11372             :  _spoolss_SendRecvBidiData
   11373             : ****************************************************************/
   11374             : 
   11375           0 : WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
   11376             :                                  struct spoolss_SendRecvBidiData *r)
   11377             : {
   11378           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11379           0 :         return WERR_NOT_SUPPORTED;
   11380             : }
   11381             : 
   11382             : /****************************************************************
   11383             :  _spoolss_62
   11384             : ****************************************************************/
   11385             : 
   11386           0 : WERROR _spoolss_62(struct pipes_struct *p,
   11387             :                    struct spoolss_62 *r)
   11388             : {
   11389           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11390           0 :         return WERR_NOT_SUPPORTED;
   11391             : }
   11392             : 
   11393             : /****************************************************************
   11394             :  _spoolss_63
   11395             : ****************************************************************/
   11396             : 
   11397           0 : WERROR _spoolss_63(struct pipes_struct *p,
   11398             :                    struct spoolss_63 *r)
   11399             : {
   11400           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11401           0 :         return WERR_NOT_SUPPORTED;
   11402             : }
   11403             : 
   11404             : /****************************************************************
   11405             :  _spoolss_64
   11406             : ****************************************************************/
   11407             : 
   11408           0 : WERROR _spoolss_64(struct pipes_struct *p,
   11409             :                    struct spoolss_64 *r)
   11410             : {
   11411           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11412           0 :         return WERR_NOT_SUPPORTED;
   11413             : }
   11414             : 
   11415             : /****************************************************************
   11416             :  _spoolss_65
   11417             : ****************************************************************/
   11418             : 
   11419           0 : WERROR _spoolss_65(struct pipes_struct *p,
   11420             :                    struct spoolss_65 *r)
   11421             : {
   11422           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11423           0 :         return WERR_NOT_SUPPORTED;
   11424             : }
   11425             : 
   11426             : /****************************************************************
   11427             :  _spoolss_GetCorePrinterDrivers
   11428             : ****************************************************************/
   11429             : 
   11430           8 : HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
   11431             :                                        struct spoolss_GetCorePrinterDrivers *r)
   11432             : {
   11433           8 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11434           8 :         return HRES_ERROR_NOT_SUPPORTED;
   11435             : }
   11436             : 
   11437             : /****************************************************************
   11438             :  _spoolss_67
   11439             : ****************************************************************/
   11440             : 
   11441           0 : WERROR _spoolss_67(struct pipes_struct *p,
   11442             :                    struct spoolss_67 *r)
   11443             : {
   11444           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11445           0 :         return WERR_NOT_SUPPORTED;
   11446             : }
   11447             : 
   11448             : /****************************************************************
   11449             :  _spoolss_GetPrinterDriverPackagePath
   11450             : ****************************************************************/
   11451             : 
   11452           4 : HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
   11453             :                                              struct spoolss_GetPrinterDriverPackagePath *r)
   11454             : {
   11455           4 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11456           4 :         return HRES_ERROR_NOT_SUPPORTED;
   11457             : }
   11458             : 
   11459             : /****************************************************************
   11460             :  _spoolss_69
   11461             : ****************************************************************/
   11462             : 
   11463           0 : WERROR _spoolss_69(struct pipes_struct *p,
   11464             :                    struct spoolss_69 *r)
   11465             : {
   11466           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11467           0 :         return WERR_NOT_SUPPORTED;
   11468             : }
   11469             : 
   11470             : /****************************************************************
   11471             :  _spoolss_6a
   11472             : ****************************************************************/
   11473             : 
   11474           0 : WERROR _spoolss_6a(struct pipes_struct *p,
   11475             :                    struct spoolss_6a *r)
   11476             : {
   11477           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11478           0 :         return WERR_NOT_SUPPORTED;
   11479             : }
   11480             : 
   11481             : /****************************************************************
   11482             :  _spoolss_6b
   11483             : ****************************************************************/
   11484             : 
   11485           0 : WERROR _spoolss_6b(struct pipes_struct *p,
   11486             :                    struct spoolss_6b *r)
   11487             : {
   11488           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11489           0 :         return WERR_NOT_SUPPORTED;
   11490             : }
   11491             : 
   11492             : /****************************************************************
   11493             :  _spoolss_6c
   11494             : ****************************************************************/
   11495             : 
   11496           0 : WERROR _spoolss_6c(struct pipes_struct *p,
   11497             :                    struct spoolss_6c *r)
   11498             : {
   11499           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11500           0 :         return WERR_NOT_SUPPORTED;
   11501             : }
   11502             : 
   11503             : /****************************************************************
   11504             :  _spoolss_6d
   11505             : ****************************************************************/
   11506             : 
   11507           0 : WERROR _spoolss_6d(struct pipes_struct *p,
   11508             :                    struct spoolss_6d *r)
   11509             : {
   11510           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11511           0 :         return WERR_NOT_SUPPORTED;
   11512             : }
   11513             : 
   11514             : /****************************************************************
   11515             :  _spoolss_GetJobNamedPropertyValue
   11516             : ****************************************************************/
   11517             : 
   11518           0 : WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
   11519             :                                          struct spoolss_GetJobNamedPropertyValue *r)
   11520             : {
   11521           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11522           0 :         return WERR_NOT_SUPPORTED;
   11523             : }
   11524             : 
   11525             : /****************************************************************
   11526             :  _spoolss_SetJobNamedProperty
   11527             : ****************************************************************/
   11528             : 
   11529           0 : WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
   11530             :                                     struct spoolss_SetJobNamedProperty *r)
   11531             : {
   11532           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11533           0 :         return WERR_NOT_SUPPORTED;
   11534             : }
   11535             : 
   11536             : /****************************************************************
   11537             :  _spoolss_DeleteJobNamedProperty
   11538             : ****************************************************************/
   11539             : 
   11540           0 : WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
   11541             :                                        struct spoolss_DeleteJobNamedProperty *r)
   11542             : {
   11543           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11544           0 :         return WERR_NOT_SUPPORTED;
   11545             : }
   11546             : 
   11547             : /****************************************************************
   11548             :  _spoolss_EnumJobNamedProperties
   11549             : ****************************************************************/
   11550             : 
   11551           0 : WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
   11552             :                                        struct spoolss_EnumJobNamedProperties *r)
   11553             : {
   11554           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11555           0 :         return WERR_NOT_SUPPORTED;
   11556             : }
   11557             : 
   11558             : /****************************************************************
   11559             :  _spoolss_72
   11560             : ****************************************************************/
   11561             : 
   11562           0 : WERROR _spoolss_72(struct pipes_struct *p,
   11563             :                    struct spoolss_72 *r)
   11564             : {
   11565           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11566           0 :         return WERR_NOT_SUPPORTED;
   11567             : }
   11568             : 
   11569             : /****************************************************************
   11570             :  _spoolss_73
   11571             : ****************************************************************/
   11572             : 
   11573           0 : WERROR _spoolss_73(struct pipes_struct *p,
   11574             :                    struct spoolss_73 *r)
   11575             : {
   11576           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11577           0 :         return WERR_NOT_SUPPORTED;
   11578             : }
   11579             : 
   11580             : /****************************************************************
   11581             :  _spoolss_RpcLogJobInfoForBranchOffice
   11582             : ****************************************************************/
   11583             : 
   11584           8 : WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
   11585             :                                           struct spoolss_LogJobInfoForBranchOffice *r)
   11586             : {
   11587           8 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11588           8 :         return WERR_NOT_SUPPORTED;
   11589             : }
   11590             : 
   11591             : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
   11592             :                 const struct dcesrv_endpoint_server *ep_server);
   11593             : 
   11594             : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
   11595             :                 const struct dcesrv_endpoint_server *ep_server);
   11596             : 
   11597             : #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
   11598             :         spoolss_init_server
   11599             : 
   11600             : #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
   11601             :         spoolss_shutdown_server
   11602             : 
   11603          28 : static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
   11604             :                 const struct dcesrv_endpoint_server *ep_server)
   11605             : {
   11606          28 :         struct messaging_context *msg_ctx = global_messaging_context();
   11607           0 :         bool ok;
   11608             : 
   11609             :         /*
   11610             :          * Migrate the printers first.
   11611             :          */
   11612          28 :         ok = nt_printing_tdb_migrate(msg_ctx);
   11613          28 :         if (!ok) {
   11614           0 :                 return NT_STATUS_UNSUCCESSFUL;
   11615             :         }
   11616             : 
   11617          28 :         return spoolss__op_init_server(dce_ctx, ep_server);
   11618             : }
   11619             : 
   11620          28 : static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
   11621             :                 const struct dcesrv_endpoint_server *ep_server)
   11622             : {
   11623          28 :         srv_spoolss_cleanup();
   11624             : 
   11625          28 :         return spoolss__op_shutdown_server(dce_ctx, ep_server);
   11626             : }
   11627             : 
   11628             : /* include the generated boilerplate */
   11629             : #include "librpc/gen_ndr/ndr_spoolss_scompat.c"

Generated by: LCOV version 1.14