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 v4-17-test 1498b464 Lines: 281 4478 6.3 %
Date: 2024-06-13 04:01:37 Functions: 20 275 7.3 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  RPC Pipe client / server routines
       4             :  *  Copyright (C) Andrew Tridgell              1992-2000,
       5             :  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
       6             :  *  Copyright (C) Jean François Micouleau      1998-2000,
       7             :  *  Copyright (C) Jeremy Allison               2001-2002,
       8             :  *  Copyright (C) Gerald Carter                2000-2004,
       9             :  *  Copyright (C) Tim Potter                   2001-2002.
      10             :  *  Copyright (C) Guenther Deschner            2009-2010.
      11             :  *  Copyright (C) Andreas Schneider            2010.
      12             :  *
      13             :  *  This program is free software; you can redistribute it and/or modify
      14             :  *  it under the terms of the GNU General Public License as published by
      15             :  *  the Free Software Foundation; either version 3 of the License, or
      16             :  *  (at your option) any later version.
      17             :  *
      18             :  *  This program is distributed in the hope that it will be useful,
      19             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      20             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      21             :  *  GNU General Public License for more details.
      22             :  *
      23             :  *  You should have received a copy of the GNU General Public License
      24             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      25             :  */
      26             : 
      27             : /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
      28             :    up, all the errors returned are DOS errors, not NT status codes. */
      29             : 
      30             : #include "includes.h"
      31             : #include "libsmb/namequery.h"
      32             : #include "ntdomain.h"
      33             : #include "nt_printing.h"
      34             : #include "srv_spoolss_util.h"
      35             : #include "librpc/gen_ndr/ndr_spoolss.h"
      36             : #include "librpc/gen_ndr/ndr_spoolss_scompat.h"
      37             : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
      38             : #include "rpc_client/init_spoolss.h"
      39             : #include "rpc_client/cli_pipe.h"
      40             : #include "../libcli/security/security.h"
      41             : #include "librpc/gen_ndr/ndr_security.h"
      42             : #include "registry.h"
      43             : #include "include/printing.h"
      44             : #include "secrets.h"
      45             : #include "../librpc/gen_ndr/netlogon.h"
      46             : #include "rpc_misc.h"
      47             : #include "printing/notify.h"
      48             : #include "serverid.h"
      49             : #include "../libcli/registry/util_reg.h"
      50             : #include "smbd/smbd.h"
      51             : #include "smbd/globals.h"
      52             : #include "auth.h"
      53             : #include "messages.h"
      54             : #include "rpc_server/spoolss/srv_spoolss_nt.h"
      55             : #include "util_tdb.h"
      56             : #include "libsmb/libsmb.h"
      57             : #include "printing/printer_list.h"
      58             : #include "../lib/tsocket/tsocket.h"
      59             : #include "rpc_client/cli_winreg_spoolss.h"
      60             : #include "../libcli/smb/smbXcli_base.h"
      61             : #include "rpc_server/spoolss/srv_spoolss_handle.h"
      62             : #include "lib/gencache.h"
      63             : #include "rpc_server/rpc_server.h"
      64             : #include "librpc/rpc/dcesrv_core.h"
      65             : #include "printing/nt_printing_migrate_internal.h"
      66             : #include "lib/util/string_wrappers.h"
      67             : #include "lib/global_contexts.h"
      68             : 
      69             : /* macros stolen from s4 spoolss server */
      70             : #define SPOOLSS_BUFFER_UNION(fn,info,level) \
      71             :         ((info)?ndr_size_##fn(info, level, 0):0)
      72             : 
      73             : #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
      74             :         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
      75             : 
      76             : #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
      77             :         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
      78             : 
      79             : #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
      80             : 
      81             : #undef DBGC_CLASS
      82             : #define DBGC_CLASS DBGC_RPC_SRV
      83             : 
      84             : #ifndef MAX_OPEN_PRINTER_EXS
      85             : #define MAX_OPEN_PRINTER_EXS 50
      86             : #endif
      87             : 
      88             : #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
      89             : #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
      90             : #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
      91             : #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
      92             : 
      93             : static struct printer_handle *printers_list;
      94             : 
      95             : struct printer_session_counter {
      96             :         struct printer_session_counter *next;
      97             :         struct printer_session_counter *prev;
      98             : 
      99             :         int snum;
     100             :         uint32_t counter;
     101             : };
     102             : 
     103             : static struct printer_session_counter *counter_list;
     104             : 
     105             : struct notify_back_channel {
     106             :         struct notify_back_channel *prev, *next;
     107             : 
     108             :         /* associated client */
     109             :         struct sockaddr_storage client_address;
     110             : 
     111             :         /* print notify back-channel pipe handle*/
     112             :         struct rpc_pipe_client *cli_pipe;
     113             :         struct cli_state *cli;
     114             :         uint32_t active_connections;
     115             : };
     116             : 
     117             : static struct notify_back_channel *back_channels;
     118             : 
     119             : /* Map generic permissions to printer object specific permissions */
     120             : 
     121             : const struct standard_mapping printer_std_mapping = {
     122             :         PRINTER_READ,
     123             :         PRINTER_WRITE,
     124             :         PRINTER_EXECUTE,
     125             :         PRINTER_ALL_ACCESS
     126             : };
     127             : 
     128             : /* Map generic permissions to print server object specific permissions */
     129             : 
     130             : const struct standard_mapping printserver_std_mapping = {
     131             :         SERVER_READ,
     132             :         SERVER_WRITE,
     133             :         SERVER_EXECUTE,
     134             :         SERVER_ALL_ACCESS
     135             : };
     136             : 
     137             : /* API table for Xcv Monitor functions */
     138             : 
     139             : struct xcv_api_table {
     140             :         const char *name;
     141             :         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
     142             : };
     143             : 
     144             : static void prune_printername_cache(void);
     145             : 
     146             : /********************************************************************
     147             :  * Canonicalize servername.
     148             :  ********************************************************************/
     149             : 
     150           2 : static const char *canon_servername(const char *servername)
     151             : {
     152           2 :         const char *pservername = servername;
     153             : 
     154           2 :         if (servername == NULL) {
     155           0 :                 return "";
     156             :         }
     157             : 
     158           7 :         while (*pservername == '\\') {
     159           4 :                 pservername++;
     160             :         }
     161           2 :         return pservername;
     162             : }
     163             : 
     164             : /* translate between internal status numbers and NT status numbers */
     165           0 : static int nt_printj_status(int v)
     166             : {
     167           0 :         switch (v) {
     168           0 :         case LPQ_QUEUED:
     169           0 :                 return 0;
     170           0 :         case LPQ_PAUSED:
     171           0 :                 return JOB_STATUS_PAUSED;
     172           0 :         case LPQ_SPOOLING:
     173           0 :                 return JOB_STATUS_SPOOLING;
     174           0 :         case LPQ_PRINTING:
     175           0 :                 return JOB_STATUS_PRINTING;
     176           0 :         case LPQ_ERROR:
     177           0 :                 return JOB_STATUS_ERROR;
     178           0 :         case LPQ_DELETING:
     179           0 :                 return JOB_STATUS_DELETING;
     180           0 :         case LPQ_OFFLINE:
     181           0 :                 return JOB_STATUS_OFFLINE;
     182           0 :         case LPQ_PAPEROUT:
     183           0 :                 return JOB_STATUS_PAPEROUT;
     184           0 :         case LPQ_PRINTED:
     185           0 :                 return JOB_STATUS_PRINTED;
     186           0 :         case LPQ_DELETED:
     187           0 :                 return JOB_STATUS_DELETED;
     188           0 :         case LPQ_BLOCKED:
     189           0 :                 return JOB_STATUS_BLOCKED_DEVQ;
     190           0 :         case LPQ_USER_INTERVENTION:
     191           0 :                 return JOB_STATUS_USER_INTERVENTION;
     192             :         }
     193           0 :         return 0;
     194             : }
     195             : 
     196           0 : static int nt_printq_status(int v)
     197             : {
     198           0 :         switch (v) {
     199           0 :         case LPQ_PAUSED:
     200           0 :                 return PRINTER_STATUS_PAUSED;
     201           0 :         case LPQ_QUEUED:
     202             :         case LPQ_SPOOLING:
     203             :         case LPQ_PRINTING:
     204           0 :                 return 0;
     205             :         }
     206           0 :         return 0;
     207             : }
     208             : 
     209             : /***************************************************************************
     210             :  Disconnect from the client
     211             : ****************************************************************************/
     212             : 
     213           2 : static void srv_spoolss_replycloseprinter(int snum,
     214             :                                           struct printer_handle *prn_hnd)
     215             : {
     216             :         WERROR result;
     217             :         NTSTATUS status;
     218             : 
     219             :         /*
     220             :          * Tell the specific printing tdb we no longer want messages for this printer
     221             :          * by deregistering our PID.
     222             :          */
     223             : 
     224           2 :         if (!print_notify_deregister_pid(snum)) {
     225           0 :                 DEBUG(0, ("Failed to register our pid for printer %s\n",
     226             :                           lp_const_servicename(snum)));
     227             :         }
     228             : 
     229             :         /* weird if the test succeeds !!! */
     230           3 :         if (prn_hnd->notify.cli_chan == NULL ||
     231           3 :             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
     232           3 :             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
     233           2 :             prn_hnd->notify.cli_chan->active_connections == 0) {
     234           0 :                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
     235           0 :                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
     236           0 :                 TALLOC_FREE(prn_hnd->notify.cli_chan);
     237           0 :                 return;
     238             :         }
     239             : 
     240           3 :         status = dcerpc_spoolss_ReplyClosePrinter(
     241           2 :                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
     242             :                                         talloc_tos(),
     243             :                                         &prn_hnd->notify.cli_hnd,
     244             :                                         &result);
     245           2 :         if (!NT_STATUS_IS_OK(status)) {
     246           0 :                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
     247             :                           nt_errstr(status)));
     248           0 :                 result = ntstatus_to_werror(status);
     249           2 :         } else if (!W_ERROR_IS_OK(result)) {
     250           0 :                 DEBUG(0, ("reply_close_printer failed [%s].\n",
     251             :                           win_errstr(result)));
     252             :         }
     253             : 
     254             :         /* if it's the last connection, deconnect the IPC$ share */
     255           2 :         if (prn_hnd->notify.cli_chan->active_connections == 1) {
     256             : 
     257           2 :                 cli_shutdown(prn_hnd->notify.cli_chan->cli);
     258           2 :                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
     259           2 :                 TALLOC_FREE(prn_hnd->notify.cli_chan);
     260             : 
     261           2 :                 if (prn_hnd->notify.msg_ctx != NULL) {
     262           2 :                         messaging_deregister(prn_hnd->notify.msg_ctx,
     263             :                                              MSG_PRINTER_NOTIFY2, NULL);
     264             :                 }
     265             :         }
     266             : 
     267           2 :         if (prn_hnd->notify.cli_chan) {
     268           0 :                 prn_hnd->notify.cli_chan->active_connections--;
     269           0 :                 prn_hnd->notify.cli_chan = NULL;
     270             :         }
     271             : }
     272             : 
     273             : /****************************************************************************
     274             :  Functions to free a printer entry datastruct.
     275             : ****************************************************************************/
     276             : 
     277           2 : static int printer_entry_destructor(struct printer_handle *Printer)
     278             : {
     279           3 :         if (Printer->notify.cli_chan != NULL &&
     280           2 :             Printer->notify.cli_chan->active_connections > 0) {
     281           2 :                 int snum = -1;
     282             : 
     283           2 :                 switch(Printer->printer_type) {
     284           2 :                 case SPLHND_SERVER:
     285           2 :                         srv_spoolss_replycloseprinter(snum, Printer);
     286           2 :                         break;
     287             : 
     288           0 :                 case SPLHND_PRINTER:
     289           0 :                         snum = print_queue_snum(Printer->sharename);
     290           0 :                         if (snum != -1) {
     291           0 :                                 srv_spoolss_replycloseprinter(snum, Printer);
     292             :                         }
     293           0 :                         break;
     294           0 :                 default:
     295           0 :                         break;
     296             :                 }
     297           0 :         }
     298             : 
     299           2 :         Printer->notify.flags=0;
     300           2 :         Printer->notify.options=0;
     301           2 :         Printer->notify.localmachine[0]='\0';
     302           2 :         Printer->notify.printerlocal=0;
     303           2 :         TALLOC_FREE(Printer->notify.option);
     304           2 :         TALLOC_FREE(Printer->devmode);
     305             : 
     306             :         /* Remove from the internal list. */
     307           2 :         DLIST_REMOVE(printers_list, Printer);
     308           2 :         return 0;
     309             : }
     310             : 
     311             : /****************************************************************************
     312             :   find printer index by handle
     313             : ****************************************************************************/
     314             : 
     315          16 : static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
     316             :                                                         struct policy_handle *hnd)
     317             : {
     318          16 :         struct printer_handle *find_printer = NULL;
     319             :         NTSTATUS status;
     320             : 
     321          16 :         find_printer = find_policy_by_hnd(p,
     322             :                                           hnd,
     323             :                                           DCESRV_HANDLE_ANY,
     324             :                                           struct printer_handle,
     325             :                                           &status);
     326          16 :         if (!NT_STATUS_IS_OK(status)) {
     327           0 :                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
     328           0 :                 return NULL;
     329             :         }
     330             : 
     331          16 :         return find_printer;
     332             : }
     333             : 
     334             : /****************************************************************************
     335             :  Close printer index by handle.
     336             : ****************************************************************************/
     337             : 
     338           2 : static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
     339             : {
     340           2 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     341             : 
     342           2 :         if (!Printer) {
     343           0 :                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
     344             :                         OUR_HANDLE(hnd)));
     345           0 :                 return false;
     346             :         }
     347             : 
     348           2 :         close_policy_hnd(p, hnd);
     349             : 
     350           2 :         return true;
     351             : }
     352             : 
     353             : /****************************************************************************
     354             :  Delete a printer given a handle.
     355             : ****************************************************************************/
     356             : 
     357           0 : static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
     358             :                                   const char *sharename,
     359             :                                   struct messaging_context *msg_ctx)
     360             : {
     361           0 :         const struct loadparm_substitution *lp_sub =
     362           0 :                 loadparm_s3_global_substitution();
     363           0 :         char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
     364           0 :         char *command = NULL;
     365             :         int ret;
     366           0 :         bool is_print_op = false;
     367             : 
     368             :         /* can't fail if we don't try */
     369             : 
     370           0 :         if ( !*cmd )
     371           0 :                 return WERR_OK;
     372             : 
     373           0 :         command = talloc_asprintf(ctx,
     374             :                         "%s \"%s\"",
     375             :                         cmd, sharename);
     376           0 :         if (!command) {
     377           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     378             :         }
     379           0 :         if ( token )
     380           0 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
     381             : 
     382           0 :         DEBUG(10,("Running [%s]\n", command));
     383             : 
     384             :         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
     385             : 
     386           0 :         if ( is_print_op )
     387           0 :                 become_root();
     388             : 
     389           0 :         ret = smbrun(command, NULL, NULL);
     390           0 :         if (ret == 0) {
     391             :                 /* Tell everyone we updated smb.conf. */
     392           0 :                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
     393             :         }
     394             : 
     395           0 :         if ( is_print_op )
     396           0 :                 unbecome_root();
     397             : 
     398             :         /********** END SePrintOperatorPrivlege BLOCK **********/
     399             : 
     400           0 :         DEBUGADD(10,("returned [%d]\n", ret));
     401             : 
     402           0 :         TALLOC_FREE(command);
     403             : 
     404           0 :         if (ret != 0)
     405           0 :                 return WERR_INVALID_HANDLE; /* What to return here? */
     406             : 
     407           0 :         return WERR_OK;
     408             : }
     409             : 
     410             : /****************************************************************************
     411             :  Delete a printer given a handle.
     412             : ****************************************************************************/
     413             : 
     414           0 : static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
     415             : {
     416           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
     417           0 :         struct auth_session_info *session_info =
     418           0 :                 dcesrv_call_session_info(dce_call);
     419           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     420             :         WERROR result;
     421             : 
     422           0 :         if (!Printer) {
     423           0 :                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
     424             :                         OUR_HANDLE(hnd)));
     425           0 :                 return WERR_INVALID_HANDLE;
     426             :         }
     427             : 
     428             :         /*
     429             :          * It turns out that Windows allows delete printer on a handle
     430             :          * opened by an admin user, then used on a pipe handle created
     431             :          * by an anonymous user..... but they're working on security.... riiight !
     432             :          * JRA.
     433             :          */
     434             : 
     435           0 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
     436           0 :                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
     437           0 :                 return WERR_ACCESS_DENIED;
     438             :         }
     439             : 
     440             :         /* this does not need a become root since the access check has been
     441             :            done on the handle already */
     442             : 
     443           0 :         result = winreg_delete_printer_key_internal(p->mem_ctx,
     444             :                                            get_session_info_system(),
     445             :                                            p->msg_ctx,
     446           0 :                                            Printer->sharename,
     447             :                                            "");
     448           0 :         if (!W_ERROR_IS_OK(result)) {
     449           0 :                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
     450           0 :                 return WERR_INVALID_HANDLE;
     451             :         }
     452             : 
     453           0 :         result = delete_printer_hook(p->mem_ctx, session_info->security_token,
     454           0 :                                      Printer->sharename, p->msg_ctx);
     455           0 :         if (!W_ERROR_IS_OK(result)) {
     456           0 :                 return result;
     457             :         }
     458           0 :         prune_printername_cache();
     459           0 :         return WERR_OK;
     460             : }
     461             : 
     462             : /****************************************************************************
     463             :  Return the snum of a printer corresponding to an handle.
     464             : ****************************************************************************/
     465             : 
     466           0 : static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
     467             :                              int *number, struct share_params **params)
     468             : {
     469           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
     470             : 
     471           0 :         if (!Printer) {
     472           0 :                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
     473             :                         OUR_HANDLE(hnd)));
     474           0 :                 return false;
     475             :         }
     476             : 
     477           0 :         switch (Printer->printer_type) {
     478           0 :                 case SPLHND_PRINTER:
     479           0 :                         DEBUG(4,("short name:%s\n", Printer->sharename));
     480           0 :                         *number = print_queue_snum(Printer->sharename);
     481           0 :                         return (*number != -1);
     482           0 :                 case SPLHND_SERVER:
     483           0 :                         return false;
     484           0 :                 default:
     485           0 :                         return false;
     486             :         }
     487             : }
     488             : 
     489             : /****************************************************************************
     490             :  Set printer handle type.
     491             :  Check if it's \\server or \\server\printer
     492             : ****************************************************************************/
     493             : 
     494           2 : static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
     495             : {
     496           2 :         DEBUG(3,("Setting printer type=%s\n", handlename));
     497             : 
     498             :         /* it's a print server */
     499           2 :         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
     500           2 :                 DEBUGADD(4,("Printer is a print server\n"));
     501           2 :                 Printer->printer_type = SPLHND_SERVER;
     502             :         }
     503             :         /* it's a printer (set_printer_hnd_name() will handle port monitors */
     504             :         else {
     505           0 :                 DEBUGADD(4,("Printer is a printer\n"));
     506           0 :                 Printer->printer_type = SPLHND_PRINTER;
     507             :         }
     508             : 
     509           2 :         return true;
     510             : }
     511             : 
     512           0 : static void prune_printername_cache_fn(const char *key, const char *value,
     513             :                                        time_t timeout, void *private_data)
     514             : {
     515           0 :         gencache_del(key);
     516           0 : }
     517             : 
     518           0 : static void prune_printername_cache(void)
     519             : {
     520           0 :         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
     521           0 : }
     522             : 
     523             : /****************************************************************************
     524             :  Set printer handle name..  Accept names like \\server, \\server\printer,
     525             :  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
     526             :  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
     527             :  XcvDataPort() interface.
     528             : ****************************************************************************/
     529             : 
     530           2 : static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
     531             :                                    const struct auth_session_info *session_info,
     532             :                                    struct messaging_context *msg_ctx,
     533             :                                    struct printer_handle *Printer,
     534             :                                    const char *handlename)
     535             : {
     536             :         int snum;
     537           2 :         int n_services=lp_numservices();
     538             :         char *aprinter;
     539             :         const char *printername;
     540           2 :         const char *servername = NULL;
     541             :         fstring sname;
     542           2 :         bool found = false;
     543           2 :         struct spoolss_PrinterInfo2 *info2 = NULL;
     544             :         WERROR result;
     545             :         char *p;
     546             : 
     547             :         /*
     548             :          * Hopefully nobody names his printers like this. Maybe \ or ,
     549             :          * are illegal in printer names even?
     550             :          */
     551           2 :         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
     552             :         char *cache_key;
     553             :         char *tmp;
     554             : 
     555           2 :         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
     556             :                 (unsigned long)strlen(handlename)));
     557             : 
     558           2 :         aprinter = discard_const_p(char, handlename);
     559           2 :         if ( *handlename == '\\' ) {
     560           2 :                 servername = canon_servername(handlename);
     561           2 :                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
     562           0 :                         *aprinter = '\0';
     563           0 :                         aprinter++;
     564             :                 }
     565           2 :                 if (!is_myname_or_ipaddr(servername)) {
     566           0 :                         return WERR_INVALID_PRINTER_NAME;
     567             :                 }
     568           2 :                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
     569           2 :                 if (Printer->servername == NULL) {
     570           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     571             :                 }
     572             :         }
     573             : 
     574           2 :         if (Printer->printer_type == SPLHND_SERVER) {
     575           2 :                 return WERR_OK;
     576             :         }
     577             : 
     578           0 :         if (Printer->printer_type != SPLHND_PRINTER) {
     579           0 :                 return WERR_INVALID_HANDLE;
     580             :         }
     581             : 
     582           0 :         DEBUGADD(5, ("searching for [%s]\n", aprinter));
     583             : 
     584           0 :         p = strchr(aprinter, ',');
     585           0 :         if (p != NULL) {
     586           0 :                 char *p2 = p;
     587           0 :                 p++;
     588           0 :                 if (*p == ' ') {
     589           0 :                         p++;
     590             :                 }
     591           0 :                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
     592           0 :                         *p2 = '\0';
     593           0 :                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
     594           0 :                         *p2 = '\0';
     595             :                 }
     596             :         }
     597             : 
     598           0 :         if (p) {
     599           0 :                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
     600             :         }
     601             : 
     602             :         /* check for the Port Monitor Interface */
     603           0 :         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
     604           0 :                 Printer->printer_type = SPLHND_PORTMON_TCP;
     605           0 :                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
     606           0 :                 found = true;
     607             :         }
     608           0 :         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
     609           0 :                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
     610           0 :                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
     611           0 :                 found = true;
     612             :         }
     613             : 
     614           0 :         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
     615           0 :         if (cache_key == NULL) {
     616           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     617             :         }
     618             : 
     619             :         /*
     620             :          * With hundreds of printers, the "for" loop iterating all
     621             :          * shares can be quite expensive, as it is done on every
     622             :          * OpenPrinter. The loop maps "aprinter" to "sname", the
     623             :          * result of which we cache in gencache.
     624             :          */
     625           0 :         if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
     626           0 :                 found = (strcmp(tmp, printer_not_found) != 0);
     627           0 :                 if (!found) {
     628           0 :                         DEBUG(4, ("Printer %s not found\n", aprinter));
     629           0 :                         TALLOC_FREE(tmp);
     630           0 :                         return WERR_INVALID_PRINTER_NAME;
     631             :                 }
     632           0 :                 fstrcpy(sname, tmp);
     633           0 :                 TALLOC_FREE(tmp);
     634             :         }
     635             : 
     636             :         /* Search all sharenames first as this is easier than pulling
     637             :            the printer_info_2 off of disk. Don't use find_service() since
     638             :            that calls out to map_username() */
     639             : 
     640             :         /* do another loop to look for printernames */
     641           0 :         for (snum = 0; !found && snum < n_services; snum++) {
     642           0 :                 const char *printer = lp_const_servicename(snum);
     643             : 
     644             :                 /* no point going on if this is not a printer */
     645           0 :                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
     646           0 :                         continue;
     647             :                 }
     648             : 
     649             :                 /* ignore [printers] share */
     650           0 :                 if (strequal(printer, "printers")) {
     651           0 :                         continue;
     652             :                 }
     653             : 
     654           0 :                 fstrcpy(sname, printer);
     655           0 :                 if (strequal(aprinter, printer)) {
     656           0 :                         found = true;
     657           0 :                         break;
     658             :                 }
     659             : 
     660             :                 /* no point looking up the printer object if
     661             :                    we aren't allowing printername != sharename */
     662           0 :                 if (lp_force_printername(snum)) {
     663           0 :                         continue;
     664             :                 }
     665             : 
     666           0 :                 result = winreg_get_printer_internal(mem_ctx,
     667             :                                             session_info,
     668             :                                             msg_ctx,
     669             :                                             sname,
     670             :                                             &info2);
     671           0 :                 if ( !W_ERROR_IS_OK(result) ) {
     672           0 :                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
     673             :                                  sname, win_errstr(result)));
     674           0 :                         continue;
     675             :                 }
     676             : 
     677           0 :                 printername = strrchr(info2->printername, '\\');
     678           0 :                 if (printername == NULL) {
     679           0 :                         printername = info2->printername;
     680             :                 } else {
     681           0 :                         printername++;
     682             :                 }
     683             : 
     684           0 :                 if (strequal(printername, aprinter)) {
     685           0 :                         found = true;
     686           0 :                         break;
     687             :                 }
     688             : 
     689           0 :                 DEBUGADD(10, ("printername: %s\n", printername));
     690             : 
     691           0 :                 TALLOC_FREE(info2);
     692             :         }
     693             : 
     694           0 :         if (!found) {
     695           0 :                 gencache_set(cache_key, printer_not_found,
     696           0 :                              time(NULL) + 300);
     697           0 :                 TALLOC_FREE(cache_key);
     698           0 :                 DEBUGADD(4,("Printer not found\n"));
     699           0 :                 return WERR_INVALID_PRINTER_NAME;
     700             :         }
     701             : 
     702           0 :         gencache_set(cache_key, sname, time(NULL) + 300);
     703           0 :         TALLOC_FREE(cache_key);
     704             : 
     705           0 :         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
     706             : 
     707           0 :         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
     708             : 
     709           0 :         return WERR_OK;
     710             : }
     711             : 
     712             : /****************************************************************************
     713             :  Find first available printer slot. creates a printer handle for you.
     714             :  ****************************************************************************/
     715             : 
     716           2 : static WERROR open_printer_hnd(struct pipes_struct *p,
     717             :                                struct policy_handle *hnd,
     718             :                                const char *name,
     719             :                                uint32_t access_granted)
     720             : {
     721             :         struct printer_handle *new_printer;
     722             :         WERROR result;
     723             : 
     724           2 :         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
     725             : 
     726           2 :         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
     727           2 :         if (new_printer == NULL) {
     728           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     729             :         }
     730           2 :         talloc_set_destructor(new_printer, printer_entry_destructor);
     731             : 
     732             :         /* This also steals the printer_handle on the policy_handle */
     733           2 :         if (!create_policy_hnd(p, hnd, 0, new_printer)) {
     734           0 :                 TALLOC_FREE(new_printer);
     735           0 :                 return WERR_INVALID_HANDLE;
     736             :         }
     737             : 
     738             :         /* Add to the internal list. */
     739           2 :         DLIST_ADD(printers_list, new_printer);
     740             : 
     741           2 :         new_printer->notify.option=NULL;
     742             : 
     743           2 :         if (!set_printer_hnd_printertype(new_printer, name)) {
     744           0 :                 close_printer_handle(p, hnd);
     745           0 :                 return WERR_INVALID_HANDLE;
     746             :         }
     747             : 
     748           2 :         result = set_printer_hnd_name(p->mem_ctx,
     749             :                                       get_session_info_system(),
     750             :                                       p->msg_ctx,
     751             :                                       new_printer, name);
     752           2 :         if (!W_ERROR_IS_OK(result)) {
     753           0 :                 close_printer_handle(p, hnd);
     754           0 :                 return result;
     755             :         }
     756             : 
     757           2 :         new_printer->access_granted = access_granted;
     758             : 
     759           2 :         DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
     760             : 
     761           2 :         return WERR_OK;
     762             : }
     763             : 
     764             : /***************************************************************************
     765             :  check to see if the client motify handle is monitoring the notification
     766             :  given by (notify_type, notify_field).
     767             :  **************************************************************************/
     768             : 
     769           0 : static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
     770             :                                       uint16_t notify_field)
     771             : {
     772           0 :         return true;
     773             : }
     774             : 
     775           0 : static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
     776             :                                 uint16_t notify_field)
     777             : {
     778           0 :         struct spoolss_NotifyOption *option = p->notify.option;
     779             :         uint32_t i, j;
     780             : 
     781             :         /*
     782             :          * Flags should always be zero when the change notify
     783             :          * is registered by the client's spooler.  A user Win32 app
     784             :          * might use the flags though instead of the NOTIFY_OPTION_INFO
     785             :          * --jerry
     786             :          */
     787             : 
     788           0 :         if (!option) {
     789           0 :                 return false;
     790             :         }
     791             : 
     792           0 :         if (p->notify.flags)
     793           0 :                 return is_monitoring_event_flags(
     794             :                         p->notify.flags, notify_type, notify_field);
     795             : 
     796           0 :         for (i = 0; i < option->count; i++) {
     797             : 
     798             :                 /* Check match for notify_type */
     799             : 
     800           0 :                 if (option->types[i].type != notify_type)
     801           0 :                         continue;
     802             : 
     803             :                 /* Check match for field */
     804             : 
     805           0 :                 for (j = 0; j < option->types[i].count; j++) {
     806           0 :                         if (option->types[i].fields[j].field == notify_field) {
     807           0 :                                 return true;
     808             :                         }
     809             :                 }
     810             :         }
     811             : 
     812           0 :         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
     813             :                    p->servername, p->sharename, notify_type, notify_field));
     814             : 
     815           0 :         return false;
     816             : }
     817             : 
     818             : #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
     819             :         _data->data.integer[0] = _integer; \
     820             :         _data->data.integer[1] = 0;
     821             : 
     822             : 
     823             : #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
     824             :         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
     825             :         if (!_data->data.string.string) {\
     826             :                 _data->data.string.size = 0; \
     827             :         } \
     828             :         _data->data.string.size = strlen_m_term(_p) * 2;
     829             : 
     830             : #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
     831             :         _data->data.devmode.devmode = _devmode;
     832             : 
     833           0 : static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
     834             :                                    struct tm *t,
     835             :                                    const char **pp,
     836             :                                    uint32_t *plen)
     837             : {
     838             :         struct spoolss_Time st;
     839           0 :         uint32_t len = 16;
     840             :         char *p;
     841             : 
     842           0 :         if (!init_systemtime(&st, t)) {
     843           0 :                 return;
     844             :         }
     845             : 
     846           0 :         p = talloc_array(mem_ctx, char, len);
     847           0 :         if (!p) {
     848           0 :                 return;
     849             :         }
     850             : 
     851             :         /*
     852             :          * Systemtime must be linearized as a set of UINT16's.
     853             :          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
     854             :          */
     855             : 
     856           0 :         SSVAL(p, 0, st.year);
     857           0 :         SSVAL(p, 2, st.month);
     858           0 :         SSVAL(p, 4, st.day_of_week);
     859           0 :         SSVAL(p, 6, st.day);
     860           0 :         SSVAL(p, 8, st.hour);
     861           0 :         SSVAL(p, 10, st.minute);
     862           0 :         SSVAL(p, 12, st.second);
     863           0 :         SSVAL(p, 14, st.millisecond);
     864             : 
     865           0 :         *pp = p;
     866           0 :         *plen = len;
     867             : }
     868             : 
     869             : /* Convert a notification message to a struct spoolss_Notify */
     870             : 
     871           0 : static void notify_one_value(struct spoolss_notify_msg *msg,
     872             :                              struct spoolss_Notify *data,
     873             :                              TALLOC_CTX *mem_ctx)
     874             : {
     875           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
     876           0 : }
     877             : 
     878           0 : static void notify_string(struct spoolss_notify_msg *msg,
     879             :                           struct spoolss_Notify *data,
     880             :                           TALLOC_CTX *mem_ctx)
     881             : {
     882             :         /* The length of the message includes the trailing \0 */
     883             : 
     884           0 :         data->data.string.size = msg->len * 2;
     885           0 :         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
     886           0 :         if (!data->data.string.string) {
     887           0 :                 data->data.string.size = 0;
     888           0 :                 return;
     889             :         }
     890             : }
     891             : 
     892           0 : static void notify_system_time(struct spoolss_notify_msg *msg,
     893             :                                struct spoolss_Notify *data,
     894             :                                TALLOC_CTX *mem_ctx)
     895             : {
     896           0 :         data->data.string.string = NULL;
     897           0 :         data->data.string.size = 0;
     898             : 
     899           0 :         if (msg->len != sizeof(time_t)) {
     900           0 :                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
     901             :                           msg->len));
     902           0 :                 return;
     903             :         }
     904             : 
     905           0 :         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
     906             :                                &data->data.string.string,
     907             :                                &data->data.string.size);
     908             : }
     909             : 
     910             : struct notify2_message_table {
     911             :         const char *name;
     912             :         void (*fn)(struct spoolss_notify_msg *msg,
     913             :                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
     914             : };
     915             : 
     916             : static struct notify2_message_table printer_notify_table[] = {
     917             :         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
     918             :         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
     919             :         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
     920             :         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
     921             :         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
     922             :         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
     923             :         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
     924             :         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
     925             :         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
     926             :         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
     927             :         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
     928             :         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
     929             :         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
     930             :         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
     931             :         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
     932             :         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
     933             :         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
     934             :         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
     935             :         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
     936             : };
     937             : 
     938             : static struct notify2_message_table job_notify_table[] = {
     939             :         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
     940             :         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
     941             :         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
     942             :         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
     943             :         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
     944             :         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
     945             :         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
     946             :         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
     947             :         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
     948             :         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
     949             :         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
     950             :         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
     951             :         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
     952             :         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
     953             :         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
     954             :         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
     955             :         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
     956             :         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
     957             :         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
     958             :         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
     959             :         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
     960             :         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
     961             :         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
     962             :         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
     963             : };
     964             : 
     965             : 
     966             : /***********************************************************************
     967             :  Allocate talloc context for container object
     968             :  **********************************************************************/
     969             : 
     970           0 : static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     971             : {
     972           0 :         if ( !ctr )
     973           0 :                 return;
     974             : 
     975           0 :         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
     976             : 
     977           0 :         return;
     978             : }
     979             : 
     980             : /***********************************************************************
     981             :  release all allocated memory and zero out structure
     982             :  **********************************************************************/
     983             : 
     984           0 : static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
     985             : {
     986           0 :         if ( !ctr )
     987           0 :                 return;
     988             : 
     989           0 :         if ( ctr->ctx )
     990           0 :                 talloc_destroy(ctr->ctx);
     991             : 
     992           0 :         ZERO_STRUCTP(ctr);
     993             : 
     994           0 :         return;
     995             : }
     996             : 
     997             : /***********************************************************************
     998             :  **********************************************************************/
     999             : 
    1000           0 : static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
    1001             : {
    1002           0 :         if ( !ctr )
    1003           0 :                 return NULL;
    1004             : 
    1005           0 :         return ctr->ctx;
    1006             : }
    1007             : 
    1008             : /***********************************************************************
    1009             :  **********************************************************************/
    1010             : 
    1011           0 : static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
    1012             : {
    1013           0 :         if ( !ctr || !ctr->msg_groups )
    1014           0 :                 return NULL;
    1015             : 
    1016           0 :         if ( idx >= ctr->num_groups )
    1017           0 :                 return NULL;
    1018             : 
    1019           0 :         return &ctr->msg_groups[idx];
    1020             : 
    1021             : }
    1022             : 
    1023             : /***********************************************************************
    1024             :  How many groups of change messages do we have ?
    1025             :  **********************************************************************/
    1026             : 
    1027           0 : static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
    1028             : {
    1029           0 :         if ( !ctr )
    1030           0 :                 return 0;
    1031             : 
    1032           0 :         return ctr->num_groups;
    1033             : }
    1034             : 
    1035             : /***********************************************************************
    1036             :  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
    1037             :  **********************************************************************/
    1038             : 
    1039           0 : static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
    1040             : {
    1041           0 :         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
    1042           0 :         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
    1043           0 :         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
    1044             :         uint32_t                        i, new_slot;
    1045             : 
    1046           0 :         if ( !ctr || !msg )
    1047           0 :                 return 0;
    1048             : 
    1049             :         /* loop over all groups looking for a matching printer name */
    1050             : 
    1051           0 :         for ( i=0; i<ctr->num_groups; i++ ) {
    1052           0 :                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
    1053           0 :                         break;
    1054             :         }
    1055             : 
    1056             :         /* add a new group? */
    1057             : 
    1058           0 :         if ( i == ctr->num_groups ) {
    1059           0 :                 ctr->num_groups++;
    1060             : 
    1061           0 :                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
    1062           0 :                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
    1063           0 :                         return 0;
    1064             :                 }
    1065           0 :                 ctr->msg_groups = groups;
    1066             : 
    1067             :                 /* clear the new entry and set the printer name */
    1068             : 
    1069           0 :                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
    1070           0 :                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
    1071             :         }
    1072             : 
    1073             :         /* add the change messages; 'i' is the correct index now regardless */
    1074             : 
    1075           0 :         msg_grp = &ctr->msg_groups[i];
    1076             : 
    1077           0 :         msg_grp->num_msgs++;
    1078             : 
    1079           0 :         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
    1080           0 :                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
    1081           0 :                 return 0;
    1082             :         }
    1083           0 :         msg_grp->msgs = msg_list;
    1084             : 
    1085           0 :         new_slot = msg_grp->num_msgs-1;
    1086           0 :         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
    1087             : 
    1088             :         /* need to allocate own copy of data */
    1089             : 
    1090           0 :         if ( msg->len != 0 )
    1091           0 :                 msg_grp->msgs[new_slot].notify.data = (char *)
    1092           0 :                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
    1093             : 
    1094           0 :         return ctr->num_groups;
    1095             : }
    1096             : 
    1097             : static void construct_info_data(struct spoolss_Notify *info_data,
    1098             :                                 enum spoolss_NotifyType type,
    1099             :                                 uint16_t field, int id);
    1100             : 
    1101             : /***********************************************************************
    1102             :  Send a change notifation message on all handles which have a call
    1103             :  back registered
    1104             :  **********************************************************************/
    1105             : 
    1106           0 : static int build_notify2_messages(TALLOC_CTX *mem_ctx,
    1107             :                                   struct printer_handle *prn_hnd,
    1108             :                                   SPOOLSS_NOTIFY_MSG *messages,
    1109             :                                   uint32_t num_msgs,
    1110             :                                   struct spoolss_Notify **_notifies,
    1111             :                                   size_t *_count)
    1112             : {
    1113             :         struct spoolss_Notify *notifies;
    1114             :         SPOOLSS_NOTIFY_MSG *msg;
    1115           0 :         size_t count = 0;
    1116             :         uint32_t id;
    1117             :         uint32_t i;
    1118             : 
    1119           0 :         notifies = talloc_zero_array(mem_ctx,
    1120             :                                      struct spoolss_Notify, num_msgs);
    1121           0 :         if (!notifies) {
    1122           0 :                 return ENOMEM;
    1123             :         }
    1124             : 
    1125           0 :         for (i = 0; i < num_msgs; i++) {
    1126             : 
    1127           0 :                 msg = &messages[i];
    1128             : 
    1129             :                 /* Are we monitoring this event? */
    1130             : 
    1131           0 :                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
    1132           0 :                         continue;
    1133             :                 }
    1134             : 
    1135           0 :                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
    1136             :                            "for printer [%s]\n",
    1137             :                            msg->type, msg->field, prn_hnd->sharename));
    1138             : 
    1139             :                 /*
    1140             :                  * if the is a printer notification handle and not a job
    1141             :                  * notification type, then set the id to 0.
    1142             :                  * Otherwise just use what was specified in the message.
    1143             :                  *
    1144             :                  * When registering change notification on a print server
    1145             :                  * handle we always need to send back the id (snum) matching
    1146             :                  * the printer for which the change took place.
    1147             :                  * For change notify registered on a printer handle,
    1148             :                  * this does not matter and the id should be 0.
    1149             :                  *
    1150             :                  * --jerry
    1151             :                  */
    1152             : 
    1153           0 :                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
    1154           0 :                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
    1155           0 :                         id = 0;
    1156             :                 } else {
    1157           0 :                         id = msg->id;
    1158             :                 }
    1159             : 
    1160             :                 /* Convert unix jobid to smb jobid */
    1161             : 
    1162           0 :                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
    1163           0 :                         id = sysjob_to_jobid(msg->id);
    1164             : 
    1165           0 :                         if (id == -1) {
    1166           0 :                                 DEBUG(3, ("no such unix jobid %d\n",
    1167             :                                           msg->id));
    1168           0 :                                 continue;
    1169             :                         }
    1170             :                 }
    1171             : 
    1172           0 :                 construct_info_data(&notifies[count],
    1173           0 :                                     msg->type, msg->field, id);
    1174             : 
    1175           0 :                 switch(msg->type) {
    1176           0 :                 case PRINTER_NOTIFY_TYPE:
    1177           0 :                         if (printer_notify_table[msg->field].fn) {
    1178           0 :                                 printer_notify_table[msg->field].fn(msg,
    1179           0 :                                                 &notifies[count], mem_ctx);
    1180             :                         }
    1181           0 :                         break;
    1182             : 
    1183           0 :                 case JOB_NOTIFY_TYPE:
    1184           0 :                         if (job_notify_table[msg->field].fn) {
    1185           0 :                                 job_notify_table[msg->field].fn(msg,
    1186           0 :                                                 &notifies[count], mem_ctx);
    1187             :                         }
    1188           0 :                         break;
    1189             : 
    1190           0 :                 default:
    1191           0 :                         DEBUG(5, ("Unknown notification type %d\n",
    1192             :                                   msg->type));
    1193           0 :                         continue;
    1194             :                 }
    1195             : 
    1196           0 :                 count++;
    1197             :         }
    1198             : 
    1199           0 :         *_notifies = notifies;
    1200           0 :         *_count = count;
    1201             : 
    1202           0 :         return 0;
    1203             : }
    1204             : 
    1205           0 : static int send_notify2_printer(TALLOC_CTX *mem_ctx,
    1206             :                                 struct printer_handle *prn_hnd,
    1207             :                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
    1208             : {
    1209             :         struct spoolss_Notify *notifies;
    1210           0 :         size_t count = 0;
    1211             :         union spoolss_ReplyPrinterInfo info;
    1212             :         struct spoolss_NotifyInfo info0;
    1213             :         uint32_t reply_result;
    1214             :         NTSTATUS status;
    1215             :         WERROR werr;
    1216             :         int ret;
    1217             : 
    1218             :         /* Is there notification on this handle? */
    1219           0 :         if (prn_hnd->notify.cli_chan == NULL ||
    1220           0 :             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
    1221           0 :             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
    1222           0 :             prn_hnd->notify.cli_chan->active_connections == 0) {
    1223           0 :                 return 0;
    1224             :         }
    1225             : 
    1226           0 :         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
    1227             :                    prn_hnd->servername, prn_hnd->sharename));
    1228             : 
    1229             :         /* For this printer? Print servers always receive notifications. */
    1230           0 :         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
    1231           0 :             (!strequal(msg_group->printername, prn_hnd->sharename))) {
    1232           0 :                 return 0;
    1233             :         }
    1234             : 
    1235           0 :         DEBUG(10,("Our printer\n"));
    1236             : 
    1237             :         /* build the array of change notifications */
    1238           0 :         ret = build_notify2_messages(mem_ctx, prn_hnd,
    1239             :                                      msg_group->msgs,
    1240             :                                      msg_group->num_msgs,
    1241             :                                      &notifies, &count);
    1242           0 :         if (ret) {
    1243           0 :                 return ret;
    1244             :         }
    1245             : 
    1246           0 :         info0.version   = 0x2;
    1247           0 :         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
    1248           0 :         info0.count     = count;
    1249           0 :         info0.notifies  = notifies;
    1250             : 
    1251           0 :         info.info0 = &info0;
    1252             : 
    1253           0 :         status = dcerpc_spoolss_RouterReplyPrinterEx(
    1254           0 :                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
    1255             :                                 mem_ctx,
    1256             :                                 &prn_hnd->notify.cli_hnd,
    1257             :                                 prn_hnd->notify.change, /* color */
    1258             :                                 prn_hnd->notify.flags,
    1259             :                                 &reply_result,
    1260             :                                 0, /* reply_type, must be 0 */
    1261             :                                 info, &werr);
    1262           0 :         if (!NT_STATUS_IS_OK(status)) {
    1263           0 :                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
    1264             :                           "failed: %s\n",
    1265             :                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
    1266             :                           nt_errstr(status)));
    1267           0 :                 werr = ntstatus_to_werror(status);
    1268           0 :         } else if (!W_ERROR_IS_OK(werr)) {
    1269           0 :                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
    1270             :                           "failed: %s\n",
    1271             :                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
    1272             :                           win_errstr(werr)));
    1273             :         }
    1274           0 :         switch (reply_result) {
    1275           0 :         case 0:
    1276           0 :                 break;
    1277           0 :         case PRINTER_NOTIFY_INFO_DISCARDED:
    1278             :         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
    1279             :         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
    1280           0 :                 break;
    1281           0 :         default:
    1282           0 :                 break;
    1283             :         }
    1284             : 
    1285           0 :         return 0;
    1286             : }
    1287             : 
    1288           0 : static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
    1289             : {
    1290             :         struct printer_handle    *p;
    1291           0 :         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
    1292           0 :         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
    1293             :         int ret;
    1294             : 
    1295           0 :         if ( !msg_group ) {
    1296           0 :                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
    1297           0 :                 return;
    1298             :         }
    1299             : 
    1300           0 :         if (!msg_group->msgs) {
    1301           0 :                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
    1302           0 :                 return;
    1303             :         }
    1304             : 
    1305           0 :         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
    1306             : 
    1307             :         /* loop over all printers */
    1308             : 
    1309           0 :         for (p = printers_list; p; p = p->next) {
    1310           0 :                 ret = send_notify2_printer(mem_ctx, p, msg_group);
    1311           0 :                 if (ret) {
    1312           0 :                         goto done;
    1313             :                 }
    1314             :         }
    1315             : 
    1316           0 : done:
    1317           0 :         DEBUG(8,("send_notify2_changes: Exit...\n"));
    1318           0 :         return;
    1319             : }
    1320             : 
    1321             : /***********************************************************************
    1322             :  **********************************************************************/
    1323             : 
    1324           0 : static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
    1325             : {
    1326             : 
    1327             :         uint32_t tv_sec, tv_usec;
    1328           0 :         size_t offset = 0;
    1329             : 
    1330             :         /* Unpack message */
    1331             : 
    1332           0 :         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
    1333           0 :                              msg->printer);
    1334             : 
    1335           0 :         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
    1336             :                                 &tv_sec, &tv_usec,
    1337             :                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
    1338             : 
    1339           0 :         if (msg->len == 0)
    1340           0 :                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
    1341             :                            &msg->notify.value[0], &msg->notify.value[1]);
    1342             :         else
    1343           0 :                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
    1344             :                            &msg->len, &msg->notify.data);
    1345             : 
    1346           0 :         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
    1347             :                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
    1348             : 
    1349           0 :         tv->tv_sec = tv_sec;
    1350           0 :         tv->tv_usec = tv_usec;
    1351             : 
    1352           0 :         if (msg->len == 0)
    1353           0 :                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
    1354             :                           msg->notify.value[1]));
    1355             :         else
    1356           0 :                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
    1357             : 
    1358           0 :         return true;
    1359             : }
    1360             : 
    1361             : /********************************************************************
    1362             :  Receive a notify2 message list
    1363             :  ********************************************************************/
    1364             : 
    1365           0 : static void receive_notify2_message_list(struct messaging_context *msg,
    1366             :                                          void *private_data,
    1367             :                                          uint32_t msg_type,
    1368             :                                          struct server_id server_id,
    1369             :                                          DATA_BLOB *data)
    1370             : {
    1371             :         size_t                  msg_count, i, num_groups;
    1372           0 :         char                    *buf = (char *)data->data;
    1373             :         char                    *msg_ptr;
    1374             :         size_t                  msg_len;
    1375             :         SPOOLSS_NOTIFY_MSG      notify;
    1376             :         SPOOLSS_NOTIFY_MSG_CTR  messages;
    1377             : 
    1378           0 :         if (data->length < 4) {
    1379           0 :                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
    1380           0 :                 return;
    1381             :         }
    1382             : 
    1383           0 :         msg_count = IVAL(buf, 0);
    1384           0 :         msg_ptr = buf + 4;
    1385             : 
    1386           0 :         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
    1387             : 
    1388           0 :         if (msg_count == 0) {
    1389           0 :                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
    1390           0 :                 return;
    1391             :         }
    1392             : 
    1393             :         /* initialize the container */
    1394             : 
    1395           0 :         ZERO_STRUCT( messages );
    1396           0 :         notify_msg_ctr_init( &messages );
    1397             : 
    1398             :         /*
    1399             :          * build message groups for each printer identified
    1400             :          * in a change_notify msg.  Remember that a PCN message
    1401             :          * includes the handle returned for the srv_spoolss_replyopenprinter()
    1402             :          * call.  Therefore messages are grouped according to printer handle.
    1403             :          */
    1404             : 
    1405           0 :         for ( i=0; i<msg_count; i++ ) {
    1406             :                 struct timeval msg_tv;
    1407             : 
    1408           0 :                 if (msg_ptr + 4 - buf > data->length) {
    1409           0 :                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
    1410           0 :                         return;
    1411             :                 }
    1412             : 
    1413           0 :                 msg_len = IVAL(msg_ptr,0);
    1414           0 :                 msg_ptr += 4;
    1415             : 
    1416           0 :                 if (msg_ptr + msg_len - buf > data->length) {
    1417           0 :                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
    1418           0 :                         return;
    1419             :                 }
    1420             : 
    1421             :                 /* unpack messages */
    1422             : 
    1423           0 :                 ZERO_STRUCT( notify );
    1424           0 :                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
    1425           0 :                 msg_ptr += msg_len;
    1426             : 
    1427             :                 /* add to correct list in container */
    1428             : 
    1429           0 :                 notify_msg_ctr_addmsg( &messages, &notify );
    1430             : 
    1431             :                 /* free memory that might have been allocated by notify2_unpack_msg() */
    1432             : 
    1433           0 :                 if ( notify.len != 0 )
    1434           0 :                         SAFE_FREE( notify.notify.data );
    1435             :         }
    1436             : 
    1437             :         /* process each group of messages */
    1438             : 
    1439           0 :         num_groups = notify_msg_ctr_numgroups( &messages );
    1440           0 :         for ( i=0; i<num_groups; i++ )
    1441           0 :                 send_notify2_changes( &messages, i );
    1442             : 
    1443             : 
    1444             :         /* cleanup */
    1445             : 
    1446           0 :         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
    1447             :                 (uint32_t)msg_count ));
    1448             : 
    1449           0 :         notify_msg_ctr_destroy( &messages );
    1450             : 
    1451           0 :         return;
    1452             : }
    1453             : 
    1454             : /********************************************************************
    1455             :  Send a message to ourself about new driver being installed
    1456             :  so we can upgrade the information for each printer bound to this
    1457             :  driver
    1458             :  ********************************************************************/
    1459             : 
    1460           0 : static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
    1461             :                                             struct messaging_context *msg_ctx)
    1462             : {
    1463           0 :         int len = strlen(drivername);
    1464             : 
    1465           0 :         if (!len)
    1466           0 :                 return false;
    1467             : 
    1468           0 :         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
    1469             :                 drivername));
    1470             : 
    1471           0 :         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
    1472             :                            MSG_PRINTER_DRVUPGRADE,
    1473           0 :                            (const uint8_t *)drivername, len+1);
    1474             : 
    1475           0 :         return true;
    1476             : }
    1477             : 
    1478           2 : void srv_spoolss_cleanup(void)
    1479             : {
    1480             :         struct printer_session_counter *session_counter;
    1481             : 
    1482           3 :         for (session_counter = counter_list;
    1483           1 :              session_counter != NULL;
    1484           0 :              session_counter = counter_list) {
    1485           0 :                 DLIST_REMOVE(counter_list, session_counter);
    1486           0 :                 TALLOC_FREE(session_counter);
    1487             :         }
    1488           2 : }
    1489             : 
    1490             : /**********************************************************************
    1491             :  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
    1492             :  over all printers, upgrading ones as necessary
    1493             :  This is now *ONLY* called inside the background lpq updater. JRA.
    1494             :  **********************************************************************/
    1495             : 
    1496           0 : void do_drv_upgrade_printer(struct messaging_context *msg,
    1497             :                             void *private_data,
    1498             :                             uint32_t msg_type,
    1499             :                             struct server_id server_id,
    1500             :                             DATA_BLOB *data)
    1501             : {
    1502             :         TALLOC_CTX *tmp_ctx;
    1503           0 :         const struct auth_session_info *session_info = get_session_info_system();
    1504             :         struct spoolss_PrinterInfo2 *pinfo2;
    1505             :         WERROR result;
    1506             :         const char *drivername;
    1507             :         int snum;
    1508           0 :         int n_services = lp_numservices();
    1509           0 :         struct dcerpc_binding_handle *b = NULL;
    1510             : 
    1511           0 :         tmp_ctx = talloc_new(NULL);
    1512           0 :         if (!tmp_ctx) return;
    1513             : 
    1514           0 :         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
    1515           0 :         if (!drivername) {
    1516           0 :                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
    1517           0 :                 goto done;
    1518             :         }
    1519             : 
    1520           0 :         DEBUG(10, ("do_drv_upgrade_printer: "
    1521             :                    "Got message for new driver [%s]\n", drivername));
    1522             : 
    1523             :         /* Iterate the printer list */
    1524             : 
    1525           0 :         for (snum = 0; snum < n_services; snum++) {
    1526           0 :                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
    1527           0 :                         continue;
    1528             :                 }
    1529             : 
    1530             :                 /* ignore [printers] share */
    1531           0 :                 if (strequal(lp_const_servicename(snum), "printers")) {
    1532           0 :                         continue;
    1533             :                 }
    1534             : 
    1535           0 :                 if (b == NULL) {
    1536           0 :                         result = winreg_printer_binding_handle(tmp_ctx,
    1537             :                                                                session_info,
    1538             :                                                                msg,
    1539             :                                                                &b);
    1540           0 :                         if (!W_ERROR_IS_OK(result)) {
    1541           0 :                                 break;
    1542             :                         }
    1543             :                 }
    1544             : 
    1545           0 :                 result = winreg_get_printer(tmp_ctx, b,
    1546             :                                             lp_const_servicename(snum),
    1547             :                                             &pinfo2);
    1548             : 
    1549           0 :                 if (!W_ERROR_IS_OK(result)) {
    1550           0 :                         continue;
    1551             :                 }
    1552             : 
    1553           0 :                 if (!pinfo2->drivername) {
    1554           0 :                         continue;
    1555             :                 }
    1556             : 
    1557           0 :                 if (strcmp(drivername, pinfo2->drivername) != 0) {
    1558           0 :                         continue;
    1559             :                 }
    1560             : 
    1561           0 :                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
    1562             : 
    1563             :                 /* all we care about currently is the change_id */
    1564           0 :                 result = winreg_printer_update_changeid(tmp_ctx, b,
    1565           0 :                                                         pinfo2->printername);
    1566             : 
    1567           0 :                 if (!W_ERROR_IS_OK(result)) {
    1568           0 :                         DEBUG(3, ("do_drv_upgrade_printer: "
    1569             :                                   "Failed to update changeid [%s]\n",
    1570             :                                   win_errstr(result)));
    1571             :                 }
    1572             :         }
    1573             : 
    1574             :         /* all done */
    1575           0 : done:
    1576           0 :         talloc_free(tmp_ctx);
    1577             : }
    1578             : 
    1579             : /********************************************************************
    1580             :  Update the cache for all printq's with a registered client
    1581             :  connection
    1582             :  ********************************************************************/
    1583             : 
    1584           0 : void update_monitored_printq_cache(struct messaging_context *msg_ctx)
    1585             : {
    1586           0 :         struct printer_handle *printer = printers_list;
    1587             :         int snum;
    1588             : 
    1589             :         /* loop through all printers and update the cache where
    1590             :            a client is connected */
    1591           0 :         while (printer) {
    1592           0 :                 if ((printer->printer_type == SPLHND_PRINTER) &&
    1593           0 :                     ((printer->notify.cli_chan != NULL) &&
    1594           0 :                      (printer->notify.cli_chan->active_connections > 0))) {
    1595           0 :                         snum = print_queue_snum(printer->sharename);
    1596           0 :                         print_queue_status(msg_ctx, snum, NULL, NULL);
    1597             :                 }
    1598             : 
    1599           0 :                 printer = printer->next;
    1600             :         }
    1601             : 
    1602           0 :         return;
    1603             : }
    1604             : 
    1605             : /****************************************************************
    1606             :  _spoolss_OpenPrinter
    1607             : ****************************************************************/
    1608             : 
    1609           2 : WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
    1610             :                             struct spoolss_OpenPrinter *r)
    1611             : {
    1612             :         struct spoolss_OpenPrinterEx e;
    1613             :         struct spoolss_UserLevel1 level1;
    1614             :         WERROR werr;
    1615             : 
    1616           2 :         ZERO_STRUCT(level1);
    1617             : 
    1618           2 :         e.in.printername        = r->in.printername;
    1619           2 :         e.in.datatype           = r->in.datatype;
    1620           2 :         e.in.devmode_ctr        = r->in.devmode_ctr;
    1621           2 :         e.in.access_mask        = r->in.access_mask;
    1622           2 :         e.in.userlevel_ctr.level                = 1;
    1623           2 :         e.in.userlevel_ctr.user_info.level1     = &level1;
    1624             : 
    1625           2 :         e.out.handle            = r->out.handle;
    1626             : 
    1627           2 :         werr = _spoolss_OpenPrinterEx(p, &e);
    1628             : 
    1629           2 :         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
    1630             :                 /* OpenPrinterEx returns this for a bad
    1631             :                  * printer name. We must return WERR_INVALID_PRINTER_NAME
    1632             :                  * instead.
    1633             :                  */
    1634           0 :                 werr = WERR_INVALID_PRINTER_NAME;
    1635             :         }
    1636             : 
    1637           2 :         return werr;
    1638             : }
    1639             : 
    1640           0 : static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
    1641             :                               struct spoolss_DeviceMode *orig,
    1642             :                               struct spoolss_DeviceMode **dest)
    1643             : {
    1644             :         struct spoolss_DeviceMode *dm;
    1645             : 
    1646           0 :         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
    1647           0 :         if (!dm) {
    1648           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1649             :         }
    1650             : 
    1651             :         /* copy all values, then duplicate strings and structs */
    1652           0 :         *dm = *orig;
    1653             : 
    1654           0 :         dm->devicename = talloc_strdup(dm, orig->devicename);
    1655           0 :         if (!dm->devicename) {
    1656           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1657             :         }
    1658           0 :         dm->formname = talloc_strdup(dm, orig->formname);
    1659           0 :         if (!dm->formname) {
    1660           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1661             :         }
    1662           0 :         if (orig->driverextra_data.data) {
    1663           0 :                 dm->driverextra_data.data =
    1664           0 :                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
    1665             :                                         orig->driverextra_data.length);
    1666           0 :                 if (!dm->driverextra_data.data) {
    1667           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1668             :                 }
    1669             :         }
    1670             : 
    1671           0 :         *dest = dm;
    1672           0 :         return WERR_OK;
    1673             : }
    1674             : 
    1675             : /****************************************************************
    1676             :  _spoolss_OpenPrinterEx
    1677             : ****************************************************************/
    1678             : 
    1679           2 : WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
    1680             :                               struct spoolss_OpenPrinterEx *r)
    1681             : {
    1682           2 :         struct dcesrv_call_state *dce_call = p->dce_call;
    1683           2 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    1684           1 :         const struct tsocket_address *remote_address =
    1685           1 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    1686           1 :         struct auth_session_info *session_info =
    1687           1 :                 dcesrv_call_session_info(dce_call);
    1688             :         int snum;
    1689             :         char *raddr;
    1690             :         char *rhost;
    1691           2 :         struct printer_handle *Printer=NULL;
    1692             :         WERROR result;
    1693             :         int rc;
    1694             : 
    1695           2 :         if (!r->in.printername) {
    1696           0 :                 return WERR_INVALID_PARAMETER;
    1697             :         }
    1698             : 
    1699           2 :         if (!*r->in.printername) {
    1700           0 :                 return WERR_INVALID_PARAMETER;
    1701             :         }
    1702             : 
    1703           2 :         if (r->in.userlevel_ctr.level > 3) {
    1704           0 :                 return WERR_INVALID_PARAMETER;
    1705             :         }
    1706           3 :         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
    1707           3 :             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
    1708           2 :             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
    1709           0 :                 return WERR_INVALID_PARAMETER;
    1710             :         }
    1711             : 
    1712             :         /*
    1713             :          * The printcap printer share inventory is updated on client
    1714             :          * enumeration. For clients that do not perform enumeration prior to
    1715             :          * access, such as cupssmbadd, we reinitialise the printer share
    1716             :          * inventory on open as well.
    1717             :          */
    1718           2 :         become_root();
    1719           2 :         delete_and_reload_printers();
    1720           2 :         unbecome_root();
    1721             : 
    1722             :         /* some sanity check because you can open a printer or a print server */
    1723             :         /* aka: \\server\printer or \\server */
    1724             : 
    1725           2 :         DEBUGADD(3,("checking name: %s\n", r->in.printername));
    1726             : 
    1727           2 :         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
    1728           2 :         if (!W_ERROR_IS_OK(result)) {
    1729           0 :                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
    1730             :                         "for printer %s\n", r->in.printername));
    1731           0 :                 ZERO_STRUCTP(r->out.handle);
    1732           0 :                 return result;
    1733             :         }
    1734             : 
    1735           2 :         Printer = find_printer_index_by_hnd(p, r->out.handle);
    1736           2 :         if ( !Printer ) {
    1737           0 :                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
    1738             :                         "handle we created for printer %s\n", r->in.printername));
    1739           0 :                 close_printer_handle(p, r->out.handle);
    1740           0 :                 ZERO_STRUCTP(r->out.handle);
    1741           0 :                 return WERR_INVALID_PARAMETER;
    1742             :         }
    1743             : 
    1744             :         /*
    1745             :          * First case: the user is opening the print server:
    1746             :          *
    1747             :          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
    1748             :          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
    1749             :          *
    1750             :          * Then both Win2k and WinNT clients try an OpenPrinterEx with
    1751             :          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
    1752             :          * or if the user is listed in the smb.conf printer admin parameter.
    1753             :          *
    1754             :          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
    1755             :          * client view printer folder, but does not show the MSAPW.
    1756             :          *
    1757             :          * Note: this test needs code to check access rights here too. Jeremy
    1758             :          * could you look at this?
    1759             :          *
    1760             :          * Second case: the user is opening a printer:
    1761             :          * NT doesn't let us connect to a printer if the connecting user
    1762             :          * doesn't have print permission.
    1763             :          *
    1764             :          * Third case: user is opening a Port Monitor
    1765             :          * access checks same as opening a handle to the print server.
    1766             :          */
    1767             : 
    1768           2 :         switch (Printer->printer_type )
    1769             :         {
    1770           2 :         case SPLHND_SERVER:
    1771             :         case SPLHND_PORTMON_TCP:
    1772             :         case SPLHND_PORTMON_LOCAL:
    1773             :                 /* Printserver handles use global struct... */
    1774             : 
    1775           2 :                 snum = -1;
    1776             : 
    1777           2 :                 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
    1778           2 :                         r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
    1779           2 :                         r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
    1780             :                 }
    1781             : 
    1782             :                 /* Map standard access rights to object specific access rights */
    1783             : 
    1784           2 :                 se_map_standard(&r->in.access_mask,
    1785             :                                 &printserver_std_mapping);
    1786             : 
    1787             :                 /* Deny any object specific bits that don't apply to print
    1788             :                    servers (i.e printer and job specific bits) */
    1789             : 
    1790           2 :                 r->in.access_mask &= SEC_MASK_SPECIFIC;
    1791             : 
    1792           2 :                 if (r->in.access_mask &
    1793             :                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
    1794           0 :                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
    1795           0 :                         close_printer_handle(p, r->out.handle);
    1796           0 :                         ZERO_STRUCTP(r->out.handle);
    1797           0 :                         return WERR_ACCESS_DENIED;
    1798             :                 }
    1799             : 
    1800             :                 /* Allow admin access */
    1801             : 
    1802           2 :                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
    1803             :                 {
    1804           2 :                         if (!lp_show_add_printer_wizard()) {
    1805           0 :                                 close_printer_handle(p, r->out.handle);
    1806           0 :                                 ZERO_STRUCTP(r->out.handle);
    1807           0 :                                 return WERR_ACCESS_DENIED;
    1808             :                         }
    1809             : 
    1810             :                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    1811             :                            and not a printer admin, then fail */
    1812             : 
    1813           3 :                         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    1814           2 :                             !security_token_has_privilege(
    1815           2 :                                     session_info->security_token,
    1816           0 :                                     SEC_PRIV_PRINT_OPERATOR) &&
    1817           0 :                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
    1818           0 :                                                 session_info->security_token)) {
    1819           0 :                                 close_printer_handle(p, r->out.handle);
    1820           0 :                                 ZERO_STRUCTP(r->out.handle);
    1821           0 :                                 DEBUG(3,("access DENIED as user is not root, "
    1822             :                                         "has no printoperator privilege and is "
    1823             :                                         "not a member of the printoperator builtin group\n"));
    1824           0 :                                 return WERR_ACCESS_DENIED;
    1825             :                         }
    1826             : 
    1827           2 :                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
    1828             :                 }
    1829             :                 else
    1830             :                 {
    1831           0 :                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
    1832             :                 }
    1833             : 
    1834           2 :                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
    1835             :                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
    1836             : 
    1837           2 :                 break;
    1838             : 
    1839           0 :         case SPLHND_PRINTER:
    1840             :                 /* NT doesn't let us connect to a printer if the connecting user
    1841             :                    doesn't have print permission.  */
    1842             : 
    1843           0 :                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
    1844           0 :                         close_printer_handle(p, r->out.handle);
    1845           0 :                         ZERO_STRUCTP(r->out.handle);
    1846           0 :                         return WERR_INVALID_HANDLE;
    1847             :                 }
    1848             : 
    1849           0 :                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
    1850           0 :                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
    1851             :                 }
    1852             : 
    1853           0 :                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
    1854             : 
    1855             :                 /* map an empty access mask to the minimum access mask */
    1856           0 :                 if (r->in.access_mask == 0x0)
    1857           0 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1858             : 
    1859             :                 /*
    1860             :                  * If we are not serving the printer driver for this printer,
    1861             :                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
    1862             :                  * will keep NT clients happy  --jerry
    1863             :                  */
    1864             : 
    1865           0 :                 if (lp_use_client_driver(snum)
    1866           0 :                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
    1867             :                 {
    1868           0 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1869             :                 }
    1870             : 
    1871             :                 /* check smb.conf parameters and the the sec_desc */
    1872           0 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    1873             :                                                          p->mem_ctx);
    1874           0 :                 if (raddr == NULL) {
    1875           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1876             :                 }
    1877             : 
    1878           0 :                 rc = get_remote_hostname(remote_address,
    1879             :                                          &rhost,
    1880             :                                          p->mem_ctx);
    1881           0 :                 if (rc < 0) {
    1882           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1883             :                 }
    1884           0 :                 if (strequal(rhost, "UNKNOWN")) {
    1885           0 :                         rhost = raddr;
    1886             :                 }
    1887             : 
    1888           0 :                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
    1889             :                                   rhost, raddr)) {
    1890           0 :                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
    1891           0 :                         ZERO_STRUCTP(r->out.handle);
    1892           0 :                         return WERR_ACCESS_DENIED;
    1893             :                 }
    1894             : 
    1895           0 :                 if (!user_ok_token(session_info->unix_info->unix_name,
    1896           0 :                                    session_info->info->domain_name,
    1897           0 :                                    session_info->security_token, snum) ||
    1898           0 :                     !W_ERROR_IS_OK(print_access_check(session_info,
    1899             :                                                       p->msg_ctx,
    1900             :                                                       snum,
    1901             :                                                       r->in.access_mask))) {
    1902           0 :                         DEBUG(3, ("access DENIED for printer open\n"));
    1903           0 :                         close_printer_handle(p, r->out.handle);
    1904           0 :                         ZERO_STRUCTP(r->out.handle);
    1905           0 :                         return WERR_ACCESS_DENIED;
    1906             :                 }
    1907             : 
    1908           0 :                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
    1909           0 :                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
    1910           0 :                         close_printer_handle(p, r->out.handle);
    1911           0 :                         ZERO_STRUCTP(r->out.handle);
    1912           0 :                         return WERR_ACCESS_DENIED;
    1913             :                 }
    1914             : 
    1915           0 :                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
    1916           0 :                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
    1917             :                 else
    1918           0 :                         r->in.access_mask = PRINTER_ACCESS_USE;
    1919             : 
    1920           0 :                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
    1921             :                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
    1922             : 
    1923           0 :                 winreg_create_printer_internal(p->mem_ctx,
    1924             :                                       get_session_info_system(),
    1925             :                                       p->msg_ctx,
    1926             :                                       lp_const_servicename(snum));
    1927             : 
    1928           0 :                 break;
    1929             : 
    1930           0 :         default:
    1931             :                 /* sanity check to prevent programmer error */
    1932           0 :                 ZERO_STRUCTP(r->out.handle);
    1933           0 :                 return WERR_INVALID_HANDLE;
    1934             :         }
    1935             : 
    1936           2 :         Printer->access_granted = r->in.access_mask;
    1937             : 
    1938             :         /*
    1939             :          * If the client sent a devmode in the OpenPrinter() call, then
    1940             :          * save it here in case we get a job submission on this handle
    1941             :          */
    1942             : 
    1943           2 :          if ((Printer->printer_type != SPLHND_SERVER)
    1944           0 :           && (r->in.devmode_ctr.devmode != NULL)) {
    1945           0 :                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
    1946             :                                 &Printer->devmode);
    1947             :          }
    1948             : 
    1949           2 :         return WERR_OK;
    1950             : }
    1951             : 
    1952             : /****************************************************************
    1953             :  _spoolss_ClosePrinter
    1954             : ****************************************************************/
    1955             : 
    1956           2 : WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
    1957             :                              struct spoolss_ClosePrinter *r)
    1958             : {
    1959           2 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    1960             : 
    1961           2 :         if (Printer && Printer->document_started) {
    1962             :                 struct spoolss_EndDocPrinter e;
    1963             : 
    1964           0 :                 e.in.handle = r->in.handle;
    1965             : 
    1966           0 :                 _spoolss_EndDocPrinter(p, &e);
    1967             :         }
    1968             : 
    1969           2 :         if (!close_printer_handle(p, r->in.handle))
    1970           0 :                 return WERR_INVALID_HANDLE;
    1971             : 
    1972             :         /* clear the returned printer handle.  Observed behavior
    1973             :            from Win2k server.  Don't think this really matters.
    1974             :            Previous code just copied the value of the closed
    1975             :            handle.    --jerry */
    1976             : 
    1977           2 :         ZERO_STRUCTP(r->out.handle);
    1978             : 
    1979           2 :         return WERR_OK;
    1980             : }
    1981             : 
    1982             : /****************************************************************
    1983             :  _spoolss_DeletePrinter
    1984             : ****************************************************************/
    1985             : 
    1986           0 : WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
    1987             :                               struct spoolss_DeletePrinter *r)
    1988             : {
    1989           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    1990             :         WERROR result;
    1991             :         int snum;
    1992             : 
    1993           0 :         if (Printer && Printer->document_started) {
    1994             :                 struct spoolss_EndDocPrinter e;
    1995             : 
    1996           0 :                 e.in.handle = r->in.handle;
    1997             : 
    1998           0 :                 _spoolss_EndDocPrinter(p, &e);
    1999             :         }
    2000             : 
    2001           0 :         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
    2002           0 :                 winreg_delete_printer_key_internal(p->mem_ctx,
    2003             :                                           get_session_info_system(),
    2004             :                                           p->msg_ctx,
    2005             :                                           lp_const_servicename(snum),
    2006             :                                           "");
    2007             :         }
    2008             : 
    2009           0 :         result = delete_printer_handle(p, r->in.handle);
    2010             : 
    2011           0 :         return result;
    2012             : }
    2013             : 
    2014             : /*******************************************************************
    2015             :  * static function to lookup the version id corresponding to an
    2016             :  * long architecture string
    2017             :  ******************************************************************/
    2018             : 
    2019             : static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
    2020             :                                    SPOOLSS_DRIVER_VERSION_NT35,
    2021             :                                    SPOOLSS_DRIVER_VERSION_NT4,
    2022             :                                    SPOOLSS_DRIVER_VERSION_200X,
    2023             :                                    -1};
    2024             : 
    2025           0 : static int get_version_id(const char *arch)
    2026             : {
    2027             :         int i;
    2028             : 
    2029           0 :         for (i=0; archi_table[i].long_archi != NULL; i++)
    2030             :         {
    2031           0 :                 if (strcmp(arch, archi_table[i].long_archi) == 0)
    2032           0 :                         return (archi_table[i].version);
    2033             :         }
    2034             : 
    2035           0 :         return -1;
    2036             : }
    2037             : 
    2038             : /****************************************************************
    2039             :  _spoolss_DeletePrinterDriver
    2040             : ****************************************************************/
    2041             : 
    2042           0 : WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
    2043             :                                     struct spoolss_DeletePrinterDriver *r)
    2044             : {
    2045             : 
    2046           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2047           0 :         struct auth_session_info *session_info =
    2048           0 :                 dcesrv_call_session_info(dce_call);
    2049           0 :         struct spoolss_DriverInfo8 *info = NULL;
    2050             :         int                             version;
    2051             :         WERROR                          status;
    2052             :         struct dcerpc_binding_handle *b;
    2053           0 :         TALLOC_CTX *tmp_ctx = NULL;
    2054             :         int i;
    2055             :         bool found;
    2056             : 
    2057             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    2058             :            and not a printer admin, then fail */
    2059             : 
    2060           0 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    2061           0 :             !security_token_has_privilege(session_info->security_token,
    2062             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    2063           0 :                 return WERR_ACCESS_DENIED;
    2064             :         }
    2065             : 
    2066           0 :         if (r->in.architecture == NULL || r->in.driver == NULL) {
    2067           0 :                 return WERR_INVALID_ENVIRONMENT;
    2068             :         }
    2069             : 
    2070             :         /* check that we have a valid driver name first */
    2071             : 
    2072           0 :         if ((version = get_version_id(r->in.architecture)) == -1) {
    2073           0 :                 return WERR_INVALID_ENVIRONMENT;
    2074             :         }
    2075             : 
    2076           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    2077           0 :         if (!tmp_ctx) {
    2078           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2079             :         }
    2080             : 
    2081           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    2082             :                                                get_session_info_system(),
    2083             :                                                p->msg_ctx,
    2084             :                                                &b);
    2085           0 :         if (!W_ERROR_IS_OK(status)) {
    2086           0 :                 goto done;
    2087             :         }
    2088             : 
    2089           0 :         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
    2090           0 :                 status = winreg_get_driver(tmp_ctx, b,
    2091             :                                            r->in.architecture, r->in.driver,
    2092           0 :                                            drv_cversion[i], &info);
    2093           0 :                 if (!W_ERROR_IS_OK(status)) {
    2094           0 :                         DEBUG(5, ("skipping del of driver with version %d\n",
    2095             :                                   drv_cversion[i]));
    2096           0 :                         continue;
    2097             :                 }
    2098           0 :                 found = true;
    2099             : 
    2100           0 :                 if (printer_driver_in_use(tmp_ctx, b, info)) {
    2101           0 :                         status = WERR_PRINTER_DRIVER_IN_USE;
    2102           0 :                         goto done;
    2103             :                 }
    2104             : 
    2105           0 :                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
    2106           0 :                 if (!W_ERROR_IS_OK(status)) {
    2107           0 :                         DEBUG(0, ("failed del of driver with version %d\n",
    2108             :                                   drv_cversion[i]));
    2109           0 :                         goto done;
    2110             :                 }
    2111             :         }
    2112           0 :         if (found == false) {
    2113           0 :                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
    2114           0 :                 status = WERR_UNKNOWN_PRINTER_DRIVER;
    2115             :         } else {
    2116           0 :                 status = WERR_OK;
    2117             :         }
    2118             : 
    2119           0 : done:
    2120           0 :         talloc_free(tmp_ctx);
    2121             : 
    2122           0 :         return status;
    2123             : }
    2124             : 
    2125           0 : static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
    2126             :                                   struct pipes_struct *p,
    2127             :                                   struct spoolss_DeletePrinterDriverEx *r,
    2128             :                                   struct dcerpc_binding_handle *b,
    2129             :                                   struct spoolss_DriverInfo8 *info)
    2130             : {
    2131           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2132           0 :         struct auth_session_info *session_info =
    2133           0 :                 dcesrv_call_session_info(dce_call);
    2134             :         WERROR status;
    2135             :         bool delete_files;
    2136             : 
    2137           0 :         if (printer_driver_in_use(mem_ctx, b, info)) {
    2138           0 :                 status = WERR_PRINTER_DRIVER_IN_USE;
    2139           0 :                 goto done;
    2140             :         }
    2141             : 
    2142             :         /*
    2143             :          * we have a couple of cases to consider.
    2144             :          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
    2145             :          *     then the delete should fail if **any** files overlap with
    2146             :          *     other drivers
    2147             :          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
    2148             :          *     non-overlapping files
    2149             :          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
    2150             :          *     are set, then do not delete any files
    2151             :          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
    2152             :          */
    2153             : 
    2154           0 :         delete_files = r->in.delete_flags
    2155           0 :                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
    2156             : 
    2157             : 
    2158           0 :         if (delete_files) {
    2159           0 :                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
    2160           0 :                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
    2161           0 :                         status = WERR_PRINTER_DRIVER_IN_USE;
    2162           0 :                         goto done;
    2163             :                 }
    2164             :                 /*
    2165             :                  * printer_driver_files_in_use() has trimmed overlapping files
    2166             :                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
    2167             :                  */
    2168             :         }
    2169             : 
    2170             : 
    2171           0 :         status = winreg_del_driver(mem_ctx, b, info, info->version);
    2172           0 :         if (!W_ERROR_IS_OK(status)) {
    2173           0 :                 goto done;
    2174             :         }
    2175             : 
    2176             :         /*
    2177             :          * now delete any associated files if delete_files is
    2178             :          * true. Even if this part failes, we return succes
    2179             :          * because the driver doesn not exist any more
    2180             :          */
    2181           0 :         if (delete_files) {
    2182           0 :                 delete_driver_files(session_info, info);
    2183             :         }
    2184             : 
    2185           0 : done:
    2186           0 :         return status;
    2187             : }
    2188             : 
    2189             : /****************************************************************
    2190             :  _spoolss_DeletePrinterDriverEx
    2191             : ****************************************************************/
    2192             : 
    2193           0 : WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
    2194             :                                       struct spoolss_DeletePrinterDriverEx *r)
    2195             : {
    2196           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2197           0 :         struct auth_session_info *session_info =
    2198           0 :                 dcesrv_call_session_info(dce_call);
    2199           0 :         struct spoolss_DriverInfo8 *info = NULL;
    2200             :         WERROR                          status;
    2201             :         struct dcerpc_binding_handle *b;
    2202           0 :         TALLOC_CTX *tmp_ctx = NULL;
    2203             :         int i;
    2204             :         bool found;
    2205             : 
    2206             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    2207             :            and not a printer admin, then fail */
    2208             : 
    2209           0 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    2210           0 :             !security_token_has_privilege(session_info->security_token,
    2211             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    2212           0 :                 return WERR_ACCESS_DENIED;
    2213             :         }
    2214             : 
    2215           0 :         if (r->in.architecture == NULL || r->in.driver == NULL) {
    2216           0 :                 return WERR_INVALID_ENVIRONMENT;
    2217             :         }
    2218             : 
    2219             :         /* check that we have a valid driver name first */
    2220           0 :         if (get_version_id(r->in.architecture) == -1) {
    2221             :                 /* this is what NT returns */
    2222           0 :                 return WERR_INVALID_ENVIRONMENT;
    2223             :         }
    2224             : 
    2225           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    2226           0 :         if (!tmp_ctx) {
    2227           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2228             :         }
    2229             : 
    2230           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    2231             :                                                get_session_info_system(),
    2232             :                                                p->msg_ctx,
    2233             :                                                &b);
    2234           0 :         if (!W_ERROR_IS_OK(status)) {
    2235           0 :                 goto done;
    2236             :         }
    2237             : 
    2238           0 :         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
    2239           0 :                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
    2240           0 :                  && (drv_cversion[i] != r->in.version)) {
    2241           0 :                         continue;
    2242             :                 }
    2243             : 
    2244             :                 /* check if a driver with this version exists before delete */
    2245           0 :                 status = winreg_get_driver(tmp_ctx, b,
    2246             :                                            r->in.architecture, r->in.driver,
    2247           0 :                                            drv_cversion[i], &info);
    2248           0 :                 if (!W_ERROR_IS_OK(status)) {
    2249           0 :                         DEBUG(5, ("skipping del of driver with version %d\n",
    2250             :                                   drv_cversion[i]));
    2251           0 :                         continue;
    2252             :                 }
    2253           0 :                 found = true;
    2254             : 
    2255           0 :                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
    2256           0 :                 if (!W_ERROR_IS_OK(status)) {
    2257           0 :                         DEBUG(0, ("failed to delete driver with version %d\n",
    2258             :                                   drv_cversion[i]));
    2259           0 :                         goto done;
    2260             :                 }
    2261             :         }
    2262           0 :         if (found == false) {
    2263           0 :                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
    2264           0 :                 status = WERR_UNKNOWN_PRINTER_DRIVER;
    2265             :         } else {
    2266           0 :                 status = WERR_OK;
    2267             :         }
    2268             : 
    2269           0 : done:
    2270           0 :         talloc_free(tmp_ctx);
    2271           0 :         return status;
    2272             : }
    2273             : 
    2274             : 
    2275             : /********************************************************************
    2276             :  GetPrinterData on a printer server Handle.
    2277             : ********************************************************************/
    2278             : 
    2279           0 : static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
    2280             :                                             const char *value,
    2281             :                                             enum winreg_Type *type,
    2282             :                                             union spoolss_PrinterData *data)
    2283             : {
    2284           0 :         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
    2285             : 
    2286           0 :         if (!strcasecmp_m(value, "W3SvcInstalled")) {
    2287           0 :                 *type = REG_DWORD;
    2288           0 :                 SIVAL(&data->value, 0, 0x00);
    2289           0 :                 return WERR_OK;
    2290             :         }
    2291             : 
    2292           0 :         if (!strcasecmp_m(value, "BeepEnabled")) {
    2293           0 :                 *type = REG_DWORD;
    2294           0 :                 SIVAL(&data->value, 0, 0x00);
    2295           0 :                 return WERR_OK;
    2296             :         }
    2297             : 
    2298           0 :         if (!strcasecmp_m(value, "EventLog")) {
    2299           0 :                 *type = REG_DWORD;
    2300             :                 /* formally was 0x1b */
    2301           0 :                 SIVAL(&data->value, 0, 0x00);
    2302           0 :                 return WERR_OK;
    2303             :         }
    2304             : 
    2305           0 :         if (!strcasecmp_m(value, "NetPopup")) {
    2306           0 :                 *type = REG_DWORD;
    2307           0 :                 SIVAL(&data->value, 0, 0x00);
    2308           0 :                 return WERR_OK;
    2309             :         }
    2310             : 
    2311           0 :         if (!strcasecmp_m(value, "MajorVersion")) {
    2312           0 :                 *type = REG_DWORD;
    2313             : 
    2314             :                 /* Windows NT 4.0 seems to not allow uploading of drivers
    2315             :                    to a server that reports 0x3 as the MajorVersion.
    2316             :                    need to investigate more how Win2k gets around this .
    2317             :                    -- jerry */
    2318             : 
    2319           0 :                 if (RA_WINNT == get_remote_arch()) {
    2320           0 :                         SIVAL(&data->value, 0, 0x02);
    2321             :                 } else {
    2322           0 :                         SIVAL(&data->value, 0, 0x03);
    2323             :                 }
    2324             : 
    2325           0 :                 return WERR_OK;
    2326             :         }
    2327             : 
    2328           0 :         if (!strcasecmp_m(value, "MinorVersion")) {
    2329           0 :                 *type = REG_DWORD;
    2330           0 :                 SIVAL(&data->value, 0, 0x00);
    2331           0 :                 return WERR_OK;
    2332             :         }
    2333             : 
    2334             :         /* REG_BINARY
    2335             :          *  uint32_t size        = 0x114
    2336             :          *  uint32_t major       = 5
    2337             :          *  uint32_t minor       = [0|1]
    2338             :          *  uint32_t build       = [2195|2600]
    2339             :          *  extra unicode string = e.g. "Service Pack 3"
    2340             :          */
    2341           0 :         if (!strcasecmp_m(value, "OSVersion")) {
    2342             :                 DATA_BLOB blob;
    2343             :                 enum ndr_err_code ndr_err;
    2344             :                 struct spoolss_OSVersion os;
    2345             : 
    2346             :                 /*
    2347             :                  * Set the default OSVersion to:
    2348             :                  *
    2349             :                  *     Windows Server 2003R2 SP2 (5.2.3790)
    2350             :                  *
    2351             :                  * used to be Windows 2000 (5.0.2195)
    2352             :                  */
    2353           0 :                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2354             :                                                       "spoolss", "os_major",
    2355             :                                                       GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
    2356           0 :                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2357             :                                                       "spoolss", "os_minor",
    2358             :                                                       GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
    2359           0 :                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
    2360             :                                                       "spoolss", "os_build",
    2361             :                                                       GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
    2362           0 :                 os.extra_string         = ""; /* leave extra string empty */
    2363             : 
    2364           0 :                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
    2365             :                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
    2366           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    2367           0 :                         return WERR_GEN_FAILURE;
    2368             :                 }
    2369             : 
    2370           0 :                 if (DEBUGLEVEL >= 10) {
    2371           0 :                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
    2372             :                 }
    2373             : 
    2374           0 :                 *type = REG_BINARY;
    2375           0 :                 data->binary = blob;
    2376             : 
    2377           0 :                 return WERR_OK;
    2378             :         }
    2379             : 
    2380             : 
    2381           0 :         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
    2382           0 :                 *type = REG_SZ;
    2383             : 
    2384           0 :                 data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
    2385           0 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2386             : 
    2387           0 :                 return WERR_OK;
    2388             :         }
    2389             : 
    2390           0 :         if (!strcasecmp_m(value, "Architecture")) {
    2391           0 :                 *type = REG_SZ;
    2392           0 :                 data->string = talloc_strdup(mem_ctx,
    2393             :                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
    2394           0 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2395             : 
    2396           0 :                 return WERR_OK;
    2397             :         }
    2398             : 
    2399           0 :         if (!strcasecmp_m(value, "DsPresent")) {
    2400           0 :                 *type = REG_DWORD;
    2401             : 
    2402             :                 /* only show the publish check box if we are a
    2403             :                    member of a AD domain */
    2404             : 
    2405           0 :                 if (lp_security() == SEC_ADS) {
    2406           0 :                         SIVAL(&data->value, 0, 0x01);
    2407             :                 } else {
    2408           0 :                         SIVAL(&data->value, 0, 0x00);
    2409             :                 }
    2410           0 :                 return WERR_OK;
    2411             :         }
    2412             : 
    2413           0 :         if (!strcasecmp_m(value, "DNSMachineName")) {
    2414           0 :                 const char *hostname = get_mydnsfullname();
    2415             : 
    2416           0 :                 if (!hostname) {
    2417           0 :                         return WERR_FILE_NOT_FOUND;
    2418             :                 }
    2419             : 
    2420           0 :                 *type = REG_SZ;
    2421           0 :                 data->string = talloc_strdup(mem_ctx, hostname);
    2422           0 :                 W_ERROR_HAVE_NO_MEMORY(data->string);
    2423             : 
    2424           0 :                 return WERR_OK;
    2425             :         }
    2426             : 
    2427           0 :         *type = REG_NONE;
    2428             : 
    2429           0 :         return WERR_INVALID_PARAMETER;
    2430             : }
    2431             : 
    2432             : /****************************************************************
    2433             :  _spoolss_GetPrinterData
    2434             : ****************************************************************/
    2435             : 
    2436           0 : WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
    2437             :                                struct spoolss_GetPrinterData *r)
    2438             : {
    2439             :         struct spoolss_GetPrinterDataEx r2;
    2440             : 
    2441           0 :         r2.in.handle            = r->in.handle;
    2442           0 :         r2.in.key_name          = "PrinterDriverData";
    2443           0 :         r2.in.value_name        = r->in.value_name;
    2444           0 :         r2.in.offered           = r->in.offered;
    2445           0 :         r2.out.type             = r->out.type;
    2446           0 :         r2.out.data             = r->out.data;
    2447           0 :         r2.out.needed           = r->out.needed;
    2448             : 
    2449           0 :         return _spoolss_GetPrinterDataEx(p, &r2);
    2450             : }
    2451             : 
    2452             : /*********************************************************
    2453             :  Connect to the client machine.
    2454             : **********************************************************/
    2455             : 
    2456           2 : static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
    2457             :                                       struct sockaddr_storage *client_ss, const char *remote_machine)
    2458             : {
    2459             :         NTSTATUS ret;
    2460             :         struct sockaddr_storage rm_addr;
    2461             :         char addr[INET6_ADDRSTRLEN];
    2462           2 :         struct cli_credentials *anon_creds = NULL;
    2463             : 
    2464           2 :         if ( is_zero_addr(client_ss) ) {
    2465           0 :                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
    2466             :                         remote_machine));
    2467           0 :                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
    2468           0 :                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
    2469           0 :                         return false;
    2470             :                 }
    2471           0 :                 print_sockaddr(addr, sizeof(addr), &rm_addr);
    2472             :         } else {
    2473           2 :                 rm_addr = *client_ss;
    2474           2 :                 print_sockaddr(addr, sizeof(addr), &rm_addr);
    2475           2 :                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
    2476             :                         addr));
    2477             :         }
    2478             : 
    2479           2 :         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
    2480           0 :                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
    2481             :                         addr));
    2482           0 :                 return false;
    2483             :         }
    2484             : 
    2485           2 :         anon_creds = cli_credentials_init_anon(NULL);
    2486           2 :         if (anon_creds == NULL) {
    2487           0 :                 DBG_ERR("cli_credentials_init_anon() failed\n");
    2488           0 :                 return false;
    2489             :         }
    2490             : 
    2491             :         /* setup the connection */
    2492           2 :         ret = cli_full_connection_creds( pp_cli, lp_netbios_name(), remote_machine,
    2493             :                 &rm_addr, 0, "IPC$", "IPC",
    2494             :                 anon_creds,
    2495             :                 CLI_FULL_CONNECTION_IPC);
    2496           2 :         TALLOC_FREE(anon_creds);
    2497           2 :         if ( !NT_STATUS_IS_OK( ret ) ) {
    2498           0 :                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
    2499             :                         remote_machine ));
    2500           0 :                 return false;
    2501             :         }
    2502             : 
    2503           2 :         if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
    2504           0 :                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
    2505           0 :                 cli_shutdown(*pp_cli);
    2506           0 :                 return false;
    2507             :         }
    2508             : 
    2509             :         /*
    2510             :          * Ok - we have an anonymous connection to the IPC$ share.
    2511             :          * Now start the NT Domain stuff :-).
    2512             :          */
    2513             : 
    2514           2 :         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
    2515           2 :         if (!NT_STATUS_IS_OK(ret)) {
    2516           0 :                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
    2517             :                         remote_machine, nt_errstr(ret)));
    2518           0 :                 cli_shutdown(*pp_cli);
    2519           0 :                 return false;
    2520             :         }
    2521             : 
    2522           2 :         return true;
    2523             : }
    2524             : 
    2525             : /***************************************************************************
    2526             :  Connect to the client.
    2527             : ****************************************************************************/
    2528             : 
    2529           2 : static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
    2530             :                                         uint32_t localprinter,
    2531             :                                         enum winreg_Type type,
    2532             :                                         struct policy_handle *handle,
    2533             :                                         struct notify_back_channel **_chan,
    2534             :                                         struct sockaddr_storage *client_ss,
    2535             :                                         struct messaging_context *msg_ctx)
    2536             : {
    2537             :         WERROR result;
    2538             :         NTSTATUS status;
    2539             :         struct notify_back_channel *chan;
    2540             : 
    2541           2 :         for (chan = back_channels; chan; chan = chan->next) {
    2542           0 :                 if (memcmp(&chan->client_address, client_ss,
    2543             :                            sizeof(struct sockaddr_storage)) == 0) {
    2544           0 :                         break;
    2545             :                 }
    2546             :         }
    2547             : 
    2548             :         /*
    2549             :          * If it's the first connection, contact the client
    2550             :          * and connect to the IPC$ share anonymously
    2551             :          */
    2552           2 :         if (!chan) {
    2553             :                 fstring unix_printer;
    2554             : 
    2555             :                 /* the +2 is to strip the leading 2 backslashs */
    2556           2 :                 fstrcpy(unix_printer, printer + 2);
    2557             : 
    2558           2 :                 chan = talloc_zero(NULL, struct notify_back_channel);
    2559           2 :                 if (!chan) {
    2560           0 :                         return false;
    2561             :                 }
    2562           2 :                 chan->client_address = *client_ss;
    2563             : 
    2564           2 :                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
    2565           0 :                         TALLOC_FREE(chan);
    2566           0 :                         return false;
    2567             :                 }
    2568             : 
    2569           2 :                 DLIST_ADD(back_channels, chan);
    2570             : 
    2571           2 :                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
    2572             :                                    receive_notify2_message_list);
    2573             :         }
    2574             : 
    2575           3 :         if (chan->cli_pipe == NULL ||
    2576           2 :             chan->cli_pipe->binding_handle == NULL) {
    2577           0 :                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
    2578             :                         "NULL %s for printer %s\n",
    2579             :                         chan->cli_pipe == NULL ?
    2580             :                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
    2581             :                         printer));
    2582           0 :                 return false;
    2583             :         }
    2584             : 
    2585             :         /*
    2586             :          * Tell the specific printing tdb we want messages for this printer
    2587             :          * by registering our PID.
    2588             :          */
    2589             : 
    2590           2 :         if (!print_notify_register_pid(snum)) {
    2591           0 :                 DEBUG(0, ("Failed to register our pid for printer %s\n",
    2592             :                           printer));
    2593             :         }
    2594             : 
    2595           2 :         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
    2596             :                                                  talloc_tos(),
    2597             :                                                  printer,
    2598             :                                                  localprinter,
    2599             :                                                  type,
    2600             :                                                  0,
    2601             :                                                  NULL,
    2602             :                                                  handle,
    2603             :                                                  &result);
    2604           2 :         if (!NT_STATUS_IS_OK(status)) {
    2605           0 :                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
    2606           0 :                 result = ntstatus_to_werror(status);
    2607           2 :         } else if (!W_ERROR_IS_OK(result)) {
    2608           0 :                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
    2609             :         }
    2610             : 
    2611           2 :         chan->active_connections++;
    2612           2 :         *_chan = chan;
    2613             : 
    2614           2 :         return (W_ERROR_IS_OK(result));
    2615             : }
    2616             : 
    2617             : /****************************************************************
    2618             :  ****************************************************************/
    2619             : 
    2620           2 : static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
    2621             :                                                              const struct spoolss_NotifyOption *r)
    2622             : {
    2623             :         struct spoolss_NotifyOption *option;
    2624             :         uint32_t i,k;
    2625             : 
    2626           2 :         if (!r) {
    2627           0 :                 return NULL;
    2628             :         }
    2629             : 
    2630           2 :         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
    2631           2 :         if (!option) {
    2632           0 :                 return NULL;
    2633             :         }
    2634             : 
    2635           2 :         *option = *r;
    2636             : 
    2637           2 :         if (!option->count) {
    2638           0 :                 return option;
    2639             :         }
    2640             : 
    2641           2 :         option->types = talloc_zero_array(option,
    2642             :                 struct spoolss_NotifyOptionType, option->count);
    2643           2 :         if (!option->types) {
    2644           0 :                 talloc_free(option);
    2645           0 :                 return NULL;
    2646             :         }
    2647             : 
    2648           6 :         for (i=0; i < option->count; i++) {
    2649           4 :                 option->types[i] = r->types[i];
    2650             : 
    2651           4 :                 if (option->types[i].count) {
    2652           4 :                         option->types[i].fields = talloc_zero_array(option,
    2653             :                                 union spoolss_Field, option->types[i].count);
    2654           4 :                         if (!option->types[i].fields) {
    2655           0 :                                 talloc_free(option);
    2656           0 :                                 return NULL;
    2657             :                         }
    2658           8 :                         for (k=0; k<option->types[i].count; k++) {
    2659           4 :                                 option->types[i].fields[k] =
    2660           4 :                                         r->types[i].fields[k];
    2661             :                         }
    2662             :                 }
    2663             :         }
    2664             : 
    2665           2 :         return option;
    2666             : }
    2667             : 
    2668             : /****************************************************************
    2669             :  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
    2670             :  *
    2671             :  * before replying OK: status=0 a rpc call is made to the workstation
    2672             :  * asking ReplyOpenPrinter
    2673             :  *
    2674             :  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
    2675             :  * called from api_spoolss_rffpcnex
    2676             : ****************************************************************/
    2677             : 
    2678           2 : WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
    2679             :                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
    2680             : {
    2681           2 :         struct dcesrv_call_state *dce_call = p->dce_call;
    2682           2 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    2683           1 :         const struct tsocket_address *remote_address =
    2684           1 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    2685           2 :         int snum = -1;
    2686           2 :         struct spoolss_NotifyOption *option = r->in.notify_options;
    2687             :         struct sockaddr_storage client_ss;
    2688             :         ssize_t client_len;
    2689             : 
    2690             :         /* store the notify value in the printer struct */
    2691             : 
    2692           2 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    2693             : 
    2694           2 :         if (!Printer) {
    2695           0 :                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2696             :                         "Invalid handle (%s:%u:%u).\n",
    2697             :                         OUR_HANDLE(r->in.handle)));
    2698           0 :                 return WERR_INVALID_HANDLE;
    2699             :         }
    2700             : 
    2701           2 :         Printer->notify.flags                = r->in.flags;
    2702           2 :         Printer->notify.options              = r->in.options;
    2703           2 :         Printer->notify.printerlocal = r->in.printer_local;
    2704           2 :         Printer->notify.msg_ctx              = p->msg_ctx;
    2705             : 
    2706           2 :         TALLOC_FREE(Printer->notify.option);
    2707           2 :         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
    2708             : 
    2709           2 :         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
    2710             : 
    2711             :         /* Connect to the client machine and send a ReplyOpenPrinter */
    2712             : 
    2713           2 :         if ( Printer->printer_type == SPLHND_SERVER)
    2714           2 :                 snum = -1;
    2715           0 :         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
    2716           0 :                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
    2717           0 :                 return WERR_INVALID_HANDLE;
    2718             : 
    2719           2 :         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2720             :                   "remote_address is %s\n",
    2721             :                   tsocket_address_string(remote_address, p->mem_ctx)));
    2722             : 
    2723           2 :         if (!lp_print_notify_backchannel(snum)) {
    2724           0 :                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
    2725             :                         "backchannel disabled\n"));
    2726           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
    2727             :         }
    2728             : 
    2729           2 :         client_len = tsocket_address_bsd_sockaddr(remote_address,
    2730             :                                                   (struct sockaddr *) &client_ss,
    2731             :                                                   sizeof(struct sockaddr_storage));
    2732           2 :         if (client_len < 0) {
    2733           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2734             :         }
    2735             : 
    2736           2 :         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
    2737             :                                         Printer->notify.printerlocal, REG_SZ,
    2738             :                                         &Printer->notify.cli_hnd,
    2739             :                                         &Printer->notify.cli_chan,
    2740             :                                         &client_ss, p->msg_ctx)) {
    2741           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
    2742             :         }
    2743             : 
    2744           2 :         return WERR_OK;
    2745             : }
    2746             : 
    2747             : /*******************************************************************
    2748             :  * fill a notify_info_data with the servername
    2749             :  ********************************************************************/
    2750             : 
    2751           0 : static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
    2752             :                                        int snum,
    2753             :                                        struct spoolss_Notify *data,
    2754             :                                        print_queue_struct *queue,
    2755             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    2756             :                                        TALLOC_CTX *mem_ctx)
    2757             : {
    2758           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
    2759           0 : }
    2760             : 
    2761             : /*******************************************************************
    2762             :  * fill a notify_info_data with the printername (not including the servername).
    2763             :  ********************************************************************/
    2764             : 
    2765           0 : static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
    2766             :                                         int snum,
    2767             :                                         struct spoolss_Notify *data,
    2768             :                                         print_queue_struct *queue,
    2769             :                                         struct spoolss_PrinterInfo2 *pinfo2,
    2770             :                                         TALLOC_CTX *mem_ctx)
    2771             : {
    2772             :         /* the notify name should not contain the \\server\ part */
    2773           0 :         const char *p = strrchr(pinfo2->printername, '\\');
    2774             : 
    2775           0 :         if (!p) {
    2776           0 :                 p = pinfo2->printername;
    2777             :         } else {
    2778           0 :                 p++;
    2779             :         }
    2780             : 
    2781           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    2782           0 : }
    2783             : 
    2784             : /*******************************************************************
    2785             :  * fill a notify_info_data with the servicename
    2786             :  ********************************************************************/
    2787             : 
    2788           0 : static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
    2789             :                                       int snum,
    2790             :                                       struct spoolss_Notify *data,
    2791             :                                       print_queue_struct *queue,
    2792             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2793             :                                       TALLOC_CTX *mem_ctx)
    2794             : {
    2795           0 :         const struct loadparm_substitution *lp_sub =
    2796           0 :                 loadparm_s3_global_substitution();
    2797             : 
    2798           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
    2799           0 : }
    2800             : 
    2801             : /*******************************************************************
    2802             :  * fill a notify_info_data with the port name
    2803             :  ********************************************************************/
    2804             : 
    2805           0 : static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
    2806             :                                      int snum,
    2807             :                                      struct spoolss_Notify *data,
    2808             :                                      print_queue_struct *queue,
    2809             :                                      struct spoolss_PrinterInfo2 *pinfo2,
    2810             :                                      TALLOC_CTX *mem_ctx)
    2811             : {
    2812           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
    2813           0 : }
    2814             : 
    2815             : /*******************************************************************
    2816             :  * fill a notify_info_data with the printername
    2817             :  * but it doesn't exist, have to see what to do
    2818             :  ********************************************************************/
    2819             : 
    2820           0 : static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
    2821             :                                        int snum,
    2822             :                                        struct spoolss_Notify *data,
    2823             :                                        print_queue_struct *queue,
    2824             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    2825             :                                        TALLOC_CTX *mem_ctx)
    2826             : {
    2827           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
    2828           0 : }
    2829             : 
    2830             : /*******************************************************************
    2831             :  * fill a notify_info_data with the comment
    2832             :  ********************************************************************/
    2833             : 
    2834           0 : static void spoolss_notify_comment(struct messaging_context *msg_ctx,
    2835             :                                    int snum,
    2836             :                                    struct spoolss_Notify *data,
    2837             :                                    print_queue_struct *queue,
    2838             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2839             :                                    TALLOC_CTX *mem_ctx)
    2840             : {
    2841           0 :         const struct loadparm_substitution *lp_sub =
    2842           0 :                 loadparm_s3_global_substitution();
    2843             :         const char *p;
    2844             : 
    2845           0 :         if (*pinfo2->comment == '\0') {
    2846           0 :                 p = lp_comment(talloc_tos(), lp_sub, snum);
    2847             :         } else {
    2848           0 :                 p = pinfo2->comment;
    2849             :         }
    2850             : 
    2851           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    2852           0 : }
    2853             : 
    2854             : /*******************************************************************
    2855             :  * fill a notify_info_data with the comment
    2856             :  * location = "Room 1, floor 2, building 3"
    2857             :  ********************************************************************/
    2858             : 
    2859           0 : static void spoolss_notify_location(struct messaging_context *msg_ctx,
    2860             :                                     int snum,
    2861             :                                     struct spoolss_Notify *data,
    2862             :                                     print_queue_struct *queue,
    2863             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2864             :                                     TALLOC_CTX *mem_ctx)
    2865             : {
    2866           0 :         const char *loc = pinfo2->location;
    2867             :         NTSTATUS status;
    2868             : 
    2869           0 :         status = printer_list_get_printer(mem_ctx,
    2870             :                                           pinfo2->sharename,
    2871             :                                           NULL,
    2872             :                                           &loc,
    2873             :                                           NULL);
    2874           0 :         if (NT_STATUS_IS_OK(status)) {
    2875           0 :                 if (loc == NULL) {
    2876           0 :                         loc = pinfo2->location;
    2877             :                 }
    2878             :         }
    2879             : 
    2880           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
    2881           0 : }
    2882             : 
    2883             : /*******************************************************************
    2884             :  * fill a notify_info_data with the device mode
    2885             :  * jfm:xxxx don't to it for know but that's a real problem !!!
    2886             :  ********************************************************************/
    2887             : 
    2888           0 : static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
    2889             :                                    int snum,
    2890             :                                    struct spoolss_Notify *data,
    2891             :                                    print_queue_struct *queue,
    2892             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2893             :                                    TALLOC_CTX *mem_ctx)
    2894             : {
    2895             :         /* for a dummy implementation we have to zero the fields */
    2896           0 :         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
    2897           0 : }
    2898             : 
    2899             : /*******************************************************************
    2900             :  * fill a notify_info_data with the separator file name
    2901             :  ********************************************************************/
    2902             : 
    2903           0 : static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
    2904             :                                    int snum,
    2905             :                                    struct spoolss_Notify *data,
    2906             :                                    print_queue_struct *queue,
    2907             :                                    struct spoolss_PrinterInfo2 *pinfo2,
    2908             :                                    TALLOC_CTX *mem_ctx)
    2909             : {
    2910           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
    2911           0 : }
    2912             : 
    2913             : /*******************************************************************
    2914             :  * fill a notify_info_data with the print processor
    2915             :  * jfm:xxxx return always winprint to indicate we don't do anything to it
    2916             :  ********************************************************************/
    2917             : 
    2918           0 : static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
    2919             :                                            int snum,
    2920             :                                            struct spoolss_Notify *data,
    2921             :                                            print_queue_struct *queue,
    2922             :                                            struct spoolss_PrinterInfo2 *pinfo2,
    2923             :                                            TALLOC_CTX *mem_ctx)
    2924             : {
    2925           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
    2926           0 : }
    2927             : 
    2928             : /*******************************************************************
    2929             :  * fill a notify_info_data with the print processor options
    2930             :  * jfm:xxxx send an empty string
    2931             :  ********************************************************************/
    2932             : 
    2933           0 : static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
    2934             :                                       int snum,
    2935             :                                       struct spoolss_Notify *data,
    2936             :                                       print_queue_struct *queue,
    2937             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2938             :                                       TALLOC_CTX *mem_ctx)
    2939             : {
    2940           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
    2941           0 : }
    2942             : 
    2943             : /*******************************************************************
    2944             :  * fill a notify_info_data with the data type
    2945             :  * jfm:xxxx always send RAW as data type
    2946             :  ********************************************************************/
    2947             : 
    2948           0 : static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
    2949             :                                     int snum,
    2950             :                                     struct spoolss_Notify *data,
    2951             :                                     print_queue_struct *queue,
    2952             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    2953             :                                     TALLOC_CTX *mem_ctx)
    2954             : {
    2955           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
    2956           0 : }
    2957             : 
    2958             : /*******************************************************************
    2959             :  * fill a notify_info_data with the security descriptor
    2960             :  * jfm:xxxx send an null pointer to say no security desc
    2961             :  * have to implement security before !
    2962             :  ********************************************************************/
    2963             : 
    2964           0 : static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
    2965             :                                          int snum,
    2966             :                                          struct spoolss_Notify *data,
    2967             :                                          print_queue_struct *queue,
    2968             :                                          struct spoolss_PrinterInfo2 *pinfo2,
    2969             :                                          TALLOC_CTX *mem_ctx)
    2970             : {
    2971           0 :         if (pinfo2->secdesc == NULL) {
    2972           0 :                 data->data.sd.sd = NULL;
    2973             :         } else {
    2974           0 :                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
    2975           0 :                                                             pinfo2->secdesc);
    2976             :         }
    2977           0 :         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
    2978             :                                                              0);
    2979           0 : }
    2980             : 
    2981             : /*******************************************************************
    2982             :  * fill a notify_info_data with the attributes
    2983             :  * jfm:xxxx a samba printer is always shared
    2984             :  ********************************************************************/
    2985             : 
    2986           0 : static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
    2987             :                                       int snum,
    2988             :                                       struct spoolss_Notify *data,
    2989             :                                       print_queue_struct *queue,
    2990             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    2991             :                                       TALLOC_CTX *mem_ctx)
    2992             : {
    2993           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
    2994           0 : }
    2995             : 
    2996             : /*******************************************************************
    2997             :  * fill a notify_info_data with the priority
    2998             :  ********************************************************************/
    2999             : 
    3000           0 : static void spoolss_notify_priority(struct messaging_context *msg_ctx,
    3001             :                                     int snum,
    3002             :                                     struct spoolss_Notify *data,
    3003             :                                     print_queue_struct *queue,
    3004             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3005             :                                     TALLOC_CTX *mem_ctx)
    3006             : {
    3007           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
    3008           0 : }
    3009             : 
    3010             : /*******************************************************************
    3011             :  * fill a notify_info_data with the default priority
    3012             :  ********************************************************************/
    3013             : 
    3014           0 : static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
    3015             :                                             int snum,
    3016             :                                             struct spoolss_Notify *data,
    3017             :                                             print_queue_struct *queue,
    3018             :                                             struct spoolss_PrinterInfo2 *pinfo2,
    3019             :                                             TALLOC_CTX *mem_ctx)
    3020             : {
    3021           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
    3022           0 : }
    3023             : 
    3024             : /*******************************************************************
    3025             :  * fill a notify_info_data with the start time
    3026             :  ********************************************************************/
    3027             : 
    3028           0 : static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
    3029             :                                       int snum,
    3030             :                                       struct spoolss_Notify *data,
    3031             :                                       print_queue_struct *queue,
    3032             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3033             :                                       TALLOC_CTX *mem_ctx)
    3034             : {
    3035           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
    3036           0 : }
    3037             : 
    3038             : /*******************************************************************
    3039             :  * fill a notify_info_data with the until time
    3040             :  ********************************************************************/
    3041             : 
    3042           0 : static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
    3043             :                                       int snum,
    3044             :                                       struct spoolss_Notify *data,
    3045             :                                       print_queue_struct *queue,
    3046             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3047             :                                       TALLOC_CTX *mem_ctx)
    3048             : {
    3049           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
    3050           0 : }
    3051             : 
    3052             : /*******************************************************************
    3053             :  * fill a notify_info_data with the status
    3054             :  ********************************************************************/
    3055             : 
    3056           0 : static void spoolss_notify_status(struct messaging_context *msg_ctx,
    3057             :                                   int snum,
    3058             :                                   struct spoolss_Notify *data,
    3059             :                                   print_queue_struct *queue,
    3060             :                                   struct spoolss_PrinterInfo2 *pinfo2,
    3061             :                                   TALLOC_CTX *mem_ctx)
    3062             : {
    3063             :         print_status_struct status;
    3064             : 
    3065           0 :         print_queue_length(msg_ctx, snum, &status);
    3066           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
    3067           0 : }
    3068             : 
    3069             : /*******************************************************************
    3070             :  * fill a notify_info_data with the number of jobs queued
    3071             :  ********************************************************************/
    3072             : 
    3073           0 : static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
    3074             :                                  int snum,
    3075             :                                  struct spoolss_Notify *data,
    3076             :                                  print_queue_struct *queue,
    3077             :                                  struct spoolss_PrinterInfo2 *pinfo2,
    3078             :                                  TALLOC_CTX *mem_ctx)
    3079             : {
    3080           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
    3081             :                 data, print_queue_length(msg_ctx, snum, NULL));
    3082           0 : }
    3083             : 
    3084             : /*******************************************************************
    3085             :  * fill a notify_info_data with the average ppm
    3086             :  ********************************************************************/
    3087             : 
    3088           0 : static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
    3089             :                                        int snum,
    3090             :                                        struct spoolss_Notify *data,
    3091             :                                        print_queue_struct *queue,
    3092             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    3093             :                                        TALLOC_CTX *mem_ctx)
    3094             : {
    3095             :         /* always respond 8 pages per minutes */
    3096             :         /* a little hard ! */
    3097           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
    3098           0 : }
    3099             : 
    3100             : /*******************************************************************
    3101             :  * fill a notify_info_data with username
    3102             :  ********************************************************************/
    3103             : 
    3104           0 : static void spoolss_notify_username(struct messaging_context *msg_ctx,
    3105             :                                     int snum,
    3106             :                                     struct spoolss_Notify *data,
    3107             :                                     print_queue_struct *queue,
    3108             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3109             :                                     TALLOC_CTX *mem_ctx)
    3110             : {
    3111           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
    3112           0 : }
    3113             : 
    3114             : /*******************************************************************
    3115             :  * fill a notify_info_data with job status
    3116             :  ********************************************************************/
    3117             : 
    3118           0 : static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
    3119             :                                       int snum,
    3120             :                                       struct spoolss_Notify *data,
    3121             :                                       print_queue_struct *queue,
    3122             :                                       struct spoolss_PrinterInfo2 *pinfo2,
    3123             :                                       TALLOC_CTX *mem_ctx)
    3124             : {
    3125           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
    3126           0 : }
    3127             : 
    3128             : /*******************************************************************
    3129             :  * fill a notify_info_data with job name
    3130             :  ********************************************************************/
    3131             : 
    3132           0 : static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
    3133             :                                     int snum,
    3134             :                                     struct spoolss_Notify *data,
    3135             :                                     print_queue_struct *queue,
    3136             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3137             :                                     TALLOC_CTX *mem_ctx)
    3138             : {
    3139           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
    3140           0 : }
    3141             : 
    3142             : /*******************************************************************
    3143             :  * fill a notify_info_data with job status
    3144             :  ********************************************************************/
    3145             : 
    3146           0 : static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
    3147             :                                              int snum,
    3148             :                                              struct spoolss_Notify *data,
    3149             :                                              print_queue_struct *queue,
    3150             :                                              struct spoolss_PrinterInfo2 *pinfo2,
    3151             :                                              TALLOC_CTX *mem_ctx)
    3152             : {
    3153             :         /*
    3154             :          * Now we're returning job status codes we just return a "" here. JRA.
    3155             :          */
    3156             : 
    3157           0 :         const char *p = "";
    3158             : 
    3159             : #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
    3160             :         p = "unknown";
    3161             : 
    3162             :         switch (queue->status) {
    3163             :         case LPQ_QUEUED:
    3164             :                 p = "Queued";
    3165             :                 break;
    3166             :         case LPQ_PAUSED:
    3167             :                 p = "";    /* NT provides the paused string */
    3168             :                 break;
    3169             :         case LPQ_SPOOLING:
    3170             :                 p = "Spooling";
    3171             :                 break;
    3172             :         case LPQ_PRINTING:
    3173             :                 p = "Printing";
    3174             :                 break;
    3175             :         }
    3176             : #endif /* NO LONGER NEEDED. */
    3177             : 
    3178           0 :         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
    3179           0 : }
    3180             : 
    3181             : /*******************************************************************
    3182             :  * fill a notify_info_data with job time
    3183             :  ********************************************************************/
    3184             : 
    3185           0 : static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
    3186             :                                     int snum,
    3187             :                                     struct spoolss_Notify *data,
    3188             :                                     print_queue_struct *queue,
    3189             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3190             :                                     TALLOC_CTX *mem_ctx)
    3191             : {
    3192           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
    3193           0 : }
    3194             : 
    3195             : /*******************************************************************
    3196             :  * fill a notify_info_data with job size
    3197             :  ********************************************************************/
    3198             : 
    3199           0 : static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
    3200             :                                     int snum,
    3201             :                                     struct spoolss_Notify *data,
    3202             :                                     print_queue_struct *queue,
    3203             :                                     struct spoolss_PrinterInfo2 *pinfo2,
    3204             :                                     TALLOC_CTX *mem_ctx)
    3205             : {
    3206           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
    3207           0 : }
    3208             : 
    3209             : /*******************************************************************
    3210             :  * fill a notify_info_data with page info
    3211             :  ********************************************************************/
    3212           0 : static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
    3213             :                                        int snum,
    3214             :                                 struct spoolss_Notify *data,
    3215             :                                 print_queue_struct *queue,
    3216             :                                 struct spoolss_PrinterInfo2 *pinfo2,
    3217             :                                 TALLOC_CTX *mem_ctx)
    3218             : {
    3219           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
    3220           0 : }
    3221             : 
    3222             : /*******************************************************************
    3223             :  * fill a notify_info_data with pages printed info.
    3224             :  ********************************************************************/
    3225           0 : static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
    3226             :                                          int snum,
    3227             :                                 struct spoolss_Notify *data,
    3228             :                                 print_queue_struct *queue,
    3229             :                                 struct spoolss_PrinterInfo2 *pinfo2,
    3230             :                                 TALLOC_CTX *mem_ctx)
    3231             : {
    3232             :         /* Add code when back-end tracks this */
    3233           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
    3234           0 : }
    3235             : 
    3236             : /*******************************************************************
    3237             :  Fill a notify_info_data with job position.
    3238             :  ********************************************************************/
    3239             : 
    3240           0 : static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
    3241             :                                         int snum,
    3242             :                                         struct spoolss_Notify *data,
    3243             :                                         print_queue_struct *queue,
    3244             :                                         struct spoolss_PrinterInfo2 *pinfo2,
    3245             :                                         TALLOC_CTX *mem_ctx)
    3246             : {
    3247           0 :         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
    3248           0 : }
    3249             : 
    3250             : /*******************************************************************
    3251             :  Fill a notify_info_data with submitted time.
    3252             :  ********************************************************************/
    3253             : 
    3254           0 : static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
    3255             :                                           int snum,
    3256             :                                           struct spoolss_Notify *data,
    3257             :                                           print_queue_struct *queue,
    3258             :                                           struct spoolss_PrinterInfo2 *pinfo2,
    3259             :                                           TALLOC_CTX *mem_ctx)
    3260             : {
    3261           0 :         data->data.string.string = NULL;
    3262           0 :         data->data.string.size = 0;
    3263             : 
    3264           0 :         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
    3265             :                                &data->data.string.string,
    3266             :                                &data->data.string.size);
    3267             : 
    3268           0 : }
    3269             : 
    3270             : struct s_notify_info_data_table
    3271             : {
    3272             :         enum spoolss_NotifyType type;
    3273             :         uint16_t field;
    3274             :         const char *name;
    3275             :         enum spoolss_NotifyTable variable_type;
    3276             :         void (*fn) (struct messaging_context *msg_ctx,
    3277             :                     int snum, struct spoolss_Notify *data,
    3278             :                     print_queue_struct *queue,
    3279             :                     struct spoolss_PrinterInfo2 *pinfo2,
    3280             :                     TALLOC_CTX *mem_ctx);
    3281             : };
    3282             : 
    3283             : /* A table describing the various print notification constants and
    3284             :    whether the notification data is a pointer to a variable sized
    3285             :    buffer, a one value uint32_t or a two value uint32_t. */
    3286             : 
    3287             : static const struct s_notify_info_data_table notify_info_data_table[] =
    3288             : {
    3289             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
    3290             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
    3291             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
    3292             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
    3293             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
    3294             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
    3295             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
    3296             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
    3297             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
    3298             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
    3299             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
    3300             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
    3301             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
    3302             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
    3303             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
    3304             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
    3305             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
    3306             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
    3307             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
    3308             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
    3309             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
    3310             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
    3311             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
    3312             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
    3313             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
    3314             : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
    3315             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
    3316             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
    3317             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
    3318             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
    3319             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
    3320             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
    3321             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
    3322             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
    3323             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
    3324             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
    3325             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
    3326             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
    3327             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
    3328             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
    3329             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
    3330             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
    3331             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
    3332             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
    3333             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
    3334             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
    3335             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
    3336             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
    3337             : { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
    3338             : };
    3339             : 
    3340             : /*******************************************************************
    3341             :  Return the variable_type of info_data structure.
    3342             : ********************************************************************/
    3343             : 
    3344           0 : static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
    3345             :                                                                   uint16_t field)
    3346             : {
    3347           0 :         int i=0;
    3348             : 
    3349           0 :         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
    3350           0 :                 if ( (notify_info_data_table[i].type == type) &&
    3351           0 :                      (notify_info_data_table[i].field == field) ) {
    3352           0 :                         return notify_info_data_table[i].variable_type;
    3353             :                 }
    3354             :         }
    3355             : 
    3356           0 :         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
    3357             : 
    3358           0 :         return (enum spoolss_NotifyTable) 0;
    3359             : }
    3360             : 
    3361             : /****************************************************************************
    3362             : ****************************************************************************/
    3363             : 
    3364           0 : static bool search_notify(enum spoolss_NotifyType type,
    3365             :                           uint16_t field,
    3366             :                           int *value)
    3367             : {
    3368             :         int i;
    3369             : 
    3370           0 :         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
    3371           0 :                 if (notify_info_data_table[i].type == type &&
    3372           0 :                     notify_info_data_table[i].field == field &&
    3373           0 :                     notify_info_data_table[i].fn != NULL) {
    3374           0 :                         *value = i;
    3375           0 :                         return true;
    3376             :                 }
    3377             :         }
    3378             : 
    3379           0 :         return false;
    3380             : }
    3381             : 
    3382             : /****************************************************************************
    3383             : ****************************************************************************/
    3384             : 
    3385           0 : static void construct_info_data(struct spoolss_Notify *info_data,
    3386             :                                 enum spoolss_NotifyType type,
    3387             :                                 uint16_t field, int id)
    3388             : {
    3389           0 :         info_data->type                      = type;
    3390           0 :         info_data->field.field               = field;
    3391           0 :         info_data->variable_type     = variable_type_of_notify_info_data(type, field);
    3392           0 :         info_data->job_id            = id;
    3393           0 : }
    3394             : 
    3395             : /*******************************************************************
    3396             :  *
    3397             :  * fill a notify_info struct with info asked
    3398             :  *
    3399             :  ********************************************************************/
    3400             : 
    3401           0 : static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
    3402             :                                           struct printer_handle *print_hnd,
    3403             :                                           struct spoolss_NotifyInfo *info,
    3404             :                                           struct spoolss_PrinterInfo2 *pinfo2,
    3405             :                                           int snum,
    3406             :                                           const struct spoolss_NotifyOptionType *option_type,
    3407             :                                           uint32_t id,
    3408             :                                           TALLOC_CTX *mem_ctx)
    3409             : {
    3410           0 :         const struct loadparm_substitution *lp_sub =
    3411           0 :                 loadparm_s3_global_substitution();
    3412             :         int field_num,j;
    3413             :         enum spoolss_NotifyType type;
    3414             :         uint16_t field;
    3415             : 
    3416             :         struct spoolss_Notify *current_data;
    3417             : 
    3418           0 :         type = option_type->type;
    3419             : 
    3420           0 :         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
    3421             :                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
    3422             :                 option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
    3423             : 
    3424           0 :         for(field_num=0; field_num < option_type->count; field_num++) {
    3425           0 :                 field = option_type->fields[field_num].field;
    3426             : 
    3427           0 :                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
    3428             : 
    3429           0 :                 if (!search_notify(type, field, &j) )
    3430           0 :                         continue;
    3431             : 
    3432           0 :                 info->notifies = talloc_realloc(info, info->notifies,
    3433             :                                                       struct spoolss_Notify,
    3434             :                                                       info->count + 1);
    3435           0 :                 if (info->notifies == NULL) {
    3436           0 :                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
    3437           0 :                         return false;
    3438             :                 }
    3439             : 
    3440           0 :                 current_data = &info->notifies[info->count];
    3441             : 
    3442           0 :                 construct_info_data(current_data, type, field, id);
    3443             : 
    3444           0 :                 DEBUG(10, ("construct_notify_printer_info: "
    3445             :                            "calling [%s]  snum=%d  printername=[%s])\n",
    3446             :                            notify_info_data_table[j].name, snum,
    3447             :                            pinfo2->printername));
    3448             : 
    3449           0 :                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
    3450             :                                              NULL, pinfo2, mem_ctx);
    3451             : 
    3452           0 :                 info->count++;
    3453             :         }
    3454             : 
    3455           0 :         return true;
    3456             : }
    3457             : 
    3458             : /*******************************************************************
    3459             :  *
    3460             :  * fill a notify_info struct with info asked
    3461             :  *
    3462             :  ********************************************************************/
    3463             : 
    3464           0 : static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
    3465             :                                        print_queue_struct *queue,
    3466             :                                        struct spoolss_NotifyInfo *info,
    3467             :                                        struct spoolss_PrinterInfo2 *pinfo2,
    3468             :                                        int snum,
    3469             :                                        const struct spoolss_NotifyOptionType *option_type,
    3470             :                                        uint32_t id,
    3471             :                                        TALLOC_CTX *mem_ctx)
    3472             : {
    3473             :         int field_num,j;
    3474             :         enum spoolss_NotifyType type;
    3475             :         uint16_t field;
    3476             :         struct spoolss_Notify *current_data;
    3477             : 
    3478           0 :         DEBUG(4,("construct_notify_jobs_info\n"));
    3479             : 
    3480           0 :         type = option_type->type;
    3481             : 
    3482           0 :         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
    3483             :                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
    3484             :                 option_type->count));
    3485             : 
    3486           0 :         for(field_num=0; field_num<option_type->count; field_num++) {
    3487           0 :                 field = option_type->fields[field_num].field;
    3488             : 
    3489           0 :                 if (!search_notify(type, field, &j) )
    3490           0 :                         continue;
    3491             : 
    3492           0 :                 info->notifies = talloc_realloc(info, info->notifies,
    3493             :                                                       struct spoolss_Notify,
    3494             :                                                       info->count + 1);
    3495           0 :                 if (info->notifies == NULL) {
    3496           0 :                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
    3497           0 :                         return false;
    3498             :                 }
    3499             : 
    3500           0 :                 current_data=&(info->notifies[info->count]);
    3501             : 
    3502           0 :                 construct_info_data(current_data, type, field, id);
    3503           0 :                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
    3504             :                                              queue, pinfo2, mem_ctx);
    3505           0 :                 info->count++;
    3506             :         }
    3507             : 
    3508           0 :         return true;
    3509             : }
    3510             : 
    3511             : /*
    3512             :  * JFM: The enumeration is not that simple, it's even non obvious.
    3513             :  *
    3514             :  * let's take an example: I want to monitor the PRINTER SERVER for
    3515             :  * the printer's name and the number of jobs currently queued.
    3516             :  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
    3517             :  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
    3518             :  *
    3519             :  * I have 3 printers on the back of my server.
    3520             :  *
    3521             :  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
    3522             :  * structures.
    3523             :  *   Number     Data                    Id
    3524             :  *      1       printer 1 name          1
    3525             :  *      2       printer 1 cjob          1
    3526             :  *      3       printer 2 name          2
    3527             :  *      4       printer 2 cjob          2
    3528             :  *      5       printer 3 name          3
    3529             :  *      6       printer 3 name          3
    3530             :  *
    3531             :  * that's the print server case, the printer case is even worse.
    3532             :  */
    3533             : 
    3534             : /*******************************************************************
    3535             :  *
    3536             :  * enumerate all printers on the printserver
    3537             :  * fill a notify_info struct with info asked
    3538             :  *
    3539             :  ********************************************************************/
    3540             : 
    3541           4 : static WERROR printserver_notify_info(struct pipes_struct *p,
    3542             :                                       struct policy_handle *hnd,
    3543             :                                       struct spoolss_NotifyInfo *info,
    3544             :                                       TALLOC_CTX *mem_ctx)
    3545             : {
    3546           2 :         const struct loadparm_substitution *lp_sub =
    3547           2 :                 loadparm_s3_global_substitution();
    3548             :         int snum;
    3549           4 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
    3550           4 :         int n_services=lp_numservices();
    3551             :         int i;
    3552             :         struct spoolss_NotifyOption *option;
    3553             :         struct spoolss_NotifyOptionType option_type;
    3554           4 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    3555             :         WERROR result;
    3556             : 
    3557           4 :         DEBUG(4,("printserver_notify_info\n"));
    3558             : 
    3559           4 :         if (!Printer)
    3560           0 :                 return WERR_INVALID_HANDLE;
    3561             : 
    3562           4 :         option = Printer->notify.option;
    3563             : 
    3564           4 :         info->version        = 2;
    3565           4 :         info->notifies       = NULL;
    3566           4 :         info->count  = 0;
    3567             : 
    3568             :         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
    3569             :            sending a ffpcn() request first */
    3570             : 
    3571           4 :         if ( !option )
    3572           0 :                 return WERR_INVALID_HANDLE;
    3573             : 
    3574          12 :         for (i=0; i<option->count; i++) {
    3575           8 :                 option_type = option->types[i];
    3576             : 
    3577           8 :                 if (option_type.type != PRINTER_NOTIFY_TYPE)
    3578           4 :                         continue;
    3579             : 
    3580         448 :                 for (snum = 0; snum < n_services; snum++) {
    3581         666 :                         if (!lp_browseable(snum) ||
    3582         666 :                             !lp_snum_ok(snum) ||
    3583         444 :                             !lp_printable(snum)) {
    3584         424 :                                 continue; /* skip */
    3585             :                         }
    3586             : 
    3587             :                         /* Maybe we should use the SYSTEM session_info here... */
    3588          20 :                         result = winreg_get_printer_internal(mem_ctx,
    3589             :                                                     get_session_info_system(),
    3590             :                                                     p->msg_ctx,
    3591          20 :                                                     lp_servicename(talloc_tos(), lp_sub, snum),
    3592             :                                                     &pinfo2);
    3593          20 :                         if (!W_ERROR_IS_OK(result)) {
    3594          20 :                                 DEBUG(4, ("printserver_notify_info: "
    3595             :                                           "Failed to get printer [%s]\n",
    3596             :                                           lp_servicename(talloc_tos(), lp_sub, snum)));
    3597          20 :                                 continue;
    3598             :                         }
    3599             : 
    3600             : 
    3601           0 :                         construct_notify_printer_info(p->msg_ctx,
    3602             :                                                       Printer, info,
    3603             :                                                       pinfo2, snum,
    3604             :                                                       &option_type, snum,
    3605             :                                                       mem_ctx);
    3606             : 
    3607           0 :                         TALLOC_FREE(pinfo2);
    3608             :                 }
    3609             :         }
    3610             : 
    3611             : #if 0
    3612             :         /*
    3613             :          * Debugging information, don't delete.
    3614             :          */
    3615             : 
    3616             :         DEBUG(1,("dumping the NOTIFY_INFO\n"));
    3617             :         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
    3618             :         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
    3619             : 
    3620             :         for (i=0; i<info->count; i++) {
    3621             :                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
    3622             :                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
    3623             :                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
    3624             :         }
    3625             : #endif
    3626             : 
    3627           4 :         return WERR_OK;
    3628             : }
    3629             : 
    3630             : /*******************************************************************
    3631             :  *
    3632             :  * fill a notify_info struct with info asked
    3633             :  *
    3634             :  ********************************************************************/
    3635             : 
    3636           0 : static WERROR printer_notify_info(struct pipes_struct *p,
    3637             :                                   struct policy_handle *hnd,
    3638             :                                   struct spoolss_NotifyInfo *info,
    3639             :                                   TALLOC_CTX *mem_ctx)
    3640             : {
    3641           0 :         const struct loadparm_substitution *lp_sub =
    3642           0 :                 loadparm_s3_global_substitution();
    3643             :         int snum;
    3644           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
    3645             :         int i;
    3646             :         uint32_t id;
    3647             :         struct spoolss_NotifyOption *option;
    3648             :         struct spoolss_NotifyOptionType option_type;
    3649             :         int count,j;
    3650           0 :         print_queue_struct *queue=NULL;
    3651             :         print_status_struct status;
    3652           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    3653             :         WERROR result;
    3654             :         struct tdb_print_db *pdb;
    3655             : 
    3656           0 :         DEBUG(4,("printer_notify_info\n"));
    3657             : 
    3658           0 :         if (!Printer)
    3659           0 :                 return WERR_INVALID_HANDLE;
    3660             : 
    3661           0 :         option = Printer->notify.option;
    3662           0 :         id = 0x0;
    3663             : 
    3664           0 :         info->version        = 2;
    3665           0 :         info->notifies       = NULL;
    3666           0 :         info->count  = 0;
    3667             : 
    3668             :         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
    3669             :            sending a ffpcn() request first */
    3670             : 
    3671           0 :         if ( !option )
    3672           0 :                 return WERR_INVALID_HANDLE;
    3673             : 
    3674           0 :         if (!get_printer_snum(p, hnd, &snum, NULL)) {
    3675           0 :                 return WERR_INVALID_HANDLE;
    3676             :         }
    3677             : 
    3678           0 :         pdb = get_print_db_byname(Printer->sharename);
    3679           0 :         if (pdb == NULL) {
    3680           0 :                 return WERR_INVALID_HANDLE;
    3681             :         }
    3682             : 
    3683             :         /* Maybe we should use the SYSTEM session_info here... */
    3684           0 :         result = winreg_get_printer_internal(mem_ctx,
    3685             :                                     get_session_info_system(),
    3686             :                                     p->msg_ctx,
    3687           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
    3688           0 :         if (!W_ERROR_IS_OK(result)) {
    3689           0 :                 result = WERR_INVALID_HANDLE;
    3690           0 :                 goto err_pdb_drop;
    3691             :         }
    3692             : 
    3693             :         /*
    3694             :          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
    3695             :          * correct servername.
    3696             :          */
    3697           0 :         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
    3698           0 :         if (pinfo2->servername == NULL) {
    3699           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3700           0 :                 goto err_pdb_drop;
    3701             :         }
    3702             : 
    3703           0 :         for (i = 0; i < option->count; i++) {
    3704           0 :                 option_type = option->types[i];
    3705             : 
    3706           0 :                 switch (option_type.type) {
    3707           0 :                 case PRINTER_NOTIFY_TYPE:
    3708           0 :                         if (construct_notify_printer_info(p->msg_ctx,
    3709             :                                                           Printer, info,
    3710             :                                                           pinfo2, snum,
    3711             :                                                           &option_type, id,
    3712             :                                                           mem_ctx)) {
    3713           0 :                                 id--;
    3714             :                         }
    3715           0 :                         break;
    3716             : 
    3717           0 :                 case JOB_NOTIFY_TYPE:
    3718             : 
    3719           0 :                         count = print_queue_status(p->msg_ctx, snum, &queue,
    3720             :                                                    &status);
    3721             : 
    3722           0 :                         for (j = 0; j < count; j++) {
    3723             :                                 uint32_t jobid;
    3724           0 :                                 jobid = sysjob_to_jobid_pdb(pdb,
    3725           0 :                                                             queue[j].sysjob);
    3726           0 :                                 if (jobid == (uint32_t)-1) {
    3727           0 :                                         DEBUG(2, ("ignoring untracked job %d\n",
    3728             :                                                   queue[j].sysjob));
    3729           0 :                                         continue;
    3730             :                                 }
    3731             :                                 /* FIXME check return value */
    3732           0 :                                 construct_notify_jobs_info(p->msg_ctx,
    3733           0 :                                                            &queue[j], info,
    3734             :                                                            pinfo2, snum,
    3735             :                                                            &option_type,
    3736             :                                                            jobid,
    3737             :                                                            mem_ctx);
    3738             :                         }
    3739             : 
    3740           0 :                         SAFE_FREE(queue);
    3741           0 :                         break;
    3742             :                 }
    3743             :         }
    3744             : 
    3745             :         /*
    3746             :          * Debugging information, don't delete.
    3747             :          */
    3748             :         /*
    3749             :         DEBUG(1,("dumping the NOTIFY_INFO\n"));
    3750             :         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
    3751             :         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
    3752             : 
    3753             :         for (i=0; i<info->count; i++) {
    3754             :                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
    3755             :                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
    3756             :                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
    3757             :         }
    3758             :         */
    3759             : 
    3760           0 :         talloc_free(pinfo2);
    3761           0 :         result = WERR_OK;
    3762           0 : err_pdb_drop:
    3763           0 :         release_print_db(pdb);
    3764           0 :         return result;
    3765             : }
    3766             : 
    3767             : /****************************************************************
    3768             :  _spoolss_RouterRefreshPrinterChangeNotify
    3769             : ****************************************************************/
    3770             : 
    3771           4 : WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
    3772             :                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
    3773             : {
    3774             :         struct spoolss_NotifyInfo *info;
    3775             : 
    3776           4 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    3777           4 :         WERROR result = WERR_INVALID_HANDLE;
    3778             : 
    3779             :         /* we always have a spoolss_NotifyInfo struct */
    3780           4 :         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
    3781           4 :         if (!info) {
    3782           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3783           0 :                 goto done;
    3784             :         }
    3785             : 
    3786           4 :         *r->out.info = info;
    3787             : 
    3788           4 :         if (!Printer) {
    3789           0 :                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
    3790             :                         "Invalid handle (%s:%u:%u).\n",
    3791             :                         OUR_HANDLE(r->in.handle)));
    3792           0 :                 goto done;
    3793             :         }
    3794             : 
    3795           4 :         DEBUG(4,("Printer type %x\n",Printer->printer_type));
    3796             : 
    3797             :         /*
    3798             :          *      We are now using the change value, and
    3799             :          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
    3800             :          *      I don't have a global notification system, I'm sending back all the
    3801             :          *      information even when _NOTHING_ has changed.
    3802             :          */
    3803             : 
    3804             :         /* We need to keep track of the change value to send back in
    3805             :            RRPCN replies otherwise our updates are ignored. */
    3806             : 
    3807           4 :         Printer->notify.fnpcn = true;
    3808             : 
    3809           6 :         if (Printer->notify.cli_chan != NULL &&
    3810           4 :             Printer->notify.cli_chan->active_connections > 0) {
    3811           4 :                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
    3812             :                         "Saving change value in request [%x]\n",
    3813             :                         r->in.change_low));
    3814           4 :                 Printer->notify.change = r->in.change_low;
    3815             :         }
    3816             : 
    3817             :         /* just ignore the spoolss_NotifyOption */
    3818             : 
    3819           4 :         switch (Printer->printer_type) {
    3820           4 :                 case SPLHND_SERVER:
    3821           4 :                         result = printserver_notify_info(p, r->in.handle,
    3822             :                                                          info, p->mem_ctx);
    3823           4 :                         break;
    3824             : 
    3825           0 :                 case SPLHND_PRINTER:
    3826           0 :                         result = printer_notify_info(p, r->in.handle,
    3827             :                                                      info, p->mem_ctx);
    3828           0 :                         break;
    3829             :         }
    3830             : 
    3831           4 :         Printer->notify.fnpcn = false;
    3832             : 
    3833           4 : done:
    3834           4 :         return result;
    3835             : }
    3836             : 
    3837             : /********************************************************************
    3838             :  ********************************************************************/
    3839             : 
    3840           0 : static WERROR create_printername(TALLOC_CTX *mem_ctx,
    3841             :                                  const char *servername,
    3842             :                                  const char *printername,
    3843             :                                  const char **printername_p)
    3844             : {
    3845             :         /* FIXME: add lp_force_printername() */
    3846             : 
    3847           0 :         if (servername == NULL) {
    3848           0 :                 *printername_p = talloc_strdup(mem_ctx, printername);
    3849           0 :                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
    3850           0 :                 return WERR_OK;
    3851             :         }
    3852             : 
    3853           0 :         if (servername[0] == '\\' && servername[1] == '\\') {
    3854           0 :                 servername += 2;
    3855             :         }
    3856             : 
    3857           0 :         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
    3858           0 :         W_ERROR_HAVE_NO_MEMORY(*printername_p);
    3859             : 
    3860           0 :         return WERR_OK;
    3861             : }
    3862             : 
    3863             : /********************************************************************
    3864             :  ********************************************************************/
    3865             : 
    3866           0 : static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
    3867             :                                           const char *printername)
    3868             : {
    3869           0 :         if (dm == NULL) {
    3870           0 :                 return;
    3871             :         }
    3872             : 
    3873           0 :         dm->devicename = talloc_strndup(dm, printername,
    3874           0 :                                         MIN(strlen(printername), 31));
    3875             : }
    3876             : 
    3877             : /********************************************************************
    3878             :  * construct_printer_info_0
    3879             :  * fill a printer_info_0 struct
    3880             :  ********************************************************************/
    3881             : 
    3882           0 : static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
    3883             :                                       const struct auth_session_info *session_info,
    3884             :                                       struct messaging_context *msg_ctx,
    3885             :                                       struct spoolss_PrinterInfo2 *info2,
    3886             :                                       const char *servername,
    3887             :                                       struct spoolss_PrinterInfo0 *r,
    3888             :                                       int snum)
    3889             : {
    3890             :         int count;
    3891             :         struct printer_session_counter *session_counter;
    3892             :         struct timeval setuptime;
    3893             :         print_status_struct status;
    3894             :         WERROR result;
    3895             :         int os_major, os_minor, os_build;
    3896             :         const char *architecture;
    3897             :         uint32_t processor_architecture, processor_type;
    3898             : 
    3899           0 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    3900           0 :         if (!W_ERROR_IS_OK(result)) {
    3901           0 :                 return result;
    3902             :         }
    3903             : 
    3904           0 :         if (servername) {
    3905           0 :                 r->servername = talloc_strdup(mem_ctx, servername);
    3906           0 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    3907             :         } else {
    3908           0 :                 r->servername = NULL;
    3909             :         }
    3910             : 
    3911           0 :         count = print_queue_length(msg_ctx, snum, &status);
    3912             : 
    3913             :         /* check if we already have a counter for this printer */
    3914           0 :         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
    3915           0 :                 if (session_counter->snum == snum)
    3916           0 :                         break;
    3917             :         }
    3918             : 
    3919             :         /* it's the first time, add it to the list */
    3920           0 :         if (session_counter == NULL) {
    3921           0 :                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
    3922           0 :                 W_ERROR_HAVE_NO_MEMORY(session_counter);
    3923           0 :                 session_counter->snum                = snum;
    3924           0 :                 session_counter->counter     = 0;
    3925           0 :                 DLIST_ADD(counter_list, session_counter);
    3926             :         }
    3927             : 
    3928             :         /* increment it */
    3929           0 :         session_counter->counter++;
    3930             : 
    3931           0 :         r->cjobs                     = count;
    3932           0 :         r->total_jobs                        = 0;
    3933           0 :         r->total_bytes                       = 0;
    3934             : 
    3935           0 :         get_startup_time(&setuptime);
    3936           0 :         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
    3937             : 
    3938             :         /* JFM:
    3939             :          * the global_counter should be stored in a TDB as it's common to all the clients
    3940             :          * and should be zeroed on samba startup
    3941             :          */
    3942           0 :         r->global_counter            = session_counter->counter;
    3943           0 :         r->total_pages                       = 0;
    3944             : 
    3945             :         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
    3946           0 :         os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
    3947             :                                "spoolss", "os_major",
    3948             :                                GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
    3949           0 :         os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
    3950             :                                "spoolss", "os_minor",
    3951             :                                GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
    3952           0 :         os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
    3953             :                                "spoolss", "os_build",
    3954             :                                GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
    3955             : 
    3956           0 :         SCVAL(&r->version, 0, os_major);
    3957           0 :         SCVAL(&r->version, 1, os_minor);
    3958           0 :         SSVAL(&r->version, 2, os_build);
    3959             : 
    3960           0 :         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    3961             :                                             "spoolss",
    3962             :                                             "architecture",
    3963             :                                             GLOBAL_SPOOLSS_ARCHITECTURE);
    3964             : 
    3965           0 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
    3966           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_AMD64;
    3967           0 :                 processor_type          = PROCESSOR_AMD_X8664;
    3968           0 :         } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
    3969           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_ARM64;
    3970           0 :                 processor_type          = PROCESSOR_ARM820;
    3971             :         } else {
    3972           0 :                 processor_architecture  = PROCESSOR_ARCHITECTURE_INTEL;
    3973           0 :                 processor_type          = PROCESSOR_INTEL_PENTIUM;
    3974             :         }
    3975             : 
    3976           0 :         r->free_build                        = SPOOLSS_RELEASE_BUILD;
    3977           0 :         r->spooling                  = 0;
    3978           0 :         r->max_spooling                      = 0;
    3979           0 :         r->session_counter           = session_counter->counter;
    3980           0 :         r->num_error_out_of_paper    = 0x0;
    3981           0 :         r->num_error_not_ready               = 0x0;          /* number of print failure */
    3982           0 :         r->job_error                 = 0x0;
    3983           0 :         r->number_of_processors              = 0x1;
    3984           0 :         r->processor_type            = processor_type;
    3985           0 :         r->high_part_total_bytes     = 0x0;
    3986             : 
    3987             :         /* ChangeID in milliseconds*/
    3988           0 :         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
    3989             :                                     info2->sharename, &r->change_id);
    3990             : 
    3991           0 :         r->last_error                        = WERR_OK;
    3992           0 :         r->status                    = nt_printq_status(status.status);
    3993           0 :         r->enumerate_network_printers        = 0x0;
    3994           0 :         r->c_setprinter                      = 0x0;
    3995           0 :         r->processor_architecture    = processor_architecture;
    3996           0 :         r->processor_level           = 0x6;          /* 6  ???*/
    3997           0 :         r->ref_ic                    = 0;
    3998           0 :         r->reserved2                 = 0;
    3999           0 :         r->reserved3                 = 0;
    4000             : 
    4001           0 :         return WERR_OK;
    4002             : }
    4003             : 
    4004             : 
    4005             : /********************************************************************
    4006             :  * construct_printer_info1
    4007             :  * fill a spoolss_PrinterInfo1 struct
    4008             : ********************************************************************/
    4009             : 
    4010           0 : static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
    4011             :                                       const struct spoolss_PrinterInfo2 *info2,
    4012             :                                       uint32_t flags,
    4013             :                                       const char *servername,
    4014             :                                       struct spoolss_PrinterInfo1 *r,
    4015             :                                       int snum)
    4016             : {
    4017           0 :         const struct loadparm_substitution *lp_sub =
    4018           0 :                 loadparm_s3_global_substitution();
    4019             :         WERROR result;
    4020             : 
    4021           0 :         r->flags             = flags;
    4022             : 
    4023           0 :         if (info2->comment == NULL || info2->comment[0] == '\0') {
    4024           0 :                 r->comment   = lp_comment(mem_ctx, lp_sub, snum);
    4025             :         } else {
    4026           0 :                 r->comment   = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
    4027             :         }
    4028           0 :         W_ERROR_HAVE_NO_MEMORY(r->comment);
    4029             : 
    4030           0 :         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
    4031           0 :         if (!W_ERROR_IS_OK(result)) {
    4032           0 :                 return result;
    4033             :         }
    4034             : 
    4035           0 :         r->description               = talloc_asprintf(mem_ctx, "%s,%s,%s",
    4036             :                                                   r->name,
    4037           0 :                                                   info2->drivername,
    4038             :                                                   r->comment);
    4039           0 :         W_ERROR_HAVE_NO_MEMORY(r->description);
    4040             : 
    4041           0 :         return WERR_OK;
    4042             : }
    4043             : 
    4044             : /********************************************************************
    4045             :  * construct_printer_info2
    4046             :  * fill a spoolss_PrinterInfo2 struct
    4047             : ********************************************************************/
    4048             : 
    4049           0 : static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
    4050             :                                       struct messaging_context *msg_ctx,
    4051             :                                       const struct spoolss_PrinterInfo2 *info2,
    4052             :                                       const char *servername,
    4053             :                                       struct spoolss_PrinterInfo2 *r,
    4054             :                                       int snum)
    4055             : {
    4056           0 :         const struct loadparm_substitution *lp_sub =
    4057           0 :                 loadparm_s3_global_substitution();
    4058             :         int count;
    4059             :         print_status_struct status;
    4060             :         WERROR result;
    4061             : 
    4062           0 :         count = print_queue_length(msg_ctx, snum, &status);
    4063             : 
    4064           0 :         if (servername) {
    4065           0 :                 r->servername                = talloc_strdup(mem_ctx, servername);
    4066           0 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    4067             :         } else {
    4068           0 :                 r->servername                = NULL;
    4069             :         }
    4070             : 
    4071           0 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4072           0 :         if (!W_ERROR_IS_OK(result)) {
    4073           0 :                 return result;
    4074             :         }
    4075             : 
    4076           0 :         r->sharename         = lp_servicename(mem_ctx, lp_sub, snum);
    4077           0 :         W_ERROR_HAVE_NO_MEMORY(r->sharename);
    4078           0 :         r->portname          = talloc_strdup(mem_ctx, info2->portname);
    4079           0 :         W_ERROR_HAVE_NO_MEMORY(r->portname);
    4080           0 :         r->drivername                = talloc_strdup(mem_ctx, info2->drivername);
    4081           0 :         W_ERROR_HAVE_NO_MEMORY(r->drivername);
    4082             : 
    4083           0 :         if (info2->comment[0] == '\0') {
    4084           0 :                 r->comment   = lp_comment(mem_ctx, lp_sub, snum);
    4085             :         } else {
    4086           0 :                 r->comment   = talloc_strdup(mem_ctx, info2->comment);
    4087             :         }
    4088           0 :         W_ERROR_HAVE_NO_MEMORY(r->comment);
    4089             : 
    4090           0 :         r->location  = talloc_strdup(mem_ctx, info2->location);
    4091           0 :         if (info2->location[0] == '\0') {
    4092           0 :                 const char *loc = NULL;
    4093             :                 NTSTATUS nt_status;
    4094             : 
    4095           0 :                 nt_status = printer_list_get_printer(mem_ctx,
    4096           0 :                                                      info2->sharename,
    4097             :                                                      NULL,
    4098             :                                                      &loc,
    4099             :                                                      NULL);
    4100           0 :                 if (NT_STATUS_IS_OK(nt_status)) {
    4101           0 :                         if (loc != NULL) {
    4102           0 :                                 r->location = talloc_strdup(mem_ctx, loc);
    4103             :                         }
    4104             :                 }
    4105             :         }
    4106           0 :         W_ERROR_HAVE_NO_MEMORY(r->location);
    4107             : 
    4108           0 :         r->sepfile           = talloc_strdup(mem_ctx, info2->sepfile);
    4109           0 :         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
    4110           0 :         r->printprocessor    = talloc_strdup(mem_ctx, info2->printprocessor);
    4111           0 :         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
    4112           0 :         r->datatype          = talloc_strdup(mem_ctx, info2->datatype);
    4113           0 :         W_ERROR_HAVE_NO_MEMORY(r->datatype);
    4114           0 :         r->parameters                = talloc_strdup(mem_ctx, info2->parameters);
    4115           0 :         W_ERROR_HAVE_NO_MEMORY(r->parameters);
    4116             : 
    4117           0 :         r->attributes                = info2->attributes;
    4118             : 
    4119           0 :         r->priority          = info2->priority;
    4120           0 :         r->defaultpriority   = info2->defaultpriority;
    4121           0 :         r->starttime         = info2->starttime;
    4122           0 :         r->untiltime         = info2->untiltime;
    4123           0 :         r->status            = nt_printq_status(status.status);
    4124           0 :         r->cjobs             = count;
    4125           0 :         r->averageppm                = info2->averageppm;
    4126             : 
    4127           0 :         if (info2->devmode != NULL) {
    4128           0 :                 result = copy_devicemode(mem_ctx,
    4129           0 :                                          info2->devmode,
    4130             :                                          &r->devmode);
    4131           0 :                 if (!W_ERROR_IS_OK(result)) {
    4132           0 :                         return result;
    4133             :                 }
    4134           0 :         } else if (lp_default_devmode(snum)) {
    4135           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    4136           0 :                                                         info2->printername,
    4137             :                                                         &r->devmode);
    4138           0 :                 if (!W_ERROR_IS_OK(result)) {
    4139           0 :                         return result;
    4140             :                 }
    4141             :         } else {
    4142           0 :                 r->devmode = NULL;
    4143           0 :                 DEBUG(8,("Returning NULL Devicemode!\n"));
    4144             :         }
    4145             : 
    4146           0 :         compose_devicemode_devicename(r->devmode, r->printername);
    4147             : 
    4148           0 :         r->secdesc = NULL;
    4149             : 
    4150           0 :         if (info2->secdesc != NULL) {
    4151             :                 /* don't use talloc_steal() here unless you do a deep steal of all
    4152             :                    the SEC_DESC members */
    4153             : 
    4154           0 :                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
    4155           0 :                 if (r->secdesc == NULL) {
    4156           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    4157             :                 }
    4158             :         }
    4159             : 
    4160           0 :         return WERR_OK;
    4161             : }
    4162             : 
    4163             : /********************************************************************
    4164             :  * construct_printer_info3
    4165             :  * fill a spoolss_PrinterInfo3 struct
    4166             :  ********************************************************************/
    4167             : 
    4168           0 : static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
    4169             :                                       const struct spoolss_PrinterInfo2 *info2,
    4170             :                                       const char *servername,
    4171             :                                       struct spoolss_PrinterInfo3 *r,
    4172             :                                       int snum)
    4173             : {
    4174             :         /* These are the components of the SD we are returning. */
    4175             : 
    4176           0 :         if (info2->secdesc != NULL) {
    4177             :                 /* don't use talloc_steal() here unless you do a deep steal of all
    4178             :                    the SEC_DESC members */
    4179             : 
    4180           0 :                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
    4181           0 :                 if (r->secdesc == NULL) {
    4182           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    4183             :                 }
    4184             :         }
    4185             : 
    4186           0 :         return WERR_OK;
    4187             : }
    4188             : 
    4189             : /********************************************************************
    4190             :  * construct_printer_info4
    4191             :  * fill a spoolss_PrinterInfo4 struct
    4192             :  ********************************************************************/
    4193             : 
    4194           0 : static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
    4195             :                                       const struct spoolss_PrinterInfo2 *info2,
    4196             :                                       const char *servername,
    4197             :                                       struct spoolss_PrinterInfo4 *r,
    4198             :                                       int snum)
    4199             : {
    4200             :         WERROR result;
    4201             : 
    4202           0 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4203           0 :         if (!W_ERROR_IS_OK(result)) {
    4204           0 :                 return result;
    4205             :         }
    4206             : 
    4207           0 :         if (servername) {
    4208           0 :                 r->servername        = talloc_strdup(mem_ctx, servername);
    4209           0 :                 W_ERROR_HAVE_NO_MEMORY(r->servername);
    4210             :         } else {
    4211           0 :                 r->servername = NULL;
    4212             :         }
    4213             : 
    4214           0 :         r->attributes        = info2->attributes;
    4215             : 
    4216           0 :         return WERR_OK;
    4217             : }
    4218             : 
    4219             : /********************************************************************
    4220             :  * construct_printer_info5
    4221             :  * fill a spoolss_PrinterInfo5 struct
    4222             :  ********************************************************************/
    4223             : 
    4224           0 : static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
    4225             :                                       const struct spoolss_PrinterInfo2 *info2,
    4226             :                                       const char *servername,
    4227             :                                       struct spoolss_PrinterInfo5 *r,
    4228             :                                       int snum)
    4229             : {
    4230             :         WERROR result;
    4231             : 
    4232           0 :         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
    4233           0 :         if (!W_ERROR_IS_OK(result)) {
    4234           0 :                 return result;
    4235             :         }
    4236             : 
    4237           0 :         r->portname  = talloc_strdup(mem_ctx, info2->portname);
    4238           0 :         W_ERROR_HAVE_NO_MEMORY(r->portname);
    4239             : 
    4240           0 :         r->attributes        = info2->attributes;
    4241             : 
    4242             :         /*
    4243             :          * These two are not used by NT+ according to MSDN. However the values
    4244             :          * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
    4245             :          */
    4246           0 :         r->device_not_selected_timeout               = 0xafc8; /* 45 sec */
    4247           0 :         r->transmission_retry_timeout                = 0xafc8; /* 45 sec */
    4248             : 
    4249           0 :         return WERR_OK;
    4250             : }
    4251             : 
    4252             : /********************************************************************
    4253             :  * construct_printer_info_6
    4254             :  * fill a spoolss_PrinterInfo6 struct
    4255             :  ********************************************************************/
    4256             : 
    4257           0 : static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
    4258             :                                       struct messaging_context *msg_ctx,
    4259             :                                       const struct spoolss_PrinterInfo2 *info2,
    4260             :                                       const char *servername,
    4261             :                                       struct spoolss_PrinterInfo6 *r,
    4262             :                                       int snum)
    4263             : {
    4264             :         print_status_struct status;
    4265             : 
    4266           0 :         print_queue_length(msg_ctx, snum, &status);
    4267             : 
    4268           0 :         r->status = nt_printq_status(status.status);
    4269             : 
    4270           0 :         return WERR_OK;
    4271             : }
    4272             : 
    4273             : /********************************************************************
    4274             :  * construct_printer_info7
    4275             :  * fill a spoolss_PrinterInfo7 struct
    4276             :  ********************************************************************/
    4277             : 
    4278           0 : static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
    4279             :                                       struct messaging_context *msg_ctx,
    4280             :                                       const char *servername,
    4281             :                                       struct spoolss_PrinterInfo7 *r,
    4282             :                                       int snum)
    4283             : {
    4284           0 :         const struct loadparm_substitution *lp_sub =
    4285           0 :                 loadparm_s3_global_substitution();
    4286             :         const struct auth_session_info *session_info;
    4287           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    4288             :         char *printer;
    4289             :         WERROR werr;
    4290           0 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    4291           0 :         if (tmp_ctx == NULL) {
    4292           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4293             :         }
    4294             : 
    4295           0 :         session_info = get_session_info_system();
    4296           0 :         SMB_ASSERT(session_info != NULL);
    4297             : 
    4298           0 :         printer = lp_servicename(tmp_ctx, lp_sub, snum);
    4299           0 :         if (printer == NULL) {
    4300           0 :                 DEBUG(0, ("invalid printer snum %d\n", snum));
    4301           0 :                 werr = WERR_INVALID_PARAMETER;
    4302           0 :                 goto out_tmp_free;
    4303             :         }
    4304             : 
    4305           0 :         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
    4306             :                                  servername, printer, &pinfo2)) {
    4307             :                 struct GUID guid;
    4308             :                 char *guidstr;
    4309           0 :                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
    4310             :                                            printer, &guid);
    4311           0 :                 if (!W_ERROR_IS_OK(werr)) {
    4312             :                         /*
    4313             :                          * If we do not have a GUID entry in the registry, then
    4314             :                          * try to retrieve it from AD and store it now.
    4315             :                          */
    4316           0 :                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
    4317             :                                                         &guid);
    4318           0 :                         if (!W_ERROR_IS_OK(werr)) {
    4319           0 :                                 DBG_NOTICE("Failed to retrieve GUID for "
    4320             :                                            "printer [%s] from AD - %s\n",
    4321             :                                            printer,
    4322             :                                            win_errstr(werr));
    4323           0 :                                 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
    4324             :                                         /*
    4325             :                                          * If we did not find it in AD, then it
    4326             :                                          * is unpublished and we should reflect
    4327             :                                          * this in the registry and return
    4328             :                                          * success.
    4329             :                                          */
    4330           0 :                                         DBG_WARNING("Unpublish printer [%s]\n",
    4331             :                                                     pinfo2->sharename);
    4332           0 :                                         nt_printer_publish(tmp_ctx,
    4333             :                                                            session_info,
    4334             :                                                            msg_ctx,
    4335             :                                                            pinfo2,
    4336             :                                                            DSPRINT_UNPUBLISH);
    4337           0 :                                         r->guid = talloc_strdup(mem_ctx, "");
    4338           0 :                                         r->action = DSPRINT_UNPUBLISH;
    4339             : 
    4340           0 :                                         if (r->guid == NULL) {
    4341           0 :                                                 werr = WERR_NOT_ENOUGH_MEMORY;
    4342             :                                         } else {
    4343           0 :                                                 werr = WERR_OK;
    4344             :                                         }
    4345             :                                 }
    4346           0 :                                 goto out_tmp_free;
    4347             :                         }
    4348             : 
    4349           0 :                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
    4350           0 :                         if (!W_ERROR_IS_OK(werr)) {
    4351           0 :                                 DEBUG(3, ("failed to store printer %s guid\n",
    4352             :                                           printer));
    4353             :                         }
    4354             :                 }
    4355             : 
    4356             :                 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
    4357           0 :                 guidstr = GUID_string2(mem_ctx, &guid);
    4358           0 :                 if (guidstr == NULL) {
    4359           0 :                         werr = WERR_NOT_ENOUGH_MEMORY;
    4360           0 :                         goto out_tmp_free;
    4361             :                 }
    4362             :                 /* Convert GUID string to uppercase otherwise printers
    4363             :                  * are pruned */
    4364           0 :                 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
    4365           0 :                 r->action = DSPRINT_PUBLISH;
    4366             : 
    4367           0 :                 TALLOC_FREE(guidstr);
    4368             :         } else {
    4369           0 :                 r->guid = talloc_strdup(mem_ctx, "");
    4370           0 :                 r->action = DSPRINT_UNPUBLISH;
    4371             :         }
    4372           0 :         if (r->guid == NULL) {
    4373           0 :                 werr = WERR_NOT_ENOUGH_MEMORY;
    4374           0 :                 goto out_tmp_free;
    4375             :         }
    4376             : 
    4377           0 :         werr = WERR_OK;
    4378           0 : out_tmp_free:
    4379           0 :         talloc_free(tmp_ctx);
    4380           0 :         return werr;
    4381             : }
    4382             : 
    4383             : /********************************************************************
    4384             :  * construct_printer_info8
    4385             :  * fill a spoolss_PrinterInfo8 struct
    4386             :  ********************************************************************/
    4387             : 
    4388           0 : static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
    4389             :                                       const struct spoolss_PrinterInfo2 *info2,
    4390             :                                       const char *servername,
    4391             :                                       struct spoolss_DeviceModeInfo *r,
    4392             :                                       int snum)
    4393             : {
    4394             :         WERROR result;
    4395             :         const char *printername;
    4396             : 
    4397           0 :         result = create_printername(mem_ctx, servername, info2->printername, &printername);
    4398           0 :         if (!W_ERROR_IS_OK(result)) {
    4399           0 :                 return result;
    4400             :         }
    4401             : 
    4402           0 :         if (info2->devmode != NULL) {
    4403           0 :                 result = copy_devicemode(mem_ctx,
    4404           0 :                                          info2->devmode,
    4405             :                                          &r->devmode);
    4406           0 :                 if (!W_ERROR_IS_OK(result)) {
    4407           0 :                         return result;
    4408             :                 }
    4409           0 :         } else if (lp_default_devmode(snum)) {
    4410           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    4411           0 :                                                         info2->printername,
    4412             :                                                         &r->devmode);
    4413           0 :                 if (!W_ERROR_IS_OK(result)) {
    4414           0 :                         return result;
    4415             :                 }
    4416             :         } else {
    4417           0 :                 r->devmode = NULL;
    4418           0 :                 DEBUG(8,("Returning NULL Devicemode!\n"));
    4419             :         }
    4420             : 
    4421           0 :         compose_devicemode_devicename(r->devmode, printername);
    4422             : 
    4423           0 :         return WERR_OK;
    4424             : }
    4425             : 
    4426             : /********************************************************************
    4427             :  Spoolss_enumprinters.
    4428             : ********************************************************************/
    4429             : 
    4430           0 : static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
    4431             :                                            const struct auth_session_info *session_info,
    4432             :                                            struct messaging_context *msg_ctx,
    4433             :                                            const char *servername,
    4434             :                                            uint32_t level,
    4435             :                                            uint32_t flags,
    4436             :                                            union spoolss_PrinterInfo **info_p,
    4437             :                                            uint32_t *count_p)
    4438             : {
    4439             :         int snum;
    4440             :         int n_services;
    4441           0 :         union spoolss_PrinterInfo *info = NULL;
    4442           0 :         uint32_t count = 0;
    4443           0 :         WERROR result = WERR_OK;
    4444           0 :         struct dcerpc_binding_handle *b = NULL;
    4445           0 :         TALLOC_CTX *tmp_ctx = NULL;
    4446             : 
    4447           0 :         tmp_ctx = talloc_new(mem_ctx);
    4448           0 :         if (!tmp_ctx) {
    4449           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4450             :         }
    4451             : 
    4452             :         /*
    4453             :          * printer shares are updated on client enumeration. The background
    4454             :          * printer process updates printer_list.tdb at regular intervals.
    4455             :          */
    4456           0 :         become_root();
    4457           0 :         delete_and_reload_printers();
    4458           0 :         unbecome_root();
    4459             : 
    4460           0 :         n_services = lp_numservices();
    4461           0 :         *count_p = 0;
    4462           0 :         *info_p = NULL;
    4463             : 
    4464           0 :         for (snum = 0; snum < n_services; snum++) {
    4465             : 
    4466             :                 const char *printer;
    4467             :                 struct spoolss_PrinterInfo2 *info2;
    4468             : 
    4469           0 :                 if (!snum_is_shared_printer(snum)) {
    4470           0 :                         continue;
    4471             :                 }
    4472             : 
    4473           0 :                 printer = lp_const_servicename(snum);
    4474             : 
    4475           0 :                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
    4476             :                         printer, snum));
    4477             : 
    4478           0 :                 if (b == NULL) {
    4479           0 :                         result = winreg_printer_binding_handle(tmp_ctx,
    4480             :                                                                session_info,
    4481             :                                                                msg_ctx,
    4482             :                                                                &b);
    4483           0 :                         if (!W_ERROR_IS_OK(result)) {
    4484           0 :                                 goto out;
    4485             :                         }
    4486             :                 }
    4487             : 
    4488           0 :                 result = winreg_create_printer(tmp_ctx, b,
    4489             :                                                printer);
    4490           0 :                 if (!W_ERROR_IS_OK(result)) {
    4491           0 :                         goto out;
    4492             :                 }
    4493             : 
    4494           0 :                 info = talloc_realloc(tmp_ctx, info,
    4495             :                                             union spoolss_PrinterInfo,
    4496             :                                             count + 1);
    4497           0 :                 if (!info) {
    4498           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    4499           0 :                         goto out;
    4500             :                 }
    4501             : 
    4502           0 :                 result = winreg_get_printer(tmp_ctx, b,
    4503             :                                             printer, &info2);
    4504           0 :                 if (!W_ERROR_IS_OK(result)) {
    4505           0 :                         goto out;
    4506             :                 }
    4507             : 
    4508           0 :                 switch (level) {
    4509           0 :                 case 0:
    4510           0 :                         result = construct_printer_info0(info, session_info,
    4511             :                                                          msg_ctx, info2,
    4512             :                                                          servername,
    4513           0 :                                                          &info[count].info0, snum);
    4514           0 :                         break;
    4515           0 :                 case 1:
    4516           0 :                         result = construct_printer_info1(info, info2, flags,
    4517             :                                                          servername,
    4518           0 :                                                          &info[count].info1, snum);
    4519           0 :                         break;
    4520           0 :                 case 2:
    4521           0 :                         result = construct_printer_info2(info, msg_ctx, info2,
    4522             :                                                          servername,
    4523           0 :                                                          &info[count].info2, snum);
    4524           0 :                         break;
    4525           0 :                 case 4:
    4526           0 :                         result = construct_printer_info4(info, info2,
    4527             :                                                          servername,
    4528           0 :                                                          &info[count].info4, snum);
    4529           0 :                         break;
    4530           0 :                 case 5:
    4531           0 :                         result = construct_printer_info5(info, info2,
    4532             :                                                          servername,
    4533           0 :                                                          &info[count].info5, snum);
    4534           0 :                         break;
    4535             : 
    4536           0 :                 default:
    4537           0 :                         result = WERR_INVALID_LEVEL;
    4538           0 :                         goto out;
    4539             :                 }
    4540             : 
    4541           0 :                 if (!W_ERROR_IS_OK(result)) {
    4542           0 :                         goto out;
    4543             :                 }
    4544             : 
    4545           0 :                 count++;
    4546             :         }
    4547             : 
    4548           0 : out:
    4549           0 :         if (W_ERROR_IS_OK(result)) {
    4550           0 :                 *info_p = talloc_move(mem_ctx, &info);
    4551           0 :                 *count_p = count;
    4552             :         }
    4553             : 
    4554           0 :         talloc_free(tmp_ctx);
    4555             : 
    4556           0 :         return result;
    4557             : }
    4558             : 
    4559             : /********************************************************************
    4560             :  * handle enumeration of printers at level 0
    4561             :  ********************************************************************/
    4562             : 
    4563           0 : static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
    4564             :                                   const struct auth_session_info *session_info,
    4565             :                                   struct messaging_context *msg_ctx,
    4566             :                                   uint32_t flags,
    4567             :                                   const char *servername,
    4568             :                                   union spoolss_PrinterInfo **info,
    4569             :                                   uint32_t *count)
    4570             : {
    4571           0 :         DEBUG(4,("enum_all_printers_info_0\n"));
    4572             : 
    4573           0 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4574             :                                             servername, 0, flags, info, count);
    4575             : }
    4576             : 
    4577             : 
    4578             : /********************************************************************
    4579             : ********************************************************************/
    4580             : 
    4581           0 : static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
    4582             :                                        const struct auth_session_info *session_info,
    4583             :                                        struct messaging_context *msg_ctx,
    4584             :                                        const char *servername,
    4585             :                                        uint32_t flags,
    4586             :                                        union spoolss_PrinterInfo **info,
    4587             :                                        uint32_t *count)
    4588             : {
    4589           0 :         DEBUG(4,("enum_all_printers_info_1\n"));
    4590             : 
    4591           0 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4592             :                                             servername, 1, flags, info, count);
    4593             : }
    4594             : 
    4595             : /********************************************************************
    4596             :  enum_all_printers_info_1_local.
    4597             : *********************************************************************/
    4598             : 
    4599           0 : static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
    4600             :                                              const struct auth_session_info *session_info,
    4601             :                                              struct messaging_context *msg_ctx,
    4602             :                                              const char *servername,
    4603             :                                              union spoolss_PrinterInfo **info,
    4604             :                                              uint32_t *count)
    4605             : {
    4606           0 :         DEBUG(4,("enum_all_printers_info_1_local\n"));
    4607             : 
    4608           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4609             :                                         servername, PRINTER_ENUM_ICON8, info, count);
    4610             : }
    4611             : 
    4612             : /********************************************************************
    4613             :  enum_all_printers_info_1_name.
    4614             : *********************************************************************/
    4615             : 
    4616           0 : static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
    4617             :                                             const struct auth_session_info *session_info,
    4618             :                                             struct messaging_context *msg_ctx,
    4619             :                                             const char *servername,
    4620             :                                             union spoolss_PrinterInfo **info,
    4621             :                                             uint32_t *count)
    4622             : {
    4623           0 :         const char *s = servername;
    4624             : 
    4625           0 :         DEBUG(4,("enum_all_printers_info_1_name\n"));
    4626             : 
    4627           0 :         if (servername != NULL &&
    4628           0 :             (servername[0] == '\\') && (servername[1] == '\\')) {
    4629           0 :                 s = servername + 2;
    4630             :         }
    4631             : 
    4632           0 :         if (!is_myname_or_ipaddr(s)) {
    4633           0 :                 return WERR_INVALID_NAME;
    4634             :         }
    4635             : 
    4636           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4637             :                                         servername, PRINTER_ENUM_ICON8, info, count);
    4638             : }
    4639             : 
    4640             : /********************************************************************
    4641             :  enum_all_printers_info_1_network.
    4642             : *********************************************************************/
    4643             : 
    4644           0 : static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
    4645             :                                                const struct auth_session_info *session_info,
    4646             :                                                struct messaging_context *msg_ctx,
    4647             :                                                const char *servername,
    4648             :                                                union spoolss_PrinterInfo **info,
    4649             :                                                uint32_t *count)
    4650             : {
    4651           0 :         const char *s = servername;
    4652             : 
    4653           0 :         DEBUG(4,("enum_all_printers_info_1_network\n"));
    4654             : 
    4655             :         /* If we respond to a enum_printers level 1 on our name with flags
    4656             :            set to PRINTER_ENUM_REMOTE with a list of printers then these
    4657             :            printers incorrectly appear in the APW browse list.
    4658             :            Specifically the printers for the server appear at the workgroup
    4659             :            level where all the other servers in the domain are
    4660             :            listed. Windows responds to this call with a
    4661             :            WERR_CAN_NOT_COMPLETE so we should do the same. */
    4662             : 
    4663           0 :         if (servername != NULL &&
    4664           0 :             (servername[0] == '\\') && (servername[1] == '\\')) {
    4665           0 :                  s = servername + 2;
    4666             :         }
    4667             : 
    4668           0 :         if (is_myname_or_ipaddr(s)) {
    4669           0 :                  return WERR_CAN_NOT_COMPLETE;
    4670             :         }
    4671             : 
    4672           0 :         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
    4673             :                                         servername, PRINTER_ENUM_NAME, info, count);
    4674             : }
    4675             : 
    4676             : /********************************************************************
    4677             :  * api_spoolss_enumprinters
    4678             :  *
    4679             :  * called from api_spoolss_enumprinters (see this to understand)
    4680             :  ********************************************************************/
    4681             : 
    4682           0 : static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
    4683             :                                        const struct auth_session_info *session_info,
    4684             :                                        struct messaging_context *msg_ctx,
    4685             :                                        const char *servername,
    4686             :                                        union spoolss_PrinterInfo **info,
    4687             :                                        uint32_t *count)
    4688             : {
    4689           0 :         DEBUG(4,("enum_all_printers_info_2\n"));
    4690             : 
    4691           0 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4692             :                                             servername, 2, 0, info, count);
    4693             : }
    4694             : 
    4695             : /********************************************************************
    4696             :  * handle enumeration of printers at level 1
    4697             :  ********************************************************************/
    4698             : 
    4699           0 : static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
    4700             :                                   const struct auth_session_info *session_info,
    4701             :                                   struct messaging_context *msg_ctx,
    4702             :                                   uint32_t flags,
    4703             :                                   const char *servername,
    4704             :                                   union spoolss_PrinterInfo **info,
    4705             :                                   uint32_t *count)
    4706             : {
    4707             :         /* Not all the flags are equals */
    4708             : 
    4709           0 :         if (flags & PRINTER_ENUM_LOCAL) {
    4710           0 :                 return enum_all_printers_info_1_local(mem_ctx, session_info,
    4711             :                                                       msg_ctx, servername, info, count);
    4712             :         }
    4713             : 
    4714           0 :         if (flags & PRINTER_ENUM_NAME) {
    4715           0 :                 return enum_all_printers_info_1_name(mem_ctx, session_info,
    4716             :                                                      msg_ctx, servername, info,
    4717             :                                                      count);
    4718             :         }
    4719             : 
    4720           0 :         if (flags & PRINTER_ENUM_NETWORK) {
    4721           0 :                 return enum_all_printers_info_1_network(mem_ctx, session_info,
    4722             :                                                         msg_ctx, servername, info,
    4723             :                                                         count);
    4724             :         }
    4725             : 
    4726           0 :         return WERR_OK; /* NT4sp5 does that */
    4727             : }
    4728             : 
    4729             : /********************************************************************
    4730             :  * handle enumeration of printers at level 2
    4731             :  ********************************************************************/
    4732             : 
    4733           0 : static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
    4734             :                                   const struct auth_session_info *session_info,
    4735             :                                   struct messaging_context *msg_ctx,
    4736             :                                   uint32_t flags,
    4737             :                                   const char *servername,
    4738             :                                   union spoolss_PrinterInfo **info,
    4739             :                                   uint32_t *count)
    4740             : {
    4741           0 :         if (flags & PRINTER_ENUM_LOCAL) {
    4742             : 
    4743           0 :                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
    4744             :                                                 servername,
    4745             :                                                 info, count);
    4746             :         }
    4747             : 
    4748           0 :         if (flags & PRINTER_ENUM_NAME) {
    4749           0 :                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
    4750           0 :                         return WERR_INVALID_NAME;
    4751             :                 }
    4752             : 
    4753           0 :                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
    4754             :                                                 servername,
    4755             :                                                 info, count);
    4756             :         }
    4757             : 
    4758           0 :         if (flags & PRINTER_ENUM_REMOTE) {
    4759           0 :                 return WERR_INVALID_LEVEL;
    4760             :         }
    4761             : 
    4762           0 :         return WERR_OK;
    4763             : }
    4764             : 
    4765             : /********************************************************************
    4766             :  * handle enumeration of printers at level 4
    4767             :  ********************************************************************/
    4768             : 
    4769           0 : static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
    4770             :                                   const struct auth_session_info *session_info,
    4771             :                                   struct messaging_context *msg_ctx,
    4772             :                                   uint32_t flags,
    4773             :                                   const char *servername,
    4774             :                                   union spoolss_PrinterInfo **info,
    4775             :                                   uint32_t *count)
    4776             : {
    4777           0 :         DEBUG(4,("enum_all_printers_info_4\n"));
    4778             : 
    4779           0 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4780             :                                             servername, 4, flags, info, count);
    4781             : }
    4782             : 
    4783             : 
    4784             : /********************************************************************
    4785             :  * handle enumeration of printers at level 5
    4786             :  ********************************************************************/
    4787             : 
    4788           0 : static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
    4789             :                                   const struct auth_session_info *session_info,
    4790             :                                   struct messaging_context *msg_ctx,
    4791             :                                   uint32_t flags,
    4792             :                                   const char *servername,
    4793             :                                   union spoolss_PrinterInfo **info,
    4794             :                                   uint32_t *count)
    4795             : {
    4796           0 :         DEBUG(4,("enum_all_printers_info_5\n"));
    4797             : 
    4798           0 :         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
    4799             :                                             servername, 5, flags, info, count);
    4800             : }
    4801             : 
    4802             : /****************************************************************
    4803             :  _spoolss_EnumPrinters
    4804             : ****************************************************************/
    4805             : 
    4806           0 : WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
    4807             :                              struct spoolss_EnumPrinters *r)
    4808             : {
    4809           0 :         const struct auth_session_info *session_info = get_session_info_system();
    4810             :         WERROR result;
    4811             : 
    4812             :         /* that's an [in out] buffer */
    4813             : 
    4814           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    4815           0 :                 return WERR_INVALID_PARAMETER;
    4816             :         }
    4817             : 
    4818           0 :         DEBUG(4,("_spoolss_EnumPrinters\n"));
    4819             : 
    4820           0 :         *r->out.needed = 0;
    4821           0 :         *r->out.count = 0;
    4822           0 :         *r->out.info = NULL;
    4823             : 
    4824             :         /*
    4825             :          * Level 1:
    4826             :          *          flags==PRINTER_ENUM_NAME
    4827             :          *           if name=="" then enumerates all printers
    4828             :          *           if name!="" then enumerate the printer
    4829             :          *          flags==PRINTER_ENUM_REMOTE
    4830             :          *          name is NULL, enumerate printers
    4831             :          * Level 2: name!="" enumerates printers, name can't be NULL
    4832             :          * Level 3: doesn't exist
    4833             :          * Level 4: does a local registry lookup
    4834             :          * Level 5: same as Level 2
    4835             :          */
    4836             : 
    4837           0 :         if (r->in.server && r->in.server[0] == '\0') {
    4838           0 :                 r->in.server = NULL;
    4839             :         }
    4840             : 
    4841           0 :         switch (r->in.level) {
    4842           0 :         case 0:
    4843           0 :                 result = enumprinters_level0(p->mem_ctx, session_info,
    4844             :                                              p->msg_ctx, r->in.flags,
    4845             :                                              r->in.server,
    4846             :                                              r->out.info, r->out.count);
    4847           0 :                 break;
    4848           0 :         case 1:
    4849           0 :                 result = enumprinters_level1(p->mem_ctx, session_info,
    4850             :                                              p->msg_ctx, r->in.flags,
    4851             :                                              r->in.server,
    4852             :                                              r->out.info, r->out.count);
    4853           0 :                 break;
    4854           0 :         case 2:
    4855           0 :                 result = enumprinters_level2(p->mem_ctx, session_info,
    4856             :                                              p->msg_ctx, r->in.flags,
    4857             :                                              r->in.server,
    4858             :                                              r->out.info, r->out.count);
    4859           0 :                 break;
    4860           0 :         case 4:
    4861           0 :                 result = enumprinters_level4(p->mem_ctx, session_info,
    4862             :                                              p->msg_ctx, r->in.flags,
    4863             :                                              r->in.server,
    4864             :                                              r->out.info, r->out.count);
    4865           0 :                 break;
    4866           0 :         case 5:
    4867           0 :                 result = enumprinters_level5(p->mem_ctx, session_info,
    4868             :                                              p->msg_ctx, r->in.flags,
    4869             :                                              r->in.server,
    4870             :                                              r->out.info, r->out.count);
    4871           0 :                 break;
    4872           0 :         default:
    4873           0 :                 return WERR_INVALID_LEVEL;
    4874             :         }
    4875             : 
    4876           0 :         if (!W_ERROR_IS_OK(result)) {
    4877           0 :                 return result;
    4878             :         }
    4879             : 
    4880           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    4881             :                                                      spoolss_EnumPrinters,
    4882             :                                                      *r->out.info, r->in.level,
    4883             :                                                      *r->out.count);
    4884           0 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    4885           0 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    4886             : 
    4887           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    4888             : }
    4889             : 
    4890             : /****************************************************************
    4891             :  _spoolss_GetPrinter
    4892             : ****************************************************************/
    4893             : 
    4894           0 : WERROR _spoolss_GetPrinter(struct pipes_struct *p,
    4895             :                            struct spoolss_GetPrinter *r)
    4896             : {
    4897           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    4898           0 :         struct spoolss_PrinterInfo2 *info2 = NULL;
    4899           0 :         WERROR result = WERR_OK;
    4900             :         int snum;
    4901             : 
    4902             :         /* that's an [in out] buffer */
    4903             : 
    4904           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    4905           0 :                 result = WERR_INVALID_PARAMETER;
    4906           0 :                 goto err_info_free;
    4907             :         }
    4908             : 
    4909           0 :         *r->out.needed = 0;
    4910             : 
    4911           0 :         if (Printer == NULL) {
    4912           0 :                 result = WERR_INVALID_HANDLE;
    4913           0 :                 goto err_info_free;
    4914             :         }
    4915             : 
    4916           0 :         if (Printer->printer_type == SPLHND_SERVER) {
    4917             : 
    4918             :                 struct dcerpc_binding_handle *b;
    4919             : 
    4920           0 :                 if (r->in.level != 3) {
    4921           0 :                         result = WERR_INVALID_LEVEL;
    4922           0 :                         goto err_info_free;
    4923             :                 }
    4924             : 
    4925           0 :                 result = winreg_printer_binding_handle(p->mem_ctx,
    4926             :                                                        get_session_info_system(),
    4927             :                                                        p->msg_ctx,
    4928             :                                                        &b);
    4929           0 :                 if (!W_ERROR_IS_OK(result)) {
    4930           0 :                         goto err_info_free;
    4931             :                 }
    4932             : 
    4933           0 :                 result = winreg_get_printserver_secdesc(p->mem_ctx,
    4934             :                                                         b,
    4935           0 :                                                         &r->out.info->info3.secdesc);
    4936           0 :                 if (!W_ERROR_IS_OK(result)) {
    4937           0 :                         goto err_info_free;
    4938             :                 }
    4939             : 
    4940           0 :                 goto done;
    4941             :         }
    4942             : 
    4943           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    4944           0 :                 result = WERR_INVALID_HANDLE;
    4945           0 :                 goto err_info_free;
    4946             :         }
    4947             : 
    4948           0 :         result = winreg_get_printer_internal(p->mem_ctx,
    4949             :                                     get_session_info_system(),
    4950             :                                     p->msg_ctx,
    4951             :                                     lp_const_servicename(snum),
    4952             :                                     &info2);
    4953           0 :         if (!W_ERROR_IS_OK(result)) {
    4954           0 :                 goto err_info_free;
    4955             :         }
    4956             : 
    4957           0 :         switch (r->in.level) {
    4958           0 :         case 0:
    4959           0 :                 result = construct_printer_info0(p->mem_ctx,
    4960             :                                                  get_session_info_system(),
    4961             :                                                  p->msg_ctx,
    4962             :                                                  info2,
    4963             :                                                  Printer->servername,
    4964           0 :                                                  &r->out.info->info0,
    4965             :                                                  snum);
    4966           0 :                 break;
    4967           0 :         case 1:
    4968           0 :                 result = construct_printer_info1(p->mem_ctx, info2,
    4969             :                                                  PRINTER_ENUM_ICON8,
    4970             :                                                  Printer->servername,
    4971           0 :                                                  &r->out.info->info1, snum);
    4972           0 :                 break;
    4973           0 :         case 2:
    4974           0 :                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
    4975             :                                                  Printer->servername,
    4976           0 :                                                  &r->out.info->info2, snum);
    4977           0 :                 break;
    4978           0 :         case 3:
    4979           0 :                 result = construct_printer_info3(p->mem_ctx, info2,
    4980             :                                                  Printer->servername,
    4981           0 :                                                  &r->out.info->info3, snum);
    4982           0 :                 break;
    4983           0 :         case 4:
    4984           0 :                 result = construct_printer_info4(p->mem_ctx, info2,
    4985             :                                                  Printer->servername,
    4986           0 :                                                  &r->out.info->info4, snum);
    4987           0 :                 break;
    4988           0 :         case 5:
    4989           0 :                 result = construct_printer_info5(p->mem_ctx, info2,
    4990             :                                                  Printer->servername,
    4991           0 :                                                  &r->out.info->info5, snum);
    4992           0 :                 break;
    4993           0 :         case 6:
    4994           0 :                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
    4995             :                                                  Printer->servername,
    4996           0 :                                                  &r->out.info->info6, snum);
    4997           0 :                 break;
    4998           0 :         case 7:
    4999           0 :                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
    5000             :                                                  Printer->servername,
    5001           0 :                                                  &r->out.info->info7, snum);
    5002           0 :                 break;
    5003           0 :         case 8:
    5004           0 :                 result = construct_printer_info8(p->mem_ctx, info2,
    5005             :                                                  Printer->servername,
    5006           0 :                                                  &r->out.info->info8, snum);
    5007           0 :                 break;
    5008           0 :         default:
    5009           0 :                 result = WERR_INVALID_LEVEL;
    5010           0 :                 break;
    5011             :         }
    5012           0 :         TALLOC_FREE(info2);
    5013             : 
    5014           0 :         if (!W_ERROR_IS_OK(result)) {
    5015           0 :                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
    5016             :                           r->in.level, win_errstr(result)));
    5017           0 :                 goto err_info_free;
    5018             :         }
    5019           0 :  done:
    5020           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
    5021             :                                                r->out.info, r->in.level);
    5022           0 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    5023             : 
    5024           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    5025             : 
    5026           0 : err_info_free:
    5027           0 :         TALLOC_FREE(r->out.info);
    5028           0 :         return result;
    5029             : }
    5030             : 
    5031             : /********************************************************************
    5032             :  ********************************************************************/
    5033             : 
    5034             : #define FILL_DRIVER_STRING(mem_ctx, in, out) \
    5035             :         do { \
    5036             :                 if (in && strlen(in)) { \
    5037             :                         out = talloc_strdup(mem_ctx, in); \
    5038             :                 } else { \
    5039             :                         out = talloc_strdup(mem_ctx, ""); \
    5040             :                 } \
    5041             :                 W_ERROR_HAVE_NO_MEMORY(out); \
    5042             :         } while (0);
    5043             : 
    5044             : #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
    5045             :         do { \
    5046             :                 if (in && strlen(in)) { \
    5047             :                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
    5048             :                 } else { \
    5049             :                         out = talloc_strdup(mem_ctx, ""); \
    5050             :                 } \
    5051             :                 W_ERROR_HAVE_NO_MEMORY(out); \
    5052             :         } while (0);
    5053             : 
    5054           0 : static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
    5055             :                                                   const char **string_array,
    5056             :                                                   const char ***presult,
    5057             :                                                   const char *cservername,
    5058             :                                                   const char *arch,
    5059             :                                                   int version)
    5060             : {
    5061             :         size_t i;
    5062           0 :         size_t num_strings = 0;
    5063           0 :         const char **array = NULL;
    5064             : 
    5065           0 :         if (string_array == NULL) {
    5066           0 :                 return WERR_INVALID_PARAMETER;
    5067             :         }
    5068             : 
    5069           0 :         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
    5070           0 :                 const char *str = NULL;
    5071             : 
    5072           0 :                 if (cservername == NULL || arch == NULL) {
    5073           0 :                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
    5074             :                 } else {
    5075           0 :                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
    5076             :                 }
    5077             : 
    5078           0 :                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
    5079           0 :                         TALLOC_FREE(array);
    5080           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    5081             :                 }
    5082             :         }
    5083             : 
    5084           0 :         if (i > 0) {
    5085           0 :                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
    5086             :                              &array, &num_strings);
    5087             :         }
    5088             : 
    5089           0 :         if (presult != NULL) {
    5090           0 :                 *presult = array;
    5091             :         } else {
    5092           0 :                 talloc_free(array);
    5093             :         }
    5094             : 
    5095           0 :         return WERR_OK;
    5096             : }
    5097             : 
    5098             : /********************************************************************
    5099             :  * fill a spoolss_DriverInfo1 struct
    5100             :  ********************************************************************/
    5101             : 
    5102           0 : static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
    5103             :                                         struct spoolss_DriverInfo1 *r,
    5104             :                                         const struct spoolss_DriverInfo8 *driver,
    5105             :                                         const char *servername)
    5106             : {
    5107           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5108           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5109             : 
    5110           0 :         return WERR_OK;
    5111             : }
    5112             : 
    5113             : /********************************************************************
    5114             :  * fill a spoolss_DriverInfo2 struct
    5115             :  ********************************************************************/
    5116             : 
    5117           0 : static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
    5118             :                                         struct spoolss_DriverInfo2 *r,
    5119             :                                         const struct spoolss_DriverInfo8 *driver,
    5120             :                                         const char *servername)
    5121             : 
    5122             : {
    5123           0 :         const char *cservername = canon_servername(servername);
    5124             : 
    5125           0 :         r->version           = driver->version;
    5126             : 
    5127           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5128           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5129           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5130           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5131             : 
    5132           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5133             :                                driver->architecture,
    5134             :                                driver->version,
    5135             :                                driver->driver_path,
    5136             :                                r->driver_path);
    5137             : 
    5138           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5139             :                                driver->architecture,
    5140             :                                driver->version,
    5141             :                                driver->data_file,
    5142             :                                r->data_file);
    5143             : 
    5144           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5145             :                                driver->architecture,
    5146             :                                driver->version,
    5147             :                                driver->config_file,
    5148             :                                r->config_file);
    5149             : 
    5150           0 :         return WERR_OK;
    5151             : }
    5152             : 
    5153             : /********************************************************************
    5154             :  * fill a spoolss_DriverInfo3 struct
    5155             :  ********************************************************************/
    5156             : 
    5157           0 : static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
    5158             :                                         struct spoolss_DriverInfo3 *r,
    5159             :                                         const struct spoolss_DriverInfo8 *driver,
    5160             :                                         const char *servername)
    5161             : {
    5162           0 :         const char *cservername = canon_servername(servername);
    5163             : 
    5164           0 :         r->version           = driver->version;
    5165             : 
    5166           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5167           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5168           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5169           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5170             : 
    5171           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5172             :                                driver->architecture,
    5173             :                                driver->version,
    5174             :                                driver->driver_path,
    5175             :                                r->driver_path);
    5176             : 
    5177           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5178             :                                driver->architecture,
    5179             :                                driver->version,
    5180             :                                driver->data_file,
    5181             :                                r->data_file);
    5182             : 
    5183           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5184             :                                driver->architecture,
    5185             :                                driver->version,
    5186             :                                driver->config_file,
    5187             :                                r->config_file);
    5188             : 
    5189           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5190             :                                driver->architecture,
    5191             :                                driver->version,
    5192             :                                driver->help_file,
    5193             :                                r->help_file);
    5194             : 
    5195           0 :         FILL_DRIVER_STRING(mem_ctx,
    5196             :                            driver->monitor_name,
    5197             :                            r->monitor_name);
    5198             : 
    5199           0 :         FILL_DRIVER_STRING(mem_ctx,
    5200             :                            driver->default_datatype,
    5201             :                            r->default_datatype);
    5202             : 
    5203           0 :         return string_array_from_driver_info(mem_ctx,
    5204           0 :                                              driver->dependent_files,
    5205             :                                              &r->dependent_files,
    5206             :                                              cservername,
    5207           0 :                                              driver->architecture,
    5208           0 :                                              driver->version);
    5209             : }
    5210             : 
    5211             : /********************************************************************
    5212             :  * fill a spoolss_DriverInfo4 struct
    5213             :  ********************************************************************/
    5214             : 
    5215           0 : static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
    5216             :                                         struct spoolss_DriverInfo4 *r,
    5217             :                                         const struct spoolss_DriverInfo8 *driver,
    5218             :                                         const char *servername)
    5219             : {
    5220           0 :         const char *cservername = canon_servername(servername);
    5221             :         WERROR result;
    5222             : 
    5223           0 :         r->version           = driver->version;
    5224             : 
    5225           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5226           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5227           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5228           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5229             : 
    5230           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5231             :                                driver->architecture,
    5232             :                                driver->version,
    5233             :                                driver->driver_path,
    5234             :                                r->driver_path);
    5235             : 
    5236           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5237             :                                driver->architecture,
    5238             :                                driver->version,
    5239             :                                driver->data_file,
    5240             :                                r->data_file);
    5241             : 
    5242           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5243             :                                driver->architecture,
    5244             :                                driver->version,
    5245             :                                driver->config_file,
    5246             :                                r->config_file);
    5247             : 
    5248           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5249             :                                driver->architecture,
    5250             :                                driver->version,
    5251             :                                driver->help_file,
    5252             :                                r->help_file);
    5253             : 
    5254           0 :         result = string_array_from_driver_info(mem_ctx,
    5255           0 :                                                driver->dependent_files,
    5256             :                                                &r->dependent_files,
    5257             :                                                cservername,
    5258           0 :                                                driver->architecture,
    5259           0 :                                                driver->version);
    5260           0 :         if (!W_ERROR_IS_OK(result)) {
    5261           0 :                 return result;
    5262             :         }
    5263             : 
    5264           0 :         FILL_DRIVER_STRING(mem_ctx,
    5265             :                            driver->monitor_name,
    5266             :                            r->monitor_name);
    5267             : 
    5268           0 :         FILL_DRIVER_STRING(mem_ctx,
    5269             :                            driver->default_datatype,
    5270             :                            r->default_datatype);
    5271             : 
    5272             : 
    5273           0 :         result = string_array_from_driver_info(mem_ctx,
    5274           0 :                                                driver->previous_names,
    5275             :                                                &r->previous_names,
    5276             :                                                NULL, NULL, 0);
    5277             : 
    5278           0 :         return result;
    5279             : }
    5280             : 
    5281             : /********************************************************************
    5282             :  * fill a spoolss_DriverInfo5 struct
    5283             :  ********************************************************************/
    5284             : 
    5285           0 : static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
    5286             :                                         struct spoolss_DriverInfo5 *r,
    5287             :                                         const struct spoolss_DriverInfo8 *driver,
    5288             :                                         const char *servername)
    5289             : {
    5290           0 :         const char *cservername = canon_servername(servername);
    5291             : 
    5292           0 :         r->version           = driver->version;
    5293             : 
    5294           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5295           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5296           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5297           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5298             : 
    5299           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5300             :                                driver->architecture,
    5301             :                                driver->version,
    5302             :                                driver->driver_path,
    5303             :                                r->driver_path);
    5304             : 
    5305           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5306             :                                driver->architecture,
    5307             :                                driver->version,
    5308             :                                driver->data_file,
    5309             :                                r->data_file);
    5310             : 
    5311           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5312             :                                driver->architecture,
    5313             :                                driver->version,
    5314             :                                driver->config_file,
    5315             :                                r->config_file);
    5316             : 
    5317           0 :         r->driver_attributes = 0;
    5318           0 :         r->config_version    = 0;
    5319           0 :         r->driver_version    = 0;
    5320             : 
    5321           0 :         return WERR_OK;
    5322             : }
    5323             : /********************************************************************
    5324             :  * fill a spoolss_DriverInfo6 struct
    5325             :  ********************************************************************/
    5326             : 
    5327           0 : static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
    5328             :                                         struct spoolss_DriverInfo6 *r,
    5329             :                                         const struct spoolss_DriverInfo8 *driver,
    5330             :                                         const char *servername)
    5331             : {
    5332           0 :         const char *cservername = canon_servername(servername);
    5333             :         WERROR result;
    5334             : 
    5335           0 :         r->version           = driver->version;
    5336             : 
    5337           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5338           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5339           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5340           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5341             : 
    5342           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5343             :                                driver->architecture,
    5344             :                                driver->version,
    5345             :                                driver->driver_path,
    5346             :                                r->driver_path);
    5347             : 
    5348           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5349             :                                driver->architecture,
    5350             :                                driver->version,
    5351             :                                driver->data_file,
    5352             :                                r->data_file);
    5353             : 
    5354           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5355             :                                driver->architecture,
    5356             :                                driver->version,
    5357             :                                driver->config_file,
    5358             :                                r->config_file);
    5359             : 
    5360           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5361             :                                driver->architecture,
    5362             :                                driver->version,
    5363             :                                driver->help_file,
    5364             :                                r->help_file);
    5365             : 
    5366           0 :         FILL_DRIVER_STRING(mem_ctx,
    5367             :                            driver->monitor_name,
    5368             :                            r->monitor_name);
    5369             : 
    5370           0 :         FILL_DRIVER_STRING(mem_ctx,
    5371             :                            driver->default_datatype,
    5372             :                            r->default_datatype);
    5373             : 
    5374           0 :         result = string_array_from_driver_info(mem_ctx,
    5375           0 :                                                driver->dependent_files,
    5376             :                                                &r->dependent_files,
    5377             :                                                cservername,
    5378           0 :                                                driver->architecture,
    5379           0 :                                                driver->version);
    5380           0 :         if (!W_ERROR_IS_OK(result)) {
    5381           0 :                 return result;
    5382             :         }
    5383             : 
    5384           0 :         result = string_array_from_driver_info(mem_ctx,
    5385           0 :                                                driver->previous_names,
    5386             :                                                &r->previous_names,
    5387             :                                                NULL, NULL, 0);
    5388           0 :         if (!W_ERROR_IS_OK(result)) {
    5389           0 :                 return result;
    5390             :         }
    5391             : 
    5392           0 :         r->driver_date               = driver->driver_date;
    5393           0 :         r->driver_version    = driver->driver_version;
    5394             : 
    5395           0 :         FILL_DRIVER_STRING(mem_ctx,
    5396             :                            driver->manufacturer_name,
    5397             :                            r->manufacturer_name);
    5398           0 :         FILL_DRIVER_STRING(mem_ctx,
    5399             :                            driver->manufacturer_url,
    5400             :                            r->manufacturer_url);
    5401           0 :         FILL_DRIVER_STRING(mem_ctx,
    5402             :                            driver->hardware_id,
    5403             :                            r->hardware_id);
    5404           0 :         FILL_DRIVER_STRING(mem_ctx,
    5405             :                            driver->provider,
    5406             :                            r->provider);
    5407             : 
    5408           0 :         return WERR_OK;
    5409             : }
    5410             : 
    5411             : /********************************************************************
    5412             :  * fill a spoolss_DriverInfo8 struct
    5413             :  ********************************************************************/
    5414             : 
    5415           0 : static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
    5416             :                                         struct spoolss_DriverInfo8 *r,
    5417             :                                         const struct spoolss_DriverInfo8 *driver,
    5418             :                                         const char *servername)
    5419             : {
    5420           0 :         const char *cservername = canon_servername(servername);
    5421             :         WERROR result;
    5422             : 
    5423           0 :         r->version           = driver->version;
    5424             : 
    5425           0 :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5426           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5427           0 :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5428           0 :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5429             : 
    5430           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5431             :                                driver->architecture,
    5432             :                                driver->version,
    5433             :                                driver->driver_path,
    5434             :                                r->driver_path);
    5435             : 
    5436           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5437             :                                driver->architecture,
    5438             :                                driver->version,
    5439             :                                driver->data_file,
    5440             :                                r->data_file);
    5441             : 
    5442           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5443             :                                driver->architecture,
    5444             :                                driver->version,
    5445             :                                driver->config_file,
    5446             :                                r->config_file);
    5447             : 
    5448           0 :         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
    5449             :                                driver->architecture,
    5450             :                                driver->version,
    5451             :                                driver->help_file,
    5452             :                                r->help_file);
    5453             : 
    5454           0 :         FILL_DRIVER_STRING(mem_ctx,
    5455             :                            driver->monitor_name,
    5456             :                            r->monitor_name);
    5457             : 
    5458           0 :         FILL_DRIVER_STRING(mem_ctx,
    5459             :                            driver->default_datatype,
    5460             :                            r->default_datatype);
    5461             : 
    5462           0 :         result = string_array_from_driver_info(mem_ctx,
    5463           0 :                                                driver->dependent_files,
    5464             :                                                &r->dependent_files,
    5465             :                                                cservername,
    5466           0 :                                                driver->architecture,
    5467           0 :                                                driver->version);
    5468           0 :         if (!W_ERROR_IS_OK(result)) {
    5469           0 :                 return result;
    5470             :         }
    5471             : 
    5472           0 :         result = string_array_from_driver_info(mem_ctx,
    5473           0 :                                                driver->previous_names,
    5474             :                                                &r->previous_names,
    5475             :                                                NULL, NULL, 0);
    5476           0 :         if (!W_ERROR_IS_OK(result)) {
    5477           0 :                 return result;
    5478             :         }
    5479             : 
    5480           0 :         r->driver_date               = driver->driver_date;
    5481           0 :         r->driver_version    = driver->driver_version;
    5482             : 
    5483           0 :         FILL_DRIVER_STRING(mem_ctx,
    5484             :                            driver->manufacturer_name,
    5485             :                            r->manufacturer_name);
    5486           0 :         FILL_DRIVER_STRING(mem_ctx,
    5487             :                            driver->manufacturer_url,
    5488             :                            r->manufacturer_url);
    5489           0 :         FILL_DRIVER_STRING(mem_ctx,
    5490             :                            driver->hardware_id,
    5491             :                            r->hardware_id);
    5492           0 :         FILL_DRIVER_STRING(mem_ctx,
    5493             :                            driver->provider,
    5494             :                            r->provider);
    5495             : 
    5496           0 :         FILL_DRIVER_STRING(mem_ctx,
    5497             :                            driver->print_processor,
    5498             :                            r->print_processor);
    5499           0 :         FILL_DRIVER_STRING(mem_ctx,
    5500             :                            driver->vendor_setup,
    5501             :                            r->vendor_setup);
    5502             : 
    5503           0 :         result = string_array_from_driver_info(mem_ctx,
    5504           0 :                                                driver->color_profiles,
    5505             :                                                &r->color_profiles,
    5506             :                                                NULL, NULL, 0);
    5507           0 :         if (!W_ERROR_IS_OK(result)) {
    5508           0 :                 return result;
    5509             :         }
    5510             : 
    5511           0 :         FILL_DRIVER_STRING(mem_ctx,
    5512             :                            driver->inf_path,
    5513             :                            r->inf_path);
    5514             : 
    5515           0 :         r->printer_driver_attributes = driver->printer_driver_attributes;
    5516             : 
    5517           0 :         result = string_array_from_driver_info(mem_ctx,
    5518           0 :                                                driver->core_driver_dependencies,
    5519             :                                                &r->core_driver_dependencies,
    5520             :                                                NULL, NULL, 0);
    5521           0 :         if (!W_ERROR_IS_OK(result)) {
    5522           0 :                 return result;
    5523             :         }
    5524             : 
    5525           0 :         r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
    5526           0 :         r->min_inbox_driver_ver_version      = driver->min_inbox_driver_ver_version;
    5527             : 
    5528           0 :         return WERR_OK;
    5529             : }
    5530             : 
    5531             : #if 0 /* disabled until marshalling issues are resolved - gd */
    5532             : /********************************************************************
    5533             :  ********************************************************************/
    5534             : 
    5535             : static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
    5536             :                                           struct spoolss_DriverFileInfo *r,
    5537             :                                           const char *cservername,
    5538             :                                           const char *file_name,
    5539             :                                           enum spoolss_DriverFileType file_type,
    5540             :                                           uint32_t file_version)
    5541             : {
    5542             :         r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
    5543             :                                           cservername, file_name);
    5544             :         W_ERROR_HAVE_NO_MEMORY(r->file_name);
    5545             :         r->file_type = file_type;
    5546             :         r->file_version      = file_version;
    5547             : 
    5548             :         return WERR_OK;
    5549             : }
    5550             : 
    5551             : /********************************************************************
    5552             :  ********************************************************************/
    5553             : 
    5554             : static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
    5555             :                                                  const struct spoolss_DriverInfo8 *driver,
    5556             :                                                  const char *cservername,
    5557             :                                                  struct spoolss_DriverFileInfo **info_p,
    5558             :                                                  uint32_t *count_p)
    5559             : {
    5560             :         struct spoolss_DriverFileInfo *info = NULL;
    5561             :         uint32_t count = 0;
    5562             :         WERROR result;
    5563             :         uint32_t i;
    5564             : 
    5565             :         *info_p = NULL;
    5566             :         *count_p = 0;
    5567             : 
    5568             :         if (strlen(driver->driver_path)) {
    5569             :                 info = talloc_realloc(mem_ctx, info,
    5570             :                                             struct spoolss_DriverFileInfo,
    5571             :                                             count + 1);
    5572             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5573             :                 result = fill_spoolss_DriverFileInfo(info,
    5574             :                                                      &info[count],
    5575             :                                                      cservername,
    5576             :                                                      driver->driver_path,
    5577             :                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
    5578             :                                                      0);
    5579             :                 W_ERROR_NOT_OK_RETURN(result);
    5580             :                 count++;
    5581             :         }
    5582             : 
    5583             :         if (strlen(driver->config_file)) {
    5584             :                 info = talloc_realloc(mem_ctx, info,
    5585             :                                             struct spoolss_DriverFileInfo,
    5586             :                                             count + 1);
    5587             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5588             :                 result = fill_spoolss_DriverFileInfo(info,
    5589             :                                                      &info[count],
    5590             :                                                      cservername,
    5591             :                                                      driver->config_file,
    5592             :                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
    5593             :                                                      0);
    5594             :                 W_ERROR_NOT_OK_RETURN(result);
    5595             :                 count++;
    5596             :         }
    5597             : 
    5598             :         if (strlen(driver->data_file)) {
    5599             :                 info = talloc_realloc(mem_ctx, info,
    5600             :                                             struct spoolss_DriverFileInfo,
    5601             :                                             count + 1);
    5602             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5603             :                 result = fill_spoolss_DriverFileInfo(info,
    5604             :                                                      &info[count],
    5605             :                                                      cservername,
    5606             :                                                      driver->data_file,
    5607             :                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
    5608             :                                                      0);
    5609             :                 W_ERROR_NOT_OK_RETURN(result);
    5610             :                 count++;
    5611             :         }
    5612             : 
    5613             :         if (strlen(driver->help_file)) {
    5614             :                 info = talloc_realloc(mem_ctx, info,
    5615             :                                             struct spoolss_DriverFileInfo,
    5616             :                                             count + 1);
    5617             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5618             :                 result = fill_spoolss_DriverFileInfo(info,
    5619             :                                                      &info[count],
    5620             :                                                      cservername,
    5621             :                                                      driver->help_file,
    5622             :                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
    5623             :                                                      0);
    5624             :                 W_ERROR_NOT_OK_RETURN(result);
    5625             :                 count++;
    5626             :         }
    5627             : 
    5628             :         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
    5629             :                 info = talloc_realloc(mem_ctx, info,
    5630             :                                             struct spoolss_DriverFileInfo,
    5631             :                                             count + 1);
    5632             :                 W_ERROR_HAVE_NO_MEMORY(info);
    5633             :                 result = fill_spoolss_DriverFileInfo(info,
    5634             :                                                      &info[count],
    5635             :                                                      cservername,
    5636             :                                                      driver->dependent_files[i],
    5637             :                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
    5638             :                                                      0);
    5639             :                 W_ERROR_NOT_OK_RETURN(result);
    5640             :                 count++;
    5641             :         }
    5642             : 
    5643             :         *info_p = info;
    5644             :         *count_p = count;
    5645             : 
    5646             :         return WERR_OK;
    5647             : }
    5648             : 
    5649             : /********************************************************************
    5650             :  * fill a spoolss_DriverInfo101 struct
    5651             :  ********************************************************************/
    5652             : 
    5653             : static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
    5654             :                                           struct spoolss_DriverInfo101 *r,
    5655             :                                           const struct spoolss_DriverInfo8 *driver,
    5656             :                                           const char *servername)
    5657             : {
    5658             :         const char *cservername = canon_servername(servername);
    5659             :         WERROR result;
    5660             : 
    5661             :         r->version           = driver->version;
    5662             : 
    5663             :         r->driver_name               = talloc_strdup(mem_ctx, driver->driver_name);
    5664             :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    5665             :         r->architecture              = talloc_strdup(mem_ctx, driver->architecture);
    5666             :         W_ERROR_HAVE_NO_MEMORY(r->architecture);
    5667             : 
    5668             :         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
    5669             :                                                     cservername,
    5670             :                                                     &r->file_info,
    5671             :                                                     &r->file_count);
    5672             :         if (!W_ERROR_IS_OK(result)) {
    5673             :                 return result;
    5674             :         }
    5675             : 
    5676             :         FILL_DRIVER_STRING(mem_ctx,
    5677             :                            driver->monitor_name,
    5678             :                            r->monitor_name);
    5679             : 
    5680             :         FILL_DRIVER_STRING(mem_ctx,
    5681             :                            driver->default_datatype,
    5682             :                            r->default_datatype);
    5683             : 
    5684             :         result = string_array_from_driver_info(mem_ctx,
    5685             :                                                driver->previous_names,
    5686             :                                                &r->previous_names,
    5687             :                                                NULL, NULL, 0);
    5688             :         if (!W_ERROR_IS_OK(result)) {
    5689             :                 return result;
    5690             :         }
    5691             : 
    5692             :         r->driver_date               = driver->driver_date;
    5693             :         r->driver_version    = driver->driver_version;
    5694             : 
    5695             :         FILL_DRIVER_STRING(mem_ctx,
    5696             :                            driver->manufacturer_name,
    5697             :                            r->manufacturer_name);
    5698             :         FILL_DRIVER_STRING(mem_ctx,
    5699             :                            driver->manufacturer_url,
    5700             :                            r->manufacturer_url);
    5701             :         FILL_DRIVER_STRING(mem_ctx,
    5702             :                            driver->hardware_id,
    5703             :                            r->hardware_id);
    5704             :         FILL_DRIVER_STRING(mem_ctx,
    5705             :                            driver->provider,
    5706             :                            r->provider);
    5707             : 
    5708             :         return WERR_OK;
    5709             : }
    5710             : #endif
    5711             : /********************************************************************
    5712             :  ********************************************************************/
    5713             : 
    5714           0 : static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
    5715             :                                                   const struct auth_session_info *session_info,
    5716             :                                                   struct messaging_context *msg_ctx,
    5717             :                                                   uint32_t level,
    5718             :                                                   union spoolss_DriverInfo *r,
    5719             :                                                   int snum,
    5720             :                                                   const char *servername,
    5721             :                                                   const char *architecture,
    5722             :                                                   uint32_t version)
    5723             : {
    5724           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    5725             :         struct spoolss_DriverInfo8 *driver;
    5726             :         WERROR result;
    5727             :         struct dcerpc_binding_handle *b;
    5728           0 :         TALLOC_CTX *tmp_ctx = NULL;
    5729             : 
    5730           0 :         if (level == 101) {
    5731           0 :                 return WERR_INVALID_LEVEL;
    5732             :         }
    5733             : 
    5734           0 :         tmp_ctx = talloc_new(mem_ctx);
    5735           0 :         if (!tmp_ctx) {
    5736           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    5737             :         }
    5738             : 
    5739           0 :         result = winreg_printer_binding_handle(tmp_ctx,
    5740             :                                                session_info,
    5741             :                                                msg_ctx,
    5742             :                                                &b);
    5743           0 :         if (!W_ERROR_IS_OK(result)) {
    5744           0 :                 goto done;
    5745             :         }
    5746             : 
    5747           0 :         result = winreg_get_printer(tmp_ctx, b,
    5748             :                                     lp_const_servicename(snum),
    5749             :                                     &pinfo2);
    5750           0 :         if (!W_ERROR_IS_OK(result)) {
    5751           0 :                 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
    5752             :                         lp_const_servicename(snum), win_errstr(result));
    5753           0 :                 result = WERR_INVALID_PRINTER_NAME;
    5754           0 :                 goto done;
    5755             :         }
    5756             : 
    5757           0 :         if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
    5758           0 :                 result = WERR_UNKNOWN_PRINTER_DRIVER;
    5759           0 :                 goto done;
    5760             :         }
    5761             : 
    5762           0 :         DBG_INFO("Construct printer driver [%s] for [%s]\n",
    5763             :                  pinfo2->drivername,
    5764             :                  pinfo2->sharename);
    5765             : 
    5766           0 :         result = winreg_get_driver(tmp_ctx, b,
    5767             :                                    architecture,
    5768           0 :                                    pinfo2->drivername, version, &driver);
    5769             : 
    5770           0 :         DBG_INFO("winreg_get_driver() status: %s\n",
    5771             :                  win_errstr(result));
    5772             : 
    5773           0 :         if (!W_ERROR_IS_OK(result)) {
    5774             :                 /*
    5775             :                  * Is this a W2k client ?
    5776             :                  */
    5777             : 
    5778           0 :                 if (version < 3) {
    5779           0 :                         result = WERR_UNKNOWN_PRINTER_DRIVER;
    5780           0 :                         goto done;
    5781             :                 }
    5782             : 
    5783             :                 /* Yes - try again with a WinNT driver. */
    5784           0 :                 version = 2;
    5785           0 :                 result = winreg_get_driver(tmp_ctx, b,
    5786             :                                            architecture,
    5787           0 :                                            pinfo2->drivername,
    5788             :                                            version, &driver);
    5789           0 :                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
    5790             :                         win_errstr(result)));
    5791           0 :                 if (!W_ERROR_IS_OK(result)) {
    5792           0 :                         result = WERR_UNKNOWN_PRINTER_DRIVER;
    5793           0 :                         goto done;
    5794             :                 }
    5795             :         }
    5796             : 
    5797             :         /* these are allocated on mem_ctx and not tmp_ctx because they are
    5798             :          * the 'return value' and need to utlive this call */
    5799           0 :         switch (level) {
    5800           0 :         case 1:
    5801           0 :                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
    5802           0 :                 break;
    5803           0 :         case 2:
    5804           0 :                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
    5805           0 :                 break;
    5806           0 :         case 3:
    5807           0 :                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
    5808           0 :                 break;
    5809           0 :         case 4:
    5810           0 :                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
    5811           0 :                 break;
    5812           0 :         case 5:
    5813           0 :                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
    5814           0 :                 break;
    5815           0 :         case 6:
    5816           0 :                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
    5817           0 :                 break;
    5818           0 :         case 8:
    5819           0 :                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
    5820           0 :                 break;
    5821             : #if 0 /* disabled until marshalling issues are resolved - gd */
    5822             :         case 101:
    5823             :                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
    5824             :                 break;
    5825             : #endif
    5826           0 :         default:
    5827           0 :                 result = WERR_INVALID_LEVEL;
    5828           0 :                 break;
    5829             :         }
    5830             : 
    5831           0 : done:
    5832           0 :         talloc_free(tmp_ctx);
    5833           0 :         return result;
    5834             : }
    5835             : 
    5836             : /****************************************************************
    5837             :  _spoolss_GetPrinterDriver2
    5838             : ****************************************************************/
    5839             : 
    5840           0 : WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
    5841             :                                   struct spoolss_GetPrinterDriver2 *r)
    5842             : {
    5843             :         struct printer_handle *printer;
    5844             :         WERROR result;
    5845           0 :         uint32_t version = r->in.client_major_version;
    5846             : 
    5847             :         int snum;
    5848             : 
    5849             :         /* that's an [in out] buffer */
    5850             : 
    5851           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    5852           0 :                 result = WERR_INVALID_PARAMETER;
    5853           0 :                 goto err_info_free;
    5854             :         }
    5855             : 
    5856           0 :         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
    5857             : 
    5858           0 :         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
    5859           0 :                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
    5860           0 :                 result = WERR_INVALID_PRINTER_NAME;
    5861           0 :                 goto err_info_free;
    5862             :         }
    5863             : 
    5864           0 :         *r->out.needed = 0;
    5865           0 :         *r->out.server_major_version = 0;
    5866           0 :         *r->out.server_minor_version = 0;
    5867             : 
    5868           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    5869           0 :                 result = WERR_INVALID_HANDLE;
    5870           0 :                 goto err_info_free;
    5871             :         }
    5872             : 
    5873           0 :         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
    5874           0 :                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
    5875             :                         "downgrading to v3\n"));
    5876           0 :                 version = SPOOLSS_DRIVER_VERSION_200X;
    5877             :         }
    5878             : 
    5879           0 :         result = construct_printer_driver_info_level(p->mem_ctx,
    5880             :                                                      get_session_info_system(),
    5881             :                                                      p->msg_ctx,
    5882             :                                                      r->in.level, r->out.info,
    5883             :                                                      snum, printer->servername,
    5884             :                                                      r->in.architecture,
    5885             :                                                      version);
    5886           0 :         if (!W_ERROR_IS_OK(result)) {
    5887           0 :                 goto err_info_free;
    5888             :         }
    5889             : 
    5890           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
    5891             :                                                r->out.info, r->in.level);
    5892           0 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    5893             : 
    5894           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    5895             : 
    5896           0 : err_info_free:
    5897           0 :         TALLOC_FREE(r->out.info);
    5898           0 :         return result;
    5899             : }
    5900             : 
    5901             : 
    5902             : /****************************************************************
    5903             :  _spoolss_StartPagePrinter
    5904             : ****************************************************************/
    5905             : 
    5906           0 : WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
    5907             :                                  struct spoolss_StartPagePrinter *r)
    5908             : {
    5909           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5910             : 
    5911           0 :         if (!Printer) {
    5912           0 :                 DEBUG(3,("_spoolss_StartPagePrinter: "
    5913             :                         "Error in startpageprinter printer handle\n"));
    5914           0 :                 return WERR_INVALID_HANDLE;
    5915             :         }
    5916             : 
    5917           0 :         Printer->page_started = true;
    5918           0 :         return WERR_OK;
    5919             : }
    5920             : 
    5921             : /****************************************************************
    5922             :  _spoolss_EndPagePrinter
    5923             : ****************************************************************/
    5924             : 
    5925           0 : WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
    5926             :                                struct spoolss_EndPagePrinter *r)
    5927             : {
    5928             :         int snum;
    5929             : 
    5930           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5931             : 
    5932           0 :         if (!Printer) {
    5933           0 :                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
    5934             :                         OUR_HANDLE(r->in.handle)));
    5935           0 :                 return WERR_INVALID_HANDLE;
    5936             :         }
    5937             : 
    5938           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    5939           0 :                 return WERR_INVALID_HANDLE;
    5940             : 
    5941           0 :         Printer->page_started = false;
    5942           0 :         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
    5943             : 
    5944           0 :         return WERR_OK;
    5945             : }
    5946             : 
    5947             : /****************************************************************
    5948             :  _spoolss_StartDocPrinter
    5949             : ****************************************************************/
    5950             : 
    5951           0 : WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
    5952             :                                 struct spoolss_StartDocPrinter *r)
    5953             : {
    5954           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    5955           0 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    5956           0 :         const struct tsocket_address *remote_address =
    5957           0 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    5958           0 :         struct auth_session_info *session_info =
    5959           0 :                 dcesrv_call_session_info(dce_call);
    5960             :         struct spoolss_DocumentInfo1 *info_1;
    5961             :         int snum;
    5962           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    5963             :         WERROR werr;
    5964             :         char *rhost;
    5965             :         int rc;
    5966             : 
    5967           0 :         if (!Printer) {
    5968           0 :                 DEBUG(2,("_spoolss_StartDocPrinter: "
    5969             :                         "Invalid handle (%s:%u:%u)\n",
    5970             :                         OUR_HANDLE(r->in.handle)));
    5971           0 :                 return WERR_INVALID_HANDLE;
    5972             :         }
    5973             : 
    5974           0 :         if (Printer->jobid) {
    5975           0 :                 DEBUG(2, ("_spoolss_StartDocPrinter: "
    5976             :                           "StartDocPrinter called twice! "
    5977             :                           "(existing jobid = %d)\n", Printer->jobid));
    5978           0 :                 return WERR_INVALID_HANDLE;
    5979             :         }
    5980             : 
    5981           0 :         if (r->in.info_ctr->level != 1) {
    5982           0 :                 return WERR_INVALID_LEVEL;
    5983             :         }
    5984             : 
    5985           0 :         info_1 = r->in.info_ctr->info.info1;
    5986             : 
    5987             :         /*
    5988             :          * a nice thing with NT is it doesn't listen to what you tell it.
    5989             :          * when asked to send _only_ RAW datas, it tries to send datas
    5990             :          * in EMF format.
    5991             :          *
    5992             :          * So I add checks like in NT Server ...
    5993             :          */
    5994             : 
    5995           0 :         if (info_1->datatype) {
    5996             :                 /*
    5997             :                  * The v4 driver model used in Windows 8 declares print jobs
    5998             :                  * intended to bypass the XPS processing layer by setting
    5999             :                  * datatype to "XPS_PASS" instead of "RAW".
    6000             :                  */
    6001           0 :                 if ((strcmp(info_1->datatype, "RAW") != 0)
    6002           0 :                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
    6003           0 :                         *r->out.job_id = 0;
    6004           0 :                         return WERR_INVALID_DATATYPE;
    6005             :                 }
    6006             :         }
    6007             : 
    6008             :         /* get the share number of the printer */
    6009           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    6010           0 :                 return WERR_INVALID_HANDLE;
    6011             :         }
    6012             : 
    6013           0 :         rc = get_remote_hostname(remote_address,
    6014             :                                  &rhost,
    6015             :                                  p->mem_ctx);
    6016           0 :         if (rc < 0) {
    6017           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6018             :         }
    6019           0 :         if (strequal(rhost,"UNKNOWN")) {
    6020           0 :                 rhost = tsocket_address_inet_addr_string(remote_address,
    6021             :                                                          p->mem_ctx);
    6022           0 :                 if (rhost == NULL) {
    6023           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    6024             :                 }
    6025             :         }
    6026             : 
    6027           0 :         werr = print_job_start(session_info,
    6028             :                                p->msg_ctx,
    6029             :                                rhost,
    6030             :                                snum,
    6031             :                                info_1->document_name,
    6032             :                                info_1->output_file,
    6033             :                                Printer->devmode,
    6034             :                                &Printer->jobid);
    6035             : 
    6036             :         /* An error occurred in print_job_start() so return an appropriate
    6037             :            NT error code. */
    6038             : 
    6039           0 :         if (!W_ERROR_IS_OK(werr)) {
    6040           0 :                 return werr;
    6041             :         }
    6042             : 
    6043           0 :         Printer->document_started = true;
    6044           0 :         *r->out.job_id = Printer->jobid;
    6045             : 
    6046           0 :         return WERR_OK;
    6047             : }
    6048             : 
    6049             : /****************************************************************
    6050             :  _spoolss_EndDocPrinter
    6051             : ****************************************************************/
    6052             : 
    6053           0 : WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
    6054             :                               struct spoolss_EndDocPrinter *r)
    6055             : {
    6056           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6057             :         NTSTATUS status;
    6058             :         int snum;
    6059             : 
    6060           0 :         if (!Printer) {
    6061           0 :                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
    6062             :                         OUR_HANDLE(r->in.handle)));
    6063           0 :                 return WERR_INVALID_HANDLE;
    6064             :         }
    6065             : 
    6066           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    6067           0 :                 return WERR_INVALID_HANDLE;
    6068             :         }
    6069             : 
    6070           0 :         Printer->document_started = false;
    6071           0 :         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
    6072           0 :         if (!NT_STATUS_IS_OK(status)) {
    6073           0 :                 DEBUG(2, ("_spoolss_EndDocPrinter: "
    6074             :                           "print_job_end failed [%s]\n",
    6075             :                           nt_errstr(status)));
    6076             :         }
    6077             : 
    6078           0 :         Printer->jobid = 0;
    6079           0 :         return ntstatus_to_werror(status);
    6080             : }
    6081             : 
    6082             : /****************************************************************
    6083             :  _spoolss_WritePrinter
    6084             : ****************************************************************/
    6085             : 
    6086           0 : WERROR _spoolss_WritePrinter(struct pipes_struct *p,
    6087             :                              struct spoolss_WritePrinter *r)
    6088             : {
    6089             :         ssize_t buffer_written;
    6090             :         int snum;
    6091           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6092             : 
    6093           0 :         if (!Printer) {
    6094           0 :                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
    6095             :                         OUR_HANDLE(r->in.handle)));
    6096           0 :                 *r->out.num_written = r->in._data_size;
    6097           0 :                 return WERR_INVALID_HANDLE;
    6098             :         }
    6099             : 
    6100           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    6101           0 :                 return WERR_INVALID_HANDLE;
    6102             : 
    6103             :         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
    6104           0 :         buffer_written = print_job_write(global_event_context(),p->msg_ctx,
    6105             :                                                    snum, Printer->jobid,
    6106           0 :                                                    (const char *)r->in.data.data,
    6107           0 :                                                    (size_t)r->in._data_size);
    6108           0 :         if (buffer_written == (ssize_t)-1) {
    6109           0 :                 *r->out.num_written = 0;
    6110           0 :                 if (errno == ENOSPC)
    6111           0 :                         return WERR_NO_SPOOL_SPACE;
    6112             :                 else
    6113           0 :                         return WERR_ACCESS_DENIED;
    6114             :         }
    6115             : 
    6116           0 :         *r->out.num_written = r->in._data_size;
    6117             : 
    6118           0 :         return WERR_OK;
    6119             : }
    6120             : 
    6121             : /********************************************************************
    6122             :  * api_spoolss_getprinter
    6123             :  * called from the spoolss dispatcher
    6124             :  *
    6125             :  ********************************************************************/
    6126             : 
    6127           0 : static WERROR control_printer(struct policy_handle *handle, uint32_t command,
    6128             :                               struct pipes_struct *p)
    6129             : {
    6130           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6131           0 :         struct auth_session_info *session_info =
    6132           0 :                 dcesrv_call_session_info(dce_call);
    6133             :         int snum;
    6134           0 :         WERROR errcode = WERR_INVALID_FUNCTION;
    6135           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6136             : 
    6137           0 :         if (!Printer) {
    6138           0 :                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
    6139             :                         OUR_HANDLE(handle)));
    6140           0 :                 return WERR_INVALID_HANDLE;
    6141             :         }
    6142             : 
    6143           0 :         if (!get_printer_snum(p, handle, &snum, NULL))
    6144           0 :                 return WERR_INVALID_HANDLE;
    6145             : 
    6146           0 :         switch (command) {
    6147           0 :         case SPOOLSS_PRINTER_CONTROL_PAUSE:
    6148           0 :                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
    6149           0 :                 break;
    6150           0 :         case SPOOLSS_PRINTER_CONTROL_RESUME:
    6151             :         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
    6152           0 :                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
    6153           0 :                 break;
    6154           0 :         case SPOOLSS_PRINTER_CONTROL_PURGE:
    6155           0 :                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
    6156           0 :                 break;
    6157           0 :         default:
    6158           0 :                 return WERR_INVALID_LEVEL;
    6159             :         }
    6160             : 
    6161           0 :         return errcode;
    6162             : }
    6163             : 
    6164             : 
    6165             : /****************************************************************
    6166             :  _spoolss_AbortPrinter
    6167             :  * From MSDN: "Deletes printer's spool file if printer is configured
    6168             :  * for spooling"
    6169             : ****************************************************************/
    6170             : 
    6171           0 : WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
    6172             :                              struct spoolss_AbortPrinter *r)
    6173             : {
    6174           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6175           0 :         struct auth_session_info *session_info =
    6176           0 :                 dcesrv_call_session_info(dce_call);
    6177           0 :         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
    6178             :         int             snum;
    6179           0 :         WERROR          errcode = WERR_OK;
    6180             : 
    6181           0 :         if (!Printer) {
    6182           0 :                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
    6183             :                         OUR_HANDLE(r->in.handle)));
    6184           0 :                 return WERR_INVALID_HANDLE;
    6185             :         }
    6186             : 
    6187           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    6188           0 :                 return WERR_INVALID_HANDLE;
    6189             : 
    6190           0 :         if (!Printer->document_started) {
    6191           0 :                 return WERR_SPL_NO_STARTDOC;
    6192             :         }
    6193             : 
    6194           0 :         errcode = print_job_delete(session_info,
    6195             :                                    p->msg_ctx,
    6196             :                                    snum,
    6197             :                                    Printer->jobid);
    6198             : 
    6199           0 :         return errcode;
    6200             : }
    6201             : 
    6202             : /********************************************************************
    6203             :  * called by spoolss_api_setprinter
    6204             :  * when updating a printer description
    6205             :  ********************************************************************/
    6206             : 
    6207           0 : static WERROR update_printer_sec(struct policy_handle *handle,
    6208             :                                  struct pipes_struct *p,
    6209             :                                  struct sec_desc_buf *secdesc_ctr)
    6210             : {
    6211           0 :         struct spoolss_security_descriptor *new_secdesc = NULL;
    6212           0 :         struct spoolss_security_descriptor *old_secdesc = NULL;
    6213           0 :         const char *printer = NULL;
    6214             :         WERROR result;
    6215           0 :         int snum = -1;
    6216           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6217             :         struct dcerpc_binding_handle *b;
    6218           0 :         TALLOC_CTX *tmp_ctx = NULL;
    6219           0 :         bool ok = false;
    6220             : 
    6221           0 :         if (!Printer) {
    6222           0 :                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
    6223             :                          OUR_HANDLE(handle)));
    6224             : 
    6225           0 :                 result = WERR_INVALID_HANDLE;
    6226           0 :                 goto done;
    6227             :         }
    6228             : 
    6229           0 :         if (secdesc_ctr == NULL) {
    6230           0 :                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
    6231           0 :                 result = WERR_INVALID_PARAMETER;
    6232           0 :                 goto done;
    6233             :         }
    6234             : 
    6235           0 :         switch (Printer->printer_type) {
    6236           0 :         case SPLHND_SERVER:
    6237           0 :                 break;
    6238           0 :         case SPLHND_PRINTER:
    6239           0 :                 if (!get_printer_snum(p, handle, &snum, NULL)) {
    6240           0 :                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
    6241             :                                  OUR_HANDLE(handle)));
    6242           0 :                         result = WERR_INVALID_HANDLE;
    6243           0 :                         goto done;
    6244             :                 }
    6245           0 :                 printer = lp_const_servicename(snum);
    6246           0 :                 break;
    6247           0 :         default:
    6248           0 :                 break;
    6249             :         }
    6250             : 
    6251             :         /* Check the user has permissions to change the security
    6252             :            descriptor.  By experimentation with two NT machines, the user
    6253             :            requires Full Access to the printer to change security
    6254             :            information. */
    6255             : 
    6256           0 :         switch (Printer->printer_type) {
    6257           0 :         case SPLHND_SERVER:
    6258           0 :                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
    6259           0 :                 break;
    6260           0 :         case SPLHND_PRINTER:
    6261           0 :                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
    6262           0 :                 break;
    6263           0 :         default:
    6264           0 :                 break;
    6265             :         }
    6266             : 
    6267           0 :         if (!ok) {
    6268           0 :                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
    6269             :                         "(access_granted: 0x%08x)\n", Printer->access_granted));
    6270           0 :                 result = WERR_ACCESS_DENIED;
    6271           0 :                 goto done;
    6272             :         }
    6273             : 
    6274           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    6275           0 :         if (!tmp_ctx) {
    6276           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6277             :         }
    6278             : 
    6279           0 :         result = winreg_printer_binding_handle(tmp_ctx,
    6280             :                                                get_session_info_system(),
    6281             :                                                p->msg_ctx,
    6282             :                                                &b);
    6283           0 :         if (!W_ERROR_IS_OK(result)) {
    6284           0 :                 goto done;
    6285             :         }
    6286             : 
    6287             :         /* NT seems to like setting the security descriptor even though
    6288             :            nothing may have actually changed. */
    6289             : 
    6290           0 :         if (printer != NULL) {
    6291           0 :                 result = winreg_get_printer_secdesc(tmp_ctx, b,
    6292             :                                                     printer,
    6293             :                                                     &old_secdesc);
    6294             :         } else {
    6295           0 :                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
    6296             :                                                         &old_secdesc);
    6297             :         }
    6298           0 :         if (!W_ERROR_IS_OK(result)) {
    6299           0 :                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
    6300           0 :                 result = WERR_INVALID_HANDLE;
    6301           0 :                 goto done;
    6302             :         }
    6303             : 
    6304           0 :         if (DEBUGLEVEL >= 10) {
    6305             :                 struct dom_sid_buf buf;
    6306             :                 struct security_acl *the_acl;
    6307             :                 int i;
    6308             : 
    6309           0 :                 the_acl = old_secdesc->dacl;
    6310           0 :                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
    6311             :                            printer, the_acl->num_aces));
    6312             : 
    6313           0 :                 for (i = 0; i < the_acl->num_aces; i++) {
    6314           0 :                         DEBUG(10, ("%s 0x%08x\n",
    6315             :                                    dom_sid_str_buf(
    6316             :                                            &the_acl->aces[i].trustee,
    6317             :                                            &buf),
    6318             :                                   the_acl->aces[i].access_mask));
    6319             :                 }
    6320             : 
    6321           0 :                 the_acl = secdesc_ctr->sd->dacl;
    6322             : 
    6323           0 :                 if (the_acl) {
    6324           0 :                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
    6325             :                                    printer, the_acl->num_aces));
    6326             : 
    6327           0 :                         for (i = 0; i < the_acl->num_aces; i++) {
    6328           0 :                                 DEBUG(10, ("%s 0x%08x\n",
    6329             :                                            dom_sid_str_buf(
    6330             :                                                    &the_acl->aces[i].trustee,
    6331             :                                                    &buf),
    6332             :                                            the_acl->aces[i].access_mask));
    6333             :                         }
    6334             :                 } else {
    6335           0 :                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
    6336             :                 }
    6337             :         }
    6338             : 
    6339           0 :         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
    6340           0 :         if (new_secdesc == NULL) {
    6341           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    6342           0 :                 goto done;
    6343             :         }
    6344             : 
    6345           0 :         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
    6346           0 :                 result = WERR_OK;
    6347           0 :                 goto done;
    6348             :         }
    6349             : 
    6350           0 :         if (printer != NULL) {
    6351           0 :                 result = winreg_set_printer_secdesc(tmp_ctx, b,
    6352             :                                                     printer,
    6353             :                                                     new_secdesc);
    6354             :         } else {
    6355           0 :                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
    6356             :                                                         new_secdesc);
    6357             :         }
    6358             : 
    6359           0 : done:
    6360           0 :         talloc_free(tmp_ctx);
    6361           0 :         return result;
    6362             : }
    6363             : 
    6364             : /********************************************************************
    6365             :  Canonicalize printer info from a client
    6366             :  ********************************************************************/
    6367             : 
    6368           0 : static bool check_printer_ok(TALLOC_CTX *mem_ctx,
    6369             :                              struct spoolss_SetPrinterInfo2 *info2,
    6370             :                              int snum)
    6371             : {
    6372             :         fstring printername;
    6373             :         const char *p;
    6374             : 
    6375           0 :         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
    6376             :                 "portname=%s drivername=%s comment=%s location=%s\n",
    6377             :                 info2->servername, info2->printername, info2->sharename,
    6378             :                 info2->portname, info2->drivername, info2->comment,
    6379             :                 info2->location));
    6380             : 
    6381             :         /* we force some elements to "correct" values */
    6382           0 :         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
    6383           0 :         if (info2->servername == NULL) {
    6384           0 :                 return false;
    6385             :         }
    6386           0 :         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
    6387           0 :         if (info2->sharename == NULL) {
    6388           0 :                 return false;
    6389             :         }
    6390             : 
    6391             :         /* check to see if we allow printername != sharename */
    6392           0 :         if (lp_force_printername(snum)) {
    6393           0 :                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
    6394             :                                         lp_netbios_name(), info2->sharename);
    6395             :         } else {
    6396             :                 /* make sure printername is in \\server\printername format */
    6397           0 :                 fstrcpy(printername, info2->printername);
    6398           0 :                 p = printername;
    6399           0 :                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
    6400           0 :                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
    6401           0 :                                 p++;
    6402             :                 }
    6403             : 
    6404           0 :                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
    6405             :                                         lp_netbios_name(), p);
    6406             :         }
    6407           0 :         if (info2->printername == NULL) {
    6408           0 :                 return false;
    6409             :         }
    6410             : 
    6411           0 :         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
    6412           0 :         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
    6413             : 
    6414           0 :         return true;
    6415             : }
    6416             : 
    6417             : /****************************************************************************
    6418             : ****************************************************************************/
    6419             : 
    6420           0 : static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
    6421             : {
    6422           0 :         const struct loadparm_substitution *lp_sub =
    6423           0 :                 loadparm_s3_global_substitution();
    6424           0 :         char *cmd = lp_addport_command(talloc_tos(), lp_sub);
    6425           0 :         char *command = NULL;
    6426             :         int ret;
    6427           0 :         bool is_print_op = false;
    6428             : 
    6429           0 :         if ( !*cmd ) {
    6430           0 :                 return WERR_ACCESS_DENIED;
    6431             :         }
    6432             : 
    6433           0 :         command = talloc_asprintf(ctx,
    6434             :                         "%s \"%s\" \"%s\"", cmd, portname, uri );
    6435           0 :         if (!command) {
    6436           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6437             :         }
    6438             : 
    6439           0 :         if ( token )
    6440           0 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
    6441             : 
    6442           0 :         DEBUG(10,("Running [%s]\n", command));
    6443             : 
    6444             :         /********* BEGIN SePrintOperatorPrivilege **********/
    6445             : 
    6446           0 :         if ( is_print_op )
    6447           0 :                 become_root();
    6448             : 
    6449           0 :         ret = smbrun(command, NULL, NULL);
    6450             : 
    6451           0 :         if ( is_print_op )
    6452           0 :                 unbecome_root();
    6453             : 
    6454             :         /********* END SePrintOperatorPrivilege **********/
    6455             : 
    6456           0 :         DEBUGADD(10,("returned [%d]\n", ret));
    6457             : 
    6458           0 :         TALLOC_FREE(command);
    6459             : 
    6460           0 :         if ( ret != 0 ) {
    6461           0 :                 return WERR_ACCESS_DENIED;
    6462             :         }
    6463             : 
    6464           0 :         return WERR_OK;
    6465             : }
    6466             : 
    6467             : /****************************************************************************
    6468             : ****************************************************************************/
    6469             : 
    6470           0 : static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
    6471             :                                    int snum)
    6472             : {
    6473             :         /*
    6474             :          * As we do not know if we are embedded in the file server process
    6475             :          * or not, we have to pretend that all shares are in use.
    6476             :          */
    6477           0 :         return true;
    6478             : }
    6479             : 
    6480           0 : static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
    6481             :                              struct spoolss_SetPrinterInfo2 *info2,
    6482             :                              const char *remote_machine,
    6483             :                              struct messaging_context *msg_ctx)
    6484             : {
    6485           0 :         const struct loadparm_substitution *lp_sub =
    6486           0 :                 loadparm_s3_global_substitution();
    6487           0 :         char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
    6488             :         char **qlines;
    6489           0 :         char *command = NULL;
    6490             :         int numlines;
    6491             :         int ret;
    6492             :         int fd;
    6493           0 :         bool is_print_op = false;
    6494             : 
    6495           0 :         if (!remote_machine) {
    6496           0 :                 return false;
    6497             :         }
    6498             : 
    6499           0 :         command = talloc_asprintf(ctx,
    6500             :                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
    6501             :                         cmd, info2->printername, info2->sharename,
    6502             :                         info2->portname, info2->drivername,
    6503             :                         info2->location, info2->comment, remote_machine);
    6504           0 :         if (!command) {
    6505           0 :                 return false;
    6506             :         }
    6507             : 
    6508           0 :         if ( token )
    6509           0 :                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
    6510             : 
    6511           0 :         DEBUG(10,("Running [%s]\n", command));
    6512             : 
    6513             :         /********* BEGIN SePrintOperatorPrivilege **********/
    6514             : 
    6515           0 :         if ( is_print_op )
    6516           0 :                 become_root();
    6517             : 
    6518           0 :         ret = smbrun(command, &fd, NULL);
    6519           0 :         if (ret == 0) {
    6520             :                 /* Tell everyone we updated smb.conf. */
    6521           0 :                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
    6522             :         }
    6523             : 
    6524           0 :         if ( is_print_op )
    6525           0 :                 unbecome_root();
    6526             : 
    6527             :         /********* END SePrintOperatorPrivilege **********/
    6528             : 
    6529           0 :         DEBUGADD(10,("returned [%d]\n", ret));
    6530             : 
    6531           0 :         TALLOC_FREE(command);
    6532             : 
    6533           0 :         if ( ret != 0 ) {
    6534           0 :                 if (fd != -1)
    6535           0 :                         close(fd);
    6536           0 :                 return false;
    6537             :         }
    6538             : 
    6539             :         /* reload our services immediately */
    6540           0 :         become_root();
    6541           0 :         reload_services(NULL, spoolss_conn_snum_used, false);
    6542           0 :         unbecome_root();
    6543             : 
    6544           0 :         numlines = 0;
    6545             :         /* Get lines and convert them back to dos-codepage */
    6546           0 :         qlines = fd_lines_load(fd, &numlines, 0, NULL);
    6547           0 :         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
    6548           0 :         close(fd);
    6549             : 
    6550             :         /* Set the portname to what the script says the portname should be. */
    6551             :         /* but don't require anything to be return from the script exit a good error code */
    6552             : 
    6553           0 :         if (numlines) {
    6554             :                 /* Set the portname to what the script says the portname should be. */
    6555           0 :                 info2->portname = talloc_strdup(ctx, qlines[0]);
    6556           0 :                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
    6557             :         }
    6558             : 
    6559           0 :         TALLOC_FREE(qlines);
    6560           0 :         return true;
    6561             : }
    6562             : 
    6563           0 : static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
    6564             :                                const struct auth_session_info *session_info,
    6565             :                                struct messaging_context *msg_ctx,
    6566             :                                int snum,
    6567             :                                struct spoolss_SetPrinterInfo2 *printer,
    6568             :                                struct spoolss_PrinterInfo2 *old_printer)
    6569             : {
    6570           0 :         bool force_update = (old_printer == NULL);
    6571             :         const char *dnsdomname;
    6572             :         const char *longname;
    6573             :         const char *uncname;
    6574             :         const char *spooling;
    6575             :         DATA_BLOB buffer;
    6576           0 :         WERROR result = WERR_OK;
    6577             :         struct dcerpc_binding_handle *b;
    6578             :         TALLOC_CTX *tmp_ctx;
    6579             :         bool ok;
    6580             : 
    6581           0 :         tmp_ctx = talloc_new(mem_ctx);
    6582           0 :         if (!tmp_ctx) {
    6583           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    6584             :         }
    6585             : 
    6586           0 :         result = winreg_printer_binding_handle(tmp_ctx,
    6587             :                                                session_info,
    6588             :                                                msg_ctx,
    6589             :                                                &b);
    6590           0 :         if (!W_ERROR_IS_OK(result)) {
    6591           0 :                 goto done;
    6592             :         }
    6593             : 
    6594           0 :         if (printer->drivername != NULL &&
    6595           0 :             (force_update ||
    6596           0 :              !strequal(printer->drivername, old_printer->drivername))) {
    6597           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
    6598           0 :                 if (!ok) {
    6599           0 :                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
    6600           0 :                         result = WERR_INVALID_DATA;
    6601           0 :                         goto done;
    6602             :                 }
    6603           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6604             :                                           printer->sharename,
    6605             :                                           SPOOL_DSSPOOLER_KEY,
    6606             :                                           SPOOL_REG_DRIVERNAME,
    6607             :                                           REG_SZ,
    6608             :                                           buffer.data,
    6609           0 :                                           buffer.length);
    6610           0 :                 if (!W_ERROR_IS_OK(result)) {
    6611           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
    6612           0 :                         goto done;
    6613             :                 }
    6614             : 
    6615           0 :                 if (!force_update) {
    6616           0 :                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
    6617             :                                 printer->drivername));
    6618             : 
    6619           0 :                         notify_printer_driver(global_event_context(), msg_ctx,
    6620           0 :                                               snum, printer->drivername ?
    6621             :                                               printer->drivername : "");
    6622             :                 }
    6623             :         }
    6624             : 
    6625           0 :         if (printer->comment != NULL &&
    6626           0 :             (force_update ||
    6627           0 :              !strequal(printer->comment, old_printer->comment))) {
    6628           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
    6629           0 :                 if (!ok) {
    6630           0 :                         DEBUG(0, ("comment data corrupted\n"));
    6631           0 :                         result = WERR_INVALID_DATA;
    6632           0 :                         goto done;
    6633             :                 }
    6634           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6635             :                                           printer->sharename,
    6636             :                                           SPOOL_DSSPOOLER_KEY,
    6637             :                                           SPOOL_REG_DESCRIPTION,
    6638             :                                           REG_SZ,
    6639             :                                           buffer.data,
    6640           0 :                                           buffer.length);
    6641           0 :                 if (!W_ERROR_IS_OK(result)) {
    6642           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
    6643           0 :                         goto done;
    6644             :                 }
    6645             : 
    6646           0 :                 if (!force_update) {
    6647           0 :                         notify_printer_comment(global_event_context(), msg_ctx,
    6648           0 :                                                snum, printer->comment ?
    6649             :                                                printer->comment : "");
    6650             :                 }
    6651             :         }
    6652             : 
    6653           0 :         if (printer->sharename != NULL &&
    6654           0 :             (force_update ||
    6655           0 :              !strequal(printer->sharename, old_printer->sharename))) {
    6656           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
    6657           0 :                 if (!ok) {
    6658           0 :                         DEBUG(0, ("sharename data corrupted\n"));
    6659           0 :                         result = WERR_INVALID_DATA;
    6660           0 :                         goto done;
    6661             :                 }
    6662           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6663             :                                           printer->sharename,
    6664             :                                           SPOOL_DSSPOOLER_KEY,
    6665             :                                           SPOOL_REG_PRINTSHARENAME,
    6666             :                                           REG_SZ,
    6667             :                                           buffer.data,
    6668           0 :                                           buffer.length);
    6669           0 :                 if (!W_ERROR_IS_OK(result)) {
    6670           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
    6671           0 :                         goto done;
    6672             :                 }
    6673             : 
    6674           0 :                 if (!force_update) {
    6675           0 :                         notify_printer_sharename(global_event_context(),
    6676             :                                                  msg_ctx,
    6677           0 :                                                  snum, printer->sharename ?
    6678             :                                                  printer->sharename : "");
    6679             :                 }
    6680             : 
    6681             :                 /* name change, purge any cache entries for the old */
    6682           0 :                 prune_printername_cache();
    6683             :         }
    6684             : 
    6685           0 :         if (printer->printername != NULL &&
    6686           0 :             (force_update ||
    6687           0 :              !strequal(printer->printername, old_printer->printername))) {
    6688             :                 const char *p;
    6689             : 
    6690           0 :                 p = strrchr(printer->printername, '\\' );
    6691           0 :                 if (p != NULL) {
    6692           0 :                         p++;
    6693             :                 } else {
    6694           0 :                         p = printer->printername;
    6695             :                 }
    6696             : 
    6697           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, p);
    6698           0 :                 if (!ok) {
    6699           0 :                         DEBUG(0, ("printername data corrupted\n"));
    6700           0 :                         result = WERR_INVALID_DATA;
    6701           0 :                         goto done;
    6702             :                 }
    6703           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6704             :                                           printer->sharename,
    6705             :                                           SPOOL_DSSPOOLER_KEY,
    6706             :                                           SPOOL_REG_PRINTERNAME,
    6707             :                                           REG_SZ,
    6708             :                                           buffer.data,
    6709           0 :                                           buffer.length);
    6710           0 :                 if (!W_ERROR_IS_OK(result)) {
    6711           0 :                         DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
    6712           0 :                         goto done;
    6713             :                 }
    6714             : 
    6715           0 :                 if (!force_update) {
    6716           0 :                         notify_printer_printername(global_event_context(),
    6717             :                                                    msg_ctx, snum, p ? p : "");
    6718             :                 }
    6719             : 
    6720             :                 /* name change, purge any cache entries for the old */
    6721           0 :                 prune_printername_cache();
    6722             :         }
    6723             : 
    6724           0 :         if (printer->portname != NULL &&
    6725           0 :             (force_update ||
    6726           0 :              !strequal(printer->portname, old_printer->portname))) {
    6727           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
    6728           0 :                 if (!ok) {
    6729           0 :                         DEBUG(0, ("portname data corrupted\n"));
    6730           0 :                         result = WERR_INVALID_DATA;
    6731           0 :                         goto done;
    6732             :                 }
    6733           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6734             :                                           printer->sharename,
    6735             :                                           SPOOL_DSSPOOLER_KEY,
    6736             :                                           SPOOL_REG_PORTNAME,
    6737             :                                           REG_SZ,
    6738             :                                           buffer.data,
    6739           0 :                                           buffer.length);
    6740           0 :                 if (!W_ERROR_IS_OK(result)) {
    6741           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
    6742           0 :                         goto done;
    6743             :                 }
    6744             : 
    6745           0 :                 if (!force_update) {
    6746           0 :                         notify_printer_port(global_event_context(),
    6747           0 :                                             msg_ctx, snum, printer->portname ?
    6748             :                                             printer->portname : "");
    6749             :                 }
    6750             :         }
    6751             : 
    6752           0 :         if (printer->location != NULL &&
    6753           0 :             (force_update ||
    6754           0 :              !strequal(printer->location, old_printer->location))) {
    6755           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
    6756           0 :                 if (!ok) {
    6757           0 :                         DEBUG(0, ("location data corrupted\n"));
    6758           0 :                         result = WERR_INVALID_DATA;
    6759           0 :                         goto done;
    6760             :                 }
    6761           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6762             :                                           printer->sharename,
    6763             :                                           SPOOL_DSSPOOLER_KEY,
    6764             :                                           SPOOL_REG_LOCATION,
    6765             :                                           REG_SZ,
    6766             :                                           buffer.data,
    6767           0 :                                           buffer.length);
    6768           0 :                 if (!W_ERROR_IS_OK(result)) {
    6769           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
    6770           0 :                         goto done;
    6771             :                 }
    6772             : 
    6773           0 :                 if (!force_update) {
    6774           0 :                         notify_printer_location(global_event_context(),
    6775             :                                                 msg_ctx, snum,
    6776           0 :                                                 printer->location ?
    6777             :                                                 printer->location : "");
    6778             :                 }
    6779             :         }
    6780             : 
    6781           0 :         if (printer->sepfile != NULL &&
    6782           0 :             (force_update ||
    6783           0 :              !strequal(printer->sepfile, old_printer->sepfile))) {
    6784           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
    6785           0 :                 if (!ok) {
    6786           0 :                         DEBUG(0, ("sepfile data corrupted\n"));
    6787           0 :                         result = WERR_INVALID_DATA;
    6788           0 :                         goto done;
    6789             :                 }
    6790           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6791             :                                           printer->sharename,
    6792             :                                           SPOOL_DSSPOOLER_KEY,
    6793             :                                           SPOOL_REG_PRINTSEPARATORFILE,
    6794             :                                           REG_SZ,
    6795             :                                           buffer.data,
    6796           0 :                                           buffer.length);
    6797           0 :                 if (!W_ERROR_IS_OK(result)) {
    6798           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
    6799           0 :                         goto done;
    6800             :                 }
    6801             : 
    6802           0 :                 if (!force_update) {
    6803           0 :                         notify_printer_sepfile(global_event_context(),
    6804             :                                                msg_ctx, snum,
    6805           0 :                                                printer->sepfile ?
    6806             :                                                printer->sepfile : "");
    6807             :                 }
    6808             :         }
    6809             : 
    6810           0 :         if (printer->starttime != 0 &&
    6811           0 :             (force_update ||
    6812           0 :              printer->starttime != old_printer->starttime)) {
    6813           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6814           0 :                 SIVAL(buffer.data, 0, printer->starttime);
    6815           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6816             :                                           printer->sharename,
    6817             :                                           SPOOL_DSSPOOLER_KEY,
    6818             :                                           SPOOL_REG_PRINTSTARTTIME,
    6819             :                                           REG_DWORD,
    6820             :                                           buffer.data,
    6821           0 :                                           buffer.length);
    6822           0 :                 if (!W_ERROR_IS_OK(result)) {
    6823           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
    6824           0 :                         goto done;
    6825             :                 }
    6826             :         }
    6827             : 
    6828           0 :         if (printer->untiltime != 0 &&
    6829           0 :             (force_update ||
    6830           0 :              printer->untiltime != old_printer->untiltime)) {
    6831           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6832           0 :                 SIVAL(buffer.data, 0, printer->untiltime);
    6833           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6834             :                                           printer->sharename,
    6835             :                                           SPOOL_DSSPOOLER_KEY,
    6836             :                                           SPOOL_REG_PRINTENDTIME,
    6837             :                                           REG_DWORD,
    6838             :                                           buffer.data,
    6839           0 :                                           buffer.length);
    6840           0 :                 if (!W_ERROR_IS_OK(result)) {
    6841           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6842           0 :                         goto done;
    6843             :                 }
    6844             :         }
    6845             : 
    6846           0 :         if (force_update || printer->priority != old_printer->priority) {
    6847           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6848           0 :                 SIVAL(buffer.data, 0, printer->priority);
    6849           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6850             :                                           printer->sharename,
    6851             :                                           SPOOL_DSSPOOLER_KEY,
    6852             :                                           SPOOL_REG_PRIORITY,
    6853             :                                           REG_DWORD,
    6854             :                                           buffer.data,
    6855           0 :                                           buffer.length);
    6856           0 :                 if (!W_ERROR_IS_OK(result)) {
    6857           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6858           0 :                         goto done;
    6859             :                 }
    6860             :         }
    6861             : 
    6862           0 :         if (force_update || printer->attributes != old_printer->attributes) {
    6863           0 :                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
    6864           0 :                 SIVAL(buffer.data, 0, (printer->attributes &
    6865             :                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
    6866           0 :                 result = winreg_set_printer_dataex(tmp_ctx, b,
    6867             :                                           printer->sharename,
    6868             :                                           SPOOL_DSSPOOLER_KEY,
    6869             :                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
    6870             :                                           REG_DWORD,
    6871             :                                           buffer.data,
    6872           0 :                                           buffer.length);
    6873           0 :                 if (!W_ERROR_IS_OK(result)) {
    6874           0 :                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
    6875           0 :                         goto done;
    6876             :                 }
    6877             : 
    6878           0 :                 switch (printer->attributes & 0x3) {
    6879           0 :                         case 0:
    6880           0 :                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
    6881           0 :                                 break;
    6882           0 :                         case 1:
    6883           0 :                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
    6884           0 :                                 break;
    6885           0 :                         case 2:
    6886           0 :                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
    6887           0 :                                 break;
    6888           0 :                         default:
    6889           0 :                                 spooling = "unknown";
    6890             :                 }
    6891           0 :                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
    6892           0 :                 if (!ok) {
    6893           0 :                         DEBUG(0, ("printSpooling data corrupted\n"));
    6894           0 :                         result = WERR_INVALID_DATA;
    6895           0 :                         goto done;
    6896             :                 }
    6897           0 :                 winreg_set_printer_dataex(tmp_ctx, b,
    6898             :                                           printer->sharename,
    6899             :                                           SPOOL_DSSPOOLER_KEY,
    6900             :                                           SPOOL_REG_PRINTSPOOLING,
    6901             :                                           REG_SZ,
    6902             :                                           buffer.data,
    6903           0 :                                           buffer.length);
    6904             :         }
    6905             : 
    6906           0 :         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
    6907           0 :         if (!ok) {
    6908           0 :                 DEBUG(0, ("shortServerName data corrupted\n"));
    6909           0 :                 result = WERR_INVALID_DATA;
    6910           0 :                 goto done;
    6911             :         }
    6912           0 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6913             :                                   printer->sharename,
    6914             :                                   SPOOL_DSSPOOLER_KEY,
    6915             :                                   SPOOL_REG_SHORTSERVERNAME,
    6916             :                                   REG_SZ,
    6917             :                                   buffer.data,
    6918           0 :                                   buffer.length);
    6919           0 :         if (!W_ERROR_IS_OK(result)) {
    6920           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
    6921           0 :                 goto done;
    6922             :         }
    6923             : 
    6924           0 :         dnsdomname = get_mydnsfullname();
    6925           0 :         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
    6926           0 :                 longname = talloc_strdup(tmp_ctx, dnsdomname);
    6927             :         } else {
    6928           0 :                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
    6929             :         }
    6930           0 :         if (longname == NULL) {
    6931           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    6932           0 :                 goto done;
    6933             :         }
    6934             : 
    6935           0 :         ok = push_reg_sz(tmp_ctx, &buffer, longname);
    6936           0 :         if (!ok) {
    6937           0 :                 DEBUG(0, ("longname data corrupted\n"));
    6938           0 :                 result = WERR_INVALID_DATA;
    6939           0 :                 goto done;
    6940             :         }
    6941           0 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6942             :                                            printer->sharename,
    6943             :                                            SPOOL_DSSPOOLER_KEY,
    6944             :                                            SPOOL_REG_SERVERNAME,
    6945             :                                            REG_SZ,
    6946             :                                            buffer.data,
    6947           0 :                                            buffer.length);
    6948           0 :         if (!W_ERROR_IS_OK(result)) {
    6949           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
    6950           0 :                 goto done;
    6951             :         }
    6952             : 
    6953           0 :         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
    6954             :                                   lp_netbios_name(), printer->sharename);
    6955           0 :         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
    6956           0 :         if (!ok) {
    6957           0 :                 DEBUG(0, ("uncName data corrupted\n"));
    6958           0 :                 result = WERR_INVALID_DATA;
    6959           0 :                 goto done;
    6960             :         }
    6961           0 :         result = winreg_set_printer_dataex(tmp_ctx, b,
    6962             :                                   printer->sharename,
    6963             :                                   SPOOL_DSSPOOLER_KEY,
    6964             :                                   SPOOL_REG_UNCNAME,
    6965             :                                   REG_SZ,
    6966             :                                   buffer.data,
    6967           0 :                                   buffer.length);
    6968           0 :         if (!W_ERROR_IS_OK(result)) {
    6969           0 :                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
    6970           0 :                 goto done;
    6971             :         }
    6972             : 
    6973           0 : done:
    6974           0 :         talloc_free(tmp_ctx);
    6975           0 :         return result;
    6976             : }
    6977             : 
    6978             : /********************************************************************
    6979             :  * Called by spoolss_api_setprinter
    6980             :  * when updating a printer description.
    6981             :  ********************************************************************/
    6982             : 
    6983           0 : static WERROR update_printer(struct pipes_struct *p,
    6984             :                              struct policy_handle *handle,
    6985             :                              struct spoolss_SetPrinterInfoCtr *info_ctr,
    6986             :                              struct spoolss_DeviceMode *devmode)
    6987             : {
    6988           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    6989           0 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    6990           0 :         const struct tsocket_address *remote_address =
    6991           0 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    6992           0 :         struct auth_session_info *session_info =
    6993           0 :                 dcesrv_call_session_info(dce_call);
    6994           0 :         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
    6995           0 :         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
    6996             :         struct spoolss_PrinterInfo2 *old_printer;
    6997           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    6998           0 :         const struct loadparm_substitution *lp_sub =
    6999           0 :                 loadparm_s3_global_substitution();
    7000             :         int snum;
    7001           0 :         WERROR result = WERR_OK;
    7002             :         TALLOC_CTX *tmp_ctx;
    7003             :         struct dcerpc_binding_handle *b;
    7004             : 
    7005           0 :         DEBUG(8,("update_printer\n"));
    7006             : 
    7007           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    7008           0 :         if (tmp_ctx == NULL) {
    7009           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    7010             :         }
    7011             : 
    7012           0 :         if (!Printer) {
    7013           0 :                 result = WERR_INVALID_HANDLE;
    7014           0 :                 goto done;
    7015             :         }
    7016             : 
    7017           0 :         if (!get_printer_snum(p, handle, &snum, NULL)) {
    7018           0 :                 result = WERR_INVALID_HANDLE;
    7019           0 :                 goto done;
    7020             :         }
    7021             : 
    7022           0 :         result = winreg_printer_binding_handle(tmp_ctx,
    7023             :                                                get_session_info_system(),
    7024             :                                                p->msg_ctx,
    7025             :                                                &b);
    7026           0 :         if (!W_ERROR_IS_OK(result)) {
    7027           0 :                 goto done;
    7028             :         }
    7029             : 
    7030           0 :         result = winreg_get_printer(tmp_ctx, b,
    7031             :                                     lp_const_servicename(snum),
    7032             :                                     &old_printer);
    7033           0 :         if (!W_ERROR_IS_OK(result)) {
    7034           0 :                 result = WERR_INVALID_HANDLE;
    7035           0 :                 goto done;
    7036             :         }
    7037             : 
    7038             :         /* Do sanity check on the requested changes for Samba */
    7039           0 :         if (!check_printer_ok(tmp_ctx, printer, snum)) {
    7040           0 :                 result = WERR_INVALID_PARAMETER;
    7041           0 :                 goto done;
    7042             :         }
    7043             : 
    7044             :         /* FIXME!!! If the driver has changed we really should verify that
    7045             :            it is installed before doing much else   --jerry */
    7046             : 
    7047             :         /* Check calling user has permission to update printer description */
    7048           0 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
    7049           0 :                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
    7050           0 :                 result = WERR_ACCESS_DENIED;
    7051           0 :                 goto done;
    7052             :         }
    7053             : 
    7054             :         /* Call addprinter hook */
    7055             :         /* Check changes to see if this is really needed */
    7056             : 
    7057           0 :         if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
    7058           0 :                         (!strequal(printer->drivername, old_printer->drivername) ||
    7059           0 :                          !strequal(printer->comment, old_printer->comment) ||
    7060           0 :                          !strequal(printer->portname, old_printer->portname) ||
    7061           0 :                          !strequal(printer->location, old_printer->location)) )
    7062             :         {
    7063             :                 char *raddr;
    7064             : 
    7065           0 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    7066             :                                                          p->mem_ctx);
    7067           0 :                 if (raddr == NULL) {
    7068           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    7069           0 :                         goto done;
    7070             :                 }
    7071             : 
    7072             :                 /* add_printer_hook() will call reload_services() */
    7073           0 :                 if (!add_printer_hook(tmp_ctx, session_info->security_token,
    7074             :                                       printer, raddr,
    7075             :                                       p->msg_ctx)) {
    7076           0 :                         result = WERR_ACCESS_DENIED;
    7077           0 :                         goto done;
    7078             :                 }
    7079             :         }
    7080             : 
    7081           0 :         result = update_dsspooler(tmp_ctx,
    7082             :                                   get_session_info_system(),
    7083             :                                   p->msg_ctx,
    7084             :                                   snum,
    7085             :                                   printer,
    7086             :                                   old_printer);
    7087           0 :         if (!W_ERROR_IS_OK(result)) {
    7088           0 :                 goto done;
    7089             :         }
    7090             : 
    7091           0 :         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
    7092             : 
    7093           0 :         if (devmode == NULL) {
    7094           0 :                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
    7095             :         }
    7096           0 :         result = winreg_update_printer(tmp_ctx, b,
    7097             :                                        printer->sharename,
    7098             :                                        printer_mask,
    7099             :                                        printer,
    7100             :                                        devmode,
    7101             :                                        NULL);
    7102             : 
    7103           0 : done:
    7104           0 :         talloc_free(tmp_ctx);
    7105             : 
    7106           0 :         return result;
    7107             : }
    7108             : 
    7109             : /****************************************************************************
    7110             : ****************************************************************************/
    7111           0 : static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
    7112             :                                            struct policy_handle *handle,
    7113             :                                            struct spoolss_SetPrinterInfo7 *info7)
    7114             : {
    7115             : #ifdef HAVE_ADS
    7116           0 :         const struct loadparm_substitution *lp_sub =
    7117           0 :                 loadparm_s3_global_substitution();
    7118           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    7119             :         WERROR result;
    7120             :         int snum;
    7121             :         struct printer_handle *Printer;
    7122             : 
    7123           0 :         if ( lp_security() != SEC_ADS ) {
    7124           0 :                 return WERR_INVALID_LEVEL;
    7125             :         }
    7126             : 
    7127           0 :         Printer = find_printer_index_by_hnd(p, handle);
    7128             : 
    7129           0 :         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
    7130             : 
    7131           0 :         if (!Printer)
    7132           0 :                 return WERR_INVALID_HANDLE;
    7133             : 
    7134           0 :         if (!get_printer_snum(p, handle, &snum, NULL))
    7135           0 :                 return WERR_INVALID_HANDLE;
    7136             : 
    7137           0 :         result = winreg_get_printer_internal(p->mem_ctx,
    7138             :                                     get_session_info_system(),
    7139             :                                     p->msg_ctx,
    7140           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum),
    7141             :                                     &pinfo2);
    7142           0 :         if (!W_ERROR_IS_OK(result)) {
    7143           0 :                 return WERR_INVALID_HANDLE;
    7144             :         }
    7145             : 
    7146           0 :         nt_printer_publish(pinfo2,
    7147             :                            get_session_info_system(),
    7148             :                            p->msg_ctx,
    7149             :                            pinfo2,
    7150           0 :                            info7->action);
    7151             : 
    7152           0 :         TALLOC_FREE(pinfo2);
    7153           0 :         return WERR_OK;
    7154             : #else
    7155             :         return WERR_INVALID_LEVEL;
    7156             : #endif
    7157             : }
    7158             : 
    7159             : /********************************************************************
    7160             :  ********************************************************************/
    7161             : 
    7162           0 : static WERROR update_printer_devmode(struct pipes_struct *p,
    7163             :                                      struct policy_handle *handle,
    7164             :                                      struct spoolss_DeviceMode *devmode)
    7165             : {
    7166             :         int snum;
    7167           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
    7168           0 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
    7169             : 
    7170           0 :         DEBUG(8,("update_printer_devmode\n"));
    7171             : 
    7172           0 :         if (!Printer) {
    7173           0 :                 return WERR_INVALID_HANDLE;
    7174             :         }
    7175             : 
    7176           0 :         if (!get_printer_snum(p, handle, &snum, NULL)) {
    7177           0 :                 return WERR_INVALID_HANDLE;
    7178             :         }
    7179             : 
    7180             :         /* Check calling user has permission to update printer description */
    7181           0 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
    7182           0 :                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
    7183           0 :                 return WERR_ACCESS_DENIED;
    7184             :         }
    7185             : 
    7186           0 :         return winreg_update_printer_internal(p->mem_ctx,
    7187             :                                      get_session_info_system(),
    7188             :                                      p->msg_ctx,
    7189             :                                      lp_const_servicename(snum),
    7190             :                                      info2_mask,
    7191             :                                      NULL,
    7192             :                                      devmode,
    7193             :                                      NULL);
    7194             : }
    7195             : 
    7196             : 
    7197             : /****************************************************************
    7198             :  _spoolss_SetPrinter
    7199             : ****************************************************************/
    7200             : 
    7201           0 : WERROR _spoolss_SetPrinter(struct pipes_struct *p,
    7202             :                            struct spoolss_SetPrinter *r)
    7203             : {
    7204             :         WERROR result;
    7205             : 
    7206           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    7207             : 
    7208           0 :         if (!Printer) {
    7209           0 :                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
    7210             :                         OUR_HANDLE(r->in.handle)));
    7211           0 :                 return WERR_INVALID_HANDLE;
    7212             :         }
    7213             : 
    7214             :         /* check the level */
    7215           0 :         switch (r->in.info_ctr->level) {
    7216           0 :                 case 0:
    7217           0 :                         return control_printer(r->in.handle, r->in.command, p);
    7218           0 :                 case 2:
    7219           0 :                         result = update_printer(p, r->in.handle,
    7220             :                                                 r->in.info_ctr,
    7221           0 :                                                 r->in.devmode_ctr->devmode);
    7222           0 :                         if (!W_ERROR_IS_OK(result))
    7223           0 :                                 return result;
    7224           0 :                         if (r->in.secdesc_ctr->sd)
    7225           0 :                                 result = update_printer_sec(r->in.handle, p,
    7226             :                                                             r->in.secdesc_ctr);
    7227           0 :                         return result;
    7228           0 :                 case 3:
    7229           0 :                         return update_printer_sec(r->in.handle, p,
    7230             :                                                   r->in.secdesc_ctr);
    7231           0 :                 case 4: {
    7232             :                         struct spoolss_PrinterInfo2 *old_printer;
    7233             :                         struct spoolss_SetPrinterInfo2 *set_old_printer;
    7234             :                         struct spoolss_SetPrinterInfoCtr *info_ctr;
    7235             :                         struct dcerpc_binding_handle *b;
    7236             :                         int snum;
    7237             :                         TALLOC_CTX *tmp_ctx;
    7238             : 
    7239           0 :                         tmp_ctx = talloc_new(p->mem_ctx);
    7240           0 :                         if (tmp_ctx == NULL) {
    7241           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7242             :                         }
    7243             : 
    7244           0 :                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7245           0 :                                 TALLOC_FREE(tmp_ctx);
    7246           0 :                                 return WERR_INVALID_HANDLE;
    7247             :                         }
    7248             : 
    7249           0 :                         result = winreg_printer_binding_handle(tmp_ctx,
    7250             :                                                                get_session_info_system(),
    7251             :                                                                p->msg_ctx,
    7252             :                                                                &b);
    7253           0 :                         if (!W_ERROR_IS_OK(result)) {
    7254           0 :                                 TALLOC_FREE(tmp_ctx);
    7255           0 :                                 return result;
    7256             :                         }
    7257             : 
    7258           0 :                         result = winreg_get_printer(tmp_ctx, b,
    7259             :                                                     lp_const_servicename(snum),
    7260             :                                                     &old_printer);
    7261           0 :                         if (!W_ERROR_IS_OK(result)) {
    7262           0 :                                 TALLOC_FREE(tmp_ctx);
    7263           0 :                                 return WERR_INVALID_HANDLE;
    7264             :                         }
    7265             : 
    7266           0 :                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
    7267           0 :                         if (old_printer->servername == NULL) {
    7268           0 :                                 TALLOC_FREE(tmp_ctx);
    7269           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7270             :                         }
    7271             : 
    7272           0 :                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
    7273           0 :                         if (old_printer->printername == NULL) {
    7274           0 :                                 TALLOC_FREE(tmp_ctx);
    7275           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7276             :                         }
    7277             : 
    7278           0 :                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
    7279             : 
    7280           0 :                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
    7281           0 :                         if (set_old_printer == NULL) {
    7282           0 :                                 TALLOC_FREE(tmp_ctx);
    7283           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7284             :                         }
    7285             : 
    7286           0 :                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
    7287             : 
    7288           0 :                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
    7289           0 :                         if (info_ctr == NULL) {
    7290           0 :                                 TALLOC_FREE(tmp_ctx);
    7291           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    7292             :                         }
    7293             : 
    7294           0 :                         info_ctr->level = 2;
    7295           0 :                         info_ctr->info.info2 = set_old_printer;
    7296             : 
    7297           0 :                         result = update_printer(p, r->in.handle,
    7298             :                                                 info_ctr,
    7299           0 :                                                 r->in.devmode_ctr->devmode);
    7300             : 
    7301           0 :                         if (!W_ERROR_IS_OK(result)) {
    7302           0 :                                 TALLOC_FREE(tmp_ctx);
    7303           0 :                                 return result;
    7304             :                         }
    7305             : 
    7306           0 :                         if (r->in.secdesc_ctr->sd) {
    7307           0 :                                 result = update_printer_sec(r->in.handle, p,
    7308             :                                                             r->in.secdesc_ctr);
    7309             :                         }
    7310             : 
    7311           0 :                         TALLOC_FREE(tmp_ctx);
    7312           0 :                         return result;
    7313             :                 }
    7314           0 :                 case 7:
    7315           0 :                         return publish_or_unpublish_printer(p, r->in.handle,
    7316           0 :                                                             r->in.info_ctr->info.info7);
    7317           0 :                 case 8:
    7318           0 :                         return update_printer_devmode(p, r->in.handle,
    7319           0 :                                                       r->in.devmode_ctr->devmode);
    7320           0 :                 default:
    7321           0 :                         return WERR_INVALID_LEVEL;
    7322             :         }
    7323             : }
    7324             : 
    7325             : /****************************************************************
    7326             :  _spoolss_FindClosePrinterNotify
    7327             : ****************************************************************/
    7328             : 
    7329           0 : WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
    7330             :                                        struct spoolss_FindClosePrinterNotify *r)
    7331             : {
    7332           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    7333             : 
    7334           0 :         if (!Printer) {
    7335           0 :                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
    7336             :                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
    7337           0 :                 return WERR_INVALID_HANDLE;
    7338             :         }
    7339             : 
    7340           0 :         if (Printer->notify.cli_chan != NULL &&
    7341           0 :             Printer->notify.cli_chan->active_connections > 0) {
    7342           0 :                 int snum = -1;
    7343             : 
    7344           0 :                 if (Printer->printer_type == SPLHND_PRINTER) {
    7345           0 :                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7346           0 :                                 return WERR_INVALID_HANDLE;
    7347             :                         }
    7348             :                 }
    7349             : 
    7350           0 :                 srv_spoolss_replycloseprinter(snum, Printer);
    7351             :         }
    7352             : 
    7353           0 :         Printer->notify.flags=0;
    7354           0 :         Printer->notify.options=0;
    7355           0 :         Printer->notify.localmachine[0]='\0';
    7356           0 :         Printer->notify.printerlocal=0;
    7357           0 :         TALLOC_FREE(Printer->notify.option);
    7358             : 
    7359           0 :         return WERR_OK;
    7360             : }
    7361             : 
    7362             : /****************************************************************
    7363             :  _spoolss_AddJob
    7364             : ****************************************************************/
    7365             : 
    7366           0 : WERROR _spoolss_AddJob(struct pipes_struct *p,
    7367             :                        struct spoolss_AddJob *r)
    7368             : {
    7369           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    7370           0 :                 return WERR_INVALID_PARAMETER;
    7371             :         }
    7372             : 
    7373             :         /* this is what a NT server returns for AddJob. AddJob must fail on
    7374             :          * non-local printers */
    7375             : 
    7376           0 :         if (r->in.level != 1) {
    7377           0 :                 return WERR_INVALID_LEVEL;
    7378             :         }
    7379             : 
    7380           0 :         return WERR_INVALID_PARAMETER;
    7381             : }
    7382             : 
    7383             : /****************************************************************************
    7384             : fill_job_info1
    7385             : ****************************************************************************/
    7386             : 
    7387           0 : static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
    7388             :                              struct spoolss_JobInfo1 *r,
    7389             :                              const print_queue_struct *queue,
    7390             :                              uint32_t jobid,
    7391             :                              int position, int snum,
    7392             :                              struct spoolss_PrinterInfo2 *pinfo2)
    7393             : {
    7394           0 :         const struct loadparm_substitution *lp_sub =
    7395           0 :                 loadparm_s3_global_substitution();
    7396             :         struct tm *t;
    7397             : 
    7398           0 :         t = gmtime(&queue->time);
    7399             : 
    7400           0 :         r->job_id            = jobid;
    7401             : 
    7402           0 :         r->printer_name              = lp_servicename(mem_ctx, lp_sub, snum);
    7403           0 :         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
    7404           0 :         r->server_name               = talloc_strdup(mem_ctx, pinfo2->servername);
    7405           0 :         W_ERROR_HAVE_NO_MEMORY(r->server_name);
    7406           0 :         r->user_name         = talloc_strdup(mem_ctx, queue->fs_user);
    7407           0 :         W_ERROR_HAVE_NO_MEMORY(r->user_name);
    7408           0 :         r->document_name     = talloc_strdup(mem_ctx, queue->fs_file);
    7409           0 :         W_ERROR_HAVE_NO_MEMORY(r->document_name);
    7410           0 :         r->data_type         = talloc_strdup(mem_ctx, "RAW");
    7411           0 :         W_ERROR_HAVE_NO_MEMORY(r->data_type);
    7412           0 :         r->text_status               = talloc_strdup(mem_ctx, "");
    7413           0 :         W_ERROR_HAVE_NO_MEMORY(r->text_status);
    7414             : 
    7415           0 :         r->status            = nt_printj_status(queue->status);
    7416           0 :         r->priority          = queue->priority;
    7417           0 :         r->position          = position;
    7418           0 :         r->total_pages               = queue->page_count;
    7419           0 :         r->pages_printed     = 0; /* ??? */
    7420             : 
    7421           0 :         init_systemtime(&r->submitted, t);
    7422             : 
    7423           0 :         return WERR_OK;
    7424             : }
    7425             : 
    7426             : /****************************************************************************
    7427             : fill_job_info2
    7428             : ****************************************************************************/
    7429             : 
    7430           0 : static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
    7431             :                              struct spoolss_JobInfo2 *r,
    7432             :                              const print_queue_struct *queue,
    7433             :                              uint32_t jobid,
    7434             :                              int position, int snum,
    7435             :                              struct spoolss_PrinterInfo2 *pinfo2,
    7436             :                              struct spoolss_DeviceMode *devmode)
    7437             : {
    7438           0 :         const struct loadparm_substitution *lp_sub =
    7439           0 :                 loadparm_s3_global_substitution();
    7440             :         struct tm *t;
    7441             : 
    7442           0 :         t = gmtime(&queue->time);
    7443             : 
    7444           0 :         r->job_id            = jobid;
    7445             : 
    7446           0 :         r->printer_name              = lp_servicename(mem_ctx, lp_sub, snum);
    7447           0 :         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
    7448           0 :         r->server_name               = talloc_strdup(mem_ctx, pinfo2->servername);
    7449           0 :         W_ERROR_HAVE_NO_MEMORY(r->server_name);
    7450           0 :         r->user_name         = talloc_strdup(mem_ctx, queue->fs_user);
    7451           0 :         W_ERROR_HAVE_NO_MEMORY(r->user_name);
    7452           0 :         r->document_name     = talloc_strdup(mem_ctx, queue->fs_file);
    7453           0 :         W_ERROR_HAVE_NO_MEMORY(r->document_name);
    7454           0 :         r->notify_name               = talloc_strdup(mem_ctx, queue->fs_user);
    7455           0 :         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
    7456           0 :         r->data_type         = talloc_strdup(mem_ctx, "RAW");
    7457           0 :         W_ERROR_HAVE_NO_MEMORY(r->data_type);
    7458           0 :         r->print_processor   = talloc_strdup(mem_ctx, "winprint");
    7459           0 :         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
    7460           0 :         r->parameters                = talloc_strdup(mem_ctx, "");
    7461           0 :         W_ERROR_HAVE_NO_MEMORY(r->parameters);
    7462           0 :         r->driver_name               = talloc_strdup(mem_ctx, pinfo2->drivername);
    7463           0 :         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
    7464             : 
    7465           0 :         r->devmode           = devmode;
    7466             : 
    7467           0 :         r->text_status               = talloc_strdup(mem_ctx, "");
    7468           0 :         W_ERROR_HAVE_NO_MEMORY(r->text_status);
    7469             : 
    7470           0 :         r->secdesc           = NULL;
    7471             : 
    7472           0 :         r->status            = nt_printj_status(queue->status);
    7473           0 :         r->priority          = queue->priority;
    7474           0 :         r->position          = position;
    7475           0 :         r->start_time                = 0;
    7476           0 :         r->until_time                = 0;
    7477           0 :         r->total_pages               = queue->page_count;
    7478           0 :         r->size                      = queue->size;
    7479           0 :         init_systemtime(&r->submitted, t);
    7480           0 :         r->time                      = 0;
    7481           0 :         r->pages_printed     = 0; /* ??? */
    7482             : 
    7483           0 :         return WERR_OK;
    7484             : }
    7485             : 
    7486             : /****************************************************************************
    7487             :  Enumjobs at level 1.
    7488             : ****************************************************************************/
    7489             : 
    7490           0 : static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
    7491             :                               const print_queue_struct *queue,
    7492             :                               uint32_t num_queues, int snum,
    7493             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7494             :                               union spoolss_JobInfo **info_p,
    7495             :                               uint32_t *count)
    7496             : {
    7497             :         union spoolss_JobInfo *info;
    7498             :         int i;
    7499           0 :         WERROR result = WERR_OK;
    7500             :         uint32_t num_filled;
    7501             :         struct tdb_print_db *pdb;
    7502             : 
    7503           0 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7504           0 :         if (info == NULL) {
    7505           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7506           0 :                 goto err_out;
    7507             :         }
    7508             : 
    7509           0 :         pdb = get_print_db_byname(pinfo2->sharename);
    7510           0 :         if (pdb == NULL) {
    7511           0 :                 result = WERR_INVALID_PARAMETER;
    7512           0 :                 goto err_info_free;
    7513             :         }
    7514             : 
    7515           0 :         num_filled = 0;
    7516           0 :         for (i = 0; i < num_queues; i++) {
    7517           0 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7518           0 :                 if (jobid == (uint32_t)-1) {
    7519           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7520           0 :                         continue;
    7521             :                 }
    7522             : 
    7523           0 :                 result = fill_job_info1(info,
    7524           0 :                                         &info[num_filled].info1,
    7525           0 :                                         &queue[i],
    7526             :                                         jobid,
    7527             :                                         i,
    7528             :                                         snum,
    7529             :                                         pinfo2);
    7530           0 :                 if (!W_ERROR_IS_OK(result)) {
    7531           0 :                         goto err_pdb_drop;
    7532             :                 }
    7533             : 
    7534           0 :                 num_filled++;
    7535             :         }
    7536             : 
    7537           0 :         release_print_db(pdb);
    7538           0 :         *info_p = info;
    7539           0 :         *count = num_filled;
    7540             : 
    7541           0 :         return WERR_OK;
    7542             : 
    7543           0 : err_pdb_drop:
    7544           0 :         release_print_db(pdb);
    7545           0 : err_info_free:
    7546           0 :         TALLOC_FREE(info);
    7547           0 : err_out:
    7548           0 :         *count = 0;
    7549           0 :         return result;
    7550             : }
    7551             : 
    7552             : /****************************************************************************
    7553             :  Enumjobs at level 2.
    7554             : ****************************************************************************/
    7555             : 
    7556           0 : static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
    7557             :                               const print_queue_struct *queue,
    7558             :                               uint32_t num_queues, int snum,
    7559             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7560             :                               union spoolss_JobInfo **info_p,
    7561             :                               uint32_t *count)
    7562             : {
    7563             :         union spoolss_JobInfo *info;
    7564             :         int i;
    7565           0 :         WERROR result = WERR_OK;
    7566             :         uint32_t num_filled;
    7567             :         struct tdb_print_db *pdb;
    7568             : 
    7569           0 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7570           0 :         if (info == NULL) {
    7571           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7572           0 :                 goto err_out;
    7573             :         }
    7574             : 
    7575           0 :         pdb = get_print_db_byname(pinfo2->sharename);
    7576           0 :         if (pdb == NULL) {
    7577           0 :                 result = WERR_INVALID_PARAMETER;
    7578           0 :                 goto err_info_free;
    7579             :         }
    7580             : 
    7581           0 :         num_filled = 0;
    7582           0 :         for (i = 0; i< num_queues; i++) {
    7583             :                 struct spoolss_DeviceMode *devmode;
    7584           0 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7585           0 :                 if (jobid == (uint32_t)-1) {
    7586           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7587           0 :                         continue;
    7588             :                 }
    7589             : 
    7590           0 :                 result = spoolss_create_default_devmode(info,
    7591             :                                                         pinfo2->printername,
    7592             :                                                         &devmode);
    7593           0 :                 if (!W_ERROR_IS_OK(result)) {
    7594           0 :                         DEBUG(3, ("Can't proceed w/o a devmode!"));
    7595           0 :                         goto err_pdb_drop;
    7596             :                 }
    7597             : 
    7598           0 :                 result = fill_job_info2(info,
    7599           0 :                                         &info[num_filled].info2,
    7600           0 :                                         &queue[i],
    7601             :                                         jobid,
    7602             :                                         i,
    7603             :                                         snum,
    7604             :                                         pinfo2,
    7605             :                                         devmode);
    7606           0 :                 if (!W_ERROR_IS_OK(result)) {
    7607           0 :                         goto err_pdb_drop;
    7608             :                 }
    7609           0 :                 num_filled++;
    7610             :         }
    7611             : 
    7612           0 :         release_print_db(pdb);
    7613           0 :         *info_p = info;
    7614           0 :         *count = num_filled;
    7615             : 
    7616           0 :         return WERR_OK;
    7617             : 
    7618           0 : err_pdb_drop:
    7619           0 :         release_print_db(pdb);
    7620           0 : err_info_free:
    7621           0 :         TALLOC_FREE(info);
    7622           0 : err_out:
    7623           0 :         *count = 0;
    7624           0 :         return result;
    7625             : }
    7626             : 
    7627             : /****************************************************************************
    7628             :  Enumjobs at level 3.
    7629             : ****************************************************************************/
    7630             : 
    7631           0 : static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
    7632             :                               const print_queue_struct *queue,
    7633             :                               uint32_t num_queues, int snum,
    7634             :                               struct spoolss_PrinterInfo2 *pinfo2,
    7635             :                               union spoolss_JobInfo **info_p,
    7636             :                               uint32_t *count)
    7637             : {
    7638             :         union spoolss_JobInfo *info;
    7639             :         int i;
    7640           0 :         WERROR result = WERR_OK;
    7641             :         uint32_t num_filled;
    7642             :         struct tdb_print_db *pdb;
    7643             : 
    7644           0 :         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
    7645           0 :         if (info == NULL) {
    7646           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    7647           0 :                 goto err_out;
    7648             :         }
    7649             : 
    7650           0 :         pdb = get_print_db_byname(pinfo2->sharename);
    7651           0 :         if (pdb == NULL) {
    7652           0 :                 result = WERR_INVALID_PARAMETER;
    7653           0 :                 goto err_info_free;
    7654             :         }
    7655             : 
    7656           0 :         num_filled = 0;
    7657           0 :         for (i = 0; i < num_queues; i++) {
    7658           0 :                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
    7659           0 :                 if (jobid == (uint32_t)-1) {
    7660           0 :                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
    7661           0 :                         continue;
    7662             :                 }
    7663             : 
    7664           0 :                 info[num_filled].info3.job_id = jobid;
    7665             :                 /* next_job_id is overwritten on next iteration */
    7666           0 :                 info[num_filled].info3.next_job_id = 0;
    7667           0 :                 info[num_filled].info3.reserved = 0;
    7668             : 
    7669           0 :                 if (num_filled > 0) {
    7670           0 :                         info[num_filled - 1].info3.next_job_id = jobid;
    7671             :                 }
    7672           0 :                 num_filled++;
    7673             :         }
    7674             : 
    7675           0 :         release_print_db(pdb);
    7676           0 :         *info_p = info;
    7677           0 :         *count = num_filled;
    7678             : 
    7679           0 :         return WERR_OK;
    7680             : 
    7681           0 : err_info_free:
    7682           0 :         TALLOC_FREE(info);
    7683           0 : err_out:
    7684           0 :         *count = 0;
    7685           0 :         return result;
    7686             : }
    7687             : 
    7688             : /****************************************************************
    7689             :  _spoolss_EnumJobs
    7690             : ****************************************************************/
    7691             : 
    7692           0 : WERROR _spoolss_EnumJobs(struct pipes_struct *p,
    7693             :                          struct spoolss_EnumJobs *r)
    7694             : {
    7695             :         WERROR result;
    7696           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    7697             :         int snum;
    7698             :         print_status_struct prt_status;
    7699           0 :         print_queue_struct *queue = NULL;
    7700             :         uint32_t count;
    7701             : 
    7702             :         /* that's an [in out] buffer */
    7703             : 
    7704           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    7705           0 :                 return WERR_INVALID_PARAMETER;
    7706             :         }
    7707             : 
    7708           0 :         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
    7709           0 :                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
    7710           0 :                 return WERR_INVALID_LEVEL;
    7711             :         }
    7712             : 
    7713           0 :         DEBUG(4,("_spoolss_EnumJobs\n"));
    7714             : 
    7715           0 :         *r->out.needed = 0;
    7716           0 :         *r->out.count = 0;
    7717           0 :         *r->out.info = NULL;
    7718             : 
    7719             :         /* lookup the printer snum and tdb entry */
    7720             : 
    7721           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7722           0 :                 return WERR_INVALID_HANDLE;
    7723             :         }
    7724             : 
    7725           0 :         result = winreg_get_printer_internal(p->mem_ctx,
    7726             :                                     get_session_info_system(),
    7727             :                                     p->msg_ctx,
    7728             :                                     lp_const_servicename(snum),
    7729             :                                     &pinfo2);
    7730           0 :         if (!W_ERROR_IS_OK(result)) {
    7731           0 :                 return result;
    7732             :         }
    7733             : 
    7734           0 :         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
    7735           0 :         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
    7736             :                 count, prt_status.status, prt_status.message));
    7737             : 
    7738           0 :         if (count == 0) {
    7739           0 :                 SAFE_FREE(queue);
    7740           0 :                 TALLOC_FREE(pinfo2);
    7741           0 :                 return WERR_OK;
    7742             :         }
    7743             : 
    7744           0 :         switch (r->in.level) {
    7745           0 :         case 1:
    7746           0 :                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
    7747             :                                          pinfo2, r->out.info, r->out.count);
    7748           0 :                 break;
    7749           0 :         case 2:
    7750           0 :                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
    7751             :                                          pinfo2, r->out.info, r->out.count);
    7752           0 :                 break;
    7753           0 :         case 3:
    7754           0 :                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
    7755             :                                          pinfo2, r->out.info, r->out.count);
    7756           0 :                 break;
    7757           0 :         default:
    7758           0 :                 SMB_ASSERT(false);      /* level checked on entry */
    7759             :                 break;
    7760             :         }
    7761             : 
    7762           0 :         SAFE_FREE(queue);
    7763           0 :         TALLOC_FREE(pinfo2);
    7764             : 
    7765           0 :         if (!W_ERROR_IS_OK(result)) {
    7766           0 :                 return result;
    7767             :         }
    7768             : 
    7769           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    7770             :                                                      spoolss_EnumJobs,
    7771             :                                                      *r->out.info, r->in.level,
    7772             :                                                      *r->out.count);
    7773           0 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    7774           0 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    7775             : 
    7776           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    7777             : }
    7778             : 
    7779             : /****************************************************************
    7780             :  _spoolss_ScheduleJob
    7781             : ****************************************************************/
    7782             : 
    7783           0 : WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
    7784             :                             struct spoolss_ScheduleJob *r)
    7785             : {
    7786           0 :         return WERR_OK;
    7787             : }
    7788             : 
    7789             : /****************************************************************
    7790             : ****************************************************************/
    7791             : 
    7792           0 : static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
    7793             :                                struct messaging_context *msg_ctx,
    7794             :                                const char *printer_name,
    7795             :                                uint32_t job_id,
    7796             :                                struct spoolss_SetJobInfo1 *r)
    7797             : {
    7798             :         char *old_doc_name;
    7799             : 
    7800           0 :         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
    7801           0 :                 return WERR_INVALID_HANDLE;
    7802             :         }
    7803             : 
    7804           0 :         if (strequal(old_doc_name, r->document_name)) {
    7805           0 :                 return WERR_OK;
    7806             :         }
    7807             : 
    7808           0 :         if (!print_job_set_name(global_event_context(), msg_ctx,
    7809             :                                 printer_name, job_id, r->document_name)) {
    7810           0 :                 return WERR_INVALID_HANDLE;
    7811             :         }
    7812             : 
    7813           0 :         return WERR_OK;
    7814             : }
    7815             : 
    7816             : /****************************************************************
    7817             :  _spoolss_SetJob
    7818             : ****************************************************************/
    7819             : 
    7820           0 : WERROR _spoolss_SetJob(struct pipes_struct *p,
    7821             :                        struct spoolss_SetJob *r)
    7822             : {
    7823           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    7824           0 :         struct auth_session_info *session_info =
    7825           0 :                 dcesrv_call_session_info(dce_call);
    7826             :         int snum;
    7827           0 :         WERROR errcode = WERR_INVALID_FUNCTION;
    7828             : 
    7829           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    7830           0 :                 return WERR_INVALID_HANDLE;
    7831             :         }
    7832             : 
    7833           0 :         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
    7834           0 :                 return WERR_INVALID_PRINTER_NAME;
    7835             :         }
    7836             : 
    7837           0 :         switch (r->in.command) {
    7838           0 :         case SPOOLSS_JOB_CONTROL_CANCEL:
    7839             :         case SPOOLSS_JOB_CONTROL_DELETE:
    7840           0 :                 errcode = print_job_delete(session_info, p->msg_ctx,
    7841             :                                            snum, r->in.job_id);
    7842           0 :                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
    7843           0 :                         errcode = WERR_OK;
    7844             :                 }
    7845           0 :                 break;
    7846           0 :         case SPOOLSS_JOB_CONTROL_PAUSE:
    7847           0 :                 errcode = print_job_pause(session_info, p->msg_ctx,
    7848             :                                           snum, r->in.job_id);
    7849           0 :                 break;
    7850           0 :         case SPOOLSS_JOB_CONTROL_RESTART:
    7851             :         case SPOOLSS_JOB_CONTROL_RESUME:
    7852           0 :                 errcode = print_job_resume(session_info, p->msg_ctx,
    7853             :                                            snum, r->in.job_id);
    7854           0 :                 break;
    7855           0 :         case SPOOLSS_JOB_CONTROL_NOOP:
    7856           0 :                 errcode = WERR_OK;
    7857           0 :                 break;
    7858           0 :         default:
    7859           0 :                 return WERR_INVALID_LEVEL;
    7860             :         }
    7861             : 
    7862           0 :         if (!W_ERROR_IS_OK(errcode)) {
    7863           0 :                 return errcode;
    7864             :         }
    7865             : 
    7866           0 :         if (r->in.ctr == NULL) {
    7867           0 :                 return errcode;
    7868             :         }
    7869             : 
    7870           0 :         switch (r->in.ctr->level) {
    7871           0 :         case 1:
    7872           0 :                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
    7873             :                                            lp_const_servicename(snum),
    7874             :                                            r->in.job_id,
    7875           0 :                                            r->in.ctr->info.info1);
    7876           0 :                 break;
    7877           0 :         case 2:
    7878             :         case 3:
    7879             :         case 4:
    7880             :         default:
    7881           0 :                 return WERR_INVALID_LEVEL;
    7882             :         }
    7883             : 
    7884           0 :         return errcode;
    7885             : }
    7886             : 
    7887             : /****************************************************************************
    7888             :  Enumerates all printer drivers by level and architecture.
    7889             : ****************************************************************************/
    7890             : 
    7891           0 : static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
    7892             :                                                        const struct auth_session_info *session_info,
    7893             :                                                        struct messaging_context *msg_ctx,
    7894             :                                                        const char *servername,
    7895             :                                                        const char *architecture,
    7896             :                                                        uint32_t level,
    7897             :                                                        union spoolss_DriverInfo **info_p,
    7898             :                                                        uint32_t *count_p)
    7899             : {
    7900             :         int i;
    7901             :         uint32_t version;
    7902             :         struct spoolss_DriverInfo8 *driver;
    7903           0 :         union spoolss_DriverInfo *info = NULL;
    7904           0 :         uint32_t count = 0;
    7905           0 :         WERROR result = WERR_OK;
    7906             :         uint32_t num_drivers;
    7907             :         const char **drivers;
    7908             :         struct dcerpc_binding_handle *b;
    7909           0 :         TALLOC_CTX *tmp_ctx = NULL;
    7910             : 
    7911           0 :         *count_p = 0;
    7912           0 :         *info_p = NULL;
    7913             : 
    7914           0 :         tmp_ctx = talloc_new(mem_ctx);
    7915           0 :         if (!tmp_ctx) {
    7916           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    7917             :         }
    7918             : 
    7919           0 :         result = winreg_printer_binding_handle(tmp_ctx,
    7920             :                                                session_info,
    7921             :                                                msg_ctx,
    7922             :                                                &b);
    7923           0 :         if (!W_ERROR_IS_OK(result)) {
    7924           0 :                 goto out;
    7925             :         }
    7926             : 
    7927           0 :         for (version=0; version<DRIVER_MAX_VERSION; version++) {
    7928           0 :                 result = winreg_get_driver_list(tmp_ctx, b,
    7929             :                                                 architecture, version,
    7930             :                                                 &num_drivers, &drivers);
    7931           0 :                 if (!W_ERROR_IS_OK(result)) {
    7932           0 :                         goto out;
    7933             :                 }
    7934           0 :                 DEBUG(4, ("we have:[%d] drivers in environment"
    7935             :                           " [%s] and version [%d]\n",
    7936             :                           num_drivers, architecture, version));
    7937             : 
    7938           0 :                 if (num_drivers != 0) {
    7939           0 :                         info = talloc_realloc(tmp_ctx, info,
    7940             :                                                     union spoolss_DriverInfo,
    7941             :                                                     count + num_drivers);
    7942           0 :                         if (!info) {
    7943           0 :                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
    7944             :                                         "failed to enlarge driver info buffer!\n"));
    7945           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
    7946           0 :                                 goto out;
    7947             :                         }
    7948             :                 }
    7949             : 
    7950           0 :                 for (i = 0; i < num_drivers; i++) {
    7951           0 :                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
    7952             : 
    7953           0 :                         result = winreg_get_driver(tmp_ctx, b,
    7954           0 :                                                    architecture, drivers[i],
    7955             :                                                    version, &driver);
    7956           0 :                         if (!W_ERROR_IS_OK(result)) {
    7957           0 :                                 goto out;
    7958             :                         }
    7959             : 
    7960           0 :                         switch (level) {
    7961           0 :                         case 1:
    7962           0 :                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
    7963             :                                                                    driver, servername);
    7964           0 :                                 break;
    7965           0 :                         case 2:
    7966           0 :                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
    7967             :                                                                    driver, servername);
    7968           0 :                                 break;
    7969           0 :                         case 3:
    7970           0 :                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
    7971             :                                                                    driver, servername);
    7972           0 :                                 break;
    7973           0 :                         case 4:
    7974           0 :                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
    7975             :                                                                    driver, servername);
    7976           0 :                                 break;
    7977           0 :                         case 5:
    7978           0 :                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
    7979             :                                                                    driver, servername);
    7980           0 :                                 break;
    7981           0 :                         case 6:
    7982           0 :                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
    7983             :                                                                    driver, servername);
    7984           0 :                                 break;
    7985           0 :                         case 8:
    7986           0 :                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
    7987             :                                                                    driver, servername);
    7988           0 :                                 break;
    7989           0 :                         default:
    7990           0 :                                 result = WERR_INVALID_LEVEL;
    7991           0 :                                 break;
    7992             :                         }
    7993             : 
    7994           0 :                         TALLOC_FREE(driver);
    7995             : 
    7996           0 :                         if (!W_ERROR_IS_OK(result)) {
    7997           0 :                                 goto out;
    7998             :                         }
    7999             :                 }
    8000             : 
    8001           0 :                 count += num_drivers;
    8002           0 :                 TALLOC_FREE(drivers);
    8003             :         }
    8004             : 
    8005           0 : out:
    8006           0 :         if (W_ERROR_IS_OK(result)) {
    8007           0 :                 *info_p = talloc_move(mem_ctx, &info);
    8008           0 :                 *count_p = count;
    8009             :         }
    8010             : 
    8011           0 :         talloc_free(tmp_ctx);
    8012           0 :         return result;
    8013             : }
    8014             : 
    8015             : /****************************************************************************
    8016             :  Enumerates all printer drivers by level.
    8017             : ****************************************************************************/
    8018             : 
    8019           0 : static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
    8020             :                                        const struct auth_session_info *session_info,
    8021             :                                        struct messaging_context *msg_ctx,
    8022             :                                        const char *servername,
    8023             :                                        const char *architecture,
    8024             :                                        uint32_t level,
    8025             :                                        union spoolss_DriverInfo **info_p,
    8026             :                                        uint32_t *count_p)
    8027             : {
    8028             :         uint32_t a,i;
    8029           0 :         WERROR result = WERR_OK;
    8030             : 
    8031           0 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
    8032             : 
    8033           0 :                 for (a=0; archi_table[a].long_archi != NULL; a++) {
    8034             : 
    8035           0 :                         union spoolss_DriverInfo *info = NULL;
    8036           0 :                         uint32_t count = 0;
    8037             : 
    8038           0 :                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
    8039             :                                                                           session_info,
    8040             :                                                                           msg_ctx,
    8041             :                                                                           servername,
    8042           0 :                                                                           archi_table[a].long_archi,
    8043             :                                                                           level,
    8044             :                                                                           &info,
    8045             :                                                                           &count);
    8046           0 :                         if (!W_ERROR_IS_OK(result)) {
    8047           0 :                                 continue;
    8048             :                         }
    8049             : 
    8050           0 :                         for (i=0; i < count; i++) {
    8051           0 :                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
    8052             :                                              info[i], info_p, count_p);
    8053             :                         }
    8054             :                 }
    8055             : 
    8056           0 :                 return result;
    8057             :         }
    8058             : 
    8059           0 :         return enumprinterdrivers_level_by_architecture(mem_ctx,
    8060             :                                                         session_info,
    8061             :                                                         msg_ctx,
    8062             :                                                         servername,
    8063             :                                                         architecture,
    8064             :                                                         level,
    8065             :                                                         info_p,
    8066             :                                                         count_p);
    8067             : }
    8068             : 
    8069             : /****************************************************************
    8070             :  _spoolss_EnumPrinterDrivers
    8071             : ****************************************************************/
    8072             : 
    8073           0 : WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
    8074             :                                    struct spoolss_EnumPrinterDrivers *r)
    8075             : {
    8076             :         const char *cservername;
    8077             :         WERROR result;
    8078             : 
    8079             :         /* that's an [in out] buffer */
    8080             : 
    8081           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8082           0 :                 return WERR_INVALID_PARAMETER;
    8083             :         }
    8084             : 
    8085           0 :         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
    8086             : 
    8087           0 :         *r->out.needed = 0;
    8088           0 :         *r->out.count = 0;
    8089           0 :         *r->out.info = NULL;
    8090             : 
    8091           0 :         cservername = canon_servername(r->in.server);
    8092             : 
    8093           0 :         if (!is_myname_or_ipaddr(cservername)) {
    8094           0 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    8095             :         }
    8096             : 
    8097           0 :         result = enumprinterdrivers_level(p->mem_ctx,
    8098             :                                           get_session_info_system(),
    8099             :                                           p->msg_ctx,
    8100             :                                           cservername,
    8101             :                                           r->in.environment,
    8102             :                                           r->in.level,
    8103             :                                           r->out.info,
    8104             :                                           r->out.count);
    8105           0 :         if (!W_ERROR_IS_OK(result)) {
    8106           0 :                 return result;
    8107             :         }
    8108             : 
    8109           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8110             :                                                      spoolss_EnumPrinterDrivers,
    8111             :                                                      *r->out.info, r->in.level,
    8112             :                                                      *r->out.count);
    8113           0 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8114           0 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8115             : 
    8116           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8117             : }
    8118             : 
    8119             : /****************************************************************
    8120             :  _spoolss_EnumForms
    8121             : ****************************************************************/
    8122             : 
    8123           0 : WERROR _spoolss_EnumForms(struct pipes_struct *p,
    8124             :                           struct spoolss_EnumForms *r)
    8125             : {
    8126             :         WERROR result;
    8127             : 
    8128           0 :         *r->out.count = 0;
    8129           0 :         *r->out.needed = 0;
    8130           0 :         *r->out.info = NULL;
    8131             : 
    8132             :         /* that's an [in out] buffer */
    8133             : 
    8134           0 :         if (!r->in.buffer && (r->in.offered != 0) ) {
    8135           0 :                 return WERR_INVALID_PARAMETER;
    8136             :         }
    8137             : 
    8138           0 :         DEBUG(4,("_spoolss_EnumForms\n"));
    8139           0 :         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
    8140           0 :         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
    8141             : 
    8142           0 :         switch (r->in.level) {
    8143           0 :         case 1:
    8144           0 :                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
    8145             :                                                    get_session_info_system(),
    8146             :                                                    p->msg_ctx,
    8147             :                                                    r->out.count,
    8148             :                                                    r->out.info);
    8149           0 :                 break;
    8150           0 :         default:
    8151           0 :                 result = WERR_INVALID_LEVEL;
    8152           0 :                 break;
    8153             :         }
    8154             : 
    8155           0 :         if (!W_ERROR_IS_OK(result)) {
    8156           0 :                 return result;
    8157             :         }
    8158             : 
    8159           0 :         if (*r->out.count == 0) {
    8160           0 :                 return WERR_NO_MORE_ITEMS;
    8161             :         }
    8162             : 
    8163           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8164             :                                                      spoolss_EnumForms,
    8165             :                                                      *r->out.info, r->in.level,
    8166             :                                                      *r->out.count);
    8167           0 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8168           0 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8169             : 
    8170           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8171             : }
    8172             : 
    8173             : /****************************************************************
    8174             :  _spoolss_GetForm
    8175             : ****************************************************************/
    8176             : 
    8177           0 : WERROR _spoolss_GetForm(struct pipes_struct *p,
    8178             :                         struct spoolss_GetForm *r)
    8179             : {
    8180             :         WERROR result;
    8181             : 
    8182             :         /* that's an [in out] buffer */
    8183             : 
    8184           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8185           0 :                 TALLOC_FREE(r->out.info);
    8186           0 :                 return WERR_INVALID_PARAMETER;
    8187             :         }
    8188             : 
    8189           0 :         DEBUG(4,("_spoolss_GetForm\n"));
    8190           0 :         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
    8191           0 :         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
    8192             : 
    8193           0 :         switch (r->in.level) {
    8194           0 :         case 1:
    8195           0 :                 result = winreg_printer_getform1_internal(p->mem_ctx,
    8196             :                                                  get_session_info_system(),
    8197             :                                                  p->msg_ctx,
    8198             :                                                  r->in.form_name,
    8199           0 :                                                  &r->out.info->info1);
    8200           0 :                 break;
    8201           0 :         default:
    8202           0 :                 result = WERR_INVALID_LEVEL;
    8203           0 :                 break;
    8204             :         }
    8205             : 
    8206           0 :         if (!W_ERROR_IS_OK(result)) {
    8207           0 :                 TALLOC_FREE(r->out.info);
    8208           0 :                 return result;
    8209             :         }
    8210             : 
    8211           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
    8212             :                                                r->out.info, r->in.level);
    8213           0 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    8214             : 
    8215           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8216             : }
    8217             : 
    8218             : /****************************************************************************
    8219             : ****************************************************************************/
    8220             : 
    8221           0 : static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
    8222             :                           struct spoolss_PortInfo1 *r,
    8223             :                           const char *name)
    8224             : {
    8225           0 :         r->port_name = talloc_strdup(mem_ctx, name);
    8226           0 :         W_ERROR_HAVE_NO_MEMORY(r->port_name);
    8227             : 
    8228           0 :         return WERR_OK;
    8229             : }
    8230             : 
    8231             : /****************************************************************************
    8232             :  TODO: This probably needs distinguish between TCP/IP and Local ports
    8233             :  somehow.
    8234             : ****************************************************************************/
    8235             : 
    8236           0 : static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
    8237             :                           struct spoolss_PortInfo2 *r,
    8238             :                           const char *name)
    8239             : {
    8240           0 :         r->port_name = talloc_strdup(mem_ctx, name);
    8241           0 :         W_ERROR_HAVE_NO_MEMORY(r->port_name);
    8242             : 
    8243           0 :         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
    8244           0 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    8245             : 
    8246           0 :         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
    8247           0 :         W_ERROR_HAVE_NO_MEMORY(r->description);
    8248             : 
    8249           0 :         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
    8250           0 :         r->reserved = 0;
    8251             : 
    8252           0 :         return WERR_OK;
    8253             : }
    8254             : 
    8255             : 
    8256             : /****************************************************************************
    8257             :  wrapper around the enumer ports command
    8258             : ****************************************************************************/
    8259             : 
    8260           0 : static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
    8261             : {
    8262           0 :         const struct loadparm_substitution *lp_sub =
    8263           0 :                 loadparm_s3_global_substitution();
    8264           0 :         char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
    8265           0 :         char **qlines = NULL;
    8266           0 :         char *command = NULL;
    8267             :         int numlines;
    8268             :         int ret;
    8269             :         int fd;
    8270             : 
    8271           0 :         *count = 0;
    8272           0 :         *lines = NULL;
    8273             : 
    8274             :         /* if no hook then just fill in the default port */
    8275             : 
    8276           0 :         if ( !*cmd ) {
    8277           0 :                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
    8278           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8279             :                 }
    8280           0 :                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
    8281           0 :                         TALLOC_FREE(qlines);
    8282           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8283             :                 }
    8284           0 :                 qlines[1] = NULL;
    8285           0 :                 numlines = 1;
    8286             :         }
    8287             :         else {
    8288             :                 /* we have a valid enumport command */
    8289             : 
    8290           0 :                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
    8291           0 :                 if (!command) {
    8292           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8293             :                 }
    8294             : 
    8295           0 :                 DEBUG(10,("Running [%s]\n", command));
    8296           0 :                 ret = smbrun(command, &fd, NULL);
    8297           0 :                 DEBUG(10,("Returned [%d]\n", ret));
    8298           0 :                 TALLOC_FREE(command);
    8299           0 :                 if (ret != 0) {
    8300           0 :                         if (fd != -1) {
    8301           0 :                                 close(fd);
    8302             :                         }
    8303           0 :                         return WERR_ACCESS_DENIED;
    8304             :                 }
    8305             : 
    8306           0 :                 numlines = 0;
    8307           0 :                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
    8308           0 :                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
    8309           0 :                 close(fd);
    8310             :         }
    8311             : 
    8312           0 :         *count = numlines;
    8313           0 :         *lines = qlines;
    8314             : 
    8315           0 :         return WERR_OK;
    8316             : }
    8317             : 
    8318             : /****************************************************************************
    8319             :  enumports level 1.
    8320             : ****************************************************************************/
    8321             : 
    8322           0 : static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
    8323             :                                 union spoolss_PortInfo **info_p,
    8324             :                                 uint32_t *count)
    8325             : {
    8326           0 :         union spoolss_PortInfo *info = NULL;
    8327           0 :         int i=0;
    8328           0 :         WERROR result = WERR_OK;
    8329           0 :         char **qlines = NULL;
    8330           0 :         int numlines = 0;
    8331             : 
    8332           0 :         result = enumports_hook(talloc_tos(), &numlines, &qlines );
    8333           0 :         if (!W_ERROR_IS_OK(result)) {
    8334           0 :                 goto out;
    8335             :         }
    8336             : 
    8337           0 :         if (numlines) {
    8338           0 :                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
    8339           0 :                 if (!info) {
    8340           0 :                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
    8341           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    8342           0 :                         goto out;
    8343             :                 }
    8344             : 
    8345           0 :                 for (i=0; i<numlines; i++) {
    8346           0 :                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
    8347           0 :                         result = fill_port_1(info, &info[i].info1, qlines[i]);
    8348           0 :                         if (!W_ERROR_IS_OK(result)) {
    8349           0 :                                 goto out;
    8350             :                         }
    8351             :                 }
    8352             :         }
    8353           0 :         TALLOC_FREE(qlines);
    8354             : 
    8355           0 : out:
    8356           0 :         if (!W_ERROR_IS_OK(result)) {
    8357           0 :                 TALLOC_FREE(info);
    8358           0 :                 TALLOC_FREE(qlines);
    8359           0 :                 *count = 0;
    8360           0 :                 *info_p = NULL;
    8361           0 :                 return result;
    8362             :         }
    8363             : 
    8364           0 :         *info_p = info;
    8365           0 :         *count = numlines;
    8366             : 
    8367           0 :         return WERR_OK;
    8368             : }
    8369             : 
    8370             : /****************************************************************************
    8371             :  enumports level 2.
    8372             : ****************************************************************************/
    8373             : 
    8374           0 : static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
    8375             :                                 union spoolss_PortInfo **info_p,
    8376             :                                 uint32_t *count)
    8377             : {
    8378           0 :         union spoolss_PortInfo *info = NULL;
    8379           0 :         int i=0;
    8380           0 :         WERROR result = WERR_OK;
    8381           0 :         char **qlines = NULL;
    8382           0 :         int numlines = 0;
    8383             : 
    8384           0 :         result = enumports_hook(talloc_tos(), &numlines, &qlines );
    8385           0 :         if (!W_ERROR_IS_OK(result)) {
    8386           0 :                 goto out;
    8387             :         }
    8388             : 
    8389           0 :         if (numlines) {
    8390           0 :                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
    8391           0 :                 if (!info) {
    8392           0 :                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
    8393           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    8394           0 :                         goto out;
    8395             :                 }
    8396             : 
    8397           0 :                 for (i=0; i<numlines; i++) {
    8398           0 :                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
    8399           0 :                         result = fill_port_2(info, &info[i].info2, qlines[i]);
    8400           0 :                         if (!W_ERROR_IS_OK(result)) {
    8401           0 :                                 goto out;
    8402             :                         }
    8403             :                 }
    8404             :         }
    8405           0 :         TALLOC_FREE(qlines);
    8406             : 
    8407           0 : out:
    8408           0 :         if (!W_ERROR_IS_OK(result)) {
    8409           0 :                 TALLOC_FREE(info);
    8410           0 :                 TALLOC_FREE(qlines);
    8411           0 :                 *count = 0;
    8412           0 :                 *info_p = NULL;
    8413           0 :                 return result;
    8414             :         }
    8415             : 
    8416           0 :         *info_p = info;
    8417           0 :         *count = numlines;
    8418             : 
    8419           0 :         return WERR_OK;
    8420             : }
    8421             : 
    8422             : /****************************************************************
    8423             :  _spoolss_EnumPorts
    8424             : ****************************************************************/
    8425             : 
    8426           0 : WERROR _spoolss_EnumPorts(struct pipes_struct *p,
    8427             :                           struct spoolss_EnumPorts *r)
    8428             : {
    8429             :         WERROR result;
    8430             : 
    8431             :         /* that's an [in out] buffer */
    8432             : 
    8433           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8434           0 :                 return WERR_INVALID_PARAMETER;
    8435             :         }
    8436             : 
    8437           0 :         DEBUG(4,("_spoolss_EnumPorts\n"));
    8438             : 
    8439           0 :         *r->out.count = 0;
    8440           0 :         *r->out.needed = 0;
    8441           0 :         *r->out.info = NULL;
    8442             : 
    8443           0 :         switch (r->in.level) {
    8444           0 :         case 1:
    8445           0 :                 result = enumports_level_1(p->mem_ctx, r->out.info,
    8446             :                                            r->out.count);
    8447           0 :                 break;
    8448           0 :         case 2:
    8449           0 :                 result = enumports_level_2(p->mem_ctx, r->out.info,
    8450             :                                            r->out.count);
    8451           0 :                 break;
    8452           0 :         default:
    8453           0 :                 return WERR_INVALID_LEVEL;
    8454             :         }
    8455             : 
    8456           0 :         if (!W_ERROR_IS_OK(result)) {
    8457           0 :                 return result;
    8458             :         }
    8459             : 
    8460           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    8461             :                                                      spoolss_EnumPorts,
    8462             :                                                      *r->out.info, r->in.level,
    8463             :                                                      *r->out.count);
    8464           0 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    8465           0 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    8466             : 
    8467           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8468             : }
    8469             : 
    8470             : /****************************************************************************
    8471             : ****************************************************************************/
    8472             : 
    8473           0 : static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
    8474             :                                            const char *server,
    8475             :                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
    8476             :                                            struct spoolss_DeviceMode *devmode,
    8477             :                                            struct security_descriptor *secdesc,
    8478             :                                            struct spoolss_UserLevelCtr *user_ctr,
    8479             :                                            struct policy_handle *handle)
    8480             : {
    8481           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    8482           0 :         struct dcesrv_connection *dcesrv_conn = dce_call->conn;
    8483           0 :         const struct tsocket_address *remote_address =
    8484           0 :                 dcesrv_connection_get_remote_address(dcesrv_conn);
    8485           0 :         struct auth_session_info *session_info =
    8486           0 :                 dcesrv_call_session_info(dce_call);
    8487           0 :         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
    8488           0 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
    8489           0 :         const struct loadparm_substitution *lp_sub =
    8490           0 :                 loadparm_s3_global_substitution();
    8491             :         int     snum;
    8492           0 :         WERROR err = WERR_OK;
    8493             : 
    8494             :         /* samba does not have a concept of local, non-shared printers yet, so
    8495             :          * make sure we always setup sharename - gd */
    8496           0 :         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
    8497           0 :             (info2->printername != NULL && info2->printername[0] != '\0')) {
    8498           0 :                 DEBUG(5, ("spoolss_addprinterex_level_2: "
    8499             :                         "no sharename has been set, setting printername %s as sharename\n",
    8500             :                         info2->printername));
    8501           0 :                 info2->sharename = info2->printername;
    8502             :         }
    8503             : 
    8504             :         /* check to see if the printer already exists */
    8505           0 :         if ((snum = print_queue_snum(info2->sharename)) != -1) {
    8506           0 :                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
    8507             :                         info2->sharename));
    8508           0 :                 return WERR_PRINTER_ALREADY_EXISTS;
    8509             :         }
    8510             : 
    8511           0 :         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
    8512           0 :                 if ((snum = print_queue_snum(info2->printername)) != -1) {
    8513           0 :                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
    8514             :                                 info2->printername));
    8515           0 :                         return WERR_PRINTER_ALREADY_EXISTS;
    8516             :                 }
    8517             :         }
    8518             : 
    8519             :         /* validate printer info struct */
    8520           0 :         if (!info2->printername || strlen(info2->printername) == 0) {
    8521           0 :                 return WERR_INVALID_PRINTER_NAME;
    8522             :         }
    8523           0 :         if (!info2->portname || strlen(info2->portname) == 0) {
    8524           0 :                 return WERR_UNKNOWN_PORT;
    8525             :         }
    8526           0 :         if (!info2->drivername || strlen(info2->drivername) == 0) {
    8527           0 :                 return WERR_UNKNOWN_PRINTER_DRIVER;
    8528             :         }
    8529           0 :         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
    8530           0 :                 return WERR_UNKNOWN_PRINTPROCESSOR;
    8531             :         }
    8532             : 
    8533             :         /* FIXME!!!  smbd should check to see if the driver is installed before
    8534             :            trying to add a printer like this  --jerry */
    8535             : 
    8536           0 :         if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
    8537             :                 char *raddr;
    8538             : 
    8539           0 :                 raddr = tsocket_address_inet_addr_string(remote_address,
    8540             :                                                          p->mem_ctx);
    8541           0 :                 if (raddr == NULL) {
    8542           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    8543             :                 }
    8544             : 
    8545           0 :                 if ( !add_printer_hook(p->mem_ctx, session_info->security_token,
    8546             :                                        info2, raddr,
    8547             :                                        p->msg_ctx) ) {
    8548           0 :                         return WERR_ACCESS_DENIED;
    8549             :                 }
    8550             :         } else {
    8551           0 :                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
    8552             :                         "smb.conf parameter \"addprinter command\" is defined. This "
    8553             :                         "parameter must exist for this call to succeed\n",
    8554             :                         info2->sharename ));
    8555             :         }
    8556             : 
    8557           0 :         if ((snum = print_queue_snum(info2->sharename)) == -1) {
    8558           0 :                 return WERR_ACCESS_DENIED;
    8559             :         }
    8560             : 
    8561             :         /* you must be a printer admin to add a new printer */
    8562           0 :         if (!W_ERROR_IS_OK(print_access_check(session_info,
    8563             :                                               p->msg_ctx,
    8564             :                                               snum,
    8565             :                                               PRINTER_ACCESS_ADMINISTER))) {
    8566           0 :                 return WERR_ACCESS_DENIED;
    8567             :         }
    8568             : 
    8569             :         /*
    8570             :          * Do sanity check on the requested changes for Samba.
    8571             :          */
    8572             : 
    8573           0 :         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
    8574           0 :                 return WERR_INVALID_PARAMETER;
    8575             :         }
    8576             : 
    8577           0 :         if (devmode == NULL) {
    8578           0 :                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
    8579             :         }
    8580             : 
    8581           0 :         err = update_dsspooler(p->mem_ctx,
    8582             :                                get_session_info_system(),
    8583             :                                p->msg_ctx,
    8584             :                                0,
    8585             :                                info2,
    8586             :                                NULL);
    8587           0 :         if (!W_ERROR_IS_OK(err)) {
    8588           0 :                 return err;
    8589             :         }
    8590             : 
    8591           0 :         err = winreg_update_printer_internal(p->mem_ctx,
    8592             :                                     get_session_info_system(),
    8593             :                                     p->msg_ctx,
    8594             :                                     info2->sharename,
    8595             :                                     info2_mask,
    8596             :                                     info2,
    8597             :                                     devmode,
    8598             :                                     secdesc);
    8599           0 :         if (!W_ERROR_IS_OK(err)) {
    8600           0 :                 return err;
    8601             :         }
    8602             : 
    8603           0 :         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
    8604           0 :         if (!W_ERROR_IS_OK(err)) {
    8605             :                 /* Handle open failed - remove addition. */
    8606           0 :                 ZERO_STRUCTP(handle);
    8607           0 :                 return err;
    8608             :         }
    8609             : 
    8610           0 :         return WERR_OK;
    8611             : }
    8612             : 
    8613             : /****************************************************************
    8614             :  _spoolss_AddPrinterEx
    8615             : ****************************************************************/
    8616             : 
    8617           0 : WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
    8618             :                              struct spoolss_AddPrinterEx *r)
    8619             : {
    8620           0 :         switch (r->in.info_ctr->level) {
    8621           0 :         case 1:
    8622             :                 /* we don't handle yet */
    8623             :                 /* but I know what to do ... */
    8624           0 :                 return WERR_INVALID_LEVEL;
    8625           0 :         case 2:
    8626           0 :                 return spoolss_addprinterex_level_2(p, r->in.server,
    8627             :                                                     r->in.info_ctr,
    8628           0 :                                                     r->in.devmode_ctr->devmode,
    8629           0 :                                                     r->in.secdesc_ctr->sd,
    8630             :                                                     r->in.userlevel_ctr,
    8631             :                                                     r->out.handle);
    8632           0 :         default:
    8633           0 :                 return WERR_INVALID_LEVEL;
    8634             :         }
    8635             : }
    8636             : 
    8637             : /****************************************************************
    8638             :  _spoolss_AddPrinter
    8639             : ****************************************************************/
    8640             : 
    8641           0 : WERROR _spoolss_AddPrinter(struct pipes_struct *p,
    8642             :                            struct spoolss_AddPrinter *r)
    8643             : {
    8644             :         struct spoolss_AddPrinterEx a;
    8645             :         struct spoolss_UserLevelCtr userlevel_ctr;
    8646             : 
    8647           0 :         ZERO_STRUCT(userlevel_ctr);
    8648             : 
    8649           0 :         userlevel_ctr.level = 1;
    8650             : 
    8651           0 :         a.in.server             = r->in.server;
    8652           0 :         a.in.info_ctr           = r->in.info_ctr;
    8653           0 :         a.in.devmode_ctr        = r->in.devmode_ctr;
    8654           0 :         a.in.secdesc_ctr        = r->in.secdesc_ctr;
    8655           0 :         a.in.userlevel_ctr      = &userlevel_ctr;
    8656           0 :         a.out.handle            = r->out.handle;
    8657             : 
    8658           0 :         return _spoolss_AddPrinterEx(p, &a);
    8659             : }
    8660             : 
    8661             : /****************************************************************
    8662             :  _spoolss_AddPrinterDriverEx
    8663             : ****************************************************************/
    8664             : 
    8665           0 : WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
    8666             :                                    struct spoolss_AddPrinterDriverEx *r)
    8667             : {
    8668           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    8669           0 :         struct auth_session_info *session_info =
    8670           0 :                 dcesrv_call_session_info(dce_call);
    8671           0 :         WERROR err = WERR_OK;
    8672           0 :         const char *driver_name = NULL;
    8673           0 :         const char *driver_directory = NULL;
    8674             :         uint32_t version;
    8675             : 
    8676             :         /*
    8677             :          * we only support the semantics of AddPrinterDriver()
    8678             :          * i.e. only copy files that are newer than existing ones
    8679             :          */
    8680             : 
    8681           0 :         if (r->in.flags == 0) {
    8682           0 :                 return WERR_INVALID_PARAMETER;
    8683             :         }
    8684             : 
    8685           0 :         if (!(r->in.flags & APD_COPY_ALL_FILES) &&
    8686           0 :             !(r->in.flags & APD_COPY_NEW_FILES)) {
    8687           0 :                 return WERR_ACCESS_DENIED;
    8688             :         }
    8689             : 
    8690             :         /* FIXME */
    8691           0 :         if (r->in.info_ctr->level != 3 &&
    8692           0 :             r->in.info_ctr->level != 6 &&
    8693           0 :             r->in.info_ctr->level != 8) {
    8694           0 :                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
    8695             :                         r->in.info_ctr->level));
    8696           0 :                 return WERR_INVALID_LEVEL;
    8697             :         }
    8698             : 
    8699           0 :         DEBUG(5,("Cleaning driver's information\n"));
    8700           0 :         err = clean_up_driver_struct(p->mem_ctx,
    8701             :                                      session_info,
    8702           0 :                                      r->in.info_ctr,
    8703             :                                      r->in.flags,
    8704             :                                      &driver_directory);
    8705           0 :         if (!W_ERROR_IS_OK(err)) {
    8706           0 :                 DBG_ERR("clean_up_driver_struct failed - %s\n",
    8707             :                         win_errstr(err));
    8708           0 :                 goto done;
    8709             :         }
    8710             : 
    8711           0 :         DEBUG(5,("Moving driver to final destination\n"));
    8712           0 :         err = move_driver_to_download_area(session_info,
    8713           0 :                                            r->in.info_ctr,
    8714             :                                            driver_directory);
    8715           0 :         if (!W_ERROR_IS_OK(err)) {
    8716           0 :                 DBG_ERR("move_driver_to_download_area failed - %s\n",
    8717             :                         win_errstr(err));
    8718           0 :                 goto done;
    8719             :         }
    8720             : 
    8721           0 :         err = winreg_add_driver_internal(p->mem_ctx,
    8722             :                                 get_session_info_system(),
    8723             :                                 p->msg_ctx,
    8724             :                                 r->in.info_ctr,
    8725             :                                 &driver_name,
    8726             :                                 &version);
    8727           0 :         if (!W_ERROR_IS_OK(err)) {
    8728           0 :                 DBG_ERR("winreg_add_driver_internal failed - %s\n",
    8729             :                         win_errstr(err));
    8730           0 :                 goto done;
    8731             :         }
    8732             : 
    8733             :         /*
    8734             :          * I think this is where he DrvUpgradePrinter() hook would be
    8735             :          * be called in a driver's interface DLL on a Windows NT 4.0/2k
    8736             :          * server.  Right now, we just need to send ourselves a message
    8737             :          * to update each printer bound to this driver.   --jerry
    8738             :          */
    8739             : 
    8740           0 :         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
    8741           0 :                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
    8742             :                         __func__, driver_name));
    8743             :         }
    8744             : 
    8745           0 : done:
    8746           0 :         return err;
    8747             : }
    8748             : 
    8749             : /****************************************************************
    8750             :  _spoolss_AddPrinterDriver
    8751             : ****************************************************************/
    8752             : 
    8753           0 : WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
    8754             :                                  struct spoolss_AddPrinterDriver *r)
    8755             : {
    8756             :         struct spoolss_AddPrinterDriverEx a;
    8757             : 
    8758           0 :         switch (r->in.info_ctr->level) {
    8759           0 :         case 2:
    8760             :         case 3:
    8761             :         case 4:
    8762             :         case 5:
    8763           0 :                 break;
    8764           0 :         default:
    8765           0 :                 return WERR_INVALID_LEVEL;
    8766             :         }
    8767             : 
    8768           0 :         a.in.servername         = r->in.servername;
    8769           0 :         a.in.info_ctr           = r->in.info_ctr;
    8770           0 :         a.in.flags              = APD_COPY_NEW_FILES;
    8771             : 
    8772           0 :         return _spoolss_AddPrinterDriverEx(p, &a);
    8773             : }
    8774             : 
    8775             : /****************************************************************************
    8776             : ****************************************************************************/
    8777             : 
    8778             : struct _spoolss_paths {
    8779             :         int type;
    8780             :         const char *share;
    8781             :         const char *dir;
    8782             : };
    8783             : 
    8784             : enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
    8785             : 
    8786             : static const struct _spoolss_paths spoolss_paths[]= {
    8787             :         { SPOOLSS_DRIVER_PATH,          "print$",     "DRIVERS" },
    8788             :         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",   "PRTPROCS" }
    8789             : };
    8790             : 
    8791           0 : static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
    8792             :                                           const char *servername,
    8793             :                                           const char *environment,
    8794             :                                           int component,
    8795             :                                           char **path)
    8796             : {
    8797           0 :         const char *pservername = NULL;
    8798             :         const char *long_archi;
    8799             :         const char *short_archi;
    8800             : 
    8801           0 :         *path = NULL;
    8802             : 
    8803             :         /* environment may be empty */
    8804           0 :         if (environment && strlen(environment)) {
    8805           0 :                 long_archi = environment;
    8806             :         } else {
    8807           0 :                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    8808             :                                                   "spoolss", "architecture",
    8809             :                                                   GLOBAL_SPOOLSS_ARCHITECTURE);
    8810             :         }
    8811             : 
    8812             :         /* servername may be empty */
    8813           0 :         if (servername && strlen(servername)) {
    8814           0 :                 pservername = canon_servername(servername);
    8815             : 
    8816           0 :                 if (!is_myname_or_ipaddr(pservername)) {
    8817           0 :                         return WERR_INVALID_PARAMETER;
    8818             :                 }
    8819             :         }
    8820             : 
    8821           0 :         if (!(short_archi = get_short_archi(long_archi))) {
    8822           0 :                 return WERR_INVALID_ENVIRONMENT;
    8823             :         }
    8824             : 
    8825           0 :         switch (component) {
    8826           0 :         case SPOOLSS_PRTPROCS_PATH:
    8827             :         case SPOOLSS_DRIVER_PATH:
    8828           0 :                 if (pservername) {
    8829           0 :                         *path = talloc_asprintf(mem_ctx,
    8830             :                                         "\\\\%s\\%s\\%s",
    8831             :                                         pservername,
    8832           0 :                                         spoolss_paths[component].share,
    8833             :                                         short_archi);
    8834             :                 } else {
    8835           0 :                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
    8836             :                                         SPOOLSS_DEFAULT_SERVER_PATH,
    8837           0 :                                         spoolss_paths[component].dir,
    8838             :                                         short_archi);
    8839             :                 }
    8840           0 :                 break;
    8841           0 :         default:
    8842           0 :                 return WERR_INVALID_PARAMETER;
    8843             :         }
    8844             : 
    8845           0 :         if (!*path) {
    8846           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    8847             :         }
    8848             : 
    8849           0 :         return WERR_OK;
    8850             : }
    8851             : 
    8852             : /****************************************************************************
    8853             : ****************************************************************************/
    8854             : 
    8855           0 : static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
    8856             :                                           const char *servername,
    8857             :                                           const char *environment,
    8858             :                                           struct spoolss_DriverDirectoryInfo1 *r)
    8859             : {
    8860             :         WERROR werr;
    8861           0 :         char *path = NULL;
    8862             : 
    8863           0 :         werr = compose_spoolss_server_path(mem_ctx,
    8864             :                                            servername,
    8865             :                                            environment,
    8866             :                                            SPOOLSS_DRIVER_PATH,
    8867             :                                            &path);
    8868           0 :         if (!W_ERROR_IS_OK(werr)) {
    8869           0 :                 return werr;
    8870             :         }
    8871             : 
    8872           0 :         DEBUG(4,("printer driver directory: [%s]\n", path));
    8873             : 
    8874           0 :         r->directory_name = path;
    8875             : 
    8876           0 :         return WERR_OK;
    8877             : }
    8878             : 
    8879             : /****************************************************************
    8880             :  _spoolss_GetPrinterDriverDirectory
    8881             : ****************************************************************/
    8882             : 
    8883           0 : WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
    8884             :                                           struct spoolss_GetPrinterDriverDirectory *r)
    8885             : {
    8886             :         WERROR werror;
    8887             : 
    8888             :         /* that's an [in out] buffer */
    8889             : 
    8890           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    8891           0 :                 TALLOC_FREE(r->out.info);
    8892           0 :                 return WERR_INVALID_PARAMETER;
    8893             :         }
    8894             : 
    8895           0 :         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
    8896             :                 r->in.level));
    8897             : 
    8898           0 :         *r->out.needed = 0;
    8899             : 
    8900             :         /* r->in.level is ignored */
    8901             : 
    8902           0 :         werror = getprinterdriverdir_level_1(p->mem_ctx,
    8903             :                                              r->in.server,
    8904             :                                              r->in.environment,
    8905           0 :                                              &r->out.info->info1);
    8906           0 :         if (!W_ERROR_IS_OK(werror)) {
    8907           0 :                 TALLOC_FREE(r->out.info);
    8908           0 :                 return werror;
    8909             :         }
    8910             : 
    8911           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
    8912             :                                                r->out.info, r->in.level);
    8913           0 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    8914             : 
    8915           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    8916             : }
    8917             : 
    8918             : /****************************************************************
    8919             :  _spoolss_EnumPrinterData
    8920             : ****************************************************************/
    8921             : 
    8922           0 : WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
    8923             :                                 struct spoolss_EnumPrinterData *r)
    8924             : {
    8925             :         WERROR result;
    8926             :         struct spoolss_EnumPrinterDataEx r2;
    8927             :         uint32_t count;
    8928           0 :         struct spoolss_PrinterEnumValues *info, *val = NULL;
    8929             :         uint32_t needed;
    8930             : 
    8931           0 :         r2.in.handle    = r->in.handle;
    8932           0 :         r2.in.key_name  = "PrinterDriverData";
    8933           0 :         r2.in.offered   = 0;
    8934           0 :         r2.out.count    = &count;
    8935           0 :         r2.out.info     = &info;
    8936           0 :         r2.out.needed   = &needed;
    8937             : 
    8938           0 :         result = _spoolss_EnumPrinterDataEx(p, &r2);
    8939           0 :         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
    8940           0 :                 r2.in.offered = needed;
    8941           0 :                 result = _spoolss_EnumPrinterDataEx(p, &r2);
    8942             :         }
    8943           0 :         if (!W_ERROR_IS_OK(result)) {
    8944           0 :                 return result;
    8945             :         }
    8946             : 
    8947             :         /*
    8948             :          * The NT machine wants to know the biggest size of value and data
    8949             :          *
    8950             :          * cf: MSDN EnumPrinterData remark section
    8951             :          */
    8952             : 
    8953           0 :         if (!r->in.value_offered && !r->in.data_offered) {
    8954           0 :                 uint32_t biggest_valuesize = 0;
    8955           0 :                 uint32_t biggest_datasize = 0;
    8956             :                 int i, name_length;
    8957             : 
    8958           0 :                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
    8959             : 
    8960           0 :                 for (i=0; i<count; i++) {
    8961             : 
    8962           0 :                         name_length = strlen(info[i].value_name);
    8963           0 :                         if (strlen(info[i].value_name) > biggest_valuesize) {
    8964           0 :                                 biggest_valuesize = name_length;
    8965             :                         }
    8966             : 
    8967           0 :                         if (info[i].data_length > biggest_datasize) {
    8968           0 :                                 biggest_datasize = info[i].data_length;
    8969             :                         }
    8970             : 
    8971           0 :                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
    8972             :                                 biggest_datasize));
    8973             :                 }
    8974             : 
    8975             :                 /* the value is an UNICODE string but real_value_size is the length
    8976             :                    in bytes including the trailing 0 */
    8977             : 
    8978           0 :                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
    8979           0 :                 *r->out.data_needed  = biggest_datasize;
    8980             : 
    8981           0 :                 DEBUG(6,("final values: [%d], [%d]\n",
    8982             :                         *r->out.value_needed, *r->out.data_needed));
    8983             : 
    8984           0 :                 return WERR_OK;
    8985             :         }
    8986             : 
    8987           0 :         if (r->in.enum_index < count) {
    8988           0 :                 val = &info[r->in.enum_index];
    8989             :         }
    8990             : 
    8991           0 :         if (val == NULL) {
    8992             :                 /* out_value should default to "" or else NT4 has
    8993             :                    problems unmarshalling the response */
    8994             : 
    8995           0 :                 if (r->in.value_offered) {
    8996           0 :                         *r->out.value_needed = 1;
    8997           0 :                         r->out.value_name = talloc_strdup(r, "");
    8998           0 :                         if (!r->out.value_name) {
    8999           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    9000             :                         }
    9001             :                 } else {
    9002           0 :                         r->out.value_name = NULL;
    9003           0 :                         *r->out.value_needed = 0;
    9004             :                 }
    9005             : 
    9006             :                 /* the data is counted in bytes */
    9007             : 
    9008           0 :                 *r->out.data_needed = r->in.data_offered;
    9009             : 
    9010           0 :                 result = WERR_NO_MORE_ITEMS;
    9011             :         } else {
    9012             :                 /*
    9013             :                  * the value is:
    9014             :                  * - counted in bytes in the request
    9015             :                  * - counted in UNICODE chars in the max reply
    9016             :                  * - counted in bytes in the real size
    9017             :                  *
    9018             :                  * take a pause *before* coding not *during* coding
    9019             :                  */
    9020             : 
    9021             :                 /* name */
    9022           0 :                 if (r->in.value_offered) {
    9023           0 :                         r->out.value_name = talloc_strdup(r, val->value_name);
    9024           0 :                         if (!r->out.value_name) {
    9025           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    9026             :                         }
    9027           0 :                         *r->out.value_needed = val->value_name_len;
    9028             :                 } else {
    9029           0 :                         r->out.value_name = NULL;
    9030           0 :                         *r->out.value_needed = 0;
    9031             :                 }
    9032             : 
    9033             :                 /* type */
    9034             : 
    9035           0 :                 *r->out.type = val->type;
    9036             : 
    9037             :                 /* data - counted in bytes */
    9038             : 
    9039             :                 /*
    9040             :                  * See the section "Dynamically Typed Query Parameters"
    9041             :                  * in MS-RPRN.
    9042             :                  */
    9043             : 
    9044           0 :                 if (r->out.data && val->data && val->data->data &&
    9045           0 :                                 val->data_length && r->in.data_offered) {
    9046           0 :                         memcpy(r->out.data, val->data->data,
    9047           0 :                                 MIN(val->data_length,r->in.data_offered));
    9048             :                 }
    9049             : 
    9050           0 :                 *r->out.data_needed = val->data_length;
    9051             : 
    9052           0 :                 result = WERR_OK;
    9053             :         }
    9054             : 
    9055           0 :         return result;
    9056             : }
    9057             : 
    9058             : /****************************************************************
    9059             :  _spoolss_SetPrinterData
    9060             : ****************************************************************/
    9061             : 
    9062           0 : WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
    9063             :                                struct spoolss_SetPrinterData *r)
    9064             : {
    9065             :         struct spoolss_SetPrinterDataEx r2;
    9066             : 
    9067           0 :         r2.in.handle            = r->in.handle;
    9068           0 :         r2.in.key_name          = "PrinterDriverData";
    9069           0 :         r2.in.value_name        = r->in.value_name;
    9070           0 :         r2.in.type              = r->in.type;
    9071           0 :         r2.in.data              = r->in.data;
    9072           0 :         r2.in.offered           = r->in.offered;
    9073             : 
    9074           0 :         return _spoolss_SetPrinterDataEx(p, &r2);
    9075             : }
    9076             : 
    9077             : /****************************************************************
    9078             :  _spoolss_ResetPrinter
    9079             : ****************************************************************/
    9080             : 
    9081           0 : WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
    9082             :                              struct spoolss_ResetPrinter *r)
    9083             : {
    9084           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9085             :         int             snum;
    9086             : 
    9087           0 :         DEBUG(5,("_spoolss_ResetPrinter\n"));
    9088             : 
    9089             :         /*
    9090             :          * All we do is to check to see if the handle and queue is valid.
    9091             :          * This call really doesn't mean anything to us because we only
    9092             :          * support RAW printing.   --jerry
    9093             :          */
    9094             : 
    9095           0 :         if (!Printer) {
    9096           0 :                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
    9097             :                         OUR_HANDLE(r->in.handle)));
    9098           0 :                 return WERR_INVALID_HANDLE;
    9099             :         }
    9100             : 
    9101           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
    9102           0 :                 return WERR_INVALID_HANDLE;
    9103             : 
    9104             : 
    9105             :         /* blindly return success */
    9106           0 :         return WERR_OK;
    9107             : }
    9108             : 
    9109             : /****************************************************************
    9110             :  _spoolss_DeletePrinterData
    9111             : ****************************************************************/
    9112             : 
    9113           0 : WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
    9114             :                                   struct spoolss_DeletePrinterData *r)
    9115             : {
    9116             :         struct spoolss_DeletePrinterDataEx r2;
    9117             : 
    9118           0 :         r2.in.handle            = r->in.handle;
    9119           0 :         r2.in.key_name          = "PrinterDriverData";
    9120           0 :         r2.in.value_name        = r->in.value_name;
    9121             : 
    9122           0 :         return _spoolss_DeletePrinterDataEx(p, &r2);
    9123             : }
    9124             : 
    9125             : /****************************************************************
    9126             :  _spoolss_AddForm
    9127             : ****************************************************************/
    9128             : 
    9129           0 : WERROR _spoolss_AddForm(struct pipes_struct *p,
    9130             :                         struct spoolss_AddForm *r)
    9131             : {
    9132           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9133           0 :         struct auth_session_info *session_info =
    9134           0 :                 dcesrv_call_session_info(dce_call);
    9135             :         struct spoolss_AddFormInfo1 *form;
    9136           0 :         int snum = -1;
    9137           0 :         WERROR status = WERR_OK;
    9138           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9139             :         struct dcerpc_binding_handle *b;
    9140           0 :         TALLOC_CTX *tmp_ctx = NULL;
    9141             : 
    9142           0 :         DEBUG(5,("_spoolss_AddForm\n"));
    9143             : 
    9144           0 :         if (!Printer) {
    9145           0 :                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
    9146             :                         OUR_HANDLE(r->in.handle)));
    9147           0 :                 return WERR_INVALID_HANDLE;
    9148             :         }
    9149             : 
    9150             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    9151             :            and not a printer admin, then fail */
    9152             : 
    9153           0 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9154           0 :             !security_token_has_privilege(session_info->security_token,
    9155             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    9156           0 :                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
    9157           0 :                 return WERR_ACCESS_DENIED;
    9158             :         }
    9159             : 
    9160           0 :         if (r->in.info_ctr->level != 1) {
    9161           0 :                 return WERR_INVALID_LEVEL;
    9162             :         }
    9163             : 
    9164           0 :         form = r->in.info_ctr->info.info1;
    9165           0 :         if (!form) {
    9166           0 :                 return WERR_INVALID_PARAMETER;
    9167             :         }
    9168             : 
    9169           0 :         switch (form->flags) {
    9170           0 :         case SPOOLSS_FORM_USER:
    9171             :         case SPOOLSS_FORM_BUILTIN:
    9172             :         case SPOOLSS_FORM_PRINTER:
    9173           0 :                 break;
    9174           0 :         default:
    9175           0 :                 return WERR_INVALID_PARAMETER;
    9176             :         }
    9177             : 
    9178           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    9179           0 :         if (!tmp_ctx) {
    9180           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9181             :         }
    9182             : 
    9183           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    9184             :                                                get_session_info_system(),
    9185             :                                                p->msg_ctx,
    9186             :                                                &b);
    9187           0 :         if (!W_ERROR_IS_OK(status)) {
    9188           0 :                 goto done;
    9189             :         }
    9190             : 
    9191           0 :         status = winreg_printer_addform1(tmp_ctx, b, form);
    9192           0 :         if (!W_ERROR_IS_OK(status)) {
    9193           0 :                 goto done;
    9194             :         }
    9195             : 
    9196             :         /*
    9197             :          * ChangeID must always be set if this is a printer
    9198             :          */
    9199           0 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9200           0 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9201           0 :                         status = WERR_INVALID_HANDLE;
    9202           0 :                         goto done;
    9203             :                 }
    9204             : 
    9205           0 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9206             :                                                         lp_const_servicename(snum));
    9207             :         }
    9208             : 
    9209           0 : done:
    9210           0 :         talloc_free(tmp_ctx);
    9211           0 :         return status;
    9212             : }
    9213             : 
    9214             : /****************************************************************
    9215             :  _spoolss_DeleteForm
    9216             : ****************************************************************/
    9217             : 
    9218           0 : WERROR _spoolss_DeleteForm(struct pipes_struct *p,
    9219             :                            struct spoolss_DeleteForm *r)
    9220             : {
    9221           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9222           0 :         struct auth_session_info *session_info =
    9223           0 :                 dcesrv_call_session_info(dce_call);
    9224           0 :         const char *form_name = r->in.form_name;
    9225           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9226           0 :         int snum = -1;
    9227           0 :         WERROR status = WERR_OK;
    9228             :         struct dcerpc_binding_handle *b;
    9229           0 :         TALLOC_CTX *tmp_ctx = NULL;
    9230             : 
    9231           0 :         DEBUG(5,("_spoolss_DeleteForm\n"));
    9232             : 
    9233           0 :         if (!Printer) {
    9234           0 :                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
    9235             :                         OUR_HANDLE(r->in.handle)));
    9236           0 :                 return WERR_INVALID_HANDLE;
    9237             :         }
    9238             : 
    9239           0 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9240           0 :             !security_token_has_privilege(session_info->security_token,
    9241             :                                           SEC_PRIV_PRINT_OPERATOR)) {
    9242           0 :                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
    9243           0 :                 return WERR_ACCESS_DENIED;
    9244             :         }
    9245             : 
    9246           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    9247           0 :         if (!tmp_ctx) {
    9248           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9249             :         }
    9250             : 
    9251           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    9252             :                                                get_session_info_system(),
    9253             :                                                p->msg_ctx,
    9254             :                                                &b);
    9255           0 :         if (!W_ERROR_IS_OK(status)) {
    9256           0 :                 goto done;
    9257             :         }
    9258             : 
    9259           0 :         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
    9260           0 :         if (!W_ERROR_IS_OK(status)) {
    9261           0 :                 goto done;
    9262             :         }
    9263             : 
    9264             :         /*
    9265             :          * ChangeID must always be set if this is a printer
    9266             :          */
    9267           0 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9268           0 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9269           0 :                         status = WERR_INVALID_HANDLE;
    9270           0 :                         goto done;
    9271             :                 }
    9272             : 
    9273           0 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9274             :                                                         lp_const_servicename(snum));
    9275             :         }
    9276             : 
    9277           0 : done:
    9278           0 :         talloc_free(tmp_ctx);
    9279           0 :         return status;
    9280             : }
    9281             : 
    9282             : /****************************************************************
    9283             :  _spoolss_SetForm
    9284             : ****************************************************************/
    9285             : 
    9286           0 : WERROR _spoolss_SetForm(struct pipes_struct *p,
    9287             :                         struct spoolss_SetForm *r)
    9288             : {
    9289           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
    9290           0 :         struct auth_session_info *session_info =
    9291           0 :                 dcesrv_call_session_info(dce_call);
    9292             :         struct spoolss_AddFormInfo1 *form;
    9293           0 :         const char *form_name = r->in.form_name;
    9294           0 :         int snum = -1;
    9295           0 :         WERROR status = WERR_OK;
    9296             :         struct dcerpc_binding_handle *b;
    9297           0 :         TALLOC_CTX *tmp_ctx = NULL;
    9298             : 
    9299           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9300             : 
    9301           0 :         DEBUG(5,("_spoolss_SetForm\n"));
    9302             : 
    9303           0 :         if (!Printer) {
    9304           0 :                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
    9305             :                         OUR_HANDLE(r->in.handle)));
    9306           0 :                 return WERR_INVALID_HANDLE;
    9307             :         }
    9308             : 
    9309             :         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
    9310             :            and not a printer admin, then fail */
    9311             : 
    9312           0 :         if ((session_info->unix_token->uid != sec_initial_uid()) &&
    9313           0 :              !security_token_has_privilege(session_info->security_token,
    9314             :                                            SEC_PRIV_PRINT_OPERATOR)) {
    9315           0 :                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
    9316           0 :                 return WERR_ACCESS_DENIED;
    9317             :         }
    9318             : 
    9319           0 :         if (r->in.info_ctr->level != 1) {
    9320           0 :                 return WERR_INVALID_LEVEL;
    9321             :         }
    9322             : 
    9323           0 :         form = r->in.info_ctr->info.info1;
    9324           0 :         if (!form) {
    9325           0 :                 return WERR_INVALID_PARAMETER;
    9326             :         }
    9327             : 
    9328           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    9329           0 :         if (!tmp_ctx) {
    9330           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9331             :         }
    9332             : 
    9333           0 :         status = winreg_printer_binding_handle(tmp_ctx,
    9334             :                                                get_session_info_system(),
    9335             :                                                p->msg_ctx,
    9336             :                                                &b);
    9337           0 :         if (!W_ERROR_IS_OK(status)) {
    9338           0 :                 goto done;
    9339             :         }
    9340             : 
    9341           0 :         status = winreg_printer_setform1(tmp_ctx, b,
    9342             :                                          form_name,
    9343             :                                          form);
    9344           0 :         if (!W_ERROR_IS_OK(status)) {
    9345           0 :                 goto done;
    9346             :         }
    9347             : 
    9348             :         /*
    9349             :          * ChangeID must always be set if this is a printer
    9350             :          */
    9351           0 :         if (Printer->printer_type == SPLHND_PRINTER) {
    9352           0 :                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9353           0 :                         status = WERR_INVALID_HANDLE;
    9354           0 :                         goto done;
    9355             :                 }
    9356             : 
    9357           0 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
    9358             :                                                         lp_const_servicename(snum));
    9359             :         }
    9360             : 
    9361           0 : done:
    9362           0 :         talloc_free(tmp_ctx);
    9363           0 :         return status;
    9364             : }
    9365             : 
    9366             : /****************************************************************************
    9367             :  fill_print_processor1
    9368             : ****************************************************************************/
    9369             : 
    9370           0 : static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
    9371             :                                     struct spoolss_PrintProcessorInfo1 *r,
    9372             :                                     const char *print_processor_name)
    9373             : {
    9374           0 :         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
    9375           0 :         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
    9376             : 
    9377           0 :         return WERR_OK;
    9378             : }
    9379             : 
    9380             : /****************************************************************************
    9381             :  enumprintprocessors level 1.
    9382             : ****************************************************************************/
    9383             : 
    9384           0 : static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
    9385             :                                           union spoolss_PrintProcessorInfo **info_p,
    9386             :                                           uint32_t *count)
    9387             : {
    9388             :         union spoolss_PrintProcessorInfo *info;
    9389             :         WERROR result;
    9390             : 
    9391           0 :         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
    9392           0 :         W_ERROR_HAVE_NO_MEMORY(info);
    9393             : 
    9394           0 :         *count = 1;
    9395             : 
    9396           0 :         result = fill_print_processor1(info, &info[0].info1, "winprint");
    9397           0 :         if (!W_ERROR_IS_OK(result)) {
    9398           0 :                 goto out;
    9399             :         }
    9400             : 
    9401           0 :  out:
    9402           0 :         if (!W_ERROR_IS_OK(result)) {
    9403           0 :                 TALLOC_FREE(info);
    9404           0 :                 *count = 0;
    9405           0 :                 return result;
    9406             :         }
    9407             : 
    9408           0 :         *info_p = info;
    9409             : 
    9410           0 :         return WERR_OK;
    9411             : }
    9412             : 
    9413             : /****************************************************************
    9414             :  _spoolss_EnumPrintProcessors
    9415             : ****************************************************************/
    9416             : 
    9417           0 : WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
    9418             :                                     struct spoolss_EnumPrintProcessors *r)
    9419             : {
    9420             :         WERROR result;
    9421             : 
    9422             :         /* that's an [in out] buffer */
    9423             : 
    9424           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9425           0 :                 return WERR_INVALID_PARAMETER;
    9426             :         }
    9427             : 
    9428           0 :         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
    9429             : 
    9430             :         /*
    9431             :          * Enumerate the print processors ...
    9432             :          *
    9433             :          * Just reply with "winprint", to keep NT happy
    9434             :          * and I can use my nice printer checker.
    9435             :          */
    9436             : 
    9437           0 :         *r->out.count = 0;
    9438           0 :         *r->out.needed = 0;
    9439           0 :         *r->out.info = NULL;
    9440             : 
    9441           0 :         if (!get_short_archi(r->in.environment)) {
    9442           0 :                 return WERR_INVALID_ENVIRONMENT;
    9443             :         }
    9444             : 
    9445           0 :         switch (r->in.level) {
    9446           0 :         case 1:
    9447           0 :                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
    9448             :                                                      r->out.count);
    9449           0 :                 break;
    9450           0 :         default:
    9451           0 :                 return WERR_INVALID_LEVEL;
    9452             :         }
    9453             : 
    9454           0 :         if (!W_ERROR_IS_OK(result)) {
    9455           0 :                 return result;
    9456             :         }
    9457             : 
    9458           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9459             :                                                      spoolss_EnumPrintProcessors,
    9460             :                                                      *r->out.info, r->in.level,
    9461             :                                                      *r->out.count);
    9462           0 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9463           0 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9464             : 
    9465           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9466             : }
    9467             : 
    9468             : /****************************************************************************
    9469             :  fill_printprocdatatype1
    9470             : ****************************************************************************/
    9471             : 
    9472           0 : static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
    9473             :                                       struct spoolss_PrintProcDataTypesInfo1 *r,
    9474             :                                       const char *name_array)
    9475             : {
    9476           0 :         r->name_array = talloc_strdup(mem_ctx, name_array);
    9477           0 :         W_ERROR_HAVE_NO_MEMORY(r->name_array);
    9478             : 
    9479           0 :         return WERR_OK;
    9480             : }
    9481             : 
    9482             : /****************************************************************************
    9483             :  enumprintprocdatatypes level 1.
    9484             : ****************************************************************************/
    9485             : 
    9486           0 : static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
    9487             :                                              union spoolss_PrintProcDataTypesInfo **info_p,
    9488             :                                              uint32_t *count)
    9489             : {
    9490             :         WERROR result;
    9491             :         union spoolss_PrintProcDataTypesInfo *info;
    9492             : 
    9493           0 :         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
    9494           0 :         W_ERROR_HAVE_NO_MEMORY(info);
    9495             : 
    9496           0 :         *count = 1;
    9497             : 
    9498           0 :         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
    9499           0 :         if (!W_ERROR_IS_OK(result)) {
    9500           0 :                 goto out;
    9501             :         }
    9502             : 
    9503           0 :  out:
    9504           0 :         if (!W_ERROR_IS_OK(result)) {
    9505           0 :                 TALLOC_FREE(info);
    9506           0 :                 *count = 0;
    9507           0 :                 return result;
    9508             :         }
    9509             : 
    9510           0 :         *info_p = info;
    9511             : 
    9512           0 :         return WERR_OK;
    9513             : }
    9514             : 
    9515             : /****************************************************************
    9516             :  _spoolss_EnumPrintProcessorDataTypes
    9517             : ****************************************************************/
    9518             : 
    9519           0 : WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
    9520             :                                             struct spoolss_EnumPrintProcessorDataTypes *r)
    9521             : {
    9522             :         WERROR result;
    9523             : 
    9524             :         /* that's an [in out] buffer */
    9525             : 
    9526           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9527           0 :                 return WERR_INVALID_PARAMETER;
    9528             :         }
    9529             : 
    9530           0 :         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
    9531             : 
    9532           0 :         *r->out.count = 0;
    9533           0 :         *r->out.needed = 0;
    9534           0 :         *r->out.info = NULL;
    9535             : 
    9536           0 :         if (r->in.print_processor_name == NULL ||
    9537           0 :             !strequal(r->in.print_processor_name, "winprint")) {
    9538           0 :                 return WERR_UNKNOWN_PRINTPROCESSOR;
    9539             :         }
    9540             : 
    9541           0 :         switch (r->in.level) {
    9542           0 :         case 1:
    9543           0 :                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
    9544             :                                                         r->out.count);
    9545           0 :                 break;
    9546           0 :         default:
    9547           0 :                 return WERR_INVALID_LEVEL;
    9548             :         }
    9549             : 
    9550           0 :         if (!W_ERROR_IS_OK(result)) {
    9551           0 :                 return result;
    9552             :         }
    9553             : 
    9554           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9555             :                                                      spoolss_EnumPrintProcessorDataTypes,
    9556             :                                                      *r->out.info, r->in.level,
    9557             :                                                      *r->out.count);
    9558           0 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9559           0 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9560             : 
    9561           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9562             : }
    9563             : 
    9564             : /****************************************************************************
    9565             :  fill_monitor_1
    9566             : ****************************************************************************/
    9567             : 
    9568           0 : static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
    9569             :                              struct spoolss_MonitorInfo1 *r,
    9570             :                              const char *monitor_name)
    9571             : {
    9572           0 :         r->monitor_name                      = talloc_strdup(mem_ctx, monitor_name);
    9573           0 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    9574             : 
    9575           0 :         return WERR_OK;
    9576             : }
    9577             : 
    9578             : /****************************************************************************
    9579             :  fill_monitor_2
    9580             : ****************************************************************************/
    9581             : 
    9582           0 : static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
    9583             :                              struct spoolss_MonitorInfo2 *r,
    9584             :                              const char *monitor_name,
    9585             :                              const char *environment,
    9586             :                              const char *dll_name)
    9587             : {
    9588           0 :         r->monitor_name                      = talloc_strdup(mem_ctx, monitor_name);
    9589           0 :         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
    9590           0 :         r->environment                       = talloc_strdup(mem_ctx, environment);
    9591           0 :         W_ERROR_HAVE_NO_MEMORY(r->environment);
    9592           0 :         r->dll_name                  = talloc_strdup(mem_ctx, dll_name);
    9593           0 :         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
    9594             : 
    9595           0 :         return WERR_OK;
    9596             : }
    9597             : 
    9598             : /****************************************************************************
    9599             :  enumprintmonitors level 1.
    9600             : ****************************************************************************/
    9601             : 
    9602           0 : static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
    9603             :                                         union spoolss_MonitorInfo **info_p,
    9604             :                                         uint32_t *count)
    9605             : {
    9606             :         union spoolss_MonitorInfo *info;
    9607           0 :         WERROR result = WERR_OK;
    9608             : 
    9609           0 :         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
    9610           0 :         W_ERROR_HAVE_NO_MEMORY(info);
    9611             : 
    9612           0 :         *count = 2;
    9613             : 
    9614           0 :         result = fill_monitor_1(info, &info[0].info1,
    9615             :                                 SPL_LOCAL_PORT);
    9616           0 :         if (!W_ERROR_IS_OK(result)) {
    9617           0 :                 goto out;
    9618             :         }
    9619             : 
    9620           0 :         result = fill_monitor_1(info, &info[1].info1,
    9621             :                                 SPL_TCPIP_PORT);
    9622           0 :         if (!W_ERROR_IS_OK(result)) {
    9623           0 :                 goto out;
    9624             :         }
    9625             : 
    9626           0 : out:
    9627           0 :         if (!W_ERROR_IS_OK(result)) {
    9628           0 :                 TALLOC_FREE(info);
    9629           0 :                 *count = 0;
    9630           0 :                 return result;
    9631             :         }
    9632             : 
    9633           0 :         *info_p = info;
    9634             : 
    9635           0 :         return WERR_OK;
    9636             : }
    9637             : 
    9638             : /****************************************************************************
    9639             :  enumprintmonitors level 2.
    9640             : ****************************************************************************/
    9641             : 
    9642           0 : static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
    9643             :                                         union spoolss_MonitorInfo **info_p,
    9644             :                                         uint32_t *count)
    9645             : {
    9646             :         union spoolss_MonitorInfo *info;
    9647           0 :         WERROR result = WERR_OK;
    9648             :         const char *architecture;
    9649             : 
    9650           0 :         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
    9651           0 :         W_ERROR_HAVE_NO_MEMORY(info);
    9652             : 
    9653           0 :         *count = 2;
    9654             : 
    9655           0 :         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
    9656             :                                             "spoolss",
    9657             :                                             "architecture",
    9658             :                                             GLOBAL_SPOOLSS_ARCHITECTURE);
    9659             : 
    9660           0 :         result = fill_monitor_2(info, &info[0].info2,
    9661             :                                 SPL_LOCAL_PORT,
    9662             :                                 architecture,
    9663             :                                 "localmon.dll");
    9664           0 :         if (!W_ERROR_IS_OK(result)) {
    9665           0 :                 goto out;
    9666             :         }
    9667             : 
    9668           0 :         result = fill_monitor_2(info, &info[1].info2,
    9669             :                                 SPL_TCPIP_PORT,
    9670             :                                 architecture,
    9671             :                                 "tcpmon.dll");
    9672           0 :         if (!W_ERROR_IS_OK(result)) {
    9673           0 :                 goto out;
    9674             :         }
    9675             : 
    9676           0 : out:
    9677           0 :         if (!W_ERROR_IS_OK(result)) {
    9678           0 :                 TALLOC_FREE(info);
    9679           0 :                 *count = 0;
    9680           0 :                 return result;
    9681             :         }
    9682             : 
    9683           0 :         *info_p = info;
    9684             : 
    9685           0 :         return WERR_OK;
    9686             : }
    9687             : 
    9688             : /****************************************************************
    9689             :  _spoolss_EnumMonitors
    9690             : ****************************************************************/
    9691             : 
    9692           0 : WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
    9693             :                              struct spoolss_EnumMonitors *r)
    9694             : {
    9695             :         WERROR result;
    9696             : 
    9697             :         /* that's an [in out] buffer */
    9698             : 
    9699           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9700           0 :                 return WERR_INVALID_PARAMETER;
    9701             :         }
    9702             : 
    9703           0 :         DEBUG(5,("_spoolss_EnumMonitors\n"));
    9704             : 
    9705             :         /*
    9706             :          * Enumerate the print monitors ...
    9707             :          *
    9708             :          * Just reply with "Local Port", to keep NT happy
    9709             :          * and I can use my nice printer checker.
    9710             :          */
    9711             : 
    9712           0 :         *r->out.count = 0;
    9713           0 :         *r->out.needed = 0;
    9714           0 :         *r->out.info = NULL;
    9715             : 
    9716           0 :         switch (r->in.level) {
    9717           0 :         case 1:
    9718           0 :                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
    9719             :                                                    r->out.count);
    9720           0 :                 break;
    9721           0 :         case 2:
    9722           0 :                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
    9723             :                                                    r->out.count);
    9724           0 :                 break;
    9725           0 :         default:
    9726           0 :                 return WERR_INVALID_LEVEL;
    9727             :         }
    9728             : 
    9729           0 :         if (!W_ERROR_IS_OK(result)) {
    9730           0 :                 return result;
    9731             :         }
    9732             : 
    9733           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
    9734             :                                                      spoolss_EnumMonitors,
    9735             :                                                      *r->out.info, r->in.level,
    9736             :                                                      *r->out.count);
    9737           0 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    9738           0 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, 0);
    9739             : 
    9740           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9741             : }
    9742             : 
    9743             : /****************************************************************************
    9744             : ****************************************************************************/
    9745             : 
    9746           0 : static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
    9747             :                              const print_queue_struct *queue,
    9748             :                              int count, int snum,
    9749             :                              struct spoolss_PrinterInfo2 *pinfo2,
    9750             :                              uint32_t jobid,
    9751             :                              int sysjob,
    9752             :                              struct spoolss_JobInfo1 *r)
    9753             : {
    9754           0 :         int i = 0;
    9755           0 :         bool found = false;
    9756             : 
    9757           0 :         for (i=0; i<count; i++) {
    9758           0 :                 if (queue[i].sysjob == sysjob) {
    9759           0 :                         found = true;
    9760           0 :                         break;
    9761             :                 }
    9762             :         }
    9763             : 
    9764           0 :         if (found == false) {
    9765             :                 /* NT treats not found as bad param... yet another bad choice */
    9766           0 :                 return WERR_INVALID_PARAMETER;
    9767             :         }
    9768             : 
    9769           0 :         return fill_job_info1(mem_ctx,
    9770             :                               r,
    9771           0 :                               &queue[i],
    9772             :                               jobid,
    9773             :                               i,
    9774             :                               snum,
    9775             :                               pinfo2);
    9776             : }
    9777             : 
    9778             : /****************************************************************************
    9779             : ****************************************************************************/
    9780             : 
    9781           0 : static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
    9782             :                              const print_queue_struct *queue,
    9783             :                              int count, int snum,
    9784             :                              struct spoolss_PrinterInfo2 *pinfo2,
    9785             :                              uint32_t jobid,
    9786             :                              int sysjob,
    9787             :                              struct spoolss_JobInfo2 *r)
    9788             : {
    9789           0 :         int i = 0;
    9790           0 :         bool found = false;
    9791             :         struct spoolss_DeviceMode *devmode;
    9792             :         WERROR result;
    9793             : 
    9794           0 :         for (i=0; i<count; i++) {
    9795           0 :                 if (queue[i].sysjob == sysjob) {
    9796           0 :                         found = true;
    9797           0 :                         break;
    9798             :                 }
    9799             :         }
    9800             : 
    9801           0 :         if (found == false) {
    9802             :                 /* NT treats not found as bad param... yet another bad
    9803             :                    choice */
    9804           0 :                 return WERR_INVALID_PARAMETER;
    9805             :         }
    9806             : 
    9807             :         /*
    9808             :          * if the print job does not have a DEVMODE associated with it,
    9809             :          * just use the one for the printer. A NULL devicemode is not
    9810             :          *  a failure condition
    9811             :          */
    9812             : 
    9813           0 :         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
    9814           0 :         if (!devmode) {
    9815           0 :                 result = spoolss_create_default_devmode(mem_ctx,
    9816             :                                                 pinfo2->printername,
    9817             :                                                 &devmode);
    9818           0 :                 if (!W_ERROR_IS_OK(result)) {
    9819           0 :                         DEBUG(3, ("Can't proceed w/o a devmode!"));
    9820           0 :                         return result;
    9821             :                 }
    9822             :         }
    9823             : 
    9824           0 :         return fill_job_info2(mem_ctx,
    9825             :                               r,
    9826           0 :                               &queue[i],
    9827             :                               jobid,
    9828             :                               i,
    9829             :                               snum,
    9830             :                               pinfo2,
    9831             :                               devmode);
    9832             : }
    9833             : 
    9834             : /****************************************************************
    9835             :  _spoolss_GetJob
    9836             : ****************************************************************/
    9837             : 
    9838           0 : WERROR _spoolss_GetJob(struct pipes_struct *p,
    9839             :                        struct spoolss_GetJob *r)
    9840             : {
    9841           0 :         WERROR result = WERR_OK;
    9842           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
    9843             :         const char *svc_name;
    9844             :         int sysjob;
    9845             :         int snum;
    9846             :         int count;
    9847             :         struct tdb_print_db *pdb;
    9848           0 :         print_queue_struct      *queue = NULL;
    9849             :         print_status_struct prt_status;
    9850             : 
    9851             :         /* that's an [in out] buffer */
    9852             : 
    9853           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
    9854           0 :                 result = WERR_INVALID_PARAMETER;
    9855           0 :                 goto err_jinfo_free;
    9856             :         }
    9857             : 
    9858           0 :         DEBUG(5,("_spoolss_GetJob\n"));
    9859             : 
    9860           0 :         *r->out.needed = 0;
    9861             : 
    9862           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
    9863           0 :                 result = WERR_INVALID_HANDLE;
    9864           0 :                 goto err_jinfo_free;
    9865             :         }
    9866             : 
    9867           0 :         svc_name = lp_const_servicename(snum);
    9868           0 :         if (svc_name == NULL) {
    9869           0 :                 result = WERR_INVALID_PARAMETER;
    9870           0 :                 goto err_jinfo_free;
    9871             :         }
    9872             : 
    9873           0 :         result = winreg_get_printer_internal(p->mem_ctx,
    9874             :                                     get_session_info_system(),
    9875             :                                     p->msg_ctx,
    9876             :                                     svc_name,
    9877             :                                     &pinfo2);
    9878           0 :         if (!W_ERROR_IS_OK(result)) {
    9879           0 :                 goto err_jinfo_free;
    9880             :         }
    9881             : 
    9882           0 :         pdb = get_print_db_byname(svc_name);
    9883           0 :         if (pdb == NULL) {
    9884           0 :                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
    9885           0 :                 result = WERR_INVALID_PARAMETER;
    9886           0 :                 goto err_pinfo_free;
    9887             :         }
    9888             : 
    9889           0 :         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
    9890           0 :         release_print_db(pdb);
    9891           0 :         if (sysjob == -1) {
    9892           0 :                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
    9893           0 :                 result = WERR_INVALID_PARAMETER;
    9894           0 :                 goto err_pinfo_free;
    9895             :         }
    9896             : 
    9897           0 :         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
    9898             : 
    9899           0 :         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
    9900             :                      count, prt_status.status, prt_status.message));
    9901             : 
    9902           0 :         switch (r->in.level) {
    9903           0 :         case 1:
    9904           0 :                 result = getjob_level_1(p->mem_ctx,
    9905             :                                         queue, count, snum, pinfo2,
    9906             :                                         r->in.job_id, sysjob,
    9907           0 :                                         &r->out.info->info1);
    9908           0 :                 break;
    9909           0 :         case 2:
    9910           0 :                 result = getjob_level_2(p->mem_ctx,
    9911             :                                         queue, count, snum, pinfo2,
    9912             :                                         r->in.job_id, sysjob,
    9913           0 :                                         &r->out.info->info2);
    9914           0 :                 break;
    9915           0 :         default:
    9916           0 :                 result = WERR_INVALID_LEVEL;
    9917           0 :                 break;
    9918             :         }
    9919             : 
    9920           0 :         SAFE_FREE(queue);
    9921           0 :         TALLOC_FREE(pinfo2);
    9922             : 
    9923           0 :         if (!W_ERROR_IS_OK(result)) {
    9924           0 :                 goto err_jinfo_free;
    9925             :         }
    9926             : 
    9927           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
    9928             :                                                                                    r->in.level);
    9929           0 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    9930             : 
    9931           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
    9932             : 
    9933           0 : err_pinfo_free:
    9934           0 :         TALLOC_FREE(pinfo2);
    9935           0 : err_jinfo_free:
    9936           0 :         TALLOC_FREE(r->out.info);
    9937           0 :         return result;
    9938             : }
    9939             : 
    9940             : /****************************************************************
    9941             :  _spoolss_GetPrinterDataEx
    9942             : ****************************************************************/
    9943             : 
    9944           0 : WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
    9945             :                                  struct spoolss_GetPrinterDataEx *r)
    9946             : {
    9947             : 
    9948           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
    9949             :         const char *printer;
    9950           0 :         int                     snum = 0;
    9951           0 :         WERROR result = WERR_OK;
    9952             :         DATA_BLOB blob;
    9953           0 :         enum winreg_Type val_type = REG_NONE;
    9954           0 :         uint8_t *val_data = NULL;
    9955           0 :         uint32_t val_size = 0;
    9956             :         struct dcerpc_binding_handle *b;
    9957             :         TALLOC_CTX *tmp_ctx;
    9958             : 
    9959           0 :         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
    9960             : 
    9961           0 :         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
    9962             :                 r->in.key_name, r->in.value_name));
    9963             : 
    9964             :         /* in case of problem, return some default values */
    9965             : 
    9966           0 :         *r->out.needed       = 0;
    9967           0 :         *r->out.type = REG_NONE;
    9968             : 
    9969           0 :         tmp_ctx = talloc_new(p->mem_ctx);
    9970           0 :         if (!tmp_ctx) {
    9971           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    9972             :         }
    9973             : 
    9974           0 :         if (!Printer) {
    9975           0 :                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
    9976             :                         OUR_HANDLE(r->in.handle)));
    9977           0 :                 result = WERR_INVALID_HANDLE;
    9978           0 :                 goto done;
    9979             :         }
    9980             : 
    9981             :         /* Is the handle to a printer or to the server? */
    9982             : 
    9983           0 :         if (Printer->printer_type == SPLHND_SERVER) {
    9984             : 
    9985             :                 union spoolss_PrinterData data;
    9986             : 
    9987           0 :                 result = getprinterdata_printer_server(tmp_ctx,
    9988             :                                                        r->in.value_name,
    9989             :                                                        r->out.type,
    9990             :                                                        &data);
    9991           0 :                 if (!W_ERROR_IS_OK(result)) {
    9992           0 :                         goto done;
    9993             :                 }
    9994             : 
    9995           0 :                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
    9996           0 :                                                   *r->out.type, &data);
    9997           0 :                 if (!W_ERROR_IS_OK(result)) {
    9998           0 :                         goto done;
    9999             :                 }
   10000             : 
   10001           0 :                 *r->out.needed = blob.length;
   10002             : 
   10003           0 :                 if (r->in.offered >= *r->out.needed) {
   10004           0 :                         memcpy(r->out.data, blob.data, blob.length);
   10005             :                 }
   10006             : 
   10007           0 :                 result = WERR_OK;
   10008           0 :                 goto done;
   10009             :         }
   10010             : 
   10011             :         /* check to see if the keyname is valid */
   10012           0 :         if (!strlen(r->in.key_name)) {
   10013           0 :                 result = WERR_INVALID_PARAMETER;
   10014           0 :                 goto done;
   10015             :         }
   10016             : 
   10017           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10018           0 :                 result = WERR_INVALID_HANDLE;
   10019           0 :                 goto done;
   10020             :         }
   10021           0 :         printer = lp_const_servicename(snum);
   10022             : 
   10023           0 :         result = winreg_printer_binding_handle(tmp_ctx,
   10024             :                                                get_session_info_system(),
   10025             :                                                p->msg_ctx,
   10026             :                                                &b);
   10027           0 :         if (!W_ERROR_IS_OK(result)) {
   10028           0 :                 goto done;
   10029             :         }
   10030             : 
   10031             :         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
   10032           0 :         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
   10033           0 :             strequal(r->in.value_name, "ChangeId")) {
   10034           0 :                 *r->out.type = REG_DWORD;
   10035           0 :                 *r->out.needed = 4;
   10036           0 :                 if (r->in.offered >= *r->out.needed) {
   10037           0 :                         uint32_t changeid = 0;
   10038             : 
   10039           0 :                         result = winreg_printer_get_changeid(tmp_ctx, b,
   10040             :                                                              printer,
   10041             :                                                              &changeid);
   10042           0 :                         if (!W_ERROR_IS_OK(result)) {
   10043           0 :                                 goto done;
   10044             :                         }
   10045             : 
   10046           0 :                         SIVAL(r->out.data, 0, changeid);
   10047           0 :                         result = WERR_OK;
   10048             :                 }
   10049           0 :                 goto done;
   10050             :         }
   10051             : 
   10052           0 :         result = winreg_get_printer_dataex(tmp_ctx, b,
   10053             :                                            printer,
   10054             :                                            r->in.key_name,
   10055             :                                            r->in.value_name,
   10056             :                                            &val_type,
   10057             :                                            &val_data,
   10058             :                                            &val_size);
   10059           0 :         if (!W_ERROR_IS_OK(result)) {
   10060           0 :                 goto done;
   10061             :         }
   10062             : 
   10063           0 :         *r->out.needed = val_size;
   10064           0 :         *r->out.type = val_type;
   10065             : 
   10066           0 :         if (r->in.offered >= *r->out.needed) {
   10067           0 :                 memcpy(r->out.data, val_data, val_size);
   10068             :         }
   10069             : 
   10070           0 : done:
   10071             :         /* NOTE: do not replace type when returning WERR_MORE_DATA */
   10072             : 
   10073           0 :         if (W_ERROR_IS_OK(result)) {
   10074           0 :                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
   10075             :         }
   10076             : 
   10077           0 :         talloc_free(tmp_ctx);
   10078           0 :         return result;
   10079             : }
   10080             : 
   10081             : /****************************************************************
   10082             :  _spoolss_SetPrinterDataEx
   10083             : ****************************************************************/
   10084             : 
   10085           0 : WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
   10086             :                                  struct spoolss_SetPrinterDataEx *r)
   10087             : {
   10088           0 :         const struct loadparm_substitution *lp_sub =
   10089           0 :                 loadparm_s3_global_substitution();
   10090           0 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
   10091           0 :         int                     snum = 0;
   10092           0 :         WERROR                  result = WERR_OK;
   10093           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10094             :         char                    *oid_string;
   10095             :         struct dcerpc_binding_handle *b;
   10096             :         TALLOC_CTX *tmp_ctx;
   10097             : 
   10098           0 :         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
   10099             : 
   10100             :         /* From MSDN documentation of SetPrinterDataEx: pass request to
   10101             :            SetPrinterData if key is "PrinterDriverData" */
   10102             : 
   10103           0 :         if (!Printer) {
   10104           0 :                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
   10105             :                         OUR_HANDLE(r->in.handle)));
   10106           0 :                 return WERR_INVALID_HANDLE;
   10107             :         }
   10108             : 
   10109           0 :         if (Printer->printer_type == SPLHND_SERVER) {
   10110           0 :                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
   10111             :                         "Not implemented for server handles yet\n"));
   10112           0 :                 return WERR_INVALID_PARAMETER;
   10113             :         }
   10114             : 
   10115           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10116           0 :                 return WERR_INVALID_HANDLE;
   10117             :         }
   10118             : 
   10119             :         /*
   10120             :          * Access check : NT returns "access denied" if you make a
   10121             :          * SetPrinterData call without the necessary privildge.
   10122             :          * we were originally returning OK if nothing changed
   10123             :          * which made Win2k issue **a lot** of SetPrinterData
   10124             :          * when connecting to a printer  --jerry
   10125             :          */
   10126             : 
   10127           0 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10128           0 :                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
   10129             :                         "change denied by handle access permissions\n"));
   10130           0 :                 return WERR_ACCESS_DENIED;
   10131             :         }
   10132             : 
   10133           0 :         tmp_ctx = talloc_new(p->mem_ctx);
   10134           0 :         if (!tmp_ctx) {
   10135           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10136             :         }
   10137             : 
   10138           0 :         result = winreg_printer_binding_handle(tmp_ctx,
   10139             :                                                get_session_info_system(),
   10140             :                                                p->msg_ctx,
   10141             :                                                &b);
   10142           0 :         if (!W_ERROR_IS_OK(result)) {
   10143           0 :                 goto done;
   10144             :         }
   10145             : 
   10146           0 :         result = winreg_get_printer(tmp_ctx, b,
   10147           0 :                                     lp_servicename(talloc_tos(), lp_sub, snum),
   10148             :                                     &pinfo2);
   10149           0 :         if (!W_ERROR_IS_OK(result)) {
   10150           0 :                 goto done;
   10151             :         }
   10152             : 
   10153             :         /* check for OID in valuename */
   10154             : 
   10155           0 :         oid_string = strchr(r->in.value_name, ',');
   10156           0 :         if (oid_string) {
   10157           0 :                 *oid_string = '\0';
   10158           0 :                 oid_string++;
   10159             :         }
   10160             : 
   10161             :         /* save the registry data */
   10162             : 
   10163           0 :         result = winreg_set_printer_dataex(tmp_ctx, b,
   10164           0 :                                            pinfo2->sharename,
   10165             :                                            r->in.key_name,
   10166             :                                            r->in.value_name,
   10167             :                                            r->in.type,
   10168             :                                            r->in.data,
   10169             :                                            r->in.offered);
   10170             : 
   10171           0 :         if (W_ERROR_IS_OK(result)) {
   10172             :                 /* save the OID if one was specified */
   10173           0 :                 if (oid_string) {
   10174           0 :                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
   10175             :                                 r->in.key_name, SPOOL_OID_KEY);
   10176           0 :                         if (!str) {
   10177           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
   10178           0 :                                 goto done;
   10179             :                         }
   10180             : 
   10181             :                         /*
   10182             :                          * I'm not checking the status here on purpose.  Don't know
   10183             :                          * if this is right, but I'm returning the status from the
   10184             :                          * previous set_printer_dataex() call.  I have no idea if
   10185             :                          * this is right.    --jerry
   10186             :                          */
   10187           0 :                         winreg_set_printer_dataex(tmp_ctx, b,
   10188           0 :                                                   pinfo2->sharename,
   10189             :                                                   str,
   10190             :                                                   r->in.value_name,
   10191             :                                                   REG_SZ,
   10192             :                                                   (uint8_t *) oid_string,
   10193           0 :                                                   strlen(oid_string) + 1);
   10194             :                 }
   10195             : 
   10196           0 :                 result = winreg_printer_update_changeid(tmp_ctx, b,
   10197             :                                                         lp_const_servicename(snum));
   10198             : 
   10199             :         }
   10200             : 
   10201           0 : done:
   10202           0 :         talloc_free(tmp_ctx);
   10203           0 :         return result;
   10204             : }
   10205             : 
   10206             : /****************************************************************
   10207             :  _spoolss_DeletePrinterDataEx
   10208             : ****************************************************************/
   10209             : 
   10210           0 : WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
   10211             :                                     struct spoolss_DeletePrinterDataEx *r)
   10212             : {
   10213             :         const char *printer;
   10214           0 :         int             snum=0;
   10215           0 :         WERROR          status = WERR_OK;
   10216           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10217             : 
   10218           0 :         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
   10219             : 
   10220           0 :         if (!Printer) {
   10221           0 :                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
   10222             :                         "Invalid handle (%s:%u:%u).\n",
   10223             :                         OUR_HANDLE(r->in.handle)));
   10224           0 :                 return WERR_INVALID_HANDLE;
   10225             :         }
   10226             : 
   10227           0 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10228           0 :                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
   10229             :                         "printer properties change denied by handle\n"));
   10230           0 :                 return WERR_ACCESS_DENIED;
   10231             :         }
   10232             : 
   10233           0 :         if (!r->in.value_name || !r->in.key_name) {
   10234           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10235             :         }
   10236             : 
   10237           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10238           0 :                 return WERR_INVALID_HANDLE;
   10239             :         }
   10240           0 :         printer = lp_const_servicename(snum);
   10241             : 
   10242           0 :         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
   10243             :                                               get_session_info_system(),
   10244             :                                               p->msg_ctx,
   10245             :                                               printer,
   10246             :                                               r->in.key_name,
   10247             :                                               r->in.value_name);
   10248           0 :         if (W_ERROR_IS_OK(status)) {
   10249           0 :                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
   10250             :                                                         get_session_info_system(),
   10251             :                                                         p->msg_ctx,
   10252             :                                                         printer);
   10253             :         }
   10254             : 
   10255           0 :         return status;
   10256             : }
   10257             : 
   10258             : /****************************************************************
   10259             :  _spoolss_EnumPrinterKey
   10260             : ****************************************************************/
   10261             : 
   10262           0 : WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
   10263             :                                struct spoolss_EnumPrinterKey *r)
   10264             : {
   10265             :         uint32_t        num_keys;
   10266           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10267           0 :         int             snum = 0;
   10268           0 :         WERROR          result = WERR_FILE_NOT_FOUND;
   10269           0 :         const char **array = NULL;
   10270             :         DATA_BLOB blob;
   10271             : 
   10272           0 :         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
   10273             : 
   10274           0 :         if (!Printer) {
   10275           0 :                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
   10276             :                         OUR_HANDLE(r->in.handle)));
   10277           0 :                 return WERR_INVALID_HANDLE;
   10278             :         }
   10279             : 
   10280           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10281           0 :                 return WERR_INVALID_HANDLE;
   10282             :         }
   10283             : 
   10284           0 :         result = winreg_enum_printer_key_internal(p->mem_ctx,
   10285             :                                          get_session_info_system(),
   10286             :                                          p->msg_ctx,
   10287             :                                          lp_const_servicename(snum),
   10288             :                                          r->in.key_name,
   10289             :                                          &num_keys,
   10290             :                                          &array);
   10291           0 :         if (!W_ERROR_IS_OK(result)) {
   10292           0 :                 goto done;
   10293             :         }
   10294             : 
   10295           0 :         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
   10296           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
   10297           0 :                 goto done;
   10298             :         }
   10299             : 
   10300           0 :         *r->out._ndr_size = r->in.offered / 2;
   10301           0 :         *r->out.needed = blob.length;
   10302             : 
   10303           0 :         if (r->in.offered < *r->out.needed) {
   10304           0 :                 result = WERR_MORE_DATA;
   10305             :         } else {
   10306           0 :                 result = WERR_OK;
   10307           0 :                 r->out.key_buffer->string_array = array;
   10308             :         }
   10309             : 
   10310           0 :  done:
   10311           0 :         if (!W_ERROR_IS_OK(result)) {
   10312           0 :                 TALLOC_FREE(array);
   10313           0 :                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
   10314           0 :                         *r->out.needed = 0;
   10315             :                 }
   10316             :         }
   10317             : 
   10318           0 :         return result;
   10319             : }
   10320             : 
   10321             : /****************************************************************
   10322             :  _spoolss_DeletePrinterKey
   10323             : ****************************************************************/
   10324             : 
   10325           0 : WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
   10326             :                                  struct spoolss_DeletePrinterKey *r)
   10327             : {
   10328           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10329           0 :         int                     snum=0;
   10330             :         WERROR                  status;
   10331             :         const char *printer;
   10332             :         struct dcerpc_binding_handle *b;
   10333             :         TALLOC_CTX *tmp_ctx;
   10334             : 
   10335           0 :         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
   10336             : 
   10337           0 :         if (!Printer) {
   10338           0 :                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
   10339             :                         OUR_HANDLE(r->in.handle)));
   10340           0 :                 return WERR_INVALID_HANDLE;
   10341             :         }
   10342             : 
   10343             :         /* if keyname == NULL, return error */
   10344           0 :         if ( !r->in.key_name )
   10345           0 :                 return WERR_INVALID_PARAMETER;
   10346             : 
   10347           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10348           0 :                 return WERR_INVALID_HANDLE;
   10349             :         }
   10350             : 
   10351           0 :         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
   10352           0 :                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
   10353             :                         "printer properties change denied by handle\n"));
   10354           0 :                 return WERR_ACCESS_DENIED;
   10355             :         }
   10356             : 
   10357           0 :         printer = lp_const_servicename(snum);
   10358             : 
   10359           0 :         tmp_ctx = talloc_new(p->mem_ctx);
   10360           0 :         if (!tmp_ctx) {
   10361           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10362             :         }
   10363             : 
   10364           0 :         status = winreg_printer_binding_handle(tmp_ctx,
   10365             :                                                get_session_info_system(),
   10366             :                                                p->msg_ctx,
   10367             :                                                &b);
   10368           0 :         if (!W_ERROR_IS_OK(status)) {
   10369           0 :                 goto done;
   10370             :         }
   10371             : 
   10372             :         /* delete the key and all subkeys */
   10373           0 :         status = winreg_delete_printer_key(tmp_ctx, b,
   10374             :                                            printer,
   10375             :                                            r->in.key_name);
   10376           0 :         if (W_ERROR_IS_OK(status)) {
   10377           0 :                 status = winreg_printer_update_changeid(tmp_ctx, b,
   10378             :                                                         printer);
   10379             :         }
   10380             : 
   10381           0 : done:
   10382           0 :         talloc_free(tmp_ctx);
   10383           0 :         return status;
   10384             : }
   10385             : 
   10386             : /****************************************************************
   10387             :  _spoolss_EnumPrinterDataEx
   10388             : ****************************************************************/
   10389             : 
   10390           0 : WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
   10391             :                                   struct spoolss_EnumPrinterDataEx *r)
   10392             : {
   10393           0 :         uint32_t        count = 0;
   10394           0 :         struct spoolss_PrinterEnumValues *info = NULL;
   10395           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10396             :         int             snum;
   10397             :         WERROR          result;
   10398             : 
   10399           0 :         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
   10400             : 
   10401           0 :         *r->out.count = 0;
   10402           0 :         *r->out.needed = 0;
   10403           0 :         *r->out.info = NULL;
   10404             : 
   10405           0 :         if (!Printer) {
   10406           0 :                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
   10407             :                         OUR_HANDLE(r->in.handle)));
   10408           0 :                 return WERR_INVALID_HANDLE;
   10409             :         }
   10410             : 
   10411             :         /*
   10412             :          * first check for a keyname of NULL or "".  Win2k seems to send
   10413             :          * this a lot and we should send back WERR_INVALID_PARAMETER
   10414             :          * no need to spend time looking up the printer in this case.
   10415             :          * --jerry
   10416             :          */
   10417             : 
   10418           0 :         if (!strlen(r->in.key_name)) {
   10419           0 :                 result = WERR_INVALID_PARAMETER;
   10420           0 :                 goto done;
   10421             :         }
   10422             : 
   10423           0 :         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
   10424           0 :                 return WERR_INVALID_HANDLE;
   10425             :         }
   10426             : 
   10427             :         /* now look for a match on the key name */
   10428           0 :         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
   10429             :                                             get_session_info_system(),
   10430             :                                             p->msg_ctx,
   10431             :                                             lp_const_servicename(snum),
   10432             :                                             r->in.key_name,
   10433             :                                             &count,
   10434             :                                             &info);
   10435           0 :         if (!W_ERROR_IS_OK(result)) {
   10436           0 :                 goto done;
   10437             :         }
   10438             : 
   10439             : #if 0 /* FIXME - gd */
   10440             :         /* housekeeping information in the reply */
   10441             : 
   10442             :         /* Fix from Martin Zielinski <mz@seh.de> - ensure
   10443             :          * the hand marshalled container size is a multiple
   10444             :          * of 4 bytes for RPC alignment.
   10445             :          */
   10446             : 
   10447             :         if (needed % 4) {
   10448             :                 needed += 4-(needed % 4);
   10449             :         }
   10450             : #endif
   10451           0 :         *r->out.count        = count;
   10452           0 :         *r->out.info = info;
   10453             : 
   10454           0 :  done:
   10455           0 :         if (!W_ERROR_IS_OK(result)) {
   10456           0 :                 return result;
   10457             :         }
   10458             : 
   10459           0 :         *r->out.needed       = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
   10460             :                                                spoolss_EnumPrinterDataEx,
   10461             :                                                *r->out.info,
   10462             :                                                *r->out.count);
   10463           0 :         *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
   10464           0 :         *r->out.count        = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
   10465             : 
   10466           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
   10467             : }
   10468             : 
   10469             : /****************************************************************************
   10470             : ****************************************************************************/
   10471             : 
   10472           0 : static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
   10473             :                                                  const char *servername,
   10474             :                                                  const char *environment,
   10475             :                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
   10476             : {
   10477             :         WERROR werr;
   10478           0 :         char *path = NULL;
   10479             : 
   10480           0 :         werr = compose_spoolss_server_path(mem_ctx,
   10481             :                                            servername,
   10482             :                                            environment,
   10483             :                                            SPOOLSS_PRTPROCS_PATH,
   10484             :                                            &path);
   10485           0 :         if (!W_ERROR_IS_OK(werr)) {
   10486           0 :                 return werr;
   10487             :         }
   10488             : 
   10489           0 :         DEBUG(4,("print processor directory: [%s]\n", path));
   10490             : 
   10491           0 :         r->directory_name = path;
   10492             : 
   10493           0 :         return WERR_OK;
   10494             : }
   10495             : 
   10496             : /****************************************************************
   10497             :  _spoolss_GetPrintProcessorDirectory
   10498             : ****************************************************************/
   10499             : 
   10500           0 : WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
   10501             :                                            struct spoolss_GetPrintProcessorDirectory *r)
   10502             : {
   10503             :         WERROR result;
   10504           0 :         char *prnproc_share = NULL;
   10505           0 :         bool prnproc_share_exists = false;
   10506             :         int snum;
   10507             : 
   10508             :         /* that's an [in out] buffer */
   10509             : 
   10510           0 :         if (!r->in.buffer && (r->in.offered != 0)) {
   10511           0 :                 result = WERR_INVALID_PARAMETER;
   10512           0 :                 goto err_info_free;
   10513             :         }
   10514             : 
   10515           0 :         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
   10516             :                 r->in.level));
   10517             : 
   10518           0 :         *r->out.needed = 0;
   10519             : 
   10520             :         /* r->in.level is ignored */
   10521             : 
   10522             :         /* We always should reply with a local print processor directory so that
   10523             :          * users are not forced to have a [prnproc$] share on the Samba spoolss
   10524             :          * server, if users decide to do so, lets announce it though - Guenther */
   10525             : 
   10526           0 :         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
   10527           0 :         if (!prnproc_share) {
   10528           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
   10529           0 :                 goto err_info_free;
   10530             :         }
   10531           0 :         if (snum != -1) {
   10532           0 :                 prnproc_share_exists = true;
   10533             :         }
   10534             : 
   10535           0 :         result = getprintprocessordirectory_level_1(p->mem_ctx,
   10536             :                                                     prnproc_share_exists ? r->in.server : NULL,
   10537             :                                                     r->in.environment,
   10538           0 :                                                     &r->out.info->info1);
   10539           0 :         if (!W_ERROR_IS_OK(result)) {
   10540           0 :                 goto err_info_free;
   10541             :         }
   10542             : 
   10543           0 :         *r->out.needed       = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
   10544             :                                                                                    r->out.info, r->in.level);
   10545           0 :         r->out.info  = SPOOLSS_BUFFER_OK(r->out.info, NULL);
   10546             : 
   10547           0 :         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
   10548             : 
   10549           0 : err_info_free:
   10550           0 :         TALLOC_FREE(r->out.info);
   10551           0 :         return result;
   10552             : }
   10553             : 
   10554             : /*******************************************************************
   10555             :  ********************************************************************/
   10556             : 
   10557           0 : static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
   10558             :                                const char *dllname)
   10559             : {
   10560             :         enum ndr_err_code ndr_err;
   10561             :         struct spoolss_MonitorUi ui;
   10562             : 
   10563           0 :         ui.dll_name = dllname;
   10564             : 
   10565           0 :         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
   10566             :                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
   10567           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10568           0 :                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
   10569             :         }
   10570           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10571             : }
   10572             : 
   10573             : /*******************************************************************
   10574             :  Streams the monitor UI DLL name in UNICODE
   10575             : *******************************************************************/
   10576             : 
   10577           0 : static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
   10578             :                                struct security_token *token, DATA_BLOB *in,
   10579             :                                DATA_BLOB *out, uint32_t *needed)
   10580             : {
   10581           0 :         const char *dllname = "tcpmonui.dll";
   10582             : 
   10583           0 :         *needed = (strlen(dllname)+1) * 2;
   10584             : 
   10585           0 :         if (out->length < *needed) {
   10586           0 :                 return WERR_INSUFFICIENT_BUFFER;
   10587             :         }
   10588             : 
   10589           0 :         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
   10590           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10591             :         }
   10592             : 
   10593           0 :         return WERR_OK;
   10594             : }
   10595             : 
   10596             : /*******************************************************************
   10597             :  ********************************************************************/
   10598             : 
   10599           0 : static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
   10600             :                              struct spoolss_PortData1 *port1,
   10601             :                              const DATA_BLOB *buf)
   10602             : {
   10603             :         enum ndr_err_code ndr_err;
   10604           0 :         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
   10605             :                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
   10606           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10607           0 :                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
   10608             :         }
   10609           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10610             : }
   10611             : 
   10612             : /*******************************************************************
   10613             :  ********************************************************************/
   10614             : 
   10615           0 : static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
   10616             :                              struct spoolss_PortData2 *port2,
   10617             :                              const DATA_BLOB *buf)
   10618             : {
   10619             :         enum ndr_err_code ndr_err;
   10620           0 :         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
   10621             :                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
   10622           0 :         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
   10623           0 :                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
   10624             :         }
   10625           0 :         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
   10626             : }
   10627             : 
   10628             : /*******************************************************************
   10629             :  Create a new TCP/IP port
   10630             : *******************************************************************/
   10631             : 
   10632           0 : static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
   10633             :                              struct security_token *token, DATA_BLOB *in,
   10634             :                              DATA_BLOB *out, uint32_t *needed)
   10635             : {
   10636             :         struct spoolss_PortData1 port1;
   10637             :         struct spoolss_PortData2 port2;
   10638           0 :         char *device_uri = NULL;
   10639             :         uint32_t version;
   10640             : 
   10641             :         const char *portname;
   10642             :         const char *hostaddress;
   10643             :         const char *queue;
   10644             :         uint32_t port_number;
   10645             :         uint32_t protocol;
   10646             : 
   10647             :         /* peek for spoolss_PortData version */
   10648             : 
   10649           0 :         if (!in || (in->length < (128 + 4))) {
   10650           0 :                 return WERR_GEN_FAILURE;
   10651             :         }
   10652             : 
   10653           0 :         version = IVAL(in->data, 128);
   10654             : 
   10655           0 :         switch (version) {
   10656           0 :                 case 1:
   10657           0 :                         ZERO_STRUCT(port1);
   10658             : 
   10659           0 :                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
   10660           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
   10661             :                         }
   10662             : 
   10663           0 :                         portname        = port1.portname;
   10664           0 :                         hostaddress     = port1.hostaddress;
   10665           0 :                         queue           = port1.queue;
   10666           0 :                         protocol        = port1.protocol;
   10667           0 :                         port_number     = port1.port_number;
   10668             : 
   10669           0 :                         break;
   10670           0 :                 case 2:
   10671           0 :                         ZERO_STRUCT(port2);
   10672             : 
   10673           0 :                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
   10674           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
   10675             :                         }
   10676             : 
   10677           0 :                         portname        = port2.portname;
   10678           0 :                         hostaddress     = port2.hostaddress;
   10679           0 :                         queue           = port2.queue;
   10680           0 :                         protocol        = port2.protocol;
   10681           0 :                         port_number     = port2.port_number;
   10682             : 
   10683           0 :                         break;
   10684           0 :                 default:
   10685           0 :                         DEBUG(1,("xcvtcp_addport: "
   10686             :                                 "unknown version of port_data: %d\n", version));
   10687           0 :                         return WERR_UNKNOWN_PORT;
   10688             :         }
   10689             : 
   10690             :         /* create the device URI and call the add_port_hook() */
   10691             : 
   10692           0 :         switch (protocol) {
   10693           0 :         case PROTOCOL_RAWTCP_TYPE:
   10694           0 :                 device_uri = talloc_asprintf(mem_ctx,
   10695             :                                 "socket://%s:%d/", hostaddress,
   10696             :                                 port_number);
   10697           0 :                 break;
   10698             : 
   10699           0 :         case PROTOCOL_LPR_TYPE:
   10700           0 :                 device_uri = talloc_asprintf(mem_ctx,
   10701             :                         "lpr://%s/%s", hostaddress, queue );
   10702           0 :                 break;
   10703             : 
   10704           0 :         default:
   10705           0 :                 return WERR_UNKNOWN_PORT;
   10706             :         }
   10707             : 
   10708           0 :         if (!device_uri) {
   10709           0 :                 return WERR_NOT_ENOUGH_MEMORY;
   10710             :         }
   10711             : 
   10712           0 :         return add_port_hook(mem_ctx, token, portname, device_uri);
   10713             : }
   10714             : 
   10715             : /*******************************************************************
   10716             : *******************************************************************/
   10717             : 
   10718             : struct xcv_api_table xcvtcp_cmds[] = {
   10719             :         { "MonitorUI",        xcvtcp_monitorui },
   10720             :         { "AddPort",  xcvtcp_addport},
   10721             :         { NULL,         NULL }
   10722             : };
   10723             : 
   10724           0 : static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
   10725             :                                      struct security_token *token, const char *command,
   10726             :                                      DATA_BLOB *inbuf,
   10727             :                                      DATA_BLOB *outbuf,
   10728             :                                      uint32_t *needed )
   10729             : {
   10730             :         int i;
   10731             : 
   10732           0 :         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
   10733             : 
   10734           0 :         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
   10735           0 :                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
   10736           0 :                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
   10737             :         }
   10738             : 
   10739           0 :         return WERR_INVALID_FUNCTION;
   10740             : }
   10741             : 
   10742             : /*******************************************************************
   10743             : *******************************************************************/
   10744             : #if 0   /* don't support management using the "Local Port" monitor */
   10745             : 
   10746             : static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
   10747             :                                  struct security_token *token, DATA_BLOB *in,
   10748             :                                  DATA_BLOB *out, uint32_t *needed)
   10749             : {
   10750             :         const char *dllname = "localui.dll";
   10751             : 
   10752             :         *needed = (strlen(dllname)+1) * 2;
   10753             : 
   10754             :         if (out->length < *needed) {
   10755             :                 return WERR_INSUFFICIENT_BUFFER;
   10756             :         }
   10757             : 
   10758             :         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
   10759             :                 return WERR_NOT_ENOUGH_MEMORY;
   10760             :         }
   10761             : 
   10762             :         return WERR_OK;
   10763             : }
   10764             : 
   10765             : /*******************************************************************
   10766             : *******************************************************************/
   10767             : 
   10768             : struct xcv_api_table xcvlocal_cmds[] = {
   10769             :         { "MonitorUI",        xcvlocal_monitorui },
   10770             :         { NULL,         NULL }
   10771             : };
   10772             : #else
   10773             : struct xcv_api_table xcvlocal_cmds[] = {
   10774             :         { NULL,         NULL }
   10775             : };
   10776             : #endif
   10777             : 
   10778             : 
   10779             : 
   10780             : /*******************************************************************
   10781             : *******************************************************************/
   10782             : 
   10783           0 : static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
   10784             :                                        struct security_token *token, const char *command,
   10785             :                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
   10786             :                                        uint32_t *needed)
   10787             : {
   10788             :         int i;
   10789             : 
   10790           0 :         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
   10791             : 
   10792           0 :         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
   10793           0 :                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
   10794           0 :                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
   10795             :         }
   10796           0 :         return WERR_INVALID_FUNCTION;
   10797             : }
   10798             : 
   10799             : /****************************************************************
   10800             :  _spoolss_XcvData
   10801             : ****************************************************************/
   10802             : 
   10803           0 : WERROR _spoolss_XcvData(struct pipes_struct *p,
   10804             :                         struct spoolss_XcvData *r)
   10805             : {
   10806           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
   10807           0 :         struct auth_session_info *session_info =
   10808           0 :                 dcesrv_call_session_info(dce_call);
   10809           0 :         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
   10810           0 :         DATA_BLOB out_data = data_blob_null;
   10811             :         WERROR werror;
   10812             : 
   10813           0 :         if (!Printer) {
   10814           0 :                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
   10815             :                         OUR_HANDLE(r->in.handle)));
   10816           0 :                 return WERR_INVALID_HANDLE;
   10817             :         }
   10818             : 
   10819             :         /* Has to be a handle to the TCP/IP port monitor */
   10820             : 
   10821           0 :         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
   10822           0 :                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
   10823           0 :                 return WERR_INVALID_HANDLE;
   10824             :         }
   10825             : 
   10826             :         /* requires administrative access to the server */
   10827             : 
   10828           0 :         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
   10829           0 :                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
   10830           0 :                 return WERR_ACCESS_DENIED;
   10831             :         }
   10832             : 
   10833             :         /* Allocate the outgoing buffer */
   10834             : 
   10835           0 :         if (r->in.out_data_size) {
   10836           0 :                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
   10837           0 :                 if (out_data.data == NULL) {
   10838           0 :                         return WERR_NOT_ENOUGH_MEMORY;
   10839             :                 }
   10840             :         }
   10841             : 
   10842           0 :         switch ( Printer->printer_type ) {
   10843           0 :         case SPLHND_PORTMON_TCP:
   10844           0 :                 werror = process_xcvtcp_command(p->mem_ctx,
   10845             :                                                 session_info->security_token,
   10846             :                                                 r->in.function_name,
   10847             :                                                 &r->in.in_data, &out_data,
   10848             :                                                 r->out.needed);
   10849           0 :                 break;
   10850           0 :         case SPLHND_PORTMON_LOCAL:
   10851           0 :                 werror = process_xcvlocal_command(p->mem_ctx,
   10852             :                                                   session_info->security_token,
   10853             :                                                   r->in.function_name,
   10854             :                                                   &r->in.in_data, &out_data,
   10855             :                                                   r->out.needed);
   10856           0 :                 break;
   10857           0 :         default:
   10858           0 :                 werror = WERR_INVALID_PRINT_MONITOR;
   10859             :         }
   10860             : 
   10861           0 :         if (!W_ERROR_IS_OK(werror)) {
   10862           0 :                 return werror;
   10863             :         }
   10864             : 
   10865           0 :         *r->out.status_code = 0;
   10866             : 
   10867           0 :         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
   10868           0 :                 memcpy(r->out.out_data, out_data.data,
   10869           0 :                         MIN(r->in.out_data_size, out_data.length));
   10870             :         }
   10871             : 
   10872           0 :         return WERR_OK;
   10873             : }
   10874             : 
   10875             : /****************************************************************
   10876             :  _spoolss_AddPrintProcessor
   10877             : ****************************************************************/
   10878             : 
   10879           0 : WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
   10880             :                                   struct spoolss_AddPrintProcessor *r)
   10881             : {
   10882             :         /* for now, just indicate success and ignore the add.  We'll
   10883             :            automatically set the winprint processor for printer
   10884             :            entries later.  Used to debug the LexMark Optra S 1855 PCL
   10885             :            driver --jerry */
   10886             : 
   10887           0 :         return WERR_OK;
   10888             : }
   10889             : 
   10890             : /****************************************************************
   10891             :  _spoolss_AddPort
   10892             : ****************************************************************/
   10893             : 
   10894           0 : WERROR _spoolss_AddPort(struct pipes_struct *p,
   10895             :                         struct spoolss_AddPort *r)
   10896             : {
   10897             :         /* do what w2k3 does */
   10898             : 
   10899           0 :         return WERR_NOT_SUPPORTED;
   10900             : }
   10901             : 
   10902             : /****************************************************************
   10903             :  _spoolss_GetPrinterDriver
   10904             : ****************************************************************/
   10905             : 
   10906           0 : WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
   10907             :                                  struct spoolss_GetPrinterDriver *r)
   10908             : {
   10909           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10910           0 :         return WERR_NOT_SUPPORTED;
   10911             : }
   10912             : 
   10913             : /****************************************************************
   10914             :  _spoolss_ReadPrinter
   10915             : ****************************************************************/
   10916             : 
   10917           0 : WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
   10918             :                             struct spoolss_ReadPrinter *r)
   10919             : {
   10920           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10921           0 :         return WERR_NOT_SUPPORTED;
   10922             : }
   10923             : 
   10924             : /****************************************************************
   10925             :  _spoolss_WaitForPrinterChange
   10926             : ****************************************************************/
   10927             : 
   10928           0 : WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
   10929             :                                      struct spoolss_WaitForPrinterChange *r)
   10930             : {
   10931           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10932           0 :         return WERR_NOT_SUPPORTED;
   10933             : }
   10934             : 
   10935             : /****************************************************************
   10936             :  _spoolss_ConfigurePort
   10937             : ****************************************************************/
   10938             : 
   10939           0 : WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
   10940             :                               struct spoolss_ConfigurePort *r)
   10941             : {
   10942           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10943           0 :         return WERR_NOT_SUPPORTED;
   10944             : }
   10945             : 
   10946             : /****************************************************************
   10947             :  _spoolss_DeletePort
   10948             : ****************************************************************/
   10949             : 
   10950           0 : WERROR _spoolss_DeletePort(struct pipes_struct *p,
   10951             :                            struct spoolss_DeletePort *r)
   10952             : {
   10953           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10954           0 :         return WERR_NOT_SUPPORTED;
   10955             : }
   10956             : 
   10957             : /****************************************************************
   10958             :  _spoolss_CreatePrinterIC
   10959             : ****************************************************************/
   10960             : 
   10961           0 : WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
   10962             :                                 struct spoolss_CreatePrinterIC *r)
   10963             : {
   10964           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10965           0 :         return WERR_NOT_SUPPORTED;
   10966             : }
   10967             : 
   10968             : /****************************************************************
   10969             :  _spoolss_PlayGDIScriptOnPrinterIC
   10970             : ****************************************************************/
   10971             : 
   10972           0 : WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
   10973             :                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
   10974             : {
   10975           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10976           0 :         return WERR_NOT_SUPPORTED;
   10977             : }
   10978             : 
   10979             : /****************************************************************
   10980             :  _spoolss_DeletePrinterIC
   10981             : ****************************************************************/
   10982             : 
   10983           0 : WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
   10984             :                                 struct spoolss_DeletePrinterIC *r)
   10985             : {
   10986           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10987           0 :         return WERR_NOT_SUPPORTED;
   10988             : }
   10989             : 
   10990             : /****************************************************************
   10991             :  _spoolss_AddPrinterConnection
   10992             : ****************************************************************/
   10993             : 
   10994           0 : WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
   10995             :                                      struct spoolss_AddPrinterConnection *r)
   10996             : {
   10997           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   10998           0 :         return WERR_NOT_SUPPORTED;
   10999             : }
   11000             : 
   11001             : /****************************************************************
   11002             :  _spoolss_DeletePrinterConnection
   11003             : ****************************************************************/
   11004             : 
   11005           0 : WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
   11006             :                                         struct spoolss_DeletePrinterConnection *r)
   11007             : {
   11008           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11009           0 :         return WERR_NOT_SUPPORTED;
   11010             : }
   11011             : 
   11012             : /****************************************************************
   11013             :  _spoolss_PrinterMessageBox
   11014             : ****************************************************************/
   11015             : 
   11016           0 : WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
   11017             :                                   struct spoolss_PrinterMessageBox *r)
   11018             : {
   11019           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11020           0 :         return WERR_NOT_SUPPORTED;
   11021             : }
   11022             : 
   11023             : /****************************************************************
   11024             :  _spoolss_AddMonitor
   11025             : ****************************************************************/
   11026             : 
   11027           0 : WERROR _spoolss_AddMonitor(struct pipes_struct *p,
   11028             :                            struct spoolss_AddMonitor *r)
   11029             : {
   11030           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11031           0 :         return WERR_NOT_SUPPORTED;
   11032             : }
   11033             : 
   11034             : /****************************************************************
   11035             :  _spoolss_DeleteMonitor
   11036             : ****************************************************************/
   11037             : 
   11038           0 : WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
   11039             :                               struct spoolss_DeleteMonitor *r)
   11040             : {
   11041           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11042           0 :         return WERR_NOT_SUPPORTED;
   11043             : }
   11044             : 
   11045             : /****************************************************************
   11046             :  _spoolss_DeletePrintProcessor
   11047             : ****************************************************************/
   11048             : 
   11049           0 : WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
   11050             :                                      struct spoolss_DeletePrintProcessor *r)
   11051             : {
   11052           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11053           0 :         return WERR_NOT_SUPPORTED;
   11054             : }
   11055             : 
   11056             : /****************************************************************
   11057             :  _spoolss_AddPrintProvidor
   11058             : ****************************************************************/
   11059             : 
   11060           0 : WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
   11061             :                                  struct spoolss_AddPrintProvidor *r)
   11062             : {
   11063           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11064           0 :         return WERR_NOT_SUPPORTED;
   11065             : }
   11066             : 
   11067             : /****************************************************************
   11068             :  _spoolss_DeletePrintProvidor
   11069             : ****************************************************************/
   11070             : 
   11071           0 : WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
   11072             :                                     struct spoolss_DeletePrintProvidor *r)
   11073             : {
   11074           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11075           0 :         return WERR_NOT_SUPPORTED;
   11076             : }
   11077             : 
   11078             : /****************************************************************
   11079             :  _spoolss_FindFirstPrinterChangeNotification
   11080             : ****************************************************************/
   11081             : 
   11082           0 : WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
   11083             :                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
   11084             : {
   11085           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11086           0 :         return WERR_NOT_SUPPORTED;
   11087             : }
   11088             : 
   11089             : /****************************************************************
   11090             :  _spoolss_FindNextPrinterChangeNotification
   11091             : ****************************************************************/
   11092             : 
   11093           0 : WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
   11094             :                                                   struct spoolss_FindNextPrinterChangeNotification *r)
   11095             : {
   11096           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11097           0 :         return WERR_NOT_SUPPORTED;
   11098             : }
   11099             : 
   11100             : /****************************************************************
   11101             :  _spoolss_RouterFindFirstPrinterChangeNotificationOld
   11102             : ****************************************************************/
   11103             : 
   11104           0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
   11105             :                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
   11106             : {
   11107           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11108           0 :         return WERR_NOT_SUPPORTED;
   11109             : }
   11110             : 
   11111             : /****************************************************************
   11112             :  _spoolss_ReplyOpenPrinter
   11113             : ****************************************************************/
   11114             : 
   11115           0 : WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
   11116             :                                  struct spoolss_ReplyOpenPrinter *r)
   11117             : {
   11118           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11119           0 :         return WERR_NOT_SUPPORTED;
   11120             : }
   11121             : 
   11122             : /****************************************************************
   11123             :  _spoolss_RouterReplyPrinter
   11124             : ****************************************************************/
   11125             : 
   11126           0 : WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
   11127             :                                    struct spoolss_RouterReplyPrinter *r)
   11128             : {
   11129           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11130           0 :         return WERR_NOT_SUPPORTED;
   11131             : }
   11132             : 
   11133             : /****************************************************************
   11134             :  _spoolss_ReplyClosePrinter
   11135             : ****************************************************************/
   11136             : 
   11137           0 : WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
   11138             :                                   struct spoolss_ReplyClosePrinter *r)
   11139             : {
   11140           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11141           0 :         return WERR_NOT_SUPPORTED;
   11142             : }
   11143             : 
   11144             : /****************************************************************
   11145             :  _spoolss_AddPortEx
   11146             : ****************************************************************/
   11147             : 
   11148           0 : WERROR _spoolss_AddPortEx(struct pipes_struct *p,
   11149             :                           struct spoolss_AddPortEx *r)
   11150             : {
   11151           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11152           0 :         return WERR_NOT_SUPPORTED;
   11153             : }
   11154             : 
   11155             : /****************************************************************
   11156             :  _spoolss_RouterFindFirstPrinterChangeNotification
   11157             : ****************************************************************/
   11158             : 
   11159           0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
   11160             :                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
   11161             : {
   11162           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11163           0 :         return WERR_NOT_SUPPORTED;
   11164             : }
   11165             : 
   11166             : /****************************************************************
   11167             :  _spoolss_SpoolerInit
   11168             : ****************************************************************/
   11169             : 
   11170           0 : WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
   11171             :                             struct spoolss_SpoolerInit *r)
   11172             : {
   11173           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11174           0 :         return WERR_NOT_SUPPORTED;
   11175             : }
   11176             : 
   11177             : /****************************************************************
   11178             :  _spoolss_ResetPrinterEx
   11179             : ****************************************************************/
   11180             : 
   11181           0 : WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
   11182             :                                struct spoolss_ResetPrinterEx *r)
   11183             : {
   11184           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11185           0 :         return WERR_NOT_SUPPORTED;
   11186             : }
   11187             : 
   11188             : /****************************************************************
   11189             :  _spoolss_RouterReplyPrinterEx
   11190             : ****************************************************************/
   11191             : 
   11192           0 : WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
   11193             :                                      struct spoolss_RouterReplyPrinterEx *r)
   11194             : {
   11195           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11196           0 :         return WERR_NOT_SUPPORTED;
   11197             : }
   11198             : 
   11199             : /****************************************************************
   11200             :  _spoolss_44
   11201             : ****************************************************************/
   11202             : 
   11203           0 : WERROR _spoolss_44(struct pipes_struct *p,
   11204             :                    struct spoolss_44 *r)
   11205             : {
   11206           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11207           0 :         return WERR_NOT_SUPPORTED;
   11208             : }
   11209             : 
   11210             : /****************************************************************
   11211             :  _spoolss_SetPort
   11212             : ****************************************************************/
   11213             : 
   11214           0 : WERROR _spoolss_SetPort(struct pipes_struct *p,
   11215             :                         struct spoolss_SetPort *r)
   11216             : {
   11217           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11218           0 :         return WERR_NOT_SUPPORTED;
   11219             : }
   11220             : 
   11221             : /****************************************************************
   11222             :  _spoolss_4a
   11223             : ****************************************************************/
   11224             : 
   11225           0 : WERROR _spoolss_4a(struct pipes_struct *p,
   11226             :                    struct spoolss_4a *r)
   11227             : {
   11228           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11229           0 :         return WERR_NOT_SUPPORTED;
   11230             : }
   11231             : 
   11232             : /****************************************************************
   11233             :  _spoolss_4b
   11234             : ****************************************************************/
   11235             : 
   11236           0 : WERROR _spoolss_4b(struct pipes_struct *p,
   11237             :                    struct spoolss_4b *r)
   11238             : {
   11239           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11240           0 :         return WERR_NOT_SUPPORTED;
   11241             : }
   11242             : 
   11243             : /****************************************************************
   11244             :  _spoolss_4c
   11245             : ****************************************************************/
   11246             : 
   11247           0 : WERROR _spoolss_4c(struct pipes_struct *p,
   11248             :                    struct spoolss_4c *r)
   11249             : {
   11250           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11251           0 :         return WERR_NOT_SUPPORTED;
   11252             : }
   11253             : 
   11254             : /****************************************************************
   11255             :  _spoolss_53
   11256             : ****************************************************************/
   11257             : 
   11258           0 : WERROR _spoolss_53(struct pipes_struct *p,
   11259             :                    struct spoolss_53 *r)
   11260             : {
   11261           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11262           0 :         return WERR_NOT_SUPPORTED;
   11263             : }
   11264             : 
   11265             : /****************************************************************
   11266             :  _spoolss_AddPerMachineConnection
   11267             : ****************************************************************/
   11268             : 
   11269           0 : WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
   11270             :                                         struct spoolss_AddPerMachineConnection *r)
   11271             : {
   11272           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11273           0 :         return WERR_NOT_SUPPORTED;
   11274             : }
   11275             : 
   11276             : /****************************************************************
   11277             :  _spoolss_DeletePerMachineConnection
   11278             : ****************************************************************/
   11279             : 
   11280           0 : WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
   11281             :                                            struct spoolss_DeletePerMachineConnection *r)
   11282             : {
   11283           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11284           0 :         return WERR_NOT_SUPPORTED;
   11285             : }
   11286             : 
   11287             : /****************************************************************
   11288             :  _spoolss_EnumPerMachineConnections
   11289             : ****************************************************************/
   11290             : 
   11291           0 : WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
   11292             :                                           struct spoolss_EnumPerMachineConnections *r)
   11293             : {
   11294           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11295           0 :         return WERR_NOT_SUPPORTED;
   11296             : }
   11297             : 
   11298             : /****************************************************************
   11299             :  _spoolss_5a
   11300             : ****************************************************************/
   11301             : 
   11302           0 : WERROR _spoolss_5a(struct pipes_struct *p,
   11303             :                    struct spoolss_5a *r)
   11304             : {
   11305           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11306           0 :         return WERR_NOT_SUPPORTED;
   11307             : }
   11308             : 
   11309             : /****************************************************************
   11310             :  _spoolss_5b
   11311             : ****************************************************************/
   11312             : 
   11313           0 : WERROR _spoolss_5b(struct pipes_struct *p,
   11314             :                    struct spoolss_5b *r)
   11315             : {
   11316           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11317           0 :         return WERR_NOT_SUPPORTED;
   11318             : }
   11319             : 
   11320             : /****************************************************************
   11321             :  _spoolss_5c
   11322             : ****************************************************************/
   11323             : 
   11324           0 : WERROR _spoolss_5c(struct pipes_struct *p,
   11325             :                    struct spoolss_5c *r)
   11326             : {
   11327           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11328           0 :         return WERR_NOT_SUPPORTED;
   11329             : }
   11330             : 
   11331             : /****************************************************************
   11332             :  _spoolss_5d
   11333             : ****************************************************************/
   11334             : 
   11335           0 : WERROR _spoolss_5d(struct pipes_struct *p,
   11336             :                    struct spoolss_5d *r)
   11337             : {
   11338           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11339           0 :         return WERR_NOT_SUPPORTED;
   11340             : }
   11341             : 
   11342             : /****************************************************************
   11343             :  _spoolss_5e
   11344             : ****************************************************************/
   11345             : 
   11346           0 : WERROR _spoolss_5e(struct pipes_struct *p,
   11347             :                    struct spoolss_5e *r)
   11348             : {
   11349           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11350           0 :         return WERR_NOT_SUPPORTED;
   11351             : }
   11352             : 
   11353             : /****************************************************************
   11354             :  _spoolss_5f
   11355             : ****************************************************************/
   11356             : 
   11357           0 : WERROR _spoolss_5f(struct pipes_struct *p,
   11358             :                    struct spoolss_5f *r)
   11359             : {
   11360           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11361           0 :         return WERR_NOT_SUPPORTED;
   11362             : }
   11363             : 
   11364             : /****************************************************************
   11365             :  _spoolss_60
   11366             : ****************************************************************/
   11367             : 
   11368           0 : WERROR _spoolss_60(struct pipes_struct *p,
   11369             :                    struct spoolss_60 *r)
   11370             : {
   11371           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11372           0 :         return WERR_NOT_SUPPORTED;
   11373             : }
   11374             : 
   11375             : /****************************************************************
   11376             :  _spoolss_SendRecvBidiData
   11377             : ****************************************************************/
   11378             : 
   11379           0 : WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
   11380             :                                  struct spoolss_SendRecvBidiData *r)
   11381             : {
   11382           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11383           0 :         return WERR_NOT_SUPPORTED;
   11384             : }
   11385             : 
   11386             : /****************************************************************
   11387             :  _spoolss_62
   11388             : ****************************************************************/
   11389             : 
   11390           0 : WERROR _spoolss_62(struct pipes_struct *p,
   11391             :                    struct spoolss_62 *r)
   11392             : {
   11393           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11394           0 :         return WERR_NOT_SUPPORTED;
   11395             : }
   11396             : 
   11397             : /****************************************************************
   11398             :  _spoolss_63
   11399             : ****************************************************************/
   11400             : 
   11401           0 : WERROR _spoolss_63(struct pipes_struct *p,
   11402             :                    struct spoolss_63 *r)
   11403             : {
   11404           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11405           0 :         return WERR_NOT_SUPPORTED;
   11406             : }
   11407             : 
   11408             : /****************************************************************
   11409             :  _spoolss_64
   11410             : ****************************************************************/
   11411             : 
   11412           0 : WERROR _spoolss_64(struct pipes_struct *p,
   11413             :                    struct spoolss_64 *r)
   11414             : {
   11415           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11416           0 :         return WERR_NOT_SUPPORTED;
   11417             : }
   11418             : 
   11419             : /****************************************************************
   11420             :  _spoolss_65
   11421             : ****************************************************************/
   11422             : 
   11423           0 : WERROR _spoolss_65(struct pipes_struct *p,
   11424             :                    struct spoolss_65 *r)
   11425             : {
   11426           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11427           0 :         return WERR_NOT_SUPPORTED;
   11428             : }
   11429             : 
   11430             : /****************************************************************
   11431             :  _spoolss_GetCorePrinterDrivers
   11432             : ****************************************************************/
   11433             : 
   11434           0 : HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
   11435             :                                        struct spoolss_GetCorePrinterDrivers *r)
   11436             : {
   11437           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11438           0 :         return HRES_ERROR_NOT_SUPPORTED;
   11439             : }
   11440             : 
   11441             : /****************************************************************
   11442             :  _spoolss_67
   11443             : ****************************************************************/
   11444             : 
   11445           0 : WERROR _spoolss_67(struct pipes_struct *p,
   11446             :                    struct spoolss_67 *r)
   11447             : {
   11448           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11449           0 :         return WERR_NOT_SUPPORTED;
   11450             : }
   11451             : 
   11452             : /****************************************************************
   11453             :  _spoolss_GetPrinterDriverPackagePath
   11454             : ****************************************************************/
   11455             : 
   11456           0 : HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
   11457             :                                              struct spoolss_GetPrinterDriverPackagePath *r)
   11458             : {
   11459           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11460           0 :         return HRES_ERROR_NOT_SUPPORTED;
   11461             : }
   11462             : 
   11463             : /****************************************************************
   11464             :  _spoolss_69
   11465             : ****************************************************************/
   11466             : 
   11467           0 : WERROR _spoolss_69(struct pipes_struct *p,
   11468             :                    struct spoolss_69 *r)
   11469             : {
   11470           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11471           0 :         return WERR_NOT_SUPPORTED;
   11472             : }
   11473             : 
   11474             : /****************************************************************
   11475             :  _spoolss_6a
   11476             : ****************************************************************/
   11477             : 
   11478           0 : WERROR _spoolss_6a(struct pipes_struct *p,
   11479             :                    struct spoolss_6a *r)
   11480             : {
   11481           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11482           0 :         return WERR_NOT_SUPPORTED;
   11483             : }
   11484             : 
   11485             : /****************************************************************
   11486             :  _spoolss_6b
   11487             : ****************************************************************/
   11488             : 
   11489           0 : WERROR _spoolss_6b(struct pipes_struct *p,
   11490             :                    struct spoolss_6b *r)
   11491             : {
   11492           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11493           0 :         return WERR_NOT_SUPPORTED;
   11494             : }
   11495             : 
   11496             : /****************************************************************
   11497             :  _spoolss_6c
   11498             : ****************************************************************/
   11499             : 
   11500           0 : WERROR _spoolss_6c(struct pipes_struct *p,
   11501             :                    struct spoolss_6c *r)
   11502             : {
   11503           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11504           0 :         return WERR_NOT_SUPPORTED;
   11505             : }
   11506             : 
   11507             : /****************************************************************
   11508             :  _spoolss_6d
   11509             : ****************************************************************/
   11510             : 
   11511           0 : WERROR _spoolss_6d(struct pipes_struct *p,
   11512             :                    struct spoolss_6d *r)
   11513             : {
   11514           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11515           0 :         return WERR_NOT_SUPPORTED;
   11516             : }
   11517             : 
   11518             : /****************************************************************
   11519             :  _spoolss_GetJobNamedPropertyValue
   11520             : ****************************************************************/
   11521             : 
   11522           0 : WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
   11523             :                                          struct spoolss_GetJobNamedPropertyValue *r)
   11524             : {
   11525           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11526           0 :         return WERR_NOT_SUPPORTED;
   11527             : }
   11528             : 
   11529             : /****************************************************************
   11530             :  _spoolss_SetJobNamedProperty
   11531             : ****************************************************************/
   11532             : 
   11533           0 : WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
   11534             :                                     struct spoolss_SetJobNamedProperty *r)
   11535             : {
   11536           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11537           0 :         return WERR_NOT_SUPPORTED;
   11538             : }
   11539             : 
   11540             : /****************************************************************
   11541             :  _spoolss_DeleteJobNamedProperty
   11542             : ****************************************************************/
   11543             : 
   11544           0 : WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
   11545             :                                        struct spoolss_DeleteJobNamedProperty *r)
   11546             : {
   11547           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11548           0 :         return WERR_NOT_SUPPORTED;
   11549             : }
   11550             : 
   11551             : /****************************************************************
   11552             :  _spoolss_EnumJobNamedProperties
   11553             : ****************************************************************/
   11554             : 
   11555           0 : WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
   11556             :                                        struct spoolss_EnumJobNamedProperties *r)
   11557             : {
   11558           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11559           0 :         return WERR_NOT_SUPPORTED;
   11560             : }
   11561             : 
   11562             : /****************************************************************
   11563             :  _spoolss_72
   11564             : ****************************************************************/
   11565             : 
   11566           0 : WERROR _spoolss_72(struct pipes_struct *p,
   11567             :                    struct spoolss_72 *r)
   11568             : {
   11569           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11570           0 :         return WERR_NOT_SUPPORTED;
   11571             : }
   11572             : 
   11573             : /****************************************************************
   11574             :  _spoolss_73
   11575             : ****************************************************************/
   11576             : 
   11577           0 : WERROR _spoolss_73(struct pipes_struct *p,
   11578             :                    struct spoolss_73 *r)
   11579             : {
   11580           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11581           0 :         return WERR_NOT_SUPPORTED;
   11582             : }
   11583             : 
   11584             : /****************************************************************
   11585             :  _spoolss_RpcLogJobInfoForBranchOffice
   11586             : ****************************************************************/
   11587             : 
   11588           0 : WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
   11589             :                                           struct spoolss_LogJobInfoForBranchOffice *r)
   11590             : {
   11591           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
   11592           0 :         return WERR_NOT_SUPPORTED;
   11593             : }
   11594             : 
   11595             : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
   11596             :                 const struct dcesrv_endpoint_server *ep_server);
   11597             : 
   11598             : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
   11599             :                 const struct dcesrv_endpoint_server *ep_server);
   11600             : 
   11601             : #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
   11602             :         spoolss_init_server
   11603             : 
   11604             : #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
   11605             :         spoolss_shutdown_server
   11606             : 
   11607           2 : static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
   11608             :                 const struct dcesrv_endpoint_server *ep_server)
   11609             : {
   11610           2 :         struct messaging_context *msg_ctx = global_messaging_context();
   11611             :         bool ok;
   11612             : 
   11613             :         /*
   11614             :          * Migrate the printers first.
   11615             :          */
   11616           2 :         ok = nt_printing_tdb_migrate(msg_ctx);
   11617           2 :         if (!ok) {
   11618           0 :                 return NT_STATUS_UNSUCCESSFUL;
   11619             :         }
   11620             : 
   11621           2 :         return spoolss__op_init_server(dce_ctx, ep_server);
   11622             : }
   11623             : 
   11624           2 : static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
   11625             :                 const struct dcesrv_endpoint_server *ep_server)
   11626             : {
   11627           2 :         srv_spoolss_cleanup();
   11628             : 
   11629           2 :         return spoolss__op_shutdown_server(dce_ctx, ep_server);
   11630             : }
   11631             : 
   11632             : /* include the generated boilerplate */
   11633             : #include "librpc/gen_ndr/ndr_spoolss_scompat.c"

Generated by: LCOV version 1.13